Skip to content

Commit

Permalink
bs3-ui seed gauge (#1129)
Browse files Browse the repository at this point in the history
  • Loading branch information
Space-Bean authored Oct 8, 2024
2 parents 8299872 + c5d251f commit ccc28df
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 69 deletions.
6 changes: 6 additions & 0 deletions projects/ui/src/components/App/SdkProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ function BeanstalkSDKProvider({ children }: { children: React.ReactNode }) {

const isArbTestnet = isArbitrum && isTestnet;

const beanstalk = sdk.contracts.beanstalk;

React.useEffect(() => {
console.log('[BeanstalkSDKProvider/beanstalk]', beanstalk.address);
}, [beanstalk.address, sdk.chainId]);

// only run this on arbitrum dev
const ready = useDynamicSeeds(sdk, isArbTestnet);

Expand Down
14 changes: 7 additions & 7 deletions projects/ui/src/components/Silo/SeedGauge/Bean2MaxLPRatio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,13 @@ const Bean2MaxLPRatio = ({ data }: IBean2MaxLPRatio) => {

const maxLP = useMemo(() => {
if (!data?.gaugeData) return;
const arr = Object.entries(data.gaugeData);
const sorted = [...arr].sort(([_ak, a], [_bk, b]) => {
const diff = Number(
b.gaugePointsPerBdv.minus(a.gaugePointsPerBdv).toString()
);
return diff;
});
const arr = Object.entries(data.gaugeData).filter(
([_, v]) => !v.token.equals(sdk.tokens.BEAN)
);

const sorted = [...arr].sort(([_aAddress, a], [_bAddress, b]) =>
b.gaugePointsPerBdv.minus(a.gaugePointsPerBdv).toNumber()
);

return sdk.tokens.findByAddress(sorted[0][0] || '');
}, [data?.gaugeData, sdk]);
Expand Down
5 changes: 1 addition & 4 deletions projects/ui/src/components/Silo/SeedGauge/SeedGaugeTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@ const useTableConfig = (
const ratio = gaugeInfo.gaugePoints.div(totalGaugePoints);

prev.push({
token,
...gaugeInfo,
gaugePointRatio: totalGaugePoints.gt(0) ? ratio : ZERO_BN,
});
Expand All @@ -267,7 +266,7 @@ const ExpectedSeedRewardDirection = (row: ISeedGaugeRow) => {
// seed rewards don't increase if every well has all gauge points
const maxed = row.gaugePointRatio.eq(1);

if (!row.gaugePoints || row.gaugePoints.lte(0) || optimal || maxed) {
if (!row.gaugePoints || row.gaugePoints.lt(0) || optimal || maxed) {
return null;
}

Expand Down Expand Up @@ -377,8 +376,6 @@ const SeedGaugeTable = ({
data: ReturnType<typeof useSeedGauge>['data'];
onToggleAdvancedMode: (v: boolean) => void;
}) => {

console.log('data', data);
const [isAdvanced, setIsAdvanced] = useState(false);
const rows = useTableConfig(isAdvanced, data);
const cols = isAdvanced ? advancedViewColumns : basicViewColumns;
Expand Down
2 changes: 1 addition & 1 deletion projects/ui/src/components/Silo/SeedGauge/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ const SeedGaugeSelect = ({
for (const token of [...sdk.tokens.siloWhitelist]) {
const setting = data.gaugeData[token.address];
if (setting?.optimalPctDepositedBdv?.gt(0)) {
tokensWithGP.push({ token: token, ...setting });
tokensWithGP.push(setting);
}
}
// sort by optimalPercentDepositedBdv
Expand Down
143 changes: 102 additions & 41 deletions projects/ui/src/hooks/beanstalk/useAvgSeedsPerBDV.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { BigNumber } from 'bignumber.js';
import { useCallback, useEffect, useState } from 'react';
import { DocumentNode, gql } from '@apollo/client';
import { BeanstalkSDK } from '@beanstalk/sdk';
import { BeanstalkSDK, ERC20Token } from '@beanstalk/sdk';
import { Time, Range } from 'lightweight-charts';
import * as LegacyToken from '~/constants/tokens';

import { ChartQueryData } from '~/components/Analytics/AdvancedChart';
import useSdk from '~/hooks/sdk';
import { apolloClient } from '~/graph/client';
import { toBNWithDecimals, tokenIshEqual } from '~/util';
import { ZERO_BN } from '~/constants';
import { TokenInstance } from './useTokens';
import { toBNWithDecimals } from '~/util';
import { SupportedChainId, ZERO_BN } from '~/constants';
import { TokenInstance, useGetNormaliseChainToken } from './useTokens';

type SeasonMap<T> = { [season: number]: T };

Expand Down Expand Up @@ -45,18 +45,22 @@ const SEED_GAUGE_DEPLOYMENT_SEASON = 21798;

const SEED_GAUGE_DEPLOYMENT_TIMESTAMP = 1716408000;

const L2_MIGRATION_SEASON = 25133;

const UNREACHABLE_SEASON = 999999999;

const apolloFetch = async (
document: DocumentNode,
first: number,
season: number
season: number,
subgraph: 'beanstalk_eth' | 'beanstalk'
) =>
apolloClient.query({
query: document,
variables: { first, season_lte: season },
fetchPolicy: 'no-cache',
notifyOnNetworkStatusChange: true,
// BS3TODO: Fix me to include L2 silo whitelist
context: { subgraph: 'beanstalk_eth' },
context: { subgraph: subgraph },
});

// Main hook with improved error handling and performance
Expand All @@ -73,6 +77,8 @@ const useAvgSeedsPerBDV = (
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);

const normaliseToken = useGetNormaliseChainToken();

useEffect(() => {
const iterations = getNumQueries(range);
setNumQueries((prevNumQueries) => Math.max(prevNumQueries, iterations));
Expand All @@ -85,19 +91,35 @@ const useAvgSeedsPerBDV = (
setError(false);
setLoading(true);
console.debug('[useAvgSeedsPerBDV/fetch]: fetching...');
const tokens = [
LegacyToken.BEAN[1],
LegacyToken.BEAN_ETH_WELL_LP[1],
LegacyToken.BEAN_WSTETH_WELL_LP[1],

const l2Tokens = [
LegacyToken.BEAN[SupportedChainId.ARBITRUM_MAINNET],
LegacyToken.BEAN_ETH_WELL_LP[SupportedChainId.ARBITRUM_MAINNET],
LegacyToken.BEAN_WSTETH_WELL_LP[SupportedChainId.ARBITRUM_MAINNET],
LegacyToken.BEAN_WEETH_WELL_LP[SupportedChainId.ARBITRUM_MAINNET],
LegacyToken.BEAN_WBTC_WELL_LP[SupportedChainId.ARBITRUM_MAINNET],
LegacyToken.BEAN_USDC_WELL_LP[SupportedChainId.ARBITRUM_MAINNET],
LegacyToken.BEAN_USDT_WELL_LP[SupportedChainId.ARBITRUM_MAINNET],
];

const l1Tokens = [
LegacyToken.BEAN[SupportedChainId.ETH_MAINNET],
LegacyToken.BEAN_ETH_WELL_LP[SupportedChainId.ETH_MAINNET],
LegacyToken.BEAN_WSTETH_WELL_LP[SupportedChainId.ETH_MAINNET],
];
// const tokens = [sdk.tokens.BEAN, ...sdk.tokens.wellLP];
const document = createMultiTokenQuery(
sdk.contracts.beanstalk.address,
tokens

const l2Document = createMultiTokenQuery(
sdk.addresses.BEANSTALK.get(SupportedChainId.ARBITRUM_MAINNET),
l2Tokens
);

const l1Document = createMultiTokenQuery(
sdk.addresses.BEANSTALK.get(SupportedChainId.ETH_MAINNET),
l1Tokens
);

const output: SiloTokenDataBySeason = {};
let earliestSeason = 999999999;
let earliestSeason = UNREACHABLE_SEASON;

try {
if (numQueries === 0) {
Expand All @@ -107,27 +129,57 @@ const useAvgSeedsPerBDV = (
);
}

const fetchData = async (lte: number) =>
apolloFetch(document, MAX_DATA_PER_QUERY, lte).then((r) => {
earliestSeason = parseResult(r.data, sdk, tokens, output);
const fetchDatas = async (lte: number, chain: SupportedChainId) => {
const isL2 = chain === SupportedChainId.ARBITRUM_MAINNET;
const subgraph = isL2 ? 'beanstalk' : 'beanstalk_eth';
const doc = isL2 ? l2Document : l1Document;
const tokens = isL2 ? l2Tokens : l1Tokens;

return apolloFetch(doc, MAX_DATA_PER_QUERY, lte, subgraph).then((r) => {
earliestSeason = parseResult(
r.data,
sdk,
tokens,
output,
normaliseToken
);
});
};

let chainId = SupportedChainId.ARBITRUM_MAINNET;

await fetchData(earliestSeason);
await fetchDatas(earliestSeason, chainId);

console.log('output: ', output);
if (earliestSeason === UNREACHABLE_SEASON) {
chainId = SupportedChainId.ETH_MAINNET;
await fetchDatas(earliestSeason, chainId);
}

if (numQueries > 1) {
const _seasons: number[] = [];
const _seasons: { lte: number; chain: SupportedChainId }[] = [];
for (let i = 0; i < numQueries - 1; i += 1) {
const offset = (i + 1) * MAX_DATA_PER_QUERY - MAX_DATA_PER_QUERY;
const season_lte = Math.max(0, earliestSeason - offset);

if (season_lte <= L2_MIGRATION_SEASON) {
chainId = SupportedChainId.ETH_MAINNET;
}

if (season_lte < SEED_GAUGE_DEPLOYMENT_SEASON) break;
_seasons.push(season_lte);
_seasons.push({
lte: season_lte,
chain:
season_lte > L2_MIGRATION_SEASON
? SupportedChainId.ARBITRUM_MAINNET
: SupportedChainId.ETH_MAINNET,
});
}

const seasons = _seasons.filter(Boolean);

await Promise.all(seasons.map((season) => fetchData(season)));
await Promise.all(
seasons.map((season) => fetchDatas(season.lte, season.chain))
);
}

const normalized = normalizeQueryResults(sdk, output);
Expand All @@ -145,7 +197,7 @@ const useAvgSeedsPerBDV = (
console.debug('[useAvgSeedsPerBDV/fetch]: fetch complete...');
setLoading(false);
}
}, [numQueries, sdk, skip]);
}, [numQueries, sdk, skip, normaliseToken]);

useEffect(() => {
fetch();
Expand Down Expand Up @@ -176,7 +228,7 @@ function createMultiTokenQuery(
tokens: TokenInstance[]
) {
const queryParts = tokens.map(
(token) => `seasonsSA_${token.symbol}: siloAssetHourlySnapshots(
(token) => `seasonsSA_${token.address}: siloAssetHourlySnapshots(
first: $first
orderBy: season
orderDirection: desc
Expand All @@ -194,7 +246,7 @@ function createMultiTokenQuery(
depositedBDV
createdAt
}
seasonsWL_${token.symbol}: whitelistTokenHourlySnapshots(
seasonsWL_${token.address}: whitelistTokenHourlySnapshots(
first: $first
orderBy: season
orderDirection: desc
Expand Down Expand Up @@ -264,25 +316,34 @@ function parseResult(
data: any,
sdk: BeanstalkSDK,
tokens: TokenInstance[],
output: SiloTokenDataBySeason
output: SiloTokenDataBySeason,
normalizeToken: (token: string) => ERC20Token | undefined
) {
let earliestSeason = Infinity;
let earliestSeason = UNREACHABLE_SEASON;

tokens.forEach((token) => {
const siloAssets = data[`seasonsSA_${token.symbol}`] as SiloAssetsReturn[];
const whitelisted = data[`seasonsWL_${token.symbol}`] as WhitelistReturn[];
for (const chainToken of tokens) {
const siloAssets = data[
`seasonsSA_${chainToken.address}`
] as SiloAssetsReturn[];
const whitelisted = data[
`seasonsWL_${chainToken.address}`
] as WhitelistReturn[];

if (!siloAssets || !whitelisted) return;
const token = normalizeToken(chainToken.address);

if (!siloAssets?.length || !whitelisted?.length || !token) {
continue;
}

// Results are sorted in desc order.
// Find earliest season from the BEAN dataset
if (tokenIshEqual(token, sdk.tokens.BEAN)) {
earliestSeason = Math.max(
earliestSeason = Math.max(
earliestSeason,
Math.max(
siloAssets[siloAssets.length - 1].season,
whitelisted[whitelisted.length - 1].season
);
}
// Create a map of seasons to whitelisted data for quick lookup
)
);

const whitelistedMap = new Map(whitelisted.map((w) => [w.season, w]));

siloAssets.forEach((sData) => {
Expand All @@ -295,7 +356,7 @@ function parseResult(
whitelistedMap.forEach((wData) => {
processTokenData(token, null, wData, output, sdk);
});
});
}

return earliestSeason;
}
Expand Down Expand Up @@ -338,7 +399,7 @@ function normalizeQueryResults(

const value = obj.grownStalkPerBDV.div(obj.depositedBDV);

const time = Number(obj.createdAt) as Time;
const time = (Number(obj.createdAt) * 60 * 60) as Time;

if (value.gt(0) && !timestamps.has(time)) {
map[season] = {
Expand Down
9 changes: 7 additions & 2 deletions projects/ui/src/hooks/beanstalk/useSeedGauge.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useMemo } from 'react';
import { multicall } from '@wagmi/core';
import { useQuery } from '@tanstack/react-query';
import { Token } from '@beanstalk/sdk';
import { ERC20Token, Token } from '@beanstalk/sdk';
import { BigNumber as BigNumberJS } from 'bignumber.js';
import { BigNumber as BigNumberEthers } from 'ethers';

Expand Down Expand Up @@ -35,6 +35,7 @@ interface BaseTokenSeedGaugeQueryInfo {
}

export interface TokenSeedGaugeInfo extends BaseTokenSeedGaugeQueryInfo {
token: ERC20Token;
/**
* the current percentage of all BDV deposited in the silo
*/
Expand Down Expand Up @@ -187,8 +188,12 @@ const useSeedGauge = () => {
if (values.isAllocatedGP) {
totalRelevantBdv = totalRelevantBdv.plus(tokenTotalBdv);
}
const token = sdk.tokens.findByAddress(address);
if (!token) return;

map[address] = {
...tokenSettingMap[address],
token: token as ERC20Token,
totalBdv: tokenTotalBdv,
currentPctDepositedBdv: ZERO_BN, // filler
};
Expand All @@ -202,7 +207,7 @@ const useSeedGauge = () => {
});

return map;
}, [query.data?.tokenSettings, siloBals]);
}, [query.data?.tokenSettings, siloBals, sdk.tokens]);

return useMemo(
() => ({
Expand Down
15 changes: 1 addition & 14 deletions projects/ui/src/hooks/beanstalk/useTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,19 +225,6 @@ export const useSupportedBalanceTokens = () => {
}, [sdk]);
};

export const useNonWellLPERC20Tokens = () => {
const sdk = useSdk();

return useMemo(() => {






}, []);
}

/**
* Sort the whitelist by
* [
Expand Down Expand Up @@ -417,4 +404,4 @@ export const useGetNormaliseChainToken = () => {
);

return getToken;
};
};

0 comments on commit ccc28df

Please sign in to comment.