@trustware/sdk-staging 1.1.9-staging.6 → 1.1.10-staging.0

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 (40) hide show
  1. package/LICENSE +5 -4
  2. package/README.md +32 -1
  3. package/THIRD_PARTY_NOTICES.md +118 -0
  4. package/dist/constants.cjs +1 -1
  5. package/dist/constants.mjs +1 -1
  6. package/dist/{core-BTPkApRH.d.cts → core-B7Ez-5-r.d.cts} +3 -2
  7. package/dist/{core-2oZuxC1J.d.ts → core-BPLiD1UG.d.ts} +3 -2
  8. package/dist/core.cjs +246 -48
  9. package/dist/core.cjs.map +1 -1
  10. package/dist/core.d.cts +2 -2
  11. package/dist/core.d.ts +2 -2
  12. package/dist/core.mjs +247 -48
  13. package/dist/core.mjs.map +1 -1
  14. package/dist/index.cjs +300 -76
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +5 -5
  17. package/dist/index.d.ts +5 -5
  18. package/dist/index.mjs +325 -103
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/{manager-BMO1O-cW.d.ts → manager-B6NNV-E_.d.ts} +129 -18
  21. package/dist/{manager-BZwbtOyf.d.cts → manager-BwjyFjjz.d.cts} +129 -18
  22. package/dist/{detect-B8xXLwHK.d.ts → metadata-BiTMMvlY.d.ts} +5 -2
  23. package/dist/{detect-C8xpZRrL.d.cts → metadata-HCflXcsF.d.cts} +5 -2
  24. package/dist/smart-account.cjs +117 -39
  25. package/dist/smart-account.cjs.map +1 -1
  26. package/dist/smart-account.d.cts +235 -222
  27. package/dist/smart-account.d.ts +235 -222
  28. package/dist/smart-account.mjs +117 -39
  29. package/dist/smart-account.mjs.map +1 -1
  30. package/dist/wallet.cjs +113 -36
  31. package/dist/wallet.cjs.map +1 -1
  32. package/dist/wallet.d.cts +4 -7
  33. package/dist/wallet.d.ts +4 -7
  34. package/dist/wallet.mjs +113 -36
  35. package/dist/wallet.mjs.map +1 -1
  36. package/dist/widget.cjs +239 -54
  37. package/dist/widget.cjs.map +1 -1
  38. package/dist/widget.mjs +267 -81
  39. package/dist/widget.mjs.map +1 -1
  40. package/package.json +3 -2
package/dist/widget.cjs CHANGED
@@ -585,7 +585,7 @@ var init_constants = __esm({
585
585
  "src/constants.ts"() {
586
586
  "use strict";
587
587
  SDK_NAME = "@trustware/sdk";
588
- SDK_VERSION = "1.1.9-staging.6";
588
+ SDK_VERSION = "1.1.10-staging.0";
589
589
  API_ROOT = "https://bv-staging-api.trustware.io";
590
590
  GTM_ID = "GTM-TZDGNCXB";
591
591
  API_PREFIX = "/api";
@@ -796,7 +796,9 @@ var init_chains = __esm({
796
796
  btc: "bitcoin",
797
797
  bitcoin: "bitcoin",
798
798
  sei: "cosmos",
799
- "pacific-1": "cosmos"
799
+ "pacific-1": "cosmos",
800
+ nibiru: "cosmos",
801
+ "cataclysm-1": "cosmos"
800
802
  };
801
803
  }
802
804
  });
@@ -1992,16 +1994,23 @@ function validateEvmAddress(address) {
1992
1994
  }
1993
1995
  return { isValid: true };
1994
1996
  }
1995
- function validateSeiAddress(address) {
1997
+ function resolveCosmosBech32Prefix(chain) {
1998
+ const chainDef = typeof chain === "object" && chain ? chain : void 0;
1999
+ const identifier = chainDef?.networkIdentifier ?? chainDef?.chainId ?? chainDef?.id ?? (typeof chain === "string" ? chain : void 0);
2000
+ const normalized = String(identifier ?? "").trim().toLowerCase();
2001
+ return COSMOS_BECH32_PREFIX_BY_CHAIN_ID[normalized] ?? "sei";
2002
+ }
2003
+ function validateCosmosAddress(address, chain) {
1996
2004
  const trimmed = address.trim();
1997
- if ((0, import_viem.isAddress)(trimmed)) {
2005
+ const prefix = resolveCosmosBech32Prefix(chain);
2006
+ if (prefix === "sei" && (0, import_viem.isAddress)(trimmed)) {
1998
2007
  return { isValid: true };
1999
2008
  }
2000
- const result = validateBech32LikeAddress(trimmed, "sei");
2009
+ const result = validateBech32LikeAddress(trimmed, prefix);
2001
2010
  if (result.isValid) return result;
2002
2011
  return {
2003
2012
  isValid: false,
2004
- error: "SEI addresses must be 0x-prefixed EVM or sei1 bech32 strings."
2013
+ error: prefix === "sei" ? "SEI addresses must be 0x-prefixed EVM or sei1 bech32 strings." : `Address must be a valid ${prefix}1 bech32 string.`
2005
2014
  };
2006
2015
  }
2007
2016
  function validateSolanaAddress(address) {
@@ -2051,15 +2060,12 @@ function validateAddressForChain(address, chain) {
2051
2060
  case "bitcoin":
2052
2061
  return validateBtcAddress(trimmed);
2053
2062
  case "cosmos":
2054
- if (chainDef?.networkIdentifier?.toLowerCase() === "sei") {
2055
- return validateSeiAddress(trimmed);
2056
- }
2057
- return validateBech32LikeAddress(trimmed, "sei");
2063
+ return validateCosmosAddress(trimmed, chainDef ?? chain);
2058
2064
  default:
2059
2065
  return { isValid: false, error: "Unsupported or unknown chain type." };
2060
2066
  }
2061
2067
  }
2062
- function validateAddressForRouteChain(address, chainType) {
2068
+ function validateAddressForRouteChain(address, chainType, chainRef) {
2063
2069
  switch (normalizeChainType(chainType)) {
2064
2070
  case "evm":
2065
2071
  return validateEvmAddress(address);
@@ -2068,7 +2074,7 @@ function validateAddressForRouteChain(address, chainType) {
2068
2074
  case "bitcoin":
2069
2075
  return validateBtcAddress(address);
2070
2076
  case "cosmos":
2071
- return validateSeiAddress(address);
2077
+ return validateCosmosAddress(address, chainRef ?? chainType);
2072
2078
  default:
2073
2079
  return { isValid: false, error: "Unsupported chain type." };
2074
2080
  }
@@ -2090,14 +2096,18 @@ function validateRouteAddresses(params) {
2090
2096
  const normalizedDirection = params.direction?.trim().toLowerCase();
2091
2097
  const isDepositFlow = normalizedDirection === "deposit" || (toType === "evm" || toType === "cosmos") && (fromType === "bitcoin" || fromType === "solana");
2092
2098
  if (isDepositFlow) {
2093
- const fromResult2 = validateAddressForRouteChain(fromAddress, fromType);
2099
+ const fromResult2 = validateAddressForRouteChain(
2100
+ fromAddress,
2101
+ fromType,
2102
+ params.fromChain
2103
+ );
2094
2104
  if (!fromResult2.isValid) {
2095
2105
  return {
2096
2106
  isValid: false,
2097
2107
  error: `From address: ${fromResult2.error ?? "Invalid address."}`
2098
2108
  };
2099
2109
  }
2100
- const toResult2 = toType === "cosmos" ? validateSeiAddress(toAddress) : validateEvmAddress(toAddress);
2110
+ const toResult2 = toType === "cosmos" ? validateCosmosAddress(toAddress, params.toChain) : validateEvmAddress(toAddress);
2101
2111
  if (!toResult2.isValid) {
2102
2112
  return {
2103
2113
  isValid: false,
@@ -2122,14 +2132,22 @@ function validateRouteAddresses(params) {
2122
2132
  }
2123
2133
  return { isValid: true };
2124
2134
  }
2125
- const fromResult = validateAddressForRouteChain(fromAddress, fromType);
2135
+ const fromResult = validateAddressForRouteChain(
2136
+ fromAddress,
2137
+ fromType,
2138
+ params.fromChain
2139
+ );
2126
2140
  if (!fromResult.isValid) {
2127
2141
  return {
2128
2142
  isValid: false,
2129
2143
  error: `From address: ${fromResult.error ?? "Invalid address."}`
2130
2144
  };
2131
2145
  }
2132
- const toResult = validateAddressForRouteChain(toAddress, toType);
2146
+ const toResult = validateAddressForRouteChain(
2147
+ toAddress,
2148
+ toType,
2149
+ params.toChain
2150
+ );
2133
2151
  if (!toResult.isValid) {
2134
2152
  return {
2135
2153
  isValid: false,
@@ -2138,7 +2156,7 @@ function validateRouteAddresses(params) {
2138
2156
  }
2139
2157
  return { isValid: true };
2140
2158
  }
2141
- var import_viem, BECH32_CHARSET;
2159
+ var import_viem, BECH32_CHARSET, COSMOS_BECH32_PREFIX_BY_CHAIN_ID;
2142
2160
  var init_address = __esm({
2143
2161
  "src/validation/address.ts"() {
2144
2162
  "use strict";
@@ -2146,6 +2164,12 @@ var init_address = __esm({
2146
2164
  init_index_node4();
2147
2165
  init_chains();
2148
2166
  BECH32_CHARSET = /^[023456789acdefghjklmnpqrstuvwxyz]+$/i;
2167
+ COSMOS_BECH32_PREFIX_BY_CHAIN_ID = {
2168
+ "pacific-1": "sei",
2169
+ sei: "sei",
2170
+ "cataclysm-1": "nibi",
2171
+ nibiru: "nibi"
2172
+ };
2149
2173
  }
2150
2174
  });
2151
2175
 
@@ -2440,6 +2464,27 @@ var init_balances = __esm({
2440
2464
  });
2441
2465
 
2442
2466
  // src/core/routes.ts
2467
+ function assertValidPostHook(hooks) {
2468
+ const postHook = hooks?.postHook;
2469
+ if (!postHook) return;
2470
+ if (!postHook.target?.trim()) {
2471
+ throw new Error("hooks.postHook.target is required.");
2472
+ }
2473
+ if (!postHook.callData?.trim()) {
2474
+ throw new Error("hooks.postHook.callData is required.");
2475
+ }
2476
+ if (postHook.fullAmount) {
2477
+ if (postHook.amountInputPos === void 0) {
2478
+ throw new Error(
2479
+ "hooks.postHook.amountInputPos is required when fullAmount is true."
2480
+ );
2481
+ }
2482
+ } else if (!postHook.fundAmount?.trim()) {
2483
+ throw new Error(
2484
+ "hooks.postHook.fundAmount is required unless fullAmount is set."
2485
+ );
2486
+ }
2487
+ }
2443
2488
  function isEvmTxRequest(txReq) {
2444
2489
  return Boolean(txReq?.data && (txReq.to || txReq.target));
2445
2490
  }
@@ -2458,6 +2503,7 @@ async function buildRoute(body, signal) {
2458
2503
  if (!addressValidation.isValid) {
2459
2504
  throw new Error(addressValidation.error || "Invalid route addresses.");
2460
2505
  }
2506
+ assertValidPostHook(body.hooks);
2461
2507
  const cfg = TrustwareConfigStore.get();
2462
2508
  const url = `${apiBase()}/v1/routes/route`;
2463
2509
  const payload = {
@@ -2496,6 +2542,7 @@ async function buildRoute(body, signal) {
2496
2542
  return { intentId, txReq, actions, finalExchangeRate, route, sponsorship };
2497
2543
  }
2498
2544
  async function buildDepositAddress(body, signal) {
2545
+ assertValidPostHook(body.hooks);
2499
2546
  const cfg = TrustwareConfigStore.get();
2500
2547
  const url = `${apiBase()}/v1/routes/deposit-address`;
2501
2548
  const payload = {
@@ -2537,7 +2584,7 @@ async function buildDepositAddress(body, signal) {
2537
2584
  route
2538
2585
  };
2539
2586
  }
2540
- async function submitReceipt(intentId, txHash, sponsorshipRequestId) {
2587
+ async function submitReceipt(intentId, txHash, sponsorshipRequestId, eoaAddress) {
2541
2588
  const r = await rateLimitedFetch(
2542
2589
  `${apiBase()}/v1/route-intent/${intentId}/receipt`,
2543
2590
  {
@@ -2545,7 +2592,8 @@ async function submitReceipt(intentId, txHash, sponsorshipRequestId) {
2545
2592
  headers: jsonHeaders({ "Idempotency-Key": txHash }),
2546
2593
  body: JSON.stringify({
2547
2594
  txHash,
2548
- ...sponsorshipRequestId ? { sponsorshipRequestId } : {}
2595
+ ...sponsorshipRequestId ? { sponsorshipRequestId } : {},
2596
+ ...eoaAddress ? { eoaAddress } : {}
2549
2597
  })
2550
2598
  }
2551
2599
  );
@@ -2855,6 +2903,7 @@ function useTrustwareConfig() {
2855
2903
  } catch {
2856
2904
  return {
2857
2905
  apiKey: "",
2906
+ mode: "deposit",
2858
2907
  routes: {
2859
2908
  toChain: "",
2860
2909
  toToken: "",
@@ -3120,7 +3169,9 @@ var init_chainHelpers = __esm({
3120
3169
  btc: "bitcoin",
3121
3170
  bitcoin: "bitcoin",
3122
3171
  sei: "cosmos",
3123
- "pacific-1": "cosmos"
3172
+ "pacific-1": "cosmos",
3173
+ nibiru: "cosmos",
3174
+ "cataclysm-1": "cosmos"
3124
3175
  };
3125
3176
  SEI_EVM_CHAIN_ID = "1329";
3126
3177
  SEI_COSMOS_CHAIN_ID = "pacific-1";
@@ -3335,7 +3386,8 @@ function filterSupportedChains(chains) {
3335
3386
  }
3336
3387
  if (chainType === "cosmos") {
3337
3388
  const seiKey = canonicalSeiChainKey(chain.chainId ?? chain.id);
3338
- if (seiKey !== "sei" && seiKey !== "pacific-1") {
3389
+ const isNibiru = normalizeChainKey2(chain.chainId ?? chain.id) === NIBIRU_COSMOS_CHAIN_ID;
3390
+ if (seiKey !== "sei" && !isNibiru) {
3339
3391
  return false;
3340
3392
  }
3341
3393
  }
@@ -3435,7 +3487,7 @@ function useChains() {
3435
3487
  error
3436
3488
  };
3437
3489
  }
3438
- var import_react4, POPULAR_CHAINS_BY_TVL, POPULAR_LIMIT;
3490
+ var import_react4, POPULAR_CHAINS_BY_TVL, POPULAR_LIMIT, NIBIRU_COSMOS_CHAIN_ID;
3439
3491
  var init_useChains = __esm({
3440
3492
  "src/core/useChains.ts"() {
3441
3493
  "use strict";
@@ -3446,6 +3498,7 @@ var init_useChains = __esm({
3446
3498
  init_popularChains();
3447
3499
  POPULAR_CHAINS_BY_TVL = popularChains_default.byTvl;
3448
3500
  POPULAR_LIMIT = popularChains_default.popularLimit;
3501
+ NIBIRU_COSMOS_CHAIN_ID = "cataclysm-1";
3449
3502
  }
3450
3503
  });
3451
3504
 
@@ -8783,46 +8836,80 @@ function normalizeSlippage(v) {
8783
8836
  if (n > 5) return 5;
8784
8837
  return n;
8785
8838
  }
8839
+ function warnDeprecatedSwapModeFlag() {
8840
+ if (hasWarnedDeprecatedSwapModeFlag) return;
8841
+ hasWarnedDeprecatedSwapModeFlag = true;
8842
+ console.warn(
8843
+ '[Trustware SDK] `features.swapMode` is deprecated \u2014 use `mode: "swap"` on the top-level config instead.'
8844
+ );
8845
+ }
8846
+ function resolveMode(input) {
8847
+ if (input.mode === "swap") return "swap";
8848
+ if (input.mode === "deposit") return "deposit";
8849
+ if (input.features?.swapMode) {
8850
+ warnDeprecatedSwapModeFlag();
8851
+ return "swap";
8852
+ }
8853
+ return "deposit";
8854
+ }
8786
8855
  function resolveConfig(input) {
8787
8856
  if (!input?.apiKey) {
8788
- throw new Error("TrustwareConfig: 'apiKey' is required.");
8857
+ throw new TrustwareError({
8858
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
8859
+ message: "TrustwareConfig: 'apiKey' is required.",
8860
+ userMessage: "Missing required API key configuration."
8861
+ });
8789
8862
  }
8790
- if (!input.routes?.toChain || !input.routes?.toToken) {
8791
- throw new Error(
8792
- "TrustwareConfig: 'routes.toChain' and 'routes.toToken' are required."
8793
- );
8863
+ const mode = resolveMode(input);
8864
+ if (mode === "deposit" && (!input.routes?.toChain || !input.routes?.toToken)) {
8865
+ throw new TrustwareError({
8866
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
8867
+ message: "TrustwareConfig: 'routes.toChain' and 'routes.toToken' are required in deposit mode.",
8868
+ userMessage: "Missing required destination chain/token configuration."
8869
+ });
8794
8870
  }
8795
- const toChain = input.routes.toChain;
8796
- if (input.routes.toAddress) {
8871
+ const toChain = input.routes?.toChain;
8872
+ if (input.routes?.toAddress && toChain) {
8797
8873
  const result = validateAddressForChain(input.routes.toAddress, toChain);
8798
8874
  if (!result.isValid) {
8799
8875
  console.error(`[Trustware SDK] Invalid toAddress: ${result.error}`);
8800
- throw new Error(`Invalid toAddress: ${result.error}`);
8876
+ throw new TrustwareError({
8877
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
8878
+ message: `Invalid toAddress: ${result.error}`,
8879
+ userMessage: "The configured destination address is invalid."
8880
+ });
8801
8881
  }
8802
8882
  }
8803
- if (input.routes.fromAddress) {
8804
- const result = validateAddressForChain(
8805
- input.routes.fromAddress,
8806
- input.routes.fromChain ?? toChain
8807
- );
8808
- if (!result.isValid) {
8809
- console.error(`[Trustware SDK] Invalid fromAddress: ${result.error}`);
8810
- throw new Error(`Invalid fromAddress: ${result.error}`);
8883
+ if (input.routes?.fromAddress) {
8884
+ const fromChain = input.routes.fromChain ?? toChain;
8885
+ if (fromChain) {
8886
+ const result = validateAddressForChain(
8887
+ input.routes.fromAddress,
8888
+ fromChain
8889
+ );
8890
+ if (!result.isValid) {
8891
+ console.error(`[Trustware SDK] Invalid fromAddress: ${result.error}`);
8892
+ throw new TrustwareError({
8893
+ code: "INVALID_CONFIG" /* INVALID_CONFIG */,
8894
+ message: `Invalid fromAddress: ${result.error}`,
8895
+ userMessage: "The configured source address is invalid."
8896
+ });
8897
+ }
8811
8898
  }
8812
8899
  }
8813
8900
  const autoDetectProvider = typeof input.autoDetectProvider === "boolean" ? input.autoDetectProvider : DEFAULT_AUTO_DETECT_PROVIDER;
8814
8901
  const routes = {
8815
- toChain: input.routes.toChain,
8816
- toToken: input.routes.toToken,
8817
- fromToken: input.routes.fromToken,
8818
- fromAddress: input.routes.fromAddress,
8819
- fromChain: input.routes.fromChain,
8820
- toAddress: input.routes.toAddress,
8902
+ toChain: input.routes?.toChain ?? "",
8903
+ toToken: input.routes?.toToken ?? "",
8904
+ fromToken: input.routes?.fromToken,
8905
+ fromAddress: input.routes?.fromAddress,
8906
+ fromChain: input.routes?.fromChain,
8907
+ toAddress: input.routes?.toAddress,
8821
8908
  defaultSlippage: normalizeSlippage(
8822
- input.routes.defaultSlippage ?? DEFAULT_SLIPPAGE
8909
+ input.routes?.defaultSlippage ?? DEFAULT_SLIPPAGE
8823
8910
  ),
8824
8911
  options: {
8825
- ...input.routes.options
8912
+ ...input.routes?.options
8826
8913
  }
8827
8914
  };
8828
8915
  const theme = input.theme ?? "system";
@@ -8841,13 +8928,16 @@ function resolveConfig(input) {
8841
8928
  tokensPagination: input.features?.tokensPagination ?? DEFAULT_FEATURE_FLAGS.tokensPagination,
8842
8929
  balanceStreaming: input.features?.balanceStreaming ?? DEFAULT_FEATURE_FLAGS.balanceStreaming,
8843
8930
  shouldAllowGA4: input.features?.shouldAllowGA4 ?? DEFAULT_FEATURE_FLAGS.shouldAllowGA4,
8844
- swapMode: input.features?.swapMode ?? DEFAULT_FEATURE_FLAGS.swapMode,
8931
+ // Always mirrors the canonical `mode`, however the caller set it (new `mode` field
8932
+ // or the deprecated `features.swapMode` flag).
8933
+ swapMode: mode === "swap",
8845
8934
  swapDefaultDestToken: input.features?.swapDefaultDestToken ?? DEFAULT_FEATURE_FLAGS.swapDefaultDestToken,
8846
8935
  swapLockDestToken: input.features?.swapLockDestToken ?? DEFAULT_FEATURE_FLAGS.swapLockDestToken,
8847
8936
  swapAllowedDestTokens: input.features?.swapAllowedDestTokens ?? DEFAULT_FEATURE_FLAGS.swapAllowedDestTokens
8848
8937
  };
8849
8938
  return {
8850
8939
  apiKey: input.apiKey,
8940
+ mode,
8851
8941
  routes,
8852
8942
  autoDetectProvider,
8853
8943
  theme,
@@ -8860,12 +8950,15 @@ function resolveConfig(input) {
8860
8950
  onEvent: input.onEvent
8861
8951
  };
8862
8952
  }
8953
+ var hasWarnedDeprecatedSwapModeFlag;
8863
8954
  var init_merge = __esm({
8864
8955
  "src/config/merge.ts"() {
8865
8956
  "use strict";
8866
8957
  init_defaults();
8867
8958
  init_config();
8868
8959
  init_index();
8960
+ init_TrustwareError();
8961
+ hasWarnedDeprecatedSwapModeFlag = false;
8869
8962
  }
8870
8963
  });
8871
8964
 
@@ -8954,6 +9047,87 @@ function backendChainId(chain, fallback) {
8954
9047
  const preferred = chain?.networkIdentifier ?? chain?.chainId ?? chain?.id;
8955
9048
  return String(preferred ?? fallback ?? "");
8956
9049
  }
9050
+ function sleep2(ms) {
9051
+ return new Promise((resolve) => setTimeout(resolve, ms));
9052
+ }
9053
+ async function sendEvmTx(w, tx) {
9054
+ if (w.type === "eip1193") {
9055
+ const from = await w.getAddress();
9056
+ const params = {
9057
+ from,
9058
+ to: tx.to,
9059
+ data: tx.data,
9060
+ value: tx.value ? `0x${tx.value.toString(16)}` : "0x0"
9061
+ };
9062
+ if (tx.chainId !== void 0) {
9063
+ params.chainId = `0x${tx.chainId.toString(16)}`;
9064
+ }
9065
+ const hash = await w.request({
9066
+ method: "eth_sendTransaction",
9067
+ params: [params]
9068
+ });
9069
+ return hash;
9070
+ }
9071
+ const response = await w.sendTransaction({
9072
+ to: tx.to,
9073
+ data: tx.data,
9074
+ value: tx.value,
9075
+ chainId: tx.chainId
9076
+ });
9077
+ return response.hash;
9078
+ }
9079
+ async function waitForTxConfirmation(chainId, txHash) {
9080
+ const timeoutMs = 12e4;
9081
+ const intervalMs = 2e3;
9082
+ const started = Date.now();
9083
+ while (Date.now() - started < timeoutMs) {
9084
+ const status = await getEVMTxStatus({ chainId, txHash });
9085
+ if (status.status === "success") return;
9086
+ if (status.status === "reverted") {
9087
+ throw new Error("Approval transaction reverted");
9088
+ }
9089
+ await sleep2(intervalMs);
9090
+ }
9091
+ throw new Error("Timed out waiting for approval confirmation");
9092
+ }
9093
+ async function ensureApprovals(w, approvals, fallbackChainId) {
9094
+ if (!approvals || approvals.length === 0) return;
9095
+ const owner = await w.getAddress();
9096
+ for (const approval of approvals) {
9097
+ const spender = approval.spender;
9098
+ const tokenAddress = approval.tokenAddress;
9099
+ const amount = approval.amount;
9100
+ if (!spender || !tokenAddress || !amount) continue;
9101
+ const chainId = approval.chainId || String(fallbackChainId ?? "");
9102
+ if (!chainId) continue;
9103
+ const amountWei = BigInt(amount);
9104
+ if (amountWei === 0n) continue;
9105
+ let currentAllowance = 0n;
9106
+ try {
9107
+ const { allowance } = await getEVMAllowance({
9108
+ chainId,
9109
+ tokenAddress,
9110
+ ownerAddress: owner,
9111
+ spenderAddress: spender
9112
+ });
9113
+ currentAllowance = BigInt(allowance || "0");
9114
+ } catch {
9115
+ }
9116
+ if (currentAllowance >= amountWei) continue;
9117
+ const data = (0, import_viem2.encodeFunctionData)({
9118
+ abi: erc20ApproveAbi,
9119
+ functionName: "approve",
9120
+ args: [spender, amountWei]
9121
+ });
9122
+ const hash = await sendEvmTx(w, {
9123
+ to: tokenAddress,
9124
+ data,
9125
+ value: 0n,
9126
+ chainId: Number.isFinite(Number(chainId)) ? Number(chainId) : void 0
9127
+ });
9128
+ await waitForTxConfirmation(chainId, hash);
9129
+ }
9130
+ }
8957
9131
  function isUserRejected(e2) {
8958
9132
  const code = e2?.code ?? e2?.data?.code;
8959
9133
  if (code === 4001) return true;
@@ -8987,6 +9161,13 @@ async function sendRouteTransaction(b, fallbackChainId) {
8987
9161
  }
8988
9162
  }
8989
9163
  }
9164
+ if (!validatedSponsorship) {
9165
+ await ensureApprovals(
9166
+ w,
9167
+ b.route?.execution?.approvals,
9168
+ Number.isFinite(target) ? target : void 0
9169
+ );
9170
+ }
8990
9171
  if (w.type === "eip1193") {
8991
9172
  const from = await w.getAddress();
8992
9173
  const hexValue = value ? `0x${value.toString(16)}` : "0x0";
@@ -9083,13 +9264,17 @@ async function runTopUp(params) {
9083
9264
  }
9084
9265
  }
9085
9266
  }
9086
- var import_viem2;
9267
+ var import_viem2, erc20ApproveAbi;
9087
9268
  var init_tx = __esm({
9088
9269
  "src/core/tx.ts"() {
9089
9270
  "use strict";
9090
9271
  init_wallets();
9091
9272
  init_routes();
9273
+ init_sdkRpc();
9092
9274
  import_viem2 = require("viem");
9275
+ erc20ApproveAbi = (0, import_viem2.parseAbi)([
9276
+ "function approve(address spender, uint256 amount) returns (bool)"
9277
+ ]);
9093
9278
  }
9094
9279
  });
9095
9280
 
@@ -31396,7 +31581,7 @@ async function sendRouteAsUserOperation(params) {
31396
31581
  );
31397
31582
  }
31398
31583
  console.debug("[send] UserOp included", { userOpHash, txHash });
31399
- await submitReceipt(intentId, txHash, getSponsorshipRequestId());
31584
+ await submitReceipt(intentId, txHash, getSponsorshipRequestId(), eoaAddress);
31400
31585
  return { userOpHash, txHash, intentId };
31401
31586
  }
31402
31587
  var NATIVE_ADDRS;
@@ -31447,7 +31632,7 @@ function normalizeTokenAddressForCompare(chain, addr) {
31447
31632
  if (chainType === "solana") return value;
31448
31633
  return value.toLowerCase();
31449
31634
  }
31450
- function sleep2(ms) {
31635
+ function sleep3(ms) {
31451
31636
  return new Promise((resolve) => setTimeout(resolve, ms));
31452
31637
  }
31453
31638
  function useTransactionActionModel({
@@ -31565,7 +31750,7 @@ function useTransactionActionModel({
31565
31750
  if (status.status === "reverted") {
31566
31751
  throw new Error("Approval transaction reverted");
31567
31752
  }
31568
- await sleep2(intervalMs);
31753
+ await sleep3(intervalMs);
31569
31754
  }
31570
31755
  throw new Error("Timed out waiting for approval confirmation");
31571
31756
  },
@@ -33230,7 +33415,7 @@ function normalizeTx(raw) {
33230
33415
  toChainTxUrl: r.toChainTxUrl || r.to_chain_tx_url || void 0
33231
33416
  };
33232
33417
  }
33233
- function sleep3(ms) {
33418
+ function sleep4(ms) {
33234
33419
  return new Promise((resolve) => setTimeout(resolve, ms));
33235
33420
  }
33236
33421
  function isUserRejection(err) {
@@ -33248,7 +33433,7 @@ async function waitForApprovalConfirmation(chainId, txHash) {
33248
33433
  if (status.status === "success") return;
33249
33434
  if (status.status === "reverted")
33250
33435
  throw new Error("Approval transaction reverted");
33251
- await sleep3(2e3);
33436
+ await sleep4(2e3);
33252
33437
  }
33253
33438
  throw new Error("Timed out waiting for approval confirmation");
33254
33439
  }
@@ -39676,7 +39861,7 @@ var init_TrustwareWidgetV2 = __esm({
39676
39861
  if (!isOpen) {
39677
39862
  return null;
39678
39863
  }
39679
- if (config.features.swapMode) {
39864
+ if (config.mode === "swap") {
39680
39865
  return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(SwapMode, { theme, style });
39681
39866
  }
39682
39867
  return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(DepositProvider, { initialStep: effectiveInitialStep, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(