Skip to content

Commit

Permalink
go
Browse files Browse the repository at this point in the history
  • Loading branch information
guibescos committed Oct 7, 2024
1 parent 803cbc1 commit 0d01893
Show file tree
Hide file tree
Showing 11 changed files with 322 additions and 167 deletions.
58 changes: 43 additions & 15 deletions apps/staking/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
getAmountByTargetAndState,
getCurrentEpoch,
PositionState,
PythnetClient,
PythStakingClient,
type StakeAccountPositions,
} from "@pythnetwork/staking-sdk";
Expand Down Expand Up @@ -43,6 +44,8 @@ type Data = {
cooldown2: bigint;
};
yieldRate: bigint;
m: bigint;
z: bigint;
integrityStakingPublishers: {
name: string | undefined;
publicKey: PublicKey;
Expand Down Expand Up @@ -95,18 +98,29 @@ export const getStakeAccount = async (

export const loadData = async (
client: PythStakingClient,
pythnetClient: PythnetClient,
hermesClient: HermesClient,
stakeAccount?: PublicKey | undefined,
): Promise<Data> =>
stakeAccount === undefined
? loadDataNoStakeAccount(client, hermesClient)
: loadDataForStakeAccount(client, hermesClient, stakeAccount);
? loadDataNoStakeAccount(client, pythnetClient, hermesClient)
: loadDataForStakeAccount(
client,
pythnetClient,
hermesClient,
stakeAccount,
);

const loadDataNoStakeAccount = async (
client: PythStakingClient,
pythnetClient: PythnetClient,
hermesClient: HermesClient,
): Promise<Data> => {
const { publishers, ...baseInfo } = await loadBaseInfo(client, hermesClient);
const { publishers, ...baseInfo } = await loadBaseInfo(
client,
pythnetClient,
hermesClient,
);

return {
...baseInfo,
Expand All @@ -127,6 +141,7 @@ const loadDataNoStakeAccount = async (

const loadDataForStakeAccount = async (
client: PythStakingClient,
pythnetClient: PythnetClient,
hermesClient: HermesClient,
stakeAccount: PublicKey,
): Promise<Data> => {
Expand All @@ -137,7 +152,7 @@ const loadDataForStakeAccount = async (
claimableRewards,
stakeAccountPositions,
] = await Promise.all([
loadBaseInfo(client, hermesClient),
loadBaseInfo(client, pythnetClient, hermesClient),
client.getStakeAccountCustody(stakeAccount),
client.getUnlockSchedule(stakeAccount),
client.getClaimableRewards(stakeAccount),
Expand Down Expand Up @@ -196,36 +211,49 @@ const loadDataForStakeAccount = async (

const loadBaseInfo = async (
client: PythStakingClient,
pythnetClient: PythnetClient,
hermesClient: HermesClient,
) => {
const [publishers, walletAmount, poolConfig, currentEpoch] =
const [publishers, walletAmount, poolConfig, currentEpoch, parameters] =
await Promise.all([
loadPublisherData(client, hermesClient),
loadPublisherData(client, pythnetClient, hermesClient),
client.getOwnerPythBalance(),
client.getPoolConfigAccount(),
getCurrentEpoch(client.connection),
pythnetClient.getStakeCapParameters(),
]);

return { yieldRate: poolConfig.y, walletAmount, publishers, currentEpoch };
return {
yieldRate: poolConfig.y,
walletAmount,
publishers,
currentEpoch,
m: parameters.m,
z: parameters.z,
};
};

const loadPublisherData = async (
client: PythStakingClient,
pythnetClient: PythnetClient,
hermesClient: HermesClient,
) => {
const [poolData, publisherRankings, publisherCaps] = await Promise.all([
client.getPoolDataAccount(),
getPublisherRankings(),
hermesClient.getLatestPublisherCaps({
parsed: true,
}),
]);
const [poolData, publisherRankings, publisherCaps, publisherNumberOfSymbols] =
await Promise.all([
client.getPoolDataAccount(),
getPublisherRankings(),
hermesClient.getLatestPublisherCaps({
parsed: true,
}),
pythnetClient.getPublisherNumberOfSymbols(),
]);

return extractPublisherData(poolData).map((publisher) => {
const publisherPubkeyString = publisher.pubkey.toBase58();
const publisherRanking = publisherRankings.find(
(ranking) => ranking.publisher === publisherPubkeyString,
);
const numberOfSymbols = publisherNumberOfSymbols[publisherPubkeyString];
const apyHistory = publisher.apyHistory.map(({ epoch, apy }) => ({
date: epochToDate(epoch + 1n),
apy,
Expand All @@ -234,7 +262,7 @@ const loadPublisherData = async (
return {
apyHistory,
name: undefined, // TODO
numFeeds: publisherRanking?.numSymbols ?? 0,
numFeeds: numberOfSymbols ?? 0,
poolCapacity: getPublisherCap(publisherCaps, publisher.pubkey),
poolUtilization: publisher.totalDelegation,
poolUtilizationDelta: publisher.totalDelegationDelta,
Expand Down
17 changes: 13 additions & 4 deletions apps/staking/src/hooks/use-api.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
"use client";

import { HermesClient } from "@pythnetwork/hermes-client";
import { PythStakingClient } from "@pythnetwork/staking-sdk";
import { PythnetClient, PythStakingClient } from "@pythnetwork/staking-sdk";
import { useLocalStorageValue } from "@react-hookz/web";
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import type { PublicKey } from "@solana/web3.js";
import { Connection, type PublicKey } from "@solana/web3.js";
import { type ComponentProps, createContext, useContext, useMemo } from "react";
import { useSWRConfig } from "swr";

Expand Down Expand Up @@ -43,6 +43,7 @@ const State = {
[StateType.LoadedNoStakeAccount]: (
isMainnet: boolean,
client: PythStakingClient,
pythnetClient: PythnetClient,
hermesClient: HermesClient,
onCreateAccount: (newAccount: PublicKey) => Promise<void>,
) => ({
Expand All @@ -51,7 +52,7 @@ const State = {
isMainnet ? "mainnet" : "devnet",
client.wallet.publicKey.toBase58(),
],
loadData: () => api.loadData(client, hermesClient),
loadData: () => api.loadData(client, pythnetClient, hermesClient),
deposit: async (amount: bigint) => {
const account = await api.createStakeAccountAndDeposit(client, amount);
return onCreateAccount(account);
Expand All @@ -61,6 +62,7 @@ const State = {
[StateType.Loaded]: (
isMainnet: boolean,
client: PythStakingClient,
pythnetClient: PythnetClient,
hermesClient: HermesClient,
account: PublicKey,
allAccounts: [PublicKey, ...PublicKey[]],
Expand Down Expand Up @@ -92,7 +94,8 @@ const State = {
selectAccount,
dashboardDataCacheKey,

loadData: () => api.loadData(client, hermesClient, account),
loadData: () =>
api.loadData(client, pythnetClient, hermesClient, account),

claim: bindApi(api.claim),
deposit: bindApi(api.deposit),
Expand Down Expand Up @@ -141,6 +144,10 @@ const useApiContext = (hermesUrl: string) => {
const { isMainnet } = useNetwork();
const { mutate } = useSWRConfig();
const hermesClient = useMemo(() => new HermesClient(hermesUrl), [hermesUrl]);
const pythnetClient = useMemo(
() => new PythnetClient(new Connection("https://pythnet.rpcpool.com")),
[],
);
const pythStakingClient = useMemo(
() =>
wallet.publicKey && wallet.signAllTransactions && wallet.signTransaction
Expand Down Expand Up @@ -209,6 +216,7 @@ const useApiContext = (hermesUrl: string) => {
return State[StateType.Loaded](
isMainnet,
pythStakingClient,
pythnetClient,
hermesClient,
selectedAccount ?? firstAccount,
[firstAccount, ...otherAccounts],
Expand All @@ -221,6 +229,7 @@ const useApiContext = (hermesUrl: string) => {
return State[StateType.LoadedNoStakeAccount](
isMainnet,
pythStakingClient,
pythnetClient,
hermesClient,
async (newAccount) => {
await stakeAccounts.mutate([newAccount]);
Expand Down
76 changes: 76 additions & 0 deletions governance/pyth_staking_sdk/idl/stake_caps_parameters.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{
"address": "ujSFv8q8woXW5PUnby52PQyxYGUudxkrvgN6A631Qmm",
"metadata": {
"name": "stake_caps_parameters",
"version": "0.1.0",
"spec": "0.1.0",
"description": "Created with Anchor"
},
"instructions": [
{
"name": "set_parameters",
"discriminator": [218, 114, 41, 75, 208, 237, 97, 28],
"accounts": [
{
"name": "signer",
"writable": true,
"signer": true
},
{
"name": "parameters",
"writable": true,
"pda": {
"seeds": [
{
"kind": "const",
"value": [112, 97, 114, 97, 109, 101, 116, 101, 114, 115]
}
]
}
},
{
"name": "system_program",
"address": "11111111111111111111111111111111"
}
],
"args": [
{
"name": "parameters",
"type": {
"defined": {
"name": "Parameters"
}
}
}
]
}
],
"accounts": [
{
"name": "Parameters",
"discriminator": [233, 2, 25, 109, 70, 228, 206, 228]
}
],
"types": [
{
"name": "Parameters",
"type": {
"kind": "struct",
"fields": [
{
"name": "current_authority",
"type": "pubkey"
},
{
"name": "m",
"type": "u64"
},
{
"name": "z",
"type": "u64"
}
]
}
}
]
}
1 change: 1 addition & 0 deletions governance/pyth_staking_sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
},
"dependencies": {
"@coral-xyz/anchor": "^0.30.1",
"@pythnetwork/client": "^2.22.0",
"@pythnetwork/solana-utils": "workspace:*",
"@solana/spl-governance": "^0.3.28",
"@solana/spl-token": "^0.3.7",
Expand Down
4 changes: 4 additions & 0 deletions governance/pyth_staking_sdk/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ export const PUBLISHER_CAPS_PROGRAM_ADDRESS = new PublicKey(
export const GOVERNANCE_ADDRESS = new PublicKey(
"pytGY6tWRgGinSCvRLnSv4fHfBTMoiDGiCsesmHWM6U",
);

export const STAKE_CAPS_PARAMETERS_PROGRAM_ADDRESS = new PublicKey(
"ujSFv8q8woXW5PUnby52PQyxYGUudxkrvgN6A631Qmm",
);
1 change: 1 addition & 0 deletions governance/pyth_staking_sdk/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from "./pdas";
export * from "./pyth-staking-client";
export * from "./pythnet-client";
export * from "./types";
export * from "./utils/apy";
export * from "./utils/clock";
Expand Down
9 changes: 9 additions & 0 deletions governance/pyth_staking_sdk/src/pdas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { PublicKey } from "@solana/web3.js";

import {
INTEGRITY_POOL_PROGRAM_ADDRESS,
STAKE_CAPS_PARAMETERS,
STAKE_CAPS_PARAMETERS_PROGRAM_ADDRESS,
STAKING_PROGRAM_ADDRESS,
} from "./constants";

Expand Down Expand Up @@ -73,3 +75,10 @@ export const getMaxVoterWeightRecordAddress = () => {
STAKING_PROGRAM_ADDRESS,
);
};

export const getStakeCapsParametersAddress = () => {
return PublicKey.findProgramAddressSync(
[Buffer.from("parameters")],
STAKE_CAPS_PARAMETERS_PROGRAM_ADDRESS,
);
};
58 changes: 58 additions & 0 deletions governance/pyth_staking_sdk/src/pythnet-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { AnchorProvider, Program } from "@coral-xyz/anchor";
import {
AccountType,
getPythProgramKeyForCluster,
parseBaseData,
parsePriceData,
} from "@pythnetwork/client";
import { Connection } from "@solana/web3.js";

import { getStakeCapsParametersAddress } from "./pdas";
import type { Parameters, StakeCapParametersAccount } from "./types";
import { convertBNToBigInt } from "./utils/bn";
import { DummyWallet } from "./utils/wallet";
import * as StakeCapsParametersIdl from "../idl/stake_caps_parameters.json";
import type { StakeCapsParameters } from "../types/stake_caps_parameters";
export class PythnetClient {
connection: Connection;
provider: AnchorProvider;
stakeCapParametersProgram: Program<StakeCapsParameters>;

constructor(connection: Connection) {
this.connection = connection;
this.provider = new AnchorProvider(connection, DummyWallet);
this.stakeCapParametersProgram = new Program<StakeCapsParameters>(
StakeCapsParametersIdl as StakeCapsParameters,
this.provider,
);
}

async getPublisherNumberOfSymbols() {
const publisherNumberOfSymbols: Record<string, number> = {};
const pythAccounts = await this.connection.getProgramAccounts(
getPythProgramKeyForCluster("pythnet"),
);
for (const account of pythAccounts) {
const base = parseBaseData(account.account.data);
if (base?.type === AccountType.Price) {
const parsed = parsePriceData(account.account.data);
for (const priceComponent of parsed.priceComponents) {
if (publisherNumberOfSymbols[priceComponent.publisher.toBase58()]) {
publisherNumberOfSymbols[priceComponent.publisher.toBase58()]! += 1;
} else {
publisherNumberOfSymbols[priceComponent.publisher.toBase58()] = 1;
}
}
}
}
return publisherNumberOfSymbols;
}

async getStakeCapParameters(): Promise<StakeCapParametersAccount> {
const parameters =
await this.stakeCapParametersProgram.account.parameters.fetch(
getStakeCapsParametersAddress()[0],
);
return convertBNToBigInt<Parameters>(parameters);
}
}
Loading

0 comments on commit 0d01893

Please sign in to comment.