From 28488ba03b5e189fdc5408317acb054302fd61fc Mon Sep 17 00:00:00 2001 From: Kobe Leenders Date: Wed, 29 Nov 2023 22:17:49 +0100 Subject: [PATCH] feat: birdeye improvement --- apps/marginfi-v2-ui/src/pages/index.tsx | 9 +++++++++ .../marginfi-v2-ui-state/src/lib/mrgnlend.ts | 18 +++++++++++++----- .../src/store/mrgnlendStore.ts | 14 +++++++------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/apps/marginfi-v2-ui/src/pages/index.tsx b/apps/marginfi-v2-ui/src/pages/index.tsx index 7dae86c16f..8d202730b6 100644 --- a/apps/marginfi-v2-ui/src/pages/index.tsx +++ b/apps/marginfi-v2-ui/src/pages/index.tsx @@ -17,6 +17,7 @@ import { PageHeader } from "~/components/common/PageHeader"; import { IconAlertTriangle } from "~/components/ui/icons"; import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger } from "~/components/ui/select"; +import { showErrorToast } from "~/utils/toastUtils"; const DesktopAccountSummary = dynamic( async () => (await import("~/components/desktop/DesktopAccountSummary")).DesktopAccountSummary, @@ -41,6 +42,7 @@ const Home = () => { setIsRefreshingStore, marginfiAccounts, selectedAccount, + emissionTokenMap, ] = useMrgnlendStore((state) => [ state.fetchMrgnlendState, state.initialized, @@ -48,8 +50,15 @@ const Home = () => { state.setIsRefreshingStore, state.marginfiAccounts, state.selectedAccount, + state.emissionTokenMap, ]); + React.useEffect(() => { + if (emissionTokenMap === null) { + showErrorToast("Failed to fetch prices, emission APY may be incorrect."); + } + }, [emissionTokenMap]); + React.useEffect(() => { const fetchData = () => { setIsRefreshingStore(true); diff --git a/packages/marginfi-v2-ui-state/src/lib/mrgnlend.ts b/packages/marginfi-v2-ui-state/src/lib/mrgnlend.ts index 7a62d79d6b..455ef1f03b 100644 --- a/packages/marginfi-v2-ui-state/src/lib/mrgnlend.ts +++ b/packages/marginfi-v2-ui-state/src/lib/mrgnlend.ts @@ -163,7 +163,7 @@ export async function makeExtendedBankEmission( extendedBankMetadatas: ExtendedBankMetadata[], tokenMap: TokenPriceMap, apiKey?: string -): Promise<[ExtendedBankInfo[], ExtendedBankMetadata[]]> { +): Promise<[ExtendedBankInfo[], ExtendedBankMetadata[], TokenPriceMap]> { const emissionsMints = Object.keys(tokenMap).map((key) => new PublicKey(key)); let birdeyePrices = emissionsMints.map(() => new BigNumber(0)); @@ -171,10 +171,14 @@ export async function makeExtendedBankEmission( birdeyePrices = await fetchBirdeyePrices(emissionsMints, apiKey); } catch (err) { console.log("Failed to fetch emissions prices from Birdeye", err); + birdeyePrices = null; } emissionsMints.map((mint, idx) => { - tokenMap[mint.toBase58()] = { ...tokenMap[mint.toBase58()], price: birdeyePrices[idx] }; + tokenMap[mint.toBase58()] = { + ...tokenMap[mint.toBase58()], + price: birdeyePrices ? birdeyePrices[idx] : new BigNumber(0), + }; }); const updatedBanks = banks.map((bank) => { @@ -214,10 +218,14 @@ export async function makeExtendedBankEmission( return b.info.state.totalDeposits * b.info.state.price - a.info.state.totalDeposits * a.info.state.price; }); - return [sortedExtendedBankInfos, sortedExtendedBankMetadatas]; + return [sortedExtendedBankInfos, sortedExtendedBankMetadatas, birdeyePrices ? tokenMap : null]; } -export async function makeEmissionsPriceMap(banks: Bank[], connection: Connection): Promise { +export async function makeEmissionsPriceMap( + banks: Bank[], + connection: Connection, + emissionTokenMap: TokenPriceMap +): Promise { const banksWithEmissions = banks.filter((bank) => !bank.emissionsMint.equals(PublicKey.default)); const emissionsMints = banksWithEmissions.map((bank) => bank.emissionsMint); @@ -226,7 +234,7 @@ export async function makeEmissionsPriceMap(banks: Bank[], connection: Connectio const mint = mintAis.map((ai) => MintLayout.decode(ai!.data)); const emissionsPrices = banksWithEmissions.map((bank, i) => ({ mint: bank.emissionsMint, - price: new BigNumber(0), + price: emissionTokenMap ? emissionTokenMap[bank.emissionsMint]?.price ?? new BigNumber(0) : new BigNumber(0), decimals: mint[0].decimals, })); diff --git a/packages/marginfi-v2-ui-state/src/store/mrgnlendStore.ts b/packages/marginfi-v2-ui-state/src/store/mrgnlendStore.ts index 1c3649cfe4..868e48e5ab 100644 --- a/packages/marginfi-v2-ui-state/src/store/mrgnlendStore.ts +++ b/packages/marginfi-v2-ui-state/src/store/mrgnlendStore.ts @@ -22,6 +22,7 @@ import { ExtendedBankMetadata, makeExtendedBankMetadata, makeExtendedBankEmission, + TokenPriceMap, } from "../lib"; import { getPointsSummary } from "../lib/points"; import { create, StateCreator } from "zustand"; @@ -49,6 +50,7 @@ interface MrgnlendState { selectedAccount: MarginfiAccountWrapper | null; nativeSolBalance: number; accountSummary: AccountSummary; + emissionTokenMap: TokenPriceMap | null; birdEyeApiKey: string; // Actions @@ -103,6 +105,7 @@ const stateCreator: StateCreator = (set, get) => ({ nativeSolBalance: 0, accountSummary: DEFAULT_ACCOUNT_SUMMARY, birdEyeApiKey: "", + emissionTokenMap: {}, // Actions fetchMrgnlendState: async (args?: { @@ -132,7 +135,7 @@ const stateCreator: StateCreator = (set, get) => ({ const banks = [...marginfiClient.banks.values()]; const birdEyeApiKey = args?.birdEyeApiKey ?? get().birdEyeApiKey; - const priceMap = await makeEmissionsPriceMap(banks, connection); + const priceMap = await makeEmissionsPriceMap(banks, connection, get().emissionTokenMap); let nativeSolBalance: number = 0; let tokenAccountMap: TokenAccountMap; @@ -283,16 +286,13 @@ const stateCreator: StateCreator = (set, get) => ({ protocolStats: { deposits, borrows, tvl: deposits - borrows, pointsTotal: pointSummary.points_total }, }); - const [sortedExtendedBankEmission, sortedExtendedBankMetadatasEmission] = await makeExtendedBankEmission( - sortedExtendedBankInfos, - sortedExtendedBankMetadatas, - priceMap, - birdEyeApiKey - ); + const [sortedExtendedBankEmission, sortedExtendedBankMetadatasEmission, emissionTokenMap] = + await makeExtendedBankEmission(sortedExtendedBankInfos, sortedExtendedBankMetadatas, priceMap, birdEyeApiKey); set({ extendedBankInfos: sortedExtendedBankEmission, extendedBankMetadatas: sortedExtendedBankMetadatasEmission, + emissionTokenMap: emissionTokenMap, }); } catch (err) { console.error("error refreshing state: ", err);