@trustware/sdk-staging 1.1.17-staging.7 → 1.1.18-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.
package/dist/wallet.cjs CHANGED
@@ -305,7 +305,7 @@ var init_constants = __esm({
305
305
  "src/constants.ts"() {
306
306
  "use strict";
307
307
  SDK_NAME = "@trustware/sdk";
308
- SDK_VERSION = "1.1.17-staging.7";
308
+ SDK_VERSION = "1.1.18-staging.1";
309
309
  API_ROOT = "https://bv-staging-api.trustware.io";
310
310
  API_PREFIX = "/api";
311
311
  WALLETCONNECT_PROJECT_ID = "72ea74c400f5111d43aea638d7d83a24";
package/dist/wallet.mjs CHANGED
@@ -279,7 +279,7 @@ var init_constants = __esm({
279
279
  "src/constants.ts"() {
280
280
  "use strict";
281
281
  SDK_NAME = "@trustware/sdk";
282
- SDK_VERSION = "1.1.17-staging.7";
282
+ SDK_VERSION = "1.1.18-staging.1";
283
283
  API_ROOT = "https://bv-staging-api.trustware.io";
284
284
  API_PREFIX = "/api";
285
285
  WALLETCONNECT_PROJECT_ID = "72ea74c400f5111d43aea638d7d83a24";
package/dist/widget.cjs CHANGED
@@ -642,7 +642,7 @@ var init_constants = __esm({
642
642
  "src/constants.ts"() {
643
643
  "use strict";
644
644
  SDK_NAME = "@trustware/sdk";
645
- SDK_VERSION = "1.1.17-staging.7";
645
+ SDK_VERSION = "1.1.18-staging.1";
646
646
  API_ROOT = "https://bv-staging-api.trustware.io";
647
647
  GTM_ID = "GTM-TZDGNCXB";
648
648
  API_PREFIX = "/api";
@@ -2903,6 +2903,32 @@ var init_routeError = __esm({
2903
2903
  }
2904
2904
  });
2905
2905
 
2906
+ // src/core/routeApprovals.ts
2907
+ function approvalAmountWei(approval, stepIndex) {
2908
+ const { amount } = approval;
2909
+ if (amount === void 0 || amount === "") {
2910
+ throw new Error(
2911
+ `Route approval ${stepIndex} (spender ${String(approval.spender)}) has no amount.`
2912
+ );
2913
+ }
2914
+ if (!DECIMAL_INTEGER.test(amount)) {
2915
+ throw new Error(
2916
+ `Route approval ${stepIndex} (spender ${String(approval.spender)}) has an invalid amount "${amount}".`
2917
+ );
2918
+ }
2919
+ return BigInt(amount);
2920
+ }
2921
+ function assertValidRouteApprovals(approvals) {
2922
+ (approvals ?? []).forEach(approvalAmountWei);
2923
+ }
2924
+ var DECIMAL_INTEGER;
2925
+ var init_routeApprovals = __esm({
2926
+ "src/core/routeApprovals.ts"() {
2927
+ "use strict";
2928
+ DECIMAL_INTEGER = /^\d+$/;
2929
+ }
2930
+ });
2931
+
2906
2932
  // src/core/routeValue.ts
2907
2933
  function parseUsd(value) {
2908
2934
  if (value == null) return null;
@@ -3063,6 +3089,7 @@ async function buildRoute(body, signal) {
3063
3089
  if (!txReq?.data) {
3064
3090
  throw new Error("Invalid route: missing transaction data");
3065
3091
  }
3092
+ assertValidRouteApprovals(route?.execution?.approvals);
3066
3093
  assertRouteDeliversValue(route);
3067
3094
  return { intentId, txReq, actions, finalExchangeRate, route, sponsorship };
3068
3095
  }
@@ -3183,6 +3210,7 @@ var init_routes = __esm({
3183
3210
  "use strict";
3184
3211
  init_http();
3185
3212
  init_routeError();
3213
+ init_routeApprovals();
3186
3214
  init_routeValue();
3187
3215
  init_store();
3188
3216
  init_address();
@@ -6544,11 +6572,13 @@ async function ensureApprovals(w, approvals, fallbackChainId, intentId, routeAmo
6544
6572
  for (const [stepIndex, approval] of approvals.entries()) {
6545
6573
  const spender = approval.spender;
6546
6574
  const tokenAddress = approval.tokenAddress;
6547
- const amount = approval.amount;
6548
- if (!spender || !tokenAddress || !amount) continue;
6575
+ if (!spender || !tokenAddress) continue;
6549
6576
  const chainId = approval.chainId || String(fallbackChainId ?? "");
6550
6577
  if (!chainId) continue;
6551
- const amountWei = requiredApprovalAmount(BigInt(amount), routeAmountWei);
6578
+ const amountWei = requiredApprovalAmount(
6579
+ approvalAmountWei(approval, stepIndex),
6580
+ routeAmountWei
6581
+ );
6552
6582
  let currentAllowance = 0n;
6553
6583
  try {
6554
6584
  const { allowance } = await getEVMAllowance({
@@ -6634,7 +6664,6 @@ async function sendRouteTransactionReporting(b, fallbackChainId, options, onAcce
6634
6664
  )}).`
6635
6665
  );
6636
6666
  }
6637
- await ensureWalletOnChain(w, target);
6638
6667
  if (!validatedSponsorship && !options?.approvalsEnsured) {
6639
6668
  await ensureApprovals(
6640
6669
  w,
@@ -6644,6 +6673,7 @@ async function sendRouteTransactionReporting(b, fallbackChainId, options, onAcce
6644
6673
  BigInt(b.route?.estimate?.fromAmount ?? "0")
6645
6674
  );
6646
6675
  }
6676
+ await ensureWalletOnChain(w, target);
6647
6677
  if (w.type === "eip1193") {
6648
6678
  const from = await w.getAddress();
6649
6679
  const hexValue = value ? `0x${value.toString(16)}` : "0x0";
@@ -6810,6 +6840,7 @@ var import_viem2, erc20ApproveAbi, NOT_FOUND_GRACE_MS, UNLIMITED_APPROVAL_FLOOR;
6810
6840
  var init_tx = __esm({
6811
6841
  "src/core/tx.ts"() {
6812
6842
  "use strict";
6843
+ init_routeApprovals();
6813
6844
  init_routeValue();
6814
6845
  init_wallets();
6815
6846
  init_routes();
@@ -7061,11 +7092,7 @@ function mapRouteFacts(facts) {
7061
7092
  return INVALID_ADDRESS;
7062
7093
  }
7063
7094
  if (!facts.allDeclined) {
7064
- return {
7065
- category: "route_error",
7066
- title: "Route Unavailable",
7067
- message: "A routing provider did not respond. Please try again in a moment."
7068
- };
7095
+ return ROUTING_BUSY;
7069
7096
  }
7070
7097
  const has = (code) => facts.codes.includes(code);
7071
7098
  if (has(RouteDeclineCode.FeesExceedOutput)) {
@@ -7085,12 +7112,8 @@ function mapRouteFacts(facts) {
7085
7112
  message: minimum ? `This route needs at least ${minimum}. Try a larger amount.` : "This amount is below the minimum for this route. Try a larger amount."
7086
7113
  };
7087
7114
  }
7088
- if (lowLiquidity && !tooLow) {
7089
- return {
7090
- category: "route_error",
7091
- title: "Insufficient Liquidity",
7092
- message: "Not enough liquidity for this swap. Try a smaller amount or different token."
7093
- };
7115
+ if (facts.codes.every((code) => code === RouteDeclineCode.InsufficientLiquidity)) {
7116
+ return INSUFFICIENT_LIQUIDITY;
7094
7117
  }
7095
7118
  if (facts.codes.every((code) => code === RouteDeclineCode.DestinationCallFailed)) {
7096
7119
  return DESTINATION_CALL_FAILED;
@@ -7142,11 +7165,7 @@ function classifyError(raw, msg) {
7142
7165
  };
7143
7166
  }
7144
7167
  if (bm.includes("liquidity") || bm.includes("slippage") || bm.includes("price impact")) {
7145
- return {
7146
- category: "route_error",
7147
- title: "Insufficient Liquidity",
7148
- message: "Not enough liquidity for this swap. Try a smaller amount or different token."
7149
- };
7168
+ return INSUFFICIENT_LIQUIDITY;
7150
7169
  }
7151
7170
  if (bm.includes("insufficient funds") || bm.includes("insufficient balance")) {
7152
7171
  return {
@@ -7182,12 +7201,8 @@ function classifyError(raw, msg) {
7182
7201
  message: "Could not get a quote right now. Please try again."
7183
7202
  };
7184
7203
  }
7185
- if (lower.includes("not enough liquidity") || lower.includes("insufficient liquidity") || lower.includes("price impact too high")) {
7186
- return {
7187
- category: "route_error",
7188
- title: "Insufficient Liquidity",
7189
- message: "Not enough liquidity for this swap. Try a smaller amount or different token."
7190
- };
7204
+ if (lower.includes("enough liquidity") || lower.includes("insufficient liquidity") || lower.includes("price impact too high")) {
7205
+ return INSUFFICIENT_LIQUIDITY;
7191
7206
  }
7192
7207
  if (lower.includes("destination contract call")) {
7193
7208
  return DESTINATION_CALL_FAILED;
@@ -7195,6 +7210,9 @@ function classifyError(raw, msg) {
7195
7210
  if (lower.includes("invalid address") || lower.includes("address is not valid")) {
7196
7211
  return INVALID_ADDRESS;
7197
7212
  }
7213
+ if (lower.includes("routing is busy")) {
7214
+ return ROUTING_BUSY;
7215
+ }
7198
7216
  if (lower.includes("did not respond") || lower.includes("routing provider")) {
7199
7217
  return {
7200
7218
  category: "route_error",
@@ -7273,7 +7291,7 @@ function classifyError(raw, msg) {
7273
7291
  message: "An unexpected error occurred. Please try again."
7274
7292
  };
7275
7293
  }
7276
- var SELF_MAPPED, INVALID_ADDRESS, DESTINATION_CALL_FAILED;
7294
+ var SELF_MAPPED, INVALID_ADDRESS, DESTINATION_CALL_FAILED, INSUFFICIENT_LIQUIDITY, ROUTING_BUSY;
7277
7295
  var init_mapError = __esm({
7278
7296
  "src/widget/lib/mapError.ts"() {
7279
7297
  "use strict";
@@ -7294,6 +7312,16 @@ var init_mapError = __esm({
7294
7312
  title: "Destination Call Failed",
7295
7313
  message: "The destination contract call could not be simulated. Check the call data and target."
7296
7314
  };
7315
+ INSUFFICIENT_LIQUIDITY = {
7316
+ category: "route_error",
7317
+ title: "Insufficient Liquidity",
7318
+ message: "There isn't enough liquidity to route this swap right now. Try a different token or network, or a smaller amount."
7319
+ };
7320
+ ROUTING_BUSY = {
7321
+ category: "route_error",
7322
+ title: "Route Unavailable",
7323
+ message: "Routing is busy right now. Please wait a moment and try again."
7324
+ };
7297
7325
  }
7298
7326
  });
7299
7327
 
@@ -19930,6 +19958,37 @@ var init_SuccessSummaryCard = __esm({
19930
19958
  }
19931
19959
  });
19932
19960
 
19961
+ // src/widget/helpers/plannedApprovals.ts
19962
+ function plannedErc20Approvals(approvals, route) {
19963
+ return (approvals ?? []).flatMap((approval, stepIndex) => {
19964
+ const token = approval.tokenAddress ?? route.fromTokenAddress;
19965
+ const spender = approval.spender;
19966
+ if (!isEvmAddress2(token) || !isEvmAddress2(spender)) return [];
19967
+ return [
19968
+ {
19969
+ stepIndex,
19970
+ chainId: approval.chainId || route.chainId,
19971
+ token,
19972
+ spender,
19973
+ // A planned 0 is the reset-to-zero step USDT-style tokens need
19974
+ // before an existing allowance can change; it is kept as 0.
19975
+ amountWei: requiredApprovalAmount(
19976
+ approvalAmountWei(approval, stepIndex),
19977
+ route.amountWei
19978
+ )
19979
+ }
19980
+ ];
19981
+ });
19982
+ }
19983
+ var init_plannedApprovals = __esm({
19984
+ "src/widget/helpers/plannedApprovals.ts"() {
19985
+ "use strict";
19986
+ init_routeApprovals();
19987
+ init_tx();
19988
+ init_chainHelpers();
19989
+ }
19990
+ });
19991
+
19933
19992
  // src/widget/lib/routeChange.ts
19934
19993
  function describeRouteChange(change) {
19935
19994
  switch (change.kind) {
@@ -33227,9 +33286,6 @@ var init_smart_account2 = __esm({
33227
33286
  });
33228
33287
 
33229
33288
  // src/widget/features/transaction/hooks/useTransactionActionModel.ts
33230
- function sleep3(ms) {
33231
- return new Promise((resolve) => setTimeout(resolve, ms));
33232
- }
33233
33289
  function useTransactionActionModel({
33234
33290
  actionErrorMessage,
33235
33291
  amountWei,
@@ -33267,92 +33323,72 @@ function useTransactionActionModel({
33267
33323
  selectedChain?.id,
33268
33324
  selectedChain?.networkIdentifier
33269
33325
  ]);
33270
- const selectedTokenOnBackendChain = (0, import_react38.useMemo)(() => {
33271
- if (!backendChainId2) return false;
33272
- const target = normalizeChainKey(backendChainId2);
33273
- return [
33274
- selectedChain?.chainId,
33275
- selectedChain?.id,
33276
- selectedChain?.networkIdentifier
33277
- ].some((c) => {
33278
- const k = normalizeChainKey(c ?? null);
33279
- return k !== "" && k === target;
33280
- });
33281
- }, [
33282
- backendChainId2,
33283
- selectedChain?.chainId,
33284
- selectedChain?.id,
33285
- selectedChain?.networkIdentifier
33286
- ]);
33287
33326
  const isNativeSelected = (0, import_react38.useMemo)(() => {
33288
33327
  const address = selectedToken?.address;
33289
33328
  return !address || isNativeTokenAddress(address, chainType);
33290
33329
  }, [chainType, selectedToken?.address]);
33291
- const spender = (0, import_react38.useMemo)(() => {
33292
- const txReq = routeResult?.txReq;
33293
- const addr = txReq?.to ?? txReq?.target;
33294
- return addr ?? null;
33295
- }, [routeResult?.txReq]);
33296
- const [allowanceWei, setAllowanceWei] = (0, import_react38.useState)(0n);
33330
+ const requiredApprovals = (0, import_react38.useMemo)(
33331
+ () => isEvm && !isNativeSelected && !routeResult?.sponsorship ? plannedErc20Approvals(routeResult?.route?.execution?.approvals, {
33332
+ fromTokenAddress: selectedToken?.address,
33333
+ chainId: backendChainId2 ?? "",
33334
+ amountWei
33335
+ }) : [],
33336
+ [
33337
+ amountWei,
33338
+ backendChainId2,
33339
+ isEvm,
33340
+ isNativeSelected,
33341
+ routeResult?.route?.execution?.approvals,
33342
+ routeResult?.sponsorship,
33343
+ selectedToken?.address
33344
+ ]
33345
+ );
33346
+ const [unmetApprovals, setUnmetApprovals] = (0, import_react38.useState)(
33347
+ []
33348
+ );
33297
33349
  const [isReadingAllowance, setIsReadingAllowance] = (0, import_react38.useState)(false);
33298
33350
  const [isApproving, setIsApproving] = (0, import_react38.useState)(false);
33299
33351
  const [gasReservationWei, setGasReservationWei] = (0, import_react38.useState)(0n);
33352
+ const findUnmetApprovals = (0, import_react38.useCallback)(async () => {
33353
+ if (!walletAddress) return [];
33354
+ const met = await Promise.all(
33355
+ requiredApprovals.map(async (approval) => {
33356
+ try {
33357
+ const { allowance } = await getEVMAllowance({
33358
+ chainId: approval.chainId,
33359
+ tokenAddress: approval.token,
33360
+ ownerAddress: walletAddress,
33361
+ spenderAddress: approval.spender
33362
+ });
33363
+ return approvalSatisfied(
33364
+ BigInt(allowance || "0"),
33365
+ approval.amountWei
33366
+ );
33367
+ } catch {
33368
+ return false;
33369
+ }
33370
+ })
33371
+ );
33372
+ return requiredApprovals.filter((_, index) => !met[index]);
33373
+ }, [requiredApprovals, walletAddress]);
33300
33374
  const readAllowance = (0, import_react38.useCallback)(async () => {
33301
- if (!isEvm || isNativeSelected || !!routeResult?.sponsorship || // sponsored routes: SA approves bridge inside the UO batch
33302
- !backendChainId2 || !selectedTokenOnBackendChain || !walletAddress || !spender || !selectedToken?.address) {
33303
- setAllowanceWei(0n);
33375
+ if (requiredApprovals.length === 0) {
33376
+ setUnmetApprovals([]);
33304
33377
  return;
33305
33378
  }
33379
+ setIsReadingAllowance(true);
33306
33380
  try {
33307
- setIsReadingAllowance(true);
33308
- const result = await getEVMAllowance({
33309
- chainId: backendChainId2,
33310
- tokenAddress: selectedToken.address,
33311
- ownerAddress: walletAddress,
33312
- spenderAddress: spender
33313
- });
33314
- setAllowanceWei(BigInt(result.allowance || "0"));
33315
- } catch {
33316
- setAllowanceWei(0n);
33381
+ setUnmetApprovals(await findUnmetApprovals());
33317
33382
  } finally {
33318
33383
  setIsReadingAllowance(false);
33319
33384
  }
33320
- }, [
33321
- backendChainId2,
33322
- isEvm,
33323
- isNativeSelected,
33324
- routeResult?.sponsorship,
33325
- selectedTokenOnBackendChain,
33326
- selectedToken?.address,
33327
- spender,
33328
- walletAddress
33329
- ]);
33385
+ }, [findUnmetApprovals, requiredApprovals.length]);
33330
33386
  (0, import_react38.useEffect)(() => {
33331
33387
  void readAllowance();
33332
33388
  }, [readAllowance]);
33333
- const needsApproval = isEvm && !isNativeSelected && !routeResult?.sponsorship && // sponsored routes use Permit2 + SA internal batch — no EOA bridge approval
33334
- !!walletAddress && !!spender && amountWei > 0n && allowanceWei < amountWei;
33335
- const waitForApprovalConfirmation2 = (0, import_react38.useCallback)(
33336
- async (chainId, txHash) => {
33337
- const timeoutMs = 12e4;
33338
- const intervalMs = 2e3;
33339
- const started = Date.now();
33340
- while (Date.now() - started < timeoutMs) {
33341
- const status = await getEVMTxStatus({ chainId, txHash });
33342
- if (status.status === "success") {
33343
- return;
33344
- }
33345
- if (status.status === "reverted") {
33346
- throw new Error("Approval transaction reverted");
33347
- }
33348
- await sleep3(intervalMs);
33349
- }
33350
- throw new Error("Timed out waiting for approval confirmation");
33351
- },
33352
- []
33353
- );
33389
+ const needsApproval = !!walletAddress && amountWei > 0n && unmetApprovals.length > 0;
33354
33390
  const handleApproveExact = (0, import_react38.useCallback)(async () => {
33355
- if (isApproving || amountWei <= 0n || !walletAddress || !spender || !selectedToken?.address) {
33391
+ if (isApproving || amountWei <= 0n || !walletAddress || unmetApprovals.length === 0) {
33356
33392
  return;
33357
33393
  }
33358
33394
  const wallet = Trustware.getWallet();
@@ -33368,80 +33404,57 @@ function useTransactionActionModel({
33368
33404
  });
33369
33405
  setIsApproving(true);
33370
33406
  try {
33371
- const targetChain = Number(
33372
- routeResult?.txReq?.chainId ?? selectedChain?.chainId ?? selectedChain?.id
33373
- );
33374
- console.log("[approve] targetChain:", targetChain, {
33375
- txReqChainId: routeResult?.txReq?.chainId,
33376
- selectedChainId: selectedChain?.chainId,
33377
- selectedChainIdAlt: selectedChain?.id
33378
- });
33379
- if (Number.isFinite(targetChain)) {
33380
- const current = await wallet.getChainId();
33381
- if (current !== targetChain) {
33382
- try {
33383
- await wallet.switchChain(targetChain);
33384
- } catch {
33385
- }
33386
- }
33387
- }
33388
- const data = (0, import_viem42.encodeFunctionData)({
33389
- abi: import_viem42.erc20Abi,
33390
- functionName: "approve",
33391
- args: [spender, amountWei]
33392
- });
33393
- let hash;
33394
- if (wallet.type === "eip1193") {
33395
- const from = await wallet.getAddress();
33396
- const params = {
33397
- from,
33398
- to: selectedToken.address,
33399
- data,
33400
- value: "0x0"
33401
- };
33402
- if (Number.isFinite(targetChain)) {
33403
- params.chainId = `0x${targetChain.toString(16)}`;
33404
- }
33405
- hash = await wallet.request({
33406
- method: "eth_sendTransaction",
33407
- params: [params]
33407
+ for (const approval of unmetApprovals) {
33408
+ const approvalChain = Number(approval.chainId);
33409
+ await ensureWalletOnChain(wallet, approvalChain);
33410
+ const data = (0, import_viem42.encodeFunctionData)({
33411
+ abi: import_viem42.erc20Abi,
33412
+ functionName: "approve",
33413
+ args: [approval.spender, approval.amountWei]
33408
33414
  });
33409
- } else {
33410
- const response = await wallet.sendTransaction({
33411
- to: selectedToken.address,
33412
- data,
33413
- value: 0n,
33414
- chainId: Number.isFinite(targetChain) ? targetChain : void 0
33415
- });
33416
- hash = response.hash;
33417
- }
33418
- if (backendChainId2) {
33419
- await waitForApprovalConfirmation2(backendChainId2, hash);
33420
- await readAllowance();
33421
- } else {
33422
- setAllowanceWei(amountWei);
33415
+ let hash;
33416
+ if (wallet.type === "eip1193") {
33417
+ const from = await wallet.getAddress();
33418
+ hash = await wallet.request({
33419
+ method: "eth_sendTransaction",
33420
+ params: [
33421
+ {
33422
+ from,
33423
+ to: approval.token,
33424
+ data,
33425
+ value: "0x0",
33426
+ chainId: `0x${approvalChain.toString(16)}`
33427
+ }
33428
+ ]
33429
+ });
33430
+ } else {
33431
+ const response = await wallet.sendTransaction({
33432
+ to: approval.token,
33433
+ data,
33434
+ value: 0n,
33435
+ chainId: approvalChain
33436
+ });
33437
+ hash = response.hash;
33438
+ }
33439
+ await waitForApprovalConfirmation(approval.chainId, hash);
33423
33440
  }
33441
+ await readAllowance();
33424
33442
  } catch {
33425
33443
  } finally {
33426
33444
  setIsApproving(false);
33427
33445
  }
33428
33446
  }, [
33429
33447
  amountWei,
33430
- backendChainId2,
33431
33448
  destinationConfig?.routes.toChain,
33432
33449
  destinationConfig?.routes.toToken,
33433
33450
  isApproving,
33434
33451
  readAllowance,
33435
- routeResult?.txReq?.chainId,
33436
33452
  selectedChain?.axelarChainName,
33437
33453
  selectedChain?.chainId,
33438
- selectedChain?.id,
33439
33454
  selectedChain?.networkName,
33440
- selectedToken?.address,
33441
33455
  selectedToken?.symbol,
33442
- spender,
33443
33456
  trackEvent,
33444
- waitForApprovalConfirmation2,
33457
+ unmetApprovals,
33445
33458
  walletAddress
33446
33459
  ]);
33447
33460
  const getCachedFeeData = (0, import_react38.useCallback)(async () => {
@@ -33628,32 +33641,13 @@ function useTransactionActionModel({
33628
33641
  const handleSwipeConfirm = (0, import_react38.useCallback)(async () => {
33629
33642
  if (needsApproval) {
33630
33643
  await handleApproveExact();
33631
- if (!backendChainId2 || !selectedTokenOnBackendChain || !selectedToken?.address || !walletAddress || !spender) {
33632
- return;
33633
- }
33634
- const freshAllowance = await getEVMAllowance({
33635
- chainId: backendChainId2,
33636
- tokenAddress: selectedToken.address,
33637
- ownerAddress: walletAddress,
33638
- spenderAddress: spender
33639
- }).then((r) => BigInt(r.allowance || "0")).catch(() => 0n);
33640
- if (freshAllowance >= amountWei) {
33644
+ if ((await findUnmetApprovals()).length === 0) {
33641
33645
  await handleConfirm();
33642
33646
  }
33643
33647
  return;
33644
33648
  }
33645
33649
  await handleConfirm();
33646
- }, [
33647
- amountWei,
33648
- backendChainId2,
33649
- handleApproveExact,
33650
- handleConfirm,
33651
- needsApproval,
33652
- selectedTokenOnBackendChain,
33653
- selectedToken?.address,
33654
- spender,
33655
- walletAddress
33656
- ]);
33650
+ }, [findUnmetApprovals, handleApproveExact, handleConfirm, needsApproval]);
33657
33651
  const isWalletConnected = walletStatus === "connected";
33658
33652
  const canSwipe = parsedAmount > 0 && !!selectedToken && isWalletConnected && !isLoadingRoute && !isSubmitting && !!routeResult && !actionErrorMessage && !isApproving && !isReadingAllowance;
33659
33653
  const swipeResetKey = (0, import_react38.useMemo)(() => {
@@ -33700,9 +33694,11 @@ var init_useTransactionActionModel = __esm({
33700
33694
  import_viem42 = require("viem");
33701
33695
  init_core2();
33702
33696
  init_sdkRpc();
33697
+ init_tx();
33703
33698
  init_hooks2();
33704
33699
  init_chains();
33705
33700
  init_utils2();
33701
+ init_plannedApprovals();
33706
33702
  init_hooks();
33707
33703
  init_routeChange();
33708
33704
  }
@@ -35143,33 +35139,15 @@ function useSwapExecution(fromChain) {
35143
35139
  const chainIdStr = String(txReq?.chainId ?? fromChain?.chainId ?? "");
35144
35140
  const amountWei = BigInt(routeResult.route?.estimate?.fromAmount ?? "0");
35145
35141
  const plannedApprovals = routeResult.route?.execution?.approvals ?? [];
35146
- const toCheck = plannedApprovals.length ? plannedApprovals.flatMap((a) => {
35147
- const token = a.tokenAddress ?? fromTokenAddress;
35148
- const required = requiredApprovalAmount(
35149
- BigInt(a.amount || "0"),
35150
- amountWei
35151
- );
35152
- if (!isEvmAddress2(token) || !isEvmAddress2(a.spender)) return [];
35153
- return [
35154
- {
35155
- chainId: a.chainId || chainIdStr,
35156
- token,
35157
- spender: a.spender,
35158
- required
35159
- }
35160
- ];
35161
- }) : (() => {
35162
- const spender = txReq?.to ?? txReq?.target;
35163
- if (!spender) return [];
35164
- return [
35165
- {
35166
- chainId: chainIdStr,
35167
- token: fromTokenAddress,
35168
- spender,
35169
- required: amountWei
35170
- }
35171
- ];
35172
- })();
35142
+ if (plannedApprovals.length === 0) {
35143
+ setState((p) => ({ ...p, allowanceStatus: "sufficient" }));
35144
+ return;
35145
+ }
35146
+ const toCheck = plannedErc20Approvals(plannedApprovals, {
35147
+ fromTokenAddress,
35148
+ chainId: chainIdStr,
35149
+ amountWei
35150
+ });
35173
35151
  if (toCheck.length === 0 || !chainIdStr || amountWei === 0n) {
35174
35152
  setState((p) => ({ ...p, allowanceStatus: "unknown" }));
35175
35153
  return;
@@ -35184,7 +35162,7 @@ function useSwapExecution(fromChain) {
35184
35162
  ownerAddress: walletAddress,
35185
35163
  spenderAddress: c.spender
35186
35164
  });
35187
- return approvalSatisfied(BigInt(allowance || "0"), c.required);
35165
+ return approvalSatisfied(BigInt(allowance || "0"), c.amountWei);
35188
35166
  })
35189
35167
  );
35190
35168
  setState((p) => ({
@@ -35239,7 +35217,6 @@ function useSwapExecution(fromChain) {
35239
35217
  const txReq = routeResult.txReq;
35240
35218
  const numericChainId = Number(txReq.chainId ?? fromChain?.chainId) || void 0;
35241
35219
  const chainIdStr = String(txReq.chainId ?? fromChain?.chainId ?? "");
35242
- const spender = txReq.to ?? txReq.target;
35243
35220
  const chainType = normalizeChainType(fromChain);
35244
35221
  const isNative = !fromTokenAddress || isNativeTokenAddress(fromTokenAddress, chainType);
35245
35222
  const fromAmountWei = BigInt(
@@ -35319,34 +35296,12 @@ function useSwapExecution(fromChain) {
35319
35296
  const acceptance = { tracking: false };
35320
35297
  try {
35321
35298
  const plannedApprovals = routeResult.route?.execution?.approvals ?? [];
35322
- const requiredApprovals = plannedApprovals.length ? plannedApprovals.flatMap((a, index) => {
35323
- const token = a.tokenAddress ?? fromTokenAddress;
35324
- const approvalSpender = a.spender;
35325
- if (!isEvmAddress2(token) || !isEvmAddress2(approvalSpender))
35326
- return [];
35327
- const amountWei = requiredApprovalAmount(
35328
- BigInt(a.amount || "0"),
35329
- fromAmountWei
35330
- );
35331
- return [
35332
- {
35333
- stepIndex: index,
35334
- token,
35335
- spender: approvalSpender,
35336
- amountWei,
35337
- chainId: a.chainId || chainIdStr
35338
- }
35339
- ];
35340
- }) : spender && fromTokenAddress ? [
35341
- {
35342
- stepIndex: null,
35343
- token: fromTokenAddress,
35344
- spender,
35345
- amountWei: fromAmountWei,
35346
- chainId: chainIdStr
35347
- }
35348
- ] : [];
35349
- const coversEveryPlannedApproval = plannedApprovals.length === 0 || requiredApprovals.length === plannedApprovals.length;
35299
+ const requiredApprovals = plannedErc20Approvals(plannedApprovals, {
35300
+ fromTokenAddress,
35301
+ chainId: chainIdStr,
35302
+ amountWei: fromAmountWei
35303
+ });
35304
+ const coversEveryPlannedApproval = requiredApprovals.length === plannedApprovals.length;
35350
35305
  const ownsApprovals = coversEveryPlannedApproval && needsErc20Approval(fromTokenAddress, chainType) && !!walletAddress && !!chainIdStr;
35351
35306
  const activeAddress = ownsApprovals ? await requireActiveAddress(wallet, walletAddress) : void 0;
35352
35307
  for (const required of requiredApprovals) {
@@ -35408,14 +35363,12 @@ function useSwapExecution(fromChain) {
35408
35363
  });
35409
35364
  approvalHash = response.hash;
35410
35365
  }
35411
- if (required.stepIndex !== null) {
35412
- void submitStepReceipt(
35413
- routeResult.intentId,
35414
- required.stepIndex,
35415
- approvalHash
35416
- ).catch(() => {
35417
- });
35418
- }
35366
+ void submitStepReceipt(
35367
+ routeResult.intentId,
35368
+ required.stepIndex,
35369
+ approvalHash
35370
+ ).catch(() => {
35371
+ });
35419
35372
  await waitForApprovalConfirmation(required.chainId, approvalHash);
35420
35373
  setState((p) => ({
35421
35374
  ...p,
@@ -35534,6 +35487,7 @@ var init_useSwapExecution = __esm({
35534
35487
  init_tx();
35535
35488
  init_sdkRpc();
35536
35489
  init_chainHelpers();
35490
+ init_plannedApprovals();
35537
35491
  init_chains();
35538
35492
  SA_COOLDOWN_MS = 3e4;
35539
35493
  }