@trustware/sdk-staging 1.1.10-staging.0 → 1.1.11-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/widget.mjs CHANGED
@@ -563,7 +563,7 @@ var init_constants = __esm({
563
563
  "src/constants.ts"() {
564
564
  "use strict";
565
565
  SDK_NAME = "@trustware/sdk";
566
- SDK_VERSION = "1.1.10-staging.0";
566
+ SDK_VERSION = "1.1.11-staging.1";
567
567
  API_ROOT = "https://bv-staging-api.trustware.io";
568
568
  GTM_ID = "GTM-TZDGNCXB";
569
569
  API_PREFIX = "/api";
@@ -607,6 +607,9 @@ async function assertOK(r) {
607
607
  }
608
608
  throw new Error(`HTTP ${r.status}: ${msg}`);
609
609
  }
610
+ function isNotFoundError(err) {
611
+ return err instanceof Error && err.message.startsWith("HTTP 404");
612
+ }
610
613
  async function validateSdkAccess() {
611
614
  const r = await fetch(`${apiBase()}/sdk/validate`, {
612
615
  method: "GET",
@@ -2579,6 +2582,19 @@ async function submitReceipt(intentId, txHash, sponsorshipRequestId, eoaAddress)
2579
2582
  const j = await r.json();
2580
2583
  return j.data;
2581
2584
  }
2585
+ async function submitStepReceipt(intentId, stepIndex, txHash) {
2586
+ const r = await rateLimitedFetch(
2587
+ `${apiBase()}/v1/route-intent/${intentId}/steps/${stepIndex}/receipt`,
2588
+ {
2589
+ method: "POST",
2590
+ headers: jsonHeaders({ "Idempotency-Key": txHash }),
2591
+ body: JSON.stringify({ txHash })
2592
+ }
2593
+ );
2594
+ await assertOK(r);
2595
+ const j = await r.json();
2596
+ return j.data;
2597
+ }
2582
2598
  async function getStatus(intentId) {
2583
2599
  const r = await rateLimitedFetch(
2584
2600
  `${apiBase()}/v1/route-intent/${intentId}/status`,
@@ -5300,75 +5316,17 @@ var init_useTransactionSubmit = __esm({
5300
5316
 
5301
5317
  // src/hooks/useGTM.ts
5302
5318
  import { useEffect as useEffect5, useRef as useRef2, useCallback as useCallback2 } from "react";
5303
- function useGTM(gtmId) {
5304
- const isInitialized = useRef2(false);
5305
- const scriptRef = useRef2(null);
5306
- const isGA4Allowed = useCallback2(() => {
5307
- try {
5308
- return Trustware.getConfig().features.shouldAllowGA4;
5309
- } catch {
5310
- return false;
5311
- }
5312
- }, []);
5313
- useEffect5(() => {
5314
- if (!isGA4Allowed()) {
5315
- console.warn(
5316
- "useGTM: GA4 tracking is disabled or Trustware config not initialized."
5317
- );
5318
- return;
5319
- }
5320
- if (!gtmId || typeof gtmId !== "string") {
5321
- console.error(
5322
- "useGTM: A valid GTM Container ID is required (format: GTM-XXXXX)."
5323
- );
5324
- return;
5325
- }
5326
- if (isInitialized.current) return;
5327
- const alreadyLoaded = document.querySelector(
5328
- `script[src*="googletagmanager.com/gtm.js?id=${gtmId}"]`
5329
- );
5330
- if (alreadyLoaded) {
5331
- window.dataLayer = window.dataLayer || [];
5332
- isInitialized.current = true;
5333
- return;
5334
- }
5335
- window.dataLayer = window.dataLayer || [];
5336
- window.dataLayer.push({
5337
- "gtm.start": (/* @__PURE__ */ new Date()).getTime(),
5338
- event: "gtm.js"
5339
- });
5340
- const firstScript = document.getElementsByTagName("script")[0];
5341
- const script = document.createElement("script");
5342
- script.async = true;
5343
- script.src = `https://www.googletagmanager.com/gtm.js?id=${gtmId}`;
5344
- firstScript.parentNode?.insertBefore(script, firstScript);
5345
- scriptRef.current = script;
5346
- isInitialized.current = true;
5347
- return () => {
5348
- if (scriptRef.current) {
5349
- scriptRef.current.parentNode?.removeChild(scriptRef.current);
5350
- scriptRef.current = null;
5351
- }
5352
- isInitialized.current = false;
5353
- };
5354
- }, [gtmId, isGA4Allowed]);
5355
- const addNoscriptIframe = useCallback2(() => {
5356
- if (!isGA4Allowed()) return;
5357
- if (document.querySelector('iframe[src*="googletagmanager.com/ns.html"]'))
5358
- return;
5359
- const noscript = document.createElement("noscript");
5360
- const iframe = document.createElement("iframe");
5361
- iframe.src = `https://www.googletagmanager.com/ns.html?id=${gtmId}`;
5362
- iframe.height = "0";
5363
- iframe.width = "0";
5364
- iframe.style.display = "none";
5365
- iframe.style.visibility = "hidden";
5366
- noscript.appendChild(iframe);
5367
- document.body.insertBefore(noscript, document.body.firstChild);
5368
- }, [gtmId, isGA4Allowed]);
5319
+ function isGA4Allowed() {
5320
+ try {
5321
+ return Trustware.getConfig().features.shouldAllowGA4;
5322
+ } catch {
5323
+ return false;
5324
+ }
5325
+ }
5326
+ function useGTMTracker() {
5369
5327
  const trackEvent = useCallback2(
5370
5328
  (eventName, eventParams = {}) => {
5371
- if (!isInitialized.current) {
5329
+ if (!isContainerInitialized) {
5372
5330
  console.warn(
5373
5331
  "useGTM: Not initialized. Ensure a valid GTM Container ID was provided."
5374
5332
  );
@@ -5395,7 +5353,7 @@ function useGTM(gtmId) {
5395
5353
  );
5396
5354
  const setUserProperty = useCallback2(
5397
5355
  (propertyName, value) => {
5398
- if (!isInitialized.current) {
5356
+ if (!isContainerInitialized) {
5399
5357
  console.warn(
5400
5358
  "useGTM: Not initialized. Ensure a valid GTM Container ID was provided."
5401
5359
  );
@@ -5421,20 +5379,77 @@ function useGTM(gtmId) {
5421
5379
  }
5422
5380
  window.gtag(command, ...args);
5423
5381
  },
5424
- [isGA4Allowed]
5382
+ []
5425
5383
  );
5426
- return {
5427
- trackEvent,
5428
- trackPageView,
5429
- setUserProperty,
5430
- directGtag,
5431
- addNoscriptIframe
5432
- };
5384
+ return { trackEvent, trackPageView, setUserProperty, directGtag };
5385
+ }
5386
+ function useGTM(gtmId) {
5387
+ const scriptRef = useRef2(null);
5388
+ const tracker = useGTMTracker();
5389
+ useEffect5(() => {
5390
+ if (!isGA4Allowed()) {
5391
+ console.warn(
5392
+ "useGTM: GA4 tracking is disabled or Trustware config not initialized."
5393
+ );
5394
+ return;
5395
+ }
5396
+ if (!gtmId || typeof gtmId !== "string") {
5397
+ console.error(
5398
+ "useGTM: A valid GTM Container ID is required (format: GTM-XXXXX)."
5399
+ );
5400
+ return;
5401
+ }
5402
+ if (isContainerInitialized) return;
5403
+ const alreadyLoaded = document.querySelector(
5404
+ `script[src*="googletagmanager.com/gtm.js?id=${gtmId}"]`
5405
+ );
5406
+ if (alreadyLoaded) {
5407
+ window.dataLayer = window.dataLayer || [];
5408
+ isContainerInitialized = true;
5409
+ return;
5410
+ }
5411
+ window.dataLayer = window.dataLayer || [];
5412
+ window.dataLayer.push({
5413
+ "gtm.start": (/* @__PURE__ */ new Date()).getTime(),
5414
+ event: "gtm.js"
5415
+ });
5416
+ const firstScript = document.getElementsByTagName("script")[0];
5417
+ const script = document.createElement("script");
5418
+ script.async = true;
5419
+ script.src = `https://www.googletagmanager.com/gtm.js?id=${gtmId}`;
5420
+ firstScript.parentNode?.insertBefore(script, firstScript);
5421
+ scriptRef.current = script;
5422
+ isContainerInitialized = true;
5423
+ return () => {
5424
+ if (scriptRef.current) {
5425
+ scriptRef.current.parentNode?.removeChild(scriptRef.current);
5426
+ scriptRef.current = null;
5427
+ }
5428
+ isContainerInitialized = false;
5429
+ };
5430
+ }, [gtmId]);
5431
+ const addNoscriptIframe = useCallback2(() => {
5432
+ if (!isGA4Allowed()) return;
5433
+ if (document.querySelector('iframe[src*="googletagmanager.com/ns.html"]'))
5434
+ return;
5435
+ const noscript = document.createElement("noscript");
5436
+ const iframe = document.createElement("iframe");
5437
+ iframe.src = `https://www.googletagmanager.com/ns.html?id=${gtmId}`;
5438
+ iframe.height = "0";
5439
+ iframe.width = "0";
5440
+ iframe.style.display = "none";
5441
+ iframe.style.visibility = "hidden";
5442
+ noscript.appendChild(iframe);
5443
+ document.body.insertBefore(noscript, document.body.firstChild);
5444
+ }, [gtmId]);
5445
+ return { ...tracker, addNoscriptIframe };
5433
5446
  }
5447
+ var isContainerInitialized;
5434
5448
  var init_useGTM = __esm({
5435
5449
  "src/hooks/useGTM.ts"() {
5436
5450
  "use strict";
5437
5451
  init_core2();
5452
+ isContainerInitialized = false;
5438
5453
  }
5439
5454
  });
5440
5455
 
@@ -5461,7 +5476,7 @@ function useTransactionPolling() {
5461
5476
  return void 0;
5462
5477
  }
5463
5478
  })();
5464
- const { trackEvent } = useGTM(GTM_ID);
5479
+ const { trackEvent } = useGTMTracker();
5465
5480
  const [state, setState] = useState6({
5466
5481
  isPolling: false,
5467
5482
  apiStatus: null,
@@ -5561,8 +5576,21 @@ function useTransactionPolling() {
5561
5576
  pollCountRef.current += 1;
5562
5577
  const pollInterval = pollCountRef.current <= 10 ? FAST_POLL_INTERVAL_MS : NORMAL_POLL_INTERVAL_MS;
5563
5578
  pollingRef.current = setTimeout(poll, pollInterval);
5564
- } catch {
5579
+ } catch (err) {
5565
5580
  if (abortRef.current) return;
5581
+ if (isNotFoundError(err)) {
5582
+ clearPolling();
5583
+ const notFoundError = "Transaction session expired. Please try again.";
5584
+ setState((prev) => ({
5585
+ ...prev,
5586
+ isPolling: false,
5587
+ error: notFoundError
5588
+ }));
5589
+ setErrorMessage(notFoundError);
5590
+ setTransactionStatus("error");
5591
+ setCurrentStep("error");
5592
+ return;
5593
+ }
5566
5594
  const elapsed = Date.now() - startTimeRef.current;
5567
5595
  if (elapsed > POLL_TIMEOUT_MS) {
5568
5596
  clearPolling();
@@ -5698,10 +5726,10 @@ var init_useTransactionPolling = __esm({
5698
5726
  "use strict";
5699
5727
  "use client";
5700
5728
  init_routes();
5729
+ init_http();
5701
5730
  init_DepositContext();
5702
5731
  init_provider();
5703
5732
  init_core2();
5704
- init_constants();
5705
5733
  init_hooks();
5706
5734
  FAST_POLL_INTERVAL_MS = 1500;
5707
5735
  NORMAL_POLL_INTERVAL_MS = 2500;
@@ -5783,6 +5811,20 @@ var init_eipWallets = __esm({
5783
5811
  "src/wallets/eipWallets.ts"() {
5784
5812
  "use strict";
5785
5813
  CHAIN_PARAMS = {
5814
+ 1: {
5815
+ chainIdHex: "0x1",
5816
+ chainName: "Ethereum",
5817
+ rpcUrls: ["https://eth.llamarpc.com"],
5818
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
5819
+ blockExplorerUrls: ["https://etherscan.io"]
5820
+ },
5821
+ 137: {
5822
+ chainIdHex: "0x89",
5823
+ chainName: "Polygon",
5824
+ rpcUrls: ["https://polygon-rpc.com"],
5825
+ nativeCurrency: { name: "POL", symbol: "POL", decimals: 18 },
5826
+ blockExplorerUrls: ["https://polygonscan.com"]
5827
+ },
5786
5828
  8453: {
5787
5829
  chainIdHex: "0x2105",
5788
5830
  chainName: "Base",
@@ -9063,18 +9105,27 @@ async function waitForTxConfirmation(chainId, txHash) {
9063
9105
  }
9064
9106
  throw new Error("Timed out waiting for approval confirmation");
9065
9107
  }
9066
- async function ensureApprovals(w, approvals, fallbackChainId) {
9108
+ function requiredApprovalAmount(planAmountWei, routeAmountWei) {
9109
+ if (planAmountWei >= UNLIMITED_APPROVAL_FLOOR && routeAmountWei !== void 0 && routeAmountWei > 0n) {
9110
+ return routeAmountWei;
9111
+ }
9112
+ return planAmountWei;
9113
+ }
9114
+ function approvalSatisfied(currentAllowance, requiredWei) {
9115
+ if (requiredWei === 0n) return currentAllowance === 0n;
9116
+ return currentAllowance >= requiredWei;
9117
+ }
9118
+ async function ensureApprovals(w, approvals, fallbackChainId, intentId, routeAmountWei) {
9067
9119
  if (!approvals || approvals.length === 0) return;
9068
9120
  const owner = await w.getAddress();
9069
- for (const approval of approvals) {
9121
+ for (const [stepIndex, approval] of approvals.entries()) {
9070
9122
  const spender = approval.spender;
9071
9123
  const tokenAddress = approval.tokenAddress;
9072
9124
  const amount = approval.amount;
9073
9125
  if (!spender || !tokenAddress || !amount) continue;
9074
9126
  const chainId = approval.chainId || String(fallbackChainId ?? "");
9075
9127
  if (!chainId) continue;
9076
- const amountWei = BigInt(amount);
9077
- if (amountWei === 0n) continue;
9128
+ const amountWei = requiredApprovalAmount(BigInt(amount), routeAmountWei);
9078
9129
  let currentAllowance = 0n;
9079
9130
  try {
9080
9131
  const { allowance } = await getEVMAllowance({
@@ -9086,7 +9137,7 @@ async function ensureApprovals(w, approvals, fallbackChainId) {
9086
9137
  currentAllowance = BigInt(allowance || "0");
9087
9138
  } catch {
9088
9139
  }
9089
- if (currentAllowance >= amountWei) continue;
9140
+ if (approvalSatisfied(currentAllowance, amountWei)) continue;
9090
9141
  const data = encodeFunctionData({
9091
9142
  abi: erc20ApproveAbi,
9092
9143
  functionName: "approve",
@@ -9098,6 +9149,10 @@ async function ensureApprovals(w, approvals, fallbackChainId) {
9098
9149
  value: 0n,
9099
9150
  chainId: Number.isFinite(Number(chainId)) ? Number(chainId) : void 0
9100
9151
  });
9152
+ if (intentId) {
9153
+ void submitStepReceipt(intentId, stepIndex, hash).catch(() => {
9154
+ });
9155
+ }
9101
9156
  await waitForTxConfirmation(chainId, hash);
9102
9157
  }
9103
9158
  }
@@ -9107,7 +9162,7 @@ function isUserRejected(e2) {
9107
9162
  const msg = String(e2?.message || e2)?.toLowerCase?.() || "";
9108
9163
  return msg.includes("user rejected") || msg.includes("user denied");
9109
9164
  }
9110
- async function sendRouteTransaction(b, fallbackChainId) {
9165
+ async function sendRouteTransaction(b, fallbackChainId, options) {
9111
9166
  const w = walletManager.wallet;
9112
9167
  if (!w) throw new Error("Trustware.wallet not configured");
9113
9168
  const txReq = b.txReq;
@@ -9134,11 +9189,13 @@ async function sendRouteTransaction(b, fallbackChainId) {
9134
9189
  }
9135
9190
  }
9136
9191
  }
9137
- if (!validatedSponsorship) {
9192
+ if (!validatedSponsorship && !options?.approvalsEnsured) {
9138
9193
  await ensureApprovals(
9139
9194
  w,
9140
9195
  b.route?.execution?.approvals,
9141
- Number.isFinite(target) ? target : void 0
9196
+ Number.isFinite(target) ? target : void 0,
9197
+ b.intentId,
9198
+ BigInt(b.route?.estimate?.fromAmount ?? "0")
9142
9199
  );
9143
9200
  }
9144
9201
  if (w.type === "eip1193") {
@@ -9237,7 +9294,7 @@ async function runTopUp(params) {
9237
9294
  }
9238
9295
  }
9239
9296
  }
9240
- var erc20ApproveAbi;
9297
+ var erc20ApproveAbi, UNLIMITED_APPROVAL_FLOOR;
9241
9298
  var init_tx = __esm({
9242
9299
  "src/core/tx.ts"() {
9243
9300
  "use strict";
@@ -9247,6 +9304,7 @@ var init_tx = __esm({
9247
9304
  erc20ApproveAbi = parseAbi([
9248
9305
  "function approve(address spender, uint256 amount) returns (bool)"
9249
9306
  ]);
9307
+ UNLIMITED_APPROVAL_FLOOR = 1n << 255n;
9250
9308
  }
9251
9309
  });
9252
9310
 
@@ -9392,6 +9450,7 @@ var init_core = __esm({
9392
9450
  buildRoute,
9393
9451
  buildDepositAddress,
9394
9452
  submitReceipt,
9453
+ submitStepReceipt,
9395
9454
  getStatus,
9396
9455
  pollStatus,
9397
9456
  getBalances,
@@ -31594,7 +31653,7 @@ function useTransactionActionModel({
31594
31653
  }) {
31595
31654
  const feeDataCacheRef = useRef13({});
31596
31655
  const { isSubmitting, submitTransaction } = useTransactionSubmit();
31597
- const { trackEvent } = useGTM(GTM_ID);
31656
+ const { trackEvent } = useGTMTracker();
31598
31657
  const destinationConfig = (() => {
31599
31658
  try {
31600
31659
  return Trustware.getConfig();
@@ -32027,7 +32086,6 @@ var init_useTransactionActionModel = __esm({
32027
32086
  init_chainHelpers();
32028
32087
  init_utils2();
32029
32088
  init_hooks();
32030
- init_constants();
32031
32089
  }
32032
32090
  });
32033
32091
 
@@ -33379,6 +33437,16 @@ async function waitForApprovalConfirmation(chainId, txHash) {
33379
33437
  }
33380
33438
  throw new Error("Timed out waiting for approval confirmation");
33381
33439
  }
33440
+ async function requireActiveAddress(wallet, plannedFor) {
33441
+ if (!wallet) throw new Error("Wallet not connected. Please reconnect.");
33442
+ const active = await wallet.getAddress();
33443
+ if (active?.toLowerCase() !== plannedFor?.toLowerCase()) {
33444
+ throw new Error(
33445
+ "Wallet account changed. Please review and confirm the swap again."
33446
+ );
33447
+ }
33448
+ return active;
33449
+ }
33382
33450
  function useSwapExecution(fromChain) {
33383
33451
  const [state, setState] = useState29({
33384
33452
  txStatus: "idle",
@@ -33435,7 +33503,15 @@ function useSwapExecution(fromChain) {
33435
33503
  if (tx.status === "bridging") {
33436
33504
  setState((p) => ({ ...p, txStatus: "bridging" }));
33437
33505
  }
33438
- } catch {
33506
+ } catch (err) {
33507
+ if (abortRef.current) return;
33508
+ if (isNotFoundError(err)) {
33509
+ clearPolling();
33510
+ const msg = "Transaction session expired. Please try again.";
33511
+ setState((p) => ({ ...p, txStatus: "error", errorMessage: msg }));
33512
+ onError(msg);
33513
+ return;
33514
+ }
33439
33515
  }
33440
33516
  if (abortRef.current) return;
33441
33517
  pollCountRef.current += 1;
@@ -33461,24 +33537,55 @@ function useSwapExecution(fromChain) {
33461
33537
  }
33462
33538
  const txReq = routeResult.txReq;
33463
33539
  const chainIdStr = String(txReq?.chainId ?? fromChain?.chainId ?? "");
33464
- const spender = txReq?.to ?? txReq?.target;
33465
33540
  const amountWei = BigInt(routeResult.route?.estimate?.fromAmount ?? "0");
33466
- if (!spender || !chainIdStr || amountWei === 0n) {
33541
+ const plannedApprovals = routeResult.route?.execution?.approvals ?? [];
33542
+ const toCheck = plannedApprovals.length ? plannedApprovals.flatMap((a) => {
33543
+ const token = a.tokenAddress ?? fromTokenAddress;
33544
+ const required = requiredApprovalAmount(
33545
+ BigInt(a.amount || "0"),
33546
+ amountWei
33547
+ );
33548
+ if (!token || !a.spender) return [];
33549
+ return [
33550
+ {
33551
+ chainId: a.chainId || chainIdStr,
33552
+ token,
33553
+ spender: a.spender,
33554
+ required
33555
+ }
33556
+ ];
33557
+ }) : (() => {
33558
+ const spender = txReq?.to ?? txReq?.target;
33559
+ if (!spender) return [];
33560
+ return [
33561
+ {
33562
+ chainId: chainIdStr,
33563
+ token: fromTokenAddress,
33564
+ spender,
33565
+ required: amountWei
33566
+ }
33567
+ ];
33568
+ })();
33569
+ if (toCheck.length === 0 || !chainIdStr || amountWei === 0n) {
33467
33570
  setState((p) => ({ ...p, allowanceStatus: "unknown" }));
33468
33571
  return;
33469
33572
  }
33470
33573
  setState((p) => ({ ...p, allowanceStatus: "checking" }));
33471
33574
  try {
33472
- const { allowance } = await getEVMAllowance({
33473
- chainId: chainIdStr,
33474
- tokenAddress: fromTokenAddress,
33475
- ownerAddress: walletAddress,
33476
- spenderAddress: spender
33477
- });
33478
- const allowanceWei = BigInt(allowance || "0");
33575
+ const results = await Promise.all(
33576
+ toCheck.map(async (c) => {
33577
+ const { allowance } = await getEVMAllowance({
33578
+ chainId: c.chainId,
33579
+ tokenAddress: c.token,
33580
+ ownerAddress: walletAddress,
33581
+ spenderAddress: c.spender
33582
+ });
33583
+ return approvalSatisfied(BigInt(allowance || "0"), c.required);
33584
+ })
33585
+ );
33479
33586
  setState((p) => ({
33480
33587
  ...p,
33481
- allowanceStatus: allowanceWei >= amountWei ? "sufficient" : "needed"
33588
+ allowanceStatus: results.every(Boolean) ? "sufficient" : "needed"
33482
33589
  }));
33483
33590
  } catch {
33484
33591
  setState((p) => ({ ...p, allowanceStatus: "needed" }));
@@ -33582,19 +33689,49 @@ function useSwapExecution(fromChain) {
33582
33689
  }
33583
33690
  }
33584
33691
  try {
33585
- if (!isNative && walletAddress && spender && chainIdStr && fromTokenAddress) {
33692
+ const plannedApprovals = routeResult.route?.execution?.approvals ?? [];
33693
+ const requiredApprovals = plannedApprovals.length ? plannedApprovals.flatMap((a, index) => {
33694
+ const token = a.tokenAddress ?? fromTokenAddress;
33695
+ const approvalSpender = a.spender;
33696
+ if (!token || !approvalSpender) return [];
33697
+ const amountWei = requiredApprovalAmount(
33698
+ BigInt(a.amount || "0"),
33699
+ fromAmountWei
33700
+ );
33701
+ return [
33702
+ {
33703
+ stepIndex: index,
33704
+ token,
33705
+ spender: approvalSpender,
33706
+ amountWei,
33707
+ chainId: a.chainId || chainIdStr
33708
+ }
33709
+ ];
33710
+ }) : spender && fromTokenAddress ? [
33711
+ {
33712
+ stepIndex: null,
33713
+ token: fromTokenAddress,
33714
+ spender,
33715
+ amountWei: fromAmountWei,
33716
+ chainId: chainIdStr
33717
+ }
33718
+ ] : [];
33719
+ const ownsApprovals = !isNative && !!walletAddress && !!chainIdStr;
33720
+ const activeAddress = ownsApprovals ? await requireActiveAddress(wallet, walletAddress) : void 0;
33721
+ for (const required of requiredApprovals) {
33722
+ if (!ownsApprovals) break;
33586
33723
  let allowanceWei = 0n;
33587
33724
  try {
33588
33725
  const { allowance } = await getEVMAllowance({
33589
- chainId: chainIdStr,
33590
- tokenAddress: fromTokenAddress,
33591
- ownerAddress: walletAddress,
33592
- spenderAddress: spender
33726
+ chainId: required.chainId,
33727
+ tokenAddress: required.token,
33728
+ ownerAddress: activeAddress,
33729
+ spenderAddress: required.spender
33593
33730
  });
33594
33731
  allowanceWei = BigInt(allowance || "0");
33595
33732
  } catch {
33596
33733
  }
33597
- if (allowanceWei < fromAmountWei) {
33734
+ if (!approvalSatisfied(allowanceWei, required.amountWei)) {
33598
33735
  setState((p) => ({ ...p, txStatus: "approving" }));
33599
33736
  if (!wallet || wallet.ecosystem !== "evm") {
33600
33737
  throw new Error("EVM wallet required for token approval");
@@ -33602,7 +33739,7 @@ function useSwapExecution(fromChain) {
33602
33739
  if (!chainIdStr || chainIdStr === "0") {
33603
33740
  throw new Error("Invalid chain ID for token approval");
33604
33741
  }
33605
- const targetChain = Number(txReq.chainId ?? fromChain?.chainId);
33742
+ const targetChain = Number(required.chainId ?? txReq.chainId);
33606
33743
  if (Number.isFinite(targetChain)) {
33607
33744
  const current = await wallet.getChainId();
33608
33745
  if (current !== targetChain) {
@@ -33614,18 +33751,18 @@ function useSwapExecution(fromChain) {
33614
33751
  }
33615
33752
  const approveAmount = maxApproval ? BigInt(
33616
33753
  "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
33617
- ) : fromAmountWei;
33754
+ ) : required.amountWei;
33618
33755
  const data = encodeFunctionData10({
33619
33756
  abi: erc20Abi2,
33620
33757
  functionName: "approve",
33621
- args: [spender, approveAmount]
33758
+ args: [required.spender, approveAmount]
33622
33759
  });
33623
33760
  let approvalHash;
33624
33761
  if (wallet.type === "eip1193") {
33625
33762
  const from = await wallet.getAddress();
33626
33763
  const params = {
33627
33764
  from,
33628
- to: fromTokenAddress,
33765
+ to: required.token,
33629
33766
  data,
33630
33767
  value: "0x0"
33631
33768
  };
@@ -33638,14 +33775,22 @@ function useSwapExecution(fromChain) {
33638
33775
  });
33639
33776
  } else {
33640
33777
  const response = await wallet.sendTransaction({
33641
- to: fromTokenAddress,
33778
+ to: required.token,
33642
33779
  data,
33643
33780
  value: 0n,
33644
33781
  chainId: Number.isFinite(targetChain) ? targetChain : void 0
33645
33782
  });
33646
33783
  approvalHash = response.hash;
33647
33784
  }
33648
- await waitForApprovalConfirmation(chainIdStr, approvalHash);
33785
+ if (required.stepIndex !== null) {
33786
+ void submitStepReceipt(
33787
+ routeResult.intentId,
33788
+ required.stepIndex,
33789
+ approvalHash
33790
+ ).catch(() => {
33791
+ });
33792
+ }
33793
+ await waitForApprovalConfirmation(required.chainId, approvalHash);
33649
33794
  setState((p) => ({
33650
33795
  ...p,
33651
33796
  txStatus: "confirming",
@@ -33653,9 +33798,13 @@ function useSwapExecution(fromChain) {
33653
33798
  }));
33654
33799
  }
33655
33800
  }
33801
+ if (ownsApprovals) {
33802
+ await requireActiveAddress(wallet, walletAddress);
33803
+ }
33656
33804
  const hash = await Trustware.sendRouteTransaction(
33657
33805
  routeResult,
33658
- numericChainId
33806
+ numericChainId,
33807
+ { approvalsEnsured: ownsApprovals }
33659
33808
  );
33660
33809
  try {
33661
33810
  await submitReceipt(routeResult.intentId, hash);
@@ -33723,6 +33872,8 @@ var init_useSwapExecution = __esm({
33723
33872
  "use client";
33724
33873
  init_core2();
33725
33874
  init_routes();
33875
+ init_http();
33876
+ init_tx();
33726
33877
  init_sdkRpc();
33727
33878
  init_chainHelpers();
33728
33879
  FAST_POLL_MS = 1500;
@@ -39687,6 +39838,7 @@ function WidgetInner({
39687
39838
  const { resolvedTheme } = useDepositUi();
39688
39839
  const { status, revalidate, errors } = useTrustware();
39689
39840
  const [showConfirmDialog, setShowConfirmDialog] = useState35(false);
39841
+ useGTM(GTM_ID);
39690
39842
  const handleCloseRequest = useCallback23(() => {
39691
39843
  if (ACTIVE_TRANSACTION_STATUSES.includes(transactionStatus)) {
39692
39844
  setShowConfirmDialog(true);
@@ -39760,6 +39912,8 @@ var init_TrustwareWidgetV2 = __esm({
39760
39912
  init_provider();
39761
39913
  init_manager();
39762
39914
  init_useTrustwareConfig();
39915
+ init_hooks();
39916
+ init_constants();
39763
39917
  init_swap();
39764
39918
  widgetContentContainerStyle = {
39765
39919
  position: "relative",