@trustware/sdk-staging 1.1.12-staging.2 → 1.1.12-staging.4

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
@@ -571,7 +571,7 @@ var init_constants = __esm({
571
571
  "src/constants.ts"() {
572
572
  "use strict";
573
573
  SDK_NAME = "@trustware/sdk";
574
- SDK_VERSION = "1.1.12-staging.2";
574
+ SDK_VERSION = "1.1.12-staging.4";
575
575
  API_ROOT = "https://bv-staging-api.trustware.io";
576
576
  GTM_ID = "GTM-TZDGNCXB";
577
577
  API_PREFIX = "/api";
@@ -735,6 +735,7 @@ function inferChainTypeFromValue(normalized) {
735
735
  if (normalized === "evm" || normalized === "solana" || normalized === "cosmos" || normalized === "bitcoin") {
736
736
  return normalized;
737
737
  }
738
+ if (normalized === SOLANA_CHAIN_ID) return "solana";
738
739
  if (/^eip155:\d+$/.test(normalized) || /^\d+$/.test(normalized)) {
739
740
  return "evm";
740
741
  }
@@ -781,12 +782,13 @@ function isZeroAddressLike(address, chainType) {
781
782
  const normalized = normalizeAddress(address, chainType);
782
783
  return normalized === normalizeAddress(getNativeTokenAddress(chainType), chainType) || normalized === "0x0000000000000000000000000000000000000000";
783
784
  }
784
- var NATIVE_EVM, NATIVE_SOLANA, CHAIN_TYPE_ALIASES;
785
+ var NATIVE_EVM, NATIVE_SOLANA, SOLANA_CHAIN_ID, CHAIN_TYPE_ALIASES;
785
786
  var init_chains = __esm({
786
787
  "src/utils/chains.ts"() {
787
788
  "use strict";
788
789
  NATIVE_EVM = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
789
790
  NATIVE_SOLANA = "So11111111111111111111111111111111111111111";
791
+ SOLANA_CHAIN_ID = "1151111081099710";
790
792
  CHAIN_TYPE_ALIASES = {
791
793
  btc: "bitcoin",
792
794
  bitcoin: "bitcoin",
@@ -2495,7 +2497,159 @@ var init_balances = __esm({
2495
2497
  }
2496
2498
  });
2497
2499
 
2500
+ // src/widget/helpers/chainHelpers.ts
2501
+ function normalizeChainKey2(id) {
2502
+ if (id === void 0 || id === null) return "";
2503
+ return String(id).trim().toLowerCase();
2504
+ }
2505
+ function getNativeTokenAddress2(chainType) {
2506
+ const normalized = chainType?.toLowerCase?.();
2507
+ return normalized === "solana" ? NATIVE_SOLANA2 : NATIVE_EVM2;
2508
+ }
2509
+ function isSolanaNativeTokenAlias2(address) {
2510
+ if (!address) return false;
2511
+ const trimmed = address.trim();
2512
+ if (!trimmed) return false;
2513
+ return trimmed === NATIVE_SOLANA2 || trimmed.toLowerCase() === NATIVE_EVM2;
2514
+ }
2515
+ function parseDecimalToWei(input, decimals) {
2516
+ if (!input?.trim()) return null;
2517
+ const s = input.trim();
2518
+ if (!/^\d*\.?\d*$/.test(s)) return null;
2519
+ const [intPartRaw, fracRaw = ""] = s.split(".");
2520
+ const intPart = intPartRaw.length ? BigInt(intPartRaw) : 0n;
2521
+ const frac = (fracRaw + "0".repeat(decimals)).slice(0, decimals);
2522
+ const fracPart = frac ? BigInt(frac) : 0n;
2523
+ const base2 = 10n ** BigInt(decimals);
2524
+ return intPart * base2 + fracPart;
2525
+ }
2526
+ function inferChainTypeFromValue2(normalized) {
2527
+ if (!normalized) return void 0;
2528
+ const aliased = CHAIN_TYPE_ALIASES2[normalized];
2529
+ if (aliased) return aliased;
2530
+ if (normalized === "evm" || normalized === "solana" || normalized === "cosmos" || normalized === "bitcoin") {
2531
+ return normalized;
2532
+ }
2533
+ if (normalized === SOLANA_CHAIN_ID2) return "solana";
2534
+ if (/^eip155:\d+$/.test(normalized) || /^\d+$/.test(normalized)) {
2535
+ return "evm";
2536
+ }
2537
+ if (normalized.startsWith("solana:") || normalized.includes("solana")) {
2538
+ return "solana";
2539
+ }
2540
+ if (normalized.startsWith("cosmos:") || normalized.startsWith("sei:") || normalized === "sei-evm") {
2541
+ return "cosmos";
2542
+ }
2543
+ return void 0;
2544
+ }
2545
+ function normalizeChainType2(chain) {
2546
+ if (!chain) return void 0;
2547
+ const raw = typeof chain === "string" ? chain : chain.type ?? chain.chainType ?? chain.networkIdentifier ?? chain.chainId ?? chain.id ?? chain.networkName ?? chain.axelarChainName;
2548
+ if (!raw) return void 0;
2549
+ const normalized = String(raw).trim().toLowerCase();
2550
+ return inferChainTypeFromValue2(normalized) ?? normalized;
2551
+ }
2552
+ function canonicalChainKeyForLink(chain) {
2553
+ const seiKey = canonicalSeiChainKey(chain.chainId ?? chain.id);
2554
+ if (seiKey) return seiKey;
2555
+ return normalizeChainKey2(
2556
+ chain.networkIdentifier ?? chain.axelarChainName ?? chain.id ?? chain.chainId ?? chain.networkName
2557
+ );
2558
+ }
2559
+ function canonicalSeiChainKey(chainId) {
2560
+ const normalized = normalizeChainKey2(chainId);
2561
+ if (!normalized) return null;
2562
+ if (normalized === SEI_EVM_CHAIN_ID) return "sei-evm";
2563
+ if (normalized === SEI_COSMOS_CHAIN_ID) return "sei";
2564
+ return null;
2565
+ }
2566
+ function isZeroAddrLike(a, chainType) {
2567
+ if (!a) return true;
2568
+ if (!chainType) return false;
2569
+ const s = normalizeAddress2(a, chainType);
2570
+ return s === normalizeAddress2(getNativeTokenAddress2(chainType), chainType) || s === "0x0000000000000000000000000000000000000000";
2571
+ }
2572
+ function normalizeAddress2(address, chainType) {
2573
+ if (chainType?.toLowerCase?.() === "solana") {
2574
+ const trimmed = address.trim();
2575
+ if (isSolanaNativeTokenAlias2(trimmed)) {
2576
+ return NATIVE_SOLANA2;
2577
+ }
2578
+ return trimmed;
2579
+ }
2580
+ return address.toLowerCase();
2581
+ }
2582
+ function isNativeTokenAddress(address, chainType) {
2583
+ if (!address) return false;
2584
+ if (!chainType) return false;
2585
+ return normalizeAddress2(address, chainType) === normalizeAddress2(getNativeTokenAddress2(chainType), chainType);
2586
+ }
2587
+ function isEvmAddress2(value) {
2588
+ return !!value && EVM_ADDRESS_RE.test(value);
2589
+ }
2590
+ function needsErc20Approval(tokenAddress, chainType) {
2591
+ if (!isEvmAddress2(tokenAddress)) return false;
2592
+ const normalizedType = normalizeChainType2(chainType ?? void 0);
2593
+ if (normalizedType && NON_EVM_CHAIN_TYPES.has(normalizedType)) return false;
2594
+ return !isNativeTokenAddress(tokenAddress, chainType) && !isZeroAddrLike(tokenAddress, chainType);
2595
+ }
2596
+ function canonicalTokenAddressForChain(chain, address, chainTokens = []) {
2597
+ const chainType = normalizeChainType2(chain);
2598
+ const rawAddress = (address ?? "").trim();
2599
+ if (chainType === "solana") return normalizeAddress2(rawAddress, "solana");
2600
+ if (chainType === "cosmos") {
2601
+ const chainIdKey = normalizeChainKey2(chain.chainId ?? chain.id ?? "");
2602
+ const nativeSymbol = chain.nativeCurrency?.symbol?.toUpperCase?.();
2603
+ const nativeFromRegistry = chainTokens.find(
2604
+ (token) => normalizeChainKey2(token.chainId) === chainIdKey && token.symbol?.toUpperCase?.() === nativeSymbol
2605
+ );
2606
+ const nativeDenom = (nativeFromRegistry?.address ?? "usei").toLowerCase();
2607
+ if (rawAddress.toLowerCase() === NATIVE_EVM2) {
2608
+ return nativeDenom;
2609
+ }
2610
+ return rawAddress.toLowerCase();
2611
+ }
2612
+ const lowerAddress = rawAddress.toLowerCase();
2613
+ if (lowerAddress === "0x0000000000000000000000000000000000000000") {
2614
+ return NATIVE_EVM2;
2615
+ }
2616
+ return lowerAddress;
2617
+ }
2618
+ var NATIVE_EVM2, NATIVE_SOLANA2, SOLANA_CHAIN_ID2, CHAIN_TYPE_ALIASES2, SEI_EVM_CHAIN_ID, SEI_COSMOS_CHAIN_ID, EVM_ADDRESS_RE, NON_EVM_CHAIN_TYPES;
2619
+ var init_chainHelpers = __esm({
2620
+ "src/widget/helpers/chainHelpers.ts"() {
2621
+ "use strict";
2622
+ NATIVE_EVM2 = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
2623
+ NATIVE_SOLANA2 = "So11111111111111111111111111111111111111111";
2624
+ SOLANA_CHAIN_ID2 = "1151111081099710";
2625
+ CHAIN_TYPE_ALIASES2 = {
2626
+ btc: "bitcoin",
2627
+ bitcoin: "bitcoin",
2628
+ sei: "cosmos",
2629
+ "pacific-1": "cosmos",
2630
+ nibiru: "cosmos",
2631
+ "cataclysm-1": "cosmos"
2632
+ };
2633
+ SEI_EVM_CHAIN_ID = "1329";
2634
+ SEI_COSMOS_CHAIN_ID = "pacific-1";
2635
+ EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
2636
+ NON_EVM_CHAIN_TYPES = /* @__PURE__ */ new Set(["solana", "bitcoin", "btc"]);
2637
+ }
2638
+ });
2639
+
2498
2640
  // src/core/routes.ts
2641
+ function canonicalRouteToken(address, chain) {
2642
+ const chainType = normalizeChainType2(
2643
+ chain === void 0 || chain === null ? void 0 : String(chain)
2644
+ );
2645
+ if (chainType !== "solana") return address ?? "";
2646
+ if (!address) return SOLANA_NATIVE_ROUTE_TOKEN;
2647
+ const trimmed = address.trim();
2648
+ if (isSolanaNativeTokenAlias2(trimmed) || trimmed === "0x0000000000000000000000000000000000000000") {
2649
+ return SOLANA_NATIVE_ROUTE_TOKEN;
2650
+ }
2651
+ return trimmed;
2652
+ }
2499
2653
  function assertValidPostHook(hooks) {
2500
2654
  const postHook = hooks?.postHook;
2501
2655
  if (!postHook) return;
@@ -2540,6 +2694,8 @@ async function buildRoute(body, signal) {
2540
2694
  const url = `${apiBase()}/v1/routes/route`;
2541
2695
  const payload = {
2542
2696
  ...body,
2697
+ fromToken: canonicalRouteToken(body.fromToken, body.fromChain),
2698
+ toToken: canonicalRouteToken(body.toToken, body.toChain),
2543
2699
  slippageBps: body.slippageBps ?? (body.slippage === void 0 ? void 0 : Math.round(body.slippage * 100)),
2544
2700
  fromAmountUSD: body.fromAmountUSD ?? body.fromAmountUsd
2545
2701
  };
@@ -2579,6 +2735,8 @@ async function buildDepositAddress(body, signal) {
2579
2735
  const url = `${apiBase()}/v1/routes/deposit-address`;
2580
2736
  const payload = {
2581
2737
  ...body,
2738
+ fromToken: canonicalRouteToken(body.fromToken, body.fromChain),
2739
+ toToken: canonicalRouteToken(body.toToken, body.toChain),
2582
2740
  slippageBps: body.slippageBps ?? (body.slippage === void 0 ? void 0 : Math.round(body.slippage * 100)),
2583
2741
  fromAmountUSD: body.fromAmountUSD ?? body.fromAmountUsd
2584
2742
  };
@@ -2677,13 +2835,15 @@ async function pollStatus(intentId, { intervalMs = 2e3, timeoutMs = 5 * 6e4 } =
2677
2835
  await new Promise((r) => setTimeout(r, intervalMs));
2678
2836
  }
2679
2837
  }
2680
- var STATUS_WIRE_TO_CAMEL;
2838
+ var SOLANA_NATIVE_ROUTE_TOKEN, STATUS_WIRE_TO_CAMEL;
2681
2839
  var init_routes = __esm({
2682
2840
  "src/core/routes.ts"() {
2683
2841
  "use strict";
2684
2842
  init_http();
2685
2843
  init_store();
2686
2844
  init_address();
2845
+ init_chainHelpers();
2846
+ SOLANA_NATIVE_ROUTE_TOKEN = "So11111111111111111111111111111111111111112";
2687
2847
  STATUS_WIRE_TO_CAMEL = {
2688
2848
  intent_id: "intentId",
2689
2849
  from_address: "fromAddress",
@@ -3028,9 +3188,9 @@ var init_useTrustwareConfig = __esm({
3028
3188
  import { useMemo as useMemo2 } from "react";
3029
3189
  function parsePositiveNumber(value) {
3030
3190
  if (value === null || value === void 0) return void 0;
3031
- const str = String(value).trim();
3032
- if (!str) return void 0;
3033
- const n = Number(str);
3191
+ const str2 = String(value).trim();
3192
+ if (!str2) return void 0;
3193
+ const n = Number(str2);
3034
3194
  return Number.isFinite(n) && n >= 0 ? n : void 0;
3035
3195
  }
3036
3196
  function useAmountConstraints() {
@@ -3039,10 +3199,10 @@ function useAmountConstraints() {
3039
3199
  const fixedFromAmountString = useMemo2(() => {
3040
3200
  const raw = routeOptions.fixedFromAmount;
3041
3201
  if (raw === null || raw === void 0) return void 0;
3042
- const str = String(raw).trim();
3043
- if (!str) return void 0;
3044
- const n = Number(str);
3045
- return Number.isFinite(n) && n > 0 ? str : void 0;
3202
+ const str2 = String(raw).trim();
3203
+ if (!str2) return void 0;
3204
+ const n = Number(str2);
3205
+ return Number.isFinite(n) && n > 0 ? str2 : void 0;
3046
3206
  }, [routeOptions.fixedFromAmount]);
3047
3207
  const fixedFromAmountValue = useMemo2(() => {
3048
3208
  if (!fixedFromAmountString) return void 0;
@@ -3121,133 +3281,6 @@ var init_registryClient = __esm({
3121
3281
  }
3122
3282
  });
3123
3283
 
3124
- // src/widget/helpers/chainHelpers.ts
3125
- function normalizeChainKey2(id) {
3126
- if (id === void 0 || id === null) return "";
3127
- return String(id).trim().toLowerCase();
3128
- }
3129
- function getNativeTokenAddress2(chainType) {
3130
- const normalized = chainType?.toLowerCase?.();
3131
- return normalized === "solana" ? NATIVE_SOLANA2 : NATIVE_EVM2;
3132
- }
3133
- function isSolanaNativeTokenAlias2(address) {
3134
- if (!address) return false;
3135
- const trimmed = address.trim();
3136
- if (!trimmed) return false;
3137
- return trimmed === NATIVE_SOLANA2 || trimmed.toLowerCase() === NATIVE_EVM2;
3138
- }
3139
- function parseDecimalToWei(input, decimals) {
3140
- if (!input?.trim()) return null;
3141
- const s = input.trim();
3142
- if (!/^\d*\.?\d*$/.test(s)) return null;
3143
- const [intPartRaw, fracRaw = ""] = s.split(".");
3144
- const intPart = intPartRaw.length ? BigInt(intPartRaw) : 0n;
3145
- const frac = (fracRaw + "0".repeat(decimals)).slice(0, decimals);
3146
- const fracPart = frac ? BigInt(frac) : 0n;
3147
- const base2 = 10n ** BigInt(decimals);
3148
- return intPart * base2 + fracPart;
3149
- }
3150
- function inferChainTypeFromValue2(normalized) {
3151
- if (!normalized) return void 0;
3152
- const aliased = CHAIN_TYPE_ALIASES2[normalized];
3153
- if (aliased) return aliased;
3154
- if (normalized === "evm" || normalized === "solana" || normalized === "cosmos" || normalized === "bitcoin") {
3155
- return normalized;
3156
- }
3157
- if (/^eip155:\d+$/.test(normalized) || /^\d+$/.test(normalized)) {
3158
- return "evm";
3159
- }
3160
- if (normalized.startsWith("solana:") || normalized.includes("solana")) {
3161
- return "solana";
3162
- }
3163
- if (normalized.startsWith("cosmos:") || normalized.startsWith("sei:") || normalized === "sei-evm") {
3164
- return "cosmos";
3165
- }
3166
- return void 0;
3167
- }
3168
- function normalizeChainType2(chain) {
3169
- if (!chain) return void 0;
3170
- const raw = typeof chain === "string" ? chain : chain.type ?? chain.chainType ?? chain.networkIdentifier ?? chain.chainId ?? chain.id ?? chain.networkName ?? chain.axelarChainName;
3171
- if (!raw) return void 0;
3172
- const normalized = String(raw).trim().toLowerCase();
3173
- return inferChainTypeFromValue2(normalized) ?? normalized;
3174
- }
3175
- function canonicalChainKeyForLink(chain) {
3176
- const seiKey = canonicalSeiChainKey(chain.chainId ?? chain.id);
3177
- if (seiKey) return seiKey;
3178
- return normalizeChainKey2(
3179
- chain.networkIdentifier ?? chain.axelarChainName ?? chain.id ?? chain.chainId ?? chain.networkName
3180
- );
3181
- }
3182
- function canonicalSeiChainKey(chainId) {
3183
- const normalized = normalizeChainKey2(chainId);
3184
- if (!normalized) return null;
3185
- if (normalized === SEI_EVM_CHAIN_ID) return "sei-evm";
3186
- if (normalized === SEI_COSMOS_CHAIN_ID) return "sei";
3187
- return null;
3188
- }
3189
- function isZeroAddrLike(a, chainType) {
3190
- if (!a) return true;
3191
- if (!chainType) return false;
3192
- const s = normalizeAddress2(a, chainType);
3193
- return s === normalizeAddress2(getNativeTokenAddress2(chainType), chainType) || s === "0x0000000000000000000000000000000000000000";
3194
- }
3195
- function normalizeAddress2(address, chainType) {
3196
- if (chainType?.toLowerCase?.() === "solana") {
3197
- const trimmed = address.trim();
3198
- if (isSolanaNativeTokenAlias2(trimmed)) {
3199
- return NATIVE_SOLANA2;
3200
- }
3201
- return trimmed;
3202
- }
3203
- return address.toLowerCase();
3204
- }
3205
- function isNativeTokenAddress(address, chainType) {
3206
- if (!address) return false;
3207
- if (!chainType) return false;
3208
- return normalizeAddress2(address, chainType) === normalizeAddress2(getNativeTokenAddress2(chainType), chainType);
3209
- }
3210
- function canonicalTokenAddressForChain(chain, address, chainTokens = []) {
3211
- const chainType = normalizeChainType2(chain);
3212
- const rawAddress = (address ?? "").trim();
3213
- if (chainType === "solana") return normalizeAddress2(rawAddress, "solana");
3214
- if (chainType === "cosmos") {
3215
- const chainIdKey = normalizeChainKey2(chain.chainId ?? chain.id ?? "");
3216
- const nativeSymbol = chain.nativeCurrency?.symbol?.toUpperCase?.();
3217
- const nativeFromRegistry = chainTokens.find(
3218
- (token) => normalizeChainKey2(token.chainId) === chainIdKey && token.symbol?.toUpperCase?.() === nativeSymbol
3219
- );
3220
- const nativeDenom = (nativeFromRegistry?.address ?? "usei").toLowerCase();
3221
- if (rawAddress.toLowerCase() === NATIVE_EVM2) {
3222
- return nativeDenom;
3223
- }
3224
- return rawAddress.toLowerCase();
3225
- }
3226
- const lowerAddress = rawAddress.toLowerCase();
3227
- if (lowerAddress === "0x0000000000000000000000000000000000000000") {
3228
- return NATIVE_EVM2;
3229
- }
3230
- return lowerAddress;
3231
- }
3232
- var NATIVE_EVM2, NATIVE_SOLANA2, CHAIN_TYPE_ALIASES2, SEI_EVM_CHAIN_ID, SEI_COSMOS_CHAIN_ID;
3233
- var init_chainHelpers = __esm({
3234
- "src/widget/helpers/chainHelpers.ts"() {
3235
- "use strict";
3236
- NATIVE_EVM2 = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
3237
- NATIVE_SOLANA2 = "So11111111111111111111111111111111111111111";
3238
- CHAIN_TYPE_ALIASES2 = {
3239
- btc: "bitcoin",
3240
- bitcoin: "bitcoin",
3241
- sei: "cosmos",
3242
- "pacific-1": "cosmos",
3243
- nibiru: "cosmos",
3244
- "cataclysm-1": "cosmos"
3245
- };
3246
- SEI_EVM_CHAIN_ID = "1329";
3247
- SEI_COSMOS_CHAIN_ID = "pacific-1";
3248
- }
3249
- });
3250
-
3251
3284
  // src/widget/helpers/tokenAmount.ts
3252
3285
  function rawToDecimal(rawAmount, decimals) {
3253
3286
  if (!rawAmount) return "0";
@@ -5393,6 +5426,52 @@ var init_useTransactionSubmit = __esm({
5393
5426
  }
5394
5427
  });
5395
5428
 
5429
+ // src/core/failure.ts
5430
+ function asRecord(value) {
5431
+ return typeof value === "object" && value !== null ? value : null;
5432
+ }
5433
+ function str(value) {
5434
+ return typeof value === "string" ? value.trim() : "";
5435
+ }
5436
+ function tidy(detail) {
5437
+ const collapsed = detail.replace(/\s+/g, " ").trim();
5438
+ return collapsed.length > MAX_DETAIL ? `${collapsed.slice(0, MAX_DETAIL - 1).trimEnd()}\u2026` : collapsed;
5439
+ }
5440
+ function describeTransactionFailure(tx) {
5441
+ const raw = asRecord(tx?.statusRaw);
5442
+ const substatus = str(raw?.substatus);
5443
+ const detail = str(raw?.substatusMessage) || str(raw?.reason) || str(raw?.error) || str(raw?.message);
5444
+ const haystack = `${substatus} ${detail}`.toLowerCase();
5445
+ if (/slippage|price impact|price movement/.test(haystack)) {
5446
+ return "Transaction failed due to price movement. Please try again with a higher slippage.";
5447
+ }
5448
+ if (/liquidity/.test(haystack)) {
5449
+ return "Transaction failed due to insufficient liquidity. Try a smaller amount.";
5450
+ }
5451
+ if (/timeout|timed out|expired/.test(haystack)) {
5452
+ return "Transaction expired. Please start a new transaction.";
5453
+ }
5454
+ if (/out.?of.?gas|insufficient (gas|fee)/.test(haystack)) {
5455
+ return "Transaction failed due to insufficient gas. Please ensure you have enough native tokens for gas.";
5456
+ }
5457
+ if (/insufficient (balance|funds)/.test(haystack)) {
5458
+ return "Transaction failed due to insufficient balance.";
5459
+ }
5460
+ if (tx?.gasStatus === "insufficient") {
5461
+ return "Transaction failed due to insufficient gas. Please ensure you have enough native tokens for gas.";
5462
+ }
5463
+ if (detail) return `Transaction failed on-chain: ${tidy(detail)}`;
5464
+ return GENERIC;
5465
+ }
5466
+ var MAX_DETAIL, GENERIC;
5467
+ var init_failure = __esm({
5468
+ "src/core/failure.ts"() {
5469
+ "use strict";
5470
+ MAX_DETAIL = 160;
5471
+ GENERIC = "Transaction failed on-chain. Please try again.";
5472
+ }
5473
+ });
5474
+
5396
5475
  // src/hooks/useGTM.ts
5397
5476
  import { useEffect as useEffect5, useRef as useRef2, useCallback as useCallback2 } from "react";
5398
5477
  function isGA4Allowed() {
@@ -5637,7 +5716,7 @@ function useTransactionPolling() {
5637
5716
  return;
5638
5717
  }
5639
5718
  if (tx.status === "failed") {
5640
- const failError = mapFailedTransactionError(tx);
5719
+ const failError = describeTransactionFailure(tx);
5641
5720
  clearPolling();
5642
5721
  setState((prev) => ({
5643
5722
  ...prev,
@@ -5776,29 +5855,6 @@ function mapReceiptError(err) {
5776
5855
  }
5777
5856
  return cleanedMsg || "Failed to submit transaction. Please try again.";
5778
5857
  }
5779
- function mapFailedTransactionError(tx) {
5780
- const statusRaw = tx.statusRaw;
5781
- if (typeof statusRaw === "object" && statusRaw !== null) {
5782
- const statusObj = statusRaw;
5783
- const reason = statusObj.reason || statusObj.error || statusObj.message;
5784
- if (reason) {
5785
- const reasonLower = String(reason).toLowerCase();
5786
- if (reasonLower.includes("slippage") || reasonLower.includes("price")) {
5787
- return "Transaction failed due to price movement. Please try again with a higher slippage.";
5788
- }
5789
- if (reasonLower.includes("liquidity")) {
5790
- return "Transaction failed due to insufficient liquidity. Try a smaller amount.";
5791
- }
5792
- if (reasonLower.includes("timeout") || reasonLower.includes("expired")) {
5793
- return "Transaction expired. Please start a new deposit.";
5794
- }
5795
- }
5796
- }
5797
- if (tx.gasStatus === "insufficient") {
5798
- return "Transaction failed due to insufficient gas. Please ensure you have enough native tokens for gas.";
5799
- }
5800
- return "Transaction failed. Please try again or contact support if the issue persists.";
5801
- }
5802
5858
  var FAST_POLL_INTERVAL_MS, NORMAL_POLL_INTERVAL_MS, POLL_TIMEOUT_MS;
5803
5859
  var init_useTransactionPolling = __esm({
5804
5860
  "src/widget/hooks/useTransactionPolling.ts"() {
@@ -5806,6 +5862,7 @@ var init_useTransactionPolling = __esm({
5806
5862
  "use client";
5807
5863
  init_routes();
5808
5864
  init_http();
5865
+ init_failure();
5809
5866
  init_DepositContext();
5810
5867
  init_provider();
5811
5868
  init_core2();
@@ -33291,10 +33348,12 @@ function mapError(raw) {
33291
33348
  };
33292
33349
  }
33293
33350
  if (lower.includes("transaction failed") || lower.includes("reverted")) {
33351
+ const specific = msg.trim();
33352
+ const isBare = /^transaction (failed|reverted)[.!]?$/i.test(specific) || specific.length > 200 || specific.includes("\n");
33294
33353
  return {
33295
33354
  category: "transaction_failed",
33296
33355
  title: "Transaction Failed",
33297
- message: "The transaction could not be completed. Please try again."
33356
+ message: isBare ? "The transaction could not be completed. Please try again." : specific
33298
33357
  };
33299
33358
  }
33300
33359
  if (lower.includes("wrong network") || lower.includes("wrong chain") || lower.includes("chain mismatch")) {
@@ -33586,7 +33645,7 @@ function useSwapExecution(fromChain) {
33586
33645
  }
33587
33646
  if (tx.status === "failed") {
33588
33647
  clearPolling();
33589
- const msg = "Transaction failed on-chain. Please try again.";
33648
+ const msg = describeTransactionFailure(tx);
33590
33649
  setState((p) => ({ ...p, txStatus: "error", errorMessage: msg }));
33591
33650
  onError(msg);
33592
33651
  return;
@@ -33621,8 +33680,7 @@ function useSwapExecution(fromChain) {
33621
33680
  return;
33622
33681
  }
33623
33682
  const chainType = normalizeChainType2(fromChain);
33624
- const isNative = !fromTokenAddress || isNativeTokenAddress(fromTokenAddress, chainType) || isZeroAddrLike(fromTokenAddress, chainType);
33625
- if (isNative) {
33683
+ if (!needsErc20Approval(fromTokenAddress, chainType)) {
33626
33684
  setState((p) => ({ ...p, allowanceStatus: "sufficient" }));
33627
33685
  return;
33628
33686
  }
@@ -33636,7 +33694,7 @@ function useSwapExecution(fromChain) {
33636
33694
  BigInt(a.amount || "0"),
33637
33695
  amountWei
33638
33696
  );
33639
- if (!token || !a.spender) return [];
33697
+ if (!isEvmAddress2(token) || !isEvmAddress2(a.spender)) return [];
33640
33698
  return [
33641
33699
  {
33642
33700
  chainId: a.chainId || chainIdStr,
@@ -33784,7 +33842,8 @@ function useSwapExecution(fromChain) {
33784
33842
  const requiredApprovals = plannedApprovals.length ? plannedApprovals.flatMap((a, index) => {
33785
33843
  const token = a.tokenAddress ?? fromTokenAddress;
33786
33844
  const approvalSpender = a.spender;
33787
- if (!token || !approvalSpender) return [];
33845
+ if (!isEvmAddress2(token) || !isEvmAddress2(approvalSpender))
33846
+ return [];
33788
33847
  const amountWei = requiredApprovalAmount(
33789
33848
  BigInt(a.amount || "0"),
33790
33849
  fromAmountWei
@@ -33807,7 +33866,8 @@ function useSwapExecution(fromChain) {
33807
33866
  chainId: chainIdStr
33808
33867
  }
33809
33868
  ] : [];
33810
- const ownsApprovals = !isNative && !!walletAddress && !!chainIdStr;
33869
+ const coversEveryPlannedApproval = plannedApprovals.length === 0 || requiredApprovals.length === plannedApprovals.length;
33870
+ const ownsApprovals = coversEveryPlannedApproval && needsErc20Approval(fromTokenAddress, chainType) && !!walletAddress && !!chainIdStr;
33811
33871
  const activeAddress = ownsApprovals ? await requireActiveAddress(wallet, walletAddress) : void 0;
33812
33872
  for (const required of requiredApprovals) {
33813
33873
  if (!ownsApprovals) break;
@@ -33962,6 +34022,7 @@ var init_useSwapExecution = __esm({
33962
34022
  init_core2();
33963
34023
  init_routes();
33964
34024
  init_http();
34025
+ init_failure();
33965
34026
  init_tx();
33966
34027
  init_sdkRpc();
33967
34028
  init_chainHelpers();
@@ -35695,8 +35756,8 @@ function truncateDecimal(n, dp) {
35695
35756
  const s = truncated.toFixed(dp);
35696
35757
  return s.includes(".") ? s.replace(/\.?0+$/, "") || "0" : s;
35697
35758
  }
35698
- function scaleFontSize(str) {
35699
- const len = str.replace(/[^0-9.]/g, "").length;
35759
+ function scaleFontSize(str2) {
35760
+ const len = str2.replace(/[^0-9.]/g, "").length;
35700
35761
  if (len <= 6) return "2.5rem";
35701
35762
  if (len <= 9) return "2rem";
35702
35763
  if (len <= 12) return "1.5rem";
@@ -35995,6 +36056,10 @@ function SwapMode({
35995
36056
  }, [lockDestToken, fromToken, fromChain, toToken, toChain, route, emitEvent]);
35996
36057
  const fromChainType = normalizeChainType2(fromChain);
35997
36058
  const toChainType = normalizeChainType2(toChain);
36059
+ const canSetMaxApproval = needsErc20Approval(
36060
+ fromToken?.address,
36061
+ fromChainType
36062
+ );
35998
36063
  const needsDestAddress = !!fromChainType && !!toChainType && fromChainType !== toChainType;
35999
36064
  const isValidDestAddress = !needsDestAddress || validateDestAddress(destAddress, toChainType ?? "");
36000
36065
  const handleReview = useCallback22(async () => {
@@ -38215,7 +38280,7 @@ function SwapMode({
38215
38280
  }
38216
38281
  )
38217
38282
  ] }),
38218
- /* @__PURE__ */ jsx59("div", { style: { marginBottom: spacing[4] }, children: /* @__PURE__ */ jsxs47(
38283
+ canSetMaxApproval && /* @__PURE__ */ jsx59("div", { style: { marginBottom: spacing[4] }, children: /* @__PURE__ */ jsxs47(
38219
38284
  "div",
38220
38285
  {
38221
38286
  style: {