@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.cjs CHANGED
@@ -593,7 +593,7 @@ var init_constants = __esm({
593
593
  "src/constants.ts"() {
594
594
  "use strict";
595
595
  SDK_NAME = "@trustware/sdk";
596
- SDK_VERSION = "1.1.12-staging.2";
596
+ SDK_VERSION = "1.1.12-staging.4";
597
597
  API_ROOT = "https://bv-staging-api.trustware.io";
598
598
  GTM_ID = "GTM-TZDGNCXB";
599
599
  API_PREFIX = "/api";
@@ -757,6 +757,7 @@ function inferChainTypeFromValue(normalized) {
757
757
  if (normalized === "evm" || normalized === "solana" || normalized === "cosmos" || normalized === "bitcoin") {
758
758
  return normalized;
759
759
  }
760
+ if (normalized === SOLANA_CHAIN_ID) return "solana";
760
761
  if (/^eip155:\d+$/.test(normalized) || /^\d+$/.test(normalized)) {
761
762
  return "evm";
762
763
  }
@@ -803,12 +804,13 @@ function isZeroAddressLike(address, chainType) {
803
804
  const normalized = normalizeAddress(address, chainType);
804
805
  return normalized === normalizeAddress(getNativeTokenAddress(chainType), chainType) || normalized === "0x0000000000000000000000000000000000000000";
805
806
  }
806
- var NATIVE_EVM, NATIVE_SOLANA, CHAIN_TYPE_ALIASES;
807
+ var NATIVE_EVM, NATIVE_SOLANA, SOLANA_CHAIN_ID, CHAIN_TYPE_ALIASES;
807
808
  var init_chains = __esm({
808
809
  "src/utils/chains.ts"() {
809
810
  "use strict";
810
811
  NATIVE_EVM = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
811
812
  NATIVE_SOLANA = "So11111111111111111111111111111111111111111";
813
+ SOLANA_CHAIN_ID = "1151111081099710";
812
814
  CHAIN_TYPE_ALIASES = {
813
815
  btc: "bitcoin",
814
816
  bitcoin: "bitcoin",
@@ -2517,7 +2519,159 @@ var init_balances = __esm({
2517
2519
  }
2518
2520
  });
2519
2521
 
2522
+ // src/widget/helpers/chainHelpers.ts
2523
+ function normalizeChainKey2(id) {
2524
+ if (id === void 0 || id === null) return "";
2525
+ return String(id).trim().toLowerCase();
2526
+ }
2527
+ function getNativeTokenAddress2(chainType) {
2528
+ const normalized = chainType?.toLowerCase?.();
2529
+ return normalized === "solana" ? NATIVE_SOLANA2 : NATIVE_EVM2;
2530
+ }
2531
+ function isSolanaNativeTokenAlias2(address) {
2532
+ if (!address) return false;
2533
+ const trimmed = address.trim();
2534
+ if (!trimmed) return false;
2535
+ return trimmed === NATIVE_SOLANA2 || trimmed.toLowerCase() === NATIVE_EVM2;
2536
+ }
2537
+ function parseDecimalToWei(input, decimals) {
2538
+ if (!input?.trim()) return null;
2539
+ const s = input.trim();
2540
+ if (!/^\d*\.?\d*$/.test(s)) return null;
2541
+ const [intPartRaw, fracRaw = ""] = s.split(".");
2542
+ const intPart = intPartRaw.length ? BigInt(intPartRaw) : 0n;
2543
+ const frac = (fracRaw + "0".repeat(decimals)).slice(0, decimals);
2544
+ const fracPart = frac ? BigInt(frac) : 0n;
2545
+ const base2 = 10n ** BigInt(decimals);
2546
+ return intPart * base2 + fracPart;
2547
+ }
2548
+ function inferChainTypeFromValue2(normalized) {
2549
+ if (!normalized) return void 0;
2550
+ const aliased = CHAIN_TYPE_ALIASES2[normalized];
2551
+ if (aliased) return aliased;
2552
+ if (normalized === "evm" || normalized === "solana" || normalized === "cosmos" || normalized === "bitcoin") {
2553
+ return normalized;
2554
+ }
2555
+ if (normalized === SOLANA_CHAIN_ID2) return "solana";
2556
+ if (/^eip155:\d+$/.test(normalized) || /^\d+$/.test(normalized)) {
2557
+ return "evm";
2558
+ }
2559
+ if (normalized.startsWith("solana:") || normalized.includes("solana")) {
2560
+ return "solana";
2561
+ }
2562
+ if (normalized.startsWith("cosmos:") || normalized.startsWith("sei:") || normalized === "sei-evm") {
2563
+ return "cosmos";
2564
+ }
2565
+ return void 0;
2566
+ }
2567
+ function normalizeChainType2(chain) {
2568
+ if (!chain) return void 0;
2569
+ const raw = typeof chain === "string" ? chain : chain.type ?? chain.chainType ?? chain.networkIdentifier ?? chain.chainId ?? chain.id ?? chain.networkName ?? chain.axelarChainName;
2570
+ if (!raw) return void 0;
2571
+ const normalized = String(raw).trim().toLowerCase();
2572
+ return inferChainTypeFromValue2(normalized) ?? normalized;
2573
+ }
2574
+ function canonicalChainKeyForLink(chain) {
2575
+ const seiKey = canonicalSeiChainKey(chain.chainId ?? chain.id);
2576
+ if (seiKey) return seiKey;
2577
+ return normalizeChainKey2(
2578
+ chain.networkIdentifier ?? chain.axelarChainName ?? chain.id ?? chain.chainId ?? chain.networkName
2579
+ );
2580
+ }
2581
+ function canonicalSeiChainKey(chainId) {
2582
+ const normalized = normalizeChainKey2(chainId);
2583
+ if (!normalized) return null;
2584
+ if (normalized === SEI_EVM_CHAIN_ID) return "sei-evm";
2585
+ if (normalized === SEI_COSMOS_CHAIN_ID) return "sei";
2586
+ return null;
2587
+ }
2588
+ function isZeroAddrLike(a, chainType) {
2589
+ if (!a) return true;
2590
+ if (!chainType) return false;
2591
+ const s = normalizeAddress2(a, chainType);
2592
+ return s === normalizeAddress2(getNativeTokenAddress2(chainType), chainType) || s === "0x0000000000000000000000000000000000000000";
2593
+ }
2594
+ function normalizeAddress2(address, chainType) {
2595
+ if (chainType?.toLowerCase?.() === "solana") {
2596
+ const trimmed = address.trim();
2597
+ if (isSolanaNativeTokenAlias2(trimmed)) {
2598
+ return NATIVE_SOLANA2;
2599
+ }
2600
+ return trimmed;
2601
+ }
2602
+ return address.toLowerCase();
2603
+ }
2604
+ function isNativeTokenAddress(address, chainType) {
2605
+ if (!address) return false;
2606
+ if (!chainType) return false;
2607
+ return normalizeAddress2(address, chainType) === normalizeAddress2(getNativeTokenAddress2(chainType), chainType);
2608
+ }
2609
+ function isEvmAddress2(value) {
2610
+ return !!value && EVM_ADDRESS_RE.test(value);
2611
+ }
2612
+ function needsErc20Approval(tokenAddress, chainType) {
2613
+ if (!isEvmAddress2(tokenAddress)) return false;
2614
+ const normalizedType = normalizeChainType2(chainType ?? void 0);
2615
+ if (normalizedType && NON_EVM_CHAIN_TYPES.has(normalizedType)) return false;
2616
+ return !isNativeTokenAddress(tokenAddress, chainType) && !isZeroAddrLike(tokenAddress, chainType);
2617
+ }
2618
+ function canonicalTokenAddressForChain(chain, address, chainTokens = []) {
2619
+ const chainType = normalizeChainType2(chain);
2620
+ const rawAddress = (address ?? "").trim();
2621
+ if (chainType === "solana") return normalizeAddress2(rawAddress, "solana");
2622
+ if (chainType === "cosmos") {
2623
+ const chainIdKey = normalizeChainKey2(chain.chainId ?? chain.id ?? "");
2624
+ const nativeSymbol = chain.nativeCurrency?.symbol?.toUpperCase?.();
2625
+ const nativeFromRegistry = chainTokens.find(
2626
+ (token) => normalizeChainKey2(token.chainId) === chainIdKey && token.symbol?.toUpperCase?.() === nativeSymbol
2627
+ );
2628
+ const nativeDenom = (nativeFromRegistry?.address ?? "usei").toLowerCase();
2629
+ if (rawAddress.toLowerCase() === NATIVE_EVM2) {
2630
+ return nativeDenom;
2631
+ }
2632
+ return rawAddress.toLowerCase();
2633
+ }
2634
+ const lowerAddress = rawAddress.toLowerCase();
2635
+ if (lowerAddress === "0x0000000000000000000000000000000000000000") {
2636
+ return NATIVE_EVM2;
2637
+ }
2638
+ return lowerAddress;
2639
+ }
2640
+ 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;
2641
+ var init_chainHelpers = __esm({
2642
+ "src/widget/helpers/chainHelpers.ts"() {
2643
+ "use strict";
2644
+ NATIVE_EVM2 = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
2645
+ NATIVE_SOLANA2 = "So11111111111111111111111111111111111111111";
2646
+ SOLANA_CHAIN_ID2 = "1151111081099710";
2647
+ CHAIN_TYPE_ALIASES2 = {
2648
+ btc: "bitcoin",
2649
+ bitcoin: "bitcoin",
2650
+ sei: "cosmos",
2651
+ "pacific-1": "cosmos",
2652
+ nibiru: "cosmos",
2653
+ "cataclysm-1": "cosmos"
2654
+ };
2655
+ SEI_EVM_CHAIN_ID = "1329";
2656
+ SEI_COSMOS_CHAIN_ID = "pacific-1";
2657
+ EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
2658
+ NON_EVM_CHAIN_TYPES = /* @__PURE__ */ new Set(["solana", "bitcoin", "btc"]);
2659
+ }
2660
+ });
2661
+
2520
2662
  // src/core/routes.ts
2663
+ function canonicalRouteToken(address, chain) {
2664
+ const chainType = normalizeChainType2(
2665
+ chain === void 0 || chain === null ? void 0 : String(chain)
2666
+ );
2667
+ if (chainType !== "solana") return address ?? "";
2668
+ if (!address) return SOLANA_NATIVE_ROUTE_TOKEN;
2669
+ const trimmed = address.trim();
2670
+ if (isSolanaNativeTokenAlias2(trimmed) || trimmed === "0x0000000000000000000000000000000000000000") {
2671
+ return SOLANA_NATIVE_ROUTE_TOKEN;
2672
+ }
2673
+ return trimmed;
2674
+ }
2521
2675
  function assertValidPostHook(hooks) {
2522
2676
  const postHook = hooks?.postHook;
2523
2677
  if (!postHook) return;
@@ -2562,6 +2716,8 @@ async function buildRoute(body, signal) {
2562
2716
  const url = `${apiBase()}/v1/routes/route`;
2563
2717
  const payload = {
2564
2718
  ...body,
2719
+ fromToken: canonicalRouteToken(body.fromToken, body.fromChain),
2720
+ toToken: canonicalRouteToken(body.toToken, body.toChain),
2565
2721
  slippageBps: body.slippageBps ?? (body.slippage === void 0 ? void 0 : Math.round(body.slippage * 100)),
2566
2722
  fromAmountUSD: body.fromAmountUSD ?? body.fromAmountUsd
2567
2723
  };
@@ -2601,6 +2757,8 @@ async function buildDepositAddress(body, signal) {
2601
2757
  const url = `${apiBase()}/v1/routes/deposit-address`;
2602
2758
  const payload = {
2603
2759
  ...body,
2760
+ fromToken: canonicalRouteToken(body.fromToken, body.fromChain),
2761
+ toToken: canonicalRouteToken(body.toToken, body.toChain),
2604
2762
  slippageBps: body.slippageBps ?? (body.slippage === void 0 ? void 0 : Math.round(body.slippage * 100)),
2605
2763
  fromAmountUSD: body.fromAmountUSD ?? body.fromAmountUsd
2606
2764
  };
@@ -2699,13 +2857,15 @@ async function pollStatus(intentId, { intervalMs = 2e3, timeoutMs = 5 * 6e4 } =
2699
2857
  await new Promise((r) => setTimeout(r, intervalMs));
2700
2858
  }
2701
2859
  }
2702
- var STATUS_WIRE_TO_CAMEL;
2860
+ var SOLANA_NATIVE_ROUTE_TOKEN, STATUS_WIRE_TO_CAMEL;
2703
2861
  var init_routes = __esm({
2704
2862
  "src/core/routes.ts"() {
2705
2863
  "use strict";
2706
2864
  init_http();
2707
2865
  init_store();
2708
2866
  init_address();
2867
+ init_chainHelpers();
2868
+ SOLANA_NATIVE_ROUTE_TOKEN = "So11111111111111111111111111111111111111112";
2709
2869
  STATUS_WIRE_TO_CAMEL = {
2710
2870
  intent_id: "intentId",
2711
2871
  from_address: "fromAddress",
@@ -3051,9 +3211,9 @@ var init_useTrustwareConfig = __esm({
3051
3211
  // src/widget/hooks/useAmountConstraints.ts
3052
3212
  function parsePositiveNumber(value) {
3053
3213
  if (value === null || value === void 0) return void 0;
3054
- const str = String(value).trim();
3055
- if (!str) return void 0;
3056
- const n = Number(str);
3214
+ const str2 = String(value).trim();
3215
+ if (!str2) return void 0;
3216
+ const n = Number(str2);
3057
3217
  return Number.isFinite(n) && n >= 0 ? n : void 0;
3058
3218
  }
3059
3219
  function useAmountConstraints() {
@@ -3062,10 +3222,10 @@ function useAmountConstraints() {
3062
3222
  const fixedFromAmountString = (0, import_react3.useMemo)(() => {
3063
3223
  const raw = routeOptions.fixedFromAmount;
3064
3224
  if (raw === null || raw === void 0) return void 0;
3065
- const str = String(raw).trim();
3066
- if (!str) return void 0;
3067
- const n = Number(str);
3068
- return Number.isFinite(n) && n > 0 ? str : void 0;
3225
+ const str2 = String(raw).trim();
3226
+ if (!str2) return void 0;
3227
+ const n = Number(str2);
3228
+ return Number.isFinite(n) && n > 0 ? str2 : void 0;
3069
3229
  }, [routeOptions.fixedFromAmount]);
3070
3230
  const fixedFromAmountValue = (0, import_react3.useMemo)(() => {
3071
3231
  if (!fixedFromAmountString) return void 0;
@@ -3146,133 +3306,6 @@ var init_registryClient = __esm({
3146
3306
  }
3147
3307
  });
3148
3308
 
3149
- // src/widget/helpers/chainHelpers.ts
3150
- function normalizeChainKey2(id) {
3151
- if (id === void 0 || id === null) return "";
3152
- return String(id).trim().toLowerCase();
3153
- }
3154
- function getNativeTokenAddress2(chainType) {
3155
- const normalized = chainType?.toLowerCase?.();
3156
- return normalized === "solana" ? NATIVE_SOLANA2 : NATIVE_EVM2;
3157
- }
3158
- function isSolanaNativeTokenAlias2(address) {
3159
- if (!address) return false;
3160
- const trimmed = address.trim();
3161
- if (!trimmed) return false;
3162
- return trimmed === NATIVE_SOLANA2 || trimmed.toLowerCase() === NATIVE_EVM2;
3163
- }
3164
- function parseDecimalToWei(input, decimals) {
3165
- if (!input?.trim()) return null;
3166
- const s = input.trim();
3167
- if (!/^\d*\.?\d*$/.test(s)) return null;
3168
- const [intPartRaw, fracRaw = ""] = s.split(".");
3169
- const intPart = intPartRaw.length ? BigInt(intPartRaw) : 0n;
3170
- const frac = (fracRaw + "0".repeat(decimals)).slice(0, decimals);
3171
- const fracPart = frac ? BigInt(frac) : 0n;
3172
- const base2 = 10n ** BigInt(decimals);
3173
- return intPart * base2 + fracPart;
3174
- }
3175
- function inferChainTypeFromValue2(normalized) {
3176
- if (!normalized) return void 0;
3177
- const aliased = CHAIN_TYPE_ALIASES2[normalized];
3178
- if (aliased) return aliased;
3179
- if (normalized === "evm" || normalized === "solana" || normalized === "cosmos" || normalized === "bitcoin") {
3180
- return normalized;
3181
- }
3182
- if (/^eip155:\d+$/.test(normalized) || /^\d+$/.test(normalized)) {
3183
- return "evm";
3184
- }
3185
- if (normalized.startsWith("solana:") || normalized.includes("solana")) {
3186
- return "solana";
3187
- }
3188
- if (normalized.startsWith("cosmos:") || normalized.startsWith("sei:") || normalized === "sei-evm") {
3189
- return "cosmos";
3190
- }
3191
- return void 0;
3192
- }
3193
- function normalizeChainType2(chain) {
3194
- if (!chain) return void 0;
3195
- const raw = typeof chain === "string" ? chain : chain.type ?? chain.chainType ?? chain.networkIdentifier ?? chain.chainId ?? chain.id ?? chain.networkName ?? chain.axelarChainName;
3196
- if (!raw) return void 0;
3197
- const normalized = String(raw).trim().toLowerCase();
3198
- return inferChainTypeFromValue2(normalized) ?? normalized;
3199
- }
3200
- function canonicalChainKeyForLink(chain) {
3201
- const seiKey = canonicalSeiChainKey(chain.chainId ?? chain.id);
3202
- if (seiKey) return seiKey;
3203
- return normalizeChainKey2(
3204
- chain.networkIdentifier ?? chain.axelarChainName ?? chain.id ?? chain.chainId ?? chain.networkName
3205
- );
3206
- }
3207
- function canonicalSeiChainKey(chainId) {
3208
- const normalized = normalizeChainKey2(chainId);
3209
- if (!normalized) return null;
3210
- if (normalized === SEI_EVM_CHAIN_ID) return "sei-evm";
3211
- if (normalized === SEI_COSMOS_CHAIN_ID) return "sei";
3212
- return null;
3213
- }
3214
- function isZeroAddrLike(a, chainType) {
3215
- if (!a) return true;
3216
- if (!chainType) return false;
3217
- const s = normalizeAddress2(a, chainType);
3218
- return s === normalizeAddress2(getNativeTokenAddress2(chainType), chainType) || s === "0x0000000000000000000000000000000000000000";
3219
- }
3220
- function normalizeAddress2(address, chainType) {
3221
- if (chainType?.toLowerCase?.() === "solana") {
3222
- const trimmed = address.trim();
3223
- if (isSolanaNativeTokenAlias2(trimmed)) {
3224
- return NATIVE_SOLANA2;
3225
- }
3226
- return trimmed;
3227
- }
3228
- return address.toLowerCase();
3229
- }
3230
- function isNativeTokenAddress(address, chainType) {
3231
- if (!address) return false;
3232
- if (!chainType) return false;
3233
- return normalizeAddress2(address, chainType) === normalizeAddress2(getNativeTokenAddress2(chainType), chainType);
3234
- }
3235
- function canonicalTokenAddressForChain(chain, address, chainTokens = []) {
3236
- const chainType = normalizeChainType2(chain);
3237
- const rawAddress = (address ?? "").trim();
3238
- if (chainType === "solana") return normalizeAddress2(rawAddress, "solana");
3239
- if (chainType === "cosmos") {
3240
- const chainIdKey = normalizeChainKey2(chain.chainId ?? chain.id ?? "");
3241
- const nativeSymbol = chain.nativeCurrency?.symbol?.toUpperCase?.();
3242
- const nativeFromRegistry = chainTokens.find(
3243
- (token) => normalizeChainKey2(token.chainId) === chainIdKey && token.symbol?.toUpperCase?.() === nativeSymbol
3244
- );
3245
- const nativeDenom = (nativeFromRegistry?.address ?? "usei").toLowerCase();
3246
- if (rawAddress.toLowerCase() === NATIVE_EVM2) {
3247
- return nativeDenom;
3248
- }
3249
- return rawAddress.toLowerCase();
3250
- }
3251
- const lowerAddress = rawAddress.toLowerCase();
3252
- if (lowerAddress === "0x0000000000000000000000000000000000000000") {
3253
- return NATIVE_EVM2;
3254
- }
3255
- return lowerAddress;
3256
- }
3257
- var NATIVE_EVM2, NATIVE_SOLANA2, CHAIN_TYPE_ALIASES2, SEI_EVM_CHAIN_ID, SEI_COSMOS_CHAIN_ID;
3258
- var init_chainHelpers = __esm({
3259
- "src/widget/helpers/chainHelpers.ts"() {
3260
- "use strict";
3261
- NATIVE_EVM2 = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
3262
- NATIVE_SOLANA2 = "So11111111111111111111111111111111111111111";
3263
- CHAIN_TYPE_ALIASES2 = {
3264
- btc: "bitcoin",
3265
- bitcoin: "bitcoin",
3266
- sei: "cosmos",
3267
- "pacific-1": "cosmos",
3268
- nibiru: "cosmos",
3269
- "cataclysm-1": "cosmos"
3270
- };
3271
- SEI_EVM_CHAIN_ID = "1329";
3272
- SEI_COSMOS_CHAIN_ID = "pacific-1";
3273
- }
3274
- });
3275
-
3276
3309
  // src/widget/helpers/tokenAmount.ts
3277
3310
  function rawToDecimal(rawAmount, decimals) {
3278
3311
  if (!rawAmount) return "0";
@@ -5419,6 +5452,52 @@ var init_useTransactionSubmit = __esm({
5419
5452
  }
5420
5453
  });
5421
5454
 
5455
+ // src/core/failure.ts
5456
+ function asRecord(value) {
5457
+ return typeof value === "object" && value !== null ? value : null;
5458
+ }
5459
+ function str(value) {
5460
+ return typeof value === "string" ? value.trim() : "";
5461
+ }
5462
+ function tidy(detail) {
5463
+ const collapsed = detail.replace(/\s+/g, " ").trim();
5464
+ return collapsed.length > MAX_DETAIL ? `${collapsed.slice(0, MAX_DETAIL - 1).trimEnd()}\u2026` : collapsed;
5465
+ }
5466
+ function describeTransactionFailure(tx) {
5467
+ const raw = asRecord(tx?.statusRaw);
5468
+ const substatus = str(raw?.substatus);
5469
+ const detail = str(raw?.substatusMessage) || str(raw?.reason) || str(raw?.error) || str(raw?.message);
5470
+ const haystack = `${substatus} ${detail}`.toLowerCase();
5471
+ if (/slippage|price impact|price movement/.test(haystack)) {
5472
+ return "Transaction failed due to price movement. Please try again with a higher slippage.";
5473
+ }
5474
+ if (/liquidity/.test(haystack)) {
5475
+ return "Transaction failed due to insufficient liquidity. Try a smaller amount.";
5476
+ }
5477
+ if (/timeout|timed out|expired/.test(haystack)) {
5478
+ return "Transaction expired. Please start a new transaction.";
5479
+ }
5480
+ if (/out.?of.?gas|insufficient (gas|fee)/.test(haystack)) {
5481
+ return "Transaction failed due to insufficient gas. Please ensure you have enough native tokens for gas.";
5482
+ }
5483
+ if (/insufficient (balance|funds)/.test(haystack)) {
5484
+ return "Transaction failed due to insufficient balance.";
5485
+ }
5486
+ if (tx?.gasStatus === "insufficient") {
5487
+ return "Transaction failed due to insufficient gas. Please ensure you have enough native tokens for gas.";
5488
+ }
5489
+ if (detail) return `Transaction failed on-chain: ${tidy(detail)}`;
5490
+ return GENERIC;
5491
+ }
5492
+ var MAX_DETAIL, GENERIC;
5493
+ var init_failure = __esm({
5494
+ "src/core/failure.ts"() {
5495
+ "use strict";
5496
+ MAX_DETAIL = 160;
5497
+ GENERIC = "Transaction failed on-chain. Please try again.";
5498
+ }
5499
+ });
5500
+
5422
5501
  // src/hooks/useGTM.ts
5423
5502
  function isGA4Allowed() {
5424
5503
  try {
@@ -5662,7 +5741,7 @@ function useTransactionPolling() {
5662
5741
  return;
5663
5742
  }
5664
5743
  if (tx.status === "failed") {
5665
- const failError = mapFailedTransactionError(tx);
5744
+ const failError = describeTransactionFailure(tx);
5666
5745
  clearPolling();
5667
5746
  setState((prev) => ({
5668
5747
  ...prev,
@@ -5801,29 +5880,6 @@ function mapReceiptError(err) {
5801
5880
  }
5802
5881
  return cleanedMsg || "Failed to submit transaction. Please try again.";
5803
5882
  }
5804
- function mapFailedTransactionError(tx) {
5805
- const statusRaw = tx.statusRaw;
5806
- if (typeof statusRaw === "object" && statusRaw !== null) {
5807
- const statusObj = statusRaw;
5808
- const reason = statusObj.reason || statusObj.error || statusObj.message;
5809
- if (reason) {
5810
- const reasonLower = String(reason).toLowerCase();
5811
- if (reasonLower.includes("slippage") || reasonLower.includes("price")) {
5812
- return "Transaction failed due to price movement. Please try again with a higher slippage.";
5813
- }
5814
- if (reasonLower.includes("liquidity")) {
5815
- return "Transaction failed due to insufficient liquidity. Try a smaller amount.";
5816
- }
5817
- if (reasonLower.includes("timeout") || reasonLower.includes("expired")) {
5818
- return "Transaction expired. Please start a new deposit.";
5819
- }
5820
- }
5821
- }
5822
- if (tx.gasStatus === "insufficient") {
5823
- return "Transaction failed due to insufficient gas. Please ensure you have enough native tokens for gas.";
5824
- }
5825
- return "Transaction failed. Please try again or contact support if the issue persists.";
5826
- }
5827
5883
  var import_react8, FAST_POLL_INTERVAL_MS, NORMAL_POLL_INTERVAL_MS, POLL_TIMEOUT_MS;
5828
5884
  var init_useTransactionPolling = __esm({
5829
5885
  "src/widget/hooks/useTransactionPolling.ts"() {
@@ -5832,6 +5888,7 @@ var init_useTransactionPolling = __esm({
5832
5888
  import_react8 = require("react");
5833
5889
  init_routes();
5834
5890
  init_http();
5891
+ init_failure();
5835
5892
  init_DepositContext();
5836
5893
  init_provider();
5837
5894
  init_core2();
@@ -33348,10 +33405,12 @@ function mapError(raw) {
33348
33405
  };
33349
33406
  }
33350
33407
  if (lower.includes("transaction failed") || lower.includes("reverted")) {
33408
+ const specific = msg.trim();
33409
+ const isBare = /^transaction (failed|reverted)[.!]?$/i.test(specific) || specific.length > 200 || specific.includes("\n");
33351
33410
  return {
33352
33411
  category: "transaction_failed",
33353
33412
  title: "Transaction Failed",
33354
- message: "The transaction could not be completed. Please try again."
33413
+ message: isBare ? "The transaction could not be completed. Please try again." : specific
33355
33414
  };
33356
33415
  }
33357
33416
  if (lower.includes("wrong network") || lower.includes("wrong chain") || lower.includes("chain mismatch")) {
@@ -33643,7 +33702,7 @@ function useSwapExecution(fromChain) {
33643
33702
  }
33644
33703
  if (tx.status === "failed") {
33645
33704
  clearPolling();
33646
- const msg = "Transaction failed on-chain. Please try again.";
33705
+ const msg = describeTransactionFailure(tx);
33647
33706
  setState((p) => ({ ...p, txStatus: "error", errorMessage: msg }));
33648
33707
  onError(msg);
33649
33708
  return;
@@ -33678,8 +33737,7 @@ function useSwapExecution(fromChain) {
33678
33737
  return;
33679
33738
  }
33680
33739
  const chainType = normalizeChainType2(fromChain);
33681
- const isNative = !fromTokenAddress || isNativeTokenAddress(fromTokenAddress, chainType) || isZeroAddrLike(fromTokenAddress, chainType);
33682
- if (isNative) {
33740
+ if (!needsErc20Approval(fromTokenAddress, chainType)) {
33683
33741
  setState((p) => ({ ...p, allowanceStatus: "sufficient" }));
33684
33742
  return;
33685
33743
  }
@@ -33693,7 +33751,7 @@ function useSwapExecution(fromChain) {
33693
33751
  BigInt(a.amount || "0"),
33694
33752
  amountWei
33695
33753
  );
33696
- if (!token || !a.spender) return [];
33754
+ if (!isEvmAddress2(token) || !isEvmAddress2(a.spender)) return [];
33697
33755
  return [
33698
33756
  {
33699
33757
  chainId: a.chainId || chainIdStr,
@@ -33841,7 +33899,8 @@ function useSwapExecution(fromChain) {
33841
33899
  const requiredApprovals = plannedApprovals.length ? plannedApprovals.flatMap((a, index) => {
33842
33900
  const token = a.tokenAddress ?? fromTokenAddress;
33843
33901
  const approvalSpender = a.spender;
33844
- if (!token || !approvalSpender) return [];
33902
+ if (!isEvmAddress2(token) || !isEvmAddress2(approvalSpender))
33903
+ return [];
33845
33904
  const amountWei = requiredApprovalAmount(
33846
33905
  BigInt(a.amount || "0"),
33847
33906
  fromAmountWei
@@ -33864,7 +33923,8 @@ function useSwapExecution(fromChain) {
33864
33923
  chainId: chainIdStr
33865
33924
  }
33866
33925
  ] : [];
33867
- const ownsApprovals = !isNative && !!walletAddress && !!chainIdStr;
33926
+ const coversEveryPlannedApproval = plannedApprovals.length === 0 || requiredApprovals.length === plannedApprovals.length;
33927
+ const ownsApprovals = coversEveryPlannedApproval && needsErc20Approval(fromTokenAddress, chainType) && !!walletAddress && !!chainIdStr;
33868
33928
  const activeAddress = ownsApprovals ? await requireActiveAddress(wallet, walletAddress) : void 0;
33869
33929
  for (const required of requiredApprovals) {
33870
33930
  if (!ownsApprovals) break;
@@ -34021,6 +34081,7 @@ var init_useSwapExecution = __esm({
34021
34081
  init_core2();
34022
34082
  init_routes();
34023
34083
  init_http();
34084
+ init_failure();
34024
34085
  init_tx();
34025
34086
  init_sdkRpc();
34026
34087
  init_chainHelpers();
@@ -35745,8 +35806,8 @@ function truncateDecimal(n, dp) {
35745
35806
  const s = truncated.toFixed(dp);
35746
35807
  return s.includes(".") ? s.replace(/\.?0+$/, "") || "0" : s;
35747
35808
  }
35748
- function scaleFontSize(str) {
35749
- const len = str.replace(/[^0-9.]/g, "").length;
35809
+ function scaleFontSize(str2) {
35810
+ const len = str2.replace(/[^0-9.]/g, "").length;
35750
35811
  if (len <= 6) return "2.5rem";
35751
35812
  if (len <= 9) return "2rem";
35752
35813
  if (len <= 12) return "1.5rem";
@@ -36045,6 +36106,10 @@ function SwapMode({
36045
36106
  }, [lockDestToken, fromToken, fromChain, toToken, toChain, route, emitEvent]);
36046
36107
  const fromChainType = normalizeChainType2(fromChain);
36047
36108
  const toChainType = normalizeChainType2(toChain);
36109
+ const canSetMaxApproval = needsErc20Approval(
36110
+ fromToken?.address,
36111
+ fromChainType
36112
+ );
36048
36113
  const needsDestAddress = !!fromChainType && !!toChainType && fromChainType !== toChainType;
36049
36114
  const isValidDestAddress = !needsDestAddress || validateDestAddress(destAddress, toChainType ?? "");
36050
36115
  const handleReview = (0, import_react50.useCallback)(async () => {
@@ -38265,7 +38330,7 @@ function SwapMode({
38265
38330
  }
38266
38331
  )
38267
38332
  ] }),
38268
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { style: { marginBottom: spacing[4] }, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
38333
+ canSetMaxApproval && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { style: { marginBottom: spacing[4] }, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
38269
38334
  "div",
38270
38335
  {
38271
38336
  style: {