Skip to content

Commit

Permalink
Merge pull request #996 from mrgnlabs/chore/be-route
Browse files Browse the repository at this point in the history
chore(mfi-v2-ui): be routes
  • Loading branch information
k0beLeenders authored Dec 11, 2024
2 parents 99c6c4e + 1084e3e commit b8f3e52
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 44 deletions.
2 changes: 1 addition & 1 deletion apps/marginfi-v2-ui/src/components/common/Stake/stake.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const Stake = () => {
React.useEffect(() => {
const fetchIntegrations = async () => {
try {
const res = await fetch(`/api/birdeye/markets?token=` + LST_MINT);
const res = await fetch(`/api/tokens/markets?token=` + LST_MINT);
if (!res.ok) {
return;
}
Expand Down
42 changes: 0 additions & 42 deletions apps/marginfi-v2-ui/src/pages/api/birdeye/index.ts

This file was deleted.

108 changes: 108 additions & 0 deletions apps/marginfi-v2-ui/src/pages/api/tokens/multi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { NextApiRequest, NextApiResponse } from "next";
import {
BankMetadata,
loadBankMetadatas,
chunkedGetRawMultipleAccountInfoOrdered,
Wallet,
} from "@mrgnlabs/mrgn-common";
import { Connection, PublicKey } from "@solana/web3.js";
import { Program, AnchorProvider } from "@coral-xyz/anchor";
import { Bank, BankRaw, MARGINFI_IDL, MarginfiIdlType, MarginfiProgram } from "@mrgnlabs/marginfi-client-v2";
import config from "~/config/marginfi";

const BIRDEYE_API = "https://public-api.birdeye.so";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const { mintList } = req.query;
if (!mintList) {
res.status(400).json({ error: "No mintList provided" });
return;
}

// use abort controller to restrict fetch to 10 seconds
const controller = new AbortController();
const timeoutId = setTimeout(() => {
controller.abort();
}, 5000);

let bankMetadataCache: {
[address: string]: BankMetadata;
} = {};

try {
// load bank metadata
bankMetadataCache = await loadBankMetadatas();

// fetch mfi banks to get emissions mints
const connection = new Connection(process.env.PRIVATE_RPC_ENDPOINT_OVERRIDE || "");
const idl = { ...MARGINFI_IDL, address: config.mfiConfig.programId.toBase58() } as unknown as MarginfiIdlType;

const provider = new AnchorProvider(connection, {} as Wallet, {
...AnchorProvider.defaultOptions(),
commitment: connection.commitment ?? AnchorProvider.defaultOptions().commitment,
});
const program = new Program(idl, provider) as any as MarginfiProgram;

const bankAddresses = Object.keys(bankMetadataCache);

const banksAis = await chunkedGetRawMultipleAccountInfoOrdered(connection, bankAddresses);
let banksMap: { address: PublicKey; data: BankRaw }[] = banksAis.map((account, index) => ({
address: new PublicKey(bankAddresses[index]),
data: Bank.decodeBankRaw(account.data, program.idl),
}));

// all supported tokens, banks / emissions mints
const allTokens = [
...new Set([
...Object.values(bankMetadataCache).map((bank) => bank.tokenAddress),
...banksMap
.map((bank) => bank.data.emissionsMint.toBase58())
.filter((mint) => mint !== PublicKey.default.toBase58()),
]),
];

// filter out restricted tokens
const requestedMints = (mintList as string).split(",");
const supportedMints = requestedMints.filter((mint) => allTokens.includes(mint));
const restrictedMints = requestedMints.filter((mint) => !allTokens.includes(mint));

if (restrictedMints.length > 0) {
console.log("Filtered out restricted tokens:", restrictedMints);
}

// if no supported tokens, return error
if (supportedMints.length === 0) {
res.status(400).json({
error: "No supported tokens in request",
});
return;
}

// continue with birdeye API call only for supported tokens
const response = await fetch(`${BIRDEYE_API}/defi/multi_price?list_address=${supportedMints.join(",")}`, {
headers: {
Accept: "application/json",
"X-Api-Key": process.env.BIRDEYE_API_KEY || "",
},
signal: controller.signal,
});

clearTimeout(timeoutId);

if (!response.ok) {
return res.status(response.status).json({
error: `Birdeye API error: ${response.status} ${response.statusText}`,
});
}
const data = await response.json();

// cache for 20 minutes
res.setHeader("Cache-Control", "s-maxage=1200, stale-while-revalidate=300");
res.status(200).json(data);
} catch (error) {
console.error("Error:", error);
res.status(500).json({
error: error instanceof Error ? error.message : "Error fetching data",
});
}
}
2 changes: 1 addition & 1 deletion packages/marginfi-v2-ui-state/src/lib/mrgnlend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ function makeBankInfo(bank: Bank, oraclePrice: OraclePrice, emissionTokenData?:
export async function fetchBirdeyePrices(mints: PublicKey[], apiKey?: string): Promise<BigNumber[]> {
const mintList = mints.map((mint) => mint.toBase58()).join(",");

const response = await fetch(`/api/birdeye?mintList=${mintList}`, {
const response = await fetch(`/api/tokens/multi?mintList=${mintList}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Expand Down

0 comments on commit b8f3e52

Please sign in to comment.