@0xsquid/react-hooks 8.11.1-beta-danal.2 → 8.12.1-beta-arc.0

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.
Files changed (69) hide show
  1. package/dist/core/canton/cantonConnector.d.ts +5 -2
  2. package/dist/core/canton/errors.d.ts +4 -0
  3. package/dist/core/canton/loopCantonConnector.d.ts +38 -0
  4. package/dist/core/client/index.d.ts +0 -1
  5. package/dist/core/constants.d.ts +1 -2
  6. package/dist/core/types/canton.d.ts +37 -3
  7. package/dist/core/types/index.d.ts +1 -1
  8. package/dist/core/types/tokens.d.ts +1 -8
  9. package/dist/core/types/wallet.d.ts +1 -8
  10. package/dist/hooks/chains/useSquidChains.d.ts +0 -1
  11. package/dist/hooks/store/useDepositAddressStore.d.ts +0 -6
  12. package/dist/hooks/swap/useDepositAddress.d.ts +0 -2
  13. package/dist/hooks/tokens/useSquidTokens.d.ts +0 -1
  14. package/dist/hooks/transaction/send/useEstimateSendTransactionGas.d.ts +3 -0
  15. package/dist/hooks/wallet/useMultiChainWallet.d.ts +0 -38
  16. package/dist/hooks/wallet/useWallet.d.ts +0 -42
  17. package/dist/{index-nTqoaD0B.js → index-BBJD55XX.js} +1110 -593
  18. package/dist/index-BBJD55XX.js.map +1 -0
  19. package/dist/{index-ByakOYXP.js → index-CLzjMzS_.js} +1109 -590
  20. package/dist/index-CLzjMzS_.js.map +1 -0
  21. package/dist/{index.es-DtFDz6qc.js → index.es-BVCh4tlV.js} +2 -2
  22. package/dist/{index.es-DtFDz6qc.js.map → index.es-BVCh4tlV.js.map} +1 -1
  23. package/dist/{index.es--AR2n7a0.js → index.es-BiK_wjSb.js} +2 -2
  24. package/dist/{index.es--AR2n7a0.js.map → index.es-BiK_wjSb.js.map} +1 -1
  25. package/dist/index.esm.js +1 -1
  26. package/dist/index.js +3 -5
  27. package/dist/index.js.map +1 -1
  28. package/dist/{secretService-29Ak2qp5.js → secretService-BZ06HTOJ.js} +2 -2
  29. package/dist/{secretService-29Ak2qp5.js.map → secretService-BZ06HTOJ.js.map} +1 -1
  30. package/dist/{secretService-cgr3P1zw.js → secretService-DkE9yz1o.js} +2 -2
  31. package/dist/{secretService-cgr3P1zw.js.map → secretService-DkE9yz1o.js.map} +1 -1
  32. package/dist/server.esm.js +1 -6
  33. package/dist/server.esm.js.map +1 -1
  34. package/dist/server.js +1 -6
  35. package/dist/server.js.map +1 -1
  36. package/dist/services/external/rpcService.d.ts +2 -4
  37. package/dist/services/index.d.ts +0 -1
  38. package/dist/services/internal/arcService.d.ts +7 -0
  39. package/dist/services/internal/assetsService.d.ts +9 -3
  40. package/dist/services/internal/cantonService.d.ts +2 -0
  41. package/dist/services/internal/cantonTransferService.d.ts +3 -3
  42. package/dist/services/internal/configService.d.ts +14 -3
  43. package/dist/services/internal/estimateService.d.ts +13 -3
  44. package/dist/services/internal/searchService.d.ts +1 -2
  45. package/dist/services/internal/tempoService.d.ts +2 -0
  46. package/dist/services/internal/transactionService.d.ts +0 -8
  47. package/dist/services/internal/walletService.d.ts +1 -1
  48. package/dist/{stellarService.client-B__dTUBZ.js → stellarService.client-DtA9zkRt.js} +2 -2
  49. package/dist/{stellarService.client-B__dTUBZ.js.map → stellarService.client-DtA9zkRt.js.map} +1 -1
  50. package/dist/{stellarService.client-D-zkMI5s.js → stellarService.client-fnyXRadt.js} +2 -2
  51. package/dist/{stellarService.client-D-zkMI5s.js.map → stellarService.client-fnyXRadt.js.map} +1 -1
  52. package/dist/tests/arcConfigService.test.d.ts +1 -0
  53. package/dist/tests/arcGasAccounting.test.d.ts +1 -0
  54. package/dist/tests/arcWalletService.test.d.ts +1 -0
  55. package/dist/tests/fixtures/arc.d.ts +8 -0
  56. package/dist/tests/loopCantonConnector.test.d.ts +1 -0
  57. package/dist/tests/loopSdkContract.test.d.ts +1 -0
  58. package/dist/tests/useArcApproval.test.d.ts +1 -0
  59. package/dist/tests/useArcSendEstimate.test.d.ts +1 -0
  60. package/dist/tests/useAutoConnectCanton.test.d.ts +1 -0
  61. package/dist/tests/useCantonRestoration.test.d.ts +1 -0
  62. package/dist/tests/useNativeTokenForChain.test.d.ts +1 -0
  63. package/dist/tests/useSwapArcSelection.test.d.ts +1 -0
  64. package/package.json +3 -2
  65. package/dist/core/types/danal.d.ts +0 -1
  66. package/dist/index-ByakOYXP.js.map +0 -1
  67. package/dist/index-nTqoaD0B.js.map +0 -1
  68. package/dist/services/internal/danalService.d.ts +0 -8
  69. /package/dist/tests/{danalService.test.d.ts → arcAssetsService.test.d.ts} +0 -0
@@ -59,7 +59,6 @@ const suiZeroAddress = "0x0000000000000000000000000000000000000000";
59
59
  const xrplZeroAddress = "rrrrrrrrrrrrrrrrrrrrrhoLvTp";
60
60
  const stellarZeroAddress = "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF";
61
61
  const cantonZeroAddress = "none::12200000000000000000000000000000000000000000000000000000000000000000";
62
- const danalZeroAddress = "PCI00000000000000000000000000000000000000000000000000";
63
62
  const chainTypeToZeroAddressMap = {
64
63
  [ChainType.EVM]: zeroAddress$1,
65
64
  [ChainType.COSMOS]: cosmosZeroAddress,
@@ -69,7 +68,6 @@ const chainTypeToZeroAddressMap = {
69
68
  [ChainType.XRPL]: xrplZeroAddress,
70
69
  [ChainType.STELLAR]: stellarZeroAddress,
71
70
  [ChainType.CANTON]: cantonZeroAddress,
72
- [ChainType.DANAL]: danalZeroAddress,
73
71
  };
74
72
  const nativeEvmTokenAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
75
73
  const nativeCosmosTokenAddress = "uosmo";
@@ -79,7 +77,6 @@ const nativeSuiTokenAddress = "0x00000000000000000000000000000000000000000000000
79
77
  const nativeXrplTokenAddress = "xrp";
80
78
  const nativeStellarTokenAddress = "CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA";
81
79
  const nativeCantonTokenAddress = "DSO::1220b1431ef217342db44d516bb9befde802be7d8899637d290895fa58880f19accc";
82
- const nativeDanalTokenAddress = "pci";
83
80
  // by setting slippage to undefined, it's set to "auto"
84
81
  const defaultSlippage = undefined;
85
82
  const destinationAddressResetValue = "null";
@@ -135,6 +132,7 @@ const CHAIN_IDS = {
135
132
  MANTRA: "5888",
136
133
  CITREA: "4114",
137
134
  TEMPO: "4217",
135
+ ARC: "5042",
138
136
  // others
139
137
  BITCOIN: "bitcoin",
140
138
  SOLANA: "solana-mainnet-beta",
@@ -145,7 +143,6 @@ const CHAIN_IDS = {
145
143
  STELLAR: "stellar-mainnet",
146
144
  STELLAR_TESTNET: "stellar-testnet",
147
145
  CANTON: "canton",
148
- DANAL_TESTNET: "danal-testnet",
149
146
  };
150
147
  const chainTypeToDefaultChainIdMap = {
151
148
  [ChainType.EVM]: CHAIN_IDS.ETHEREUM,
@@ -156,7 +153,6 @@ const chainTypeToDefaultChainIdMap = {
156
153
  [ChainType.XRPL]: CHAIN_IDS.XRPL,
157
154
  [ChainType.STELLAR]: CHAIN_IDS.STELLAR,
158
155
  [ChainType.CANTON]: CHAIN_IDS.CANTON,
159
- [ChainType.DANAL]: CHAIN_IDS.DANAL_TESTNET,
160
156
  };
161
157
  const chainTypeToNativeTokenAddressMap = {
162
158
  [ChainType.EVM]: nativeEvmTokenAddress,
@@ -167,7 +163,6 @@ const chainTypeToNativeTokenAddressMap = {
167
163
  [ChainType.XRPL]: nativeXrplTokenAddress,
168
164
  [ChainType.STELLAR]: nativeStellarTokenAddress,
169
165
  [ChainType.CANTON]: nativeCantonTokenAddress,
170
- [ChainType.DANAL]: nativeDanalTokenAddress,
171
166
  };
172
167
  const defaultConfigValues = {
173
168
  integratorId: INTEGRATOR_ID,
@@ -20949,6 +20944,27 @@ const isBitcoinAddressValid = (address$1) => {
20949
20944
  }
20950
20945
  };
20951
20946
 
20947
+ const arcUsdcTokenAddress = "0x3600000000000000000000000000000000000000";
20948
+ const isArcChain = (chainId) => chainId === CHAIN_IDS.ARC;
20949
+ const isArcUsdcToken = (token) => isArcChain(token?.chainId) &&
20950
+ token?.address.toLowerCase() === arcUsdcTokenAddress;
20951
+ const isArcNativeToken = (token) => isArcChain(token?.chainId) &&
20952
+ token?.address.toLowerCase() === nativeEvmTokenAddress;
20953
+ const normalizeArcTokenAddress = (chainId, address) => isArcChain(chainId) && address?.toLowerCase() === nativeEvmTokenAddress
20954
+ ? arcUsdcTokenAddress
20955
+ : address;
20956
+ const deduplicateArcBalances = (tokens) => {
20957
+ const canonicalChains = new Set(tokens
20958
+ .filter((token) => isArcChain(token.chainId) &&
20959
+ token.address?.toLowerCase() === arcUsdcTokenAddress)
20960
+ .map((token) => token.chainId));
20961
+ return tokens.filter((token) => !(canonicalChains.has(token.chainId) &&
20962
+ token.address?.toLowerCase() === nativeEvmTokenAddress));
20963
+ };
20964
+
20965
+ function getCantonCommandId(memo) {
20966
+ return `canton-${memo}`;
20967
+ }
20952
20968
  /**
20953
20969
  * Format a Canton connector into a Squid {@link CantonWallet}. Shared by the
20954
20970
  * announce-discovery and injected-provider paths.
@@ -21099,51 +21115,16 @@ function cantonInstrumentKey(instrument) {
21099
21115
  * is already a Decimal, not base units).
21100
21116
  */
21101
21117
  function groupCantonHoldingBalances(acsResponse) {
21118
+ return sumCantonHoldingBalances(parseCantonHoldings(acsResponse).filter((holding) => !holding.locked));
21119
+ }
21120
+ function sumCantonHoldingBalances(holdings) {
21102
21121
  const totals = {};
21103
- for (const holding of parseCantonHoldings(acsResponse)) {
21104
- // Locked holdings are not spendable, skip them
21105
- if (holding.locked)
21106
- continue;
21122
+ for (const holding of holdings) {
21107
21123
  const key = cantonInstrumentKey(holding.instrument);
21108
21124
  const total = totals[key] ?? new BigNumber(0);
21109
21125
  totals[key] = total.plus(new BigNumber(holding.amount));
21110
21126
  }
21111
- return Object.fromEntries(Object.entries(totals).map(([key, total]) => [key, total.toString(10)]));
21112
- }
21113
-
21114
- // Matches the backend validation: "PCI" + 50 uppercase-hex chars, case-sensitive.
21115
- const DANAL_ADDRESS_REGEX = /^PCI[0-9A-F]{50}$/;
21116
- function isDanalAddressValid(address) {
21117
- if (!address)
21118
- return false;
21119
- return DANAL_ADDRESS_REGEX.test(address);
21120
- }
21121
- // Fabric transaction id: 64 hex chars, no 0x prefix
21122
- const DANAL_TX_HASH_REGEX = /^[0-9a-fA-F]{64}$/;
21123
- function isDanalTxHashValid(hash) {
21124
- if (!hash)
21125
- return false;
21126
- return DANAL_TX_HASH_REGEX.test(hash);
21127
- }
21128
- function isDanalTransferRequestBody(value) {
21129
- if (typeof value !== "object" || value === null)
21130
- return false;
21131
- const { receiver, amount, memo } = value;
21132
- return (typeof receiver === "string" &&
21133
- receiver.length > 0 &&
21134
- typeof amount === "string" &&
21135
- amount.length > 0 &&
21136
- typeof memo === "string" &&
21137
- memo.length > 0);
21138
- }
21139
- function parseDanalTransferBody(data) {
21140
- try {
21141
- const parsed = JSON.parse(data);
21142
- return isDanalTransferRequestBody(parsed) ? parsed : null;
21143
- }
21144
- catch {
21145
- return null;
21146
- }
21127
+ return Object.fromEntries(Object.entries(totals).map(([key, total]) => [key, total.toFixed()]));
21147
21128
  }
21148
21129
 
21149
21130
  const solanaTokenProgramIdByAddress = {
@@ -21482,15 +21463,6 @@ function isOnChainTxData(squidData) {
21482
21463
  function isDepositAddressDirectTransferRoute(squidData) {
21483
21464
  return squidData.type === SquidDataType.DepositAddressDirectTransfer;
21484
21465
  }
21485
- /**
21486
- * Danal keeps SquidDataType.DepositAddressWithMemo, which XRPL/Stellar use for
21487
- * wallet-signed transactions — so the deposit treatment is gated on the chain,
21488
- * not just the type
21489
- */
21490
- function isDanalDepositRoute(route) {
21491
- return (route.params.fromChain === CHAIN_IDS.DANAL_TESTNET &&
21492
- route.transactionRequest?.type === SquidDataType.DepositAddressWithMemo);
21493
- }
21494
21466
  function getHistoryTransactionId(tx) {
21495
21467
  switch (tx.txType) {
21496
21468
  case HistoryTxType.SWAP:
@@ -22015,11 +21987,6 @@ const chainTypeToTrimLength = {
22015
21987
  start: 3,
22016
21988
  end: 3,
22017
21989
  },
22018
- // PCI0180...E77E
22019
- [ChainType.DANAL]: {
22020
- start: 7,
22021
- end: 4,
22022
- },
22023
21990
  };
22024
21991
  const truncateWithEllipsis = (value, startLength, endLength) => value.length <= startLength + endLength
22025
21992
  ? value
@@ -22068,8 +22035,6 @@ const isWalletAddressValid = (chainData, address) => {
22068
22035
  return isStellarAddressValid(address);
22069
22036
  case ChainType.CANTON:
22070
22037
  return isCantonAddressValid(address);
22071
- case ChainType.DANAL:
22072
- return isDanalAddressValid(address);
22073
22038
  }
22074
22039
  };
22075
22040
  const redirectToExtensionsStore = (wallet) => {
@@ -22233,7 +22198,7 @@ function sortAddressBook(a, b, selectedAddress) {
22233
22198
  return 0;
22234
22199
  }
22235
22200
  const calculateTotalUsdBalanceUSD = (tokens) => {
22236
- const totalUsd = tokens.reduce((total, token) => {
22201
+ const totalUsd = deduplicateArcBalances(tokens).reduce((total, token) => {
22237
22202
  const balance = parseFloat(token.balance);
22238
22203
  const usdPrice = token.usdPrice ?? 0;
22239
22204
  const balanceUsd = balance * usdPrice;
@@ -22354,8 +22319,6 @@ const connectByChainType = async (chainType, wallet, defaultChain, params) => {
22354
22319
  connector,
22355
22320
  },
22356
22321
  });
22357
- case ChainType.DANAL:
22358
- return null;
22359
22322
  }
22360
22323
  };
22361
22324
  const getChainTypesToConnect = (selectedChainTypes, defaultChain, supportedChains) => {
@@ -22480,6 +22443,8 @@ const cancelConnectWallet = (wallet) => {
22480
22443
  return;
22481
22444
  }
22482
22445
  switch (wallet.type) {
22446
+ case ChainType.CANTON:
22447
+ return wallet.connector.cancelConnect?.();
22483
22448
  case ChainType.XRPL:
22484
22449
  return wallet.connector.cancelConnect?.();
22485
22450
  default:
@@ -23045,22 +23010,36 @@ const getFirstAvailableChainId = (config, direction, chains = []) => {
23045
23010
  // if no initial chain ID is found in config, return the first available chain ID
23046
23011
  return availableChains.length > 0 ? availableChains[0].chainId : undefined;
23047
23012
  };
23048
- const fetchHighestBalanceToken = (fetchCachedBalance, chainId) => {
23013
+ const fetchHighestBalanceToken = (fetchCachedBalance, chainId, selectableTokens, direction) => {
23049
23014
  let address = undefined;
23050
23015
  if (fetchCachedBalance) {
23051
23016
  const queryCache = fetchCachedBalance?.queryClient?.getQueryCache();
23017
+ const directionCache = isArcChain(chainId) && direction
23018
+ ? queryCache?.find(keys().allTokensBalance(fetchCachedBalance.address, ChainType.EVM, direction))
23019
+ : undefined;
23052
23020
  // get cached balance from key
23053
- const cache = queryCache?.find(keys().allTokensBalance(fetchCachedBalance?.address, !isNaN(Number(chainId)) ? ChainType.EVM : ChainType.COSMOS));
23054
- // Parse result to TokenWithBalance[]
23055
- const cacheResult = cache?.state.data ?? [];
23021
+ const cache = directionCache?.state.data !== undefined
23022
+ ? directionCache
23023
+ : queryCache?.find(keys().allTokensBalance(fetchCachedBalance?.address, !isNaN(Number(chainId)) ? ChainType.EVM : ChainType.COSMOS));
23024
+ const cacheData = cache?.state.data;
23025
+ const cacheResult = Array.isArray(cacheData)
23026
+ ? cacheData
23027
+ : isArcChain(chainId)
23028
+ ? (cacheData?.tokens ?? [])
23029
+ : [];
23056
23030
  if (cacheResult.length > 0) {
23057
- const tokensWithBalance = cacheResult.filter((t) => t.chainId === chainId && Number(t.balance) > 0);
23031
+ const tokensWithBalance = deduplicateArcBalances(cacheResult).filter((t) => t.chainId === chainId &&
23032
+ Number(t.balance) > 0 &&
23033
+ (!selectableTokens ||
23034
+ selectableTokens.some((token) => token.chainId === t.chainId &&
23035
+ token.address.toLowerCase() ===
23036
+ normalizeArcTokenAddress(t.chainId, t.address)?.toLowerCase())));
23058
23037
  if (tokensWithBalance.length > 0) {
23059
23038
  // Return the token with the highest balance
23060
23039
  // TODO: At the moment we're not taking into account usd price
23061
23040
  const tokenWithHighestBalance = tokensWithBalance.reduce((prev, current) => Number(prev.balance) > Number(current.balance) ? prev : current);
23062
23041
  if (tokenWithHighestBalance) {
23063
- address = tokenWithHighestBalance.address;
23042
+ address = normalizeArcTokenAddress(tokenWithHighestBalance.chainId, tokenWithHighestBalance.address);
23064
23043
  }
23065
23044
  }
23066
23045
  }
@@ -23071,6 +23050,21 @@ const findNativeTokenForChainType = (tokens) => {
23071
23050
  return tokens.find((t) => t.address.toLowerCase() ===
23072
23051
  chainTypeToNativeTokenAddressMap[t.type].toLowerCase());
23073
23052
  };
23053
+ const getTokenAddressForSelection = ({ tokens, config, chainId, address, direction, excludeToken, }) => {
23054
+ if (!isArcChain(chainId))
23055
+ return address;
23056
+ const normalizedAddress = normalizeArcTokenAddress(chainId, address);
23057
+ const excludedAddress = normalizeArcTokenAddress(excludeToken?.chainId, excludeToken?.address);
23058
+ if (!chainId ||
23059
+ !normalizedAddress ||
23060
+ (excludeToken?.chainId === chainId &&
23061
+ normalizedAddress.toLowerCase() === excludedAddress?.toLowerCase()) ||
23062
+ !getSupportedChainIdsForDirection([chainId], config, direction).includes(chainId)) {
23063
+ return undefined;
23064
+ }
23065
+ return filterViewableTokens(tokens, config, direction).find((token) => token.chainId === chainId &&
23066
+ token.address.toLowerCase() === normalizedAddress.toLowerCase())?.address;
23067
+ };
23074
23068
  /**
23075
23069
  * Returns the default token address for a specific chain and direction based on config.
23076
23070
  * If no default tokens are set in config, returns the native token for the specified chain
@@ -23088,6 +23082,25 @@ const getInitialOrDefaultTokenAddressForChain = ({ tokens, config, chainId, dire
23088
23082
  const supportedChainIds = getSupportedChainIdsForDirection([chainId], config, direction);
23089
23083
  if (!supportedChainIds.includes(chainId))
23090
23084
  return;
23085
+ if (isArcChain(chainId)) {
23086
+ const selectAddress = (address) => getTokenAddressForSelection({
23087
+ tokens,
23088
+ config,
23089
+ chainId,
23090
+ address,
23091
+ direction,
23092
+ excludeToken,
23093
+ });
23094
+ const selectableTokens = tokens.filter((token) => token.chainId === chainId &&
23095
+ !isArcNativeToken(token) &&
23096
+ selectAddress(token.address) !== undefined);
23097
+ return (selectAddress(config.defaultTokensPerChain?.find((token) => token.chainId === chainId)
23098
+ ?.address) ??
23099
+ selectAddress(getInitialTokenAddressForChain({ tokens, config, chainId, direction })) ??
23100
+ selectAddress(fetchHighestBalanceToken(fetchCachedBalance, chainId, selectableTokens, direction)) ??
23101
+ selectAddress(arcUsdcTokenAddress) ??
23102
+ selectableTokens[0]?.address);
23103
+ }
23091
23104
  const configDefaultTokenForChain = config.defaultTokensPerChain?.find((token) => token.chainId == chainId);
23092
23105
  // get default token from config
23093
23106
  if (configDefaultTokenForChain &&
@@ -23131,6 +23144,23 @@ const getInitialTokenAddressForChain = ({ chainId, config, direction, tokens, un
23131
23144
  const initialAsset = config.initialAssets?.[direction];
23132
23145
  if (!initialAsset)
23133
23146
  return undefined;
23147
+ if (isArcChain(chainId)) {
23148
+ const address = isNamedTokenConfig(initialAsset)
23149
+ ? tokens.find((token) => token.chainId === chainId &&
23150
+ !isArcNativeToken(token) &&
23151
+ token.symbol.toLowerCase() === initialAsset.symbol?.toLowerCase())?.address
23152
+ : initialAsset.chainId === chainId
23153
+ ? initialAsset.address
23154
+ : undefined;
23155
+ return getTokenAddressForSelection({
23156
+ tokens,
23157
+ config,
23158
+ chainId,
23159
+ address,
23160
+ direction,
23161
+ excludeToken: { chainId, address: unavailableTokenAddress },
23162
+ });
23163
+ }
23134
23164
  if (isNamedTokenConfig(initialAsset)) {
23135
23165
  if (!initialAsset.symbol)
23136
23166
  return undefined;
@@ -23340,12 +23370,44 @@ const handleDestinationAddressOnSwapChange = ({ fromChainId, fromTokenAddress, t
23340
23370
  });
23341
23371
  let destinationTokenAddress = toChainId && !toTokenAddress
23342
23372
  ? defaultToAddress
23343
- : toTokenAddress ?? swapRoute?.toTokenAddress;
23373
+ : (toTokenAddress ?? swapRoute?.toTokenAddress);
23344
23374
  const lowerCaseDestinationTokenAddress = destinationTokenAddress?.toLowerCase();
23345
23375
  if (destinationTokensFiltered.find((t) => t.address === lowerCaseDestinationTokenAddress) === undefined) {
23346
23376
  destinationTokenAddress = defaultToAddress;
23347
23377
  }
23348
- return lowerCaseDestinationTokenAddress;
23378
+ return isArcChain(toChainId ?? swapRoute?.toChainId)
23379
+ ? destinationTokenAddress?.toLowerCase()
23380
+ : lowerCaseDestinationTokenAddress;
23381
+ };
23382
+ const normalizeSwapParamsForSelection = ({ swapParams, tokens, chains, config, }) => {
23383
+ const fromTokenAddress = getTokenAddressForSelection({
23384
+ tokens,
23385
+ config,
23386
+ chainId: swapParams.fromChainId,
23387
+ address: swapParams.fromTokenAddress,
23388
+ direction: "from",
23389
+ });
23390
+ const fromToken = tokens.find((token) => token.chainId === swapParams.fromChainId &&
23391
+ token.address.toLowerCase() === fromTokenAddress?.toLowerCase());
23392
+ const toTokenAddress = getTokenAddressForSelection({
23393
+ tokens: isArcChain(swapParams.toChainId)
23394
+ ? filterTokensForDestination({
23395
+ tokens,
23396
+ selectedDestinationChain: chains.find((chain) => chain.chainId === swapParams.toChainId),
23397
+ selectedSourceToken: fromToken,
23398
+ removeSourceToken: true,
23399
+ })
23400
+ : tokens,
23401
+ config,
23402
+ chainId: swapParams.toChainId,
23403
+ address: swapParams.toTokenAddress,
23404
+ direction: "to",
23405
+ excludeToken: {
23406
+ chainId: swapParams.fromChainId,
23407
+ address: fromTokenAddress,
23408
+ },
23409
+ });
23410
+ return { ...swapParams, fromTokenAddress, toTokenAddress };
23349
23411
  };
23350
23412
  /**
23351
23413
  * When user changes something from the SwapView
@@ -23357,10 +23419,19 @@ const handleDestinationAddressOnSwapChange = ({ fromChainId, fromTokenAddress, t
23357
23419
  * If only destination token is changed but source is not, and they were the same, then source token updates to something else
23358
23420
  *
23359
23421
  */
23360
- const getNewSwapParamsFromInput = ({ inputParams, initialSwapRoute, tokens, chains, config, queryClient, connectedSourceAddress, }) => {
23361
- const { fromChainId, fromTokenAddress, toChainId, toTokenAddress, destinationAddress, fallbackAddress, depositRefundAddress, } = inputParams;
23422
+ const getNewSwapParamsFromInput = ({ inputParams, initialSwapRoute: storedSwapRoute, tokens, chains, config, queryClient, connectedSourceAddress, }) => {
23423
+ const initialSwapRoute = storedSwapRoute
23424
+ ? {
23425
+ ...storedSwapRoute,
23426
+ fromTokenAddress: normalizeArcTokenAddress(storedSwapRoute.fromChainId, storedSwapRoute.fromTokenAddress),
23427
+ toTokenAddress: normalizeArcTokenAddress(storedSwapRoute.toChainId, storedSwapRoute.toTokenAddress),
23428
+ }
23429
+ : undefined;
23430
+ const { fromChainId, toChainId, destinationAddress, fallbackAddress, depositRefundAddress, } = inputParams;
23362
23431
  const srcChainId = fromChainId ?? initialSwapRoute?.fromChainId;
23363
23432
  const destinationChainId = toChainId ?? initialSwapRoute?.toChainId;
23433
+ const fromTokenAddress = normalizeArcTokenAddress(srcChainId, inputParams.fromTokenAddress);
23434
+ const toTokenAddress = normalizeArcTokenAddress(destinationChainId, inputParams.toTokenAddress);
23364
23435
  const defaultFromAddress = getInitialOrDefaultTokenAddressForChain({
23365
23436
  tokens,
23366
23437
  config,
@@ -23392,7 +23463,7 @@ const getNewSwapParamsFromInput = ({ inputParams, initialSwapRoute, tokens, chai
23392
23463
  toTokenAddress === initialSwapRoute?.fromTokenAddress;
23393
23464
  const sourceTokenAddress = sameNewDestAndInitialSource || onlySourceChainIdChanged
23394
23465
  ? defaultFromAddress
23395
- : fromTokenAddress ?? initialSwapRoute?.fromTokenAddress;
23466
+ : (fromTokenAddress ?? initialSwapRoute?.fromTokenAddress);
23396
23467
  let destinationTokenAddress = undefined;
23397
23468
  if (!sameNewSourceAndInitialDest) {
23398
23469
  if (onlySourceChainIdChanged) {
@@ -23436,15 +23507,20 @@ const getNewSwapParamsFromInput = ({ inputParams, initialSwapRoute, tokens, chai
23436
23507
  const newDepositRefundAddress = sourceChainChanged
23437
23508
  ? undefined
23438
23509
  : depositRefundAddress || initialSwapRoute?.depositRefundAddress;
23439
- return {
23440
- fromChainId: srcChainId,
23441
- fromTokenAddress: sourceTokenAddress,
23442
- toChainId: destinationChainId,
23443
- toTokenAddress: destinationTokenAddress,
23444
- destinationAddress: newDestinationAddress,
23445
- fallbackAddress: newFallbackAddress,
23446
- depositRefundAddress: newDepositRefundAddress,
23447
- };
23510
+ return normalizeSwapParamsForSelection({
23511
+ swapParams: {
23512
+ fromChainId: srcChainId,
23513
+ fromTokenAddress: sourceTokenAddress,
23514
+ toChainId: destinationChainId,
23515
+ toTokenAddress: destinationTokenAddress,
23516
+ destinationAddress: newDestinationAddress,
23517
+ fallbackAddress: newFallbackAddress,
23518
+ depositRefundAddress: newDepositRefundAddress,
23519
+ },
23520
+ tokens,
23521
+ chains,
23522
+ config,
23523
+ });
23448
23524
  };
23449
23525
  /* Sorts tokens based on the following order:
23450
23526
  * 1. Native token on chain ID "1" (Ethereum) comes first.
@@ -23502,8 +23578,10 @@ const sortAllTokens = (tokenA, tokenB) => {
23502
23578
  return 0;
23503
23579
  };
23504
23580
  const findToken = (tokens, chainId, address) => tokens.find((t) => t.chainId === chainId && t.address === address);
23505
- const findNativeToken = (tokens, chain) => tokens.find((t) => t.symbol.toUpperCase() === chain.nativeCurrency.symbol.toUpperCase() &&
23506
- t.chainId == chain.chainId);
23581
+ const findNativeToken = (tokens, chain) => tokens.find((t) => t.chainId === chain.chainId &&
23582
+ (isArcChain(chain.chainId)
23583
+ ? isArcNativeToken(t)
23584
+ : t.symbol.toUpperCase() === chain.nativeCurrency.symbol.toUpperCase()));
23507
23585
  const normalizeIbcAddress = (address) => {
23508
23586
  if (!address.toLowerCase().startsWith("ibc/")) {
23509
23587
  return address;
@@ -23573,9 +23651,7 @@ function selectGroupDefaultInfo(tokens) {
23573
23651
  const groupTokensBySymbol = (tokens, chainType) => {
23574
23652
  const groups = {};
23575
23653
  // Filter tokens by chain type if specified
23576
- const filteredTokens = chainType
23577
- ? tokens.filter((token) => token.type === chainType)
23578
- : tokens;
23654
+ const filteredTokens = deduplicateArcBalances(chainType ? tokens.filter((token) => token.type === chainType) : tokens);
23579
23655
  // First pass: group by coingeckoId or symbol
23580
23656
  filteredTokens.forEach((token) => {
23581
23657
  const groupKey = token.coingeckoId || token.symbol.split(".")[0];
@@ -23651,7 +23727,7 @@ const groupTokensBySymbol = (tokens, chainType) => {
23651
23727
  */
23652
23728
  const groupTokensByChainId = (tokens, chains) => {
23653
23729
  const groups = {};
23654
- tokens.forEach((token) => {
23730
+ deduplicateArcBalances(tokens).forEach((token) => {
23655
23731
  const chainData = chains.find((chain) => chain.chainId === token.chainId);
23656
23732
  const groupKey = token.chainId;
23657
23733
  if (!groups[groupKey]) {
@@ -23699,6 +23775,8 @@ const filterViewableTokens = (tokens, config, direction) => {
23699
23775
  { chainId: CHAIN_IDS.DCHAIN, address: nativeEvmTokenAddress },
23700
23776
  ];
23701
23777
  return (tokens.filter((token) => {
23778
+ if (isArcNativeToken(token))
23779
+ return false;
23702
23780
  if (direction) {
23703
23781
  const parsedDirection = getParsedDirection(direction);
23704
23782
  const availableTokensForDirection = config.availableTokens?.[parsedDirection];
@@ -23714,7 +23792,7 @@ const filterViewableTokens = (tokens, config, direction) => {
23714
23792
  };
23715
23793
  const getSecretNetworkBalances = async (chainData, cosmosAddress, squidTokens, keplrTypeWallet) => {
23716
23794
  const squidSecretTokens = squidTokens.filter((t) => t.chainId === CHAIN_IDS.SECRET);
23717
- const { fetchAllSecretBalances } = await import('./secretService-cgr3P1zw.js');
23795
+ const { fetchAllSecretBalances } = await import('./secretService-DkE9yz1o.js');
23718
23796
  return fetchAllSecretBalances(chainData, cosmosAddress, squidSecretTokens, keplrTypeWallet);
23719
23797
  };
23720
23798
  function getTokenAssetsKey(token) {
@@ -25295,8 +25373,7 @@ const searchTokens = (query, tokens, chains) => {
25295
25373
  .filter((chain) => chain.nativeCurrency.symbol.toLowerCase() === query.toLowerCase() ||
25296
25374
  chain.nativeCurrency.name.toLowerCase().includes(query.toLowerCase()) ||
25297
25375
  chain.networkName.toLowerCase().includes(query.toLowerCase()) ||
25298
- (chain.axelarChainName?.toLowerCase().includes(query.toLowerCase()) ??
25299
- false))
25376
+ chain.axelarChainName.toLowerCase().includes(query.toLowerCase()))
25300
25377
  .map((chain) => tokens.find((token) => token.chainId === chain.chainId &&
25301
25378
  token.address.toLowerCase() === nativeEvmTokenAddress))
25302
25379
  .filter((token) => token !== undefined);
@@ -25709,7 +25786,7 @@ const useSquidTokens = (direction) => {
25709
25786
  config.availableChains,
25710
25787
  direction,
25711
25788
  ]);
25712
- const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, cantonTokens, danalTokens, } = useMemo(() => {
25789
+ const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, cantonTokens, } = useMemo(() => {
25713
25790
  return tokens?.reduce((acc, token) => {
25714
25791
  switch (token.type) {
25715
25792
  case ChainType.EVM:
@@ -25736,9 +25813,6 @@ const useSquidTokens = (direction) => {
25736
25813
  case ChainType.CANTON:
25737
25814
  acc.cantonTokens.push(token);
25738
25815
  break;
25739
- case ChainType.DANAL:
25740
- acc.danalTokens.push(token);
25741
- break;
25742
25816
  }
25743
25817
  return acc;
25744
25818
  }, {
@@ -25750,7 +25824,6 @@ const useSquidTokens = (direction) => {
25750
25824
  xrplTokens: [],
25751
25825
  stellarTokens: [],
25752
25826
  cantonTokens: [],
25753
- danalTokens: [],
25754
25827
  });
25755
25828
  }, [tokens]);
25756
25829
  const findToken = useCallback((address, chainId) => {
@@ -25769,7 +25842,6 @@ const useSquidTokens = (direction) => {
25769
25842
  xrplTokens,
25770
25843
  stellarTokens,
25771
25844
  cantonTokens,
25772
- danalTokens,
25773
25845
  };
25774
25846
  };
25775
25847
 
@@ -26306,7 +26378,6 @@ const chainTypeToRefetchInterval = {
26306
26378
  [ChainType.XRPL]: 1_000,
26307
26379
  [ChainType.STELLAR]: 1_000,
26308
26380
  [ChainType.CANTON]: 1_000,
26309
- [ChainType.DANAL]: 1_000,
26310
26381
  };
26311
26382
  /**
26312
26383
  * Returns the status refetch interval of a Send transaction
@@ -26573,7 +26644,7 @@ const useSquidChains = (direction) => {
26573
26644
  const chain = findChain(chainId);
26574
26645
  return chain?.chainType;
26575
26646
  }, [findChain]);
26576
- const { evmChains, cosmosChains, suiChains, stellarChains, xrplChains, cantonChains, danalChains, } = useMemo(() => {
26647
+ const { evmChains, cosmosChains, suiChains, stellarChains, xrplChains, cantonChains, } = useMemo(() => {
26577
26648
  return chains.reduce((acc, chain) => {
26578
26649
  switch (chain.chainType) {
26579
26650
  case ChainType.EVM:
@@ -26594,9 +26665,6 @@ const useSquidChains = (direction) => {
26594
26665
  case ChainType.CANTON:
26595
26666
  acc.cantonChains.push(chain);
26596
26667
  break;
26597
- case ChainType.DANAL:
26598
- acc.danalChains.push(chain);
26599
- break;
26600
26668
  }
26601
26669
  return acc;
26602
26670
  }, {
@@ -26606,7 +26674,6 @@ const useSquidChains = (direction) => {
26606
26674
  xrplChains: [],
26607
26675
  stellarChains: [],
26608
26676
  cantonChains: [],
26609
- danalChains: [],
26610
26677
  });
26611
26678
  }, [chains]);
26612
26679
  const { supportedSourceChains, supportedDestinationChains } = useMemo(() => {
@@ -26628,7 +26695,6 @@ const useSquidChains = (direction) => {
26628
26695
  xrplChains,
26629
26696
  stellarChains,
26630
26697
  cantonChains,
26631
- danalChains,
26632
26698
  getChainType,
26633
26699
  findChain,
26634
26700
  };
@@ -26942,7 +27008,343 @@ const useBitcoinContext = () => {
26942
27008
  return context;
26943
27009
  };
26944
27010
 
26945
- const REQUEST_TIMEOUT_MS = 60_000;
27011
+ const vParty = (party) => ({ party });
27012
+ const vText = (text) => ({ text });
27013
+ const vNumeric = (numeric) => ({ numeric });
27014
+ const vContractId = (contractId) => ({
27015
+ contractId,
27016
+ });
27017
+ const vList = (elements) => ({
27018
+ list: { elements },
27019
+ });
27020
+ const vRecord = (fields) => ({
27021
+ record: { fields: fields.map(([label, value]) => ({ label, value })) },
27022
+ });
27023
+ const vTextMap = (entries) => ({ textMap: { entries } });
27024
+ const vTimestamp = (isoString) => ({
27025
+ timestamp: String(Math.floor(new Date(isoString).getTime() * 1000)),
27026
+ });
27027
+ function isRecord(value) {
27028
+ return typeof value === "object" && value !== null && !Array.isArray(value);
27029
+ }
27030
+ function normalizeChoiceContextValue(value) {
27031
+ if (typeof value === "string")
27032
+ return value;
27033
+ if (!isRecord(value) || typeof value.tag !== "string")
27034
+ return null;
27035
+ switch (value.tag) {
27036
+ case "AV_Text":
27037
+ case "AV_ContractId":
27038
+ return typeof value.value === "string"
27039
+ ? { tag: value.tag, value: value.value }
27040
+ : null;
27041
+ case "AV_Bool":
27042
+ return typeof value.value === "boolean"
27043
+ ? { tag: value.tag, value: value.value }
27044
+ : null;
27045
+ case "AV_List":
27046
+ if (!Array.isArray(value.value))
27047
+ return null;
27048
+ return {
27049
+ tag: value.tag,
27050
+ value: value.value.flatMap((entry) => {
27051
+ const normalized = normalizeChoiceContextValue(entry);
27052
+ return normalized ? [normalized] : [];
27053
+ }),
27054
+ };
27055
+ default: {
27056
+ const inner = value.value;
27057
+ if (typeof inner === "string" ||
27058
+ typeof inner === "number" ||
27059
+ typeof inner === "boolean" ||
27060
+ inner === null) {
27061
+ return { tag: value.tag, value: inner };
27062
+ }
27063
+ if (Array.isArray(inner)) {
27064
+ return {
27065
+ tag: value.tag,
27066
+ value: inner.flatMap((entry) => {
27067
+ const normalized = normalizeChoiceContextValue(entry);
27068
+ return normalized ? [normalized] : [];
27069
+ }),
27070
+ };
27071
+ }
27072
+ if (!isRecord(inner))
27073
+ return null;
27074
+ const normalizedObject = {};
27075
+ for (const [key, entry] of Object.entries(inner)) {
27076
+ if (typeof entry !== "string" &&
27077
+ typeof entry !== "number" &&
27078
+ typeof entry !== "boolean" &&
27079
+ entry !== null) {
27080
+ return null;
27081
+ }
27082
+ normalizedObject[key] = entry;
27083
+ }
27084
+ return { tag: value.tag, value: normalizedObject };
27085
+ }
27086
+ }
27087
+ }
27088
+ function stringifyChoiceContextValue(value) {
27089
+ return typeof value === "string" ? value : String(value);
27090
+ }
27091
+ function choiceContextValueToAnyValue(value) {
27092
+ if (typeof value === "string") {
27093
+ return {
27094
+ variant: { constructor: "AV_Text", value: vText(value) },
27095
+ };
27096
+ }
27097
+ switch (value.tag) {
27098
+ case "AV_ContractId":
27099
+ if (typeof value.value !== "string") {
27100
+ throw new TypeError("AV_ContractId values must be strings");
27101
+ }
27102
+ return {
27103
+ variant: { constructor: value.tag, value: vContractId(value.value) },
27104
+ };
27105
+ case "AV_Bool":
27106
+ if (typeof value.value !== "boolean") {
27107
+ throw new TypeError("AV_Bool values must be booleans");
27108
+ }
27109
+ return {
27110
+ variant: { constructor: value.tag, value: { bool: value.value } },
27111
+ };
27112
+ case "AV_List":
27113
+ if (!Array.isArray(value.value)) {
27114
+ throw new TypeError("AV_List values must be arrays");
27115
+ }
27116
+ return {
27117
+ variant: {
27118
+ constructor: value.tag,
27119
+ value: vList(value.value.map(choiceContextValueToAnyValue)),
27120
+ },
27121
+ };
27122
+ default:
27123
+ return {
27124
+ variant: {
27125
+ constructor: value.tag,
27126
+ value: vText(stringifyChoiceContextValue(value.value)),
27127
+ },
27128
+ };
27129
+ }
27130
+ }
27131
+
27132
+ /** Metadata key used by Splice token-standard transfers to carry our Squid orderhash memo. */
27133
+ const CANTON_MEMO_KEY = "splice.lfdecentralizedtrust.org/reason";
27134
+ /** Interface id for the transfer factory contract returned by the token registry. */
27135
+ const TRANSFER_FACTORY_INTERFACE_ID = "#splice-api-token-transfer-instruction-v1:Splice.Api.Token.TransferInstructionV1:TransferFactory";
27136
+ /** Choice exercised on the transfer factory to create the token-standard transfer. */
27137
+ const TRANSFER_FACTORY_CHOICE = "TransferFactory_Transfer";
27138
+ /** CIP-056 (non-Amulet) tokens expose a registrar parameterized by admin party. */
27139
+ const CIP056_REGISTRAR_BASE = "https://api.utilities.digitalasset.com/api/token-standard/v0/registrars";
27140
+ const TRANSFER_REQUESTED_AT_SKEW_MS = 60_000;
27141
+ const TRANSFER_EXECUTE_WINDOW_MS = 24 * 60 * 60 * 1000;
27142
+ function resolveCantonRegistryUrl(instrument) {
27143
+ if (instrument.id === CANTON_AMULET_INSTRUMENT_ID) {
27144
+ return CANTON_AMULET_REGISTRY_URL;
27145
+ }
27146
+ return `${CIP056_REGISTRAR_BASE}/${encodeURIComponent(instrument.admin)}`;
27147
+ }
27148
+ /**
27149
+ * Build the plain JSON arguments expected by the registry transfer-factory
27150
+ * endpoint before it adds choice context and disclosed contracts.
27151
+ */
27152
+ function buildTransferChoiceArgs({ sender, receiver, amount, instrument, inputHoldingCids, memo, nowMs, }) {
27153
+ return {
27154
+ expectedAdmin: instrument.admin,
27155
+ transfer: {
27156
+ sender,
27157
+ receiver,
27158
+ amount,
27159
+ instrumentId: { admin: instrument.admin, id: instrument.id },
27160
+ requestedAt: new Date(nowMs - TRANSFER_REQUESTED_AT_SKEW_MS).toISOString(),
27161
+ executeBefore: new Date(nowMs + TRANSFER_EXECUTE_WINDOW_MS).toISOString(),
27162
+ inputHoldingCids,
27163
+ meta: { values: { [CANTON_MEMO_KEY]: memo } },
27164
+ },
27165
+ extraArgs: { context: { values: {} }, meta: { values: {} } },
27166
+ };
27167
+ }
27168
+ /**
27169
+ * Canton's Holding contracts follow Bitcoin-style UTXOs model.
27170
+ *
27171
+ * Pick Holding contract ids covering `amount` for the instrument: prefer a
27172
+ * single exact-amount holding, else accumulate largest-first.
27173
+ */
27174
+ function selectInputHoldingCids(holdings, instrument, amount) {
27175
+ const spendableHoldings = holdings.filter((h) => !h.locked &&
27176
+ h.instrument.admin === instrument.admin &&
27177
+ h.instrument.id === instrument.id);
27178
+ const target = new BigNumber(amount);
27179
+ const exact = spendableHoldings.find((h) => new BigNumber(h.amount).eq(target));
27180
+ if (exact)
27181
+ return [exact.contractId];
27182
+ const sorted = [...spendableHoldings].sort((a, b) => new BigNumber(b.amount).comparedTo(new BigNumber(a.amount)));
27183
+ const selected = [];
27184
+ let sum = new BigNumber(0);
27185
+ for (const holding of sorted) {
27186
+ selected.push(holding.contractId);
27187
+ sum = sum.plus(holding.amount);
27188
+ if (sum.gte(target))
27189
+ break;
27190
+ }
27191
+ if (sum.lt(target)) {
27192
+ throw new Error("Insufficient Canton holdings to cover transfer amount");
27193
+ }
27194
+ return selected;
27195
+ }
27196
+ async function fetchInputHoldingCids(connector, party, instrument, amount) {
27197
+ const ledgerEnd = await connector.ledgerApi({
27198
+ requestMethod: "get",
27199
+ resource: "/v2/state/ledger-end",
27200
+ });
27201
+ const activeContracts = await connector.ledgerApi({
27202
+ requestMethod: "post",
27203
+ resource: "/v2/state/active-contracts",
27204
+ body: buildHoldingsAcsRequestBody(party, String(ledgerEnd.offset)),
27205
+ });
27206
+ return selectInputHoldingCids(parseCantonHoldings(activeContracts), instrument, amount);
27207
+ }
27208
+ /**
27209
+ * Ask the token registry for the transfer factory contract and extra context
27210
+ * required to exercise its transfer choice.
27211
+ */
27212
+ async function fetchTransferFactory(registryUrl, choiceArgs) {
27213
+ const response = await fetch(`${registryUrl}/registry/transfer-instruction/v1/transfer-factory`, {
27214
+ method: "POST",
27215
+ headers: { "Content-Type": "application/json" },
27216
+ body: JSON.stringify({
27217
+ choiceArguments: choiceArgs,
27218
+ excludeDebugFields: true,
27219
+ }),
27220
+ });
27221
+ if (!response.ok) {
27222
+ throw new Error(`Canton transfer-factory request failed (${response.status})`);
27223
+ }
27224
+ return response.json();
27225
+ }
27226
+ /**
27227
+ * Convert transfer choice args into strict Daml Value JSON for the wallet's
27228
+ * prepareExecute ExerciseCommand.
27229
+ */
27230
+ function buildPrepareChoiceArgument(choiceArgs) {
27231
+ const contextValues = Object.entries(choiceArgs.extraArgs.context?.values ?? {})
27232
+ .map(([key, value]) => {
27233
+ const normalized = normalizeChoiceContextValue(value);
27234
+ return normalized
27235
+ ? { key, value: choiceContextValueToAnyValue(normalized) }
27236
+ : undefined;
27237
+ })
27238
+ .filter((entry) => Boolean(entry));
27239
+ return vRecord([
27240
+ ["expectedAdmin", vParty(choiceArgs.expectedAdmin)],
27241
+ [
27242
+ "transfer",
27243
+ vRecord([
27244
+ ["sender", vParty(choiceArgs.transfer.sender)],
27245
+ ["receiver", vParty(choiceArgs.transfer.receiver)],
27246
+ ["amount", vNumeric(choiceArgs.transfer.amount)],
27247
+ [
27248
+ "instrumentId",
27249
+ vRecord([
27250
+ ["admin", vParty(choiceArgs.transfer.instrumentId.admin)],
27251
+ ["id", vText(choiceArgs.transfer.instrumentId.id)],
27252
+ ]),
27253
+ ],
27254
+ ["requestedAt", vTimestamp(choiceArgs.transfer.requestedAt)],
27255
+ ["executeBefore", vTimestamp(choiceArgs.transfer.executeBefore)],
27256
+ [
27257
+ "inputHoldingCids",
27258
+ vList(choiceArgs.transfer.inputHoldingCids.map(vContractId)),
27259
+ ],
27260
+ [
27261
+ "meta",
27262
+ vRecord([
27263
+ [
27264
+ "values",
27265
+ vTextMap(Object.entries(choiceArgs.transfer.meta.values).map(([key, value]) => ({ key, value: vText(value) }))),
27266
+ ],
27267
+ ]),
27268
+ ],
27269
+ ]),
27270
+ ],
27271
+ [
27272
+ "extraArgs",
27273
+ vRecord([
27274
+ ["context", vRecord([["values", vTextMap(contextValues)]])],
27275
+ ["meta", vRecord([["values", vTextMap([])]])],
27276
+ ]),
27277
+ ],
27278
+ ]);
27279
+ }
27280
+ /**
27281
+ * Convert a registry disclosed contract into the wallet submission shape,
27282
+ * dropping debug fields and entries without a usable createdEventBlob.
27283
+ */
27284
+ function toDisclosedContract(raw) {
27285
+ if (typeof raw.createdEventBlob !== "string")
27286
+ return null;
27287
+ return {
27288
+ createdEventBlob: raw.createdEventBlob,
27289
+ contractId: typeof raw.contractId === "string" ? raw.contractId : undefined,
27290
+ synchronizerId: typeof raw.synchronizerId === "string" ? raw.synchronizerId : undefined,
27291
+ };
27292
+ }
27293
+ /**
27294
+ * Build a Splice token-standard transfer of `amount` of `token` from `sender`
27295
+ * to `receiver`, carrying `memo`, ready to hand to a wallet's prepareExecute.
27296
+ * Returns the full prepareExecute params (commandId + commands + actAs +
27297
+ * disclosedContracts).
27298
+ */
27299
+ async function buildCantonTransfer(connector, { sender, receiver, amount, token, memo, nowMs, }) {
27300
+ if (!token.originalAddress) {
27301
+ throw new Error("Canton token originalAddress is required");
27302
+ }
27303
+ const instrument = parseCantonInstrument(token.originalAddress);
27304
+ if (!instrument) {
27305
+ throw new Error(`Invalid Canton token address: ${token.originalAddress}`);
27306
+ }
27307
+ const registryUrl = resolveCantonRegistryUrl(instrument);
27308
+ const inputHoldingCids = await fetchInputHoldingCids(connector, sender, instrument, amount);
27309
+ const choiceArgs = buildTransferChoiceArgs({
27310
+ sender,
27311
+ receiver,
27312
+ amount,
27313
+ instrument,
27314
+ inputHoldingCids,
27315
+ memo,
27316
+ nowMs,
27317
+ });
27318
+ const factory = await fetchTransferFactory(registryUrl, choiceArgs);
27319
+ const choiceContextData = factory.choiceContext.choiceContextData;
27320
+ if (!choiceContextData) {
27321
+ throw new Error("Transfer factory choice context is missing");
27322
+ }
27323
+ choiceArgs.extraArgs.context = choiceContextData;
27324
+ const disclosedContracts = (factory.choiceContext?.disclosedContracts ?? []).flatMap((raw) => {
27325
+ const disclosedContract = toDisclosedContract(raw);
27326
+ return disclosedContract ? [disclosedContract] : [];
27327
+ });
27328
+ // Command ID: client-supplied identifier used to deduplicate submissions
27329
+ const commandId = getCantonCommandId(memo);
27330
+ return {
27331
+ commandId,
27332
+ commands: [
27333
+ {
27334
+ ExerciseCommand: {
27335
+ templateId: TRANSFER_FACTORY_INTERFACE_ID,
27336
+ contractId: factory.factoryId,
27337
+ choice: TRANSFER_FACTORY_CHOICE,
27338
+ choiceArgument: buildPrepareChoiceArgument(choiceArgs),
27339
+ },
27340
+ },
27341
+ ],
27342
+ actAs: [sender],
27343
+ disclosedContracts,
27344
+ };
27345
+ }
27346
+
27347
+ const REQUEST_TIMEOUT_MS$1 = 60_000;
26946
27348
  function pickAddress(accounts) {
26947
27349
  return (accounts.find((a) => a.primary) ?? accounts[0])?.partyId;
26948
27350
  }
@@ -26951,6 +27353,7 @@ function pickAddress(accounts) {
26951
27353
  * (bound to its announce `target`) and exposes the lifecycle methods.
26952
27354
  */
26953
27355
  class CantonBrowserConnector {
27356
+ kind = "cip103";
26954
27357
  providerId;
26955
27358
  name;
26956
27359
  target;
@@ -26965,7 +27368,7 @@ class CantonBrowserConnector {
26965
27368
  client ??
26966
27369
  createCantonClient(new WindowTransport(win, {
26967
27370
  target: this.target,
26968
- timeout: REQUEST_TIMEOUT_MS,
27371
+ timeout: REQUEST_TIMEOUT_MS$1,
26969
27372
  }));
26970
27373
  }
26971
27374
  get accounts() {
@@ -27011,6 +27414,28 @@ class CantonBrowserConnector {
27011
27414
  this._accounts = await this.client.listAccounts();
27012
27415
  return this._accounts;
27013
27416
  }
27417
+ async getBalances(partyId) {
27418
+ const { offset } = await this.ledgerApi({
27419
+ requestMethod: "get",
27420
+ resource: "/v2/state/ledger-end",
27421
+ });
27422
+ const contracts = await this.ledgerApi({
27423
+ requestMethod: "post",
27424
+ resource: "/v2/state/active-contracts",
27425
+ body: buildHoldingsAcsRequestBody(partyId, String(offset)),
27426
+ });
27427
+ return groupCantonHoldingBalances(contracts);
27428
+ }
27429
+ async transfer(params) {
27430
+ const payload = await buildCantonTransfer(this, params);
27431
+ const result = await this.prepareExecuteAndWait(payload);
27432
+ const updateId = result.tx?.payload?.updateId ?? "";
27433
+ return {
27434
+ status: "completed",
27435
+ commandId: getCantonCommandId(params.memo),
27436
+ updateId,
27437
+ };
27438
+ }
27014
27439
  on(event, handler) {
27015
27440
  this.listeners[event].add(handler);
27016
27441
  }
@@ -27117,6 +27542,313 @@ function discoverInjectedCantonWallets(win) {
27117
27542
  });
27118
27543
  }
27119
27544
 
27545
+ class CantonConnectionCancelledError extends Error {
27546
+ code = 4001;
27547
+ constructor() {
27548
+ super("Wallet connection cancelled");
27549
+ }
27550
+ }
27551
+
27552
+ const REQUEST_TIMEOUT_MS = 5 * 60_000;
27553
+ const OVERLAY_ID = "loop-sdk-connect-overlay";
27554
+ class LoopSubmissionUnknownError extends Error {
27555
+ constructor(cause) {
27556
+ super("Loop transfer outcome is unknown. Check Loop before trying again.", {
27557
+ cause,
27558
+ });
27559
+ }
27560
+ }
27561
+ function parseLoopTransferUpdate(value, commandId) {
27562
+ if (!value || typeof value !== "object")
27563
+ return undefined;
27564
+ const response = value;
27565
+ if (response.command_id !== commandId)
27566
+ return undefined;
27567
+ if (response.status === "failed" || response.error) {
27568
+ const error = response.error;
27569
+ return {
27570
+ status: "failed",
27571
+ commandId,
27572
+ message: typeof error?.error_message === "string"
27573
+ ? error.error_message
27574
+ : "Loop transaction failed",
27575
+ };
27576
+ }
27577
+ if (typeof response.update_id === "string" && response.update_id) {
27578
+ return { status: "completed", commandId, updateId: response.update_id };
27579
+ }
27580
+ return undefined;
27581
+ }
27582
+ class LoopCantonConnector {
27583
+ loadSdk;
27584
+ kind = "loop";
27585
+ providerId = "canton-loop";
27586
+ name = "Loop";
27587
+ target = undefined;
27588
+ module;
27589
+ initialization;
27590
+ provider;
27591
+ pendingConnection;
27592
+ connectionStart = Promise.resolve();
27593
+ transfers = new Map();
27594
+ listeners = { connect: new Set(), disconnect: new Set() };
27595
+ constructor(loadSdk = () => import('@fivenorth/loop-sdk')) {
27596
+ this.loadSdk = loadSdk;
27597
+ }
27598
+ get accounts() {
27599
+ return this.provider
27600
+ ? [{ partyId: this.provider.party_id, primary: true }]
27601
+ : [];
27602
+ }
27603
+ get address() {
27604
+ return this.provider?.party_id;
27605
+ }
27606
+ connect() {
27607
+ return this.startConnection(true);
27608
+ }
27609
+ autoConnect() {
27610
+ return this.startConnection(false);
27611
+ }
27612
+ cancelConnect() {
27613
+ if (!this.pendingConnection)
27614
+ return;
27615
+ this.rejectConnection(new CantonConnectionCancelledError());
27616
+ this.module?.loop.logout();
27617
+ }
27618
+ async disconnect() {
27619
+ this.cancelConnect();
27620
+ this.module?.loop.logout();
27621
+ this.provider = undefined;
27622
+ this.emit("disconnect");
27623
+ }
27624
+ async getAccounts() {
27625
+ const provider = this.requireProvider();
27626
+ try {
27627
+ const account = await provider.getAccount();
27628
+ if (account.party_id !== provider.party_id) {
27629
+ await this.disconnect();
27630
+ throw new Error("Loop account changed. Connect again.");
27631
+ }
27632
+ return this.accounts;
27633
+ }
27634
+ catch (error) {
27635
+ if (this.module && error instanceof this.module.UnauthorizedError) {
27636
+ await this.disconnect();
27637
+ }
27638
+ throw error;
27639
+ }
27640
+ }
27641
+ async getBalances(partyId) {
27642
+ const provider = this.requireProvider();
27643
+ if (partyId !== provider.party_id) {
27644
+ throw new Error("Loop balances require the connected account");
27645
+ }
27646
+ const holdings = await provider.getHolding();
27647
+ return sumCantonHoldingBalances(holdings.map((holding) => {
27648
+ const amount = new BigNumber(holding.total_unlocked_coin);
27649
+ if (!amount.isFinite() || amount.isNegative()) {
27650
+ throw new Error("Loop returned an invalid balance");
27651
+ }
27652
+ return {
27653
+ instrument: holding.instrument_id,
27654
+ amount: holding.total_unlocked_coin,
27655
+ };
27656
+ }));
27657
+ }
27658
+ transfer(params) {
27659
+ const commandId = getCantonCommandId(params.memo);
27660
+ const existing = this.transfers.get(commandId);
27661
+ if (existing)
27662
+ return existing;
27663
+ const request = this.submitTransfer(params, commandId).catch((error) => {
27664
+ if (!(error instanceof LoopSubmissionUnknownError))
27665
+ this.transfers.delete(commandId);
27666
+ throw error;
27667
+ });
27668
+ this.transfers.set(commandId, request);
27669
+ return request;
27670
+ }
27671
+ on(event, handler) {
27672
+ this.listeners[event].add(handler);
27673
+ }
27674
+ off(event, handler) {
27675
+ this.listeners[event].delete(handler);
27676
+ }
27677
+ emit(event, ...args) {
27678
+ this.listeners[event].forEach((handler) => handler(...args));
27679
+ }
27680
+ initialize() {
27681
+ if (!this.initialization) {
27682
+ this.initialization = this.loadSdk()
27683
+ .then((module) => {
27684
+ module.loop.init({
27685
+ appName: SQUID_METADATA.name,
27686
+ network: "mainnet",
27687
+ onAccept: (provider) => this.acceptConnection(provider),
27688
+ onReject: () => {
27689
+ this.rejectConnection(new CantonConnectionCancelledError());
27690
+ this.provider = undefined;
27691
+ this.emit("disconnect");
27692
+ },
27693
+ });
27694
+ this.module = module;
27695
+ })
27696
+ .catch((error) => {
27697
+ this.initialization = undefined;
27698
+ throw error;
27699
+ });
27700
+ }
27701
+ return this.initialization;
27702
+ }
27703
+ startConnection(interactive) {
27704
+ if (this.pendingConnection)
27705
+ return this.pendingConnection.promise;
27706
+ let resolve;
27707
+ let reject;
27708
+ const promise = new Promise((accept, decline) => {
27709
+ resolve = accept;
27710
+ reject = decline;
27711
+ });
27712
+ const timer = setTimeout(() => {
27713
+ this.rejectConnection(new Error("Loop connection timed out"));
27714
+ this.module?.loop.logout();
27715
+ }, REQUEST_TIMEOUT_MS);
27716
+ let observer;
27717
+ const pending = {
27718
+ promise,
27719
+ resolve,
27720
+ reject,
27721
+ cleanup: () => {
27722
+ clearTimeout(timer);
27723
+ observer?.disconnect();
27724
+ },
27725
+ };
27726
+ this.pendingConnection = pending;
27727
+ this.connectionStart = this.connectionStart
27728
+ .then(async () => {
27729
+ await this.initialize();
27730
+ if (this.pendingConnection !== pending)
27731
+ return;
27732
+ if (interactive && typeof MutationObserver !== "undefined") {
27733
+ let sawOverlay = false;
27734
+ observer = new MutationObserver(() => {
27735
+ const overlay = document.getElementById(OVERLAY_ID);
27736
+ if (overlay)
27737
+ sawOverlay = true;
27738
+ if (sawOverlay && !overlay && this.pendingConnection === pending) {
27739
+ this.cancelConnect();
27740
+ }
27741
+ });
27742
+ observer.observe(document.body, { childList: true });
27743
+ }
27744
+ const sdk = this.module.loop;
27745
+ if (interactive)
27746
+ await sdk.connect();
27747
+ else
27748
+ await sdk.autoConnect();
27749
+ if (!interactive && this.pendingConnection === pending) {
27750
+ this.rejectConnection(new Error("No saved Loop connection"));
27751
+ }
27752
+ else if (interactive &&
27753
+ this.pendingConnection !== pending &&
27754
+ !this.provider) {
27755
+ sdk.logout();
27756
+ }
27757
+ })
27758
+ .catch((error) => {
27759
+ if (this.pendingConnection === pending)
27760
+ this.rejectConnection(error);
27761
+ });
27762
+ return promise;
27763
+ }
27764
+ acceptConnection(provider) {
27765
+ const pending = this.pendingConnection;
27766
+ if (!pending)
27767
+ return;
27768
+ if (!provider.party_id) {
27769
+ this.rejectConnection(new Error("Loop returned no account"));
27770
+ return;
27771
+ }
27772
+ this.provider = provider;
27773
+ this.pendingConnection = undefined;
27774
+ pending.cleanup();
27775
+ pending.resolve({ address: provider.party_id, accounts: this.accounts });
27776
+ this.emit("connect", provider.party_id);
27777
+ }
27778
+ rejectConnection(error) {
27779
+ const pending = this.pendingConnection;
27780
+ if (!pending)
27781
+ return;
27782
+ this.pendingConnection = undefined;
27783
+ pending.cleanup();
27784
+ pending.reject(error);
27785
+ }
27786
+ requireProvider() {
27787
+ if (!this.provider)
27788
+ throw new Error("Loop wallet is not connected");
27789
+ return this.provider;
27790
+ }
27791
+ async submitTransfer(params, commandId) {
27792
+ const provider = this.requireProvider();
27793
+ if (params.sender !== provider.party_id)
27794
+ throw new Error("Loop account does not match the sender");
27795
+ const instrument = params.token.originalAddress
27796
+ ? parseCantonInstrument(params.token.originalAddress)
27797
+ : null;
27798
+ if (!instrument)
27799
+ throw new Error("Canton token originalAddress is required");
27800
+ if (!new BigNumber(params.amount).isFinite() ||
27801
+ !new BigNumber(params.amount).isPositive()) {
27802
+ throw new Error("Canton transfer amount must be positive");
27803
+ }
27804
+ const payload = await provider.connection.prepareTransfer(provider.getAuthToken(), {
27805
+ recipient: params.receiver,
27806
+ amount: params.amount,
27807
+ instrument: {
27808
+ instrument_admin: instrument.admin,
27809
+ instrument_id: instrument.id,
27810
+ },
27811
+ memo: params.memo,
27812
+ requested_at: new Date(params.nowMs - 60_000).toISOString(),
27813
+ execute_before: new Date(params.nowMs + 24 * 60 * 60_000).toISOString(),
27814
+ });
27815
+ if (this.provider !== provider)
27816
+ throw new Error("Loop account disconnected before submission");
27817
+ let response;
27818
+ let timer;
27819
+ try {
27820
+ const submission = { ...payload, commandId };
27821
+ const submitted = provider.submitAndWaitForTransaction(submission, {
27822
+ requestTimeout: REQUEST_TIMEOUT_MS,
27823
+ });
27824
+ response = await Promise.race([
27825
+ submitted,
27826
+ new Promise((_, reject) => {
27827
+ timer = setTimeout(() => reject(new Error("Loop submission timed out")), REQUEST_TIMEOUT_MS);
27828
+ }),
27829
+ ]);
27830
+ }
27831
+ catch (error) {
27832
+ if (this.module && error instanceof this.module.RejectRequestError) {
27833
+ throw Object.assign(new Error("Loop transaction rejected"), {
27834
+ code: 4001,
27835
+ });
27836
+ }
27837
+ throw new LoopSubmissionUnknownError(error);
27838
+ }
27839
+ finally {
27840
+ clearTimeout(timer);
27841
+ }
27842
+ const update = parseLoopTransferUpdate(response, commandId);
27843
+ if (update?.status === "failed")
27844
+ throw new Error(update.message);
27845
+ if (!update)
27846
+ throw new LoopSubmissionUnknownError();
27847
+ return update;
27848
+ }
27849
+ }
27850
+ const loopCantonConnector = new LoopCantonConnector();
27851
+
27120
27852
  /**
27121
27853
  * Discovers Canton browser-extension wallets and maps each to a
27122
27854
  * {@link CantonWallet}: CIP-103 announce-protocol wallets (on mount and on
@@ -27163,7 +27895,19 @@ function useCantonWallets() {
27163
27895
  return;
27164
27896
  const announced = (await discoverCantonProviders()).map(toAnnouncedWallet);
27165
27897
  const injected = discoverInjectedCantonWallets().map(toInjectedWallet);
27166
- setWallets(mergeInjectedCantonWallets(announced, injected));
27898
+ const loopWallet = {
27899
+ ...formatCantonWallet({
27900
+ connectorId: "canton-loop",
27901
+ name: "Loop",
27902
+ icon: "https://raw.githubusercontent.com/0xsquid/assets/main/images/master/wallets/canton-loop.svg",
27903
+ connector: loopCantonConnector,
27904
+ }),
27905
+ links: { website: "https://cantonloop.com" },
27906
+ isInstalled: () => false,
27907
+ skipInstallCheck: true,
27908
+ isMobile: true,
27909
+ };
27910
+ setWallets(mergeInjectedCantonWallets(announced, [...injected, loopWallet]));
27167
27911
  }, [toAnnouncedWallet, toInjectedWallet]);
27168
27912
  useEffect(() => {
27169
27913
  refresh();
@@ -27194,7 +27938,9 @@ function useCanton() {
27194
27938
  // Try to reconnect silently first (existing session, no popup)
27195
27939
  result = await wallet.connector.autoConnect();
27196
27940
  }
27197
- catch {
27941
+ catch (error) {
27942
+ if (error instanceof CantonConnectionCancelledError)
27943
+ throw error;
27198
27944
  // Otherwise prompt the wallet to connect
27199
27945
  result = await wallet.connector.connect();
27200
27946
  }
@@ -27216,8 +27962,7 @@ function useCanton() {
27216
27962
  wallet: recentCantonWallet,
27217
27963
  address,
27218
27964
  });
27219
- // eslint-disable-next-line react-hooks/exhaustive-deps
27220
- }, [wallets.map((w) => w.connectorId), recentCantonWalletId]);
27965
+ }, [wallets, recentCantonWalletId, setConnectedWallet]);
27221
27966
  useEffect(() => {
27222
27967
  const wallet = connectedCantonWallet.wallet;
27223
27968
  if (!wallet) {
@@ -27474,7 +28219,7 @@ function useStellarWallets() {
27474
28219
  try {
27475
28220
  const { allowAllModules: initializeAllModules } = await import('@creit.tech/stellar-wallets-kit');
27476
28221
  const { LedgerModule } = await import('@creit.tech/stellar-wallets-kit/modules/ledger.module.mjs');
27477
- const { formatStellarWallet } = await import('./stellarService.client-B__dTUBZ.js');
28222
+ const { formatStellarWallet } = await import('./stellarService.client-DtA9zkRt.js');
27478
28223
  const modules = [...initializeAllModules(), new LedgerModule()];
27479
28224
  const promises = modules.map(async (module) => {
27480
28225
  const isAvailable = await module.isAvailable();
@@ -28053,6 +28798,11 @@ const useWallet = () => {
28053
28798
  }
28054
28799
  }
28055
28800
  catch (error) {
28801
+ const connecting = useWalletStore.getState().connectingWalletState;
28802
+ if (connecting.wallet !== wallet ||
28803
+ connecting.status !== ConnectingWalletStatus.CONNECTING) {
28804
+ return false;
28805
+ }
28056
28806
  console.error("Failed to connect wallet", error);
28057
28807
  walletConnectionError(wallet, error);
28058
28808
  return false;
@@ -28284,8 +29034,6 @@ const useMultiChainWallet = (chain) => {
28284
29034
  chainType: chain.chainType,
28285
29035
  }),
28286
29036
  };
28287
- case ChainType.DANAL:
28288
- return {};
28289
29037
  }
28290
29038
  }, [
28291
29039
  chain?.chainType,
@@ -28399,12 +29147,27 @@ const useMultiChainWallet = (chain) => {
28399
29147
  };
28400
29148
 
28401
29149
  const useSwap = () => {
28402
- const { initialAssets, defaultTokensPerChain, disabledChains, availableChains, } = useConfigStore((state) => state.config);
29150
+ const { initialAssets, defaultTokensPerChain, disabledChains, availableChains, availableTokens, } = useConfigStore((state) => state.config);
28403
29151
  const fromPrice = useTransactionStore((state) => state.fromPrice);
28404
- const { swapRoute } = useSwapRoutePersistStore();
29152
+ const { swapRoute: storedSwapRoute } = useSwapRoutePersistStore();
28405
29153
  const { tokens } = useSquidTokens();
28406
29154
  const queryClient = useQueryClient();
28407
29155
  const { chains, supportedDestinationChains, supportedSourceChains } = useSquidChains();
29156
+ const swapRoute = useMemo(() => storedSwapRoute
29157
+ ? normalizeSwapParamsForSelection({
29158
+ swapParams: storedSwapRoute,
29159
+ tokens,
29160
+ chains,
29161
+ config: { disabledChains, availableChains, availableTokens },
29162
+ })
29163
+ : undefined, [
29164
+ storedSwapRoute,
29165
+ tokens,
29166
+ chains,
29167
+ disabledChains,
29168
+ availableChains,
29169
+ availableTokens,
29170
+ ]);
28408
29171
  const sourceChainId = useMemo(() => swapRoute?.fromChainId ??
28409
29172
  (initialAssets?.from
28410
29173
  ? resolveChainIdFromAsset(initialAssets.from, supportedSourceChains)
@@ -28415,13 +29178,23 @@ const useSwap = () => {
28415
29178
  : undefined), [swapRoute?.toChainId, supportedDestinationChains, initialAssets?.to]);
28416
29179
  const fromChain = useMemo(() => supportedSourceChains.find((c) => c.chainId === swapRoute?.fromChainId), [swapRoute?.fromChainId, supportedSourceChains]);
28417
29180
  const toChain = useMemo(() => supportedDestinationChains.find((c) => c.chainId === swapRoute?.toChainId), [swapRoute?.toChainId, supportedDestinationChains]);
28418
- const fromTokens = useMemo(() => getTokensForChain(tokens, sourceChainId), [tokens, sourceChainId]);
29181
+ const fromTokens = useMemo(() => {
29182
+ const chainTokens = getTokensForChain(tokens, sourceChainId);
29183
+ return isArcChain(sourceChainId)
29184
+ ? filterViewableTokens(chainTokens, { availableTokens }, "from")
29185
+ : chainTokens;
29186
+ }, [tokens, sourceChainId, availableTokens]);
28419
29187
  const fromToken = useMemo(() => fromTokens.find((t) => t.address.toLowerCase() === swapRoute?.fromTokenAddress?.toLowerCase()), [fromTokens, swapRoute?.fromTokenAddress]);
28420
- const toTokens = useMemo(() => filterTokensForDestination({
28421
- tokens: getTokensForChain(tokens, destChainId),
28422
- selectedDestinationChain: toChain,
28423
- selectedSourceToken: fromToken,
28424
- }), [destChainId, toChain, fromToken, tokens]);
29188
+ const toTokens = useMemo(() => {
29189
+ const destinationTokens = filterTokensForDestination({
29190
+ tokens: getTokensForChain(tokens, destChainId),
29191
+ selectedDestinationChain: toChain,
29192
+ selectedSourceToken: fromToken,
29193
+ });
29194
+ return isArcChain(destChainId)
29195
+ ? filterViewableTokens(destinationTokens, { availableTokens }, "to")
29196
+ : destinationTokens;
29197
+ }, [destChainId, toChain, fromToken, tokens, availableTokens]);
28425
29198
  const toToken = useMemo(() => toTokens.find((t) => t.address.toLowerCase() === swapRoute?.toTokenAddress?.toLowerCase()), [toTokens, swapRoute?.toTokenAddress]);
28426
29199
  const isSameChain = sourceChainId === destChainId;
28427
29200
  const tokenItems = useMemo(() => ({ from: fromTokens, to: toTokens }), [fromTokens, toTokens]);
@@ -28469,6 +29242,7 @@ const useSwap = () => {
28469
29242
  defaultTokensPerChain,
28470
29243
  disabledChains,
28471
29244
  availableChains,
29245
+ availableTokens,
28472
29246
  },
28473
29247
  queryClient,
28474
29248
  connectedSourceAddress: connectedSourceAddress.address,
@@ -28508,6 +29282,7 @@ const useSwap = () => {
28508
29282
  defaultTokensPerChain,
28509
29283
  disabledChains,
28510
29284
  availableChains,
29285
+ availableTokens,
28511
29286
  initialAssets,
28512
29287
  queryClient,
28513
29288
  swapRoute,
@@ -28563,6 +29338,10 @@ const useSwap = () => {
28563
29338
  },
28564
29339
  direction: "to",
28565
29340
  });
29341
+ if ([defaultFromChainId, defaultToChainId].some((chainId) => isArcChain(chainId) &&
29342
+ !tokens.some((token) => token.chainId === chainId && !isArcNativeToken(token)))) {
29343
+ return;
29344
+ }
28566
29345
  const fromTokenAddress = getInitialOrDefaultTokenAddressForChain({
28567
29346
  tokens,
28568
29347
  config: {
@@ -28570,6 +29349,7 @@ const useSwap = () => {
28570
29349
  defaultTokensPerChain,
28571
29350
  disabledChains,
28572
29351
  availableChains,
29352
+ availableTokens,
28573
29353
  },
28574
29354
  chainId: defaultFromChainId,
28575
29355
  direction: "from",
@@ -28581,6 +29361,7 @@ const useSwap = () => {
28581
29361
  defaultTokensPerChain,
28582
29362
  disabledChains,
28583
29363
  availableChains,
29364
+ availableTokens,
28584
29365
  },
28585
29366
  chainId: defaultToChainId,
28586
29367
  direction: "to",
@@ -28605,6 +29386,7 @@ const useSwap = () => {
28605
29386
  initialAssets,
28606
29387
  disabledChains,
28607
29388
  availableChains,
29389
+ availableTokens,
28608
29390
  defaultTokensPerChain,
28609
29391
  tokens,
28610
29392
  ]);
@@ -29124,8 +29906,6 @@ async function createClient(chain) {
29124
29906
  return new StellarRpcClient(chain.rpc);
29125
29907
  case ChainType.CANTON:
29126
29908
  return null;
29127
- case ChainType.DANAL:
29128
- return null;
29129
29909
  }
29130
29910
  }
29131
29911
 
@@ -30140,8 +30920,7 @@ const getAllStellarTokensBalance = async (userAddress, stellarTokens, stellarCha
30140
30920
  };
30141
30921
  /**
30142
30922
  * Canton balances are private: they can only be read with a wallet-authorized
30143
- * `ledgerApi` session (the connected wallet supplies a JWT that can read as the
30144
- * party). So balance is fetchable only when a Canton wallet is connected, and
30923
+ * session. Balance is fetchable only when a Canton wallet is connected, and
30145
30924
  * only for that wallet's party — there's no address-only read.
30146
30925
  */
30147
30926
  const getCantonTokenBalance = async (userAddress, token, cantonConnector) => {
@@ -30150,30 +30929,14 @@ const getCantonTokenBalance = async (userAddress, token, cantonConnector) => {
30150
30929
  const instrument = parseCantonInstrument(token.originalAddress);
30151
30930
  if (!instrument)
30152
30931
  return "0";
30153
- const ledgerEnd = await cantonConnector.ledgerApi({ requestMethod: "get", resource: "/v2/state/ledger-end" });
30154
- const activeContracts = await cantonConnector.ledgerApi({
30155
- requestMethod: "post",
30156
- resource: "/v2/state/active-contracts",
30157
- body: buildHoldingsAcsRequestBody(userAddress, String(ledgerEnd.offset)),
30158
- });
30159
- const grouped = groupCantonHoldingBalances(activeContracts);
30932
+ const grouped = await cantonConnector.getBalances(userAddress);
30160
30933
  return grouped[cantonInstrumentKey(instrument)] ?? "0";
30161
30934
  };
30162
30935
  /**
30163
- * Fetch balances for all Canton tokens in one ACS query. Canton balances are
30164
- * private, so this requires a connected wallet's authorized `ledgerApi`.
30936
+ * Fetch balances for all Canton tokens through the connected wallet.
30165
30937
  */
30166
30938
  async function getAllCantonTokensBalance({ connector, partyId, tokens, }) {
30167
- const ledgerEnd = await connector.ledgerApi({
30168
- requestMethod: "get",
30169
- resource: "/v2/state/ledger-end",
30170
- });
30171
- const activeContracts = await connector.ledgerApi({
30172
- requestMethod: "post",
30173
- resource: "/v2/state/active-contracts",
30174
- body: buildHoldingsAcsRequestBody(partyId, String(ledgerEnd.offset)),
30175
- });
30176
- const grouped = groupCantonHoldingBalances(activeContracts);
30939
+ const grouped = await connector.getBalances(partyId);
30177
30940
  return tokens.map((token) => {
30178
30941
  const instrument = token.originalAddress
30179
30942
  ? parseCantonInstrument(token.originalAddress)
@@ -30392,7 +31155,7 @@ const useCantonBalance = ({ chain, token, userAddress, enabled = true, refreshIn
30392
31155
  };
30393
31156
 
30394
31157
  function useNativeTokenForChain(chain) {
30395
- const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, cantonTokens, danalTokens, } = useSquidTokens();
31158
+ const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, cantonTokens, } = useSquidTokens();
30396
31159
  const getTokensForChainType = () => {
30397
31160
  if (!chain?.chainType)
30398
31161
  return [];
@@ -30413,21 +31176,20 @@ function useNativeTokenForChain(chain) {
30413
31176
  return stellarTokens;
30414
31177
  case ChainType.CANTON:
30415
31178
  return cantonTokens;
30416
- case ChainType.DANAL:
30417
- return danalTokens;
30418
31179
  }
30419
31180
  };
31181
+ const tokens = getTokensForChainType();
30420
31182
  const nativeTokenForChainType = useMemo(() => {
30421
31183
  if (!chain)
30422
31184
  return undefined;
30423
- return findNativeToken(getTokensForChainType(), chain);
30424
- }, [chain]);
31185
+ return findNativeToken(tokens, chain);
31186
+ }, [chain, tokens]);
30425
31187
  return { nativeToken: nativeTokenForChainType };
30426
31188
  }
30427
31189
 
30428
31190
  const useEvmNativeBalance = ({ address, chain, }) => {
30429
31191
  const { isChainTypeConnected } = useWallet();
30430
- const { data: nativeEvmBalance, isLoading } = useBalance({
31192
+ const { data: nativeEvmBalance, isLoading, isError, } = useBalance({
30431
31193
  address: address,
30432
31194
  chainId: Number(chain?.chainId),
30433
31195
  query: {
@@ -30439,6 +31201,8 @@ const useEvmNativeBalance = ({ address, chain, }) => {
30439
31201
  },
30440
31202
  });
30441
31203
  const balance = useMemo(() => {
31204
+ if (isArcChain(chain?.chainId) && isError)
31205
+ return undefined;
30442
31206
  if (nativeEvmBalance?.decimals != null && nativeEvmBalance?.value != null) {
30443
31207
  if (chain?.chainId === CHAIN_IDS.HEDERA) {
30444
31208
  return {
@@ -30452,7 +31216,12 @@ const useEvmNativeBalance = ({ address, chain, }) => {
30452
31216
  };
30453
31217
  }
30454
31218
  return;
30455
- }, [nativeEvmBalance?.decimals, nativeEvmBalance?.value, chain?.chainId]);
31219
+ }, [
31220
+ nativeEvmBalance?.decimals,
31221
+ nativeEvmBalance?.value,
31222
+ chain?.chainId,
31223
+ isError,
31224
+ ]);
30456
31225
  return {
30457
31226
  balance,
30458
31227
  isLoading,
@@ -30675,9 +31444,6 @@ const useNativeBalance = (chain) => {
30675
31444
  case ChainType.CANTON:
30676
31445
  balance = nativeCantonBalance;
30677
31446
  break;
30678
- case ChainType.DANAL:
30679
- balance = undefined;
30680
- break;
30681
31447
  }
30682
31448
  const balanceFormatted = !!balance
30683
31449
  ? formatBNToReadable(balance.value, balance.decimals)
@@ -30717,8 +31483,6 @@ const useNativeBalance = (chain) => {
30717
31483
  return isStellarLoading;
30718
31484
  case ChainType.CANTON:
30719
31485
  return isCantonLoading;
30720
- case ChainType.DANAL:
30721
- return false;
30722
31486
  }
30723
31487
  }, [
30724
31488
  chain?.chainType,
@@ -30944,7 +31708,7 @@ function hederaWalletConnect(parameters) {
30944
31708
  const optionalChains = config.chains.map((x) => x.id);
30945
31709
  if (!optionalChains.length)
30946
31710
  return;
30947
- const { EthereumProvider } = await import('./index.es--AR2n7a0.js');
31711
+ const { EthereumProvider } = await import('./index.es-BiK_wjSb.js');
30948
31712
  const rawProvider = await EthereumProvider.init({
30949
31713
  ...restParameters,
30950
31714
  disableProviderPing: true,
@@ -31178,8 +31942,6 @@ const useSigner = ({ chain }) => {
31178
31942
  return isStellarSignerReady;
31179
31943
  case ChainType.CANTON:
31180
31944
  return isCantonSignerReady;
31181
- case ChainType.DANAL:
31182
- return false;
31183
31945
  }
31184
31946
  }, [
31185
31947
  chain?.chainType,
@@ -31632,12 +32394,8 @@ const useSendTransactionStore = create((set, get) => ({
31632
32394
  const useDepositAddressStore = create((set) => ({
31633
32395
  deposit: null,
31634
32396
  selectedPaymentMethod: "connectedWallet",
31635
- userDepositTxId: null,
31636
32397
  setDeposit: (data) => {
31637
- set({ deposit: data, userDepositTxId: null });
31638
- },
31639
- setUserDepositTxId: (txId) => {
31640
- set({ userDepositTxId: txId });
32398
+ set({ deposit: data });
31641
32399
  },
31642
32400
  setPaymentMethod: (method) => {
31643
32401
  set({ selectedPaymentMethod: method });
@@ -31649,7 +32407,7 @@ function useDepositAddress(squidRoute) {
31649
32407
  selectedPaymentMethod: state.selectedPaymentMethod,
31650
32408
  depositAddress: state.deposit?.depositAddress,
31651
32409
  }));
31652
- const { setDeposit, setPaymentMethod, deposit, userDepositTxId, setUserDepositTxId, } = useDepositAddressStore();
32410
+ const { setDeposit, setPaymentMethod, deposit } = useDepositAddressStore();
31653
32411
  const { squid } = useSquidStore();
31654
32412
  const { fromChain } = useSwap();
31655
32413
  const isAvailableAsPaymentMethod = useMemo(() => {
@@ -31659,13 +32417,11 @@ function useDepositAddress(squidRoute) {
31659
32417
  CHAIN_IDS.BITCOIN,
31660
32418
  CHAIN_IDS.SOLANA,
31661
32419
  CHAIN_IDS.CANTON,
31662
- CHAIN_IDS.DANAL_TESTNET,
31663
32420
  ];
31664
32421
  return chainsSupportingDepositAddress.includes(fromChain.chainId);
31665
32422
  }, [fromChain?.chainId]);
31666
- const routeProvidesDirectDepositAddress = (!!squidRoute?.transactionRequest &&
31667
- isDepositAddressDirectTransferRoute(squidRoute.transactionRequest)) ||
31668
- (!!squidRoute && isDanalDepositRoute(squidRoute));
32423
+ const routeProvidesDirectDepositAddress = !!squidRoute?.transactionRequest &&
32424
+ isDepositAddressDirectTransferRoute(squidRoute.transactionRequest);
31669
32425
  const swapWillGenerateDepositAddress = isChainflipDepositRoute(squidRoute) || routeProvidesDirectDepositAddress;
31670
32426
  const paymentMethod = isAvailableAsPaymentMethod
31671
32427
  ? selectedPaymentMethod
@@ -31691,19 +32447,6 @@ function useDepositAddress(squidRoute) {
31691
32447
  });
31692
32448
  return;
31693
32449
  }
31694
- else if (isDanalDepositRoute(route)) {
31695
- const transferBody = parseDanalTransferBody(route.transactionRequest.data);
31696
- if (!transferBody) {
31697
- throw new Error("Could not parse Danal transfer request body");
31698
- }
31699
- setDeposit({
31700
- amount: transferBody.amount,
31701
- depositAddress: route.transactionRequest.target,
31702
- statusTrackingId: transferBody.memo,
31703
- memo: transferBody.memo,
31704
- });
31705
- return;
31706
- }
31707
32450
  else if (isDepositAddressDirectTransferRoute(route.transactionRequest)) {
31708
32451
  // Canton case
31709
32452
  const orderHash = route.transactionRequest.data;
@@ -31726,8 +32469,6 @@ function useDepositAddress(squidRoute) {
31726
32469
  depositAddress,
31727
32470
  closeDepositChannel,
31728
32471
  depositData: deposit,
31729
- userDepositTxId,
31730
- setUserDepositTxId,
31731
32472
  };
31732
32473
  }
31733
32474
 
@@ -31755,7 +32496,7 @@ const useUrlSwapParams = () => {
31755
32496
 
31756
32497
  const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, queryOptions, }) => {
31757
32498
  const { evmChains, cosmosChains, suiChains, xrplChains, stellarChains } = useSquidChains(direction);
31758
- const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, cantonTokens, danalTokens, } = useSquidTokens(direction);
32499
+ const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, cantonTokens, } = useSquidTokens(direction);
31759
32500
  const { keplrTypeWallet } = useCosmosContext();
31760
32501
  const cantonConnector = useWalletStore((store) => store.connectedWalletsByChainType[ChainType.CANTON]?.wallet?.connector);
31761
32502
  const placeholderData = useMemo(() => {
@@ -31768,7 +32509,6 @@ const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, qu
31768
32509
  [ChainType.XRPL]: xrplTokens.map((t) => ({ ...t, balance: "0" })),
31769
32510
  [ChainType.STELLAR]: stellarTokens.map((t) => ({ ...t, balance: "0" })),
31770
32511
  [ChainType.CANTON]: cantonTokens.map((t) => ({ ...t, balance: "0" })),
31771
- [ChainType.DANAL]: danalTokens.map((t) => ({ ...t, balance: "0" })),
31772
32512
  };
31773
32513
  if (!chainType) {
31774
32514
  // Return all tokens with zero balance
@@ -31791,7 +32531,6 @@ const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, qu
31791
32531
  xrplTokens,
31792
32532
  stellarTokens,
31793
32533
  cantonTokens,
31794
- danalTokens,
31795
32534
  ]);
31796
32535
  const isQueryEnabled = useMemo(() => {
31797
32536
  // Respect the queryOptions.enabled override if provided
@@ -31816,8 +32555,6 @@ const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, qu
31816
32555
  return stellarTokens.length > 0;
31817
32556
  case ChainType.CANTON:
31818
32557
  return cantonTokens.length > 0;
31819
- case ChainType.DANAL:
31820
- return danalTokens.length > 0;
31821
32558
  }
31822
32559
  }, [
31823
32560
  chainType,
@@ -31831,7 +32568,6 @@ const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, qu
31831
32568
  xrplTokens.length,
31832
32569
  stellarTokens.length,
31833
32570
  cantonTokens.length,
31834
- danalTokens.length,
31835
32571
  ]);
31836
32572
  const query = useQuery(keys().allTokensBalance(address, chainType, direction), async () => {
31837
32573
  // Return zero balances if no address
@@ -31956,12 +32692,6 @@ const useAllConnectedWalletBalances = ({ direction, queryOptions = {
31956
32692
  direction,
31957
32693
  queryOptions,
31958
32694
  });
31959
- const danalBalancesQuery = useAllTokensWithBalanceForChainType({
31960
- chainType: ChainType.DANAL,
31961
- address: connectedAddresses?.[ChainType.DANAL],
31962
- direction,
31963
- queryOptions,
31964
- });
31965
32695
  // Create a map of chain type to balance query results
31966
32696
  const balanceQueries = useMemo(() => ({
31967
32697
  [ChainType.EVM]: evmBalancesQuery,
@@ -31972,7 +32702,6 @@ const useAllConnectedWalletBalances = ({ direction, queryOptions = {
31972
32702
  [ChainType.XRPL]: xrplBalancesQuery,
31973
32703
  [ChainType.STELLAR]: stellarBalancesQuery,
31974
32704
  [ChainType.CANTON]: cantonBalancesQuery,
31975
- [ChainType.DANAL]: danalBalancesQuery,
31976
32705
  }), [
31977
32706
  evmBalancesQuery,
31978
32707
  cosmosBalancesQuery,
@@ -31982,7 +32711,6 @@ const useAllConnectedWalletBalances = ({ direction, queryOptions = {
31982
32711
  xrplBalancesQuery,
31983
32712
  stellarBalancesQuery,
31984
32713
  cantonBalancesQuery,
31985
- danalBalancesQuery,
31986
32714
  ]);
31987
32715
  // Combine all tokens from different chains
31988
32716
  const allTokens = useMemo(() => Object.values(balanceQueries).flatMap((query) => query.data?.tokens ?? []), [balanceQueries]);
@@ -32090,8 +32818,6 @@ const useMultiChainBalance = ({ chain, token, userAddress, enabled = true, }) =>
32090
32818
  return stellarBalance;
32091
32819
  case ChainType.CANTON:
32092
32820
  return cantonBalance;
32093
- case ChainType.DANAL:
32094
- return "0";
32095
32821
  }
32096
32822
  }, [
32097
32823
  chain?.chainType,
@@ -32297,6 +33023,27 @@ function useSourceChainGasToken({ fromChain, fromToken, }) {
32297
33023
  normalizeFee: convertTempoFeeToStablecoinUnits,
32298
33024
  };
32299
33025
  }
33026
+ if (isArcChain(fromChain.chainId)) {
33027
+ const isUsdc = isArcUsdcToken(fromToken);
33028
+ const isNative = isArcNativeToken(fromToken);
33029
+ if (fromToken.chainId !== fromChain.chainId ||
33030
+ nativeBalance.decimals !== 18 ||
33031
+ (isUsdc && fromToken.decimals !== 6) ||
33032
+ (isNative && fromToken.decimals !== 18)) {
33033
+ return null;
33034
+ }
33035
+ return {
33036
+ fromTokenPaysGasFees: isUsdc || isNative,
33037
+ gasTokenBalanceWei: nativeBalance.value,
33038
+ normalizeFee: (fee) => fee,
33039
+ fromAmountToGasUnits: isUsdc
33040
+ ? (amount) => amount * 10n ** 12n
33041
+ : undefined,
33042
+ gasUnitsToFromAmount: isUsdc
33043
+ ? (amount) => amount / 10n ** 12n
33044
+ : undefined,
33045
+ };
33046
+ }
32300
33047
  return {
32301
33048
  fromTokenPaysGasFees: fromToken.address.toLowerCase() ===
32302
33049
  chainTypeToNativeTokenAddressMap[fromToken.type].toLowerCase(),
@@ -32304,10 +33051,10 @@ function useSourceChainGasToken({ fromChain, fromToken, }) {
32304
33051
  normalizeFee: (fee) => fee,
32305
33052
  };
32306
33053
  }, [
32307
- fromToken?.address,
32308
- fromToken?.type,
33054
+ fromToken,
32309
33055
  fromChain?.chainId,
32310
33056
  nativeBalance?.value,
33057
+ nativeBalance?.decimals,
32311
33058
  tempoFeeData,
32312
33059
  ]);
32313
33060
  /**
@@ -32322,9 +33069,20 @@ function useSourceChainGasToken({ fromChain, fromToken, }) {
32322
33069
  return evmTokens.find((t) => t.chainId === fromChain.chainId &&
32323
33070
  t.address.toLowerCase() === tempoFeeData.gasTokenAddress.toLowerCase());
32324
33071
  }
33072
+ if (isArcChain(fromChain.chainId)) {
33073
+ return nativeToken?.decimals === 18
33074
+ ? {
33075
+ ...nativeToken,
33076
+ symbol: fromChain.nativeCurrency.symbol,
33077
+ name: fromChain.nativeCurrency.name,
33078
+ }
33079
+ : undefined;
33080
+ }
32325
33081
  return nativeToken;
32326
33082
  }, [
32327
33083
  fromChain?.chainId,
33084
+ fromChain?.nativeCurrency.symbol,
33085
+ fromChain?.nativeCurrency.name,
32328
33086
  fromToken?.address,
32329
33087
  nativeToken,
32330
33088
  tempoFeeData,
@@ -32483,22 +33241,57 @@ const calculateTotalNativeFees = ({ expressFeeCost, firstFeeCost, firstGasCost,
32483
33241
  (sameTokenBetweenFees
32484
33242
  ? BigInt(firstFeeCost?.amount ?? "0") + BigInt(firstGasCost?.amount ?? "0")
32485
33243
  : BigInt(firstGasCost?.amount ?? "0"));
33244
+ const addGasReserve = (fee) => (fee * 110n + 99n) / 100n;
33245
+ const calculateArcGasCosts = (gasCosts) => {
33246
+ const sourceGasCosts = gasCosts.filter((cost) => isArcChain(cost.token.chainId));
33247
+ if (sourceGasCosts.length === 0)
33248
+ return undefined;
33249
+ let total = 0n;
33250
+ for (const { amount, token } of sourceGasCosts) {
33251
+ const fee = BigInt(amount);
33252
+ if (fee <= 0n)
33253
+ return undefined;
33254
+ if (isArcUsdcToken(token) && token.decimals === 6) {
33255
+ total += fee * 10n ** 12n;
33256
+ }
33257
+ else if (isArcNativeToken(token) && token.decimals === 18) {
33258
+ total += fee;
33259
+ }
33260
+ else {
33261
+ return undefined;
33262
+ }
33263
+ }
33264
+ return total;
33265
+ };
33266
+ const calculateTotalGasBalanceNeeded = ({ fromAmount, networkFeesWei, chainFeeParams, }) => {
33267
+ if (!chainFeeParams || networkFeesWei == null)
33268
+ return undefined;
33269
+ if (!chainFeeParams.fromTokenPaysGasFees)
33270
+ return networkFeesWei;
33271
+ const amount = BigInt(fromAmount ?? "0");
33272
+ const amountInGasUnits = chainFeeParams.fromAmountToGasUnits?.(amount) ?? amount;
33273
+ return amountInGasUnits + networkFeesWei;
33274
+ };
32486
33275
  const checkIsGasBalanceEnough = ({ fromAmount, networkFeesWei, chainFeeParams, }) => {
32487
33276
  if (!chainFeeParams)
32488
33277
  return false;
32489
- if (chainFeeParams.fromTokenPaysGasFees) {
32490
- return (BigInt(fromAmount ?? "0") + networkFeesWei <=
32491
- chainFeeParams.gasTokenBalanceWei);
32492
- }
32493
- return networkFeesWei <= chainFeeParams.gasTokenBalanceWei;
33278
+ const total = calculateTotalGasBalanceNeeded({
33279
+ fromAmount,
33280
+ networkFeesWei,
33281
+ chainFeeParams,
33282
+ });
33283
+ return total != null && total <= chainFeeParams.gasTokenBalanceWei;
32494
33284
  };
32495
33285
  const calculateMinAmountValueWarnMsg = ({ networkFeesWei, chainFeeParams, fromTokenDecimals, }) => {
32496
- if (!chainFeeParams?.fromTokenPaysGasFees)
33286
+ if (!chainFeeParams?.fromTokenPaysGasFees || networkFeesWei == null)
32497
33287
  return undefined;
32498
33288
  const minAmount = chainFeeParams.gasTokenBalanceWei - networkFeesWei;
32499
33289
  if (minAmount <= BigInt(0))
32500
33290
  return undefined;
32501
- return formatBNToReadable(minAmount, fromTokenDecimals);
33291
+ const amountInTokenUnits = chainFeeParams.gasUnitsToFromAmount?.(minAmount) ?? minAmount;
33292
+ if (amountInTokenUnits <= 0n)
33293
+ return undefined;
33294
+ return formatBNToReadable(amountInTokenUnits, fromTokenDecimals);
32502
33295
  };
32503
33296
  /**
32504
33297
  * Calculates the estimated duration of a route
@@ -32547,14 +33340,22 @@ const calculateEstimateResults = ({ squidRoute, tokens, fromChain, toChain, coll
32547
33340
  const expectedGasRefundCostUSD = convertTokenAmountToUSD(formatBNToReadable(expectedGasRefundCost, firstFeeCost?.token.decimals ?? 18), firstFeeCost?.token.usdPrice ?? "0");
32548
33341
  const sameTokenBetweenFees = firstFeeCost?.token.address === firstGasCost?.token.address &&
32549
33342
  firstFeeCost?.token.chainId === firstGasCost?.token.chainId;
32550
- const totalNativeFees = calculateTotalNativeFees({
32551
- expressFeeCost,
32552
- firstFeeCost,
32553
- firstGasCost,
32554
- sameTokenBetweenFees,
32555
- });
32556
- const totalFeesInNativeTokenPlusRatio = (totalNativeFees * BigInt(110)) / BigInt(100);
32557
- const networkFeesWei = chainFeeParams?.normalizeFee(totalFeesInNativeTokenPlusRatio) ?? BigInt(0);
33343
+ const totalNativeFees = isArcChain(fromChain?.chainId)
33344
+ ? calculateArcGasCosts(allGasCosts)
33345
+ : calculateTotalNativeFees({
33346
+ expressFeeCost,
33347
+ firstFeeCost,
33348
+ firstGasCost,
33349
+ sameTokenBetweenFees,
33350
+ });
33351
+ const totalFeesInNativeTokenPlusRatio = totalNativeFees == null
33352
+ ? undefined
33353
+ : isArcChain(fromChain?.chainId)
33354
+ ? addGasReserve(totalNativeFees)
33355
+ : (totalNativeFees * BigInt(110)) / BigInt(100);
33356
+ const networkFeesWei = totalFeesInNativeTokenPlusRatio == null
33357
+ ? undefined
33358
+ : chainFeeParams?.normalizeFee(totalFeesInNativeTokenPlusRatio);
32558
33359
  const isGasBalanceEnough = checkIsGasBalanceEnough({
32559
33360
  chainFeeParams,
32560
33361
  fromAmount,
@@ -32570,10 +33371,12 @@ const calculateEstimateResults = ({ squidRoute, tokens, fromChain, toChain, coll
32570
33371
  estimatedRouteDuration: squidRoute?.estimate?.estimatedRouteDuration,
32571
33372
  isSingleChainRoute,
32572
33373
  });
32573
- // gas fees + fromAmount (if fromToken is gas token)
32574
- const totalGasBalanceNeeded = networkFeesWei +
32575
- BigInt(chainFeeParams?.fromTokenPaysGasFees ? (fromAmount ?? 0) : 0);
32576
- const gasBalanceNeeded = gasToken
33374
+ const totalGasBalanceNeeded = calculateTotalGasBalanceNeeded({
33375
+ fromAmount,
33376
+ networkFeesWei,
33377
+ chainFeeParams,
33378
+ });
33379
+ const gasBalanceNeeded = gasToken && totalGasBalanceNeeded != null
32577
33380
  ? formatBNToReadable(totalGasBalanceNeeded, gasToken.decimals)
32578
33381
  : undefined;
32579
33382
  return {
@@ -32595,7 +33398,7 @@ const calculateEstimateResults = ({ squidRoute, tokens, fromChain, toChain, coll
32595
33398
  expectedGasRefundCostUSD,
32596
33399
  sameTokenBetweenFees,
32597
33400
  fromTokenPaysGasFees: chainFeeParams?.fromTokenPaysGasFees ?? false,
32598
- totalNativeFees,
33401
+ totalNativeFees: totalNativeFees ?? 0n,
32599
33402
  isGasBalanceEnough,
32600
33403
  minAmountValueWarnMsg,
32601
33404
  estimatedRouteDuration,
@@ -32644,8 +33447,12 @@ function useSendTransactionGas({ chain, token, from, }) {
32644
33447
  case ChainType.EVM: {
32645
33448
  const client = await getClient(chain);
32646
33449
  const feeData = await client.getFeeData();
32647
- if (!feeData.maxFeePerGas)
33450
+ if (!feeData.maxFeePerGas) {
33451
+ if (isArcChain(chain.chainId)) {
33452
+ throw new Error("Gas price is unavailable");
33453
+ }
32648
33454
  return BigInt(0);
33455
+ }
32649
33456
  let maxFeePerGas = feeData.maxFeePerGas;
32650
33457
  if (token.chainId === CHAIN_IDS.HEDERA) {
32651
33458
  maxFeePerGas = scaleWeiToHbar(BigInt(feeData.maxFeePerGas));
@@ -32665,6 +33472,9 @@ function useSendTransactionGas({ chain, token, from, }) {
32665
33472
  value: 1,
32666
33473
  chainId: chain.chainId,
32667
33474
  });
33475
+ if (isArcChain(chain.chainId) && gas <= 0n) {
33476
+ throw new Error("Gas estimate is unavailable");
33477
+ }
32668
33478
  return gas * maxFeePerGas;
32669
33479
  }
32670
33480
  const erc20Interface = new Interface(erc20Abi);
@@ -32679,6 +33489,9 @@ function useSendTransactionGas({ chain, token, from, }) {
32679
33489
  chainId: chain.chainId,
32680
33490
  });
32681
33491
  const feeWei = gas * maxFeePerGas;
33492
+ if (isArcChain(chain.chainId) && feeWei <= 0n) {
33493
+ throw new Error("Gas estimate is unavailable");
33494
+ }
32682
33495
  // Tempo gas fees are denominated 18 units,
32683
33496
  // this value needs to be scaled to 6 decimals
32684
33497
  if (chain.chainId === CHAIN_IDS.TEMPO) {
@@ -32726,35 +33539,45 @@ function useSendTransactionGas({ chain, token, from, }) {
32726
33539
  }
32727
33540
 
32728
33541
  function useEstimateSendTransaction({ chain, token, amount, balance, from, }) {
32729
- const { data: estimatedGas = BigInt(0), isLoading } = useSendTransactionGas({
33542
+ const { data, isLoading, isFetching, isError, refetch } = useSendTransactionGas({
32730
33543
  chain,
32731
33544
  token,
32732
33545
  from,
32733
33546
  });
33547
+ const estimatedGas = isError || isFetching ? undefined : data;
33548
+ const networkFeesWei = estimatedGas == null
33549
+ ? undefined
33550
+ : isArcChain(chain?.chainId)
33551
+ ? addGasReserve(estimatedGas)
33552
+ : estimatedGas;
32734
33553
  const { chainFeeParams, gasToken } = useSourceChainGasToken({
32735
33554
  fromChain: chain,
32736
33555
  fromToken: token,
32737
33556
  });
32738
33557
  const isGasBalanceEnough = useMemo(() => {
32739
- if (!amount || !token?.decimals)
33558
+ if (!amount || token?.decimals == null || !gasToken)
32740
33559
  return false;
32741
33560
  return checkIsGasBalanceEnough({
32742
33561
  fromAmount: parseToBigInt(amount, token.decimals).toString(),
32743
- networkFeesWei: estimatedGas,
33562
+ networkFeesWei,
32744
33563
  chainFeeParams,
32745
33564
  });
32746
- }, [amount, estimatedGas, token, chainFeeParams]);
33565
+ }, [amount, networkFeesWei, token, chainFeeParams, gasToken]);
32747
33566
  const gasBalanceNeeded = useMemo(() => {
32748
- if (!amount || !token?.decimals || !gasToken?.decimals)
33567
+ if (!amount || token?.decimals == null || gasToken?.decimals == null)
33568
+ return undefined;
33569
+ const totalGasBalanceNeeded = calculateTotalGasBalanceNeeded({
33570
+ fromAmount: parseToBigInt(amount, token.decimals).toString(),
33571
+ networkFeesWei,
33572
+ chainFeeParams,
33573
+ });
33574
+ if (totalGasBalanceNeeded == null)
32749
33575
  return undefined;
32750
- // gas fees + fromAmount (if fromToken is gas token)
32751
- const totalGasBalanceNeeded = estimatedGas +
32752
- parseToBigInt(chainFeeParams?.fromTokenPaysGasFees ? (amount ?? "0") : "0", token.decimals);
32753
33576
  return formatBNToReadable(totalGasBalanceNeeded, gasToken.decimals);
32754
33577
  }, [
32755
33578
  amount,
32756
- chainFeeParams?.fromTokenPaysGasFees,
32757
- estimatedGas,
33579
+ chainFeeParams,
33580
+ networkFeesWei,
32758
33581
  gasToken?.decimals,
32759
33582
  token?.decimals,
32760
33583
  ]);
@@ -32765,20 +33588,22 @@ function useEstimateSendTransaction({ chain, token, amount, balance, from, }) {
32765
33588
  parseToBigInt(amount, token.decimals));
32766
33589
  }, [amount, balance, token?.decimals]);
32767
33590
  const minAmountValueWarnMsg = useMemo(() => {
32768
- if (!token?.address || !estimatedGas || !chainFeeParams)
33591
+ if (!token?.address || !gasToken || !chainFeeParams)
32769
33592
  return undefined;
32770
33593
  return calculateMinAmountValueWarnMsg({
32771
33594
  chainFeeParams,
32772
- networkFeesWei: estimatedGas,
33595
+ networkFeesWei,
32773
33596
  fromTokenDecimals: token.decimals,
32774
33597
  });
32775
- }, [estimatedGas, token, chainFeeParams]);
33598
+ }, [networkFeesWei, token, chainFeeParams, gasToken]);
32776
33599
  return {
32777
33600
  estimatedGas,
32778
33601
  gasBalanceNeeded,
32779
33602
  isBalanceEnough,
32780
33603
  tokenPaysGasFees: chainFeeParams?.fromTokenPaysGasFees ?? false,
32781
- isLoading,
33604
+ isLoading: isLoading || isFetching,
33605
+ isError,
33606
+ refetchGasEstimate: refetch,
32782
33607
  isGasBalanceEnough,
32783
33608
  minAmountValueWarnMsg,
32784
33609
  };
@@ -33201,9 +34026,8 @@ function useSendTransaction({ to, amount, token, chain, }) {
33201
34026
  chain,
33202
34027
  });
33203
34028
  break;
33204
- case ChainType.CANTON:
33205
- case ChainType.DANAL: {
33206
- throw new Error(`Send not implemented for chain type ${chain.chainType}`);
34029
+ case ChainType.CANTON: {
34030
+ throw new Error("Not implemented");
33207
34031
  }
33208
34032
  }
33209
34033
  return {
@@ -33409,8 +34233,7 @@ async function getSendTransactionStatus({ chain, txHash, }) {
33409
34233
  chain,
33410
34234
  });
33411
34235
  case ChainType.CANTON:
33412
- case ChainType.DANAL:
33413
- throw new Error(`Send not implemented for chain type ${chain.chainType}`);
34236
+ throw new Error("Not implemented");
33414
34237
  }
33415
34238
  }
33416
34239
 
@@ -33681,6 +34504,19 @@ const useApproval = ({ squidRoute, }) => {
33681
34504
  const { getChainType } = useSquidChains();
33682
34505
  const { switchChainAsync } = useSwitchChain();
33683
34506
  const { connectedAddress: { address: sourceUserAddress }, } = useMultiChainWallet(fromChain);
34507
+ const arcNativeBalanceQuery = useBalance({
34508
+ address: sourceUserAddress,
34509
+ chainId: Number(fromChain?.chainId),
34510
+ query: { enabled: false },
34511
+ });
34512
+ const arcTokenBalanceQuery = useReadContract({
34513
+ address: fromToken?.address,
34514
+ abi: erc20Abi,
34515
+ functionName: "balanceOf",
34516
+ args: [sourceUserAddress],
34517
+ chainId: Number(fromChain?.chainId),
34518
+ query: { enabled: false },
34519
+ });
33684
34520
  const isSagaEvmSameChainSwap = isSameChain &&
33685
34521
  fromChain?.chainId.toString() === CHAIN_IDS.SAGA_EVM.toString();
33686
34522
  // Swaps on SagaEVM are regular EVM transactions, following the standard ERC20 approve/allowance mechanism.
@@ -33841,13 +34677,20 @@ const useApproval = ({ squidRoute, }) => {
33841
34677
  return false;
33842
34678
  }
33843
34679
  }, {
33844
- onSuccess: async () => {
34680
+ onSuccess: async (approved) => {
34681
+ if (approved && isArcChain(fromChain?.chainId)) {
34682
+ await Promise.all([
34683
+ arcNativeBalanceQuery.refetch({ throwOnError: true }),
34684
+ arcTokenBalanceQuery.refetch({ throwOnError: true }),
34685
+ ]);
34686
+ queryClient.invalidateQueries(getPrefixKey(QueryKeys.AllTokensBalance));
34687
+ }
33845
34688
  await allowanceQuery?.refetch();
33846
34689
  queryClient.invalidateQueries(getPrefixKey(QueryKeys.RouteApproved));
33847
34690
  // After an approval, we refetch the transaction query with all required parameters
33848
34691
  // This is to ensure we're using the latest expiry timestamp
33849
34692
  if (squidRoute) {
33850
- queryClient.refetchQueries({
34693
+ await queryClient.refetchQueries({
33851
34694
  queryKey: keys().transaction(squidRoute.params.fromChain, squidRoute.params.toChain, squidRoute.params.toToken, squidRoute.params.fromToken, fromPrice, squidRoute.params.slippage, squidRoute.params.fromAddress, squidRoute.params.bypassGuardrails, squidRoute.params.toAddress, squidRoute.params.fallbackAddresses?.[0]?.address, squidRoute.params.quoteOnly, getChainType(squidRoute.params.fromChain), squidRoute.params.preHook, squidRoute.params.postHook,
33852
34695
  // TODO: update types
33853
34696
  squidRoute.params?.overrideGasRefundAddress),
@@ -37031,342 +37874,6 @@ coin.DecProto = {
37031
37874
 
37032
37875
  } (tx));
37033
37876
 
37034
- const vParty = (party) => ({ party });
37035
- const vText = (text) => ({ text });
37036
- const vNumeric = (numeric) => ({ numeric });
37037
- const vContractId = (contractId) => ({
37038
- contractId,
37039
- });
37040
- const vList = (elements) => ({
37041
- list: { elements },
37042
- });
37043
- const vRecord = (fields) => ({
37044
- record: { fields: fields.map(([label, value]) => ({ label, value })) },
37045
- });
37046
- const vTextMap = (entries) => ({ textMap: { entries } });
37047
- const vTimestamp = (isoString) => ({
37048
- timestamp: String(Math.floor(new Date(isoString).getTime() * 1000)),
37049
- });
37050
- function isRecord(value) {
37051
- return typeof value === "object" && value !== null && !Array.isArray(value);
37052
- }
37053
- function normalizeChoiceContextValue(value) {
37054
- if (typeof value === "string")
37055
- return value;
37056
- if (!isRecord(value) || typeof value.tag !== "string")
37057
- return null;
37058
- switch (value.tag) {
37059
- case "AV_Text":
37060
- case "AV_ContractId":
37061
- return typeof value.value === "string"
37062
- ? { tag: value.tag, value: value.value }
37063
- : null;
37064
- case "AV_Bool":
37065
- return typeof value.value === "boolean"
37066
- ? { tag: value.tag, value: value.value }
37067
- : null;
37068
- case "AV_List":
37069
- if (!Array.isArray(value.value))
37070
- return null;
37071
- return {
37072
- tag: value.tag,
37073
- value: value.value.flatMap((entry) => {
37074
- const normalized = normalizeChoiceContextValue(entry);
37075
- return normalized ? [normalized] : [];
37076
- }),
37077
- };
37078
- default: {
37079
- const inner = value.value;
37080
- if (typeof inner === "string" ||
37081
- typeof inner === "number" ||
37082
- typeof inner === "boolean" ||
37083
- inner === null) {
37084
- return { tag: value.tag, value: inner };
37085
- }
37086
- if (Array.isArray(inner)) {
37087
- return {
37088
- tag: value.tag,
37089
- value: inner.flatMap((entry) => {
37090
- const normalized = normalizeChoiceContextValue(entry);
37091
- return normalized ? [normalized] : [];
37092
- }),
37093
- };
37094
- }
37095
- if (!isRecord(inner))
37096
- return null;
37097
- const normalizedObject = {};
37098
- for (const [key, entry] of Object.entries(inner)) {
37099
- if (typeof entry !== "string" &&
37100
- typeof entry !== "number" &&
37101
- typeof entry !== "boolean" &&
37102
- entry !== null) {
37103
- return null;
37104
- }
37105
- normalizedObject[key] = entry;
37106
- }
37107
- return { tag: value.tag, value: normalizedObject };
37108
- }
37109
- }
37110
- }
37111
- function stringifyChoiceContextValue(value) {
37112
- return typeof value === "string" ? value : String(value);
37113
- }
37114
- function choiceContextValueToAnyValue(value) {
37115
- if (typeof value === "string") {
37116
- return {
37117
- variant: { constructor: "AV_Text", value: vText(value) },
37118
- };
37119
- }
37120
- switch (value.tag) {
37121
- case "AV_ContractId":
37122
- if (typeof value.value !== "string") {
37123
- throw new TypeError("AV_ContractId values must be strings");
37124
- }
37125
- return {
37126
- variant: { constructor: value.tag, value: vContractId(value.value) },
37127
- };
37128
- case "AV_Bool":
37129
- if (typeof value.value !== "boolean") {
37130
- throw new TypeError("AV_Bool values must be booleans");
37131
- }
37132
- return {
37133
- variant: { constructor: value.tag, value: { bool: value.value } },
37134
- };
37135
- case "AV_List":
37136
- if (!Array.isArray(value.value)) {
37137
- throw new TypeError("AV_List values must be arrays");
37138
- }
37139
- return {
37140
- variant: {
37141
- constructor: value.tag,
37142
- value: vList(value.value.map(choiceContextValueToAnyValue)),
37143
- },
37144
- };
37145
- default:
37146
- return {
37147
- variant: {
37148
- constructor: value.tag,
37149
- value: vText(stringifyChoiceContextValue(value.value)),
37150
- },
37151
- };
37152
- }
37153
- }
37154
-
37155
- /** Metadata key used by Splice token-standard transfers to carry our Squid orderhash memo. */
37156
- const CANTON_MEMO_KEY = "splice.lfdecentralizedtrust.org/reason";
37157
- /** Interface id for the transfer factory contract returned by the token registry. */
37158
- const TRANSFER_FACTORY_INTERFACE_ID = "#splice-api-token-transfer-instruction-v1:Splice.Api.Token.TransferInstructionV1:TransferFactory";
37159
- /** Choice exercised on the transfer factory to create the token-standard transfer. */
37160
- const TRANSFER_FACTORY_CHOICE = "TransferFactory_Transfer";
37161
- /** CIP-056 (non-Amulet) tokens expose a registrar parameterized by admin party. */
37162
- const CIP056_REGISTRAR_BASE = "https://api.utilities.digitalasset.com/api/token-standard/v0/registrars";
37163
- const TRANSFER_REQUESTED_AT_SKEW_MS = 60_000;
37164
- const TRANSFER_EXECUTE_WINDOW_MS = 24 * 60 * 60 * 1000;
37165
- function resolveCantonRegistryUrl(instrument) {
37166
- if (instrument.id === CANTON_AMULET_INSTRUMENT_ID) {
37167
- return CANTON_AMULET_REGISTRY_URL;
37168
- }
37169
- return `${CIP056_REGISTRAR_BASE}/${encodeURIComponent(instrument.admin)}`;
37170
- }
37171
- /**
37172
- * Build the plain JSON arguments expected by the registry transfer-factory
37173
- * endpoint before it adds choice context and disclosed contracts.
37174
- */
37175
- function buildTransferChoiceArgs({ sender, receiver, amount, instrument, inputHoldingCids, memo, nowMs, }) {
37176
- return {
37177
- expectedAdmin: instrument.admin,
37178
- transfer: {
37179
- sender,
37180
- receiver,
37181
- amount,
37182
- instrumentId: { admin: instrument.admin, id: instrument.id },
37183
- requestedAt: new Date(nowMs - TRANSFER_REQUESTED_AT_SKEW_MS).toISOString(),
37184
- executeBefore: new Date(nowMs + TRANSFER_EXECUTE_WINDOW_MS).toISOString(),
37185
- inputHoldingCids,
37186
- meta: { values: { [CANTON_MEMO_KEY]: memo } },
37187
- },
37188
- extraArgs: { context: { values: {} }, meta: { values: {} } },
37189
- };
37190
- }
37191
- /**
37192
- * Canton's Holding contracts follow Bitcoin-style UTXOs model.
37193
- *
37194
- * Pick Holding contract ids covering `amount` for the instrument: prefer a
37195
- * single exact-amount holding, else accumulate largest-first.
37196
- */
37197
- function selectInputHoldingCids(holdings, instrument, amount) {
37198
- const spendableHoldings = holdings.filter((h) => !h.locked &&
37199
- h.instrument.admin === instrument.admin &&
37200
- h.instrument.id === instrument.id);
37201
- const target = new BigNumber(amount);
37202
- const exact = spendableHoldings.find((h) => new BigNumber(h.amount).eq(target));
37203
- if (exact)
37204
- return [exact.contractId];
37205
- const sorted = [...spendableHoldings].sort((a, b) => new BigNumber(b.amount).comparedTo(new BigNumber(a.amount)));
37206
- const selected = [];
37207
- let sum = new BigNumber(0);
37208
- for (const holding of sorted) {
37209
- selected.push(holding.contractId);
37210
- sum = sum.plus(holding.amount);
37211
- if (sum.gte(target))
37212
- break;
37213
- }
37214
- if (sum.lt(target)) {
37215
- throw new Error("Insufficient Canton holdings to cover transfer amount");
37216
- }
37217
- return selected;
37218
- }
37219
- async function fetchInputHoldingCids(connector, party, instrument, amount) {
37220
- const ledgerEnd = await connector.ledgerApi({
37221
- requestMethod: "get",
37222
- resource: "/v2/state/ledger-end",
37223
- });
37224
- const activeContracts = await connector.ledgerApi({
37225
- requestMethod: "post",
37226
- resource: "/v2/state/active-contracts",
37227
- body: buildHoldingsAcsRequestBody(party, String(ledgerEnd.offset)),
37228
- });
37229
- return selectInputHoldingCids(parseCantonHoldings(activeContracts), instrument, amount);
37230
- }
37231
- /**
37232
- * Ask the token registry for the transfer factory contract and extra context
37233
- * required to exercise its transfer choice.
37234
- */
37235
- async function fetchTransferFactory(registryUrl, choiceArgs) {
37236
- const response = await fetch(`${registryUrl}/registry/transfer-instruction/v1/transfer-factory`, {
37237
- method: "POST",
37238
- headers: { "Content-Type": "application/json" },
37239
- body: JSON.stringify({
37240
- choiceArguments: choiceArgs,
37241
- excludeDebugFields: true,
37242
- }),
37243
- });
37244
- if (!response.ok) {
37245
- throw new Error(`Canton transfer-factory request failed (${response.status})`);
37246
- }
37247
- return response.json();
37248
- }
37249
- /**
37250
- * Convert transfer choice args into strict Daml Value JSON for the wallet's
37251
- * prepareExecute ExerciseCommand.
37252
- */
37253
- function buildPrepareChoiceArgument(choiceArgs) {
37254
- const contextValues = Object.entries(choiceArgs.extraArgs.context?.values ?? {})
37255
- .map(([key, value]) => {
37256
- const normalized = normalizeChoiceContextValue(value);
37257
- return normalized
37258
- ? { key, value: choiceContextValueToAnyValue(normalized) }
37259
- : undefined;
37260
- })
37261
- .filter((entry) => Boolean(entry));
37262
- return vRecord([
37263
- ["expectedAdmin", vParty(choiceArgs.expectedAdmin)],
37264
- [
37265
- "transfer",
37266
- vRecord([
37267
- ["sender", vParty(choiceArgs.transfer.sender)],
37268
- ["receiver", vParty(choiceArgs.transfer.receiver)],
37269
- ["amount", vNumeric(choiceArgs.transfer.amount)],
37270
- [
37271
- "instrumentId",
37272
- vRecord([
37273
- ["admin", vParty(choiceArgs.transfer.instrumentId.admin)],
37274
- ["id", vText(choiceArgs.transfer.instrumentId.id)],
37275
- ]),
37276
- ],
37277
- ["requestedAt", vTimestamp(choiceArgs.transfer.requestedAt)],
37278
- ["executeBefore", vTimestamp(choiceArgs.transfer.executeBefore)],
37279
- [
37280
- "inputHoldingCids",
37281
- vList(choiceArgs.transfer.inputHoldingCids.map(vContractId)),
37282
- ],
37283
- [
37284
- "meta",
37285
- vRecord([
37286
- [
37287
- "values",
37288
- vTextMap(Object.entries(choiceArgs.transfer.meta.values).map(([key, value]) => ({ key, value: vText(value) }))),
37289
- ],
37290
- ]),
37291
- ],
37292
- ]),
37293
- ],
37294
- [
37295
- "extraArgs",
37296
- vRecord([
37297
- ["context", vRecord([["values", vTextMap(contextValues)]])],
37298
- ["meta", vRecord([["values", vTextMap([])]])],
37299
- ]),
37300
- ],
37301
- ]);
37302
- }
37303
- /**
37304
- * Convert a registry disclosed contract into the wallet submission shape,
37305
- * dropping debug fields and entries without a usable createdEventBlob.
37306
- */
37307
- function toDisclosedContract(raw) {
37308
- if (typeof raw.createdEventBlob !== "string")
37309
- return null;
37310
- return {
37311
- createdEventBlob: raw.createdEventBlob,
37312
- contractId: typeof raw.contractId === "string" ? raw.contractId : undefined,
37313
- synchronizerId: typeof raw.synchronizerId === "string" ? raw.synchronizerId : undefined,
37314
- };
37315
- }
37316
- /**
37317
- * Build a Splice token-standard transfer of `amount` of `token` from `sender`
37318
- * to `receiver`, carrying `memo`, ready to hand to a wallet's prepareExecute.
37319
- * Returns the full prepareExecute params (commandId + commands + actAs +
37320
- * disclosedContracts).
37321
- */
37322
- async function buildCantonTransfer(connector, { sender, receiver, amount, token, memo, nowMs, }) {
37323
- if (!token.originalAddress) {
37324
- throw new Error("Canton token originalAddress is required");
37325
- }
37326
- const instrument = parseCantonInstrument(token.originalAddress);
37327
- if (!instrument) {
37328
- throw new Error(`Invalid Canton token address: ${token.originalAddress}`);
37329
- }
37330
- const registryUrl = resolveCantonRegistryUrl(instrument);
37331
- const inputHoldingCids = await fetchInputHoldingCids(connector, sender, instrument, amount);
37332
- const choiceArgs = buildTransferChoiceArgs({
37333
- sender,
37334
- receiver,
37335
- amount,
37336
- instrument,
37337
- inputHoldingCids,
37338
- memo,
37339
- nowMs,
37340
- });
37341
- const factory = await fetchTransferFactory(registryUrl, choiceArgs);
37342
- const choiceContextData = factory.choiceContext.choiceContextData;
37343
- if (!choiceContextData) {
37344
- throw new Error("Transfer factory choice context is missing");
37345
- }
37346
- choiceArgs.extraArgs.context = choiceContextData;
37347
- const disclosedContracts = (factory.choiceContext?.disclosedContracts ?? []).flatMap((raw) => {
37348
- const disclosedContract = toDisclosedContract(raw);
37349
- return disclosedContract ? [disclosedContract] : [];
37350
- });
37351
- // Command ID: client-supplied identifier used to deduplicate submissions
37352
- const commandId = `canton-${memo}`;
37353
- return {
37354
- commandId,
37355
- commands: [
37356
- {
37357
- ExerciseCommand: {
37358
- templateId: TRANSFER_FACTORY_INTERFACE_ID,
37359
- contractId: factory.factoryId,
37360
- choice: TRANSFER_FACTORY_CHOICE,
37361
- choiceArgument: buildPrepareChoiceArgument(choiceArgs),
37362
- },
37363
- },
37364
- ],
37365
- actAs: [sender],
37366
- disclosedContracts,
37367
- };
37368
- }
37369
-
37370
37877
  const useExecuteTransaction = (squidRoute) => {
37371
37878
  const { fromChain, toChain, fromToken, toToken, isSameChain } = useSwap();
37372
37879
  // A route completes on source tx only if it's same-chain AND
@@ -37981,7 +38488,7 @@ const useExecuteTransaction = (squidRoute) => {
37981
38488
  }
37982
38489
  const amount = formatBNToReadable(fromAmount, token.decimals);
37983
38490
  dispatchSignatureRequestEvent(route);
37984
- const transferParams = await buildCantonTransfer(cantonSigner, {
38491
+ const result = await cantonSigner.transfer({
37985
38492
  sender: sourceUserAddress,
37986
38493
  receiver,
37987
38494
  amount,
@@ -37989,15 +38496,14 @@ const useExecuteTransaction = (squidRoute) => {
37989
38496
  memo: orderHash,
37990
38497
  nowMs: Date.now(),
37991
38498
  });
37992
- const result = await cantonSigner.prepareExecuteAndWait(transferParams);
37993
- const txHash = result.tx?.payload?.updateId ?? "";
38499
+ const txHash = result.updateId;
37994
38500
  if (txHash) {
37995
38501
  resetQueriesAfterTxSigned();
37996
38502
  }
37997
38503
  WidgetEvents.getInstance().dispatchSwapExecuteCall(route, txHash);
37998
38504
  const txParams = setTransactionState({
37999
38505
  route,
38000
- txHash: txHash,
38506
+ txHash,
38001
38507
  userAddress: sourceUserAddress,
38002
38508
  status: TransactionStatus.INITIAL_LOADING,
38003
38509
  sourceStatus: TransactionStatus.ONGOING,
@@ -38280,7 +38786,7 @@ refetchIntervalInBackground = false, refetchInterval = 30000, quoteOnly = true,
38280
38786
  //
38281
38787
  // If deposit address is not selected, we use the connected address as the source address instead
38282
38788
  const sourceUserAddress = isDepositAddressActive
38283
- ? depositRefundAddress ?? sourceConnectedAddress
38789
+ ? (depositRefundAddress ?? sourceConnectedAddress)
38284
38790
  : sourceConnectedAddress;
38285
38791
  const squidRouteQueryKeys = useMemo(() => keys().transaction(fromChain?.chainId, toChain?.chainId, toToken?.address, fromToken?.address, fromPrice, config.slippage, sourceUserAddress, config.degenMode, destinationAddress, fallbackAddress, quoteOnly, fromChain?.chainType, config.preHook, config.postHook, config.overrideGasRefundAddress), [
38286
38792
  fromChain?.chainId,
@@ -38572,6 +39078,10 @@ const useAutoConnect = () => {
38572
39078
  const { chains } = useSquidChains();
38573
39079
  const { isInitialized } = useConfigStore();
38574
39080
  const hasAttemptedReconnect = useRef(false);
39081
+ const hasAttemptedCantonReconnect = useRef(false);
39082
+ const { autoConnectCanton, wallets: cantonWallets } = useCantonContext();
39083
+ const recentCantonWalletId = useWalletStore((state) => state.recentConnectorIds[ChainType.CANTON]);
39084
+ const hasRecentCantonWallet = cantonWallets.some((wallet) => wallet.connectorId === recentCantonWalletId);
38575
39085
  const { autoConnectEvm } = useEvmContext();
38576
39086
  const { autoConnectSolana } = useSolanaContext();
38577
39087
  const { autoConnectSui } = useSuiContext();
@@ -38639,6 +39149,15 @@ const useAutoConnect = () => {
38639
39149
  useEffect(() => {
38640
39150
  autoConnect();
38641
39151
  }, [autoConnect]);
39152
+ useEffect(() => {
39153
+ if (!isInitialized ||
39154
+ chains.length === 0 ||
39155
+ !hasRecentCantonWallet ||
39156
+ hasAttemptedCantonReconnect.current)
39157
+ return;
39158
+ hasAttemptedCantonReconnect.current = true;
39159
+ autoConnectCanton().catch(() => undefined);
39160
+ }, [autoConnectCanton, hasRecentCantonWallet, isInitialized, chains.length]);
38642
39161
  return { autoConnect };
38643
39162
  };
38644
39163
 
@@ -38947,5 +39466,5 @@ const SquidProvider = ({ children, config, placeholder, }) => {
38947
39466
  React.createElement(CosmosProvider, null, children))))))))))) : (placeholder);
38948
39467
  };
38949
39468
 
38950
- export { useWalletStore as $, AxelarStatusResponseType as A, useHederaAccountActivation as B, CHAIN_IDS as C, DEFAULT_LOCALE as D, useHederaTokenAssociations as E, useKeyboardNavigation as F, useSquidQueryClient as G, HistoryTxType as H, useSquid as I, useStellarAccountActivation as J, useStellarTrustLine as K, useAddressBookStore as L, useAssetsColorsStore as M, Nr as N, useFavoriteTokensStore as O, useHistoryStore as P, QueryKeys as Q, useSendTransactionStore as R, SquidStatusErrorType as S, TransactionErrorType as T, useConfigStore as U, useSquidStore as V, Wo as W, XamanXrplNetwork as X, useSwapRoutePersistStore as Y, useTransactionStore as Z, ConnectingWalletStatus as _, WindowWalletFlag as a, useAvailableQuotes as a$, useDepositAddress as a0, useSwap as a1, buildUrlSearchParamsFromSwapEvent as a2, parseInitialAssetsFromUrl as a3, useUrlSwapParams as a4, useAllConnectedWalletBalances as a5, useAllTokensWithBalanceForChainType as a6, useCosmosBalance as a7, useEvmBalance as a8, useMultiChainBalance as a9, useRouteWarnings as aA, useSendTransactionStatus as aB, useSwapTransactionStatus as aC, useAvatar as aD, useHistory as aE, useDebouncedValue as aF, useAddToken as aG, useAutoConnect as aH, useEnsDataForAddress as aI, useEnsSearch as aJ, useGnosisContext as aK, useIsSameAddressAndGnosisContext as aL, useIntegratorContext as aM, useMultiChainWallet as aN, useSigner as aO, useWallet as aP, useWallets as aQ, useXrplTrustLine as aR, TX_STATUS_CONSTANTS as aS, FINAL_TRANSACTION_STATUSES as aT, useGetFiatQuote as aU, useGetOnRampConfig as aV, useExecuteFiatQuote as aW, useFiatOnRampTxStatus as aX, useFiatTransactions as aY, useCurrencyDetails as aZ, useCountryDetails as a_, useMultipleTokenPrices as aa, useBitcoinNativeBalance as ab, useCosmosNativeBalance as ac, useEvmNativeBalance as ad, useNativeBalance as ae, useSolanaNativeBalance as af, useStellarNativeBalance as ag, useSuiNativeBalance as ah, useXrplNativeBalance as ai, useNativeTokenForChain as aj, useSingleTokenPrice as ak, useSourceChainGasToken as al, useSquidTokens as am, useHistoricalData as an, useTokensData as ao, useEstimateSendTransaction as ap, useSendTransaction as aq, useSendTransactionGas as ar, useAllTransactionsStatus as as, useApproval as at, useDepositTransactionStatus as au, useEstimate as av, useEstimatePriceImpact as aw, useExecuteTransaction as ax, useGetRoute as ay, useGetRouteWrapper as az, DEFAULT_ROUTE_REFETCH_INTERVAL as b, createQuoteRequestParamsHash as b$, useRecommendedQuote as b0, useGetOnrampPaymentTypes as b1, useSuggestedFiatAmounts as b2, SquidProvider as b3, EnsService as b4, getXummClient as b5, isXamanXAppContext as b6, getQueryHeaders as b7, getStatusCode as b8, is404Error as b9, randomIntFromInterval as bA, getTokensForChain as bB, getFirstAvailableChainId as bC, fetchHighestBalanceToken as bD, getInitialOrDefaultTokenAddressForChain as bE, getInitialTokenAddressForChain as bF, filterTokensForDestination as bG, getInitialChainIdFromConfig as bH, getCosmosKey as bI, getKeysSettled as bJ, getAllKeysForSupportedCosmosChains as bK, isCosmosAddressValid as bL, getCosmosSigningClient as bM, getCosmosChainInfosObject as bN, connectCosmosWallet as bO, isFallbackAddressNeeded as bP, suggestChainOrThrow as bQ, isDanalAddressValid as bR, isDanalTxHashValid as bS, parseDanalTransferBody as bT, normalizeError as bU, transactionErrorCode as bV, isUserRejectionError as bW, getTransactionError as bX, handleTransactionErrorEvents as bY, isSwapRouteError as bZ, isStatusError as b_, assetsBaseUrl as ba, shareSubgraphId as bb, sortTokensBySharedSubgraphIds as bc, getSupportedChainIdsForDirection as bd, filterChains as be, filterTokens as bf, getTokenImage as bg, getNewSwapParamsFromInput as bh, sortAllTokens as bi, findToken as bj, findNativeToken as bk, normalizeIbcAddress as bl, groupTokensBySymbol as bm, groupTokensByChainId as bn, filterViewableTokens as bo, getSecretNetworkBalances as bp, getTokenAssetsKey as bq, fetchAssetsColors as br, isSupportedChainType as bs, initializeSquidData as bt, isEmptyObject as bu, normalizeTokenSymbol as bv, areTokenSymbolsCompatible as bw, isEvmosChain as bx, resolveChainIdFromAsset as by, getConfigWithDefaults as bz, chainTypeToNativeTokenAddressMap as c, getHalfSuccessState as c$, WidgetEvents as c0, EvmNetworkNotSupportedErrorCode as c1, addEthereumChain as c2, parseEvmAddress as c3, formatEvmWallet as c4, filterWagmiConnector as c5, waitForReceiptWithRetry as c6, getUserCountry as c7, getCountryData as c8, getCurrencyData as c9, stellarAddressToScVal as cA, getStellarTrustLineAsset as cB, isStellarToken as cC, isStellarIssuedToken as cD, getStellarHorizonApiUrl as cE, isValidIssuedAsset as cF, isValidHorizonAsset as cG, formatTransactionHistoryDate as cH, getAxelarExplorerTxUrl as cI, getSourceExplorerTxUrl as cJ, getMainExplorerUrl as cK, formatDistance as cL, formatSeconds as cM, formatSwapTxStatusResponseForStorage as cN, simplifyRouteAction as cO, fetchSwapTransactionStatus as cP, compareTransactionIds as cQ, isCoralBridgeAction as cR, isActionCompletedOnSourceTx as cS, sleep as cT, isChainflipDepositRoute as cU, isChainflipBridgeTransaction as cV, isOnChainTxData as cW, isDepositAddressDirectTransferRoute as cX, isDanalDepositRoute as cY, getHistoryTransactionId as cZ, getStepStatuses as c_, adaptiveRound as ca, getSuggestedAmountsForCurrency as cb, HederaExtensionHelper as cc, convertHederaAccountIdToEvmAddress as cd, convertEvmAddressToHederaAccountId as ce, scaleHbarToWei as cf, scaleWeiToHbar as cg, parseToBigInt as ch, roundNumericValue as ci, formatUnitsRounded as cj, formatTokenAmount as ck, formatUsdAmount as cl, trimExtraDecimals as cm, getNumericValue as cn, cleanAmount as co, convertTokenAmountToUSD as cp, convertUSDToTokenAmount as cq, calculateTotal24hChange as cr, getRouteExpiry as cs, searchTokens as ct, filterSolanaWallets as cu, isSolanaAddressValid as cv, executeSolanaSwap as cw, executeSolanaTransfer as cx, isStellarAddressValid as cy, getStellarNetwork as cz, definedInWindow as d, getStepsInfos as d0, getSwapTxStatusRefetchInterval as d1, getSendTxStatusRefetchInterval as d2, chainflipMultihopBridgeType as d3, getBridgeType as d4, getTransactionStatus as d5, getTransactionEndStatus as d6, isHistoryTransactionPending as d7, isHistoryTransactionFailed as d8, isHistoryTransactionWarning as d9, parseXrplTokenAddress as dA, isHistoryTransactionEnded as da, formatHash as db, isWalletAddressValid as dc, redirectToExtensionsStore as dd, populateWallets as de, buildFallbackWallets as df, getDefaultChain as dg, sortWallets as dh, areSameAddress as di, sortAddressBook as dj, calculateTotalUsdBalanceUSD as dk, addTokenToWallet as dl, isEvmChainNotSupportedError as dm, getWalletSupportedChainTypes as dn, getConnectorForChainType as dp, walletSupportsChainType as dq, connectWallet as dr, cancelConnectWallet as ds, isProblematicConnector as dt, mergeWallets as du, isXionSmartContractAddress as dv, isXrplAddressValid as dw, buildXrplTrustSetTx as dx, getXrplNetwork as dy, parseXrplPaymentTx as dz, er as e, formatBNToReadable as f, chainTypeToZeroAddressMap as g, destinationAddressResetValue as h, fallbackAddressResetValue as i, nativeCantonTokenAddress as j, nativeCosmosTokenAddress as k, nativeEvmTokenAddress as l, nativeSolanaTokenAddress as m, nativeBitcoinTokenAddress as n, nativeStellarTokenAddress as o, nativeSuiTokenAddress as p, nativeXrplTokenAddress as q, CosmosProvider as r, SendTransactionStatus as s, TransactionStatus as t, useCosmosContext as u, useTrackSearchEmpty as v, walletIconBaseUrl as w, useSquidChains as x, useClient as y, useCosmosForChain as z };
38951
- //# sourceMappingURL=index-ByakOYXP.js.map
39469
+ export { useWalletStore as $, AxelarStatusResponseType as A, useHederaAccountActivation as B, CHAIN_IDS as C, DEFAULT_LOCALE as D, useHederaTokenAssociations as E, useKeyboardNavigation as F, useSquidQueryClient as G, HistoryTxType as H, useSquid as I, useStellarAccountActivation as J, useStellarTrustLine as K, useAddressBookStore as L, useAssetsColorsStore as M, Nr as N, useFavoriteTokensStore as O, useHistoryStore as P, QueryKeys as Q, useSendTransactionStore as R, SquidStatusErrorType as S, TransactionErrorType as T, useConfigStore as U, useSquidStore as V, Wo as W, XamanXrplNetwork as X, useSwapRoutePersistStore as Y, useTransactionStore as Z, ConnectingWalletStatus as _, WindowWalletFlag as a, useAvailableQuotes as a$, useDepositAddress as a0, useSwap as a1, buildUrlSearchParamsFromSwapEvent as a2, parseInitialAssetsFromUrl as a3, useUrlSwapParams as a4, useAllConnectedWalletBalances as a5, useAllTokensWithBalanceForChainType as a6, useCosmosBalance as a7, useEvmBalance as a8, useMultiChainBalance as a9, useRouteWarnings as aA, useSendTransactionStatus as aB, useSwapTransactionStatus as aC, useAvatar as aD, useHistory as aE, useDebouncedValue as aF, useAddToken as aG, useAutoConnect as aH, useEnsDataForAddress as aI, useEnsSearch as aJ, useGnosisContext as aK, useIsSameAddressAndGnosisContext as aL, useIntegratorContext as aM, useMultiChainWallet as aN, useSigner as aO, useWallet as aP, useWallets as aQ, useXrplTrustLine as aR, TX_STATUS_CONSTANTS as aS, FINAL_TRANSACTION_STATUSES as aT, useGetFiatQuote as aU, useGetOnRampConfig as aV, useExecuteFiatQuote as aW, useFiatOnRampTxStatus as aX, useFiatTransactions as aY, useCurrencyDetails as aZ, useCountryDetails as a_, useMultipleTokenPrices as aa, useBitcoinNativeBalance as ab, useCosmosNativeBalance as ac, useEvmNativeBalance as ad, useNativeBalance as ae, useSolanaNativeBalance as af, useStellarNativeBalance as ag, useSuiNativeBalance as ah, useXrplNativeBalance as ai, useNativeTokenForChain as aj, useSingleTokenPrice as ak, useSourceChainGasToken as al, useSquidTokens as am, useHistoricalData as an, useTokensData as ao, useEstimateSendTransaction as ap, useSendTransaction as aq, useSendTransactionGas as ar, useAllTransactionsStatus as as, useApproval as at, useDepositTransactionStatus as au, useEstimate as av, useEstimatePriceImpact as aw, useExecuteTransaction as ax, useGetRoute as ay, useGetRouteWrapper as az, DEFAULT_ROUTE_REFETCH_INTERVAL as b, WidgetEvents as b$, useRecommendedQuote as b0, useGetOnrampPaymentTypes as b1, useSuggestedFiatAmounts as b2, SquidProvider as b3, EnsService as b4, getXummClient as b5, isXamanXAppContext as b6, getQueryHeaders as b7, getStatusCode as b8, is404Error as b9, getConfigWithDefaults as bA, randomIntFromInterval as bB, getTokensForChain as bC, getFirstAvailableChainId as bD, fetchHighestBalanceToken as bE, getTokenAddressForSelection as bF, getInitialOrDefaultTokenAddressForChain as bG, getInitialTokenAddressForChain as bH, filterTokensForDestination as bI, getInitialChainIdFromConfig as bJ, getCosmosKey as bK, getKeysSettled as bL, getAllKeysForSupportedCosmosChains as bM, isCosmosAddressValid as bN, getCosmosSigningClient as bO, getCosmosChainInfosObject as bP, connectCosmosWallet as bQ, isFallbackAddressNeeded as bR, suggestChainOrThrow as bS, normalizeError as bT, transactionErrorCode as bU, isUserRejectionError as bV, getTransactionError as bW, handleTransactionErrorEvents as bX, isSwapRouteError as bY, isStatusError as bZ, createQuoteRequestParamsHash as b_, assetsBaseUrl as ba, shareSubgraphId as bb, sortTokensBySharedSubgraphIds as bc, getSupportedChainIdsForDirection as bd, filterChains as be, filterTokens as bf, getTokenImage as bg, normalizeSwapParamsForSelection as bh, getNewSwapParamsFromInput as bi, sortAllTokens as bj, findToken as bk, findNativeToken as bl, normalizeIbcAddress as bm, groupTokensBySymbol as bn, groupTokensByChainId as bo, filterViewableTokens as bp, getSecretNetworkBalances as bq, getTokenAssetsKey as br, fetchAssetsColors as bs, isSupportedChainType as bt, initializeSquidData as bu, isEmptyObject as bv, normalizeTokenSymbol as bw, areTokenSymbolsCompatible as bx, isEvmosChain as by, resolveChainIdFromAsset as bz, chainTypeToNativeTokenAddressMap as c, getSwapTxStatusRefetchInterval as c$, EvmNetworkNotSupportedErrorCode as c0, addEthereumChain as c1, parseEvmAddress as c2, formatEvmWallet as c3, filterWagmiConnector as c4, waitForReceiptWithRetry as c5, getUserCountry as c6, getCountryData as c7, getCurrencyData as c8, adaptiveRound as c9, getStellarTrustLineAsset as cA, isStellarToken as cB, isStellarIssuedToken as cC, getStellarHorizonApiUrl as cD, isValidIssuedAsset as cE, isValidHorizonAsset as cF, formatTransactionHistoryDate as cG, getAxelarExplorerTxUrl as cH, getSourceExplorerTxUrl as cI, getMainExplorerUrl as cJ, formatDistance as cK, formatSeconds as cL, formatSwapTxStatusResponseForStorage as cM, simplifyRouteAction as cN, fetchSwapTransactionStatus as cO, compareTransactionIds as cP, isCoralBridgeAction as cQ, isActionCompletedOnSourceTx as cR, sleep as cS, isChainflipDepositRoute as cT, isChainflipBridgeTransaction as cU, isOnChainTxData as cV, isDepositAddressDirectTransferRoute as cW, getHistoryTransactionId as cX, getStepStatuses as cY, getHalfSuccessState as cZ, getStepsInfos as c_, getSuggestedAmountsForCurrency as ca, HederaExtensionHelper as cb, convertHederaAccountIdToEvmAddress as cc, convertEvmAddressToHederaAccountId as cd, scaleHbarToWei as ce, scaleWeiToHbar as cf, parseToBigInt as cg, roundNumericValue as ch, formatUnitsRounded as ci, formatTokenAmount as cj, formatUsdAmount as ck, trimExtraDecimals as cl, getNumericValue as cm, cleanAmount as cn, convertTokenAmountToUSD as co, convertUSDToTokenAmount as cp, calculateTotal24hChange as cq, getRouteExpiry as cr, searchTokens as cs, filterSolanaWallets as ct, isSolanaAddressValid as cu, executeSolanaSwap as cv, executeSolanaTransfer as cw, isStellarAddressValid as cx, getStellarNetwork as cy, stellarAddressToScVal as cz, definedInWindow as d, getSendTxStatusRefetchInterval as d0, chainflipMultihopBridgeType as d1, getBridgeType as d2, getTransactionStatus as d3, getTransactionEndStatus as d4, isHistoryTransactionPending as d5, isHistoryTransactionFailed as d6, isHistoryTransactionWarning as d7, isHistoryTransactionEnded as d8, formatHash as d9, isWalletAddressValid as da, redirectToExtensionsStore as db, populateWallets as dc, buildFallbackWallets as dd, getDefaultChain as de, sortWallets as df, areSameAddress as dg, sortAddressBook as dh, calculateTotalUsdBalanceUSD as di, addTokenToWallet as dj, isEvmChainNotSupportedError as dk, getWalletSupportedChainTypes as dl, getConnectorForChainType as dm, walletSupportsChainType as dn, connectWallet as dp, cancelConnectWallet as dq, isProblematicConnector as dr, mergeWallets as ds, isXionSmartContractAddress as dt, isXrplAddressValid as du, buildXrplTrustSetTx as dv, getXrplNetwork as dw, parseXrplPaymentTx as dx, parseXrplTokenAddress as dy, er as e, formatBNToReadable as f, chainTypeToZeroAddressMap as g, destinationAddressResetValue as h, fallbackAddressResetValue as i, nativeCantonTokenAddress as j, nativeCosmosTokenAddress as k, nativeEvmTokenAddress as l, nativeSolanaTokenAddress as m, nativeBitcoinTokenAddress as n, nativeStellarTokenAddress as o, nativeSuiTokenAddress as p, nativeXrplTokenAddress as q, CosmosProvider as r, SendTransactionStatus as s, TransactionStatus as t, useCosmosContext as u, useTrackSearchEmpty as v, walletIconBaseUrl as w, useSquidChains as x, useClient as y, useCosmosForChain as z };
39470
+ //# sourceMappingURL=index-CLzjMzS_.js.map