@0xsquid/react-hooks 8.9.1-beta.0 → 8.10.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 (73) hide show
  1. package/dist/core/canton/cantonConnector.d.ts +28 -0
  2. package/dist/core/canton/cip103Client.d.ts +20 -0
  3. package/dist/core/client/index.d.ts +1 -0
  4. package/dist/core/connectors/bitcoin/errors/index.d.ts +0 -3
  5. package/dist/core/connectors/bitcoin/wallets/index.d.ts +0 -1
  6. package/dist/core/connectors/bitcoin/wallets/phantom.d.ts +26 -10
  7. package/dist/core/constants.d.ts +3 -0
  8. package/dist/core/fallbackWallets.d.ts +16 -0
  9. package/dist/core/providers/CantonProvider.d.ts +19 -0
  10. package/dist/core/types/canton.d.ts +58 -0
  11. package/dist/core/types/cosmos.d.ts +5 -0
  12. package/dist/core/types/wallet.d.ts +15 -7
  13. package/dist/core/wallets.d.ts +5 -0
  14. package/dist/hooks/canton/useCanton.d.ts +2 -0
  15. package/dist/hooks/canton/useCantonWallets.d.ts +8 -0
  16. package/dist/hooks/chains/useSquidChains.d.ts +1 -0
  17. package/dist/hooks/index.d.ts +1 -0
  18. package/dist/hooks/store/useDepositAddressStore.d.ts +18 -5
  19. package/dist/hooks/swap/useDepositAddress.d.ts +6 -7
  20. package/dist/hooks/tokens/useBalance.d.ts +1 -0
  21. package/dist/hooks/tokens/useNativeBalance.d.ts +1 -0
  22. package/dist/hooks/tokens/useSquidTokens.d.ts +1 -0
  23. package/dist/hooks/transaction/useDepositTransactionStatus.d.ts +20 -0
  24. package/dist/hooks/transaction/useSwapStatusQuery.d.ts +29 -0
  25. package/dist/hooks/wallet/useMultiChainWallet.d.ts +55 -29
  26. package/dist/hooks/wallet/useSigner.d.ts +1 -0
  27. package/dist/hooks/wallet/useWallet.d.ts +59 -29
  28. package/dist/hooks/xrpl/useXrplWallets.d.ts +2 -2
  29. package/dist/{index-Ypw6i6uY.js → index-BlB3yIoX.js} +1398 -294
  30. package/dist/index-BlB3yIoX.js.map +1 -0
  31. package/dist/{index-sCLxPcqi.js → index-Dzir2lUQ.js} +1383 -276
  32. package/dist/index-Dzir2lUQ.js.map +1 -0
  33. package/dist/{index.es-B2QD8f3q.js → index.es-BPXYaraD.js} +5 -4
  34. package/dist/index.es-BPXYaraD.js.map +1 -0
  35. package/dist/{index.es-Bot12hgd.js → index.es-DwtZr7bN.js} +5 -4
  36. package/dist/index.es-DwtZr7bN.js.map +1 -0
  37. package/dist/index.esm.js +4 -3
  38. package/dist/index.esm.js.map +1 -1
  39. package/dist/index.js +10 -6
  40. package/dist/index.js.map +1 -1
  41. package/dist/{secretService-C3jMjsK0.js → secretService-ICina23f.js} +5 -4
  42. package/dist/{secretService-C3jMjsK0.js.map → secretService-ICina23f.js.map} +1 -1
  43. package/dist/{secretService-BAK4sBb7.js → secretService-eiBnD7dI.js} +5 -4
  44. package/dist/{secretService-BAK4sBb7.js.map → secretService-eiBnD7dI.js.map} +1 -1
  45. package/dist/server.d.ts +1 -1
  46. package/dist/server.esm.js +7 -1
  47. package/dist/server.esm.js.map +1 -1
  48. package/dist/server.js +7 -0
  49. package/dist/server.js.map +1 -1
  50. package/dist/services/external/onrampAdapter.d.ts +3 -4
  51. package/dist/services/external/rpcService.d.ts +17 -0
  52. package/dist/services/internal/assetsService.d.ts +10 -1
  53. package/dist/services/internal/cantonDamlValue.d.ts +75 -0
  54. package/dist/services/internal/cantonService.d.ts +64 -0
  55. package/dist/services/internal/cantonTransferService.d.ts +93 -0
  56. package/dist/services/internal/transactionService.d.ts +5 -1
  57. package/dist/services/internal/walletService.d.ts +3 -6
  58. package/dist/{stellarService.client-SrhXgRGB.js → stellarService.client-Bjc92sC_.js} +6 -5
  59. package/dist/{stellarService.client-SrhXgRGB.js.map → stellarService.client-Bjc92sC_.js.map} +1 -1
  60. package/dist/{stellarService.client-DkJ6WAdl.js → stellarService.client-VOmCOPzL.js} +6 -5
  61. package/dist/{stellarService.client-DkJ6WAdl.js.map → stellarService.client-VOmCOPzL.js.map} +1 -1
  62. package/dist/tests/cantonService.test.d.ts +1 -0
  63. package/dist/tests/cantonTransferService.test.d.ts +1 -0
  64. package/dist/tests/cip103Client.test.d.ts +1 -0
  65. package/dist/tests/fallbackWallets.test.d.ts +1 -0
  66. package/dist/tests/wallets.test.d.ts +1 -0
  67. package/package.json +3 -2
  68. package/dist/core/connectors/bitcoin/bitcoinFeatures.d.ts +0 -53
  69. package/dist/core/connectors/bitcoin/wallets/standard.d.ts +0 -30
  70. package/dist/index-Ypw6i6uY.js.map +0 -1
  71. package/dist/index-sCLxPcqi.js.map +0 -1
  72. package/dist/index.es-B2QD8f3q.js.map +0 -1
  73. package/dist/index.es-Bot12hgd.js.map +0 -1
@@ -3,7 +3,6 @@ import { zeroAddress as zeroAddress$1, parseUnits, formatUnits, isAddress, Switc
3
3
  import React, { useMemo, useCallback, useState, useEffect, createContext, useContext, useRef } from 'react';
4
4
  import { useQuery, useMutation, useQueries, useQueryClient, QueryClient, QueryClientProvider } from '@tanstack/react-query';
5
5
  import { fromBech32 } from '@cosmjs/encoding';
6
- import { getWallets } from '@wallet-standard/core';
7
6
  import * as bitcoin from 'bitcoinjs-lib';
8
7
  import { address } from 'bitcoinjs-lib';
9
8
  import * as ecc from '@bitcoinerlab/secp256k1';
@@ -11,13 +10,13 @@ import axios, { AxiosError } from 'axios';
11
10
  import { WalletConnectModal } from '@walletconnect/modal';
12
11
  import UniversalProvider from '@walletconnect/universal-provider';
13
12
  import { isValidXAddress, isValidClassicAddress } from 'ripple-address-codec';
13
+ import BigNumber, { BigNumber as BigNumber$1 } from 'bignumber.js';
14
14
  import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID, getAssociatedTokenAddress, createAssociatedTokenAccountInstruction, createTransferInstruction } from '@solana/spl-token';
15
15
  import { StandardWalletAdapter } from '@solana/wallet-standard-wallet-adapter-base';
16
16
  import { PublicKey, Transaction, SystemProgram, VersionedTransaction, Connection } from '@solana/web3.js';
17
17
  import { StrKey, Networks, nativeToScVal, Address, rpc, TransactionBuilder, BASE_FEE, Contract, TimeoutInfinite, scValToNative, Asset, Operation, Transaction as Transaction$1, xdr } from '@stellar/stellar-sdk';
18
18
  import { SUI_TESTNET_CHAIN, SUI_MAINNET_CHAIN } from '@mysten/wallet-standard';
19
19
  import { CloudflareProvider, JsonRpcProvider, ethers, Interface, BrowserProvider, JsonRpcSigner, Contract as Contract$1, isError } from 'ethers';
20
- import BigNumber$1, { BigNumber } from 'bignumber.js';
21
20
  import { countries } from 'countries-list';
22
21
  import getSymbolFromCurrency from 'currency-symbol-map';
23
22
  import Fuse from 'fuse.js';
@@ -25,6 +24,8 @@ import { create } from 'zustand';
25
24
  import { persist } from 'zustand/middleware';
26
25
  import { useAccount, useConnectors, useConnect, useDisconnect, useSwitchChain, useBalance, useReadContract, createConfig, http, useWalletClient, usePublicClient, WagmiProvider } from 'wagmi';
27
26
  import SafeAppsSDK, { TransactionStatus as TransactionStatus$1 } from '@safe-global/safe-apps-sdk';
27
+ import { createCantonClient, WindowTransport } from '@sigilry/dapp';
28
+ import { getWallets } from '@wallet-standard/core';
28
29
  import { SlushWallet } from '@mysten/slush-wallet';
29
30
  import { StargateClient, SigningStargateClient } from '@cosmjs/stargate';
30
31
  import { SuiClient } from '@mysten/sui/client';
@@ -57,6 +58,7 @@ const solanaZeroAddress = "11111111111111111111111111111111";
57
58
  const suiZeroAddress = "0x0000000000000000000000000000000000000000";
58
59
  const xrplZeroAddress = "rrrrrrrrrrrrrrrrrrrrrhoLvTp";
59
60
  const stellarZeroAddress = "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF";
61
+ const cantonZeroAddress = "none::12200000000000000000000000000000000000000000000000000000000000000000";
60
62
  const chainTypeToZeroAddressMap = {
61
63
  [ChainType.EVM]: zeroAddress$1,
62
64
  [ChainType.COSMOS]: cosmosZeroAddress,
@@ -65,6 +67,7 @@ const chainTypeToZeroAddressMap = {
65
67
  [ChainType.SUI]: suiZeroAddress,
66
68
  [ChainType.XRPL]: xrplZeroAddress,
67
69
  [ChainType.STELLAR]: stellarZeroAddress,
70
+ [ChainType.CANTON]: cantonZeroAddress,
68
71
  };
69
72
  const nativeEvmTokenAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
70
73
  const nativeCosmosTokenAddress = "uosmo";
@@ -73,6 +76,7 @@ const nativeBitcoinTokenAddress = "satoshi";
73
76
  const nativeSuiTokenAddress = "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI";
74
77
  const nativeXrplTokenAddress = "xrp";
75
78
  const nativeStellarTokenAddress = "CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA";
79
+ const nativeCantonTokenAddress = "DSO::1220b1431ef217342db44d516bb9befde802be7d8899637d290895fa58880f19accc";
76
80
  // by setting slippage to undefined, it's set to "auto"
77
81
  const defaultSlippage = undefined;
78
82
  const destinationAddressResetValue = "null";
@@ -81,6 +85,7 @@ const gasRefundMultiplier = 25;
81
85
  const internalSquidApiBaseUrl = "https://app.squidrouter.com/api";
82
86
  const XAMAN_API_URL = `${internalSquidApiBaseUrl}/xaman/`;
83
87
  const TOKEN_PRICE_API_URL = `${internalSquidApiBaseUrl}/coingecko`;
88
+ const CANTON_AMULET_REGISTRY_URL = `${internalSquidApiBaseUrl}/canton/scan-proxy`;
84
89
  const DEFAULT_ROUTE_REFETCH_INTERVAL = 30_000;
85
90
  const SOLANA_RPC_URL = "https://meredith-ute2ko-fast-mainnet.helius-rpc.com";
86
91
  const INTEGRATOR_ID = "squid-widget-playground-local-cd33cba6-7e12-4fcc-8d5d-35e286f655ea";
@@ -136,6 +141,7 @@ const CHAIN_IDS = {
136
141
  XRPL_TESTNET: "xrpl-testnet",
137
142
  STELLAR: "stellar-mainnet",
138
143
  STELLAR_TESTNET: "stellar-testnet",
144
+ CANTON: "canton",
139
145
  };
140
146
  const chainTypeToDefaultChainIdMap = {
141
147
  [ChainType.EVM]: CHAIN_IDS.ETHEREUM,
@@ -145,6 +151,7 @@ const chainTypeToDefaultChainIdMap = {
145
151
  [ChainType.SUI]: CHAIN_IDS.SUI,
146
152
  [ChainType.XRPL]: CHAIN_IDS.XRPL,
147
153
  [ChainType.STELLAR]: CHAIN_IDS.STELLAR,
154
+ [ChainType.CANTON]: CHAIN_IDS.CANTON,
148
155
  };
149
156
  const chainTypeToNativeTokenAddressMap = {
150
157
  [ChainType.EVM]: nativeEvmTokenAddress,
@@ -154,6 +161,7 @@ const chainTypeToNativeTokenAddressMap = {
154
161
  [ChainType.SUI]: nativeSuiTokenAddress,
155
162
  [ChainType.XRPL]: nativeXrplTokenAddress,
156
163
  [ChainType.STELLAR]: nativeStellarTokenAddress,
164
+ [ChainType.CANTON]: nativeCantonTokenAddress,
157
165
  };
158
166
  const defaultConfigValues = {
159
167
  integratorId: INTEGRATOR_ID,
@@ -4709,11 +4717,6 @@ class BitcoinConnectorInvalidAccountError extends BitcoinConnectorError {
4709
4717
  super("Bitcoin account is invalid");
4710
4718
  }
4711
4719
  }
4712
- class BitcoinConnectorFeatureNotSupportedError extends BitcoinConnectorError {
4713
- constructor(providerName, feature) {
4714
- super(`Bitcoin provider ${providerName} does not support ${feature}`);
4715
- }
4716
- }
4717
4720
 
4718
4721
  class KeplrConnector {
4719
4722
  get getProvider() {
@@ -4742,20 +4745,6 @@ class KeplrConnector {
4742
4745
  }
4743
4746
  }
4744
4747
 
4745
- const BitcoinConnect = "bitcoin:connect";
4746
- const BitcoinSignTransaction = "bitcoin:signTransaction";
4747
- const REQUIRED_BITCOIN_FEATURES = [
4748
- BitcoinConnect,
4749
- BitcoinSignTransaction,
4750
- ];
4751
- /**
4752
- * Type guard: the wallet exposes the Bitcoin features this SDK needs (connect +
4753
- * signTransaction). Wallets advertising only a subset are treated as unsupported.
4754
- */
4755
- function hasBitcoinFeatures(wallet) {
4756
- return REQUIRED_BITCOIN_FEATURES.every((feature) => feature in wallet.features);
4757
- }
4758
-
4759
4748
  bitcoin.initEccLib(ecc);
4760
4749
  const network = bitcoin.networks.bitcoin;
4761
4750
  const fromHexString = (hexString) => {
@@ -4845,100 +4834,55 @@ async function getTransactionStatus$1(txHash) {
4845
4834
  }
4846
4835
 
4847
4836
  const MAINNET = bitcoin.networks.bitcoin;
4848
- /**
4849
- * Bitcoin connector backed by the Bitcoin Wallet Standard.
4850
- *
4851
- * Discovers the wallet from the Wallet Standard registry at call time (mirroring
4852
- * how Solana/Sui wallets are resolved) and connects/signs through the
4853
- * `bitcoin:connect` and `bitcoin:signTransaction` features instead of a
4854
- * wallet-specific injected provider. Configure it with a `walletName` to support
4855
- * any wallet exposing the Bitcoin Wallet Standard — Phantom is the first consumer.
4856
- */
4857
- class BitcoinStandardConnector {
4858
- walletName;
4859
- constructor({ walletName }) {
4860
- this.walletName = walletName;
4861
- }
4862
- getWallet() {
4863
- const wallet = getWallets()
4864
- .get()
4865
- .find((candidate) => candidate.name.toLowerCase() === this.walletName.toLowerCase());
4866
- if (!wallet) {
4867
- throw new BitcoinConnectorProviderNotFoundError(this.walletName);
4868
- }
4869
- const bitcoinWallet = wallet;
4870
- if (!hasBitcoinFeatures(bitcoinWallet)) {
4871
- throw new BitcoinConnectorFeatureNotSupportedError(this.walletName, "Bitcoin Wallet Standard");
4837
+ class PhantomConnector {
4838
+ get getProvider() {
4839
+ const provider = window?.phantom?.bitcoin;
4840
+ if (!provider) {
4841
+ throw new BitcoinConnectorProviderNotFoundError("Phantom");
4872
4842
  }
4873
- return bitcoinWallet;
4843
+ return provider;
4874
4844
  }
4875
- async connectAccount(purpose) {
4876
- const wallet = this.getWallet();
4877
- const connect = wallet.features[BitcoinConnect]?.connect;
4878
- if (!connect) {
4879
- throw new BitcoinConnectorFeatureNotSupportedError(this.walletName, BitcoinConnect);
4880
- }
4881
- const { accounts } = await connect({ purposes: [purpose] });
4882
- // `purpose` is a user preference, not a guarantee (per Phantom's docs), but
4883
- // requesting a single purpose returns the matching account first.
4884
- const account = accounts[0];
4885
- if (typeof account?.address !== "string") {
4845
+ async requestAccount() {
4846
+ const phantomAccounts = await this.getProvider.requestAccounts();
4847
+ if (!phantomAccounts)
4848
+ throw new BitcoinConnectorInvalidAccountError();
4849
+ const paymentAccount = phantomAccounts.find((account) => account.purpose === "payment");
4850
+ if (typeof paymentAccount?.address !== "string") {
4886
4851
  throw new BitcoinConnectorInvalidAccountError();
4887
4852
  }
4888
- return account;
4889
- }
4890
- async requestAccount() {
4891
- const account = await this.connectAccount("payment");
4892
4853
  return {
4893
- address: account.address,
4854
+ address: paymentAccount.address,
4894
4855
  };
4895
4856
  }
4896
4857
  async sendBTC(to, amount) {
4897
- const account = await this.connectAccount("payment");
4898
- const { psbtHex } = await createSendBtcPsbt(account.address, to, amount);
4899
- const txId = await this.signAndBroadcast(psbtHex, account);
4858
+ const { address } = await this.requestAccount();
4859
+ const { psbtHex } = await createSendBtcPsbt(address, to, amount);
4860
+ const { txId } = await this.signPsbt(psbtHex);
4900
4861
  if (!txId)
4901
4862
  throw new BitcoinConnectorTransactionFailedError();
4902
4863
  return { txHash: txId };
4903
4864
  }
4904
- async signAndBroadcast(psbtHex, account) {
4905
- const wallet = this.getWallet();
4906
- const signTransaction = wallet.features[BitcoinSignTransaction]?.signTransaction;
4907
- if (!signTransaction) {
4908
- throw new BitcoinConnectorFeatureNotSupportedError(this.walletName, BitcoinSignTransaction);
4909
- }
4910
- const unsignedPsbt = bitcoin.Psbt.fromHex(psbtHex, { network: MAINNET });
4911
- const signingIndexes = unsignedPsbt.data.inputs.map((_, index) => index);
4912
- const [result] = await signTransaction({
4913
- psbt: fromHexString(psbtHex),
4914
- inputsToSign: [
4915
- {
4916
- // All inputs are funded from the payment account.
4917
- account,
4918
- signingIndexes,
4919
- },
4920
- ],
4865
+ async signPsbt(psbtHex) {
4866
+ const { address: paymentAddress } = await this.requestAccount();
4867
+ const toSignPsbt = bitcoin.Psbt.fromHex(String(psbtHex), {
4868
+ network: MAINNET,
4921
4869
  });
4922
- if (!result?.signedPsbt) {
4923
- throw new BitcoinConnectorTransactionFailedError();
4924
- }
4925
- const signedPsbt = bitcoin.Psbt.fromBuffer(result.signedPsbt);
4870
+ const inputs = toSignPsbt.data.inputs;
4871
+ const inputsToSign = [
4872
+ {
4873
+ // Need to sign each input with the payment address
4874
+ address: paymentAddress,
4875
+ signingIndexes: inputs.map((_, index) => index),
4876
+ },
4877
+ ];
4878
+ const signedPsbtBytes = await this.getProvider.signPSBT(fromHexString(psbtHex), {
4879
+ inputsToSign,
4880
+ });
4881
+ const signedPsbt = bitcoin.Psbt.fromBuffer(signedPsbtBytes);
4926
4882
  signedPsbt.finalizeAllInputs();
4927
4883
  const tx = signedPsbt.extractTransaction();
4928
- return broadcastTx(tx.toHex());
4929
- }
4930
- }
4931
-
4932
- /**
4933
- * Phantom Bitcoin connector via the Bitcoin Wallet Standard.
4934
- *
4935
- * Phantom deprecated the injected `window.phantom.bitcoin` provider in favour of
4936
- * the Wallet Standard; this resolves Phantom from the registry by name and signs
4937
- * through the standard Bitcoin features. See {@link BitcoinStandardConnector}.
4938
- */
4939
- class PhantomConnector extends BitcoinStandardConnector {
4940
- constructor() {
4941
- super({ walletName: "Phantom" });
4884
+ const txId = await broadcastTx(tx.toHex());
4885
+ return { txId };
4942
4886
  }
4943
4887
  }
4944
4888
 
@@ -20600,6 +20544,17 @@ var WindowWalletFlag;
20600
20544
  })(WindowWalletFlag || (WindowWalletFlag = {}));
20601
20545
 
20602
20546
  const walletIconBaseUrl = "https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/wallets";
20547
+ /**
20548
+ * Dynamically accesses a nested property of an object based on a dot-separated string path.
20549
+ * Returns the value of the property if found, otherwise undefined.
20550
+ */
20551
+ const accessProperty = (object, path) => {
20552
+ const value = get$2(object, path);
20553
+ if (value === undefined) {
20554
+ console.error(`Property "${path}" not found while reading object`, object);
20555
+ }
20556
+ return value;
20557
+ };
20603
20558
  const bitcoinWallets = [
20604
20559
  {
20605
20560
  name: "Unisat",
@@ -20896,6 +20851,34 @@ const walletStoreLinks = {
20896
20851
  },
20897
20852
  };
20898
20853
 
20854
+ /**
20855
+ * Wallets to show regardless of whether they're detected.
20856
+ * Useful when we want to link to the browser extension store
20857
+ * for wallets that are automatically discovered (i.e. EVM, SOLANA, CANTON...)
20858
+ */
20859
+ const fallbackWallets = [
20860
+ {
20861
+ chainType: ChainType.CANTON,
20862
+ id: "ldmohiccoioolenadmogclhoklmanpgi",
20863
+ name: "Send Connect",
20864
+ connectorName: "Send Connect",
20865
+ icon: `${walletIconBaseUrl}/canton-send.webp`,
20866
+ links: {
20867
+ chrome: "https://chromewebstore.google.com/detail/send-connect/ldmohiccoioolenadmogclhoklmanpgi",
20868
+ },
20869
+ },
20870
+ {
20871
+ chainType: ChainType.CANTON,
20872
+ id: "lpnfhpbpmlobjlgkdmnjieeihjmihhjd",
20873
+ name: "Console Wallet",
20874
+ connectorName: "Console Wallet",
20875
+ icon: `${walletIconBaseUrl}/canton-console.webp`,
20876
+ links: {
20877
+ chrome: "https://chromewebstore.google.com/detail/console-wallet/lpnfhpbpmlobjlgkdmnjieeihjmihhjd",
20878
+ },
20879
+ },
20880
+ ];
20881
+
20899
20882
  // Validation taken from Squid API repo
20900
20883
  const isBitcoinAddressValid = (address$1) => {
20901
20884
  try {
@@ -20915,6 +20898,142 @@ const isBitcoinAddressValid = (address$1) => {
20915
20898
  }
20916
20899
  };
20917
20900
 
20901
+ // Canton PartyID = address
20902
+ const CANTON_PARTY_ID_SEPARATOR = "::";
20903
+ /** Canton Coin's well-known token-standard instrument id (its address carries no id prefix). */
20904
+ const CANTON_AMULET_INSTRUMENT_ID = "Amulet";
20905
+ function isCantonAddressValid(address) {
20906
+ // Canton address format: `name::fingerprint`, where name is an arbitrary string
20907
+ // and fingerprint is a 64-character hex string with a 1220 prefix (SHA-256 hash of the public key)
20908
+ const parts = address.split(CANTON_PARTY_ID_SEPARATOR);
20909
+ if (parts.length !== 2)
20910
+ return false;
20911
+ const [name, fingerprint] = parts;
20912
+ return name.length > 0 && /^1220[0-9a-f]{64}$/.test(fingerprint);
20913
+ }
20914
+ /**
20915
+ * Splice token-standard Holding interface id. A party's balance for an
20916
+ * instrument is the sum of `amount` across active contracts implementing this interface.
20917
+ */
20918
+ const CANTON_HOLDING_INTERFACE_ID = "#splice-api-token-holding-v1:Splice.Api.Token.HoldingV1:Holding";
20919
+ /**
20920
+ * Derive the token-standard instrument `{ admin, id }` from a Squid Canton token
20921
+ * address (use the case-sensitive `originalAddress`), or `null` when the address
20922
+ * is not a valid Canton token address.
20923
+ *
20924
+ * The admin party is the last two `::` segments (`name::fingerprint`); the
20925
+ * instrument id is everything before that. Canton Coin has no id prefix
20926
+ * (`DSO::1220…`) and uses the well-known id `Amulet`.
20927
+ * - `DSO::1220…` -> { admin: "DSO::1220…", id: "Amulet" }
20928
+ * - `USDCx::decentralized-usdc-…::12208…` -> { admin: "decentralized-usdc-…::12208…", id: "USDCx" }
20929
+ */
20930
+ function parseCantonInstrument(address) {
20931
+ const segments = address.split(CANTON_PARTY_ID_SEPARATOR);
20932
+ if (segments.length < 2) {
20933
+ return null;
20934
+ }
20935
+ const admin = segments.slice(-2).join(CANTON_PARTY_ID_SEPARATOR);
20936
+ const idPrefix = segments.slice(0, -2).join(CANTON_PARTY_ID_SEPARATOR);
20937
+ return {
20938
+ admin,
20939
+ id: idPrefix.length > 0 ? idPrefix : CANTON_AMULET_INSTRUMENT_ID,
20940
+ };
20941
+ }
20942
+ /**
20943
+ * Body for `POST /v2/state/active-contracts`, filtered to the party's Holding
20944
+ * contracts with the interface view included (so we can read amount/instrument).
20945
+ *
20946
+ * ACS: Active Contract Set — the ledger's currently-active contracts (created and
20947
+ * not yet archived) as of a ledger offset.
20948
+ */
20949
+ function buildHoldingsAcsRequestBody(partyId, activeAtOffset) {
20950
+ return {
20951
+ activeAtOffset,
20952
+ eventFormat: {
20953
+ verbose: true,
20954
+ filtersByParty: {
20955
+ [partyId]: {
20956
+ cumulative: [
20957
+ {
20958
+ identifierFilter: {
20959
+ InterfaceFilter: {
20960
+ value: {
20961
+ interfaceId: CANTON_HOLDING_INTERFACE_ID,
20962
+ includeInterfaceView: true,
20963
+ includeCreatedEventBlob: false,
20964
+ },
20965
+ },
20966
+ },
20967
+ },
20968
+ ],
20969
+ },
20970
+ },
20971
+ },
20972
+ };
20973
+ }
20974
+ /**
20975
+ * Parse the party's Holding contracts (with contract ids) from a raw
20976
+ * `/v2/state/active-contracts` response
20977
+ * Defensive: skips entries it can't parse.
20978
+ */
20979
+ function parseCantonHoldings(acsResponse) {
20980
+ if (!Array.isArray(acsResponse))
20981
+ return [];
20982
+ const holdings = [];
20983
+ for (const entry of acsResponse) {
20984
+ const createdEvent = entry?.contractEntry?.JsActiveContract
20985
+ ?.createdEvent;
20986
+ const contractId = createdEvent?.contractId;
20987
+ const views = createdEvent?.interfaceViews;
20988
+ if (!contractId || !Array.isArray(views))
20989
+ continue;
20990
+ for (const view of views) {
20991
+ const value = view?.viewValue;
20992
+ const instrumentId = value?.instrumentId;
20993
+ if (!instrumentId?.admin ||
20994
+ instrumentId.id == null ||
20995
+ value.amount == null) {
20996
+ continue;
20997
+ }
20998
+ holdings.push({
20999
+ contractId,
21000
+ instrument: { admin: instrumentId.admin, id: instrumentId.id },
21001
+ amount: String(value.amount),
21002
+ // Locked holdings are not spendable, skip them
21003
+ locked: value.lock != null,
21004
+ });
21005
+ }
21006
+ }
21007
+ return holdings;
21008
+ }
21009
+ /**
21010
+ * Key used to group holdings by instrument.
21011
+ */
21012
+ function instrumentKey(admin, id) {
21013
+ return `${admin}|${id}`;
21014
+ }
21015
+ function cantonInstrumentKey(instrument) {
21016
+ return instrumentKey(instrument.admin, instrument.id);
21017
+ }
21018
+ /**
21019
+ * Group the (unlocked) Holding amounts by instrument from a raw
21020
+ * `/v2/state/active-contracts` response. Returns a map of instrument key
21021
+ * (`admin|id`) -> human-readable decimal string (the token-standard `amount`
21022
+ * is already a Decimal, not base units).
21023
+ */
21024
+ function groupCantonHoldingBalances(acsResponse) {
21025
+ const totals = {};
21026
+ for (const holding of parseCantonHoldings(acsResponse)) {
21027
+ // Locked holdings are not spendable, skip them
21028
+ if (holding.locked)
21029
+ continue;
21030
+ const key = cantonInstrumentKey(holding.instrument);
21031
+ const total = totals[key] ?? new BigNumber(0);
21032
+ totals[key] = total.plus(new BigNumber(holding.amount));
21033
+ }
21034
+ return Object.fromEntries(Object.entries(totals).map(([key, total]) => [key, total.toString(10)]));
21035
+ }
21036
+
20918
21037
  const solanaTokenProgramIdByAddress = {
20919
21038
  [TOKEN_PROGRAM_ID.toBase58()]: TOKEN_PROGRAM_ID,
20920
21039
  [TOKEN_2022_PROGRAM_ID.toBase58()]: TOKEN_2022_PROGRAM_ID,
@@ -21054,6 +21173,7 @@ const getSourceExplorerTxUrl = (chain, txID) => {
21054
21173
  case CHAIN_IDS.AGORIC:
21055
21174
  case CHAIN_IDS.XRPL:
21056
21175
  case CHAIN_IDS.XRPL_TESTNET:
21176
+ case CHAIN_IDS.CANTON:
21057
21177
  txSuffix = "/transactions/";
21058
21178
  break;
21059
21179
  case CHAIN_IDS.HEDERA:
@@ -21163,10 +21283,16 @@ const simplifyRouteAction = (action) => {
21163
21283
  };
21164
21284
  const fetchSwapTransactionStatus = async ({ transaction, integratorId, apiUrl, }) => {
21165
21285
  const statusEndpoint = `${apiUrl}/v2/status`;
21286
+ const isCanton = transaction?.fromChain === CHAIN_IDS.CANTON;
21287
+ // For Canton, the backend handles all tx detection/submission from the quoteId
21288
+ // alone, so no transactionId is sent — only the quoteId param below.
21289
+ const transactionId = isCanton
21290
+ ? undefined
21291
+ : (transaction?.transactionIdForStatus ?? transaction?.transactionId);
21166
21292
  try {
21167
21293
  const response = await axios.get(statusEndpoint, {
21168
21294
  params: {
21169
- transactionId: transaction?.transactionIdForStatus ?? transaction?.transactionId,
21295
+ transactionId,
21170
21296
  fromChainId: transaction?.fromChain,
21171
21297
  toChainId: transaction?.toChain,
21172
21298
  bridgeType: transaction?.bridgeType,
@@ -21213,7 +21339,7 @@ function isActionCompletedOnSourceTx(action, fromChainId) {
21213
21339
  function sleep(ms) {
21214
21340
  return new Promise((resolve) => setTimeout(resolve, ms));
21215
21341
  }
21216
- const isDepositRoute = (route) => {
21342
+ const isChainflipDepositRoute = (route) => {
21217
21343
  return (!!route &&
21218
21344
  route.transactionRequest?.type === SquidDataType.ChainflipDepositAddress);
21219
21345
  };
@@ -21238,6 +21364,12 @@ function isOnChainTxData(squidData) {
21238
21364
  SquidDataType.DepositAddressWithMemo,
21239
21365
  ].includes(squidData.type);
21240
21366
  }
21367
+ /**
21368
+ * Checks if a route is of type DepositAddressDirectTransfer
21369
+ */
21370
+ function isDepositAddressDirectTransferRoute(squidData) {
21371
+ return squidData.type === SquidDataType.DepositAddressDirectTransfer;
21372
+ }
21241
21373
  function getHistoryTransactionId(tx) {
21242
21374
  switch (tx.txType) {
21243
21375
  case HistoryTxType.SWAP:
@@ -21757,7 +21889,17 @@ const chainTypeToTrimLength = {
21757
21889
  start: 4,
21758
21890
  end: 4,
21759
21891
  },
21892
+ // abc...123::abc...123
21893
+ [ChainType.CANTON]: {
21894
+ start: 3,
21895
+ end: 3,
21896
+ },
21760
21897
  };
21898
+ const truncateWithEllipsis = (value, startLength, endLength) => value.length <= startLength + endLength
21899
+ ? value
21900
+ : value.slice(0, startLength) +
21901
+ "..." +
21902
+ value.slice(value.length - endLength);
21761
21903
  const formatHash = ({ chainType, hash }) => {
21762
21904
  if (!hash)
21763
21905
  return "";
@@ -21770,14 +21912,15 @@ const formatHash = ({ chainType, hash }) => {
21770
21912
  chainTypeFormat = ChainType.COSMOS;
21771
21913
  }
21772
21914
  }
21773
- const trimLengthStart = chainTypeToTrimLength[chainTypeFormat].start;
21774
- const trimLengthEnd = chainTypeToTrimLength[chainTypeFormat].end;
21775
- // return the same hash if its length is less than the trim length
21776
- if (hash.length <= trimLengthStart + trimLengthEnd)
21777
- return hash;
21778
- return (hash.slice(0, trimLengthStart) +
21779
- "..." +
21780
- hash.slice(hash.length - trimLengthEnd, hash.length));
21915
+ const { start, end } = chainTypeToTrimLength[chainTypeFormat];
21916
+ if (chainTypeFormat === ChainType.CANTON &&
21917
+ hash.includes(CANTON_PARTY_ID_SEPARATOR)) {
21918
+ const [namespace, identifier] = hash.split(CANTON_PARTY_ID_SEPARATOR);
21919
+ return (truncateWithEllipsis(namespace, start, end) +
21920
+ CANTON_PARTY_ID_SEPARATOR +
21921
+ truncateWithEllipsis(identifier, start, end));
21922
+ }
21923
+ return truncateWithEllipsis(hash, start, end);
21781
21924
  };
21782
21925
  const isWalletAddressValid = (chainData, address) => {
21783
21926
  if (!address || !chainData?.chainType)
@@ -21797,33 +21940,25 @@ const isWalletAddressValid = (chainData, address) => {
21797
21940
  return isXrplAddressValid(address);
21798
21941
  case ChainType.STELLAR:
21799
21942
  return isStellarAddressValid(address);
21943
+ case ChainType.CANTON:
21944
+ return isCantonAddressValid(address);
21800
21945
  }
21801
21946
  };
21802
21947
  const redirectToExtensionsStore = (wallet) => {
21803
21948
  const { userAgent } = navigator;
21804
21949
  let link;
21805
21950
  if (userAgent.indexOf("Firefox") > -1) {
21806
- link = wallet.url || walletStoreLinks[wallet.connectorId]?.firefox;
21951
+ link =
21952
+ wallet.links?.firefox || walletStoreLinks[wallet.connectorId]?.firefox;
21807
21953
  }
21808
21954
  else if (userAgent.indexOf("Chrome") > -1) {
21809
- link = wallet.url || walletStoreLinks[wallet.connectorId]?.chrome;
21955
+ link = wallet.links?.chrome || walletStoreLinks[wallet.connectorId]?.chrome;
21810
21956
  }
21957
+ link = link || wallet.links?.website;
21811
21958
  if (link && link !== "") {
21812
21959
  window?.open(link, "_blank")?.focus();
21813
21960
  }
21814
21961
  };
21815
- /**
21816
- * Dynamically accesses a nested property of an object based on a dot-separated string path.
21817
- * Returns the value of the property if found, otherwise undefined.
21818
- * e.g. "xfi.keplr" will return window.xfi.keplr
21819
- */
21820
- const accessProperty = (object, path) => {
21821
- const value = get$2(object, path);
21822
- if (value === undefined) {
21823
- console.error(`Property "${path}" not found while reading object`, object);
21824
- }
21825
- return value;
21826
- };
21827
21962
  const definedInWindow = (path, clientWindow) => {
21828
21963
  if (!path || !clientWindow)
21829
21964
  return false;
@@ -21852,6 +21987,32 @@ const populateWallets = (window, wallets) => {
21852
21987
  return wallet;
21853
21988
  });
21854
21989
  };
21990
+ const createUninstalledConnector = () => new Proxy({}, {
21991
+ get(_target, prop) {
21992
+ throw new Error(`Cannot use connector of an uninstalled wallet (accessed "${String(prop)}")`);
21993
+ },
21994
+ });
21995
+ const buildFallbackWallets = (discovered) => {
21996
+ const fallbackKey = (chainType, connectorId) => `${chainType}:${connectorId}`;
21997
+ const discoveredKeys = new Set(discovered.flatMap((wallet) => wallet.isMultiChain
21998
+ ? wallet.supportedNetworks.map((network) => fallbackKey(network.chainType, wallet.connectorId))
21999
+ : [fallbackKey(wallet.type, wallet.connectorId)]));
22000
+ return fallbackWallets
22001
+ .filter((config) => !discoveredKeys.has(fallbackKey(config.chainType, config.id)))
22002
+ .map((config) => ({
22003
+ name: config.name,
22004
+ connectorId: config.id,
22005
+ connectorName: config.connectorName,
22006
+ icon: config.icon,
22007
+ windowFlag: config.id,
22008
+ links: config.links,
22009
+ isInstalled: () => false,
22010
+ skipInstallCheck: false,
22011
+ isMultiChain: false,
22012
+ type: config.chainType,
22013
+ connector: createUninstalledConnector(),
22014
+ }));
22015
+ };
21855
22016
  /**
21856
22017
  * Get the base chain to connect to
21857
22018
  * If only one chain type is selected, use that chain type
@@ -22058,6 +22219,13 @@ const connectByChainType = async (chainType, wallet, defaultChain, params) => {
22058
22219
  connector,
22059
22220
  },
22060
22221
  });
22222
+ case ChainType.CANTON:
22223
+ return params.connectCanton.mutateAsync({
22224
+ wallet: {
22225
+ ...wallet,
22226
+ connector,
22227
+ },
22228
+ });
22061
22229
  }
22062
22230
  };
22063
22231
  const getChainTypesToConnect = (selectedChainTypes, defaultChain, supportedChains) => {
@@ -22094,6 +22262,7 @@ const connectMultiChainWallet = async (params) => {
22094
22262
  connectSui: params.connectSui,
22095
22263
  connectXrpl: params.connectXrpl,
22096
22264
  connectStellar: params.connectStellar,
22265
+ connectCanton: params.connectCanton,
22097
22266
  });
22098
22267
  if (result) {
22099
22268
  results.push({
@@ -22127,6 +22296,7 @@ const connectSingleChainWallet = async (params) => {
22127
22296
  connectSui: params.connectSui,
22128
22297
  connectXrpl: params.connectXrpl,
22129
22298
  connectStellar: params.connectStellar,
22299
+ connectCanton: params.connectCanton,
22130
22300
  });
22131
22301
  return result
22132
22302
  ? {
@@ -22917,8 +23087,8 @@ function convertTokenAmountToUSD(tokenAmount, tokenPrice, maxDecimals = 4) {
22917
23087
  if (!tokenAmount || !tokenPrice)
22918
23088
  return "";
22919
23089
  try {
22920
- const amount = new BigNumber(cleanAmount(tokenAmount));
22921
- const price = new BigNumber(cleanAmount(tokenPrice));
23090
+ const amount = new BigNumber$1(cleanAmount(tokenAmount));
23091
+ const price = new BigNumber$1(cleanAmount(tokenPrice));
22922
23092
  return amount.multipliedBy(price).decimalPlaces(maxDecimals).toString();
22923
23093
  }
22924
23094
  catch {
@@ -22935,8 +23105,8 @@ function convertTokenAmountToUSD(tokenAmount, tokenPrice, maxDecimals = 4) {
22935
23105
  function convertUSDToTokenAmount(usdAmount, tokenPrice, maxDecimals) {
22936
23106
  if (!usdAmount || !tokenPrice || !maxDecimals)
22937
23107
  return "0";
22938
- const amount = new BigNumber(cleanAmount(usdAmount));
22939
- const price = new BigNumber(cleanAmount(tokenPrice));
23108
+ const amount = new BigNumber$1(cleanAmount(usdAmount));
23109
+ const price = new BigNumber$1(cleanAmount(tokenPrice));
22940
23110
  return amount.dividedBy(price).decimalPlaces(maxDecimals).toString();
22941
23111
  }
22942
23112
  const calculateTotal24hChange = (tokensWithBalance, totalUSDAmount) => {
@@ -23040,7 +23210,7 @@ const handleDestinationAddressOnSwapChange = ({ fromChainId, fromTokenAddress, t
23040
23210
  });
23041
23211
  let destinationTokenAddress = toChainId && !toTokenAddress
23042
23212
  ? defaultToAddress
23043
- : toTokenAddress ?? swapRoute?.toTokenAddress;
23213
+ : (toTokenAddress ?? swapRoute?.toTokenAddress);
23044
23214
  const lowerCaseDestinationTokenAddress = destinationTokenAddress?.toLowerCase();
23045
23215
  if (destinationTokensFiltered.find((t) => t.address === lowerCaseDestinationTokenAddress) === undefined) {
23046
23216
  destinationTokenAddress = defaultToAddress;
@@ -23092,7 +23262,7 @@ const getNewSwapParamsFromInput = ({ inputParams, initialSwapRoute, tokens, chai
23092
23262
  toTokenAddress === initialSwapRoute?.fromTokenAddress;
23093
23263
  const sourceTokenAddress = sameNewDestAndInitialSource || onlySourceChainIdChanged
23094
23264
  ? defaultFromAddress
23095
- : fromTokenAddress ?? initialSwapRoute?.fromTokenAddress;
23265
+ : (fromTokenAddress ?? initialSwapRoute?.fromTokenAddress);
23096
23266
  let destinationTokenAddress = undefined;
23097
23267
  if (!sameNewSourceAndInitialDest) {
23098
23268
  if (onlySourceChainIdChanged) {
@@ -23132,7 +23302,10 @@ const getNewSwapParamsFromInput = ({ inputParams, initialSwapRoute, tokens, chai
23132
23302
  else {
23133
23303
  newFallbackAddress = fallbackAddress ?? initialSwapRoute?.fallbackAddress;
23134
23304
  }
23135
- const newDepositRefundAddress = depositRefundAddress || initialSwapRoute?.depositRefundAddress;
23305
+ const sourceChainChanged = fromChainId !== undefined && fromChainId !== initialSwapRoute?.fromChainId;
23306
+ const newDepositRefundAddress = sourceChainChanged
23307
+ ? undefined
23308
+ : depositRefundAddress || initialSwapRoute?.depositRefundAddress;
23136
23309
  return {
23137
23310
  fromChainId: srcChainId,
23138
23311
  fromTokenAddress: sourceTokenAddress,
@@ -23290,11 +23463,11 @@ const groupTokensBySymbol = (tokens, chainType) => {
23290
23463
  };
23291
23464
  }
23292
23465
  groups[groupKey].tokens.push(token);
23293
- groups[groupKey].totalBalance = new BigNumber$1(groups[groupKey].totalBalance)
23466
+ groups[groupKey].totalBalance = new BigNumber(groups[groupKey].totalBalance)
23294
23467
  .plus(token.balance)
23295
23468
  .toString();
23296
23469
  const tokenUsdValue = convertTokenAmountToUSD(token.balance, token.usdPrice || 0);
23297
- groups[groupKey].totalBalanceUsd = new BigNumber$1(groups[groupKey].totalBalanceUsd ?? "0")
23470
+ groups[groupKey].totalBalanceUsd = new BigNumber(groups[groupKey].totalBalanceUsd ?? "0")
23298
23471
  .plus(tokenUsdValue)
23299
23472
  .toString();
23300
23473
  });
@@ -23316,11 +23489,11 @@ const groupTokensBySymbol = (tokens, chainType) => {
23316
23489
  else {
23317
23490
  // Combine tokens and sum up total balance for existing groups
23318
23491
  mergedGroups[mergeKey].tokens.push(...group.tokens);
23319
- mergedGroups[mergeKey].totalBalance = new BigNumber$1(mergedGroups[mergeKey].totalBalance)
23492
+ mergedGroups[mergeKey].totalBalance = new BigNumber(mergedGroups[mergeKey].totalBalance)
23320
23493
  .plus(group.totalBalance)
23321
23494
  .toString();
23322
23495
  // Add this line to properly merge USD values
23323
- mergedGroups[mergeKey].totalBalanceUsd = new BigNumber$1(mergedGroups[mergeKey].totalBalanceUsd ?? "0")
23496
+ mergedGroups[mergeKey].totalBalanceUsd = new BigNumber(mergedGroups[mergeKey].totalBalanceUsd ?? "0")
23324
23497
  .plus(group.totalBalanceUsd ?? "0")
23325
23498
  .toString();
23326
23499
  }
@@ -23365,13 +23538,13 @@ const groupTokensByChainId = (tokens, chains) => {
23365
23538
  };
23366
23539
  }
23367
23540
  groups[groupKey].tokens.push(token);
23368
- groups[groupKey].totalBalance = new BigNumber$1(groups[groupKey].totalBalance)
23541
+ groups[groupKey].totalBalance = new BigNumber(groups[groupKey].totalBalance)
23369
23542
  .plus(token.balance)
23370
23543
  .toString();
23371
23544
  // Only add to USD total if token has a valid price
23372
23545
  if (token.usdPrice && token.usdPrice > 0) {
23373
23546
  const tokenUsdValue = convertTokenAmountToUSD(token.balance, token.usdPrice);
23374
- groups[groupKey].totalBalanceUsd = new BigNumber$1(groups[groupKey].totalBalanceUsd ?? "0")
23547
+ groups[groupKey].totalBalanceUsd = new BigNumber(groups[groupKey].totalBalanceUsd ?? "0")
23375
23548
  .plus(tokenUsdValue)
23376
23549
  .toString();
23377
23550
  }
@@ -23411,7 +23584,7 @@ const filterViewableTokens = (tokens, config, direction) => {
23411
23584
  };
23412
23585
  const getSecretNetworkBalances = async (chainData, cosmosAddress, squidTokens, keplrTypeWallet) => {
23413
23586
  const squidSecretTokens = squidTokens.filter((t) => t.chainId === CHAIN_IDS.SECRET);
23414
- const { fetchAllSecretBalances } = await import('./secretService-BAK4sBb7.js');
23587
+ const { fetchAllSecretBalances } = await import('./secretService-eiBnD7dI.js');
23415
23588
  return fetchAllSecretBalances(chainData, cosmosAddress, squidSecretTokens, keplrTypeWallet);
23416
23589
  };
23417
23590
  function getTokenAssetsKey(token) {
@@ -23438,9 +23611,29 @@ async function fetchAssetsColors() {
23438
23611
  };
23439
23612
  }
23440
23613
  }
23441
- function initializeSquidWithAssetsColors(squid, assetsColors) {
23442
- const evmosChainIds = squid.chains.filter(isEvmosChain).map((c) => c.chainId);
23443
- squid.tokens = squid.tokens.map((token) => {
23614
+ const supportedChainTypes = new Set(Object.values(ChainType));
23615
+ function isSupportedChainType(chainType) {
23616
+ return supportedChainTypes.has(chainType);
23617
+ }
23618
+ /**
23619
+ * Normalizes SDK data after each init/refetch before the rest of hooks consumes it.
23620
+ *
23621
+ * - Removes chains whose chainType is not supported by the local package.
23622
+ * - Drops tokens for those removed chains.
23623
+ * - Converts Evmos chains/tokens to EVM.
23624
+ * - Applies optional asset colors.
23625
+ */
23626
+ function initializeSquidData(squid, assetsColors = {
23627
+ chains: {},
23628
+ tokens: {},
23629
+ }) {
23630
+ const supportedChains = squid.chains.filter((chain) => isSupportedChainType(chain.chainType));
23631
+ const supportedChainIds = new Set(supportedChains.map((chain) => chain.chainId));
23632
+ const evmosChainIds = supportedChains
23633
+ .filter(isEvmosChain)
23634
+ .map((c) => c.chainId);
23635
+ const supportedTokens = squid.tokens.filter((token) => supportedChainIds.has(token.chainId));
23636
+ squid.tokens = supportedTokens.map((token) => {
23444
23637
  const isEvmosToken = evmosChainIds.includes(token.chainId);
23445
23638
  return {
23446
23639
  ...token,
@@ -23449,7 +23642,7 @@ function initializeSquidWithAssetsColors(squid, assetsColors) {
23449
23642
  textColor: assetsColors.tokens[getTokenAssetsKey(token)]?.textColor,
23450
23643
  };
23451
23644
  });
23452
- squid.chains = squid.chains.map((chain) => {
23645
+ squid.chains = supportedChains.map((chain) => {
23453
23646
  const bgColor = assetsColors.chains[chain.chainId]?.bgColor;
23454
23647
  // convert evmos cosmos chains to evm chains
23455
23648
  // TODO: this will be fixed in the backend
@@ -25102,7 +25295,7 @@ class OnrampService {
25102
25295
  });
25103
25296
  return data;
25104
25297
  }
25105
- async getConfiguration({ chains, tokens, }) {
25298
+ async getConfiguration({ tokens, }) {
25106
25299
  const { data } = await axios.get(`${this.baseUrl}/config`);
25107
25300
  // Filter supportedCryptos to only include tokens that match our provided tokens
25108
25301
  const filteredCryptos = data.supportedCryptos.filter((supportedCrypto) => tokens.some((token) => token.address.toLowerCase() ===
@@ -25326,7 +25519,7 @@ const useSquid = () => {
25326
25519
  queryFn: async () => {
25327
25520
  if (squid) {
25328
25521
  await squid?.init();
25329
- initializeSquidWithAssetsColors(squid, assetsColors);
25522
+ initializeSquidData(squid, assetsColors);
25330
25523
  return squid;
25331
25524
  }
25332
25525
  return null;
@@ -25385,7 +25578,7 @@ const useSquidTokens = (direction) => {
25385
25578
  config.availableChains,
25386
25579
  direction,
25387
25580
  ]);
25388
- const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, } = useMemo(() => {
25581
+ const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, cantonTokens, } = useMemo(() => {
25389
25582
  return tokens?.reduce((acc, token) => {
25390
25583
  switch (token.type) {
25391
25584
  case ChainType.EVM:
@@ -25409,6 +25602,9 @@ const useSquidTokens = (direction) => {
25409
25602
  case ChainType.STELLAR:
25410
25603
  acc.stellarTokens.push(token);
25411
25604
  break;
25605
+ case ChainType.CANTON:
25606
+ acc.cantonTokens.push(token);
25607
+ break;
25412
25608
  }
25413
25609
  return acc;
25414
25610
  }, {
@@ -25419,6 +25615,7 @@ const useSquidTokens = (direction) => {
25419
25615
  suiTokens: [],
25420
25616
  xrplTokens: [],
25421
25617
  stellarTokens: [],
25618
+ cantonTokens: [],
25422
25619
  });
25423
25620
  }, [tokens]);
25424
25621
  const findToken = useCallback((address, chainId) => {
@@ -25436,6 +25633,7 @@ const useSquidTokens = (direction) => {
25436
25633
  suiTokens,
25437
25634
  xrplTokens,
25438
25635
  stellarTokens,
25636
+ cantonTokens,
25439
25637
  };
25440
25638
  };
25441
25639
 
@@ -25536,12 +25734,10 @@ const useGetFiatQuote = ({ fiatCurrency, cryptoCurrencyID, amount, region, payme
25536
25734
  */
25537
25735
  const useGetOnRampConfig = () => {
25538
25736
  const service = useMemo(() => new OnrampService(), []);
25539
- const { chains } = useSquidChains();
25540
25737
  const { tokens } = useSquidTokens();
25541
25738
  return useQuery({
25542
25739
  queryKey: keys().fiatToCryptoConfig(),
25543
25740
  queryFn: () => service.getConfiguration({
25544
- chains,
25545
25741
  tokens,
25546
25742
  }),
25547
25743
  cacheTime: 1000 * 60 * 60,
@@ -25973,6 +26169,7 @@ const chainTypeToRefetchInterval = {
25973
26169
  [ChainType.SUI]: 1_000,
25974
26170
  [ChainType.XRPL]: 1_000,
25975
26171
  [ChainType.STELLAR]: 1_000,
26172
+ [ChainType.CANTON]: 1_000,
25976
26173
  };
25977
26174
  /**
25978
26175
  * Returns the status refetch interval of a Send transaction
@@ -26239,7 +26436,7 @@ const useSquidChains = (direction) => {
26239
26436
  const chain = findChain(chainId);
26240
26437
  return chain?.chainType;
26241
26438
  }, [findChain]);
26242
- const { evmChains, cosmosChains, suiChains, stellarChains, xrplChains } = useMemo(() => {
26439
+ const { evmChains, cosmosChains, suiChains, stellarChains, xrplChains, cantonChains, } = useMemo(() => {
26243
26440
  return chains.reduce((acc, chain) => {
26244
26441
  switch (chain.chainType) {
26245
26442
  case ChainType.EVM:
@@ -26257,6 +26454,9 @@ const useSquidChains = (direction) => {
26257
26454
  case ChainType.STELLAR:
26258
26455
  acc.stellarChains.push(chain);
26259
26456
  break;
26457
+ case ChainType.CANTON:
26458
+ acc.cantonChains.push(chain);
26459
+ break;
26260
26460
  }
26261
26461
  return acc;
26262
26462
  }, {
@@ -26265,6 +26465,7 @@ const useSquidChains = (direction) => {
26265
26465
  suiChains: [],
26266
26466
  xrplChains: [],
26267
26467
  stellarChains: [],
26468
+ cantonChains: [],
26268
26469
  });
26269
26470
  }, [chains]);
26270
26471
  const { supportedSourceChains, supportedDestinationChains } = useMemo(() => {
@@ -26285,6 +26486,7 @@ const useSquidChains = (direction) => {
26285
26486
  suiChains,
26286
26487
  xrplChains,
26287
26488
  stellarChains,
26489
+ cantonChains,
26288
26490
  getChainType,
26289
26491
  findChain,
26290
26492
  };
@@ -26598,6 +26800,253 @@ const useBitcoinContext = () => {
26598
26800
  return context;
26599
26801
  };
26600
26802
 
26803
+ const REQUEST_TIMEOUT_MS = 60_000;
26804
+ function pickAddress(accounts) {
26805
+ return (accounts.find((a) => a.primary) ?? accounts[0])?.partyId;
26806
+ }
26807
+ /**
26808
+ * Browser-extension Canton connector: wraps one discovered CIP-103 provider
26809
+ * (bound to its announce `target`) and exposes the lifecycle methods.
26810
+ */
26811
+ class CantonBrowserConnector {
26812
+ providerId;
26813
+ name;
26814
+ target;
26815
+ client;
26816
+ listeners = { connect: new Set(), disconnect: new Set() };
26817
+ _accounts = [];
26818
+ constructor(provider, win = window) {
26819
+ this.providerId = provider.id;
26820
+ this.name = provider.name;
26821
+ this.target = provider.target ?? provider.id;
26822
+ this.client = createCantonClient(new WindowTransport(win, {
26823
+ target: this.target,
26824
+ timeout: REQUEST_TIMEOUT_MS,
26825
+ }));
26826
+ }
26827
+ get accounts() {
26828
+ return this._accounts;
26829
+ }
26830
+ get address() {
26831
+ return pickAddress(this._accounts);
26832
+ }
26833
+ async connect() {
26834
+ await this.client.connect();
26835
+ const result = await this.refreshAccounts();
26836
+ this.emit("connect", result.address);
26837
+ return result;
26838
+ }
26839
+ /** Silent connect: read accounts without prompting; throws if not connected. */
26840
+ async autoConnect() {
26841
+ const accounts = await this.client.listAccounts();
26842
+ if (!accounts.length) {
26843
+ throw new Error("Canton wallet not connected");
26844
+ }
26845
+ this._accounts = accounts;
26846
+ const address = pickAddress(accounts);
26847
+ this.emit("connect", address);
26848
+ return { address, accounts };
26849
+ }
26850
+ async disconnect() {
26851
+ try {
26852
+ await this.client.disconnect();
26853
+ }
26854
+ finally {
26855
+ this._accounts = [];
26856
+ this.emit("disconnect");
26857
+ }
26858
+ }
26859
+ async ledgerApi(params) {
26860
+ const result = await this.client.ledgerApi(params);
26861
+ return result;
26862
+ }
26863
+ async prepareExecuteAndWait(params) {
26864
+ return this.client.prepareExecuteAndWait(params);
26865
+ }
26866
+ async getAccounts() {
26867
+ this._accounts = await this.client.listAccounts();
26868
+ return this._accounts;
26869
+ }
26870
+ on(event, handler) {
26871
+ this.listeners[event].add(handler);
26872
+ }
26873
+ off(event, handler) {
26874
+ this.listeners[event].delete(handler);
26875
+ }
26876
+ emit(event, ...args) {
26877
+ this.listeners[event].forEach((handler) => handler(...args));
26878
+ }
26879
+ async refreshAccounts() {
26880
+ const accounts = await this.client.listAccounts();
26881
+ this._accounts = accounts;
26882
+ const address = pickAddress(accounts);
26883
+ if (!address) {
26884
+ throw new Error("Canton wallet returned no accounts");
26885
+ }
26886
+ return { address, accounts };
26887
+ }
26888
+ }
26889
+
26890
+ const CANTON_REQUEST_PROVIDER_EVENT = "canton:requestProvider";
26891
+ const CANTON_ANNOUNCE_PROVIDER_EVENT = "canton:announceProvider";
26892
+ const DEFAULT_DISCOVERY_TIMEOUT_MS = 300;
26893
+ /**
26894
+ * CIP-103 browser-wallet discovery (EIP-6963-style).
26895
+ * The wallet dispatches `canton:announceProvider` and dApps
26896
+ * dispatch `canton:requestProvider` to ask installed wallets to re-announce.
26897
+ * Each announcement carries a `target` we route through Sigilry's `WindowTransport`,
26898
+ * so multiple extensions coexist without contending on the `window.canton` global.
26899
+ */
26900
+ async function discoverCantonProviders(timeoutMs = DEFAULT_DISCOVERY_TIMEOUT_MS, win = window) {
26901
+ if (typeof win === "undefined")
26902
+ return [];
26903
+ const discovered = new Map();
26904
+ const handler = (event) => {
26905
+ const detail = event.detail;
26906
+ if (!detail?.id || !detail.name || discovered.has(detail.id))
26907
+ return;
26908
+ discovered.set(detail.id, {
26909
+ id: detail.id,
26910
+ name: detail.name,
26911
+ icon: detail.icon,
26912
+ target: detail.target ?? detail.id,
26913
+ });
26914
+ };
26915
+ win.addEventListener(CANTON_ANNOUNCE_PROVIDER_EVENT, handler);
26916
+ try {
26917
+ win.dispatchEvent(new CustomEvent(CANTON_REQUEST_PROVIDER_EVENT, { detail: {} }));
26918
+ await new Promise((resolve) => setTimeout(resolve, timeoutMs));
26919
+ }
26920
+ finally {
26921
+ win.removeEventListener(CANTON_ANNOUNCE_PROVIDER_EVENT, handler);
26922
+ }
26923
+ return Array.from(discovered.values());
26924
+ }
26925
+
26926
+ /**
26927
+ * Discovers Canton browser-extension wallets via the CIP-103 announce protocol
26928
+ * (on mount and on window focus) and maps each to a {@link CantonWallet}.
26929
+ */
26930
+ function useCantonWallets() {
26931
+ const [wallets, setWallets] = useState([]);
26932
+ const connectorCache = useRef(new Map());
26933
+ const toWallet = useCallback((provider) => {
26934
+ let connector = connectorCache.current.get(provider.id);
26935
+ if (!connector) {
26936
+ connector = new CantonBrowserConnector(provider);
26937
+ connectorCache.current.set(provider.id, connector);
26938
+ }
26939
+ return {
26940
+ name: provider.name,
26941
+ connectorId: provider.id,
26942
+ connectorName: provider.name,
26943
+ icon: provider.icon,
26944
+ windowFlag: provider.id,
26945
+ skipInstallCheck: true,
26946
+ isInstalled: () => true,
26947
+ isMultiChain: false,
26948
+ type: ChainType.CANTON,
26949
+ connector,
26950
+ };
26951
+ }, []);
26952
+ const refresh = useCallback(async () => {
26953
+ if (typeof window === "undefined")
26954
+ return;
26955
+ const providers = await discoverCantonProviders();
26956
+ setWallets(providers.map(toWallet));
26957
+ }, [toWallet]);
26958
+ useEffect(() => {
26959
+ refresh();
26960
+ if (typeof window === "undefined")
26961
+ return;
26962
+ const onFocus = () => refresh();
26963
+ window.addEventListener("focus", onFocus);
26964
+ return () => window.removeEventListener("focus", onFocus);
26965
+ }, [refresh]);
26966
+ return { wallets };
26967
+ }
26968
+
26969
+ function useCanton() {
26970
+ const disconnectWallet = useWalletStore((store) => store.disconnectWallet);
26971
+ const setConnectedWallet = useWalletStore((store) => store.setConnectedWallet);
26972
+ const { wallets } = useCantonWallets();
26973
+ const connectedCantonWallet = useWalletStore((store) => store.connectedWalletsByChainType[ChainType.CANTON]);
26974
+ const recentCantonWalletId = useWalletStore((store) => store.recentConnectorIds[ChainType.CANTON]);
26975
+ const connectCanton = useMutation(async ({ wallet, }) => {
26976
+ let result;
26977
+ try {
26978
+ // Try to reconnect silently first (existing session, no popup)
26979
+ result = await wallet.connector.autoConnect();
26980
+ }
26981
+ catch {
26982
+ // Otherwise prompt the wallet to connect
26983
+ result = await wallet.connector.connect();
26984
+ }
26985
+ return {
26986
+ wallet,
26987
+ address: result.address,
26988
+ };
26989
+ });
26990
+ const disconnectCanton = useCallback(async () => {
26991
+ await connectedCantonWallet.wallet?.connector.disconnect();
26992
+ }, [connectedCantonWallet.wallet?.connector]);
26993
+ const autoConnectCanton = useCallback(async () => {
26994
+ const recentCantonWallet = wallets.find((w) => w.connectorId === recentCantonWalletId);
26995
+ if (!recentCantonWallet) {
26996
+ return;
26997
+ }
26998
+ const { address } = await recentCantonWallet.connector.autoConnect();
26999
+ setConnectedWallet(ChainType.CANTON, {
27000
+ wallet: recentCantonWallet,
27001
+ address,
27002
+ });
27003
+ // eslint-disable-next-line react-hooks/exhaustive-deps
27004
+ }, [wallets.map((w) => w.connectorId), recentCantonWalletId]);
27005
+ useEffect(() => {
27006
+ const wallet = connectedCantonWallet.wallet;
27007
+ if (!wallet) {
27008
+ return;
27009
+ }
27010
+ function onConnect(newAddress) {
27011
+ if (wallet) {
27012
+ setConnectedWallet(ChainType.CANTON, {
27013
+ wallet,
27014
+ address: newAddress,
27015
+ });
27016
+ }
27017
+ }
27018
+ function onDisconnect() {
27019
+ disconnectWallet(ChainType.CANTON);
27020
+ }
27021
+ wallet.connector.on("connect", onConnect);
27022
+ wallet.connector.on("disconnect", onDisconnect);
27023
+ return () => {
27024
+ wallet.connector.off("connect", onConnect);
27025
+ wallet.connector.off("disconnect", onDisconnect);
27026
+ };
27027
+ }, [disconnectWallet, setConnectedWallet, connectedCantonWallet.wallet]);
27028
+ return {
27029
+ connectCanton,
27030
+ disconnectCanton,
27031
+ autoConnectCanton,
27032
+ signer: connectedCantonWallet.wallet?.connector,
27033
+ wallets,
27034
+ };
27035
+ }
27036
+
27037
+ const CantonContext = createContext(undefined);
27038
+ const CantonProvider = ({ children, }) => {
27039
+ const cantonHook = useCanton();
27040
+ return (React.createElement(CantonContext.Provider, { value: cantonHook }, children));
27041
+ };
27042
+ const useCantonContext = () => {
27043
+ const context = useContext(CantonContext);
27044
+ if (!context) {
27045
+ throw new Error("useCantonContext must be used within a CantonProvider");
27046
+ }
27047
+ return context;
27048
+ };
27049
+
26601
27050
  function useEvmWallets() {
26602
27051
  const connectors = useConnectors();
26603
27052
  const wallets = useMemo(() => {
@@ -26809,7 +27258,7 @@ function useStellarWallets() {
26809
27258
  try {
26810
27259
  const { allowAllModules: initializeAllModules } = await import('@creit.tech/stellar-wallets-kit');
26811
27260
  const { LedgerModule } = await import('@creit.tech/stellar-wallets-kit/modules/ledger.module.mjs');
26812
- const { formatStellarWallet } = await import('./stellarService.client-DkJ6WAdl.js');
27261
+ const { formatStellarWallet } = await import('./stellarService.client-VOmCOPzL.js');
26813
27262
  const modules = [...initializeAllModules(), new LedgerModule()];
26814
27263
  const promises = modules.map(async (module) => {
26815
27264
  const isAvailable = await module.isAvailable();
@@ -27282,17 +27731,24 @@ const useWallets = () => {
27282
27731
  const { wallets: suiWallets } = useSuiContext();
27283
27732
  const { wallets: xrplWallets } = useXrplContext();
27284
27733
  const { wallets: stellarWallets } = useStellarContext();
27734
+ const { wallets: cantonWallets } = useCantonContext();
27285
27735
  const wallets = useMemo(() => {
27286
27736
  const singleChainWallets$1 = populateWallets(clientWindow, singleChainWallets);
27287
27737
  const multiChainWallets$1 = populateWallets(clientWindow, multiChainWallets);
27738
+ const discoveredWallets = [
27739
+ ...evmWallets,
27740
+ ...solanaWallets,
27741
+ ...suiWallets,
27742
+ ...cantonWallets,
27743
+ ];
27744
+ const fallbackWallets = buildFallbackWallets(discoveredWallets);
27288
27745
  return mergeWallets({
27289
27746
  singleChainWallets: [
27290
27747
  ...singleChainWallets$1,
27291
- ...evmWallets,
27292
- ...solanaWallets,
27293
- ...suiWallets,
27748
+ ...discoveredWallets,
27294
27749
  ...xrplWallets,
27295
27750
  ...stellarWallets,
27751
+ ...fallbackWallets,
27296
27752
  ],
27297
27753
  multiChainWallets: multiChainWallets$1,
27298
27754
  });
@@ -27303,6 +27759,7 @@ const useWallets = () => {
27303
27759
  suiWallets,
27304
27760
  xrplWallets,
27305
27761
  stellarWallets,
27762
+ cantonWallets,
27306
27763
  ]);
27307
27764
  return {
27308
27765
  wallets,
@@ -27318,6 +27775,7 @@ const useWallet = () => {
27318
27775
  const { connectSui, disconnectSui } = useSuiContext();
27319
27776
  const { connectXrpl, disconnectXrpl } = useXrplContext();
27320
27777
  const { connectStellar, disconnectStellar } = useStellarContext();
27778
+ const { connectCanton, disconnectCanton } = useCantonContext();
27321
27779
  const { findChain } = useSquidChains();
27322
27780
  const { isGnosisConnected, gnosisAddress } = useGnosisContext();
27323
27781
  const destinationAddress = useSwapRoutePersistStore((state) => state.swapRoute?.destinationAddress);
@@ -27354,6 +27812,7 @@ const useWallet = () => {
27354
27812
  connectSui,
27355
27813
  connectXrpl,
27356
27814
  connectStellar,
27815
+ connectCanton,
27357
27816
  selectedChainTypes,
27358
27817
  findChain,
27359
27818
  });
@@ -27402,6 +27861,9 @@ const useWallet = () => {
27402
27861
  case ChainType.STELLAR:
27403
27862
  await disconnectStellar();
27404
27863
  break;
27864
+ case ChainType.CANTON:
27865
+ await disconnectCanton();
27866
+ break;
27405
27867
  default:
27406
27868
  // TODO: Implement disconnect for other chains
27407
27869
  break;
@@ -27508,6 +27970,7 @@ const useMultiChainWallet = (chain) => {
27508
27970
  const suiAddress = connectedAddresses[ChainType.SUI];
27509
27971
  const xrplAddress = connectedAddresses[ChainType.XRPL];
27510
27972
  const stellarAddress = connectedAddresses[ChainType.STELLAR];
27973
+ const cantonAddress = connectedAddresses[ChainType.CANTON];
27511
27974
  // Cosmos is a special case because the address changes on every chain
27512
27975
  // so we can't use the default cosmos connected address
27513
27976
  const { data: cosmosAddress } = useCosmosForChain(chain);
@@ -27595,6 +28058,16 @@ const useMultiChainWallet = (chain) => {
27595
28058
  chainType: chain.chainType,
27596
28059
  }),
27597
28060
  };
28061
+ case ChainType.CANTON:
28062
+ if (!cantonAddress)
28063
+ return {};
28064
+ return {
28065
+ address: cantonAddress,
28066
+ formatted: formatHash({
28067
+ hash: cantonAddress,
28068
+ chainType: chain.chainType,
28069
+ }),
28070
+ };
27598
28071
  }
27599
28072
  }, [
27600
28073
  chain?.chainType,
@@ -27606,6 +28079,7 @@ const useMultiChainWallet = (chain) => {
27606
28079
  suiAddress,
27607
28080
  xrplAddress,
27608
28081
  stellarAddress,
28082
+ cantonAddress,
27609
28083
  ]);
27610
28084
  /**
27611
28085
  * Change current network for desired chain
@@ -28430,6 +28904,8 @@ async function createClient(chain) {
28430
28904
  return new XrplRpcClient(chain.rpc);
28431
28905
  case ChainType.STELLAR:
28432
28906
  return new StellarRpcClient(chain.rpc);
28907
+ case ChainType.CANTON:
28908
+ return null;
28433
28909
  }
28434
28910
  }
28435
28911
 
@@ -29442,6 +29918,54 @@ const getAllStellarTokensBalance = async (userAddress, stellarTokens, stellarCha
29442
29918
  const allResults = await Promise.all(stellarChains.map(getBalancesForChain));
29443
29919
  return allResults.flat();
29444
29920
  };
29921
+ /**
29922
+ * Canton balances are private: they can only be read with a wallet-authorized
29923
+ * `ledgerApi` session (the connected wallet supplies a JWT that can read as the
29924
+ * party). So balance is fetchable only when a Canton wallet is connected, and
29925
+ * only for that wallet's party — there's no address-only read.
29926
+ */
29927
+ const getCantonTokenBalance = async (userAddress, token, cantonConnector) => {
29928
+ if (!token.originalAddress)
29929
+ return "0";
29930
+ const instrument = parseCantonInstrument(token.originalAddress);
29931
+ if (!instrument)
29932
+ return "0";
29933
+ const ledgerEnd = await cantonConnector.ledgerApi({ requestMethod: "get", resource: "/v2/state/ledger-end" });
29934
+ const activeContracts = await cantonConnector.ledgerApi({
29935
+ requestMethod: "post",
29936
+ resource: "/v2/state/active-contracts",
29937
+ body: buildHoldingsAcsRequestBody(userAddress, String(ledgerEnd.offset)),
29938
+ });
29939
+ const grouped = groupCantonHoldingBalances(activeContracts);
29940
+ return grouped[cantonInstrumentKey(instrument)] ?? "0";
29941
+ };
29942
+ /**
29943
+ * Fetch balances for all Canton tokens in one ACS query. Canton balances are
29944
+ * private, so this requires a connected wallet's authorized `ledgerApi`.
29945
+ */
29946
+ async function getAllCantonTokensBalance({ connector, partyId, tokens, }) {
29947
+ const ledgerEnd = await connector.ledgerApi({
29948
+ requestMethod: "get",
29949
+ resource: "/v2/state/ledger-end",
29950
+ });
29951
+ const activeContracts = await connector.ledgerApi({
29952
+ requestMethod: "post",
29953
+ resource: "/v2/state/active-contracts",
29954
+ body: buildHoldingsAcsRequestBody(partyId, String(ledgerEnd.offset)),
29955
+ });
29956
+ const grouped = groupCantonHoldingBalances(activeContracts);
29957
+ return tokens.map((token) => {
29958
+ const instrument = token.originalAddress
29959
+ ? parseCantonInstrument(token.originalAddress)
29960
+ : null;
29961
+ return {
29962
+ ...token,
29963
+ balance: instrument
29964
+ ? grouped[cantonInstrumentKey(instrument)] ?? "0"
29965
+ : "0",
29966
+ };
29967
+ });
29968
+ }
29445
29969
  /**
29446
29970
  * Returns a promise that resolves when the given promise resolves or after the given timeout
29447
29971
  * @param ms - timeout in milliseconds
@@ -29626,9 +30150,29 @@ const useStellarBalance = ({ userAddress, chain, enabled, token, refreshInterval
29626
30150
  });
29627
30151
  return { balance, isLoading };
29628
30152
  };
30153
+ const useCantonBalance = ({ chain, token, userAddress, enabled = true, refreshIntervalMs = DEFAULT_REFRESH_INTERVAL_MS$1, }) => {
30154
+ const cantonConnector = useWalletStore((store) => store.connectedWalletsByChainType[ChainType.CANTON]?.wallet?.connector);
30155
+ const { data: balance = "0", isLoading } = useQuery({
30156
+ queryKey: keys().balance(chain?.chainId, token?.address, userAddress),
30157
+ queryFn: async () => {
30158
+ if (!cantonConnector || !userAddress || !token)
30159
+ return "0";
30160
+ return getCantonTokenBalance(userAddress, token, cantonConnector);
30161
+ },
30162
+ enabled: enabled &&
30163
+ !!cantonConnector &&
30164
+ !!userAddress &&
30165
+ !!token &&
30166
+ chain?.chainType === ChainType.CANTON &&
30167
+ isCantonAddressValid(userAddress),
30168
+ refetchInterval: refreshIntervalMs,
30169
+ retry: 2,
30170
+ });
30171
+ return { balance, isLoading };
30172
+ };
29629
30173
 
29630
30174
  function useNativeTokenForChain(chain) {
29631
- const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, } = useSquidTokens();
30175
+ const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, cantonTokens, } = useSquidTokens();
29632
30176
  const getTokensForChainType = () => {
29633
30177
  if (!chain?.chainType)
29634
30178
  return [];
@@ -29647,6 +30191,8 @@ function useNativeTokenForChain(chain) {
29647
30191
  return xrplTokens;
29648
30192
  case ChainType.STELLAR:
29649
30193
  return stellarTokens;
30194
+ case ChainType.CANTON:
30195
+ return cantonTokens;
29650
30196
  }
29651
30197
  };
29652
30198
  const nativeTokenForChainType = useMemo(() => {
@@ -29828,6 +30374,24 @@ const useStellarNativeBalance = ({ address, chain, }) => {
29828
30374
  isLoading,
29829
30375
  };
29830
30376
  };
30377
+ const useCantonNativeBalance = ({ address, chain, }) => {
30378
+ const { nativeToken } = useNativeTokenForChain(chain);
30379
+ const { balance: rawBalance, isLoading } = useCantonBalance({
30380
+ chain,
30381
+ token: nativeToken,
30382
+ userAddress: address,
30383
+ enabled: chain?.chainType === ChainType.CANTON,
30384
+ });
30385
+ const balance = useMemo(() => {
30386
+ if (nativeToken?.decimals && rawBalance) {
30387
+ return {
30388
+ decimals: nativeToken.decimals,
30389
+ value: parseToBigInt(rawBalance, nativeToken.decimals),
30390
+ };
30391
+ }
30392
+ }, [nativeToken?.decimals, rawBalance]);
30393
+ return { balance, isLoading };
30394
+ };
29831
30395
  const useNativeBalance = (chain) => {
29832
30396
  const { connectedAddresses } = useWallet();
29833
30397
  const { data: cosmosAddressForChain } = useCosmosForChain(chain);
@@ -29858,6 +30422,10 @@ const useNativeBalance = (chain) => {
29858
30422
  address: connectedAddresses[ChainType.STELLAR],
29859
30423
  chain,
29860
30424
  });
30425
+ const { balance: nativeCantonBalance, isLoading: isCantonLoading } = useCantonNativeBalance({
30426
+ address: connectedAddresses[ChainType.CANTON],
30427
+ chain,
30428
+ });
29861
30429
  const { nativeBalance, nativeBalanceFormatted } = useMemo(() => {
29862
30430
  let balance;
29863
30431
  switch (chain?.chainType) {
@@ -29881,6 +30449,10 @@ const useNativeBalance = (chain) => {
29881
30449
  break;
29882
30450
  case ChainType.STELLAR:
29883
30451
  balance = nativeStellarBalance;
30452
+ break;
30453
+ case ChainType.CANTON:
30454
+ balance = nativeCantonBalance;
30455
+ break;
29884
30456
  }
29885
30457
  const balanceFormatted = !!balance
29886
30458
  ? formatBNToReadable(balance.value, balance.decimals)
@@ -29898,6 +30470,7 @@ const useNativeBalance = (chain) => {
29898
30470
  nativeSuiBalance,
29899
30471
  nativeXrplBalance,
29900
30472
  nativeStellarBalance,
30473
+ nativeCantonBalance,
29901
30474
  ]);
29902
30475
  const isLoading = useMemo(() => {
29903
30476
  if (!chain?.chainType)
@@ -29917,6 +30490,8 @@ const useNativeBalance = (chain) => {
29917
30490
  return isXrpLoading;
29918
30491
  case ChainType.STELLAR:
29919
30492
  return isStellarLoading;
30493
+ case ChainType.CANTON:
30494
+ return isCantonLoading;
29920
30495
  }
29921
30496
  }, [
29922
30497
  chain?.chainType,
@@ -29927,6 +30502,7 @@ const useNativeBalance = (chain) => {
29927
30502
  isSuiLoading,
29928
30503
  isXrpLoading,
29929
30504
  isStellarLoading,
30505
+ isCantonLoading,
29930
30506
  ]);
29931
30507
  return { nativeBalance, nativeBalanceFormatted, isLoading };
29932
30508
  };
@@ -30141,7 +30717,7 @@ function hederaWalletConnect(parameters) {
30141
30717
  const optionalChains = config.chains.map((x) => x.id);
30142
30718
  if (!optionalChains.length)
30143
30719
  return;
30144
- const { EthereumProvider } = await import('./index.es-Bot12hgd.js');
30720
+ const { EthereumProvider } = await import('./index.es-DwtZr7bN.js');
30145
30721
  const rawProvider = await EthereumProvider.init({
30146
30722
  ...restParameters,
30147
30723
  disableProviderPing: true,
@@ -30346,6 +30922,7 @@ const useSigner = ({ chain }) => {
30346
30922
  const { signer: suiSigner } = useSuiContext();
30347
30923
  const { signer: xrplSigner } = useXrplContext();
30348
30924
  const { signer: stellarSigner } = useStellarContext();
30925
+ const { signer: cantonSigner } = useCantonContext();
30349
30926
  const isEvmSignerReady = !!evmSigner;
30350
30927
  const isSolanaSignerReady = !!solanaSigner;
30351
30928
  const isCosmosSignerReady = !!cosmosSigner;
@@ -30353,6 +30930,7 @@ const useSigner = ({ chain }) => {
30353
30930
  const isSuiSignerReady = !!suiSigner;
30354
30931
  const isXrplSignerReady = !!xrplSigner;
30355
30932
  const isStellarSignerReady = !!stellarSigner;
30933
+ const isCantonSignerReady = !!cantonSigner;
30356
30934
  const isSignerReady = useMemo(() => {
30357
30935
  if (!chain?.chainType)
30358
30936
  return false;
@@ -30371,6 +30949,8 @@ const useSigner = ({ chain }) => {
30371
30949
  return isXrplSignerReady;
30372
30950
  case ChainType.STELLAR:
30373
30951
  return isStellarSignerReady;
30952
+ case ChainType.CANTON:
30953
+ return isCantonSignerReady;
30374
30954
  }
30375
30955
  }, [
30376
30956
  chain?.chainType,
@@ -30381,6 +30961,7 @@ const useSigner = ({ chain }) => {
30381
30961
  isSuiSignerReady,
30382
30962
  isXrplSignerReady,
30383
30963
  isStellarSignerReady,
30964
+ isCantonSignerReady,
30384
30965
  ]);
30385
30966
  return {
30386
30967
  isSignerReady,
@@ -30391,6 +30972,7 @@ const useSigner = ({ chain }) => {
30391
30972
  suiSigner,
30392
30973
  xrplSigner,
30393
30974
  stellarSigner,
30975
+ cantonSigner,
30394
30976
  };
30395
30977
  };
30396
30978
 
@@ -30726,10 +31308,10 @@ function useStellarTrustLine({ address, chain, token, amount }) {
30726
31308
  if (!amount) {
30727
31309
  throw new Error("Amount is required");
30728
31310
  }
30729
- const limitBn = BigNumber$1(trustLineQuery.data?.limit || "0");
30730
- const balanceBn = BigNumber$1(trustLineQuery.data?.balance || "0");
31311
+ const limitBn = BigNumber(trustLineQuery.data?.limit || "0");
31312
+ const balanceBn = BigNumber(trustLineQuery.data?.balance || "0");
30731
31313
  const availableAllowanceBn = limitBn.minus(balanceBn);
30732
- const amountBn = BigNumber$1(formatBNToReadable(amount, token.decimals));
31314
+ const amountBn = BigNumber(formatBNToReadable(amount, token.decimals));
30733
31315
  return availableAllowanceBn.gte(amountBn);
30734
31316
  },
30735
31317
  enabled: !!address &&
@@ -30820,21 +31402,21 @@ const useSendTransactionStore = create((set, get) => ({
30820
31402
 
30821
31403
  const useDepositAddressStore = create((set) => ({
30822
31404
  deposit: null,
30823
- isEnabled: false,
31405
+ selectedPaymentMethod: "connectedWallet",
30824
31406
  setDeposit: (data) => {
30825
31407
  set({ deposit: data });
30826
31408
  },
30827
- toggleDepositFlow: (enabled) => {
30828
- set({ isEnabled: enabled });
31409
+ setPaymentMethod: (method) => {
31410
+ set({ selectedPaymentMethod: method });
30829
31411
  },
30830
31412
  }));
30831
31413
 
30832
31414
  function useDepositAddress(squidRoute) {
30833
- const { isEnabled, depositAddress } = useDepositAddressStore((state) => ({
30834
- isEnabled: state.isEnabled,
31415
+ const { selectedPaymentMethod, depositAddress } = useDepositAddressStore((state) => ({
31416
+ selectedPaymentMethod: state.selectedPaymentMethod,
30835
31417
  depositAddress: state.deposit?.depositAddress,
30836
31418
  }));
30837
- const { setDeposit, toggleDepositFlow, deposit } = useDepositAddressStore();
31419
+ const { setDeposit, setPaymentMethod, deposit } = useDepositAddressStore();
30838
31420
  const { squid } = useSquidStore();
30839
31421
  const { fromChain } = useSwap();
30840
31422
  const isAvailableAsPaymentMethod = useMemo(() => {
@@ -30843,41 +31425,55 @@ function useDepositAddress(squidRoute) {
30843
31425
  const chainsSupportingDepositAddress = [
30844
31426
  CHAIN_IDS.BITCOIN,
30845
31427
  CHAIN_IDS.SOLANA,
31428
+ CHAIN_IDS.CANTON,
30846
31429
  ];
30847
31430
  return chainsSupportingDepositAddress.includes(fromChain.chainId);
30848
31431
  }, [fromChain?.chainId]);
30849
- const swapWillGenerateDepositAddress = useMemo(() => {
30850
- return (squidRoute?.transactionRequest?.type ===
30851
- SquidDataType.ChainflipDepositAddress);
30852
- }, [squidRoute?.transactionRequest?.type]);
30853
- const enable = useCallback(() => {
30854
- toggleDepositFlow(true);
30855
- }, [toggleDepositFlow]);
30856
- const disable = useCallback(() => {
30857
- toggleDepositFlow(false);
30858
- }, [toggleDepositFlow]);
31432
+ const routeProvidesDirectDepositAddress = !!squidRoute?.transactionRequest &&
31433
+ isDepositAddressDirectTransferRoute(squidRoute.transactionRequest);
31434
+ const swapWillGenerateDepositAddress = isChainflipDepositRoute(squidRoute) || routeProvidesDirectDepositAddress;
31435
+ const paymentMethod = isAvailableAsPaymentMethod
31436
+ ? selectedPaymentMethod
31437
+ : "connectedWallet";
31438
+ const routeSupportsDepositAddress = !squidRoute?.transactionRequest || swapWillGenerateDepositAddress;
31439
+ const isDepositAddressActive = paymentMethod === "depositAddress" && routeSupportsDepositAddress;
30859
31440
  const closeDepositChannel = useCallback(() => {
30860
- toggleDepositFlow(false);
30861
31441
  setDeposit(null);
30862
- }, [toggleDepositFlow, setDeposit]);
31442
+ }, [setDeposit]);
30863
31443
  const getRouteWithDeposit = useMutation(async ({ route }) => {
30864
- if (!squid)
30865
- throw new Error("Squid SDK not initialized");
30866
- const depositAddressResponse = (await squid.executeRoute({
30867
- signer: {},
30868
- route,
30869
- }));
30870
- setDeposit(depositAddressResponse);
30871
- return {
30872
- depositAddress: depositAddressResponse,
30873
- };
31444
+ if (!squid || !route.transactionRequest) {
31445
+ throw new Error("Missing required params");
31446
+ }
31447
+ if (isChainflipDepositRoute(route)) {
31448
+ const depositAddressResponse = (await squid.executeRoute({
31449
+ signer: {},
31450
+ route,
31451
+ }));
31452
+ setDeposit({
31453
+ amount: depositAddressResponse.amount,
31454
+ depositAddress: depositAddressResponse.depositAddress,
31455
+ statusTrackingId: depositAddressResponse.chainflipStatusTrackingId,
31456
+ });
31457
+ return;
31458
+ }
31459
+ else if (isDepositAddressDirectTransferRoute(route.transactionRequest)) {
31460
+ // Canton case
31461
+ const orderHash = route.transactionRequest.data;
31462
+ setDeposit({
31463
+ amount: route.params.fromAmount ?? "",
31464
+ depositAddress: route.transactionRequest.target,
31465
+ statusTrackingId: orderHash,
31466
+ memo: orderHash,
31467
+ });
31468
+ return;
31469
+ }
30874
31470
  });
30875
31471
  return {
30876
- isEnabled,
31472
+ paymentMethod,
31473
+ isDepositAddressActive,
30877
31474
  isAvailableAsPaymentMethod,
30878
31475
  swapWillGenerateDepositAddress,
30879
- enable,
30880
- disable,
31476
+ setPaymentMethod,
30881
31477
  getRouteWithDeposit,
30882
31478
  depositAddress,
30883
31479
  closeDepositChannel,
@@ -30909,8 +31505,9 @@ const useUrlSwapParams = () => {
30909
31505
 
30910
31506
  const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, queryOptions, }) => {
30911
31507
  const { evmChains, cosmosChains, suiChains, xrplChains, stellarChains } = useSquidChains(direction);
30912
- const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, } = useSquidTokens(direction);
31508
+ const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, cantonTokens, } = useSquidTokens(direction);
30913
31509
  const { keplrTypeWallet } = useCosmosContext();
31510
+ const cantonConnector = useWalletStore((store) => store.connectedWalletsByChainType[ChainType.CANTON]?.wallet?.connector);
30914
31511
  const placeholderData = useMemo(() => {
30915
31512
  const tokens = {
30916
31513
  [ChainType.EVM]: evmTokens.map((t) => ({ ...t, balance: "0" })),
@@ -30920,6 +31517,7 @@ const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, qu
30920
31517
  [ChainType.SUI]: suiTokens.map((t) => ({ ...t, balance: "0" })),
30921
31518
  [ChainType.XRPL]: xrplTokens.map((t) => ({ ...t, balance: "0" })),
30922
31519
  [ChainType.STELLAR]: stellarTokens.map((t) => ({ ...t, balance: "0" })),
31520
+ [ChainType.CANTON]: cantonTokens.map((t) => ({ ...t, balance: "0" })),
30923
31521
  };
30924
31522
  if (!chainType) {
30925
31523
  // Return all tokens with zero balance
@@ -30941,6 +31539,7 @@ const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, qu
30941
31539
  suiTokens,
30942
31540
  xrplTokens,
30943
31541
  stellarTokens,
31542
+ cantonTokens,
30944
31543
  ]);
30945
31544
  const isQueryEnabled = useMemo(() => {
30946
31545
  // Respect the queryOptions.enabled override if provided
@@ -30963,6 +31562,8 @@ const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, qu
30963
31562
  return xrplTokens.length > 0;
30964
31563
  case ChainType.STELLAR:
30965
31564
  return stellarTokens.length > 0;
31565
+ case ChainType.CANTON:
31566
+ return cantonTokens.length > 0;
30966
31567
  }
30967
31568
  }, [
30968
31569
  chainType,
@@ -30975,6 +31576,7 @@ const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, qu
30975
31576
  suiTokens.length,
30976
31577
  xrplTokens.length,
30977
31578
  stellarTokens.length,
31579
+ cantonTokens.length,
30978
31580
  ]);
30979
31581
  const query = useQuery(keys().allTokensBalance(address, chainType, direction), async () => {
30980
31582
  // Return zero balances if no address
@@ -31014,6 +31616,15 @@ const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, qu
31014
31616
  case ChainType.STELLAR:
31015
31617
  fetchedTokens = await getAllStellarTokensBalance(address, stellarTokens, stellarChains);
31016
31618
  break;
31619
+ case ChainType.CANTON:
31620
+ fetchedTokens = cantonConnector
31621
+ ? await getAllCantonTokensBalance({
31622
+ connector: cantonConnector,
31623
+ partyId: address,
31624
+ tokens: cantonTokens,
31625
+ })
31626
+ : placeholderData.tokens;
31627
+ break;
31017
31628
  default:
31018
31629
  fetchedTokens = placeholderData.tokens;
31019
31630
  break;
@@ -31084,6 +31695,12 @@ const useAllConnectedWalletBalances = ({ direction, queryOptions = {
31084
31695
  direction,
31085
31696
  queryOptions,
31086
31697
  });
31698
+ const cantonBalancesQuery = useAllTokensWithBalanceForChainType({
31699
+ chainType: ChainType.CANTON,
31700
+ address: connectedAddresses?.[ChainType.CANTON],
31701
+ direction,
31702
+ queryOptions,
31703
+ });
31087
31704
  // Create a map of chain type to balance query results
31088
31705
  const balanceQueries = useMemo(() => ({
31089
31706
  [ChainType.EVM]: evmBalancesQuery,
@@ -31093,6 +31710,7 @@ const useAllConnectedWalletBalances = ({ direction, queryOptions = {
31093
31710
  [ChainType.SUI]: suiBalancesQuery,
31094
31711
  [ChainType.XRPL]: xrplBalancesQuery,
31095
31712
  [ChainType.STELLAR]: stellarBalancesQuery,
31713
+ [ChainType.CANTON]: cantonBalancesQuery,
31096
31714
  }), [
31097
31715
  evmBalancesQuery,
31098
31716
  cosmosBalancesQuery,
@@ -31101,6 +31719,7 @@ const useAllConnectedWalletBalances = ({ direction, queryOptions = {
31101
31719
  suiBalancesQuery,
31102
31720
  xrplBalancesQuery,
31103
31721
  stellarBalancesQuery,
31722
+ cantonBalancesQuery,
31104
31723
  ]);
31105
31724
  // Combine all tokens from different chains
31106
31725
  const allTokens = useMemo(() => Object.values(balanceQueries).flatMap((query) => query.data?.tokens ?? []), [balanceQueries]);
@@ -31111,9 +31730,9 @@ const useAllConnectedWalletBalances = ({ direction, queryOptions = {
31111
31730
  const balanceStr = query?.data?.totalUsdBalance;
31112
31731
  if (!balanceStr)
31113
31732
  return total;
31114
- const balance = new BigNumber$1(balanceStr);
31733
+ const balance = new BigNumber(balanceStr);
31115
31734
  return balance.isFinite() ? total.plus(balance) : total;
31116
- }, new BigNumber$1(0))
31735
+ }, new BigNumber(0))
31117
31736
  .toString();
31118
31737
  }, [balanceQueries]);
31119
31738
  // Aggregate loading states
@@ -31182,6 +31801,12 @@ const useMultiChainBalance = ({ chain, token, userAddress, enabled = true, }) =>
31182
31801
  userAddress,
31183
31802
  enabled: chain?.chainType === ChainType.STELLAR && enabled,
31184
31803
  });
31804
+ const { balance: cantonBalance } = useCantonBalance({
31805
+ chain,
31806
+ token,
31807
+ userAddress,
31808
+ enabled: chain?.chainType === ChainType.CANTON && enabled,
31809
+ });
31185
31810
  const balance = useMemo(() => {
31186
31811
  if (!chain?.chainType)
31187
31812
  return "0";
@@ -31200,6 +31825,8 @@ const useMultiChainBalance = ({ chain, token, userAddress, enabled = true, }) =>
31200
31825
  return xrplBalance;
31201
31826
  case ChainType.STELLAR:
31202
31827
  return stellarBalance;
31828
+ case ChainType.CANTON:
31829
+ return cantonBalance;
31203
31830
  }
31204
31831
  }, [
31205
31832
  chain?.chainType,
@@ -31210,6 +31837,7 @@ const useMultiChainBalance = ({ chain, token, userAddress, enabled = true, }) =>
31210
31837
  suiBalance,
31211
31838
  xrplBalance,
31212
31839
  stellarBalance,
31840
+ cantonBalance,
31213
31841
  ]);
31214
31842
  return { balance };
31215
31843
  };
@@ -31679,7 +32307,7 @@ const calculateEstimateResults = ({ squidRoute, tokens, fromChain, toChain, coll
31679
32307
  });
31680
32308
  // gas fees + fromAmount (if fromToken is gas token)
31681
32309
  const totalGasBalanceNeeded = networkFeesWei +
31682
- BigInt(chainFeeParams?.fromTokenPaysGasFees ? fromAmount ?? 0 : 0);
32310
+ BigInt(chainFeeParams?.fromTokenPaysGasFees ? (fromAmount ?? 0) : 0);
31683
32311
  const gasBalanceNeeded = gasToken
31684
32312
  ? formatBNToReadable(totalGasBalanceNeeded, gasToken.decimals)
31685
32313
  : undefined;
@@ -31856,7 +32484,7 @@ function useEstimateSendTransaction({ chain, token, amount, balance, from, }) {
31856
32484
  return undefined;
31857
32485
  // gas fees + fromAmount (if fromToken is gas token)
31858
32486
  const totalGasBalanceNeeded = estimatedGas +
31859
- parseToBigInt(chainFeeParams?.fromTokenPaysGasFees ? amount ?? "0" : "0", token.decimals);
32487
+ parseToBigInt(chainFeeParams?.fromTokenPaysGasFees ? (amount ?? "0") : "0", token.decimals);
31860
32488
  return formatBNToReadable(totalGasBalanceNeeded, gasToken.decimals);
31861
32489
  }, [
31862
32490
  amount,
@@ -32308,6 +32936,9 @@ function useSendTransaction({ to, amount, token, chain, }) {
32308
32936
  chain,
32309
32937
  });
32310
32938
  break;
32939
+ case ChainType.CANTON: {
32940
+ throw new Error("Not implemented");
32941
+ }
32311
32942
  }
32312
32943
  return {
32313
32944
  amount,
@@ -32511,6 +33142,8 @@ async function getSendTransactionStatus({ chain, txHash, }) {
32511
33142
  txHash,
32512
33143
  chain,
32513
33144
  });
33145
+ case ChainType.CANTON:
33146
+ throw new Error("Not implemented");
32514
33147
  }
32515
33148
  }
32516
33149
 
@@ -32534,7 +33167,7 @@ const useHistory = (txType) => {
32534
33167
  fromChain: tx.params.fromChain,
32535
33168
  fromToken: tx.params.fromToken,
32536
33169
  fromAddress: tx.params.fromAddress,
32537
- fromAmount: tx.params.fromAmount,
33170
+ fromAmount: tx.params.fromAmount ?? "",
32538
33171
  toChain: tx.params.toChain,
32539
33172
  toToken: tx.params.toToken,
32540
33173
  toAddress: tx.params.toAddress,
@@ -32962,6 +33595,129 @@ const useApproval = ({ squidRoute, }) => {
32962
33595
  };
32963
33596
  };
32964
33597
 
33598
+ const useSwapStatusQuery = ({ transaction, retry = 25, refetchOnWindowFocus = "always", enabled = true, onStatus, onEndStatus, onNotFound, onError, }) => {
33599
+ const config = useConfigStore((state) => state.config);
33600
+ const isInitialized = useConfigStore((state) => state.isInitialized);
33601
+ const [isTransactionComplete, setIsTransactionComplete] = useState(false);
33602
+ const [refetchInterval, setRefetchInterval] = useState(getSwapTxStatusRefetchInterval(transaction));
33603
+ const { getChainType } = useSquidChains();
33604
+ const fetchTransactionStatusWithLatestConfig = useCallback(async () => {
33605
+ const latestConfig = useConfigStore.getState().config;
33606
+ return fetchSwapTransactionStatus({
33607
+ transaction,
33608
+ integratorId: latestConfig.integratorId,
33609
+ apiUrl: latestConfig.apiUrl,
33610
+ });
33611
+ }, [transaction]);
33612
+ const transactionStatusQuery = useQuery(keys().swapTransactionStatus(transaction?.transactionId), fetchTransactionStatusWithLatestConfig, {
33613
+ enabled: enabled &&
33614
+ transaction?.transactionId !== "0" &&
33615
+ !!transaction?.transactionId &&
33616
+ !!transaction.fromAddress &&
33617
+ !!config.apiUrl &&
33618
+ transaction !== undefined &&
33619
+ !isTransactionComplete &&
33620
+ isInitialized,
33621
+ refetchInterval(statusResponse) {
33622
+ if (statusResponse &&
33623
+ transactionEndStatuses.includes(getTransactionStatus(statusResponse) ?? "")) {
33624
+ return false;
33625
+ }
33626
+ return refetchInterval;
33627
+ },
33628
+ retryDelay: getChainType(transaction?.fromChain) === ChainType.COSMOS ? 5000 : 3000,
33629
+ retry: getChainType(transaction?.fromChain) === ChainType.COSMOS ? 6 : retry,
33630
+ refetchOnWindowFocus,
33631
+ onSuccess: (statusResponse) => {
33632
+ WidgetEvents.getInstance().dispatchSwapStatus(statusResponse.squidTransactionStatus ?? "");
33633
+ onStatus?.({
33634
+ status: getTransactionStatus(statusResponse) ?? "",
33635
+ statusResponse,
33636
+ });
33637
+ const endStatus = getTransactionEndStatus({ statusResponse });
33638
+ if (endStatus) {
33639
+ setIsTransactionComplete(true);
33640
+ onEndStatus?.({ status: endStatus, statusResponse });
33641
+ }
33642
+ },
33643
+ onError: (error) => {
33644
+ if (is404Error(error.cause)) {
33645
+ onNotFound?.();
33646
+ return;
33647
+ }
33648
+ setRefetchInterval(-1);
33649
+ setIsTransactionComplete(true);
33650
+ onError?.();
33651
+ },
33652
+ });
33653
+ return {
33654
+ transactionStatusQuery,
33655
+ };
33656
+ };
33657
+
33658
+ // Statuses that indicate the source deposit has been received
33659
+ // and the swap is now progressing.
33660
+ const sourceReceivedStatuses = [
33661
+ // Chainflip
33662
+ "DEPOSIT_RECEIVED",
33663
+ "BROADCAST_REQUESTED",
33664
+ "COMPLETE",
33665
+ "SWAPPING",
33666
+ // Canton (Squid Intents)
33667
+ "awaiting",
33668
+ "success",
33669
+ ];
33670
+ /**
33671
+ * Tracks a deposit address intent before it becomes a persisted swap history item.
33672
+ *
33673
+ * Once the source deposit is received, it registers the transaction in the transaction
33674
+ * and history stores, then signals the view via `onReceived` to navigate.
33675
+ */
33676
+ const useDepositTransactionStatus = ({ transaction, route, retry = 25, refetchOnWindowFocus = "always", enabled = true, onReceived, }) => {
33677
+ const { fromChain, toChain } = useSwap();
33678
+ const { addSwapTransaction } = useHistory();
33679
+ const getTransaction = useTransactionStore((state) => state.getTransaction);
33680
+ const setTransactionStoreState = useTransactionStore((state) => state.setTransactionState);
33681
+ return useSwapStatusQuery({
33682
+ transaction,
33683
+ retry,
33684
+ refetchOnWindowFocus,
33685
+ enabled,
33686
+ onStatus: ({ status }) => {
33687
+ if (!sourceReceivedStatuses.includes(status))
33688
+ return;
33689
+ if (!transaction?.transactionId || !route?.transactionRequest)
33690
+ return;
33691
+ const { transactionId } = transaction;
33692
+ if (getTransaction(transactionId))
33693
+ return;
33694
+ useTransactionStore.setState({
33695
+ txLocalId: transactionId,
33696
+ currentTransaction: undefined,
33697
+ });
33698
+ const tx = {
33699
+ routeType: route.transactionRequest.type,
33700
+ fromChain,
33701
+ toChain,
33702
+ fromAddress: transaction.fromAddress,
33703
+ transactionId,
33704
+ transactionIdForStatus: transaction.transactionIdForStatus,
33705
+ quoteId: transaction.quoteId ?? "",
33706
+ status: TransactionStatus.ONGOING,
33707
+ sourceStatus: TransactionStatus.SUCCESS,
33708
+ timestamp: Date.now(),
33709
+ };
33710
+ setTransactionStoreState(transactionId, tx);
33711
+ addSwapTransaction({
33712
+ ...tx,
33713
+ params: route.params,
33714
+ estimate: route.estimate,
33715
+ });
33716
+ onReceived?.();
33717
+ },
33718
+ });
33719
+ };
33720
+
32965
33721
  const DEFAULT_PROVIDER_IMAGE_URL = "https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/providers/squid.webp";
32966
33722
  const AXELAR_PROVIDER_IMAGE_URL = "https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/providers/axelar.webp";
32967
33723
  const useEstimate = (squidRoute) => {
@@ -36008,6 +36764,342 @@ coin.DecProto = {
36008
36764
 
36009
36765
  } (tx));
36010
36766
 
36767
+ const vParty = (party) => ({ party });
36768
+ const vText = (text) => ({ text });
36769
+ const vNumeric = (numeric) => ({ numeric });
36770
+ const vContractId = (contractId) => ({
36771
+ contractId,
36772
+ });
36773
+ const vList = (elements) => ({
36774
+ list: { elements },
36775
+ });
36776
+ const vRecord = (fields) => ({
36777
+ record: { fields: fields.map(([label, value]) => ({ label, value })) },
36778
+ });
36779
+ const vTextMap = (entries) => ({ textMap: { entries } });
36780
+ const vTimestamp = (isoString) => ({
36781
+ timestamp: String(Math.floor(new Date(isoString).getTime() * 1000)),
36782
+ });
36783
+ function isRecord(value) {
36784
+ return typeof value === "object" && value !== null && !Array.isArray(value);
36785
+ }
36786
+ function normalizeChoiceContextValue(value) {
36787
+ if (typeof value === "string")
36788
+ return value;
36789
+ if (!isRecord(value) || typeof value.tag !== "string")
36790
+ return null;
36791
+ switch (value.tag) {
36792
+ case "AV_Text":
36793
+ case "AV_ContractId":
36794
+ return typeof value.value === "string"
36795
+ ? { tag: value.tag, value: value.value }
36796
+ : null;
36797
+ case "AV_Bool":
36798
+ return typeof value.value === "boolean"
36799
+ ? { tag: value.tag, value: value.value }
36800
+ : null;
36801
+ case "AV_List":
36802
+ if (!Array.isArray(value.value))
36803
+ return null;
36804
+ return {
36805
+ tag: value.tag,
36806
+ value: value.value.flatMap((entry) => {
36807
+ const normalized = normalizeChoiceContextValue(entry);
36808
+ return normalized ? [normalized] : [];
36809
+ }),
36810
+ };
36811
+ default: {
36812
+ const inner = value.value;
36813
+ if (typeof inner === "string" ||
36814
+ typeof inner === "number" ||
36815
+ typeof inner === "boolean" ||
36816
+ inner === null) {
36817
+ return { tag: value.tag, value: inner };
36818
+ }
36819
+ if (Array.isArray(inner)) {
36820
+ return {
36821
+ tag: value.tag,
36822
+ value: inner.flatMap((entry) => {
36823
+ const normalized = normalizeChoiceContextValue(entry);
36824
+ return normalized ? [normalized] : [];
36825
+ }),
36826
+ };
36827
+ }
36828
+ if (!isRecord(inner))
36829
+ return null;
36830
+ const normalizedObject = {};
36831
+ for (const [key, entry] of Object.entries(inner)) {
36832
+ if (typeof entry !== "string" &&
36833
+ typeof entry !== "number" &&
36834
+ typeof entry !== "boolean" &&
36835
+ entry !== null) {
36836
+ return null;
36837
+ }
36838
+ normalizedObject[key] = entry;
36839
+ }
36840
+ return { tag: value.tag, value: normalizedObject };
36841
+ }
36842
+ }
36843
+ }
36844
+ function stringifyChoiceContextValue(value) {
36845
+ return typeof value === "string" ? value : String(value);
36846
+ }
36847
+ function choiceContextValueToAnyValue(value) {
36848
+ if (typeof value === "string") {
36849
+ return {
36850
+ variant: { constructor: "AV_Text", value: vText(value) },
36851
+ };
36852
+ }
36853
+ switch (value.tag) {
36854
+ case "AV_ContractId":
36855
+ if (typeof value.value !== "string") {
36856
+ throw new TypeError("AV_ContractId values must be strings");
36857
+ }
36858
+ return {
36859
+ variant: { constructor: value.tag, value: vContractId(value.value) },
36860
+ };
36861
+ case "AV_Bool":
36862
+ if (typeof value.value !== "boolean") {
36863
+ throw new TypeError("AV_Bool values must be booleans");
36864
+ }
36865
+ return {
36866
+ variant: { constructor: value.tag, value: { bool: value.value } },
36867
+ };
36868
+ case "AV_List":
36869
+ if (!Array.isArray(value.value)) {
36870
+ throw new TypeError("AV_List values must be arrays");
36871
+ }
36872
+ return {
36873
+ variant: {
36874
+ constructor: value.tag,
36875
+ value: vList(value.value.map(choiceContextValueToAnyValue)),
36876
+ },
36877
+ };
36878
+ default:
36879
+ return {
36880
+ variant: {
36881
+ constructor: value.tag,
36882
+ value: vText(stringifyChoiceContextValue(value.value)),
36883
+ },
36884
+ };
36885
+ }
36886
+ }
36887
+
36888
+ /** Metadata key used by Splice token-standard transfers to carry our Squid orderhash memo. */
36889
+ const CANTON_MEMO_KEY = "splice.lfdecentralizedtrust.org/reason";
36890
+ /** Interface id for the transfer factory contract returned by the token registry. */
36891
+ const TRANSFER_FACTORY_INTERFACE_ID = "#splice-api-token-transfer-instruction-v1:Splice.Api.Token.TransferInstructionV1:TransferFactory";
36892
+ /** Choice exercised on the transfer factory to create the token-standard transfer. */
36893
+ const TRANSFER_FACTORY_CHOICE = "TransferFactory_Transfer";
36894
+ /** CIP-056 (non-Amulet) tokens expose a registrar parameterized by admin party. */
36895
+ const CIP056_REGISTRAR_BASE = "https://api.utilities.digitalasset.com/api/token-standard/v0/registrars";
36896
+ const TRANSFER_REQUESTED_AT_SKEW_MS = 60_000;
36897
+ const TRANSFER_EXECUTE_WINDOW_MS = 24 * 60 * 60 * 1000;
36898
+ function resolveCantonRegistryUrl(instrument) {
36899
+ if (instrument.id === CANTON_AMULET_INSTRUMENT_ID) {
36900
+ return CANTON_AMULET_REGISTRY_URL;
36901
+ }
36902
+ return `${CIP056_REGISTRAR_BASE}/${encodeURIComponent(instrument.admin)}`;
36903
+ }
36904
+ /**
36905
+ * Build the plain JSON arguments expected by the registry transfer-factory
36906
+ * endpoint before it adds choice context and disclosed contracts.
36907
+ */
36908
+ function buildTransferChoiceArgs({ sender, receiver, amount, instrument, inputHoldingCids, memo, nowMs, }) {
36909
+ return {
36910
+ expectedAdmin: instrument.admin,
36911
+ transfer: {
36912
+ sender,
36913
+ receiver,
36914
+ amount,
36915
+ instrumentId: { admin: instrument.admin, id: instrument.id },
36916
+ requestedAt: new Date(nowMs - TRANSFER_REQUESTED_AT_SKEW_MS).toISOString(),
36917
+ executeBefore: new Date(nowMs + TRANSFER_EXECUTE_WINDOW_MS).toISOString(),
36918
+ inputHoldingCids,
36919
+ meta: { values: { [CANTON_MEMO_KEY]: memo } },
36920
+ },
36921
+ extraArgs: { context: { values: {} }, meta: { values: {} } },
36922
+ };
36923
+ }
36924
+ /**
36925
+ * Canton's Holding contracts follow Bitcoin-style UTXOs model.
36926
+ *
36927
+ * Pick Holding contract ids covering `amount` for the instrument: prefer a
36928
+ * single exact-amount holding, else accumulate largest-first.
36929
+ */
36930
+ function selectInputHoldingCids(holdings, instrument, amount) {
36931
+ const spendableHoldings = holdings.filter((h) => !h.locked &&
36932
+ h.instrument.admin === instrument.admin &&
36933
+ h.instrument.id === instrument.id);
36934
+ const target = new BigNumber(amount);
36935
+ const exact = spendableHoldings.find((h) => new BigNumber(h.amount).eq(target));
36936
+ if (exact)
36937
+ return [exact.contractId];
36938
+ const sorted = [...spendableHoldings].sort((a, b) => new BigNumber(b.amount).comparedTo(new BigNumber(a.amount)));
36939
+ const selected = [];
36940
+ let sum = new BigNumber(0);
36941
+ for (const holding of sorted) {
36942
+ selected.push(holding.contractId);
36943
+ sum = sum.plus(holding.amount);
36944
+ if (sum.gte(target))
36945
+ break;
36946
+ }
36947
+ if (sum.lt(target)) {
36948
+ throw new Error("Insufficient Canton holdings to cover transfer amount");
36949
+ }
36950
+ return selected;
36951
+ }
36952
+ async function fetchInputHoldingCids(connector, party, instrument, amount) {
36953
+ const ledgerEnd = await connector.ledgerApi({
36954
+ requestMethod: "get",
36955
+ resource: "/v2/state/ledger-end",
36956
+ });
36957
+ const activeContracts = await connector.ledgerApi({
36958
+ requestMethod: "post",
36959
+ resource: "/v2/state/active-contracts",
36960
+ body: buildHoldingsAcsRequestBody(party, String(ledgerEnd.offset)),
36961
+ });
36962
+ return selectInputHoldingCids(parseCantonHoldings(activeContracts), instrument, amount);
36963
+ }
36964
+ /**
36965
+ * Ask the token registry for the transfer factory contract and extra context
36966
+ * required to exercise its transfer choice.
36967
+ */
36968
+ async function fetchTransferFactory(registryUrl, choiceArgs) {
36969
+ const response = await fetch(`${registryUrl}/registry/transfer-instruction/v1/transfer-factory`, {
36970
+ method: "POST",
36971
+ headers: { "Content-Type": "application/json" },
36972
+ body: JSON.stringify({
36973
+ choiceArguments: choiceArgs,
36974
+ excludeDebugFields: true,
36975
+ }),
36976
+ });
36977
+ if (!response.ok) {
36978
+ throw new Error(`Canton transfer-factory request failed (${response.status})`);
36979
+ }
36980
+ return response.json();
36981
+ }
36982
+ /**
36983
+ * Convert transfer choice args into strict Daml Value JSON for the wallet's
36984
+ * prepareExecute ExerciseCommand.
36985
+ */
36986
+ function buildPrepareChoiceArgument(choiceArgs) {
36987
+ const contextValues = Object.entries(choiceArgs.extraArgs.context?.values ?? {})
36988
+ .map(([key, value]) => {
36989
+ const normalized = normalizeChoiceContextValue(value);
36990
+ return normalized
36991
+ ? { key, value: choiceContextValueToAnyValue(normalized) }
36992
+ : undefined;
36993
+ })
36994
+ .filter((entry) => Boolean(entry));
36995
+ return vRecord([
36996
+ ["expectedAdmin", vParty(choiceArgs.expectedAdmin)],
36997
+ [
36998
+ "transfer",
36999
+ vRecord([
37000
+ ["sender", vParty(choiceArgs.transfer.sender)],
37001
+ ["receiver", vParty(choiceArgs.transfer.receiver)],
37002
+ ["amount", vNumeric(choiceArgs.transfer.amount)],
37003
+ [
37004
+ "instrumentId",
37005
+ vRecord([
37006
+ ["admin", vParty(choiceArgs.transfer.instrumentId.admin)],
37007
+ ["id", vText(choiceArgs.transfer.instrumentId.id)],
37008
+ ]),
37009
+ ],
37010
+ ["requestedAt", vTimestamp(choiceArgs.transfer.requestedAt)],
37011
+ ["executeBefore", vTimestamp(choiceArgs.transfer.executeBefore)],
37012
+ [
37013
+ "inputHoldingCids",
37014
+ vList(choiceArgs.transfer.inputHoldingCids.map(vContractId)),
37015
+ ],
37016
+ [
37017
+ "meta",
37018
+ vRecord([
37019
+ [
37020
+ "values",
37021
+ vTextMap(Object.entries(choiceArgs.transfer.meta.values).map(([key, value]) => ({ key, value: vText(value) }))),
37022
+ ],
37023
+ ]),
37024
+ ],
37025
+ ]),
37026
+ ],
37027
+ [
37028
+ "extraArgs",
37029
+ vRecord([
37030
+ ["context", vRecord([["values", vTextMap(contextValues)]])],
37031
+ ["meta", vRecord([["values", vTextMap([])]])],
37032
+ ]),
37033
+ ],
37034
+ ]);
37035
+ }
37036
+ /**
37037
+ * Convert a registry disclosed contract into the wallet submission shape,
37038
+ * dropping debug fields and entries without a usable createdEventBlob.
37039
+ */
37040
+ function toDisclosedContract(raw) {
37041
+ if (typeof raw.createdEventBlob !== "string")
37042
+ return null;
37043
+ return {
37044
+ createdEventBlob: raw.createdEventBlob,
37045
+ contractId: typeof raw.contractId === "string" ? raw.contractId : undefined,
37046
+ synchronizerId: typeof raw.synchronizerId === "string" ? raw.synchronizerId : undefined,
37047
+ };
37048
+ }
37049
+ /**
37050
+ * Build a Splice token-standard transfer of `amount` of `token` from `sender`
37051
+ * to `receiver`, carrying `memo`, ready to hand to a wallet's prepareExecute.
37052
+ * Returns the full prepareExecute params (commandId + commands + actAs +
37053
+ * disclosedContracts).
37054
+ */
37055
+ async function buildCantonTransfer(connector, { sender, receiver, amount, token, memo, nowMs, }) {
37056
+ if (!token.originalAddress) {
37057
+ throw new Error("Canton token originalAddress is required");
37058
+ }
37059
+ const instrument = parseCantonInstrument(token.originalAddress);
37060
+ if (!instrument) {
37061
+ throw new Error(`Invalid Canton token address: ${token.originalAddress}`);
37062
+ }
37063
+ const registryUrl = resolveCantonRegistryUrl(instrument);
37064
+ const inputHoldingCids = await fetchInputHoldingCids(connector, sender, instrument, amount);
37065
+ const choiceArgs = buildTransferChoiceArgs({
37066
+ sender,
37067
+ receiver,
37068
+ amount,
37069
+ instrument,
37070
+ inputHoldingCids,
37071
+ memo,
37072
+ nowMs,
37073
+ });
37074
+ const factory = await fetchTransferFactory(registryUrl, choiceArgs);
37075
+ const choiceContextData = factory.choiceContext.choiceContextData;
37076
+ if (!choiceContextData) {
37077
+ throw new Error("Transfer factory choice context is missing");
37078
+ }
37079
+ choiceArgs.extraArgs.context = choiceContextData;
37080
+ const disclosedContracts = (factory.choiceContext?.disclosedContracts ?? []).flatMap((raw) => {
37081
+ const disclosedContract = toDisclosedContract(raw);
37082
+ return disclosedContract ? [disclosedContract] : [];
37083
+ });
37084
+ // Command ID: client-supplied identifier used to deduplicate submissions
37085
+ const commandId = `canton-${memo}`;
37086
+ return {
37087
+ commandId,
37088
+ commands: [
37089
+ {
37090
+ ExerciseCommand: {
37091
+ templateId: TRANSFER_FACTORY_INTERFACE_ID,
37092
+ contractId: factory.factoryId,
37093
+ choice: TRANSFER_FACTORY_CHOICE,
37094
+ choiceArgument: buildPrepareChoiceArgument(choiceArgs),
37095
+ },
37096
+ },
37097
+ ],
37098
+ actAs: [sender],
37099
+ disclosedContracts,
37100
+ };
37101
+ }
37102
+
36011
37103
  const useExecuteTransaction = (squidRoute) => {
36012
37104
  const { fromChain, toChain, fromToken, toToken, isSameChain } = useSwap();
36013
37105
  // A route completes on source tx only if it's same-chain AND
@@ -36016,7 +37108,7 @@ const useExecuteTransaction = (squidRoute) => {
36016
37108
  !!fromChain &&
36017
37109
  !!squidRoute &&
36018
37110
  squidRoute.estimate.actions.every((a) => isActionCompletedOnSourceTx(a, fromChain.chainId));
36019
- const { evmSigner, cosmosSigner, solanaSigner, bitcoinSigner, suiSigner, xrplSigner, stellarSigner, } = useSigner({
37111
+ const { evmSigner, cosmosSigner, solanaSigner, bitcoinSigner, suiSigner, xrplSigner, stellarSigner, cantonSigner, } = useSigner({
36020
37112
  chain: fromChain,
36021
37113
  });
36022
37114
  const { findToken } = useSquidTokens();
@@ -36271,7 +37363,7 @@ const useExecuteTransaction = (squidRoute) => {
36271
37363
  });
36272
37364
  const swapMutationSolana = useMutation(async ({ id, route }) => {
36273
37365
  try {
36274
- if (!route) {
37366
+ if (!route?.transactionRequest) {
36275
37367
  throw new Error("Route is required");
36276
37368
  }
36277
37369
  if (!solanaSigner) {
@@ -36280,10 +37372,10 @@ const useExecuteTransaction = (squidRoute) => {
36280
37372
  if (!route.params.fromAddress || !route.params.toAddress) {
36281
37373
  throw new Error("From or to address is required");
36282
37374
  }
36283
- const isDirectTransfer = isDepositRoute(route);
37375
+ const isChainflipDirectTransfer = isChainflipDepositRoute(route);
36284
37376
  // Means it's a transfer to a deposit address
36285
37377
  // Instead of a Swap/Contract call using a DEX like Jupiter
36286
- if (isDirectTransfer) {
37378
+ if (isChainflipDirectTransfer) {
36287
37379
  // Get the deposit address from the squidRoute
36288
37380
  const depositData = useDepositAddressStore.getState().deposit;
36289
37381
  // Validate params
@@ -36291,7 +37383,7 @@ const useExecuteTransaction = (squidRoute) => {
36291
37383
  throw new Error("Deposit address is required");
36292
37384
  }
36293
37385
  const signature = await executeSolanaTransfer({
36294
- amount: BigInt(route.params.fromAmount),
37386
+ amount: BigInt(route.params.fromAmount ?? ""),
36295
37387
  target: depositData.depositAddress,
36296
37388
  signer: solanaSigner,
36297
37389
  connection: solanaConnection,
@@ -36301,7 +37393,7 @@ const useExecuteTransaction = (squidRoute) => {
36301
37393
  const txParams = setTransactionState({
36302
37394
  route,
36303
37395
  txHash,
36304
- transactionIdForStatus: depositData.chainflipStatusTrackingId,
37396
+ transactionIdForStatus: depositData.statusTrackingId,
36305
37397
  userAddress: sourceUserAddress,
36306
37398
  status: TransactionStatus.INITIAL_LOADING,
36307
37399
  sourceStatus: TransactionStatus.ONGOING,
@@ -36352,7 +37444,7 @@ const useExecuteTransaction = (squidRoute) => {
36352
37444
  }
36353
37445
  });
36354
37446
  const swapMutationBitcoin = useMutation(async ({ id, route }) => {
36355
- const { depositAddress, amount: sendAmount, chainflipStatusTrackingId, } = useDepositAddressStore.getState().deposit ?? {};
37447
+ const { depositAddress, amount: sendAmount, statusTrackingId, } = useDepositAddressStore.getState().deposit ?? {};
36356
37448
  if (!depositAddress) {
36357
37449
  throw new Error(`Invalid deposit address: ${depositAddress}`);
36358
37450
  }
@@ -36375,7 +37467,7 @@ const useExecuteTransaction = (squidRoute) => {
36375
37467
  txHash,
36376
37468
  // When bridging from Bitcoin we need to send the chainflipId to the status endpoint
36377
37469
  // instead of the Bitcoin transaction hash
36378
- transactionIdForStatus: chainflipStatusTrackingId,
37470
+ transactionIdForStatus: statusTrackingId,
36379
37471
  userAddress: sourceUserAddress,
36380
37472
  status: TransactionStatus.INITIAL_LOADING,
36381
37473
  sourceStatus: TransactionStatus.ONGOING,
@@ -36567,6 +37659,56 @@ const useExecuteTransaction = (squidRoute) => {
36567
37659
  const sentTransaction = await client.sendTransaction(signedTransaction);
36568
37660
  await client.waitForTransaction(sentTransaction.hash);
36569
37661
  }, {});
37662
+ const swapMutationCanton = useMutation(async ({ id, route }) => {
37663
+ if (!route?.transactionRequest) {
37664
+ throw new Error("Route is required");
37665
+ }
37666
+ if (!cantonSigner) {
37667
+ throw new Error("Canton signer is required");
37668
+ }
37669
+ if (!isDepositAddressDirectTransferRoute(route.transactionRequest)) {
37670
+ throw new Error("Invalid Canton route type");
37671
+ }
37672
+ const receiver = route.transactionRequest.target;
37673
+ const orderHash = route.transactionRequest.data;
37674
+ const fromAmount = route.params.fromAmount;
37675
+ const token = findToken(route.params.fromToken, route.params.fromChain);
37676
+ if (!sourceUserAddress || !fromAmount || !token) {
37677
+ throw new Error("Need all parameters");
37678
+ }
37679
+ const amount = formatBNToReadable(fromAmount, token.decimals);
37680
+ dispatchSignatureRequestEvent(route);
37681
+ const transferParams = await buildCantonTransfer(cantonSigner, {
37682
+ sender: sourceUserAddress,
37683
+ receiver,
37684
+ amount,
37685
+ token,
37686
+ memo: orderHash,
37687
+ nowMs: Date.now(),
37688
+ });
37689
+ const result = await cantonSigner.prepareExecuteAndWait(transferParams);
37690
+ const txHash = result.tx?.payload?.updateId ?? "";
37691
+ if (txHash) {
37692
+ resetQueriesAfterTxSigned();
37693
+ }
37694
+ WidgetEvents.getInstance().dispatchSwapExecuteCall(route, txHash);
37695
+ const txParams = setTransactionState({
37696
+ route,
37697
+ txHash: txHash,
37698
+ userAddress: sourceUserAddress,
37699
+ status: TransactionStatus.INITIAL_LOADING,
37700
+ sourceStatus: TransactionStatus.ONGOING,
37701
+ id,
37702
+ });
37703
+ if (txParams) {
37704
+ addSwapTransaction({
37705
+ ...txParams,
37706
+ params: route.params,
37707
+ estimate: route.estimate,
37708
+ });
37709
+ }
37710
+ return txHash;
37711
+ });
36570
37712
  const handleTransactionSuccess = useCallback((id) => {
36571
37713
  const currentTx = getTransaction(id);
36572
37714
  queryClient.invalidateQueries(getPrefixKey(QueryKeys.Balances));
@@ -36625,7 +37767,7 @@ const useExecuteTransaction = (squidRoute) => {
36625
37767
  if (!mutationParams.route?.transactionRequest) {
36626
37768
  throw new Error("Route is required");
36627
37769
  }
36628
- const sourceChain = findChain(mutationParams.route.params?.fromChain);
37770
+ const sourceChain = findChain(mutationParams.route.params.fromChain);
36629
37771
  if (!sourceChain)
36630
37772
  throw new Error("Could not find source chain");
36631
37773
  // After getting signature (if needed), continue with the swap flow
@@ -36651,6 +37793,9 @@ const useExecuteTransaction = (squidRoute) => {
36651
37793
  case ChainType.STELLAR: {
36652
37794
  return swapMutationStellar.mutateAsync(mutationParams);
36653
37795
  }
37796
+ case ChainType.CANTON: {
37797
+ return swapMutationCanton.mutateAsync(mutationParams);
37798
+ }
36654
37799
  default:
36655
37800
  throw new Error(`Swap mutation not implemented for chain type: ${sourceChain.chainType}`);
36656
37801
  }
@@ -36823,7 +37968,7 @@ refetchIntervalInBackground = false, refetchInterval = 30000, quoteOnly = true,
36823
37968
  const squid = useSquidStore((state) => state.squid);
36824
37969
  const fallbackAddress = useSwapRoutePersistStore((store) => store.swapRoute?.fallbackAddress);
36825
37970
  const depositRefundAddress = useSwapRoutePersistStore((store) => store.swapRoute?.depositRefundAddress);
36826
- const { isAvailableAsPaymentMethod, isEnabled: isDepositAddressEnabled } = useDepositAddress();
37971
+ const { isDepositAddressActive } = useDepositAddress();
36827
37972
  const getRouteMutation = useGetRoute();
36828
37973
  const { fromChain, toChain, fromPrice, destinationAddress: { address: destinationAddress } = {}, fromToken, toToken, } = useSwap();
36829
37974
  const { connectedAddress: { address: sourceConnectedAddress }, } = useMultiChainWallet(fromChain);
@@ -36831,8 +37976,8 @@ refetchIntervalInBackground = false, refetchInterval = 30000, quoteOnly = true,
36831
37976
  // Tokens will be sent to this address in case of swap failure
36832
37977
  //
36833
37978
  // If deposit address is not selected, we use the connected address as the source address instead
36834
- const sourceUserAddress = isDepositAddressEnabled && isAvailableAsPaymentMethod
36835
- ? depositRefundAddress ?? sourceConnectedAddress
37979
+ const sourceUserAddress = isDepositAddressActive
37980
+ ? (depositRefundAddress ?? sourceConnectedAddress)
36836
37981
  : sourceConnectedAddress;
36837
37982
  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), [
36838
37983
  fromChain?.chainId,
@@ -36976,94 +38121,50 @@ function useSendTransactionStatus({ chain, txHash, }) {
36976
38121
  * Fetch status of a Swap transaction
36977
38122
  */
36978
38123
  const useSwapTransactionStatus = ({ transaction, retry = 25, refetchOnWindowFocus = "always", enabled = true, }) => {
36979
- const config = useConfigStore((state) => state.config);
36980
- const isInitialized = useConfigStore((state) => state.isInitialized);
36981
38124
  const { replaceSwapTransactionStatus } = useHistory();
36982
38125
  const findTransaction = useHistoryStore((state) => state.findTransaction);
36983
- const [isTransactionComplete, setIsTransactionComplete] = useState(false);
36984
- const [refetchInterval, setRefetchInterval] = useState(getSwapTxStatusRefetchInterval(transaction));
36985
- const { getChainType } = useSquidChains();
36986
38126
  const currentHistoryItem = useMemo(() => findTransaction({
36987
38127
  transactionId: transaction?.transactionId,
36988
38128
  txType: HistoryTxType.SWAP,
36989
38129
  }), [findTransaction, transaction?.transactionId]);
36990
- /**
36991
- * Transaction status endpoint
36992
- * Squid api is using axelar endpoint and parsing the response
36993
- * @returns {StatusResponse} Status response
36994
- */
36995
- const fetchTransactionStatusWithLatestConfig = useCallback(async () => {
36996
- const latestConfig = useConfigStore.getState().config;
36997
- return fetchSwapTransactionStatus({
36998
- transaction,
36999
- integratorId: latestConfig.integratorId,
37000
- apiUrl: latestConfig.apiUrl,
37001
- });
37002
- }, [transaction]);
37003
- const transactionStatusQuery = useQuery(keys().swapTransactionStatus(transaction?.transactionId), fetchTransactionStatusWithLatestConfig, {
38130
+ const transactionStatusQuery = useSwapStatusQuery({
38131
+ transaction,
38132
+ retry,
38133
+ refetchOnWindowFocus,
37004
38134
  enabled: enabled &&
37005
- transaction?.transactionId !== "0" &&
37006
- !!transaction?.transactionId &&
37007
- !!transaction.fromAddress &&
37008
- !!config.apiUrl &&
37009
- transaction !== undefined &&
37010
- !isTransactionComplete &&
37011
- isInitialized &&
37012
38135
  !!currentHistoryItem &&
37013
38136
  !isHistoryTransactionEnded({
37014
38137
  data: currentHistoryItem?.data,
37015
38138
  txType: HistoryTxType.SWAP,
37016
38139
  }),
37017
- refetchInterval(statusResponse) {
37018
- // If the status response is something telling that the transaction
37019
- // is finished, then store transaction history state if success
37020
- // And return false to indicate refetcher to stop
37021
- if (statusResponse &&
37022
- transactionEndStatuses.includes(getTransactionStatus(statusResponse) ?? "")) {
37023
- return false;
37024
- }
37025
- return refetchInterval; // Had to handle a variable here because after onError, we want the interval to stop
38140
+ onEndStatus: ({ status, statusResponse }) => {
38141
+ if (!transaction?.transactionId)
38142
+ return;
38143
+ replaceSwapTransactionStatus({
38144
+ transactionId: transaction.transactionId,
38145
+ statusResponse,
38146
+ status,
38147
+ });
37026
38148
  },
37027
- // At the moment Cosmos indexing takes more time, so need more time between retries
37028
- retryDelay: getChainType(transaction?.fromChain) === ChainType.COSMOS ? 5000 : 3000,
37029
- retry: getChainType(transaction?.fromChain) === ChainType.COSMOS ? 6 : retry,
37030
- refetchOnWindowFocus,
37031
- onSuccess: (statusResponse) => {
37032
- // Dispatch event
37033
- WidgetEvents.getInstance().dispatchSwapStatus(statusResponse.squidTransactionStatus ?? "");
37034
- const endStatus = getTransactionEndStatus({ statusResponse });
37035
- if (endStatus && transaction?.transactionId) {
37036
- setIsTransactionComplete(true);
37037
- replaceSwapTransactionStatus({
37038
- transactionId: transaction.transactionId,
37039
- statusResponse,
37040
- status: endStatus,
37041
- });
37042
- }
38149
+ onNotFound: () => {
38150
+ if (!transaction?.transactionId)
38151
+ return;
38152
+ replaceSwapTransactionStatus({
38153
+ transactionId: transaction.transactionId,
38154
+ statusResponse: undefined,
38155
+ status: TransactionStatus.NOT_FOUND,
38156
+ });
37043
38157
  },
37044
- onError: (error) => {
37045
- // `fetchTransactionStatus` throws an error with a cause being an AxiosError
37046
- const is404 = is404Error(error.cause);
38158
+ onError: () => {
37047
38159
  if (!transaction?.transactionId)
37048
38160
  return;
37049
- if (is404) {
37050
- replaceSwapTransactionStatus({
37051
- transactionId: transaction.transactionId,
37052
- statusResponse: undefined,
37053
- status: TransactionStatus.NOT_FOUND,
37054
- });
37055
- }
37056
- else {
37057
- setRefetchInterval(-1);
37058
- setIsTransactionComplete(true);
37059
- replaceSwapTransactionStatus({
37060
- transactionId: transaction.transactionId,
37061
- statusResponse: undefined,
37062
- status: TransactionStatus.ERROR,
37063
- });
37064
- }
38161
+ replaceSwapTransactionStatus({
38162
+ transactionId: transaction.transactionId,
38163
+ statusResponse: undefined,
38164
+ status: TransactionStatus.ERROR,
38165
+ });
37065
38166
  },
37066
- });
38167
+ }).transactionStatusQuery;
37067
38168
  return {
37068
38169
  transactionStatusQuery,
37069
38170
  latestStatus: transactionStatusQuery.data
@@ -37374,10 +38475,10 @@ function useXrplTrustLine({ address, chain, token, amount }) {
37374
38475
  if (!amount) {
37375
38476
  throw new Error("Amount is required");
37376
38477
  }
37377
- const limitBn = BigNumber$1(trustLineQuery.data?.limit || "0");
37378
- const balanceBn = BigNumber$1(trustLineQuery.data?.balance || "0");
38478
+ const limitBn = BigNumber(trustLineQuery.data?.limit || "0");
38479
+ const balanceBn = BigNumber(trustLineQuery.data?.balance || "0");
37379
38480
  const availableAllowanceBn = limitBn.minus(balanceBn);
37380
- const amountBn = BigNumber$1(formatBNToReadable(amount, token.decimals));
38481
+ const amountBn = BigNumber(formatBNToReadable(amount, token.decimals));
37381
38482
  return availableAllowanceBn.gte(amountBn);
37382
38483
  },
37383
38484
  enabled: !!address &&
@@ -37462,8 +38563,10 @@ const SquidProvider = ({ children, config, placeholder, }) => {
37462
38563
  }
37463
38564
  if (assetsColorsResponse.status === "fulfilled") {
37464
38565
  useAssetsColorsStore.setState(assetsColorsResponse.value);
37465
- initializeSquidWithAssetsColors(squid, assetsColorsResponse.value);
37466
38566
  }
38567
+ initializeSquidData(squid, assetsColorsResponse.status === "fulfilled"
38568
+ ? assetsColorsResponse.value
38569
+ : undefined);
37467
38570
  const shouldResetSwapRouteStore =
37468
38571
  // reset swap route if specified in config
37469
38572
  !config?.loadPreviousStateFromLocalStorage ||
@@ -37495,8 +38598,8 @@ const SquidProvider = ({ children, config, placeholder, }) => {
37495
38598
  error instanceof Error;
37496
38599
  if (isBackendDown) {
37497
38600
  const maintenanceMessage = isAxios503Error
37498
- ? error.response?.data
37499
- ?.message ?? undefined
38601
+ ? (error.response?.data
38602
+ ?.message ?? undefined)
37500
38603
  : "Unable to connect to Squid. Please check your connection or try again later.";
37501
38604
  // Even with an error, we want wagmi to be defined so that we can display the maintenance mode layout
37502
38605
  // Create wagmi config with mainnet as fallback in maintenance mode
@@ -37531,14 +38634,15 @@ const SquidProvider = ({ children, config, placeholder, }) => {
37531
38634
  }, [initializeSdk]);
37532
38635
  return wagmiConfig ? (React.createElement(WagmiProvider, { reconnectOnMount: false, config: wagmiConfig },
37533
38636
  React.createElement(QueryClientProvider, { client: queryClient },
37534
- React.createElement(StellarProvider, null,
37535
- React.createElement(EvmProvider, null,
37536
- React.createElement(XrplProvider, null,
37537
- React.createElement(SuiProvider, null,
37538
- React.createElement(SolanaProvider, null,
37539
- React.createElement(BitcoinProvider, null,
37540
- React.createElement(CosmosProvider, null, children)))))))))) : (placeholder);
37541
- };
37542
-
37543
- export { useDepositAddress as $, AxelarStatusResponseType as A, useHederaTokenAssociations as B, CHAIN_IDS as C, DEFAULT_LOCALE as D, useKeyboardNavigation as E, useSquidQueryClient as F, useSquid as G, HistoryTxType as H, useStellarAccountActivation as I, useStellarTrustLine as J, useAddressBookStore as K, useAssetsColorsStore as L, useFavoriteTokensStore as M, Nr as N, useHistoryStore as O, useSendTransactionStore as P, QueryKeys as Q, useConfigStore as R, SquidStatusErrorType as S, TransactionErrorType as T, useSquidStore as U, useSwapRoutePersistStore as V, Wo as W, XamanXrplNetwork as X, useTransactionStore as Y, ConnectingWalletStatus as Z, useWalletStore as _, WindowWalletFlag as a, useGetOnrampPaymentTypes as a$, useSwap as a0, buildUrlSearchParamsFromSwapEvent as a1, parseInitialAssetsFromUrl as a2, useUrlSwapParams as a3, useAllConnectedWalletBalances as a4, useAllTokensWithBalanceForChainType as a5, useCosmosBalance as a6, useEvmBalance as a7, useMultiChainBalance as a8, useMultipleTokenPrices as a9, useSwapTransactionStatus as aA, useAvatar as aB, useHistory as aC, useDebouncedValue as aD, useAddToken as aE, useAutoConnect as aF, useEnsDataForAddress as aG, useEnsSearch as aH, useGnosisContext as aI, useIsSameAddressAndGnosisContext as aJ, useIntegratorContext as aK, useMultiChainWallet as aL, useSigner as aM, useWallet as aN, useWallets as aO, useXrplTrustLine as aP, TX_STATUS_CONSTANTS as aQ, FINAL_TRANSACTION_STATUSES as aR, useGetFiatQuote as aS, useGetOnRampConfig as aT, useExecuteFiatQuote as aU, useFiatOnRampTxStatus as aV, useFiatTransactions as aW, useCurrencyDetails as aX, useCountryDetails as aY, useAvailableQuotes as aZ, useRecommendedQuote as a_, useBitcoinNativeBalance as aa, useCosmosNativeBalance as ab, useEvmNativeBalance as ac, useNativeBalance as ad, useSolanaNativeBalance as ae, useStellarNativeBalance as af, useSuiNativeBalance as ag, useXrplNativeBalance as ah, useNativeTokenForChain as ai, useSingleTokenPrice as aj, useSourceChainGasToken as ak, useSquidTokens as al, useHistoricalData as am, useTokensData as an, useEstimateSendTransaction as ao, useSendTransaction as ap, useSendTransactionGas as aq, useAllTransactionsStatus as ar, useApproval as as, useEstimate as at, useEstimatePriceImpact as au, useExecuteTransaction as av, useGetRoute as aw, useGetRouteWrapper as ax, useRouteWarnings as ay, useSendTransactionStatus as az, chainTypeToZeroAddressMap as b, filterWagmiConnector as b$, useSuggestedFiatAmounts as b0, SquidProvider as b1, EnsService as b2, getXummClient as b3, isXamanXAppContext as b4, getQueryHeaders as b5, getStatusCode as b6, is404Error as b7, assetsBaseUrl as b8, shareSubgraphId as b9, fetchHighestBalanceToken as bA, getInitialOrDefaultTokenAddressForChain as bB, getInitialTokenAddressForChain as bC, filterTokensForDestination as bD, getInitialChainIdFromConfig as bE, getCosmosKey as bF, getKeysSettled as bG, getAllKeysForSupportedCosmosChains as bH, isCosmosAddressValid as bI, getCosmosSigningClient as bJ, getCosmosChainInfosObject as bK, connectCosmosWallet as bL, isFallbackAddressNeeded as bM, suggestChainOrThrow as bN, normalizeError as bO, transactionErrorCode as bP, isUserRejectionError as bQ, getTransactionError as bR, handleTransactionErrorEvents as bS, isSwapRouteError as bT, isStatusError as bU, createQuoteRequestParamsHash as bV, WidgetEvents as bW, EvmNetworkNotSupportedErrorCode as bX, addEthereumChain as bY, parseEvmAddress as bZ, formatEvmWallet as b_, sortTokensBySharedSubgraphIds as ba, getSupportedChainIdsForDirection as bb, filterChains as bc, filterTokens as bd, getTokenImage as be, getNewSwapParamsFromInput as bf, sortAllTokens as bg, findToken as bh, findNativeToken as bi, normalizeIbcAddress as bj, groupTokensBySymbol as bk, groupTokensByChainId as bl, filterViewableTokens as bm, getSecretNetworkBalances as bn, getTokenAssetsKey as bo, fetchAssetsColors as bp, initializeSquidWithAssetsColors as bq, isEmptyObject as br, normalizeTokenSymbol as bs, areTokenSymbolsCompatible as bt, isEvmosChain as bu, resolveChainIdFromAsset as bv, getConfigWithDefaults as bw, randomIntFromInterval as bx, getTokensForChain as by, getFirstAvailableChainId as bz, chainTypeToNativeTokenAddressMap as c, isHistoryTransactionPending as c$, waitForReceiptWithRetry as c0, getUserCountry as c1, getCountryData as c2, getCurrencyData as c3, adaptiveRound as c4, getSuggestedAmountsForCurrency as c5, HederaExtensionHelper as c6, convertHederaAccountIdToEvmAddress as c7, convertEvmAddressToHederaAccountId as c8, scaleHbarToWei as c9, isValidHorizonAsset as cA, formatTransactionHistoryDate as cB, getAxelarExplorerTxUrl as cC, getSourceExplorerTxUrl as cD, getMainExplorerUrl as cE, formatDistance as cF, formatSeconds as cG, formatSwapTxStatusResponseForStorage as cH, simplifyRouteAction as cI, fetchSwapTransactionStatus as cJ, compareTransactionIds as cK, isCoralBridgeAction as cL, isActionCompletedOnSourceTx as cM, sleep as cN, isDepositRoute as cO, isChainflipBridgeTransaction as cP, isOnChainTxData as cQ, getHistoryTransactionId as cR, getStepStatuses as cS, getHalfSuccessState as cT, getStepsInfos as cU, getSwapTxStatusRefetchInterval as cV, getSendTxStatusRefetchInterval as cW, chainflipMultihopBridgeType as cX, getBridgeType as cY, getTransactionStatus as cZ, getTransactionEndStatus as c_, scaleWeiToHbar as ca, parseToBigInt as cb, roundNumericValue as cc, formatUnitsRounded as cd, formatTokenAmount as ce, formatUsdAmount as cf, trimExtraDecimals as cg, getNumericValue as ch, cleanAmount as ci, convertTokenAmountToUSD as cj, convertUSDToTokenAmount as ck, calculateTotal24hChange as cl, getRouteExpiry as cm, searchTokens as cn, filterSolanaWallets as co, isSolanaAddressValid as cp, executeSolanaSwap as cq, executeSolanaTransfer as cr, isStellarAddressValid as cs, getStellarNetwork as ct, stellarAddressToScVal as cu, getStellarTrustLineAsset as cv, isStellarToken as cw, isStellarIssuedToken as cx, getStellarHorizonApiUrl as cy, isValidIssuedAsset as cz, definedInWindow as d, isHistoryTransactionFailed as d0, isHistoryTransactionWarning as d1, isHistoryTransactionEnded as d2, formatHash as d3, isWalletAddressValid as d4, redirectToExtensionsStore as d5, accessProperty as d6, populateWallets as d7, getDefaultChain as d8, sortWallets as d9, areSameAddress as da, sortAddressBook as db, calculateTotalUsdBalanceUSD as dc, addTokenToWallet as dd, isEvmChainNotSupportedError as de, getWalletSupportedChainTypes as df, getConnectorForChainType as dg, walletSupportsChainType as dh, connectWallet as di, cancelConnectWallet as dj, isProblematicConnector as dk, mergeWallets as dl, isXionSmartContractAddress as dm, isXrplAddressValid as dn, buildXrplTrustSetTx as dp, getXrplNetwork as dq, parseXrplPaymentTx as dr, parseXrplTokenAddress as ds, er as e, formatBNToReadable as f, DEFAULT_ROUTE_REFETCH_INTERVAL as g, destinationAddressResetValue as h, fallbackAddressResetValue as i, nativeCosmosTokenAddress as j, nativeEvmTokenAddress as k, nativeSolanaTokenAddress as l, nativeStellarTokenAddress as m, nativeBitcoinTokenAddress as n, nativeSuiTokenAddress as o, nativeXrplTokenAddress as p, CosmosProvider as q, SendTransactionStatus as r, TransactionStatus as s, useTrackSearchEmpty as t, useCosmosContext as u, useSquidChains as v, walletIconBaseUrl as w, useClient as x, useCosmosForChain as y, useHederaAccountActivation as z };
37544
- //# sourceMappingURL=index-Ypw6i6uY.js.map
38637
+ React.createElement(CantonProvider, null,
38638
+ React.createElement(StellarProvider, null,
38639
+ React.createElement(EvmProvider, null,
38640
+ React.createElement(XrplProvider, null,
38641
+ React.createElement(SuiProvider, null,
38642
+ React.createElement(SolanaProvider, null,
38643
+ React.createElement(BitcoinProvider, null,
38644
+ React.createElement(CosmosProvider, null, children))))))))))) : (placeholder);
38645
+ };
38646
+
38647
+ export { useDepositAddress as $, AxelarStatusResponseType as A, useHederaTokenAssociations as B, CHAIN_IDS as C, DEFAULT_LOCALE as D, useKeyboardNavigation as E, useSquidQueryClient as F, useSquid as G, HistoryTxType as H, useStellarAccountActivation as I, useStellarTrustLine as J, useAddressBookStore as K, useAssetsColorsStore as L, useFavoriteTokensStore as M, Nr as N, useHistoryStore as O, useSendTransactionStore as P, QueryKeys as Q, useConfigStore as R, SquidStatusErrorType as S, TransactionErrorType as T, useSquidStore as U, useSwapRoutePersistStore as V, Wo as W, XamanXrplNetwork as X, useTransactionStore as Y, ConnectingWalletStatus as Z, useWalletStore as _, WindowWalletFlag as a, useRecommendedQuote as a$, useSwap as a0, buildUrlSearchParamsFromSwapEvent as a1, parseInitialAssetsFromUrl as a2, useUrlSwapParams as a3, useAllConnectedWalletBalances as a4, useAllTokensWithBalanceForChainType as a5, useCosmosBalance as a6, useEvmBalance as a7, useMultiChainBalance as a8, useMultipleTokenPrices as a9, useSendTransactionStatus as aA, useSwapTransactionStatus as aB, useAvatar as aC, useHistory as aD, useDebouncedValue as aE, useAddToken as aF, useAutoConnect as aG, useEnsDataForAddress as aH, useEnsSearch as aI, useGnosisContext as aJ, useIsSameAddressAndGnosisContext as aK, useIntegratorContext as aL, useMultiChainWallet as aM, useSigner as aN, useWallet as aO, useWallets as aP, useXrplTrustLine as aQ, TX_STATUS_CONSTANTS as aR, FINAL_TRANSACTION_STATUSES as aS, useGetFiatQuote as aT, useGetOnRampConfig as aU, useExecuteFiatQuote as aV, useFiatOnRampTxStatus as aW, useFiatTransactions as aX, useCurrencyDetails as aY, useCountryDetails as aZ, useAvailableQuotes as a_, useBitcoinNativeBalance as aa, useCosmosNativeBalance as ab, useEvmNativeBalance as ac, useNativeBalance as ad, useSolanaNativeBalance as ae, useStellarNativeBalance as af, useSuiNativeBalance as ag, useXrplNativeBalance as ah, useNativeTokenForChain as ai, useSingleTokenPrice as aj, useSourceChainGasToken as ak, useSquidTokens as al, useHistoricalData as am, useTokensData as an, useEstimateSendTransaction as ao, useSendTransaction as ap, useSendTransactionGas as aq, useAllTransactionsStatus as ar, useApproval as as, useDepositTransactionStatus as at, useEstimate as au, useEstimatePriceImpact as av, useExecuteTransaction as aw, useGetRoute as ax, useGetRouteWrapper as ay, useRouteWarnings as az, chainTypeToZeroAddressMap as b, parseEvmAddress as b$, useGetOnrampPaymentTypes as b0, useSuggestedFiatAmounts as b1, SquidProvider as b2, EnsService as b3, getXummClient as b4, isXamanXAppContext as b5, getQueryHeaders as b6, getStatusCode as b7, is404Error as b8, assetsBaseUrl as b9, getTokensForChain as bA, getFirstAvailableChainId as bB, fetchHighestBalanceToken as bC, getInitialOrDefaultTokenAddressForChain as bD, getInitialTokenAddressForChain as bE, filterTokensForDestination as bF, getInitialChainIdFromConfig as bG, getCosmosKey as bH, getKeysSettled as bI, getAllKeysForSupportedCosmosChains as bJ, isCosmosAddressValid as bK, getCosmosSigningClient as bL, getCosmosChainInfosObject as bM, connectCosmosWallet as bN, isFallbackAddressNeeded as bO, suggestChainOrThrow as bP, normalizeError as bQ, transactionErrorCode as bR, isUserRejectionError as bS, getTransactionError as bT, handleTransactionErrorEvents as bU, isSwapRouteError as bV, isStatusError as bW, createQuoteRequestParamsHash as bX, WidgetEvents as bY, EvmNetworkNotSupportedErrorCode as bZ, addEthereumChain as b_, shareSubgraphId as ba, sortTokensBySharedSubgraphIds as bb, getSupportedChainIdsForDirection as bc, filterChains as bd, filterTokens as be, getTokenImage as bf, getNewSwapParamsFromInput as bg, sortAllTokens as bh, findToken as bi, findNativeToken as bj, normalizeIbcAddress as bk, groupTokensBySymbol as bl, groupTokensByChainId as bm, filterViewableTokens as bn, getSecretNetworkBalances as bo, getTokenAssetsKey as bp, fetchAssetsColors as bq, isSupportedChainType as br, initializeSquidData as bs, isEmptyObject as bt, normalizeTokenSymbol as bu, areTokenSymbolsCompatible as bv, isEvmosChain as bw, resolveChainIdFromAsset as bx, getConfigWithDefaults as by, randomIntFromInterval as bz, chainTypeToNativeTokenAddressMap as c, getBridgeType as c$, formatEvmWallet as c0, filterWagmiConnector as c1, waitForReceiptWithRetry as c2, getUserCountry as c3, getCountryData as c4, getCurrencyData as c5, adaptiveRound as c6, getSuggestedAmountsForCurrency as c7, HederaExtensionHelper as c8, convertHederaAccountIdToEvmAddress as c9, getStellarHorizonApiUrl as cA, isValidIssuedAsset as cB, isValidHorizonAsset as cC, formatTransactionHistoryDate as cD, getAxelarExplorerTxUrl as cE, getSourceExplorerTxUrl as cF, getMainExplorerUrl as cG, formatDistance as cH, formatSeconds as cI, formatSwapTxStatusResponseForStorage as cJ, simplifyRouteAction as cK, fetchSwapTransactionStatus as cL, compareTransactionIds as cM, isCoralBridgeAction as cN, isActionCompletedOnSourceTx as cO, sleep as cP, isChainflipDepositRoute as cQ, isChainflipBridgeTransaction as cR, isOnChainTxData as cS, isDepositAddressDirectTransferRoute as cT, getHistoryTransactionId as cU, getStepStatuses as cV, getHalfSuccessState as cW, getStepsInfos as cX, getSwapTxStatusRefetchInterval as cY, getSendTxStatusRefetchInterval as cZ, chainflipMultihopBridgeType as c_, convertEvmAddressToHederaAccountId as ca, scaleHbarToWei as cb, scaleWeiToHbar as cc, parseToBigInt as cd, roundNumericValue as ce, formatUnitsRounded as cf, formatTokenAmount as cg, formatUsdAmount as ch, trimExtraDecimals as ci, getNumericValue as cj, cleanAmount as ck, convertTokenAmountToUSD as cl, convertUSDToTokenAmount as cm, calculateTotal24hChange as cn, getRouteExpiry as co, searchTokens as cp, filterSolanaWallets as cq, isSolanaAddressValid as cr, executeSolanaSwap as cs, executeSolanaTransfer as ct, isStellarAddressValid as cu, getStellarNetwork as cv, stellarAddressToScVal as cw, getStellarTrustLineAsset as cx, isStellarToken as cy, isStellarIssuedToken as cz, definedInWindow as d, getTransactionStatus as d0, getTransactionEndStatus as d1, isHistoryTransactionPending as d2, isHistoryTransactionFailed as d3, isHistoryTransactionWarning as d4, isHistoryTransactionEnded as d5, formatHash as d6, isWalletAddressValid as d7, redirectToExtensionsStore as d8, populateWallets as d9, buildFallbackWallets as da, getDefaultChain as db, sortWallets as dc, areSameAddress as dd, sortAddressBook as de, calculateTotalUsdBalanceUSD as df, addTokenToWallet as dg, isEvmChainNotSupportedError as dh, getWalletSupportedChainTypes as di, getConnectorForChainType as dj, walletSupportsChainType as dk, connectWallet as dl, cancelConnectWallet as dm, isProblematicConnector as dn, mergeWallets as dp, isXionSmartContractAddress as dq, isXrplAddressValid as dr, buildXrplTrustSetTx as ds, getXrplNetwork as dt, parseXrplPaymentTx as du, parseXrplTokenAddress as dv, er as e, formatBNToReadable as f, DEFAULT_ROUTE_REFETCH_INTERVAL as g, destinationAddressResetValue as h, fallbackAddressResetValue as i, nativeCosmosTokenAddress as j, nativeEvmTokenAddress as k, nativeSolanaTokenAddress as l, nativeStellarTokenAddress as m, nativeBitcoinTokenAddress as n, nativeSuiTokenAddress as o, nativeXrplTokenAddress as p, CosmosProvider as q, SendTransactionStatus as r, TransactionStatus as s, useTrackSearchEmpty as t, useCosmosContext as u, useSquidChains as v, walletIconBaseUrl as w, useClient as x, useCosmosForChain as y, useHederaAccountActivation as z };
38648
+ //# sourceMappingURL=index-BlB3yIoX.js.map