@relai-fi/x402 0.5.13 → 0.5.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -139,7 +139,7 @@ var NETWORK_TOKENS = {
139
139
  isStableUsd: true
140
140
  },
141
141
  {
142
- address: "0xB6BB22f4D1e58E9E43eFa2ec7F572D215B3CF08a",
142
+ address: "0x185a7228a7ef0ff5c1b6b3f1045e0b95547ca143",
143
143
  symbol: "BBRL",
144
144
  name: "Braza BRL",
145
145
  decimals: 18,
@@ -241,6 +241,9 @@ function stripePayTo(stripeSecretKey, options) {
241
241
  }
242
242
  var USD_PRICE_CACHE_TTL_MS = 60 * 1e3;
243
243
  var usdPriceCache = /* @__PURE__ */ new Map();
244
+ var GECKOTERMINAL_NETWORK_BY_RELAI = {
245
+ polygon: "polygon_pos"
246
+ };
244
247
  var COINGECKO_ID_BY_SYMBOL = {
245
248
  WETH: "ethereum",
246
249
  WBTC: "bitcoin",
@@ -278,6 +281,42 @@ async function fetchUsdPriceFromCoinGecko(coinId) {
278
281
  });
279
282
  return usd;
280
283
  }
284
+ async function fetchUsdPriceFromGeckoTerminal(network, tokenAddress) {
285
+ const geckoNetwork = GECKOTERMINAL_NETWORK_BY_RELAI[network];
286
+ if (!geckoNetwork) {
287
+ throw new Error(`GeckoTerminal network not configured for ${network}`);
288
+ }
289
+ const normalizedAddress = String(tokenAddress || "").trim().toLowerCase();
290
+ if (!normalizedAddress) {
291
+ throw new Error("GeckoTerminal requires a token address");
292
+ }
293
+ const cacheKey = `gt:${geckoNetwork}:${normalizedAddress}`;
294
+ const now = Date.now();
295
+ const cached = usdPriceCache.get(cacheKey);
296
+ if (cached && cached.expiresAt > now) {
297
+ return cached.usd;
298
+ }
299
+ const url = `https://api.geckoterminal.com/api/v2/networks/${encodeURIComponent(geckoNetwork)}/tokens/${encodeURIComponent(normalizedAddress)}`;
300
+ const res = await fetch(url, {
301
+ method: "GET",
302
+ headers: {
303
+ Accept: "application/json"
304
+ }
305
+ });
306
+ if (!res.ok) {
307
+ throw new Error(`GeckoTerminal price request failed: HTTP ${res.status}`);
308
+ }
309
+ const payload = await res.json();
310
+ const usd = Number(payload?.data?.attributes?.price_usd);
311
+ if (!Number.isFinite(usd) || usd <= 0) {
312
+ throw new Error(`GeckoTerminal returned invalid usd price for ${normalizedAddress} on ${geckoNetwork}`);
313
+ }
314
+ usdPriceCache.set(cacheKey, {
315
+ usd,
316
+ expiresAt: now + USD_PRICE_CACHE_TTL_MS
317
+ });
318
+ return usd;
319
+ }
281
320
  async function resolveAmountAtomicFromUsd({
282
321
  priceUsd,
283
322
  token,
@@ -297,7 +336,22 @@ async function resolveAmountAtomicFromUsd({
297
336
  throw new Error(`No USD quote source configured for token ${symbol || token.address} on ${network}`);
298
337
  }
299
338
  const overrideEnv = process.env[`EVM_TOKEN_PRICE_${symbol}_USD`];
300
- const usdPerToken = overrideEnv && Number(overrideEnv) > 0 ? Number(overrideEnv) : await fetchUsdPriceFromCoinGecko(coinGeckoId);
339
+ let usdPerToken;
340
+ if (overrideEnv && Number(overrideEnv) > 0) {
341
+ usdPerToken = Number(overrideEnv);
342
+ } else {
343
+ try {
344
+ usdPerToken = await fetchUsdPriceFromCoinGecko(coinGeckoId);
345
+ } catch (coinGeckoError) {
346
+ try {
347
+ usdPerToken = await fetchUsdPriceFromGeckoTerminal(network, token.address);
348
+ } catch (geckoTerminalError) {
349
+ throw new Error(
350
+ `USD quote failed for ${symbol || token.address} on ${network}. CoinGecko: ${coinGeckoError instanceof Error ? coinGeckoError.message : String(coinGeckoError)}; GeckoTerminal: ${geckoTerminalError instanceof Error ? geckoTerminalError.message : String(geckoTerminalError)}`
351
+ );
352
+ }
353
+ }
354
+ }
301
355
  const tokenAmount = priceUsd / usdPerToken;
302
356
  const rawUnits = tokenAmount * Math.pow(10, decimals);
303
357
  if (!Number.isFinite(rawUnits) || rawUnits <= 0) {