-
Notifications
You must be signed in to change notification settings - Fork 302
feat(staking): add stake accounts and supply routes #1957
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
76c0dd6
f9acf98
cd5c4bc
26d1bbf
acf97a9
3a94e05
595aeeb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| import { PythStakingClient } from "@pythnetwork/staking-sdk"; | ||
| import { Connection, PublicKey } from "@solana/web3.js"; | ||
| import { type NextRequest } from "next/server"; | ||
|
|
||
| import { RPC } from "../../../config/server"; | ||
|
|
||
| type ResponseType = { | ||
| custodyAccount: string; | ||
| actualAmount: number; | ||
| lock: { | ||
| type: string; | ||
| schedule: { | ||
| date: Date; | ||
| amount: number; | ||
| }[]; | ||
| }; | ||
| }[]; | ||
keyvankhademi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| const stakingClient = new PythStakingClient({ | ||
| connection: new Connection(RPC ?? "https://api.devnet.solana.com"), | ||
keyvankhademi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }); | ||
|
|
||
| export async function GET(req: NextRequest) { | ||
| const owner = req.nextUrl.searchParams.get("owner"); | ||
|
|
||
| if (owner === null) { | ||
| return Response.json( | ||
| { | ||
| error: "Must provide the 'owner' query parameters", | ||
| }, | ||
| { | ||
| status: 400, | ||
| }, | ||
| ); | ||
| } | ||
|
|
||
| const positions = await stakingClient.getAllStakeAccountPositions( | ||
| new PublicKey(owner), | ||
| ); | ||
|
|
||
| const response: ResponseType = await Promise.all( | ||
| positions.map(async (position) => { | ||
| const custodyAccount = | ||
| await stakingClient.getStakeAccountCustody(position); | ||
| const lock = await stakingClient.getUnlockSchedule(position, true); | ||
| return { | ||
| custodyAccount: custodyAccount.address.toBase58(), | ||
| actualAmount: Number(custodyAccount.amount), | ||
| lock: { | ||
| type: lock.type, | ||
| schedule: lock.schedule.map((unlock) => ({ | ||
| date: unlock.date, | ||
| amount: Number(unlock.amount), | ||
| })), | ||
| }, | ||
| }; | ||
| }), | ||
| ); | ||
|
|
||
| return Response.json(response); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import { PythStakingClient } from "@pythnetwork/staking-sdk"; | ||
| import { Connection } from "@solana/web3.js"; | ||
| import { type NextRequest } from "next/server"; | ||
|
|
||
| import { RPC } from "../../../config/server"; | ||
|
|
||
| const stakingClient = new PythStakingClient({ | ||
| connection: new Connection(RPC ?? "https://api.devnet.solana.com"), | ||
keyvankhademi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }); | ||
|
|
||
| function validateQ(q: string | null): q is "totalSupply" | "circulatingSupply" { | ||
| return q !== null && ["totalSupply", "circulatingSupply"].includes(q); | ||
| } | ||
keyvankhademi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| function getResponse(data: unknown) { | ||
| return Response.json(data, { | ||
| headers: { | ||
| "Cache-Control": "max-age=0, s-maxage=3600", | ||
keyvankhademi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }, | ||
| }); | ||
| } | ||
|
|
||
| export async function GET(req: NextRequest) { | ||
| const q = req.nextUrl.searchParams.get("q"); | ||
|
|
||
| if (!validateQ(q)) { | ||
| return Response.json( | ||
| { | ||
| error: | ||
| "The 'q' query parameter must be one of 'totalSupply' or 'circulatingSupply'.", | ||
| }, | ||
| { | ||
| status: 400, | ||
| }, | ||
| ); | ||
| } | ||
|
|
||
| if (q === "circulatingSupply") { | ||
| const circulatingSupply = await stakingClient.getCirculatingSupply(); | ||
| return getResponse(Number(circulatingSupply)); | ||
| } else { | ||
| const pythMint = await stakingClient.getPythTokenMint(); | ||
| return getResponse(Number(pythMint.supply)); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems a bit odd to me to have a single endpoint that has a query param that enables it to do two totally different and unrelated things. Why not just split these into separate endpoints? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i 100% agree, but let's keep it the same for now since other users are already integrated using this with the old ui. |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,8 @@ | ||
| export * from "./pdas"; | ||
| export * from "./pyth-staking-client"; | ||
| export * from "./types"; | ||
| export * from "./utils/apy"; | ||
| export * from "./utils/clock"; | ||
| export * from "./utils/position"; | ||
| export * from "./utils/pool"; | ||
| export * from "./utils/apy"; | ||
| export * from "./types"; | ||
| export * from "./utils/position"; | ||
| export * from "./utils/vesting"; |
Uh oh!
There was an error while loading. Please reload this page.