@trustware/sdk-staging 1.1.12-staging.3 → 1.1.12-staging.5

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.3";
574
+ SDK_VERSION = "1.1.12-staging.5";
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,144 +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 isEvmAddress2(value) {
3211
- return !!value && EVM_ADDRESS_RE.test(value);
3212
- }
3213
- function needsErc20Approval(tokenAddress, chainType) {
3214
- if (!isEvmAddress2(tokenAddress)) return false;
3215
- const normalizedType = normalizeChainType2(chainType ?? void 0);
3216
- if (normalizedType && NON_EVM_CHAIN_TYPES.has(normalizedType)) return false;
3217
- return !isNativeTokenAddress(tokenAddress, chainType) && !isZeroAddrLike(tokenAddress, chainType);
3218
- }
3219
- function canonicalTokenAddressForChain(chain, address, chainTokens = []) {
3220
- const chainType = normalizeChainType2(chain);
3221
- const rawAddress = (address ?? "").trim();
3222
- if (chainType === "solana") return normalizeAddress2(rawAddress, "solana");
3223
- if (chainType === "cosmos") {
3224
- const chainIdKey = normalizeChainKey2(chain.chainId ?? chain.id ?? "");
3225
- const nativeSymbol = chain.nativeCurrency?.symbol?.toUpperCase?.();
3226
- const nativeFromRegistry = chainTokens.find(
3227
- (token) => normalizeChainKey2(token.chainId) === chainIdKey && token.symbol?.toUpperCase?.() === nativeSymbol
3228
- );
3229
- const nativeDenom = (nativeFromRegistry?.address ?? "usei").toLowerCase();
3230
- if (rawAddress.toLowerCase() === NATIVE_EVM2) {
3231
- return nativeDenom;
3232
- }
3233
- return rawAddress.toLowerCase();
3234
- }
3235
- const lowerAddress = rawAddress.toLowerCase();
3236
- if (lowerAddress === "0x0000000000000000000000000000000000000000") {
3237
- return NATIVE_EVM2;
3238
- }
3239
- return lowerAddress;
3240
- }
3241
- var NATIVE_EVM2, NATIVE_SOLANA2, CHAIN_TYPE_ALIASES2, SEI_EVM_CHAIN_ID, SEI_COSMOS_CHAIN_ID, EVM_ADDRESS_RE, NON_EVM_CHAIN_TYPES;
3242
- var init_chainHelpers = __esm({
3243
- "src/widget/helpers/chainHelpers.ts"() {
3244
- "use strict";
3245
- NATIVE_EVM2 = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
3246
- NATIVE_SOLANA2 = "So11111111111111111111111111111111111111111";
3247
- CHAIN_TYPE_ALIASES2 = {
3248
- btc: "bitcoin",
3249
- bitcoin: "bitcoin",
3250
- sei: "cosmos",
3251
- "pacific-1": "cosmos",
3252
- nibiru: "cosmos",
3253
- "cataclysm-1": "cosmos"
3254
- };
3255
- SEI_EVM_CHAIN_ID = "1329";
3256
- SEI_COSMOS_CHAIN_ID = "pacific-1";
3257
- EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
3258
- NON_EVM_CHAIN_TYPES = /* @__PURE__ */ new Set(["solana", "bitcoin", "btc"]);
3259
- }
3260
- });
3261
-
3262
3284
  // src/widget/helpers/tokenAmount.ts
3263
3285
  function rawToDecimal(rawAmount, decimals) {
3264
3286
  if (!rawAmount) return "0";
@@ -5404,6 +5426,52 @@ var init_useTransactionSubmit = __esm({
5404
5426
  }
5405
5427
  });
5406
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
+
5407
5475
  // src/hooks/useGTM.ts
5408
5476
  import { useEffect as useEffect5, useRef as useRef2, useCallback as useCallback2 } from "react";
5409
5477
  function isGA4Allowed() {
@@ -5648,7 +5716,7 @@ function useTransactionPolling() {
5648
5716
  return;
5649
5717
  }
5650
5718
  if (tx.status === "failed") {
5651
- const failError = mapFailedTransactionError(tx);
5719
+ const failError = describeTransactionFailure(tx);
5652
5720
  clearPolling();
5653
5721
  setState((prev) => ({
5654
5722
  ...prev,
@@ -5787,29 +5855,6 @@ function mapReceiptError(err) {
5787
5855
  }
5788
5856
  return cleanedMsg || "Failed to submit transaction. Please try again.";
5789
5857
  }
5790
- function mapFailedTransactionError(tx) {
5791
- const statusRaw = tx.statusRaw;
5792
- if (typeof statusRaw === "object" && statusRaw !== null) {
5793
- const statusObj = statusRaw;
5794
- const reason = statusObj.reason || statusObj.error || statusObj.message;
5795
- if (reason) {
5796
- const reasonLower = String(reason).toLowerCase();
5797
- if (reasonLower.includes("slippage") || reasonLower.includes("price")) {
5798
- return "Transaction failed due to price movement. Please try again with a higher slippage.";
5799
- }
5800
- if (reasonLower.includes("liquidity")) {
5801
- return "Transaction failed due to insufficient liquidity. Try a smaller amount.";
5802
- }
5803
- if (reasonLower.includes("timeout") || reasonLower.includes("expired")) {
5804
- return "Transaction expired. Please start a new deposit.";
5805
- }
5806
- }
5807
- }
5808
- if (tx.gasStatus === "insufficient") {
5809
- return "Transaction failed due to insufficient gas. Please ensure you have enough native tokens for gas.";
5810
- }
5811
- return "Transaction failed. Please try again or contact support if the issue persists.";
5812
- }
5813
5858
  var FAST_POLL_INTERVAL_MS, NORMAL_POLL_INTERVAL_MS, POLL_TIMEOUT_MS;
5814
5859
  var init_useTransactionPolling = __esm({
5815
5860
  "src/widget/hooks/useTransactionPolling.ts"() {
@@ -5817,6 +5862,7 @@ var init_useTransactionPolling = __esm({
5817
5862
  "use client";
5818
5863
  init_routes();
5819
5864
  init_http();
5865
+ init_failure();
5820
5866
  init_DepositContext();
5821
5867
  init_provider();
5822
5868
  init_core2();
@@ -33302,10 +33348,12 @@ function mapError(raw) {
33302
33348
  };
33303
33349
  }
33304
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");
33305
33353
  return {
33306
33354
  category: "transaction_failed",
33307
33355
  title: "Transaction Failed",
33308
- message: "The transaction could not be completed. Please try again."
33356
+ message: isBare ? "The transaction could not be completed. Please try again." : specific
33309
33357
  };
33310
33358
  }
33311
33359
  if (lower.includes("wrong network") || lower.includes("wrong chain") || lower.includes("chain mismatch")) {
@@ -33597,7 +33645,7 @@ function useSwapExecution(fromChain) {
33597
33645
  }
33598
33646
  if (tx.status === "failed") {
33599
33647
  clearPolling();
33600
- const msg = "Transaction failed on-chain. Please try again.";
33648
+ const msg = describeTransactionFailure(tx);
33601
33649
  setState((p) => ({ ...p, txStatus: "error", errorMessage: msg }));
33602
33650
  onError(msg);
33603
33651
  return;
@@ -33974,6 +34022,7 @@ var init_useSwapExecution = __esm({
33974
34022
  init_core2();
33975
34023
  init_routes();
33976
34024
  init_http();
34025
+ init_failure();
33977
34026
  init_tx();
33978
34027
  init_sdkRpc();
33979
34028
  init_chainHelpers();
@@ -35707,8 +35756,8 @@ function truncateDecimal(n, dp) {
35707
35756
  const s = truncated.toFixed(dp);
35708
35757
  return s.includes(".") ? s.replace(/\.?0+$/, "") || "0" : s;
35709
35758
  }
35710
- function scaleFontSize(str) {
35711
- const len = str.replace(/[^0-9.]/g, "").length;
35759
+ function scaleFontSize(str2) {
35760
+ const len = str2.replace(/[^0-9.]/g, "").length;
35712
35761
  if (len <= 6) return "2.5rem";
35713
35762
  if (len <= 9) return "2rem";
35714
35763
  if (len <= 12) return "1.5rem";