@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/index.mjs CHANGED
@@ -442,6 +442,20 @@ var init_eipWallets = __esm({
442
442
  "src/wallets/eipWallets.ts"() {
443
443
  "use strict";
444
444
  CHAIN_PARAMS = {
445
+ 1: {
446
+ chainIdHex: "0x1",
447
+ chainName: "Ethereum",
448
+ rpcUrls: ["https://eth.llamarpc.com"],
449
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
450
+ blockExplorerUrls: ["https://etherscan.io"]
451
+ },
452
+ 137: {
453
+ chainIdHex: "0x89",
454
+ chainName: "Polygon",
455
+ rpcUrls: ["https://polygon-rpc.com"],
456
+ nativeCurrency: { name: "POL", symbol: "POL", decimals: 18 },
457
+ blockExplorerUrls: ["https://polygonscan.com"]
458
+ },
445
459
  8453: {
446
460
  chainIdHex: "0x2105",
447
461
  chainName: "Base",
@@ -473,7 +487,7 @@ var init_constants = __esm({
473
487
  "src/constants.ts"() {
474
488
  "use strict";
475
489
  SDK_NAME = "@trustware/sdk";
476
- SDK_VERSION = "1.1.10-staging.0";
490
+ SDK_VERSION = "1.1.11-staging.1";
477
491
  API_ROOT = "https://bv-staging-api.trustware.io";
478
492
  GTM_ID = "GTM-TZDGNCXB";
479
493
  API_PREFIX = "/api";
@@ -517,6 +531,9 @@ async function assertOK(r) {
517
531
  }
518
532
  throw new Error(`HTTP ${r.status}: ${msg}`);
519
533
  }
534
+ function isNotFoundError(err) {
535
+ return err instanceof Error && err.message.startsWith("HTTP 404");
536
+ }
520
537
  async function validateSdkAccess() {
521
538
  const r = await fetch(`${apiBase()}/sdk/validate`, {
522
539
  method: "GET",
@@ -4514,6 +4531,19 @@ async function submitReceipt(intentId, txHash, sponsorshipRequestId, eoaAddress)
4514
4531
  const j = await r.json();
4515
4532
  return j.data;
4516
4533
  }
4534
+ async function submitStepReceipt(intentId, stepIndex, txHash) {
4535
+ const r = await rateLimitedFetch(
4536
+ `${apiBase()}/v1/route-intent/${intentId}/steps/${stepIndex}/receipt`,
4537
+ {
4538
+ method: "POST",
4539
+ headers: jsonHeaders({ "Idempotency-Key": txHash }),
4540
+ body: JSON.stringify({ txHash })
4541
+ }
4542
+ );
4543
+ await assertOK(r);
4544
+ const j = await r.json();
4545
+ return j.data;
4546
+ }
4517
4547
  async function getStatus(intentId) {
4518
4548
  const r = await rateLimitedFetch(
4519
4549
  `${apiBase()}/v1/route-intent/${intentId}/status`,
@@ -5252,18 +5282,27 @@ async function waitForTxConfirmation(chainId, txHash) {
5252
5282
  }
5253
5283
  throw new Error("Timed out waiting for approval confirmation");
5254
5284
  }
5255
- async function ensureApprovals(w, approvals, fallbackChainId) {
5285
+ function requiredApprovalAmount(planAmountWei, routeAmountWei) {
5286
+ if (planAmountWei >= UNLIMITED_APPROVAL_FLOOR && routeAmountWei !== void 0 && routeAmountWei > 0n) {
5287
+ return routeAmountWei;
5288
+ }
5289
+ return planAmountWei;
5290
+ }
5291
+ function approvalSatisfied(currentAllowance, requiredWei) {
5292
+ if (requiredWei === 0n) return currentAllowance === 0n;
5293
+ return currentAllowance >= requiredWei;
5294
+ }
5295
+ async function ensureApprovals(w, approvals, fallbackChainId, intentId, routeAmountWei) {
5256
5296
  if (!approvals || approvals.length === 0) return;
5257
5297
  const owner = await w.getAddress();
5258
- for (const approval of approvals) {
5298
+ for (const [stepIndex, approval] of approvals.entries()) {
5259
5299
  const spender = approval.spender;
5260
5300
  const tokenAddress = approval.tokenAddress;
5261
5301
  const amount = approval.amount;
5262
5302
  if (!spender || !tokenAddress || !amount) continue;
5263
5303
  const chainId = approval.chainId || String(fallbackChainId ?? "");
5264
5304
  if (!chainId) continue;
5265
- const amountWei = BigInt(amount);
5266
- if (amountWei === 0n) continue;
5305
+ const amountWei = requiredApprovalAmount(BigInt(amount), routeAmountWei);
5267
5306
  let currentAllowance = 0n;
5268
5307
  try {
5269
5308
  const { allowance } = await getEVMAllowance({
@@ -5275,7 +5314,7 @@ async function ensureApprovals(w, approvals, fallbackChainId) {
5275
5314
  currentAllowance = BigInt(allowance || "0");
5276
5315
  } catch {
5277
5316
  }
5278
- if (currentAllowance >= amountWei) continue;
5317
+ if (approvalSatisfied(currentAllowance, amountWei)) continue;
5279
5318
  const data = encodeFunctionData({
5280
5319
  abi: erc20ApproveAbi,
5281
5320
  functionName: "approve",
@@ -5287,6 +5326,10 @@ async function ensureApprovals(w, approvals, fallbackChainId) {
5287
5326
  value: 0n,
5288
5327
  chainId: Number.isFinite(Number(chainId)) ? Number(chainId) : void 0
5289
5328
  });
5329
+ if (intentId) {
5330
+ void submitStepReceipt(intentId, stepIndex, hash).catch(() => {
5331
+ });
5332
+ }
5290
5333
  await waitForTxConfirmation(chainId, hash);
5291
5334
  }
5292
5335
  }
@@ -5296,7 +5339,7 @@ function isUserRejected(e2) {
5296
5339
  const msg = String(e2?.message || e2)?.toLowerCase?.() || "";
5297
5340
  return msg.includes("user rejected") || msg.includes("user denied");
5298
5341
  }
5299
- async function sendRouteTransaction(b, fallbackChainId) {
5342
+ async function sendRouteTransaction(b, fallbackChainId, options) {
5300
5343
  const w = walletManager.wallet;
5301
5344
  if (!w) throw new Error("Trustware.wallet not configured");
5302
5345
  const txReq = b.txReq;
@@ -5323,11 +5366,13 @@ async function sendRouteTransaction(b, fallbackChainId) {
5323
5366
  }
5324
5367
  }
5325
5368
  }
5326
- if (!validatedSponsorship) {
5369
+ if (!validatedSponsorship && !options?.approvalsEnsured) {
5327
5370
  await ensureApprovals(
5328
5371
  w,
5329
5372
  b.route?.execution?.approvals,
5330
- Number.isFinite(target) ? target : void 0
5373
+ Number.isFinite(target) ? target : void 0,
5374
+ b.intentId,
5375
+ BigInt(b.route?.estimate?.fromAmount ?? "0")
5331
5376
  );
5332
5377
  }
5333
5378
  if (w.type === "eip1193") {
@@ -5426,7 +5471,7 @@ async function runTopUp(params) {
5426
5471
  }
5427
5472
  }
5428
5473
  }
5429
- var erc20ApproveAbi;
5474
+ var erc20ApproveAbi, UNLIMITED_APPROVAL_FLOOR;
5430
5475
  var init_tx = __esm({
5431
5476
  "src/core/tx.ts"() {
5432
5477
  "use strict";
@@ -5436,6 +5481,7 @@ var init_tx = __esm({
5436
5481
  erc20ApproveAbi = parseAbi([
5437
5482
  "function approve(address spender, uint256 amount) returns (bool)"
5438
5483
  ]);
5484
+ UNLIMITED_APPROVAL_FLOOR = 1n << 255n;
5439
5485
  }
5440
5486
  });
5441
5487
 
@@ -7709,6 +7755,7 @@ var init_core = __esm({
7709
7755
  buildRoute,
7710
7756
  buildDepositAddress,
7711
7757
  submitReceipt,
7758
+ submitStepReceipt,
7712
7759
  getStatus,
7713
7760
  pollStatus,
7714
7761
  getBalances,
@@ -8939,75 +8986,17 @@ var init_useTransactionSubmit = __esm({
8939
8986
 
8940
8987
  // src/hooks/useGTM.ts
8941
8988
  import { useEffect as useEffect11, useRef as useRef3, useCallback as useCallback8 } from "react";
8942
- function useGTM(gtmId) {
8943
- const isInitialized = useRef3(false);
8944
- const scriptRef = useRef3(null);
8945
- const isGA4Allowed = useCallback8(() => {
8946
- try {
8947
- return Trustware.getConfig().features.shouldAllowGA4;
8948
- } catch {
8949
- return false;
8950
- }
8951
- }, []);
8952
- useEffect11(() => {
8953
- if (!isGA4Allowed()) {
8954
- console.warn(
8955
- "useGTM: GA4 tracking is disabled or Trustware config not initialized."
8956
- );
8957
- return;
8958
- }
8959
- if (!gtmId || typeof gtmId !== "string") {
8960
- console.error(
8961
- "useGTM: A valid GTM Container ID is required (format: GTM-XXXXX)."
8962
- );
8963
- return;
8964
- }
8965
- if (isInitialized.current) return;
8966
- const alreadyLoaded = document.querySelector(
8967
- `script[src*="googletagmanager.com/gtm.js?id=${gtmId}"]`
8968
- );
8969
- if (alreadyLoaded) {
8970
- window.dataLayer = window.dataLayer || [];
8971
- isInitialized.current = true;
8972
- return;
8973
- }
8974
- window.dataLayer = window.dataLayer || [];
8975
- window.dataLayer.push({
8976
- "gtm.start": (/* @__PURE__ */ new Date()).getTime(),
8977
- event: "gtm.js"
8978
- });
8979
- const firstScript = document.getElementsByTagName("script")[0];
8980
- const script = document.createElement("script");
8981
- script.async = true;
8982
- script.src = `https://www.googletagmanager.com/gtm.js?id=${gtmId}`;
8983
- firstScript.parentNode?.insertBefore(script, firstScript);
8984
- scriptRef.current = script;
8985
- isInitialized.current = true;
8986
- return () => {
8987
- if (scriptRef.current) {
8988
- scriptRef.current.parentNode?.removeChild(scriptRef.current);
8989
- scriptRef.current = null;
8990
- }
8991
- isInitialized.current = false;
8992
- };
8993
- }, [gtmId, isGA4Allowed]);
8994
- const addNoscriptIframe = useCallback8(() => {
8995
- if (!isGA4Allowed()) return;
8996
- if (document.querySelector('iframe[src*="googletagmanager.com/ns.html"]'))
8997
- return;
8998
- const noscript = document.createElement("noscript");
8999
- const iframe = document.createElement("iframe");
9000
- iframe.src = `https://www.googletagmanager.com/ns.html?id=${gtmId}`;
9001
- iframe.height = "0";
9002
- iframe.width = "0";
9003
- iframe.style.display = "none";
9004
- iframe.style.visibility = "hidden";
9005
- noscript.appendChild(iframe);
9006
- document.body.insertBefore(noscript, document.body.firstChild);
9007
- }, [gtmId, isGA4Allowed]);
8989
+ function isGA4Allowed() {
8990
+ try {
8991
+ return Trustware.getConfig().features.shouldAllowGA4;
8992
+ } catch {
8993
+ return false;
8994
+ }
8995
+ }
8996
+ function useGTMTracker() {
9008
8997
  const trackEvent = useCallback8(
9009
8998
  (eventName, eventParams = {}) => {
9010
- if (!isInitialized.current) {
8999
+ if (!isContainerInitialized) {
9011
9000
  console.warn(
9012
9001
  "useGTM: Not initialized. Ensure a valid GTM Container ID was provided."
9013
9002
  );
@@ -9034,7 +9023,7 @@ function useGTM(gtmId) {
9034
9023
  );
9035
9024
  const setUserProperty = useCallback8(
9036
9025
  (propertyName, value) => {
9037
- if (!isInitialized.current) {
9026
+ if (!isContainerInitialized) {
9038
9027
  console.warn(
9039
9028
  "useGTM: Not initialized. Ensure a valid GTM Container ID was provided."
9040
9029
  );
@@ -9060,20 +9049,77 @@ function useGTM(gtmId) {
9060
9049
  }
9061
9050
  window.gtag(command, ...args);
9062
9051
  },
9063
- [isGA4Allowed]
9052
+ []
9064
9053
  );
9065
- return {
9066
- trackEvent,
9067
- trackPageView,
9068
- setUserProperty,
9069
- directGtag,
9070
- addNoscriptIframe
9071
- };
9054
+ return { trackEvent, trackPageView, setUserProperty, directGtag };
9055
+ }
9056
+ function useGTM(gtmId) {
9057
+ const scriptRef = useRef3(null);
9058
+ const tracker = useGTMTracker();
9059
+ useEffect11(() => {
9060
+ if (!isGA4Allowed()) {
9061
+ console.warn(
9062
+ "useGTM: GA4 tracking is disabled or Trustware config not initialized."
9063
+ );
9064
+ return;
9065
+ }
9066
+ if (!gtmId || typeof gtmId !== "string") {
9067
+ console.error(
9068
+ "useGTM: A valid GTM Container ID is required (format: GTM-XXXXX)."
9069
+ );
9070
+ return;
9071
+ }
9072
+ if (isContainerInitialized) return;
9073
+ const alreadyLoaded = document.querySelector(
9074
+ `script[src*="googletagmanager.com/gtm.js?id=${gtmId}"]`
9075
+ );
9076
+ if (alreadyLoaded) {
9077
+ window.dataLayer = window.dataLayer || [];
9078
+ isContainerInitialized = true;
9079
+ return;
9080
+ }
9081
+ window.dataLayer = window.dataLayer || [];
9082
+ window.dataLayer.push({
9083
+ "gtm.start": (/* @__PURE__ */ new Date()).getTime(),
9084
+ event: "gtm.js"
9085
+ });
9086
+ const firstScript = document.getElementsByTagName("script")[0];
9087
+ const script = document.createElement("script");
9088
+ script.async = true;
9089
+ script.src = `https://www.googletagmanager.com/gtm.js?id=${gtmId}`;
9090
+ firstScript.parentNode?.insertBefore(script, firstScript);
9091
+ scriptRef.current = script;
9092
+ isContainerInitialized = true;
9093
+ return () => {
9094
+ if (scriptRef.current) {
9095
+ scriptRef.current.parentNode?.removeChild(scriptRef.current);
9096
+ scriptRef.current = null;
9097
+ }
9098
+ isContainerInitialized = false;
9099
+ };
9100
+ }, [gtmId]);
9101
+ const addNoscriptIframe = useCallback8(() => {
9102
+ if (!isGA4Allowed()) return;
9103
+ if (document.querySelector('iframe[src*="googletagmanager.com/ns.html"]'))
9104
+ return;
9105
+ const noscript = document.createElement("noscript");
9106
+ const iframe = document.createElement("iframe");
9107
+ iframe.src = `https://www.googletagmanager.com/ns.html?id=${gtmId}`;
9108
+ iframe.height = "0";
9109
+ iframe.width = "0";
9110
+ iframe.style.display = "none";
9111
+ iframe.style.visibility = "hidden";
9112
+ noscript.appendChild(iframe);
9113
+ document.body.insertBefore(noscript, document.body.firstChild);
9114
+ }, [gtmId]);
9115
+ return { ...tracker, addNoscriptIframe };
9072
9116
  }
9117
+ var isContainerInitialized;
9073
9118
  var init_useGTM = __esm({
9074
9119
  "src/hooks/useGTM.ts"() {
9075
9120
  "use strict";
9076
9121
  init_core2();
9122
+ isContainerInitialized = false;
9077
9123
  }
9078
9124
  });
9079
9125
 
@@ -9100,7 +9146,7 @@ function useTransactionPolling() {
9100
9146
  return void 0;
9101
9147
  }
9102
9148
  })();
9103
- const { trackEvent } = useGTM(GTM_ID);
9149
+ const { trackEvent } = useGTMTracker();
9104
9150
  const [state, setState] = useState13({
9105
9151
  isPolling: false,
9106
9152
  apiStatus: null,
@@ -9200,8 +9246,21 @@ function useTransactionPolling() {
9200
9246
  pollCountRef.current += 1;
9201
9247
  const pollInterval = pollCountRef.current <= 10 ? FAST_POLL_INTERVAL_MS : NORMAL_POLL_INTERVAL_MS;
9202
9248
  pollingRef.current = setTimeout(poll, pollInterval);
9203
- } catch {
9249
+ } catch (err) {
9204
9250
  if (abortRef.current) return;
9251
+ if (isNotFoundError(err)) {
9252
+ clearPolling();
9253
+ const notFoundError = "Transaction session expired. Please try again.";
9254
+ setState((prev) => ({
9255
+ ...prev,
9256
+ isPolling: false,
9257
+ error: notFoundError
9258
+ }));
9259
+ setErrorMessage(notFoundError);
9260
+ setTransactionStatus("error");
9261
+ setCurrentStep("error");
9262
+ return;
9263
+ }
9205
9264
  const elapsed = Date.now() - startTimeRef.current;
9206
9265
  if (elapsed > POLL_TIMEOUT_MS) {
9207
9266
  clearPolling();
@@ -9337,10 +9396,10 @@ var init_useTransactionPolling = __esm({
9337
9396
  "use strict";
9338
9397
  "use client";
9339
9398
  init_routes();
9399
+ init_http();
9340
9400
  init_DepositContext();
9341
9401
  init_provider();
9342
9402
  init_core2();
9343
- init_constants();
9344
9403
  init_hooks();
9345
9404
  FAST_POLL_INTERVAL_MS = 1500;
9346
9405
  NORMAL_POLL_INTERVAL_MS = 2500;
@@ -31756,7 +31815,7 @@ function useTransactionActionModel({
31756
31815
  }) {
31757
31816
  const feeDataCacheRef = useRef13({});
31758
31817
  const { isSubmitting, submitTransaction } = useTransactionSubmit();
31759
- const { trackEvent } = useGTM(GTM_ID);
31818
+ const { trackEvent } = useGTMTracker();
31760
31819
  const destinationConfig = (() => {
31761
31820
  try {
31762
31821
  return Trustware.getConfig();
@@ -32189,7 +32248,6 @@ var init_useTransactionActionModel = __esm({
32189
32248
  init_chainHelpers();
32190
32249
  init_utils();
32191
32250
  init_hooks();
32192
- init_constants();
32193
32251
  }
32194
32252
  });
32195
32253
 
@@ -33541,6 +33599,16 @@ async function waitForApprovalConfirmation(chainId, txHash) {
33541
33599
  }
33542
33600
  throw new Error("Timed out waiting for approval confirmation");
33543
33601
  }
33602
+ async function requireActiveAddress(wallet, plannedFor) {
33603
+ if (!wallet) throw new Error("Wallet not connected. Please reconnect.");
33604
+ const active = await wallet.getAddress();
33605
+ if (active?.toLowerCase() !== plannedFor?.toLowerCase()) {
33606
+ throw new Error(
33607
+ "Wallet account changed. Please review and confirm the swap again."
33608
+ );
33609
+ }
33610
+ return active;
33611
+ }
33544
33612
  function useSwapExecution(fromChain) {
33545
33613
  const [state, setState] = useState29({
33546
33614
  txStatus: "idle",
@@ -33597,7 +33665,15 @@ function useSwapExecution(fromChain) {
33597
33665
  if (tx.status === "bridging") {
33598
33666
  setState((p) => ({ ...p, txStatus: "bridging" }));
33599
33667
  }
33600
- } catch {
33668
+ } catch (err) {
33669
+ if (abortRef.current) return;
33670
+ if (isNotFoundError(err)) {
33671
+ clearPolling();
33672
+ const msg = "Transaction session expired. Please try again.";
33673
+ setState((p) => ({ ...p, txStatus: "error", errorMessage: msg }));
33674
+ onError(msg);
33675
+ return;
33676
+ }
33601
33677
  }
33602
33678
  if (abortRef.current) return;
33603
33679
  pollCountRef.current += 1;
@@ -33623,24 +33699,55 @@ function useSwapExecution(fromChain) {
33623
33699
  }
33624
33700
  const txReq = routeResult.txReq;
33625
33701
  const chainIdStr = String(txReq?.chainId ?? fromChain?.chainId ?? "");
33626
- const spender = txReq?.to ?? txReq?.target;
33627
33702
  const amountWei = BigInt(routeResult.route?.estimate?.fromAmount ?? "0");
33628
- if (!spender || !chainIdStr || amountWei === 0n) {
33703
+ const plannedApprovals = routeResult.route?.execution?.approvals ?? [];
33704
+ const toCheck = plannedApprovals.length ? plannedApprovals.flatMap((a) => {
33705
+ const token = a.tokenAddress ?? fromTokenAddress;
33706
+ const required = requiredApprovalAmount(
33707
+ BigInt(a.amount || "0"),
33708
+ amountWei
33709
+ );
33710
+ if (!token || !a.spender) return [];
33711
+ return [
33712
+ {
33713
+ chainId: a.chainId || chainIdStr,
33714
+ token,
33715
+ spender: a.spender,
33716
+ required
33717
+ }
33718
+ ];
33719
+ }) : (() => {
33720
+ const spender = txReq?.to ?? txReq?.target;
33721
+ if (!spender) return [];
33722
+ return [
33723
+ {
33724
+ chainId: chainIdStr,
33725
+ token: fromTokenAddress,
33726
+ spender,
33727
+ required: amountWei
33728
+ }
33729
+ ];
33730
+ })();
33731
+ if (toCheck.length === 0 || !chainIdStr || amountWei === 0n) {
33629
33732
  setState((p) => ({ ...p, allowanceStatus: "unknown" }));
33630
33733
  return;
33631
33734
  }
33632
33735
  setState((p) => ({ ...p, allowanceStatus: "checking" }));
33633
33736
  try {
33634
- const { allowance } = await getEVMAllowance({
33635
- chainId: chainIdStr,
33636
- tokenAddress: fromTokenAddress,
33637
- ownerAddress: walletAddress,
33638
- spenderAddress: spender
33639
- });
33640
- const allowanceWei = BigInt(allowance || "0");
33737
+ const results = await Promise.all(
33738
+ toCheck.map(async (c) => {
33739
+ const { allowance } = await getEVMAllowance({
33740
+ chainId: c.chainId,
33741
+ tokenAddress: c.token,
33742
+ ownerAddress: walletAddress,
33743
+ spenderAddress: c.spender
33744
+ });
33745
+ return approvalSatisfied(BigInt(allowance || "0"), c.required);
33746
+ })
33747
+ );
33641
33748
  setState((p) => ({
33642
33749
  ...p,
33643
- allowanceStatus: allowanceWei >= amountWei ? "sufficient" : "needed"
33750
+ allowanceStatus: results.every(Boolean) ? "sufficient" : "needed"
33644
33751
  }));
33645
33752
  } catch {
33646
33753
  setState((p) => ({ ...p, allowanceStatus: "needed" }));
@@ -33744,19 +33851,49 @@ function useSwapExecution(fromChain) {
33744
33851
  }
33745
33852
  }
33746
33853
  try {
33747
- if (!isNative && walletAddress && spender && chainIdStr && fromTokenAddress) {
33854
+ const plannedApprovals = routeResult.route?.execution?.approvals ?? [];
33855
+ const requiredApprovals = plannedApprovals.length ? plannedApprovals.flatMap((a, index) => {
33856
+ const token = a.tokenAddress ?? fromTokenAddress;
33857
+ const approvalSpender = a.spender;
33858
+ if (!token || !approvalSpender) return [];
33859
+ const amountWei = requiredApprovalAmount(
33860
+ BigInt(a.amount || "0"),
33861
+ fromAmountWei
33862
+ );
33863
+ return [
33864
+ {
33865
+ stepIndex: index,
33866
+ token,
33867
+ spender: approvalSpender,
33868
+ amountWei,
33869
+ chainId: a.chainId || chainIdStr
33870
+ }
33871
+ ];
33872
+ }) : spender && fromTokenAddress ? [
33873
+ {
33874
+ stepIndex: null,
33875
+ token: fromTokenAddress,
33876
+ spender,
33877
+ amountWei: fromAmountWei,
33878
+ chainId: chainIdStr
33879
+ }
33880
+ ] : [];
33881
+ const ownsApprovals = !isNative && !!walletAddress && !!chainIdStr;
33882
+ const activeAddress = ownsApprovals ? await requireActiveAddress(wallet, walletAddress) : void 0;
33883
+ for (const required of requiredApprovals) {
33884
+ if (!ownsApprovals) break;
33748
33885
  let allowanceWei = 0n;
33749
33886
  try {
33750
33887
  const { allowance } = await getEVMAllowance({
33751
- chainId: chainIdStr,
33752
- tokenAddress: fromTokenAddress,
33753
- ownerAddress: walletAddress,
33754
- spenderAddress: spender
33888
+ chainId: required.chainId,
33889
+ tokenAddress: required.token,
33890
+ ownerAddress: activeAddress,
33891
+ spenderAddress: required.spender
33755
33892
  });
33756
33893
  allowanceWei = BigInt(allowance || "0");
33757
33894
  } catch {
33758
33895
  }
33759
- if (allowanceWei < fromAmountWei) {
33896
+ if (!approvalSatisfied(allowanceWei, required.amountWei)) {
33760
33897
  setState((p) => ({ ...p, txStatus: "approving" }));
33761
33898
  if (!wallet || wallet.ecosystem !== "evm") {
33762
33899
  throw new Error("EVM wallet required for token approval");
@@ -33764,7 +33901,7 @@ function useSwapExecution(fromChain) {
33764
33901
  if (!chainIdStr || chainIdStr === "0") {
33765
33902
  throw new Error("Invalid chain ID for token approval");
33766
33903
  }
33767
- const targetChain = Number(txReq.chainId ?? fromChain?.chainId);
33904
+ const targetChain = Number(required.chainId ?? txReq.chainId);
33768
33905
  if (Number.isFinite(targetChain)) {
33769
33906
  const current = await wallet.getChainId();
33770
33907
  if (current !== targetChain) {
@@ -33776,18 +33913,18 @@ function useSwapExecution(fromChain) {
33776
33913
  }
33777
33914
  const approveAmount = maxApproval ? BigInt(
33778
33915
  "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
33779
- ) : fromAmountWei;
33916
+ ) : required.amountWei;
33780
33917
  const data = encodeFunctionData10({
33781
33918
  abi: erc20Abi2,
33782
33919
  functionName: "approve",
33783
- args: [spender, approveAmount]
33920
+ args: [required.spender, approveAmount]
33784
33921
  });
33785
33922
  let approvalHash;
33786
33923
  if (wallet.type === "eip1193") {
33787
33924
  const from = await wallet.getAddress();
33788
33925
  const params = {
33789
33926
  from,
33790
- to: fromTokenAddress,
33927
+ to: required.token,
33791
33928
  data,
33792
33929
  value: "0x0"
33793
33930
  };
@@ -33800,14 +33937,22 @@ function useSwapExecution(fromChain) {
33800
33937
  });
33801
33938
  } else {
33802
33939
  const response = await wallet.sendTransaction({
33803
- to: fromTokenAddress,
33940
+ to: required.token,
33804
33941
  data,
33805
33942
  value: 0n,
33806
33943
  chainId: Number.isFinite(targetChain) ? targetChain : void 0
33807
33944
  });
33808
33945
  approvalHash = response.hash;
33809
33946
  }
33810
- await waitForApprovalConfirmation(chainIdStr, approvalHash);
33947
+ if (required.stepIndex !== null) {
33948
+ void submitStepReceipt(
33949
+ routeResult.intentId,
33950
+ required.stepIndex,
33951
+ approvalHash
33952
+ ).catch(() => {
33953
+ });
33954
+ }
33955
+ await waitForApprovalConfirmation(required.chainId, approvalHash);
33811
33956
  setState((p) => ({
33812
33957
  ...p,
33813
33958
  txStatus: "confirming",
@@ -33815,9 +33960,13 @@ function useSwapExecution(fromChain) {
33815
33960
  }));
33816
33961
  }
33817
33962
  }
33963
+ if (ownsApprovals) {
33964
+ await requireActiveAddress(wallet, walletAddress);
33965
+ }
33818
33966
  const hash = await Trustware.sendRouteTransaction(
33819
33967
  routeResult,
33820
- numericChainId
33968
+ numericChainId,
33969
+ { approvalsEnsured: ownsApprovals }
33821
33970
  );
33822
33971
  try {
33823
33972
  await submitReceipt(routeResult.intentId, hash);
@@ -33885,6 +34034,8 @@ var init_useSwapExecution = __esm({
33885
34034
  "use client";
33886
34035
  init_core2();
33887
34036
  init_routes();
34037
+ init_http();
34038
+ init_tx();
33888
34039
  init_sdkRpc();
33889
34040
  init_chainHelpers();
33890
34041
  FAST_POLL_MS = 1500;
@@ -39849,6 +40000,7 @@ function WidgetInner({
39849
40000
  const { resolvedTheme } = useDepositUi();
39850
40001
  const { status, revalidate, errors } = useTrustware();
39851
40002
  const [showConfirmDialog, setShowConfirmDialog] = useState35(false);
40003
+ useGTM(GTM_ID);
39852
40004
  const handleCloseRequest = useCallback23(() => {
39853
40005
  if (ACTIVE_TRANSACTION_STATUSES.includes(transactionStatus)) {
39854
40006
  setShowConfirmDialog(true);
@@ -39922,6 +40074,8 @@ var init_TrustwareWidgetV2 = __esm({
39922
40074
  init_provider();
39923
40075
  init_manager();
39924
40076
  init_useTrustwareConfig();
40077
+ init_hooks();
40078
+ init_constants();
39925
40079
  init_swap();
39926
40080
  widgetContentContainerStyle = {
39927
40081
  position: "relative",