Skip to content
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

feat(mfi-v2-ui): state fetching optimization #379

Merged
merged 1 commit into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 56 additions & 9 deletions packages/marginfi-v2-ui-state/src/lib/mrgnlend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,28 +158,75 @@ export async function fetchBirdeyePrices(mints: PublicKey[], apiKey?: string): P
throw new Error("Failed to fetch price");
}

export async function fetchEmissionsPriceMap(
banks: Bank[],
connection: Connection,
export async function makeExtendedBankEmission(
banks: ExtendedBankInfo[],
extendedBankMetadatas: ExtendedBankMetadata[],
tokenMap: TokenPriceMap,
apiKey?: string
): Promise<TokenPriceMap> {
const banksWithEmissions = banks.filter((bank) => !bank.emissionsMint.equals(PublicKey.default));
const emissionsMints = banksWithEmissions.map((bank) => bank.emissionsMint);

let birdeyePrices = emissionsMints.map((m) => new BigNumber(0));
): Promise<[ExtendedBankInfo[], ExtendedBankMetadata[]]> {
const emissionsMints = Object.keys(tokenMap).map((key) => new PublicKey(key));
let birdeyePrices = emissionsMints.map(() => new BigNumber(0));

try {
birdeyePrices = await fetchBirdeyePrices(emissionsMints, apiKey);
} catch (err) {
console.log("Failed to fetch emissions prices from Birdeye", err);
}

emissionsMints.map((mint, idx) => {
tokenMap[mint.toBase58()] = { ...tokenMap[mint.toBase58()], price: birdeyePrices[idx] };
});

const updatedBanks = banks.map((bank) => {
const rawBank = bank.info.rawBank;
const emissionTokenData = tokenMap[rawBank.emissionsMint.toBase58()];
let emissionsRate: number = 0;
let emissions = Emissions.Inactive;
if ((rawBank.emissionsActiveLending || rawBank.emissionsActiveBorrowing) && emissionTokenData) {
const emissionsRateAmount = new BigNumber(nativeToUi(rawBank.emissionsRate, emissionTokenData.decimals));
const emissionsRateValue = emissionsRateAmount.times(emissionTokenData.price);
const emissionsRateAdditionalyApy = emissionsRateValue.div(bank.info.oraclePrice.price);

emissionsRate = emissionsRateAdditionalyApy.toNumber();

if (rawBank.emissionsActiveBorrowing) {
emissions = Emissions.Borrowing;
} else if (rawBank.emissionsActiveLending) {
emissions = Emissions.Lending;
}

bank.info.state = {
...bank.info.state,
emissionsRate,
emissions,
};
}
return bank;
});

const sortedExtendedBankInfos = updatedBanks.sort(
(a, b) => b.info.state.totalDeposits * b.info.state.price - a.info.state.totalDeposits * a.info.state.price
);

const sortedExtendedBankMetadatas = extendedBankMetadatas.sort((am, bm) => {
const a = sortedExtendedBankInfos.find((a) => a.address.equals(am.address))!;
const b = sortedExtendedBankInfos.find((b) => b.address.equals(bm.address))!;
return b.info.state.totalDeposits * b.info.state.price - a.info.state.totalDeposits * a.info.state.price;
});

return [sortedExtendedBankInfos, sortedExtendedBankMetadatas];
}

export async function makeEmissionsPriceMap(banks: Bank[], connection: Connection): Promise<TokenPriceMap> {
const banksWithEmissions = banks.filter((bank) => !bank.emissionsMint.equals(PublicKey.default));
const emissionsMints = banksWithEmissions.map((bank) => bank.emissionsMint);

const mintAis = await connection.getMultipleAccountsInfo(emissionsMints);

const mint = mintAis.map((ai) => MintLayout.decode(ai!.data));
const emissionsPrices = banksWithEmissions.map((bank, i) => ({
mint: bank.emissionsMint,
price: birdeyePrices[i],
price: new BigNumber(0),
decimals: mint[0].decimals,
}));

Expand Down
27 changes: 23 additions & 4 deletions packages/marginfi-v2-ui-state/src/store/mrgnlendStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Bank, OraclePrice } from "@mrgnlabs/marginfi-client-v2";
import { Connection, PublicKey } from "@solana/web3.js";
import {
DEFAULT_ACCOUNT_SUMMARY,
fetchEmissionsPriceMap,
makeEmissionsPriceMap,
computeAccountSummary,
fetchTokenAccounts,
makeExtendedBankInfo,
Expand All @@ -21,6 +21,7 @@ import {
TokenAccountMap,
ExtendedBankMetadata,
makeExtendedBankMetadata,
makeExtendedBankEmission,
} from "../lib";
import { getPointsSummary } from "../lib/points";
import { create, StateCreator } from "zustand";
Expand Down Expand Up @@ -131,7 +132,7 @@ const stateCreator: StateCreator<MrgnlendState, [], []> = (set, get) => ({
const banks = [...marginfiClient.banks.values()];

const birdEyeApiKey = args?.birdEyeApiKey ?? get().birdEyeApiKey;
const priceMap = await fetchEmissionsPriceMap(banks, connection, birdEyeApiKey);
const priceMap = await makeEmissionsPriceMap(banks, connection);

let nativeSolBalance: number = 0;
let tokenAccountMap: TokenAccountMap;
Expand Down Expand Up @@ -252,7 +253,7 @@ const stateCreator: StateCreator<MrgnlendState, [], []> = (set, get) => ({
accountSummary = computeAccountSummary(selectedAccount, extendedBankInfos);
}

const pointSummary = await getPointsSummary();
const pointsTotal = get().protocolStats.pointsTotal;

set({
initialized: true,
Expand All @@ -268,13 +269,31 @@ const stateCreator: StateCreator<MrgnlendState, [], []> = (set, get) => ({
deposits,
borrows,
tvl: deposits - borrows,
pointsTotal: pointSummary.points_total,
pointsTotal: pointsTotal,
},
selectedAccount,
nativeSolBalance,
accountSummary,
birdEyeApiKey,
});

const pointSummary = await getPointsSummary();

set({
protocolStats: { deposits, borrows, tvl: deposits - borrows, pointsTotal: pointSummary.points_total },
});

const [sortedExtendedBankEmission, sortedExtendedBankMetadatasEmission] = await makeExtendedBankEmission(
sortedExtendedBankInfos,
sortedExtendedBankMetadatas,
priceMap,
birdEyeApiKey
);

set({
extendedBankInfos: sortedExtendedBankEmission,
extendedBankMetadatas: sortedExtendedBankMetadatasEmission,
});
} catch (err) {
console.error("error refreshing state: ", err);
set({ isRefreshingStore: false });
Expand Down