@trustware/sdk-staging 1.1.11-staging.1 → 1.1.12-staging.1

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.
Files changed (44) hide show
  1. package/README.md +54 -21
  2. package/dist/{blockchain-BxAFzp0s.d.cts → blockchain-DmCPxnxr.d.cts} +25 -1
  3. package/dist/{blockchain-BxAFzp0s.d.ts → blockchain-DmCPxnxr.d.ts} +25 -1
  4. package/dist/constants.cjs +1 -1
  5. package/dist/constants.mjs +1 -1
  6. package/dist/{core-BgYLe9Q7.d.ts → core-B4YDGtJT.d.ts} +3 -3
  7. package/dist/{core-fLSt4qD2.d.cts → core-Ck7dinYj.d.cts} +3 -3
  8. package/dist/core.cjs +141 -52
  9. package/dist/core.cjs.map +1 -1
  10. package/dist/core.d.cts +4 -4
  11. package/dist/core.d.ts +4 -4
  12. package/dist/core.mjs +139 -51
  13. package/dist/core.mjs.map +1 -1
  14. package/dist/index.cjs +166 -75
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +14 -8
  17. package/dist/index.d.ts +14 -8
  18. package/dist/index.mjs +164 -75
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/{manager-DT8enQbE.d.cts → manager-BZ8gyHGT.d.cts} +90 -23
  21. package/dist/{manager-BY3NHAks.d.ts → manager-D8nQsod2.d.ts} +90 -23
  22. package/dist/{metadata-DyxUcKHk.d.cts → metadata-B23D0oO9.d.cts} +1 -1
  23. package/dist/{metadata-BPvFYMlc.d.ts → metadata-BOjEF7oo.d.ts} +1 -1
  24. package/dist/smart-account.cjs +62 -47
  25. package/dist/smart-account.cjs.map +1 -1
  26. package/dist/smart-account.d.cts +6 -0
  27. package/dist/smart-account.d.ts +6 -0
  28. package/dist/smart-account.mjs +62 -47
  29. package/dist/smart-account.mjs.map +1 -1
  30. package/dist/{types-BJY9r-mz.d.ts → types-CMmx0S4U.d.ts} +1 -1
  31. package/dist/{types-DX3HtFcn.d.cts → types-DEUb5IZA.d.cts} +1 -1
  32. package/dist/wallet.cjs +51 -40
  33. package/dist/wallet.cjs.map +1 -1
  34. package/dist/wallet.d.cts +4 -4
  35. package/dist/wallet.d.ts +4 -4
  36. package/dist/wallet.mjs +51 -40
  37. package/dist/wallet.mjs.map +1 -1
  38. package/dist/widget.cjs +160 -75
  39. package/dist/widget.cjs.map +1 -1
  40. package/dist/widget.d.cts +2 -2
  41. package/dist/widget.d.ts +2 -2
  42. package/dist/widget.mjs +160 -75
  43. package/dist/widget.mjs.map +1 -1
  44. package/package.json +74 -5
package/dist/widget.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import React__default from 'react';
2
- import { N as NavigationStep } from './types-DX3HtFcn.cjs';
3
- import './blockchain-BxAFzp0s.cjs';
2
+ import { N as NavigationStep } from './types-DEUb5IZA.cjs';
3
+ import './blockchain-DmCPxnxr.cjs';
4
4
 
5
5
  type Theme = "light" | "dark" | "system";
6
6
 
package/dist/widget.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import React__default from 'react';
2
- import { N as NavigationStep } from './types-BJY9r-mz.js';
3
- import './blockchain-BxAFzp0s.js';
2
+ import { N as NavigationStep } from './types-CMmx0S4U.js';
3
+ import './blockchain-DmCPxnxr.js';
4
4
 
5
5
  type Theme = "light" | "dark" | "system";
6
6
 
package/dist/widget.mjs CHANGED
@@ -535,19 +535,27 @@ var init_defaults = __esm({
535
535
  });
536
536
 
537
537
  // src/types/config.ts
538
- var DEFAULT_RETRY_CONFIG, DEFAULT_FEATURE_FLAGS;
538
+ var DEFAULT_RETRY_CONFIG, RATE_LIMIT_WAIT_BUDGET_MS, DEFAULT_FEATURE_FLAGS;
539
539
  var init_config = __esm({
540
540
  "src/types/config.ts"() {
541
541
  "use strict";
542
542
  DEFAULT_RETRY_CONFIG = {
543
- autoRetry: true,
544
- maxRetries: 3,
545
- baseDelayMs: 1e3,
546
543
  approachingThreshold: 5
547
544
  };
545
+ RATE_LIMIT_WAIT_BUDGET_MS = 1e4;
548
546
  DEFAULT_FEATURE_FLAGS = {
549
547
  tokensPagination: true,
550
- balanceStreaming: false,
548
+ // On by default: an address scan covers every configured chain and takes
549
+ // seconds end to end, so streaming turns one long wait into a wallet that
550
+ // fills in as results land — first chunk in ~200ms against a ~2.3s buffered
551
+ // response, measured on a live backend.
552
+ //
553
+ // Safe to default because the path degrades on its own: a backend with
554
+ // BALANCE_STREAM_ENABLED off refuses the stream, and the SDK falls back to
555
+ // the buffered endpoint (emitting balance_stream_fallback), as does any
556
+ // runtime whose fetch has no readable body — React Native, most notably.
557
+ // The cost of defaulting ahead of a backend is one refused request per scan.
558
+ balanceStreaming: true,
551
559
  shouldAllowGA4: true,
552
560
  swapMode: false,
553
561
  swapDefaultDestToken: null,
@@ -563,7 +571,7 @@ var init_constants = __esm({
563
571
  "src/constants.ts"() {
564
572
  "use strict";
565
573
  SDK_NAME = "@trustware/sdk";
566
- SDK_VERSION = "1.1.11-staging.1";
574
+ SDK_VERSION = "1.1.12-staging.1";
567
575
  API_ROOT = "https://bv-staging-api.trustware.io";
568
576
  GTM_ID = "GTM-TZDGNCXB";
569
577
  API_PREFIX = "/api";
@@ -611,7 +619,7 @@ function isNotFoundError(err) {
611
619
  return err instanceof Error && err.message.startsWith("HTTP 404");
612
620
  }
613
621
  async function validateSdkAccess() {
614
- const r = await fetch(`${apiBase()}/sdk/validate`, {
622
+ const r = await fetch(`${apiBase()}/v1/sdk/validate`, {
615
623
  method: "GET",
616
624
  headers: jsonHeaders()
617
625
  });
@@ -650,60 +658,66 @@ function notifyRateLimitCallbacks(info, isRateLimited, retryCount) {
650
658
  retry.onRateLimitApproaching(info, retry.approachingThreshold);
651
659
  }
652
660
  }
653
- function calculateBackoffDelay(baseDelayMs, retryCount, retryAfter) {
654
- if (retryAfter && retryAfter > 0) {
655
- return retryAfter * 1e3;
661
+ function serverDirectedWaitMs(info) {
662
+ if (!info) return null;
663
+ if (typeof info.retryAfter === "number" && info.retryAfter > 0) {
664
+ return info.retryAfter * 1e3;
656
665
  }
657
- return baseDelayMs * Math.pow(2, retryCount);
666
+ if (typeof info.reset === "number" && info.reset > 0) {
667
+ const untilReset = info.reset * 1e3 - Date.now();
668
+ if (untilReset > 0) return untilReset;
669
+ }
670
+ return null;
658
671
  }
659
672
  function sleep(ms) {
660
673
  return new Promise((resolve) => setTimeout(resolve, ms));
661
674
  }
662
- async function rateLimitedFetch(url, options = {}) {
663
- const { skipRateLimit, ...fetchOptions } = options;
664
- const cfg = TrustwareConfigStore.get();
665
- if (!cfg.retry.autoRetry || skipRateLimit) {
666
- return fetch(url, fetchOptions);
667
- }
668
- const { maxRetries, baseDelayMs } = cfg.retry;
675
+ async function withRateLimitRetry(attempt) {
676
+ let waitedMs = 0;
669
677
  let retryCount = 0;
670
678
  while (true) {
671
- const response = await fetch(url, fetchOptions);
679
+ const response = await attempt();
672
680
  const rateLimitInfo = parseRateLimitHeaders(response);
673
- if (response.status === 429) {
681
+ if (response.status !== 429) {
674
682
  if (rateLimitInfo) {
675
- notifyRateLimitCallbacks(rateLimitInfo, true, retryCount);
683
+ notifyRateLimitCallbacks(rateLimitInfo, false, 0);
676
684
  }
677
- if (retryCount >= maxRetries) {
678
- throw new RateLimitError(
679
- rateLimitInfo || { limit: 0, remaining: 0, reset: 0 },
680
- true
681
- );
682
- }
683
- const delay = calculateBackoffDelay(
684
- baseDelayMs,
685
- retryCount,
686
- rateLimitInfo?.retryAfter
687
- );
688
- await sleep(delay);
689
- retryCount++;
690
- continue;
685
+ return response;
691
686
  }
692
687
  if (rateLimitInfo) {
693
- notifyRateLimitCallbacks(rateLimitInfo, false, 0);
688
+ notifyRateLimitCallbacks(rateLimitInfo, true, retryCount);
694
689
  }
695
- return response;
690
+ const waitMs = serverDirectedWaitMs(rateLimitInfo);
691
+ const info = rateLimitInfo || { limit: 0, remaining: 0, reset: 0 };
692
+ if (waitMs === null) {
693
+ throw new RateLimitError(info, true);
694
+ }
695
+ if (waitedMs + waitMs > RATE_LIMIT_WAIT_BUDGET_MS) {
696
+ throw new RateLimitError(info, false);
697
+ }
698
+ await sleep(waitMs);
699
+ waitedMs += waitMs;
700
+ retryCount++;
696
701
  }
697
702
  }
703
+ async function rateLimitedFetch(url, options = {}) {
704
+ const { skipRateLimit, ...fetchOptions } = options;
705
+ if (skipRateLimit) {
706
+ return fetch(url, fetchOptions);
707
+ }
708
+ return withRateLimitRetry(() => fetch(url, fetchOptions));
709
+ }
698
710
  var RateLimitError;
699
711
  var init_http = __esm({
700
712
  "src/core/http.ts"() {
701
713
  "use strict";
702
714
  init_constants();
703
715
  init_config2();
716
+ init_config();
704
717
  RateLimitError = class extends Error {
705
718
  constructor(info, retriesExhausted) {
706
- const message = retriesExhausted ? `Rate limit exceeded after max retries. Try again in ${info.retryAfter ?? Math.ceil((info.reset * 1e3 - Date.now()) / 1e3)} seconds.` : `Rate limit exceeded. Try again in ${info.retryAfter} seconds.`;
719
+ const seconds = info.retryAfter ?? (info.reset > 0 ? Math.max(0, Math.ceil((info.reset * 1e3 - Date.now()) / 1e3)) : null);
720
+ const message = seconds === null ? "Rate limit exceeded. The server did not say when to retry." : `Rate limit exceeded. Try again in ${seconds} seconds.`;
707
721
  super(message);
708
722
  this.name = "RateLimitError";
709
723
  this.rateLimitInfo = info;
@@ -2288,6 +2302,16 @@ function mergeBalanceWrappers(current, incoming) {
2288
2302
  }
2289
2303
  return Array.from(merged.values());
2290
2304
  }
2305
+ function toSummary(frame, address) {
2306
+ const total = toNumberOrUndefined(frame.total) ?? 0;
2307
+ return {
2308
+ address: toStringOrUndefined(frame.address) ?? address,
2309
+ partial: Boolean(frame.partial),
2310
+ completed: toNumberOrUndefined(frame.completed) ?? 0,
2311
+ total,
2312
+ elapsedMs: toNumberOrUndefined(frame.elapsed)
2313
+ };
2314
+ }
2291
2315
  async function parseStreamingBalances(response, address, options = {}) {
2292
2316
  if (!response.body) {
2293
2317
  throw new Error("balances stream: empty response body");
@@ -2308,7 +2332,12 @@ async function parseStreamingBalances(response, address, options = {}) {
2308
2332
  if (!trimmed) continue;
2309
2333
  try {
2310
2334
  const parsed = JSON.parse(trimmed);
2311
- if (!parsed.chain_id) continue;
2335
+ if (!parsed.chain_id) {
2336
+ if (parsed.type === "summary") {
2337
+ options.onSummary?.(toSummary(parsed, address));
2338
+ }
2339
+ continue;
2340
+ }
2312
2341
  const chunk = normalizeStreamChunk(parsed);
2313
2342
  emitBalanceStreamChunk(address, chunk.length);
2314
2343
  yield chunk;
@@ -2327,6 +2356,8 @@ async function parseStreamingBalances(response, address, options = {}) {
2327
2356
  const chunk = normalizeStreamChunk(parsed);
2328
2357
  emitBalanceStreamChunk(address, chunk.length);
2329
2358
  yield chunk;
2359
+ } else if (parsed.type === "summary") {
2360
+ options.onSummary?.(toSummary(parsed, address));
2330
2361
  }
2331
2362
  } catch (error) {
2332
2363
  if (options.strict) {
@@ -2360,7 +2391,7 @@ async function getBalances(chainRef, address, opts) {
2360
2391
  if (cached) return cached;
2361
2392
  }
2362
2393
  const url = `${apiBase()}/v1/data/wallets/${encodeURIComponent(chainKey)}/${trimmedAddress}/balances`;
2363
- const response = await fetch(url, {
2394
+ const response = await rateLimitedFetch(url, {
2364
2395
  method: "GET",
2365
2396
  credentials: "omit",
2366
2397
  headers: jsonHeaders()
@@ -2381,7 +2412,7 @@ async function getBalancesByAddress(address, opts) {
2381
2412
  }
2382
2413
  return merged;
2383
2414
  }
2384
- const url = `${apiBase()}/data/balances/${address}`;
2415
+ const url = `${apiBase()}/v1/data/balances/${address}`;
2385
2416
  const r = await rateLimitedFetch(url, {
2386
2417
  method: "GET",
2387
2418
  credentials: "omit",
@@ -2389,14 +2420,27 @@ async function getBalancesByAddress(address, opts) {
2389
2420
  });
2390
2421
  if (!r.ok) throw new Error(`balances: HTTP ${r.status}`);
2391
2422
  const j = await r.json();
2392
- return Array.isArray(j) ? j : j.results ?? [];
2423
+ const results = Array.isArray(j) ? j : j.results ?? [];
2424
+ if (opts?.onSummary) {
2425
+ const completed = results.length;
2426
+ opts.onSummary({
2427
+ address,
2428
+ partial: Array.isArray(j) ? false : Boolean(j.partial),
2429
+ completed,
2430
+ total: completed
2431
+ });
2432
+ }
2433
+ return results;
2434
+ }
2435
+ function bufferedOptions(opts) {
2436
+ return { ...opts, stream: false };
2393
2437
  }
2394
2438
  async function* getBalancesByAddressStream(address, opts = {}) {
2395
2439
  if (!TrustwareConfigStore.get().features.balanceStreaming) {
2396
- yield await getBalancesByAddress(address);
2440
+ yield await getBalancesByAddress(address, bufferedOptions(opts));
2397
2441
  return;
2398
2442
  }
2399
- const url = `${apiBase()}/data/balances/${address}?stream=1`;
2443
+ const url = `${apiBase()}/v1/data/balances/${address}?stream=1`;
2400
2444
  try {
2401
2445
  const response = await rateLimitedFetch(url, {
2402
2446
  method: "GET",
@@ -2412,7 +2456,14 @@ async function* getBalancesByAddressStream(address, opts = {}) {
2412
2456
  const contentType = response.headers.get("content-type") ?? "";
2413
2457
  if (contentType.includes("application/json")) {
2414
2458
  const payload = await response.json();
2415
- yield Array.isArray(payload) ? payload : payload.results ?? [];
2459
+ const results = Array.isArray(payload) ? payload : payload.results ?? [];
2460
+ opts.onSummary?.({
2461
+ address,
2462
+ partial: Array.isArray(payload) ? false : Boolean(payload.partial),
2463
+ completed: results.length,
2464
+ total: results.length
2465
+ });
2466
+ yield results;
2416
2467
  return;
2417
2468
  }
2418
2469
  const stream = await parseStreamingBalances(response, address, opts);
@@ -2421,7 +2472,7 @@ async function* getBalancesByAddressStream(address, opts = {}) {
2421
2472
  }
2422
2473
  } catch (error) {
2423
2474
  emitBalanceStreamFallback(address, error);
2424
- yield await getBalancesByAddress(address);
2475
+ yield await getBalancesByAddress(address, bufferedOptions(opts));
2425
2476
  }
2426
2477
  }
2427
2478
  async function ensureRegistry() {
@@ -2604,7 +2655,18 @@ async function getStatus(intentId) {
2604
2655
  );
2605
2656
  await assertOK(r);
2606
2657
  const j = await r.json();
2607
- return j.data;
2658
+ return normalizeStatusPayload(j.data);
2659
+ }
2660
+ function normalizeStatusPayload(raw) {
2661
+ if (!raw || typeof raw !== "object") return raw;
2662
+ const wire = raw;
2663
+ const out = { ...wire };
2664
+ for (const [snake, camel] of Object.entries(STATUS_WIRE_TO_CAMEL)) {
2665
+ if (out[camel] !== void 0) continue;
2666
+ if (!(snake in wire)) continue;
2667
+ out[camel] = wire[snake];
2668
+ }
2669
+ return out;
2608
2670
  }
2609
2671
  async function pollStatus(intentId, { intervalMs = 2e3, timeoutMs = 5 * 6e4 } = {}) {
2610
2672
  const t0 = Date.now();
@@ -2615,12 +2677,39 @@ async function pollStatus(intentId, { intervalMs = 2e3, timeoutMs = 5 * 6e4 } =
2615
2677
  await new Promise((r) => setTimeout(r, intervalMs));
2616
2678
  }
2617
2679
  }
2680
+ var STATUS_WIRE_TO_CAMEL;
2618
2681
  var init_routes = __esm({
2619
2682
  "src/core/routes.ts"() {
2620
2683
  "use strict";
2621
2684
  init_http();
2622
2685
  init_store();
2623
2686
  init_address();
2687
+ STATUS_WIRE_TO_CAMEL = {
2688
+ intent_id: "intentId",
2689
+ from_address: "fromAddress",
2690
+ to_address: "toAddress",
2691
+ from_chain_id: "fromChainId",
2692
+ to_chain_id: "toChainId",
2693
+ source_tx_hash: "sourceTxHash",
2694
+ dest_tx_hash: "destTxHash",
2695
+ request_id: "requestId",
2696
+ provider_request_id: "providerRequestId",
2697
+ transaction_request: "transactionRequest",
2698
+ status_raw: "statusRaw",
2699
+ route_path: "routePath",
2700
+ route_status: "routeStatus",
2701
+ to_amount_wei: "toAmountWei",
2702
+ from_chain_block: "fromChainBlock",
2703
+ to_chain_block: "toChainBlock",
2704
+ from_chain_tx_url: "fromChainTxUrl",
2705
+ to_chain_tx_url: "toChainTxUrl",
2706
+ gas_status: "gasStatus",
2707
+ is_gmp_transaction: "isGMPTransaction",
2708
+ axelar_transaction_url: "axelarTransactionUrl",
2709
+ create_date: "createdDate",
2710
+ update_date: "updatedDate",
2711
+ time_spent_ms: "timeSpentMs"
2712
+ };
2624
2713
  }
2625
2714
  });
2626
2715
 
@@ -2911,21 +3000,10 @@ function useTrustwareConfig() {
2911
3000
  title: "Trustware SDK",
2912
3001
  description: "Seamlessly bridge assets across chains with Trustware."
2913
3002
  },
2914
- retry: {
2915
- autoRetry: true,
2916
- maxRetries: 3,
2917
- baseDelayMs: 1e3,
2918
- approachingThreshold: 5
2919
- },
2920
- features: {
2921
- tokensPagination: true,
2922
- balanceStreaming: false,
2923
- shouldAllowGA4: true,
2924
- swapMode: false,
2925
- swapDefaultDestToken: null,
2926
- swapLockDestToken: false,
2927
- swapAllowedDestTokens: null
2928
- }
3003
+ // Shared with the resolver rather than restated, so this placeholder
3004
+ // can't drift from the real defaults.
3005
+ retry: { ...DEFAULT_RETRY_CONFIG },
3006
+ features: { ...DEFAULT_FEATURE_FLAGS }
2929
3007
  };
2930
3008
  }
2931
3009
  });
@@ -2941,6 +3019,7 @@ var init_useTrustwareConfig = __esm({
2941
3019
  "src/hooks/useTrustwareConfig.ts"() {
2942
3020
  "use strict";
2943
3021
  "use client";
3022
+ init_config();
2944
3023
  init_store();
2945
3024
  }
2946
3025
  });
@@ -8929,9 +9008,6 @@ function resolveConfig(input) {
8929
9008
  const theme = input.theme ?? "system";
8930
9009
  const messages = deepMerge(DEFAULT_MESSAGES, input.messages);
8931
9010
  const retry = {
8932
- autoRetry: input.retry?.autoRetry ?? DEFAULT_RETRY_CONFIG.autoRetry,
8933
- maxRetries: input.retry?.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries,
8934
- baseDelayMs: input.retry?.baseDelayMs ?? DEFAULT_RETRY_CONFIG.baseDelayMs,
8935
9011
  approachingThreshold: input.retry?.approachingThreshold ?? DEFAULT_RETRY_CONFIG.approachingThreshold,
8936
9012
  onRateLimitInfo: input.retry?.onRateLimitInfo,
8937
9013
  onRateLimited: input.retry?.onRateLimited,
@@ -20362,7 +20438,7 @@ var VERSION;
20362
20438
  var init_version = __esm({
20363
20439
  "node_modules/@aa-sdk/core/dist/esm/version.js"() {
20364
20440
  "use strict";
20365
- VERSION = "4.88.4";
20441
+ VERSION = "4.88.5";
20366
20442
  }
20367
20443
  });
20368
20444
 
@@ -28871,7 +28947,7 @@ var VERSION2;
28871
28947
  var init_version2 = __esm({
28872
28948
  "node_modules/@account-kit/infra/dist/esm/version.js"() {
28873
28949
  "use strict";
28874
- VERSION2 = "4.88.4";
28950
+ VERSION2 = "4.88.5";
28875
28951
  }
28876
28952
  });
28877
28953
 
@@ -30607,7 +30683,7 @@ import {
30607
30683
  keccak256 as keccak2566,
30608
30684
  stringToHex
30609
30685
  } from "viem";
30610
- async function fetchWithTimeout(url, init) {
30686
+ async function fetchOnceWithTimeout(url, init) {
30611
30687
  const controller = new AbortController();
30612
30688
  const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
30613
30689
  try {
@@ -30628,6 +30704,9 @@ async function fetchWithTimeout(url, init) {
30628
30704
  clearTimeout(timer);
30629
30705
  }
30630
30706
  }
30707
+ async function fetchWithTimeout(url, init) {
30708
+ return withRateLimitRetry(() => fetchOnceWithTimeout(url, init));
30709
+ }
30631
30710
  function extractRevertHex(err) {
30632
30711
  if (typeof err.data === "string" && err.data.startsWith("0x"))
30633
30712
  return err.data;
@@ -31127,7 +31206,7 @@ async function estimateRelayFeeInToken(valueWei, fromAmountWei, fromAmountUSD, c
31127
31206
  tokenUnitsPerDollar = Number(fromAmountWei) / fromUSD;
31128
31207
  } else if (fromToken && fromDecimals !== void 0) {
31129
31208
  try {
31130
- const resp = await fetch(
31209
+ const resp = await rateLimitedFetch(
31131
31210
  `${apiBase()}/v1/price/token?chainId=${cid}&address=${fromToken}`,
31132
31211
  { headers: jsonHeaders() }
31133
31212
  );
@@ -31143,9 +31222,10 @@ async function estimateRelayFeeInToken(valueWei, fromAmountWei, fromAmountUSD, c
31143
31222
  return 0n;
31144
31223
  }
31145
31224
  try {
31146
- const resp = await fetch(`${apiBase()}/v1/price/native?chainId=${cid}`, {
31147
- headers: jsonHeaders()
31148
- });
31225
+ const resp = await rateLimitedFetch(
31226
+ `${apiBase()}/v1/price/native?chainId=${cid}`,
31227
+ { headers: jsonHeaders() }
31228
+ );
31149
31229
  if (!resp.ok) throw new Error(`native price HTTP ${resp.status}`);
31150
31230
  const json = await resp.json();
31151
31231
  const ethPriceUSD = parseFloat(json.data?.priceUSD ?? "0");
@@ -33885,9 +33965,14 @@ var init_useSwapExecution = __esm({
33885
33965
 
33886
33966
  // src/core/forex.ts
33887
33967
  async function fetchForexRates(base2 = "USD") {
33888
- const r = await fetch(`${apiBase()}/v1/forex?base=${base2}`, {
33889
- headers: jsonHeaders()
33890
- });
33968
+ let r;
33969
+ try {
33970
+ r = await rateLimitedFetch(`${apiBase()}/v1/forex?base=${base2}`, {
33971
+ headers: jsonHeaders()
33972
+ });
33973
+ } catch {
33974
+ return {};
33975
+ }
33891
33976
  if (!r.ok) return {};
33892
33977
  const j = await r.json();
33893
33978
  const rates = j?.data?.rates ?? j?.rates ?? j?.data ?? {};