@trustware/sdk-staging 1.1.9-staging.7 → 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/constants.cjs +1 -1
- package/dist/constants.mjs +1 -1
- package/dist/{core-DzqVEWwP.d.ts → core-BgYLe9Q7.d.ts} +15 -2
- package/dist/{core-gNyi5xsp.d.cts → core-fLSt4qD2.d.cts} +15 -2
- package/dist/core.cjs +318 -145
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +2 -2
- package/dist/core.d.ts +2 -2
- package/dist/core.mjs +318 -144
- package/dist/core.mjs.map +1 -1
- package/dist/index.cjs +407 -114
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.mjs +433 -140
- package/dist/index.mjs.map +1 -1
- package/dist/{manager-Dn4muk74.d.ts → manager-BY3NHAks.d.ts} +138 -2
- package/dist/{manager-DWFNyouP.d.cts → manager-DT8enQbE.d.cts} +138 -2
- package/dist/{detect-Cprq6X9o.d.ts → metadata-BPvFYMlc.d.ts} +5 -2
- package/dist/{detect-DWL4uExV.d.cts → metadata-DyxUcKHk.d.cts} +5 -2
- package/dist/smart-account.cjs +1 -1
- package/dist/smart-account.cjs.map +1 -1
- package/dist/smart-account.d.cts +247 -234
- package/dist/smart-account.d.ts +247 -234
- package/dist/smart-account.mjs +1 -1
- package/dist/smart-account.mjs.map +1 -1
- package/dist/wallet.cjs +15 -1
- package/dist/wallet.cjs.map +1 -1
- package/dist/wallet.d.cts +4 -7
- package/dist/wallet.d.ts +4 -7
- package/dist/wallet.mjs +15 -1
- package/dist/wallet.mjs.map +1 -1
- package/dist/widget.cjs +381 -113
- package/dist/widget.cjs.map +1 -1
- package/dist/widget.mjs +409 -139
- package/dist/widget.mjs.map +1 -1
- package/package.json +1 -1
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.
|
|
588
|
+
SDK_VERSION = "1.1.11-staging.1";
|
|
589
589
|
API_ROOT = "https://bv-staging-api.trustware.io";
|
|
590
590
|
GTM_ID = "GTM-TZDGNCXB";
|
|
591
591
|
API_PREFIX = "/api";
|
|
@@ -629,6 +629,9 @@ async function assertOK(r) {
|
|
|
629
629
|
}
|
|
630
630
|
throw new Error(`HTTP ${r.status}: ${msg}`);
|
|
631
631
|
}
|
|
632
|
+
function isNotFoundError(err) {
|
|
633
|
+
return err instanceof Error && err.message.startsWith("HTTP 404");
|
|
634
|
+
}
|
|
632
635
|
async function validateSdkAccess() {
|
|
633
636
|
const r = await fetch(`${apiBase()}/sdk/validate`, {
|
|
634
637
|
method: "GET",
|
|
@@ -2464,6 +2467,27 @@ var init_balances = __esm({
|
|
|
2464
2467
|
});
|
|
2465
2468
|
|
|
2466
2469
|
// src/core/routes.ts
|
|
2470
|
+
function assertValidPostHook(hooks) {
|
|
2471
|
+
const postHook = hooks?.postHook;
|
|
2472
|
+
if (!postHook) return;
|
|
2473
|
+
if (!postHook.target?.trim()) {
|
|
2474
|
+
throw new Error("hooks.postHook.target is required.");
|
|
2475
|
+
}
|
|
2476
|
+
if (!postHook.callData?.trim()) {
|
|
2477
|
+
throw new Error("hooks.postHook.callData is required.");
|
|
2478
|
+
}
|
|
2479
|
+
if (postHook.fullAmount) {
|
|
2480
|
+
if (postHook.amountInputPos === void 0) {
|
|
2481
|
+
throw new Error(
|
|
2482
|
+
"hooks.postHook.amountInputPos is required when fullAmount is true."
|
|
2483
|
+
);
|
|
2484
|
+
}
|
|
2485
|
+
} else if (!postHook.fundAmount?.trim()) {
|
|
2486
|
+
throw new Error(
|
|
2487
|
+
"hooks.postHook.fundAmount is required unless fullAmount is set."
|
|
2488
|
+
);
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2467
2491
|
function isEvmTxRequest(txReq) {
|
|
2468
2492
|
return Boolean(txReq?.data && (txReq.to || txReq.target));
|
|
2469
2493
|
}
|
|
@@ -2482,6 +2506,7 @@ async function buildRoute(body, signal) {
|
|
|
2482
2506
|
if (!addressValidation.isValid) {
|
|
2483
2507
|
throw new Error(addressValidation.error || "Invalid route addresses.");
|
|
2484
2508
|
}
|
|
2509
|
+
assertValidPostHook(body.hooks);
|
|
2485
2510
|
const cfg = TrustwareConfigStore.get();
|
|
2486
2511
|
const url = `${apiBase()}/v1/routes/route`;
|
|
2487
2512
|
const payload = {
|
|
@@ -2520,6 +2545,7 @@ async function buildRoute(body, signal) {
|
|
|
2520
2545
|
return { intentId, txReq, actions, finalExchangeRate, route, sponsorship };
|
|
2521
2546
|
}
|
|
2522
2547
|
async function buildDepositAddress(body, signal) {
|
|
2548
|
+
assertValidPostHook(body.hooks);
|
|
2523
2549
|
const cfg = TrustwareConfigStore.get();
|
|
2524
2550
|
const url = `${apiBase()}/v1/routes/deposit-address`;
|
|
2525
2551
|
const payload = {
|
|
@@ -2578,6 +2604,19 @@ async function submitReceipt(intentId, txHash, sponsorshipRequestId, eoaAddress)
|
|
|
2578
2604
|
const j = await r.json();
|
|
2579
2605
|
return j.data;
|
|
2580
2606
|
}
|
|
2607
|
+
async function submitStepReceipt(intentId, stepIndex, txHash) {
|
|
2608
|
+
const r = await rateLimitedFetch(
|
|
2609
|
+
`${apiBase()}/v1/route-intent/${intentId}/steps/${stepIndex}/receipt`,
|
|
2610
|
+
{
|
|
2611
|
+
method: "POST",
|
|
2612
|
+
headers: jsonHeaders({ "Idempotency-Key": txHash }),
|
|
2613
|
+
body: JSON.stringify({ txHash })
|
|
2614
|
+
}
|
|
2615
|
+
);
|
|
2616
|
+
await assertOK(r);
|
|
2617
|
+
const j = await r.json();
|
|
2618
|
+
return j.data;
|
|
2619
|
+
}
|
|
2581
2620
|
async function getStatus(intentId) {
|
|
2582
2621
|
const r = await rateLimitedFetch(
|
|
2583
2622
|
`${apiBase()}/v1/route-intent/${intentId}/status`,
|
|
@@ -5302,75 +5341,17 @@ var init_useTransactionSubmit = __esm({
|
|
|
5302
5341
|
});
|
|
5303
5342
|
|
|
5304
5343
|
// src/hooks/useGTM.ts
|
|
5305
|
-
function
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
}
|
|
5314
|
-
}, []);
|
|
5315
|
-
(0, import_react7.useEffect)(() => {
|
|
5316
|
-
if (!isGA4Allowed()) {
|
|
5317
|
-
console.warn(
|
|
5318
|
-
"useGTM: GA4 tracking is disabled or Trustware config not initialized."
|
|
5319
|
-
);
|
|
5320
|
-
return;
|
|
5321
|
-
}
|
|
5322
|
-
if (!gtmId || typeof gtmId !== "string") {
|
|
5323
|
-
console.error(
|
|
5324
|
-
"useGTM: A valid GTM Container ID is required (format: GTM-XXXXX)."
|
|
5325
|
-
);
|
|
5326
|
-
return;
|
|
5327
|
-
}
|
|
5328
|
-
if (isInitialized.current) return;
|
|
5329
|
-
const alreadyLoaded = document.querySelector(
|
|
5330
|
-
`script[src*="googletagmanager.com/gtm.js?id=${gtmId}"]`
|
|
5331
|
-
);
|
|
5332
|
-
if (alreadyLoaded) {
|
|
5333
|
-
window.dataLayer = window.dataLayer || [];
|
|
5334
|
-
isInitialized.current = true;
|
|
5335
|
-
return;
|
|
5336
|
-
}
|
|
5337
|
-
window.dataLayer = window.dataLayer || [];
|
|
5338
|
-
window.dataLayer.push({
|
|
5339
|
-
"gtm.start": (/* @__PURE__ */ new Date()).getTime(),
|
|
5340
|
-
event: "gtm.js"
|
|
5341
|
-
});
|
|
5342
|
-
const firstScript = document.getElementsByTagName("script")[0];
|
|
5343
|
-
const script = document.createElement("script");
|
|
5344
|
-
script.async = true;
|
|
5345
|
-
script.src = `https://www.googletagmanager.com/gtm.js?id=${gtmId}`;
|
|
5346
|
-
firstScript.parentNode?.insertBefore(script, firstScript);
|
|
5347
|
-
scriptRef.current = script;
|
|
5348
|
-
isInitialized.current = true;
|
|
5349
|
-
return () => {
|
|
5350
|
-
if (scriptRef.current) {
|
|
5351
|
-
scriptRef.current.parentNode?.removeChild(scriptRef.current);
|
|
5352
|
-
scriptRef.current = null;
|
|
5353
|
-
}
|
|
5354
|
-
isInitialized.current = false;
|
|
5355
|
-
};
|
|
5356
|
-
}, [gtmId, isGA4Allowed]);
|
|
5357
|
-
const addNoscriptIframe = (0, import_react7.useCallback)(() => {
|
|
5358
|
-
if (!isGA4Allowed()) return;
|
|
5359
|
-
if (document.querySelector('iframe[src*="googletagmanager.com/ns.html"]'))
|
|
5360
|
-
return;
|
|
5361
|
-
const noscript = document.createElement("noscript");
|
|
5362
|
-
const iframe = document.createElement("iframe");
|
|
5363
|
-
iframe.src = `https://www.googletagmanager.com/ns.html?id=${gtmId}`;
|
|
5364
|
-
iframe.height = "0";
|
|
5365
|
-
iframe.width = "0";
|
|
5366
|
-
iframe.style.display = "none";
|
|
5367
|
-
iframe.style.visibility = "hidden";
|
|
5368
|
-
noscript.appendChild(iframe);
|
|
5369
|
-
document.body.insertBefore(noscript, document.body.firstChild);
|
|
5370
|
-
}, [gtmId, isGA4Allowed]);
|
|
5344
|
+
function isGA4Allowed() {
|
|
5345
|
+
try {
|
|
5346
|
+
return Trustware.getConfig().features.shouldAllowGA4;
|
|
5347
|
+
} catch {
|
|
5348
|
+
return false;
|
|
5349
|
+
}
|
|
5350
|
+
}
|
|
5351
|
+
function useGTMTracker() {
|
|
5371
5352
|
const trackEvent = (0, import_react7.useCallback)(
|
|
5372
5353
|
(eventName, eventParams = {}) => {
|
|
5373
|
-
if (!
|
|
5354
|
+
if (!isContainerInitialized) {
|
|
5374
5355
|
console.warn(
|
|
5375
5356
|
"useGTM: Not initialized. Ensure a valid GTM Container ID was provided."
|
|
5376
5357
|
);
|
|
@@ -5397,7 +5378,7 @@ function useGTM(gtmId) {
|
|
|
5397
5378
|
);
|
|
5398
5379
|
const setUserProperty = (0, import_react7.useCallback)(
|
|
5399
5380
|
(propertyName, value) => {
|
|
5400
|
-
if (!
|
|
5381
|
+
if (!isContainerInitialized) {
|
|
5401
5382
|
console.warn(
|
|
5402
5383
|
"useGTM: Not initialized. Ensure a valid GTM Container ID was provided."
|
|
5403
5384
|
);
|
|
@@ -5423,22 +5404,78 @@ function useGTM(gtmId) {
|
|
|
5423
5404
|
}
|
|
5424
5405
|
window.gtag(command, ...args);
|
|
5425
5406
|
},
|
|
5426
|
-
[
|
|
5407
|
+
[]
|
|
5427
5408
|
);
|
|
5428
|
-
return {
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5409
|
+
return { trackEvent, trackPageView, setUserProperty, directGtag };
|
|
5410
|
+
}
|
|
5411
|
+
function useGTM(gtmId) {
|
|
5412
|
+
const scriptRef = (0, import_react7.useRef)(null);
|
|
5413
|
+
const tracker = useGTMTracker();
|
|
5414
|
+
(0, import_react7.useEffect)(() => {
|
|
5415
|
+
if (!isGA4Allowed()) {
|
|
5416
|
+
console.warn(
|
|
5417
|
+
"useGTM: GA4 tracking is disabled or Trustware config not initialized."
|
|
5418
|
+
);
|
|
5419
|
+
return;
|
|
5420
|
+
}
|
|
5421
|
+
if (!gtmId || typeof gtmId !== "string") {
|
|
5422
|
+
console.error(
|
|
5423
|
+
"useGTM: A valid GTM Container ID is required (format: GTM-XXXXX)."
|
|
5424
|
+
);
|
|
5425
|
+
return;
|
|
5426
|
+
}
|
|
5427
|
+
if (isContainerInitialized) return;
|
|
5428
|
+
const alreadyLoaded = document.querySelector(
|
|
5429
|
+
`script[src*="googletagmanager.com/gtm.js?id=${gtmId}"]`
|
|
5430
|
+
);
|
|
5431
|
+
if (alreadyLoaded) {
|
|
5432
|
+
window.dataLayer = window.dataLayer || [];
|
|
5433
|
+
isContainerInitialized = true;
|
|
5434
|
+
return;
|
|
5435
|
+
}
|
|
5436
|
+
window.dataLayer = window.dataLayer || [];
|
|
5437
|
+
window.dataLayer.push({
|
|
5438
|
+
"gtm.start": (/* @__PURE__ */ new Date()).getTime(),
|
|
5439
|
+
event: "gtm.js"
|
|
5440
|
+
});
|
|
5441
|
+
const firstScript = document.getElementsByTagName("script")[0];
|
|
5442
|
+
const script = document.createElement("script");
|
|
5443
|
+
script.async = true;
|
|
5444
|
+
script.src = `https://www.googletagmanager.com/gtm.js?id=${gtmId}`;
|
|
5445
|
+
firstScript.parentNode?.insertBefore(script, firstScript);
|
|
5446
|
+
scriptRef.current = script;
|
|
5447
|
+
isContainerInitialized = true;
|
|
5448
|
+
return () => {
|
|
5449
|
+
if (scriptRef.current) {
|
|
5450
|
+
scriptRef.current.parentNode?.removeChild(scriptRef.current);
|
|
5451
|
+
scriptRef.current = null;
|
|
5452
|
+
}
|
|
5453
|
+
isContainerInitialized = false;
|
|
5454
|
+
};
|
|
5455
|
+
}, [gtmId]);
|
|
5456
|
+
const addNoscriptIframe = (0, import_react7.useCallback)(() => {
|
|
5457
|
+
if (!isGA4Allowed()) return;
|
|
5458
|
+
if (document.querySelector('iframe[src*="googletagmanager.com/ns.html"]'))
|
|
5459
|
+
return;
|
|
5460
|
+
const noscript = document.createElement("noscript");
|
|
5461
|
+
const iframe = document.createElement("iframe");
|
|
5462
|
+
iframe.src = `https://www.googletagmanager.com/ns.html?id=${gtmId}`;
|
|
5463
|
+
iframe.height = "0";
|
|
5464
|
+
iframe.width = "0";
|
|
5465
|
+
iframe.style.display = "none";
|
|
5466
|
+
iframe.style.visibility = "hidden";
|
|
5467
|
+
noscript.appendChild(iframe);
|
|
5468
|
+
document.body.insertBefore(noscript, document.body.firstChild);
|
|
5469
|
+
}, [gtmId]);
|
|
5470
|
+
return { ...tracker, addNoscriptIframe };
|
|
5435
5471
|
}
|
|
5436
|
-
var import_react7;
|
|
5472
|
+
var import_react7, isContainerInitialized;
|
|
5437
5473
|
var init_useGTM = __esm({
|
|
5438
5474
|
"src/hooks/useGTM.ts"() {
|
|
5439
5475
|
"use strict";
|
|
5440
5476
|
import_react7 = require("react");
|
|
5441
5477
|
init_core2();
|
|
5478
|
+
isContainerInitialized = false;
|
|
5442
5479
|
}
|
|
5443
5480
|
});
|
|
5444
5481
|
|
|
@@ -5464,7 +5501,7 @@ function useTransactionPolling() {
|
|
|
5464
5501
|
return void 0;
|
|
5465
5502
|
}
|
|
5466
5503
|
})();
|
|
5467
|
-
const { trackEvent } =
|
|
5504
|
+
const { trackEvent } = useGTMTracker();
|
|
5468
5505
|
const [state, setState] = (0, import_react8.useState)({
|
|
5469
5506
|
isPolling: false,
|
|
5470
5507
|
apiStatus: null,
|
|
@@ -5564,8 +5601,21 @@ function useTransactionPolling() {
|
|
|
5564
5601
|
pollCountRef.current += 1;
|
|
5565
5602
|
const pollInterval = pollCountRef.current <= 10 ? FAST_POLL_INTERVAL_MS : NORMAL_POLL_INTERVAL_MS;
|
|
5566
5603
|
pollingRef.current = setTimeout(poll, pollInterval);
|
|
5567
|
-
} catch {
|
|
5604
|
+
} catch (err) {
|
|
5568
5605
|
if (abortRef.current) return;
|
|
5606
|
+
if (isNotFoundError(err)) {
|
|
5607
|
+
clearPolling();
|
|
5608
|
+
const notFoundError = "Transaction session expired. Please try again.";
|
|
5609
|
+
setState((prev) => ({
|
|
5610
|
+
...prev,
|
|
5611
|
+
isPolling: false,
|
|
5612
|
+
error: notFoundError
|
|
5613
|
+
}));
|
|
5614
|
+
setErrorMessage(notFoundError);
|
|
5615
|
+
setTransactionStatus("error");
|
|
5616
|
+
setCurrentStep("error");
|
|
5617
|
+
return;
|
|
5618
|
+
}
|
|
5569
5619
|
const elapsed = Date.now() - startTimeRef.current;
|
|
5570
5620
|
if (elapsed > POLL_TIMEOUT_MS) {
|
|
5571
5621
|
clearPolling();
|
|
@@ -5702,10 +5752,10 @@ var init_useTransactionPolling = __esm({
|
|
|
5702
5752
|
"use client";
|
|
5703
5753
|
import_react8 = require("react");
|
|
5704
5754
|
init_routes();
|
|
5755
|
+
init_http();
|
|
5705
5756
|
init_DepositContext();
|
|
5706
5757
|
init_provider();
|
|
5707
5758
|
init_core2();
|
|
5708
|
-
init_constants();
|
|
5709
5759
|
init_hooks();
|
|
5710
5760
|
FAST_POLL_INTERVAL_MS = 1500;
|
|
5711
5761
|
NORMAL_POLL_INTERVAL_MS = 2500;
|
|
@@ -5787,6 +5837,20 @@ var init_eipWallets = __esm({
|
|
|
5787
5837
|
"src/wallets/eipWallets.ts"() {
|
|
5788
5838
|
"use strict";
|
|
5789
5839
|
CHAIN_PARAMS = {
|
|
5840
|
+
1: {
|
|
5841
|
+
chainIdHex: "0x1",
|
|
5842
|
+
chainName: "Ethereum",
|
|
5843
|
+
rpcUrls: ["https://eth.llamarpc.com"],
|
|
5844
|
+
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
|
|
5845
|
+
blockExplorerUrls: ["https://etherscan.io"]
|
|
5846
|
+
},
|
|
5847
|
+
137: {
|
|
5848
|
+
chainIdHex: "0x89",
|
|
5849
|
+
chainName: "Polygon",
|
|
5850
|
+
rpcUrls: ["https://polygon-rpc.com"],
|
|
5851
|
+
nativeCurrency: { name: "POL", symbol: "POL", decimals: 18 },
|
|
5852
|
+
blockExplorerUrls: ["https://polygonscan.com"]
|
|
5853
|
+
},
|
|
5790
5854
|
8453: {
|
|
5791
5855
|
chainIdHex: "0x2105",
|
|
5792
5856
|
chainName: "Base",
|
|
@@ -9024,13 +9088,107 @@ function backendChainId(chain, fallback) {
|
|
|
9024
9088
|
const preferred = chain?.networkIdentifier ?? chain?.chainId ?? chain?.id;
|
|
9025
9089
|
return String(preferred ?? fallback ?? "");
|
|
9026
9090
|
}
|
|
9091
|
+
function sleep2(ms) {
|
|
9092
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
9093
|
+
}
|
|
9094
|
+
async function sendEvmTx(w, tx) {
|
|
9095
|
+
if (w.type === "eip1193") {
|
|
9096
|
+
const from = await w.getAddress();
|
|
9097
|
+
const params = {
|
|
9098
|
+
from,
|
|
9099
|
+
to: tx.to,
|
|
9100
|
+
data: tx.data,
|
|
9101
|
+
value: tx.value ? `0x${tx.value.toString(16)}` : "0x0"
|
|
9102
|
+
};
|
|
9103
|
+
if (tx.chainId !== void 0) {
|
|
9104
|
+
params.chainId = `0x${tx.chainId.toString(16)}`;
|
|
9105
|
+
}
|
|
9106
|
+
const hash = await w.request({
|
|
9107
|
+
method: "eth_sendTransaction",
|
|
9108
|
+
params: [params]
|
|
9109
|
+
});
|
|
9110
|
+
return hash;
|
|
9111
|
+
}
|
|
9112
|
+
const response = await w.sendTransaction({
|
|
9113
|
+
to: tx.to,
|
|
9114
|
+
data: tx.data,
|
|
9115
|
+
value: tx.value,
|
|
9116
|
+
chainId: tx.chainId
|
|
9117
|
+
});
|
|
9118
|
+
return response.hash;
|
|
9119
|
+
}
|
|
9120
|
+
async function waitForTxConfirmation(chainId, txHash) {
|
|
9121
|
+
const timeoutMs = 12e4;
|
|
9122
|
+
const intervalMs = 2e3;
|
|
9123
|
+
const started = Date.now();
|
|
9124
|
+
while (Date.now() - started < timeoutMs) {
|
|
9125
|
+
const status = await getEVMTxStatus({ chainId, txHash });
|
|
9126
|
+
if (status.status === "success") return;
|
|
9127
|
+
if (status.status === "reverted") {
|
|
9128
|
+
throw new Error("Approval transaction reverted");
|
|
9129
|
+
}
|
|
9130
|
+
await sleep2(intervalMs);
|
|
9131
|
+
}
|
|
9132
|
+
throw new Error("Timed out waiting for approval confirmation");
|
|
9133
|
+
}
|
|
9134
|
+
function requiredApprovalAmount(planAmountWei, routeAmountWei) {
|
|
9135
|
+
if (planAmountWei >= UNLIMITED_APPROVAL_FLOOR && routeAmountWei !== void 0 && routeAmountWei > 0n) {
|
|
9136
|
+
return routeAmountWei;
|
|
9137
|
+
}
|
|
9138
|
+
return planAmountWei;
|
|
9139
|
+
}
|
|
9140
|
+
function approvalSatisfied(currentAllowance, requiredWei) {
|
|
9141
|
+
if (requiredWei === 0n) return currentAllowance === 0n;
|
|
9142
|
+
return currentAllowance >= requiredWei;
|
|
9143
|
+
}
|
|
9144
|
+
async function ensureApprovals(w, approvals, fallbackChainId, intentId, routeAmountWei) {
|
|
9145
|
+
if (!approvals || approvals.length === 0) return;
|
|
9146
|
+
const owner = await w.getAddress();
|
|
9147
|
+
for (const [stepIndex, approval] of approvals.entries()) {
|
|
9148
|
+
const spender = approval.spender;
|
|
9149
|
+
const tokenAddress = approval.tokenAddress;
|
|
9150
|
+
const amount = approval.amount;
|
|
9151
|
+
if (!spender || !tokenAddress || !amount) continue;
|
|
9152
|
+
const chainId = approval.chainId || String(fallbackChainId ?? "");
|
|
9153
|
+
if (!chainId) continue;
|
|
9154
|
+
const amountWei = requiredApprovalAmount(BigInt(amount), routeAmountWei);
|
|
9155
|
+
let currentAllowance = 0n;
|
|
9156
|
+
try {
|
|
9157
|
+
const { allowance } = await getEVMAllowance({
|
|
9158
|
+
chainId,
|
|
9159
|
+
tokenAddress,
|
|
9160
|
+
ownerAddress: owner,
|
|
9161
|
+
spenderAddress: spender
|
|
9162
|
+
});
|
|
9163
|
+
currentAllowance = BigInt(allowance || "0");
|
|
9164
|
+
} catch {
|
|
9165
|
+
}
|
|
9166
|
+
if (approvalSatisfied(currentAllowance, amountWei)) continue;
|
|
9167
|
+
const data = (0, import_viem2.encodeFunctionData)({
|
|
9168
|
+
abi: erc20ApproveAbi,
|
|
9169
|
+
functionName: "approve",
|
|
9170
|
+
args: [spender, amountWei]
|
|
9171
|
+
});
|
|
9172
|
+
const hash = await sendEvmTx(w, {
|
|
9173
|
+
to: tokenAddress,
|
|
9174
|
+
data,
|
|
9175
|
+
value: 0n,
|
|
9176
|
+
chainId: Number.isFinite(Number(chainId)) ? Number(chainId) : void 0
|
|
9177
|
+
});
|
|
9178
|
+
if (intentId) {
|
|
9179
|
+
void submitStepReceipt(intentId, stepIndex, hash).catch(() => {
|
|
9180
|
+
});
|
|
9181
|
+
}
|
|
9182
|
+
await waitForTxConfirmation(chainId, hash);
|
|
9183
|
+
}
|
|
9184
|
+
}
|
|
9027
9185
|
function isUserRejected(e2) {
|
|
9028
9186
|
const code = e2?.code ?? e2?.data?.code;
|
|
9029
9187
|
if (code === 4001) return true;
|
|
9030
9188
|
const msg = String(e2?.message || e2)?.toLowerCase?.() || "";
|
|
9031
9189
|
return msg.includes("user rejected") || msg.includes("user denied");
|
|
9032
9190
|
}
|
|
9033
|
-
async function sendRouteTransaction(b, fallbackChainId) {
|
|
9191
|
+
async function sendRouteTransaction(b, fallbackChainId, options) {
|
|
9034
9192
|
const w = walletManager.wallet;
|
|
9035
9193
|
if (!w) throw new Error("Trustware.wallet not configured");
|
|
9036
9194
|
const txReq = b.txReq;
|
|
@@ -9057,6 +9215,15 @@ async function sendRouteTransaction(b, fallbackChainId) {
|
|
|
9057
9215
|
}
|
|
9058
9216
|
}
|
|
9059
9217
|
}
|
|
9218
|
+
if (!validatedSponsorship && !options?.approvalsEnsured) {
|
|
9219
|
+
await ensureApprovals(
|
|
9220
|
+
w,
|
|
9221
|
+
b.route?.execution?.approvals,
|
|
9222
|
+
Number.isFinite(target) ? target : void 0,
|
|
9223
|
+
b.intentId,
|
|
9224
|
+
BigInt(b.route?.estimate?.fromAmount ?? "0")
|
|
9225
|
+
);
|
|
9226
|
+
}
|
|
9060
9227
|
if (w.type === "eip1193") {
|
|
9061
9228
|
const from = await w.getAddress();
|
|
9062
9229
|
const hexValue = value ? `0x${value.toString(16)}` : "0x0";
|
|
@@ -9153,13 +9320,18 @@ async function runTopUp(params) {
|
|
|
9153
9320
|
}
|
|
9154
9321
|
}
|
|
9155
9322
|
}
|
|
9156
|
-
var import_viem2;
|
|
9323
|
+
var import_viem2, erc20ApproveAbi, UNLIMITED_APPROVAL_FLOOR;
|
|
9157
9324
|
var init_tx = __esm({
|
|
9158
9325
|
"src/core/tx.ts"() {
|
|
9159
9326
|
"use strict";
|
|
9160
9327
|
init_wallets();
|
|
9161
9328
|
init_routes();
|
|
9329
|
+
init_sdkRpc();
|
|
9162
9330
|
import_viem2 = require("viem");
|
|
9331
|
+
erc20ApproveAbi = (0, import_viem2.parseAbi)([
|
|
9332
|
+
"function approve(address spender, uint256 amount) returns (bool)"
|
|
9333
|
+
]);
|
|
9334
|
+
UNLIMITED_APPROVAL_FLOOR = 1n << 255n;
|
|
9163
9335
|
}
|
|
9164
9336
|
});
|
|
9165
9337
|
|
|
@@ -9305,6 +9477,7 @@ var init_core = __esm({
|
|
|
9305
9477
|
buildRoute,
|
|
9306
9478
|
buildDepositAddress,
|
|
9307
9479
|
submitReceipt,
|
|
9480
|
+
submitStepReceipt,
|
|
9308
9481
|
getStatus,
|
|
9309
9482
|
pollStatus,
|
|
9310
9483
|
getBalances,
|
|
@@ -31517,7 +31690,7 @@ function normalizeTokenAddressForCompare(chain, addr) {
|
|
|
31517
31690
|
if (chainType === "solana") return value;
|
|
31518
31691
|
return value.toLowerCase();
|
|
31519
31692
|
}
|
|
31520
|
-
function
|
|
31693
|
+
function sleep3(ms) {
|
|
31521
31694
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
31522
31695
|
}
|
|
31523
31696
|
function useTransactionActionModel({
|
|
@@ -31533,7 +31706,7 @@ function useTransactionActionModel({
|
|
|
31533
31706
|
}) {
|
|
31534
31707
|
const feeDataCacheRef = (0, import_react37.useRef)({});
|
|
31535
31708
|
const { isSubmitting, submitTransaction } = useTransactionSubmit();
|
|
31536
|
-
const { trackEvent } =
|
|
31709
|
+
const { trackEvent } = useGTMTracker();
|
|
31537
31710
|
const destinationConfig = (() => {
|
|
31538
31711
|
try {
|
|
31539
31712
|
return Trustware.getConfig();
|
|
@@ -31635,7 +31808,7 @@ function useTransactionActionModel({
|
|
|
31635
31808
|
if (status.status === "reverted") {
|
|
31636
31809
|
throw new Error("Approval transaction reverted");
|
|
31637
31810
|
}
|
|
31638
|
-
await
|
|
31811
|
+
await sleep3(intervalMs);
|
|
31639
31812
|
}
|
|
31640
31813
|
throw new Error("Timed out waiting for approval confirmation");
|
|
31641
31814
|
},
|
|
@@ -31969,7 +32142,6 @@ var init_useTransactionActionModel = __esm({
|
|
|
31969
32142
|
init_chainHelpers();
|
|
31970
32143
|
init_utils2();
|
|
31971
32144
|
init_hooks();
|
|
31972
|
-
init_constants();
|
|
31973
32145
|
}
|
|
31974
32146
|
});
|
|
31975
32147
|
|
|
@@ -33300,7 +33472,7 @@ function normalizeTx(raw) {
|
|
|
33300
33472
|
toChainTxUrl: r.toChainTxUrl || r.to_chain_tx_url || void 0
|
|
33301
33473
|
};
|
|
33302
33474
|
}
|
|
33303
|
-
function
|
|
33475
|
+
function sleep4(ms) {
|
|
33304
33476
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
33305
33477
|
}
|
|
33306
33478
|
function isUserRejection(err) {
|
|
@@ -33318,10 +33490,20 @@ async function waitForApprovalConfirmation(chainId, txHash) {
|
|
|
33318
33490
|
if (status.status === "success") return;
|
|
33319
33491
|
if (status.status === "reverted")
|
|
33320
33492
|
throw new Error("Approval transaction reverted");
|
|
33321
|
-
await
|
|
33493
|
+
await sleep4(2e3);
|
|
33322
33494
|
}
|
|
33323
33495
|
throw new Error("Timed out waiting for approval confirmation");
|
|
33324
33496
|
}
|
|
33497
|
+
async function requireActiveAddress(wallet, plannedFor) {
|
|
33498
|
+
if (!wallet) throw new Error("Wallet not connected. Please reconnect.");
|
|
33499
|
+
const active = await wallet.getAddress();
|
|
33500
|
+
if (active?.toLowerCase() !== plannedFor?.toLowerCase()) {
|
|
33501
|
+
throw new Error(
|
|
33502
|
+
"Wallet account changed. Please review and confirm the swap again."
|
|
33503
|
+
);
|
|
33504
|
+
}
|
|
33505
|
+
return active;
|
|
33506
|
+
}
|
|
33325
33507
|
function useSwapExecution(fromChain) {
|
|
33326
33508
|
const [state, setState] = (0, import_react45.useState)({
|
|
33327
33509
|
txStatus: "idle",
|
|
@@ -33378,7 +33560,15 @@ function useSwapExecution(fromChain) {
|
|
|
33378
33560
|
if (tx.status === "bridging") {
|
|
33379
33561
|
setState((p) => ({ ...p, txStatus: "bridging" }));
|
|
33380
33562
|
}
|
|
33381
|
-
} catch {
|
|
33563
|
+
} catch (err) {
|
|
33564
|
+
if (abortRef.current) return;
|
|
33565
|
+
if (isNotFoundError(err)) {
|
|
33566
|
+
clearPolling();
|
|
33567
|
+
const msg = "Transaction session expired. Please try again.";
|
|
33568
|
+
setState((p) => ({ ...p, txStatus: "error", errorMessage: msg }));
|
|
33569
|
+
onError(msg);
|
|
33570
|
+
return;
|
|
33571
|
+
}
|
|
33382
33572
|
}
|
|
33383
33573
|
if (abortRef.current) return;
|
|
33384
33574
|
pollCountRef.current += 1;
|
|
@@ -33404,24 +33594,55 @@ function useSwapExecution(fromChain) {
|
|
|
33404
33594
|
}
|
|
33405
33595
|
const txReq = routeResult.txReq;
|
|
33406
33596
|
const chainIdStr = String(txReq?.chainId ?? fromChain?.chainId ?? "");
|
|
33407
|
-
const spender = txReq?.to ?? txReq?.target;
|
|
33408
33597
|
const amountWei = BigInt(routeResult.route?.estimate?.fromAmount ?? "0");
|
|
33409
|
-
|
|
33598
|
+
const plannedApprovals = routeResult.route?.execution?.approvals ?? [];
|
|
33599
|
+
const toCheck = plannedApprovals.length ? plannedApprovals.flatMap((a) => {
|
|
33600
|
+
const token = a.tokenAddress ?? fromTokenAddress;
|
|
33601
|
+
const required = requiredApprovalAmount(
|
|
33602
|
+
BigInt(a.amount || "0"),
|
|
33603
|
+
amountWei
|
|
33604
|
+
);
|
|
33605
|
+
if (!token || !a.spender) return [];
|
|
33606
|
+
return [
|
|
33607
|
+
{
|
|
33608
|
+
chainId: a.chainId || chainIdStr,
|
|
33609
|
+
token,
|
|
33610
|
+
spender: a.spender,
|
|
33611
|
+
required
|
|
33612
|
+
}
|
|
33613
|
+
];
|
|
33614
|
+
}) : (() => {
|
|
33615
|
+
const spender = txReq?.to ?? txReq?.target;
|
|
33616
|
+
if (!spender) return [];
|
|
33617
|
+
return [
|
|
33618
|
+
{
|
|
33619
|
+
chainId: chainIdStr,
|
|
33620
|
+
token: fromTokenAddress,
|
|
33621
|
+
spender,
|
|
33622
|
+
required: amountWei
|
|
33623
|
+
}
|
|
33624
|
+
];
|
|
33625
|
+
})();
|
|
33626
|
+
if (toCheck.length === 0 || !chainIdStr || amountWei === 0n) {
|
|
33410
33627
|
setState((p) => ({ ...p, allowanceStatus: "unknown" }));
|
|
33411
33628
|
return;
|
|
33412
33629
|
}
|
|
33413
33630
|
setState((p) => ({ ...p, allowanceStatus: "checking" }));
|
|
33414
33631
|
try {
|
|
33415
|
-
const
|
|
33416
|
-
|
|
33417
|
-
|
|
33418
|
-
|
|
33419
|
-
|
|
33420
|
-
|
|
33421
|
-
|
|
33632
|
+
const results = await Promise.all(
|
|
33633
|
+
toCheck.map(async (c) => {
|
|
33634
|
+
const { allowance } = await getEVMAllowance({
|
|
33635
|
+
chainId: c.chainId,
|
|
33636
|
+
tokenAddress: c.token,
|
|
33637
|
+
ownerAddress: walletAddress,
|
|
33638
|
+
spenderAddress: c.spender
|
|
33639
|
+
});
|
|
33640
|
+
return approvalSatisfied(BigInt(allowance || "0"), c.required);
|
|
33641
|
+
})
|
|
33642
|
+
);
|
|
33422
33643
|
setState((p) => ({
|
|
33423
33644
|
...p,
|
|
33424
|
-
allowanceStatus:
|
|
33645
|
+
allowanceStatus: results.every(Boolean) ? "sufficient" : "needed"
|
|
33425
33646
|
}));
|
|
33426
33647
|
} catch {
|
|
33427
33648
|
setState((p) => ({ ...p, allowanceStatus: "needed" }));
|
|
@@ -33525,19 +33746,49 @@ function useSwapExecution(fromChain) {
|
|
|
33525
33746
|
}
|
|
33526
33747
|
}
|
|
33527
33748
|
try {
|
|
33528
|
-
|
|
33749
|
+
const plannedApprovals = routeResult.route?.execution?.approvals ?? [];
|
|
33750
|
+
const requiredApprovals = plannedApprovals.length ? plannedApprovals.flatMap((a, index) => {
|
|
33751
|
+
const token = a.tokenAddress ?? fromTokenAddress;
|
|
33752
|
+
const approvalSpender = a.spender;
|
|
33753
|
+
if (!token || !approvalSpender) return [];
|
|
33754
|
+
const amountWei = requiredApprovalAmount(
|
|
33755
|
+
BigInt(a.amount || "0"),
|
|
33756
|
+
fromAmountWei
|
|
33757
|
+
);
|
|
33758
|
+
return [
|
|
33759
|
+
{
|
|
33760
|
+
stepIndex: index,
|
|
33761
|
+
token,
|
|
33762
|
+
spender: approvalSpender,
|
|
33763
|
+
amountWei,
|
|
33764
|
+
chainId: a.chainId || chainIdStr
|
|
33765
|
+
}
|
|
33766
|
+
];
|
|
33767
|
+
}) : spender && fromTokenAddress ? [
|
|
33768
|
+
{
|
|
33769
|
+
stepIndex: null,
|
|
33770
|
+
token: fromTokenAddress,
|
|
33771
|
+
spender,
|
|
33772
|
+
amountWei: fromAmountWei,
|
|
33773
|
+
chainId: chainIdStr
|
|
33774
|
+
}
|
|
33775
|
+
] : [];
|
|
33776
|
+
const ownsApprovals = !isNative && !!walletAddress && !!chainIdStr;
|
|
33777
|
+
const activeAddress = ownsApprovals ? await requireActiveAddress(wallet, walletAddress) : void 0;
|
|
33778
|
+
for (const required of requiredApprovals) {
|
|
33779
|
+
if (!ownsApprovals) break;
|
|
33529
33780
|
let allowanceWei = 0n;
|
|
33530
33781
|
try {
|
|
33531
33782
|
const { allowance } = await getEVMAllowance({
|
|
33532
|
-
chainId:
|
|
33533
|
-
tokenAddress:
|
|
33534
|
-
ownerAddress:
|
|
33535
|
-
spenderAddress: spender
|
|
33783
|
+
chainId: required.chainId,
|
|
33784
|
+
tokenAddress: required.token,
|
|
33785
|
+
ownerAddress: activeAddress,
|
|
33786
|
+
spenderAddress: required.spender
|
|
33536
33787
|
});
|
|
33537
33788
|
allowanceWei = BigInt(allowance || "0");
|
|
33538
33789
|
} catch {
|
|
33539
33790
|
}
|
|
33540
|
-
if (allowanceWei
|
|
33791
|
+
if (!approvalSatisfied(allowanceWei, required.amountWei)) {
|
|
33541
33792
|
setState((p) => ({ ...p, txStatus: "approving" }));
|
|
33542
33793
|
if (!wallet || wallet.ecosystem !== "evm") {
|
|
33543
33794
|
throw new Error("EVM wallet required for token approval");
|
|
@@ -33545,7 +33796,7 @@ function useSwapExecution(fromChain) {
|
|
|
33545
33796
|
if (!chainIdStr || chainIdStr === "0") {
|
|
33546
33797
|
throw new Error("Invalid chain ID for token approval");
|
|
33547
33798
|
}
|
|
33548
|
-
const targetChain = Number(
|
|
33799
|
+
const targetChain = Number(required.chainId ?? txReq.chainId);
|
|
33549
33800
|
if (Number.isFinite(targetChain)) {
|
|
33550
33801
|
const current = await wallet.getChainId();
|
|
33551
33802
|
if (current !== targetChain) {
|
|
@@ -33557,18 +33808,18 @@ function useSwapExecution(fromChain) {
|
|
|
33557
33808
|
}
|
|
33558
33809
|
const approveAmount = maxApproval ? BigInt(
|
|
33559
33810
|
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
|
33560
|
-
) :
|
|
33811
|
+
) : required.amountWei;
|
|
33561
33812
|
const data = (0, import_viem43.encodeFunctionData)({
|
|
33562
33813
|
abi: import_viem43.erc20Abi,
|
|
33563
33814
|
functionName: "approve",
|
|
33564
|
-
args: [spender, approveAmount]
|
|
33815
|
+
args: [required.spender, approveAmount]
|
|
33565
33816
|
});
|
|
33566
33817
|
let approvalHash;
|
|
33567
33818
|
if (wallet.type === "eip1193") {
|
|
33568
33819
|
const from = await wallet.getAddress();
|
|
33569
33820
|
const params = {
|
|
33570
33821
|
from,
|
|
33571
|
-
to:
|
|
33822
|
+
to: required.token,
|
|
33572
33823
|
data,
|
|
33573
33824
|
value: "0x0"
|
|
33574
33825
|
};
|
|
@@ -33581,14 +33832,22 @@ function useSwapExecution(fromChain) {
|
|
|
33581
33832
|
});
|
|
33582
33833
|
} else {
|
|
33583
33834
|
const response = await wallet.sendTransaction({
|
|
33584
|
-
to:
|
|
33835
|
+
to: required.token,
|
|
33585
33836
|
data,
|
|
33586
33837
|
value: 0n,
|
|
33587
33838
|
chainId: Number.isFinite(targetChain) ? targetChain : void 0
|
|
33588
33839
|
});
|
|
33589
33840
|
approvalHash = response.hash;
|
|
33590
33841
|
}
|
|
33591
|
-
|
|
33842
|
+
if (required.stepIndex !== null) {
|
|
33843
|
+
void submitStepReceipt(
|
|
33844
|
+
routeResult.intentId,
|
|
33845
|
+
required.stepIndex,
|
|
33846
|
+
approvalHash
|
|
33847
|
+
).catch(() => {
|
|
33848
|
+
});
|
|
33849
|
+
}
|
|
33850
|
+
await waitForApprovalConfirmation(required.chainId, approvalHash);
|
|
33592
33851
|
setState((p) => ({
|
|
33593
33852
|
...p,
|
|
33594
33853
|
txStatus: "confirming",
|
|
@@ -33596,9 +33855,13 @@ function useSwapExecution(fromChain) {
|
|
|
33596
33855
|
}));
|
|
33597
33856
|
}
|
|
33598
33857
|
}
|
|
33858
|
+
if (ownsApprovals) {
|
|
33859
|
+
await requireActiveAddress(wallet, walletAddress);
|
|
33860
|
+
}
|
|
33599
33861
|
const hash = await Trustware.sendRouteTransaction(
|
|
33600
33862
|
routeResult,
|
|
33601
|
-
numericChainId
|
|
33863
|
+
numericChainId,
|
|
33864
|
+
{ approvalsEnsured: ownsApprovals }
|
|
33602
33865
|
);
|
|
33603
33866
|
try {
|
|
33604
33867
|
await submitReceipt(routeResult.intentId, hash);
|
|
@@ -33668,6 +33931,8 @@ var init_useSwapExecution = __esm({
|
|
|
33668
33931
|
import_viem43 = require("viem");
|
|
33669
33932
|
init_core2();
|
|
33670
33933
|
init_routes();
|
|
33934
|
+
init_http();
|
|
33935
|
+
init_tx();
|
|
33671
33936
|
init_sdkRpc();
|
|
33672
33937
|
init_chainHelpers();
|
|
33673
33938
|
FAST_POLL_MS = 1500;
|
|
@@ -39617,6 +39882,7 @@ function WidgetInner({
|
|
|
39617
39882
|
const { resolvedTheme } = useDepositUi();
|
|
39618
39883
|
const { status, revalidate, errors } = useTrustware();
|
|
39619
39884
|
const [showConfirmDialog, setShowConfirmDialog] = (0, import_react51.useState)(false);
|
|
39885
|
+
useGTM(GTM_ID);
|
|
39620
39886
|
const handleCloseRequest = (0, import_react51.useCallback)(() => {
|
|
39621
39887
|
if (ACTIVE_TRANSACTION_STATUSES.includes(transactionStatus)) {
|
|
39622
39888
|
setShowConfirmDialog(true);
|
|
@@ -39691,6 +39957,8 @@ var init_TrustwareWidgetV2 = __esm({
|
|
|
39691
39957
|
init_provider();
|
|
39692
39958
|
init_manager();
|
|
39693
39959
|
init_useTrustwareConfig();
|
|
39960
|
+
init_hooks();
|
|
39961
|
+
init_constants();
|
|
39694
39962
|
init_swap();
|
|
39695
39963
|
import_jsx_runtime60 = require("react/jsx-runtime");
|
|
39696
39964
|
widgetContentContainerStyle = {
|