Skip to content

Commit

Permalink
chore: turn on token restriction in multi route
Browse files Browse the repository at this point in the history
  • Loading branch information
chambaz committed Dec 12, 2024
1 parent c0c7ee9 commit 69f6a44
Showing 1 changed file with 75 additions and 94 deletions.
169 changes: 75 additions & 94 deletions apps/marginfi-v2-ui/src/pages/api/tokens/multi.ts
Original file line number Diff line number Diff line change
@@ -1,95 +1,85 @@
import { NextResponse } from "next/server";
import { NextApiRequest, NextApiResponse } from "next";
import {
BankMetadata,
// loadBankMetadatas,
// chunkedGetRawMultipleAccountInfoOrdered,
// Wallet,
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 marginfiConfig from "~/config/marginfi";
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 const config = {
runtime: "edge",
};

export default async function handler(req: Request) {
// Get query params from URL
const url = new URL(req.url);
const mintList = url.searchParams.get("mintList");

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const { mintList } = req.query;
if (!mintList) {
return NextResponse.json({ error: "No mintList provided" }, { status: 400 });
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 {
// let bankMetadataCache: {
// [address: string]: BankMetadata;
// } = {};

// // 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: marginfiConfig.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) {
// return NextResponse.json(
// {
// error: "No supported tokens in request",
// },
// { status: 400 }
// );
// }
// 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=${mintList}`, {
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 || "",
Expand All @@ -100,28 +90,19 @@ export default async function handler(req: Request) {
clearTimeout(timeoutId);

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

// return with cache headers
return NextResponse.json(data, {
headers: {
"Cache-Control": "public, s-maxage=300, stale-while-revalidate=0",
},
});
// 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);
return NextResponse.json(
{
error: error instanceof Error ? error.message : "Error fetching data",
},
{ status: 500 }
);
res.status(500).json({
error: error instanceof Error ? error.message : "Error fetching data",
});
}
}

0 comments on commit 69f6a44

Please sign in to comment.