feat(rwallet): use CoinGecko Demo API key for batch token pricing
Reads COINGECKO_API_KEY from env (injected via Infisical) and appends x_cg_demo_api_key param. Enables batch lookups + spam filtering. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
1c338529bf
commit
e0e9802bd7
|
|
@ -42,15 +42,23 @@ const TTL = 5 * 60 * 1000; // 5 minutes
|
||||||
const cache = new Map<string, CacheEntry>();
|
const cache = new Map<string, CacheEntry>();
|
||||||
const inFlight = new Map<string, Promise<CacheEntry>>();
|
const inFlight = new Map<string, Promise<CacheEntry>>();
|
||||||
|
|
||||||
|
const CG_API_KEY = process.env.COINGECKO_API_KEY || "";
|
||||||
|
|
||||||
|
function cgUrl(url: string): string {
|
||||||
|
if (!CG_API_KEY) return url;
|
||||||
|
const sep = url.includes("?") ? "&" : "?";
|
||||||
|
return `${url}${sep}x_cg_demo_api_key=${CG_API_KEY}`;
|
||||||
|
}
|
||||||
|
|
||||||
async function cgFetch(url: string): Promise<any> {
|
async function cgFetch(url: string): Promise<any> {
|
||||||
const res = await fetch(url, {
|
const res = await fetch(cgUrl(url), {
|
||||||
headers: { accept: "application/json" },
|
headers: { accept: "application/json" },
|
||||||
signal: AbortSignal.timeout(10000),
|
signal: AbortSignal.timeout(10000),
|
||||||
});
|
});
|
||||||
if (res.status === 429) {
|
if (res.status === 429) {
|
||||||
console.warn("[price-feed] CoinGecko rate limited, waiting 60s...");
|
console.warn("[price-feed] CoinGecko rate limited, waiting 60s...");
|
||||||
await new Promise((r) => setTimeout(r, 60000));
|
await new Promise((r) => setTimeout(r, 60000));
|
||||||
const retry = await fetch(url, {
|
const retry = await fetch(cgUrl(url), {
|
||||||
headers: { accept: "application/json" },
|
headers: { accept: "application/json" },
|
||||||
signal: AbortSignal.timeout(10000),
|
signal: AbortSignal.timeout(10000),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue