@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/index.mjs CHANGED
@@ -492,7 +492,7 @@ var init_constants = __esm({
492
492
  "src/constants.ts"() {
493
493
  "use strict";
494
494
  SDK_NAME = "@trustware/sdk";
495
- SDK_VERSION = "1.1.12-staging.2";
495
+ SDK_VERSION = "1.1.12-staging.4";
496
496
  API_ROOT = "https://bv-staging-api.trustware.io";
497
497
  GTM_ID = "GTM-TZDGNCXB";
498
498
  API_PREFIX = "/api";
@@ -2450,6 +2450,7 @@ function inferChainTypeFromValue(normalized) {
2450
2450
  if (normalized === "evm" || normalized === "solana" || normalized === "cosmos" || normalized === "bitcoin") {
2451
2451
  return normalized;
2452
2452
  }
2453
+ if (normalized === SOLANA_CHAIN_ID) return "solana";
2453
2454
  if (/^eip155:\d+$/.test(normalized) || /^\d+$/.test(normalized)) {
2454
2455
  return "evm";
2455
2456
  }
@@ -2496,12 +2497,13 @@ function isZeroAddressLike(address, chainType) {
2496
2497
  const normalized = normalizeAddress(address, chainType);
2497
2498
  return normalized === normalizeAddress(getNativeTokenAddress(chainType), chainType) || normalized === "0x0000000000000000000000000000000000000000";
2498
2499
  }
2499
- var NATIVE_EVM, NATIVE_SOLANA, CHAIN_TYPE_ALIASES;
2500
+ var NATIVE_EVM, NATIVE_SOLANA, SOLANA_CHAIN_ID, CHAIN_TYPE_ALIASES;
2500
2501
  var init_chains = __esm({
2501
2502
  "src/utils/chains.ts"() {
2502
2503
  "use strict";
2503
2504
  NATIVE_EVM = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
2504
2505
  NATIVE_SOLANA = "So11111111111111111111111111111111111111111";
2506
+ SOLANA_CHAIN_ID = "1151111081099710";
2505
2507
  CHAIN_TYPE_ALIASES = {
2506
2508
  btc: "bitcoin",
2507
2509
  bitcoin: "bitcoin",
@@ -4404,7 +4406,159 @@ var init_wallets = __esm({
4404
4406
  }
4405
4407
  });
4406
4408
 
4409
+ // src/widget/helpers/chainHelpers.ts
4410
+ function normalizeChainKey2(id) {
4411
+ if (id === void 0 || id === null) return "";
4412
+ return String(id).trim().toLowerCase();
4413
+ }
4414
+ function getNativeTokenAddress2(chainType) {
4415
+ const normalized = chainType?.toLowerCase?.();
4416
+ return normalized === "solana" ? NATIVE_SOLANA2 : NATIVE_EVM2;
4417
+ }
4418
+ function isSolanaNativeTokenAlias2(address) {
4419
+ if (!address) return false;
4420
+ const trimmed = address.trim();
4421
+ if (!trimmed) return false;
4422
+ return trimmed === NATIVE_SOLANA2 || trimmed.toLowerCase() === NATIVE_EVM2;
4423
+ }
4424
+ function parseDecimalToWei(input, decimals) {
4425
+ if (!input?.trim()) return null;
4426
+ const s = input.trim();
4427
+ if (!/^\d*\.?\d*$/.test(s)) return null;
4428
+ const [intPartRaw, fracRaw = ""] = s.split(".");
4429
+ const intPart = intPartRaw.length ? BigInt(intPartRaw) : 0n;
4430
+ const frac = (fracRaw + "0".repeat(decimals)).slice(0, decimals);
4431
+ const fracPart = frac ? BigInt(frac) : 0n;
4432
+ const base2 = 10n ** BigInt(decimals);
4433
+ return intPart * base2 + fracPart;
4434
+ }
4435
+ function inferChainTypeFromValue2(normalized) {
4436
+ if (!normalized) return void 0;
4437
+ const aliased = CHAIN_TYPE_ALIASES2[normalized];
4438
+ if (aliased) return aliased;
4439
+ if (normalized === "evm" || normalized === "solana" || normalized === "cosmos" || normalized === "bitcoin") {
4440
+ return normalized;
4441
+ }
4442
+ if (normalized === SOLANA_CHAIN_ID2) return "solana";
4443
+ if (/^eip155:\d+$/.test(normalized) || /^\d+$/.test(normalized)) {
4444
+ return "evm";
4445
+ }
4446
+ if (normalized.startsWith("solana:") || normalized.includes("solana")) {
4447
+ return "solana";
4448
+ }
4449
+ if (normalized.startsWith("cosmos:") || normalized.startsWith("sei:") || normalized === "sei-evm") {
4450
+ return "cosmos";
4451
+ }
4452
+ return void 0;
4453
+ }
4454
+ function normalizeChainType2(chain) {
4455
+ if (!chain) return void 0;
4456
+ const raw = typeof chain === "string" ? chain : chain.type ?? chain.chainType ?? chain.networkIdentifier ?? chain.chainId ?? chain.id ?? chain.networkName ?? chain.axelarChainName;
4457
+ if (!raw) return void 0;
4458
+ const normalized = String(raw).trim().toLowerCase();
4459
+ return inferChainTypeFromValue2(normalized) ?? normalized;
4460
+ }
4461
+ function canonicalChainKeyForLink(chain) {
4462
+ const seiKey = canonicalSeiChainKey(chain.chainId ?? chain.id);
4463
+ if (seiKey) return seiKey;
4464
+ return normalizeChainKey2(
4465
+ chain.networkIdentifier ?? chain.axelarChainName ?? chain.id ?? chain.chainId ?? chain.networkName
4466
+ );
4467
+ }
4468
+ function canonicalSeiChainKey(chainId) {
4469
+ const normalized = normalizeChainKey2(chainId);
4470
+ if (!normalized) return null;
4471
+ if (normalized === SEI_EVM_CHAIN_ID) return "sei-evm";
4472
+ if (normalized === SEI_COSMOS_CHAIN_ID) return "sei";
4473
+ return null;
4474
+ }
4475
+ function isZeroAddrLike(a, chainType) {
4476
+ if (!a) return true;
4477
+ if (!chainType) return false;
4478
+ const s = normalizeAddress2(a, chainType);
4479
+ return s === normalizeAddress2(getNativeTokenAddress2(chainType), chainType) || s === "0x0000000000000000000000000000000000000000";
4480
+ }
4481
+ function normalizeAddress2(address, chainType) {
4482
+ if (chainType?.toLowerCase?.() === "solana") {
4483
+ const trimmed = address.trim();
4484
+ if (isSolanaNativeTokenAlias2(trimmed)) {
4485
+ return NATIVE_SOLANA2;
4486
+ }
4487
+ return trimmed;
4488
+ }
4489
+ return address.toLowerCase();
4490
+ }
4491
+ function isNativeTokenAddress(address, chainType) {
4492
+ if (!address) return false;
4493
+ if (!chainType) return false;
4494
+ return normalizeAddress2(address, chainType) === normalizeAddress2(getNativeTokenAddress2(chainType), chainType);
4495
+ }
4496
+ function isEvmAddress2(value) {
4497
+ return !!value && EVM_ADDRESS_RE.test(value);
4498
+ }
4499
+ function needsErc20Approval(tokenAddress, chainType) {
4500
+ if (!isEvmAddress2(tokenAddress)) return false;
4501
+ const normalizedType = normalizeChainType2(chainType ?? void 0);
4502
+ if (normalizedType && NON_EVM_CHAIN_TYPES.has(normalizedType)) return false;
4503
+ return !isNativeTokenAddress(tokenAddress, chainType) && !isZeroAddrLike(tokenAddress, chainType);
4504
+ }
4505
+ function canonicalTokenAddressForChain(chain, address, chainTokens = []) {
4506
+ const chainType = normalizeChainType2(chain);
4507
+ const rawAddress = (address ?? "").trim();
4508
+ if (chainType === "solana") return normalizeAddress2(rawAddress, "solana");
4509
+ if (chainType === "cosmos") {
4510
+ const chainIdKey = normalizeChainKey2(chain.chainId ?? chain.id ?? "");
4511
+ const nativeSymbol = chain.nativeCurrency?.symbol?.toUpperCase?.();
4512
+ const nativeFromRegistry = chainTokens.find(
4513
+ (token) => normalizeChainKey2(token.chainId) === chainIdKey && token.symbol?.toUpperCase?.() === nativeSymbol
4514
+ );
4515
+ const nativeDenom = (nativeFromRegistry?.address ?? "usei").toLowerCase();
4516
+ if (rawAddress.toLowerCase() === NATIVE_EVM2) {
4517
+ return nativeDenom;
4518
+ }
4519
+ return rawAddress.toLowerCase();
4520
+ }
4521
+ const lowerAddress = rawAddress.toLowerCase();
4522
+ if (lowerAddress === "0x0000000000000000000000000000000000000000") {
4523
+ return NATIVE_EVM2;
4524
+ }
4525
+ return lowerAddress;
4526
+ }
4527
+ 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;
4528
+ var init_chainHelpers = __esm({
4529
+ "src/widget/helpers/chainHelpers.ts"() {
4530
+ "use strict";
4531
+ NATIVE_EVM2 = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
4532
+ NATIVE_SOLANA2 = "So11111111111111111111111111111111111111111";
4533
+ SOLANA_CHAIN_ID2 = "1151111081099710";
4534
+ CHAIN_TYPE_ALIASES2 = {
4535
+ btc: "bitcoin",
4536
+ bitcoin: "bitcoin",
4537
+ sei: "cosmos",
4538
+ "pacific-1": "cosmos",
4539
+ nibiru: "cosmos",
4540
+ "cataclysm-1": "cosmos"
4541
+ };
4542
+ SEI_EVM_CHAIN_ID = "1329";
4543
+ SEI_COSMOS_CHAIN_ID = "pacific-1";
4544
+ EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
4545
+ NON_EVM_CHAIN_TYPES = /* @__PURE__ */ new Set(["solana", "bitcoin", "btc"]);
4546
+ }
4547
+ });
4548
+
4407
4549
  // src/core/routes.ts
4550
+ function canonicalRouteToken(address, chain) {
4551
+ const chainType = normalizeChainType2(
4552
+ chain === void 0 || chain === null ? void 0 : String(chain)
4553
+ );
4554
+ if (chainType !== "solana") return address ?? "";
4555
+ if (!address) return SOLANA_NATIVE_ROUTE_TOKEN;
4556
+ const trimmed = address.trim();
4557
+ if (isSolanaNativeTokenAlias2(trimmed) || trimmed === "0x0000000000000000000000000000000000000000") {
4558
+ return SOLANA_NATIVE_ROUTE_TOKEN;
4559
+ }
4560
+ return trimmed;
4561
+ }
4408
4562
  function assertValidPostHook(hooks) {
4409
4563
  const postHook = hooks?.postHook;
4410
4564
  if (!postHook) return;
@@ -4449,6 +4603,8 @@ async function buildRoute(body, signal) {
4449
4603
  const url = `${apiBase()}/v1/routes/route`;
4450
4604
  const payload = {
4451
4605
  ...body,
4606
+ fromToken: canonicalRouteToken(body.fromToken, body.fromChain),
4607
+ toToken: canonicalRouteToken(body.toToken, body.toChain),
4452
4608
  slippageBps: body.slippageBps ?? (body.slippage === void 0 ? void 0 : Math.round(body.slippage * 100)),
4453
4609
  fromAmountUSD: body.fromAmountUSD ?? body.fromAmountUsd
4454
4610
  };
@@ -4488,6 +4644,8 @@ async function buildDepositAddress(body, signal) {
4488
4644
  const url = `${apiBase()}/v1/routes/deposit-address`;
4489
4645
  const payload = {
4490
4646
  ...body,
4647
+ fromToken: canonicalRouteToken(body.fromToken, body.fromChain),
4648
+ toToken: canonicalRouteToken(body.toToken, body.toChain),
4491
4649
  slippageBps: body.slippageBps ?? (body.slippage === void 0 ? void 0 : Math.round(body.slippage * 100)),
4492
4650
  fromAmountUSD: body.fromAmountUSD ?? body.fromAmountUsd
4493
4651
  };
@@ -4586,13 +4744,15 @@ async function pollStatus(intentId, { intervalMs = 2e3, timeoutMs = 5 * 6e4 } =
4586
4744
  await new Promise((r) => setTimeout(r, intervalMs));
4587
4745
  }
4588
4746
  }
4589
- var STATUS_WIRE_TO_CAMEL;
4747
+ var SOLANA_NATIVE_ROUTE_TOKEN, STATUS_WIRE_TO_CAMEL;
4590
4748
  var init_routes = __esm({
4591
4749
  "src/core/routes.ts"() {
4592
4750
  "use strict";
4593
4751
  init_http();
4594
4752
  init_store();
4595
4753
  init_address();
4754
+ init_chainHelpers();
4755
+ SOLANA_NATIVE_ROUTE_TOKEN = "So11111111111111111111111111111111111111112";
4596
4756
  STATUS_WIRE_TO_CAMEL = {
4597
4757
  intent_id: "intentId",
4598
4758
  from_address: "fromAddress",
@@ -5571,133 +5731,6 @@ var init_tx = __esm({
5571
5731
  }
5572
5732
  });
5573
5733
 
5574
- // src/widget/helpers/chainHelpers.ts
5575
- function normalizeChainKey2(id) {
5576
- if (id === void 0 || id === null) return "";
5577
- return String(id).trim().toLowerCase();
5578
- }
5579
- function getNativeTokenAddress2(chainType) {
5580
- const normalized = chainType?.toLowerCase?.();
5581
- return normalized === "solana" ? NATIVE_SOLANA2 : NATIVE_EVM2;
5582
- }
5583
- function isSolanaNativeTokenAlias2(address) {
5584
- if (!address) return false;
5585
- const trimmed = address.trim();
5586
- if (!trimmed) return false;
5587
- return trimmed === NATIVE_SOLANA2 || trimmed.toLowerCase() === NATIVE_EVM2;
5588
- }
5589
- function parseDecimalToWei(input, decimals) {
5590
- if (!input?.trim()) return null;
5591
- const s = input.trim();
5592
- if (!/^\d*\.?\d*$/.test(s)) return null;
5593
- const [intPartRaw, fracRaw = ""] = s.split(".");
5594
- const intPart = intPartRaw.length ? BigInt(intPartRaw) : 0n;
5595
- const frac = (fracRaw + "0".repeat(decimals)).slice(0, decimals);
5596
- const fracPart = frac ? BigInt(frac) : 0n;
5597
- const base2 = 10n ** BigInt(decimals);
5598
- return intPart * base2 + fracPart;
5599
- }
5600
- function inferChainTypeFromValue2(normalized) {
5601
- if (!normalized) return void 0;
5602
- const aliased = CHAIN_TYPE_ALIASES2[normalized];
5603
- if (aliased) return aliased;
5604
- if (normalized === "evm" || normalized === "solana" || normalized === "cosmos" || normalized === "bitcoin") {
5605
- return normalized;
5606
- }
5607
- if (/^eip155:\d+$/.test(normalized) || /^\d+$/.test(normalized)) {
5608
- return "evm";
5609
- }
5610
- if (normalized.startsWith("solana:") || normalized.includes("solana")) {
5611
- return "solana";
5612
- }
5613
- if (normalized.startsWith("cosmos:") || normalized.startsWith("sei:") || normalized === "sei-evm") {
5614
- return "cosmos";
5615
- }
5616
- return void 0;
5617
- }
5618
- function normalizeChainType2(chain) {
5619
- if (!chain) return void 0;
5620
- const raw = typeof chain === "string" ? chain : chain.type ?? chain.chainType ?? chain.networkIdentifier ?? chain.chainId ?? chain.id ?? chain.networkName ?? chain.axelarChainName;
5621
- if (!raw) return void 0;
5622
- const normalized = String(raw).trim().toLowerCase();
5623
- return inferChainTypeFromValue2(normalized) ?? normalized;
5624
- }
5625
- function canonicalChainKeyForLink(chain) {
5626
- const seiKey = canonicalSeiChainKey(chain.chainId ?? chain.id);
5627
- if (seiKey) return seiKey;
5628
- return normalizeChainKey2(
5629
- chain.networkIdentifier ?? chain.axelarChainName ?? chain.id ?? chain.chainId ?? chain.networkName
5630
- );
5631
- }
5632
- function canonicalSeiChainKey(chainId) {
5633
- const normalized = normalizeChainKey2(chainId);
5634
- if (!normalized) return null;
5635
- if (normalized === SEI_EVM_CHAIN_ID) return "sei-evm";
5636
- if (normalized === SEI_COSMOS_CHAIN_ID) return "sei";
5637
- return null;
5638
- }
5639
- function isZeroAddrLike(a, chainType) {
5640
- if (!a) return true;
5641
- if (!chainType) return false;
5642
- const s = normalizeAddress2(a, chainType);
5643
- return s === normalizeAddress2(getNativeTokenAddress2(chainType), chainType) || s === "0x0000000000000000000000000000000000000000";
5644
- }
5645
- function normalizeAddress2(address, chainType) {
5646
- if (chainType?.toLowerCase?.() === "solana") {
5647
- const trimmed = address.trim();
5648
- if (isSolanaNativeTokenAlias2(trimmed)) {
5649
- return NATIVE_SOLANA2;
5650
- }
5651
- return trimmed;
5652
- }
5653
- return address.toLowerCase();
5654
- }
5655
- function isNativeTokenAddress(address, chainType) {
5656
- if (!address) return false;
5657
- if (!chainType) return false;
5658
- return normalizeAddress2(address, chainType) === normalizeAddress2(getNativeTokenAddress2(chainType), chainType);
5659
- }
5660
- function canonicalTokenAddressForChain(chain, address, chainTokens = []) {
5661
- const chainType = normalizeChainType2(chain);
5662
- const rawAddress = (address ?? "").trim();
5663
- if (chainType === "solana") return normalizeAddress2(rawAddress, "solana");
5664
- if (chainType === "cosmos") {
5665
- const chainIdKey = normalizeChainKey2(chain.chainId ?? chain.id ?? "");
5666
- const nativeSymbol = chain.nativeCurrency?.symbol?.toUpperCase?.();
5667
- const nativeFromRegistry = chainTokens.find(
5668
- (token) => normalizeChainKey2(token.chainId) === chainIdKey && token.symbol?.toUpperCase?.() === nativeSymbol
5669
- );
5670
- const nativeDenom = (nativeFromRegistry?.address ?? "usei").toLowerCase();
5671
- if (rawAddress.toLowerCase() === NATIVE_EVM2) {
5672
- return nativeDenom;
5673
- }
5674
- return rawAddress.toLowerCase();
5675
- }
5676
- const lowerAddress = rawAddress.toLowerCase();
5677
- if (lowerAddress === "0x0000000000000000000000000000000000000000") {
5678
- return NATIVE_EVM2;
5679
- }
5680
- return lowerAddress;
5681
- }
5682
- var NATIVE_EVM2, NATIVE_SOLANA2, CHAIN_TYPE_ALIASES2, SEI_EVM_CHAIN_ID, SEI_COSMOS_CHAIN_ID;
5683
- var init_chainHelpers = __esm({
5684
- "src/widget/helpers/chainHelpers.ts"() {
5685
- "use strict";
5686
- NATIVE_EVM2 = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
5687
- NATIVE_SOLANA2 = "So11111111111111111111111111111111111111111";
5688
- CHAIN_TYPE_ALIASES2 = {
5689
- btc: "bitcoin",
5690
- bitcoin: "bitcoin",
5691
- sei: "cosmos",
5692
- "pacific-1": "cosmos",
5693
- nibiru: "cosmos",
5694
- "cataclysm-1": "cosmos"
5695
- };
5696
- SEI_EVM_CHAIN_ID = "1329";
5697
- SEI_COSMOS_CHAIN_ID = "pacific-1";
5698
- }
5699
- });
5700
-
5701
5734
  // src/widget/helpers/tokenAmount.ts
5702
5735
  function rawToDecimal(rawAmount, decimals) {
5703
5736
  if (!rawAmount) return "0";
@@ -8855,9 +8888,9 @@ var init_useRouteBuilder = __esm({
8855
8888
  import { useMemo as useMemo7 } from "react";
8856
8889
  function parsePositiveNumber(value) {
8857
8890
  if (value === null || value === void 0) return void 0;
8858
- const str = String(value).trim();
8859
- if (!str) return void 0;
8860
- const n = Number(str);
8891
+ const str2 = String(value).trim();
8892
+ if (!str2) return void 0;
8893
+ const n = Number(str2);
8861
8894
  return Number.isFinite(n) && n >= 0 ? n : void 0;
8862
8895
  }
8863
8896
  function useAmountConstraints() {
@@ -8866,10 +8899,10 @@ function useAmountConstraints() {
8866
8899
  const fixedFromAmountString = useMemo7(() => {
8867
8900
  const raw = routeOptions.fixedFromAmount;
8868
8901
  if (raw === null || raw === void 0) return void 0;
8869
- const str = String(raw).trim();
8870
- if (!str) return void 0;
8871
- const n = Number(str);
8872
- return Number.isFinite(n) && n > 0 ? str : void 0;
8902
+ const str2 = String(raw).trim();
8903
+ if (!str2) return void 0;
8904
+ const n = Number(str2);
8905
+ return Number.isFinite(n) && n > 0 ? str2 : void 0;
8873
8906
  }, [routeOptions.fixedFromAmount]);
8874
8907
  const fixedFromAmountValue = useMemo7(() => {
8875
8908
  if (!fixedFromAmountString) return void 0;
@@ -9061,6 +9094,52 @@ var init_useTransactionSubmit = __esm({
9061
9094
  }
9062
9095
  });
9063
9096
 
9097
+ // src/core/failure.ts
9098
+ function asRecord(value) {
9099
+ return typeof value === "object" && value !== null ? value : null;
9100
+ }
9101
+ function str(value) {
9102
+ return typeof value === "string" ? value.trim() : "";
9103
+ }
9104
+ function tidy(detail) {
9105
+ const collapsed = detail.replace(/\s+/g, " ").trim();
9106
+ return collapsed.length > MAX_DETAIL ? `${collapsed.slice(0, MAX_DETAIL - 1).trimEnd()}\u2026` : collapsed;
9107
+ }
9108
+ function describeTransactionFailure(tx) {
9109
+ const raw = asRecord(tx?.statusRaw);
9110
+ const substatus = str(raw?.substatus);
9111
+ const detail = str(raw?.substatusMessage) || str(raw?.reason) || str(raw?.error) || str(raw?.message);
9112
+ const haystack = `${substatus} ${detail}`.toLowerCase();
9113
+ if (/slippage|price impact|price movement/.test(haystack)) {
9114
+ return "Transaction failed due to price movement. Please try again with a higher slippage.";
9115
+ }
9116
+ if (/liquidity/.test(haystack)) {
9117
+ return "Transaction failed due to insufficient liquidity. Try a smaller amount.";
9118
+ }
9119
+ if (/timeout|timed out|expired/.test(haystack)) {
9120
+ return "Transaction expired. Please start a new transaction.";
9121
+ }
9122
+ if (/out.?of.?gas|insufficient (gas|fee)/.test(haystack)) {
9123
+ return "Transaction failed due to insufficient gas. Please ensure you have enough native tokens for gas.";
9124
+ }
9125
+ if (/insufficient (balance|funds)/.test(haystack)) {
9126
+ return "Transaction failed due to insufficient balance.";
9127
+ }
9128
+ if (tx?.gasStatus === "insufficient") {
9129
+ return "Transaction failed due to insufficient gas. Please ensure you have enough native tokens for gas.";
9130
+ }
9131
+ if (detail) return `Transaction failed on-chain: ${tidy(detail)}`;
9132
+ return GENERIC;
9133
+ }
9134
+ var MAX_DETAIL, GENERIC;
9135
+ var init_failure = __esm({
9136
+ "src/core/failure.ts"() {
9137
+ "use strict";
9138
+ MAX_DETAIL = 160;
9139
+ GENERIC = "Transaction failed on-chain. Please try again.";
9140
+ }
9141
+ });
9142
+
9064
9143
  // src/hooks/useGTM.ts
9065
9144
  import { useEffect as useEffect11, useRef as useRef3, useCallback as useCallback8 } from "react";
9066
9145
  function isGA4Allowed() {
@@ -9305,7 +9384,7 @@ function useTransactionPolling() {
9305
9384
  return;
9306
9385
  }
9307
9386
  if (tx.status === "failed") {
9308
- const failError = mapFailedTransactionError(tx);
9387
+ const failError = describeTransactionFailure(tx);
9309
9388
  clearPolling();
9310
9389
  setState((prev) => ({
9311
9390
  ...prev,
@@ -9444,29 +9523,6 @@ function mapReceiptError(err) {
9444
9523
  }
9445
9524
  return cleanedMsg || "Failed to submit transaction. Please try again.";
9446
9525
  }
9447
- function mapFailedTransactionError(tx) {
9448
- const statusRaw = tx.statusRaw;
9449
- if (typeof statusRaw === "object" && statusRaw !== null) {
9450
- const statusObj = statusRaw;
9451
- const reason = statusObj.reason || statusObj.error || statusObj.message;
9452
- if (reason) {
9453
- const reasonLower = String(reason).toLowerCase();
9454
- if (reasonLower.includes("slippage") || reasonLower.includes("price")) {
9455
- return "Transaction failed due to price movement. Please try again with a higher slippage.";
9456
- }
9457
- if (reasonLower.includes("liquidity")) {
9458
- return "Transaction failed due to insufficient liquidity. Try a smaller amount.";
9459
- }
9460
- if (reasonLower.includes("timeout") || reasonLower.includes("expired")) {
9461
- return "Transaction expired. Please start a new deposit.";
9462
- }
9463
- }
9464
- }
9465
- if (tx.gasStatus === "insufficient") {
9466
- return "Transaction failed due to insufficient gas. Please ensure you have enough native tokens for gas.";
9467
- }
9468
- return "Transaction failed. Please try again or contact support if the issue persists.";
9469
- }
9470
9526
  var FAST_POLL_INTERVAL_MS, NORMAL_POLL_INTERVAL_MS, POLL_TIMEOUT_MS;
9471
9527
  var init_useTransactionPolling = __esm({
9472
9528
  "src/widget/hooks/useTransactionPolling.ts"() {
@@ -9474,6 +9530,7 @@ var init_useTransactionPolling = __esm({
9474
9530
  "use client";
9475
9531
  init_routes();
9476
9532
  init_http();
9533
+ init_failure();
9477
9534
  init_DepositContext();
9478
9535
  init_provider();
9479
9536
  init_core2();
@@ -33454,10 +33511,12 @@ function mapError(raw) {
33454
33511
  };
33455
33512
  }
33456
33513
  if (lower.includes("transaction failed") || lower.includes("reverted")) {
33514
+ const specific = msg.trim();
33515
+ const isBare = /^transaction (failed|reverted)[.!]?$/i.test(specific) || specific.length > 200 || specific.includes("\n");
33457
33516
  return {
33458
33517
  category: "transaction_failed",
33459
33518
  title: "Transaction Failed",
33460
- message: "The transaction could not be completed. Please try again."
33519
+ message: isBare ? "The transaction could not be completed. Please try again." : specific
33461
33520
  };
33462
33521
  }
33463
33522
  if (lower.includes("wrong network") || lower.includes("wrong chain") || lower.includes("chain mismatch")) {
@@ -33749,7 +33808,7 @@ function useSwapExecution(fromChain) {
33749
33808
  }
33750
33809
  if (tx.status === "failed") {
33751
33810
  clearPolling();
33752
- const msg = "Transaction failed on-chain. Please try again.";
33811
+ const msg = describeTransactionFailure(tx);
33753
33812
  setState((p) => ({ ...p, txStatus: "error", errorMessage: msg }));
33754
33813
  onError(msg);
33755
33814
  return;
@@ -33784,8 +33843,7 @@ function useSwapExecution(fromChain) {
33784
33843
  return;
33785
33844
  }
33786
33845
  const chainType = normalizeChainType2(fromChain);
33787
- const isNative = !fromTokenAddress || isNativeTokenAddress(fromTokenAddress, chainType) || isZeroAddrLike(fromTokenAddress, chainType);
33788
- if (isNative) {
33846
+ if (!needsErc20Approval(fromTokenAddress, chainType)) {
33789
33847
  setState((p) => ({ ...p, allowanceStatus: "sufficient" }));
33790
33848
  return;
33791
33849
  }
@@ -33799,7 +33857,7 @@ function useSwapExecution(fromChain) {
33799
33857
  BigInt(a.amount || "0"),
33800
33858
  amountWei
33801
33859
  );
33802
- if (!token || !a.spender) return [];
33860
+ if (!isEvmAddress2(token) || !isEvmAddress2(a.spender)) return [];
33803
33861
  return [
33804
33862
  {
33805
33863
  chainId: a.chainId || chainIdStr,
@@ -33947,7 +34005,8 @@ function useSwapExecution(fromChain) {
33947
34005
  const requiredApprovals = plannedApprovals.length ? plannedApprovals.flatMap((a, index) => {
33948
34006
  const token = a.tokenAddress ?? fromTokenAddress;
33949
34007
  const approvalSpender = a.spender;
33950
- if (!token || !approvalSpender) return [];
34008
+ if (!isEvmAddress2(token) || !isEvmAddress2(approvalSpender))
34009
+ return [];
33951
34010
  const amountWei = requiredApprovalAmount(
33952
34011
  BigInt(a.amount || "0"),
33953
34012
  fromAmountWei
@@ -33970,7 +34029,8 @@ function useSwapExecution(fromChain) {
33970
34029
  chainId: chainIdStr
33971
34030
  }
33972
34031
  ] : [];
33973
- const ownsApprovals = !isNative && !!walletAddress && !!chainIdStr;
34032
+ const coversEveryPlannedApproval = plannedApprovals.length === 0 || requiredApprovals.length === plannedApprovals.length;
34033
+ const ownsApprovals = coversEveryPlannedApproval && needsErc20Approval(fromTokenAddress, chainType) && !!walletAddress && !!chainIdStr;
33974
34034
  const activeAddress = ownsApprovals ? await requireActiveAddress(wallet, walletAddress) : void 0;
33975
34035
  for (const required of requiredApprovals) {
33976
34036
  if (!ownsApprovals) break;
@@ -34125,6 +34185,7 @@ var init_useSwapExecution = __esm({
34125
34185
  init_core2();
34126
34186
  init_routes();
34127
34187
  init_http();
34188
+ init_failure();
34128
34189
  init_tx();
34129
34190
  init_sdkRpc();
34130
34191
  init_chainHelpers();
@@ -35858,8 +35919,8 @@ function truncateDecimal(n, dp) {
35858
35919
  const s = truncated.toFixed(dp);
35859
35920
  return s.includes(".") ? s.replace(/\.?0+$/, "") || "0" : s;
35860
35921
  }
35861
- function scaleFontSize(str) {
35862
- const len = str.replace(/[^0-9.]/g, "").length;
35922
+ function scaleFontSize(str2) {
35923
+ const len = str2.replace(/[^0-9.]/g, "").length;
35863
35924
  if (len <= 6) return "2.5rem";
35864
35925
  if (len <= 9) return "2rem";
35865
35926
  if (len <= 12) return "1.5rem";
@@ -36158,6 +36219,10 @@ function SwapMode({
36158
36219
  }, [lockDestToken, fromToken, fromChain, toToken, toChain, route, emitEvent]);
36159
36220
  const fromChainType = normalizeChainType2(fromChain);
36160
36221
  const toChainType = normalizeChainType2(toChain);
36222
+ const canSetMaxApproval = needsErc20Approval(
36223
+ fromToken?.address,
36224
+ fromChainType
36225
+ );
36161
36226
  const needsDestAddress = !!fromChainType && !!toChainType && fromChainType !== toChainType;
36162
36227
  const isValidDestAddress = !needsDestAddress || validateDestAddress(destAddress, toChainType ?? "");
36163
36228
  const handleReview = useCallback22(async () => {
@@ -38378,7 +38443,7 @@ function SwapMode({
38378
38443
  }
38379
38444
  )
38380
38445
  ] }),
38381
- /* @__PURE__ */ jsx59("div", { style: { marginBottom: spacing[4] }, children: /* @__PURE__ */ jsxs47(
38446
+ canSetMaxApproval && /* @__PURE__ */ jsx59("div", { style: { marginBottom: spacing[4] }, children: /* @__PURE__ */ jsxs47(
38382
38447
  "div",
38383
38448
  {
38384
38449
  style: {