@trustware/sdk-staging 1.1.12-staging.3 → 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.3";
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,144 +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 isEvmAddress2(value) {
3236
- return !!value && EVM_ADDRESS_RE.test(value);
3237
- }
3238
- function needsErc20Approval(tokenAddress, chainType) {
3239
- if (!isEvmAddress2(tokenAddress)) return false;
3240
- const normalizedType = normalizeChainType2(chainType ?? void 0);
3241
- if (normalizedType && NON_EVM_CHAIN_TYPES.has(normalizedType)) return false;
3242
- return !isNativeTokenAddress(tokenAddress, chainType) && !isZeroAddrLike(tokenAddress, chainType);
3243
- }
3244
- function canonicalTokenAddressForChain(chain, address, chainTokens = []) {
3245
- const chainType = normalizeChainType2(chain);
3246
- const rawAddress = (address ?? "").trim();
3247
- if (chainType === "solana") return normalizeAddress2(rawAddress, "solana");
3248
- if (chainType === "cosmos") {
3249
- const chainIdKey = normalizeChainKey2(chain.chainId ?? chain.id ?? "");
3250
- const nativeSymbol = chain.nativeCurrency?.symbol?.toUpperCase?.();
3251
- const nativeFromRegistry = chainTokens.find(
3252
- (token) => normalizeChainKey2(token.chainId) === chainIdKey && token.symbol?.toUpperCase?.() === nativeSymbol
3253
- );
3254
- const nativeDenom = (nativeFromRegistry?.address ?? "usei").toLowerCase();
3255
- if (rawAddress.toLowerCase() === NATIVE_EVM2) {
3256
- return nativeDenom;
3257
- }
3258
- return rawAddress.toLowerCase();
3259
- }
3260
- const lowerAddress = rawAddress.toLowerCase();
3261
- if (lowerAddress === "0x0000000000000000000000000000000000000000") {
3262
- return NATIVE_EVM2;
3263
- }
3264
- return lowerAddress;
3265
- }
3266
- var NATIVE_EVM2, NATIVE_SOLANA2, CHAIN_TYPE_ALIASES2, SEI_EVM_CHAIN_ID, SEI_COSMOS_CHAIN_ID, EVM_ADDRESS_RE, NON_EVM_CHAIN_TYPES;
3267
- var init_chainHelpers = __esm({
3268
- "src/widget/helpers/chainHelpers.ts"() {
3269
- "use strict";
3270
- NATIVE_EVM2 = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
3271
- NATIVE_SOLANA2 = "So11111111111111111111111111111111111111111";
3272
- CHAIN_TYPE_ALIASES2 = {
3273
- btc: "bitcoin",
3274
- bitcoin: "bitcoin",
3275
- sei: "cosmos",
3276
- "pacific-1": "cosmos",
3277
- nibiru: "cosmos",
3278
- "cataclysm-1": "cosmos"
3279
- };
3280
- SEI_EVM_CHAIN_ID = "1329";
3281
- SEI_COSMOS_CHAIN_ID = "pacific-1";
3282
- EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
3283
- NON_EVM_CHAIN_TYPES = /* @__PURE__ */ new Set(["solana", "bitcoin", "btc"]);
3284
- }
3285
- });
3286
-
3287
3309
  // src/widget/helpers/tokenAmount.ts
3288
3310
  function rawToDecimal(rawAmount, decimals) {
3289
3311
  if (!rawAmount) return "0";
@@ -5430,6 +5452,52 @@ var init_useTransactionSubmit = __esm({
5430
5452
  }
5431
5453
  });
5432
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
+
5433
5501
  // src/hooks/useGTM.ts
5434
5502
  function isGA4Allowed() {
5435
5503
  try {
@@ -5673,7 +5741,7 @@ function useTransactionPolling() {
5673
5741
  return;
5674
5742
  }
5675
5743
  if (tx.status === "failed") {
5676
- const failError = mapFailedTransactionError(tx);
5744
+ const failError = describeTransactionFailure(tx);
5677
5745
  clearPolling();
5678
5746
  setState((prev) => ({
5679
5747
  ...prev,
@@ -5812,29 +5880,6 @@ function mapReceiptError(err) {
5812
5880
  }
5813
5881
  return cleanedMsg || "Failed to submit transaction. Please try again.";
5814
5882
  }
5815
- function mapFailedTransactionError(tx) {
5816
- const statusRaw = tx.statusRaw;
5817
- if (typeof statusRaw === "object" && statusRaw !== null) {
5818
- const statusObj = statusRaw;
5819
- const reason = statusObj.reason || statusObj.error || statusObj.message;
5820
- if (reason) {
5821
- const reasonLower = String(reason).toLowerCase();
5822
- if (reasonLower.includes("slippage") || reasonLower.includes("price")) {
5823
- return "Transaction failed due to price movement. Please try again with a higher slippage.";
5824
- }
5825
- if (reasonLower.includes("liquidity")) {
5826
- return "Transaction failed due to insufficient liquidity. Try a smaller amount.";
5827
- }
5828
- if (reasonLower.includes("timeout") || reasonLower.includes("expired")) {
5829
- return "Transaction expired. Please start a new deposit.";
5830
- }
5831
- }
5832
- }
5833
- if (tx.gasStatus === "insufficient") {
5834
- return "Transaction failed due to insufficient gas. Please ensure you have enough native tokens for gas.";
5835
- }
5836
- return "Transaction failed. Please try again or contact support if the issue persists.";
5837
- }
5838
5883
  var import_react8, FAST_POLL_INTERVAL_MS, NORMAL_POLL_INTERVAL_MS, POLL_TIMEOUT_MS;
5839
5884
  var init_useTransactionPolling = __esm({
5840
5885
  "src/widget/hooks/useTransactionPolling.ts"() {
@@ -5843,6 +5888,7 @@ var init_useTransactionPolling = __esm({
5843
5888
  import_react8 = require("react");
5844
5889
  init_routes();
5845
5890
  init_http();
5891
+ init_failure();
5846
5892
  init_DepositContext();
5847
5893
  init_provider();
5848
5894
  init_core2();
@@ -33359,10 +33405,12 @@ function mapError(raw) {
33359
33405
  };
33360
33406
  }
33361
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");
33362
33410
  return {
33363
33411
  category: "transaction_failed",
33364
33412
  title: "Transaction Failed",
33365
- message: "The transaction could not be completed. Please try again."
33413
+ message: isBare ? "The transaction could not be completed. Please try again." : specific
33366
33414
  };
33367
33415
  }
33368
33416
  if (lower.includes("wrong network") || lower.includes("wrong chain") || lower.includes("chain mismatch")) {
@@ -33654,7 +33702,7 @@ function useSwapExecution(fromChain) {
33654
33702
  }
33655
33703
  if (tx.status === "failed") {
33656
33704
  clearPolling();
33657
- const msg = "Transaction failed on-chain. Please try again.";
33705
+ const msg = describeTransactionFailure(tx);
33658
33706
  setState((p) => ({ ...p, txStatus: "error", errorMessage: msg }));
33659
33707
  onError(msg);
33660
33708
  return;
@@ -34033,6 +34081,7 @@ var init_useSwapExecution = __esm({
34033
34081
  init_core2();
34034
34082
  init_routes();
34035
34083
  init_http();
34084
+ init_failure();
34036
34085
  init_tx();
34037
34086
  init_sdkRpc();
34038
34087
  init_chainHelpers();
@@ -35757,8 +35806,8 @@ function truncateDecimal(n, dp) {
35757
35806
  const s = truncated.toFixed(dp);
35758
35807
  return s.includes(".") ? s.replace(/\.?0+$/, "") || "0" : s;
35759
35808
  }
35760
- function scaleFontSize(str) {
35761
- const len = str.replace(/[^0-9.]/g, "").length;
35809
+ function scaleFontSize(str2) {
35810
+ const len = str2.replace(/[^0-9.]/g, "").length;
35762
35811
  if (len <= 6) return "2.5rem";
35763
35812
  if (len <= 9) return "2rem";
35764
35813
  if (len <= 12) return "1.5rem";