@0xsquid/react-hooks 8.9.0 → 8.9.1-beta-canton-wallet-connection.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 (68) 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/constants.d.ts +3 -0
  5. package/dist/core/fallbackWallets.d.ts +16 -0
  6. package/dist/core/providers/CantonProvider.d.ts +19 -0
  7. package/dist/core/types/canton.d.ts +58 -0
  8. package/dist/core/types/cosmos.d.ts +5 -0
  9. package/dist/core/types/wallet.d.ts +15 -7
  10. package/dist/core/wallets.d.ts +5 -0
  11. package/dist/hooks/canton/useCanton.d.ts +2 -0
  12. package/dist/hooks/canton/useCantonWallets.d.ts +8 -0
  13. package/dist/hooks/chains/useSquidChains.d.ts +1 -0
  14. package/dist/hooks/index.d.ts +1 -0
  15. package/dist/hooks/store/useDepositAddressStore.d.ts +18 -5
  16. package/dist/hooks/swap/useDepositAddress.d.ts +6 -7
  17. package/dist/hooks/tokens/useBalance.d.ts +1 -0
  18. package/dist/hooks/tokens/useNativeBalance.d.ts +1 -0
  19. package/dist/hooks/tokens/useSquidTokens.d.ts +1 -0
  20. package/dist/hooks/transaction/useDepositTransactionStatus.d.ts +20 -0
  21. package/dist/hooks/transaction/useSwapStatusQuery.d.ts +29 -0
  22. package/dist/hooks/wallet/useMultiChainWallet.d.ts +55 -29
  23. package/dist/hooks/wallet/useSigner.d.ts +1 -0
  24. package/dist/hooks/wallet/useWallet.d.ts +59 -29
  25. package/dist/hooks/xrpl/useXrplWallets.d.ts +2 -2
  26. package/dist/{index-BL_AUWQg.js → index-B8h1ypYK.js} +1364 -195
  27. package/dist/index-B8h1ypYK.js.map +1 -0
  28. package/dist/{index-DcBFug8t.js → index-doLvokYY.js} +1349 -177
  29. package/dist/index-doLvokYY.js.map +1 -0
  30. package/dist/{index.es-1XEAWjab.js → index.es-CuIvGVFi.js} +4 -3
  31. package/dist/index.es-CuIvGVFi.js.map +1 -0
  32. package/dist/{index.es-DSQHpime.js → index.es-reWGC10l.js} +4 -3
  33. package/dist/index.es-reWGC10l.js.map +1 -0
  34. package/dist/index.esm.js +3 -2
  35. package/dist/index.esm.js.map +1 -1
  36. package/dist/index.js +9 -5
  37. package/dist/index.js.map +1 -1
  38. package/dist/{secretService-B1SDXLS1.js → secretService-3g7QoMaM.js} +4 -3
  39. package/dist/{secretService-B1SDXLS1.js.map → secretService-3g7QoMaM.js.map} +1 -1
  40. package/dist/{secretService-DxQ78j5I.js → secretService-DMcFUD-e.js} +4 -3
  41. package/dist/{secretService-DxQ78j5I.js.map → secretService-DMcFUD-e.js.map} +1 -1
  42. package/dist/server.d.ts +1 -1
  43. package/dist/server.esm.js +7 -1
  44. package/dist/server.esm.js.map +1 -1
  45. package/dist/server.js +7 -0
  46. package/dist/server.js.map +1 -1
  47. package/dist/services/external/onrampAdapter.d.ts +3 -4
  48. package/dist/services/external/rpcService.d.ts +17 -0
  49. package/dist/services/internal/assetsService.d.ts +10 -1
  50. package/dist/services/internal/cantonDamlValue.d.ts +75 -0
  51. package/dist/services/internal/cantonService.d.ts +64 -0
  52. package/dist/services/internal/cantonTransferService.d.ts +93 -0
  53. package/dist/services/internal/transactionService.d.ts +5 -1
  54. package/dist/services/internal/walletService.d.ts +3 -6
  55. package/dist/{stellarService.client-C4TLBEpm.js → stellarService.client-DLPxIX3n.js} +5 -4
  56. package/dist/{stellarService.client-C4TLBEpm.js.map → stellarService.client-DLPxIX3n.js.map} +1 -1
  57. package/dist/{stellarService.client-CkP5ng2n.js → stellarService.client-DMdUVPJ8.js} +5 -4
  58. package/dist/{stellarService.client-CkP5ng2n.js.map → stellarService.client-DMdUVPJ8.js.map} +1 -1
  59. package/dist/tests/cantonService.test.d.ts +1 -0
  60. package/dist/tests/cantonTransferService.test.d.ts +1 -0
  61. package/dist/tests/cip103Client.test.d.ts +1 -0
  62. package/dist/tests/fallbackWallets.test.d.ts +1 -0
  63. package/dist/tests/wallets.test.d.ts +1 -0
  64. package/package.json +3 -2
  65. package/dist/index-BL_AUWQg.js.map +0 -1
  66. package/dist/index-DcBFug8t.js.map +0 -1
  67. package/dist/index.es-1XEAWjab.js.map +0 -1
  68. package/dist/index.es-DSQHpime.js.map +0 -1
@@ -11,13 +11,13 @@ var axios = require('axios');
11
11
  var modal = require('@walletconnect/modal');
12
12
  var UniversalProvider = require('@walletconnect/universal-provider');
13
13
  var rippleAddressCodec = require('ripple-address-codec');
14
+ var BigNumber = require('bignumber.js');
14
15
  var splToken = require('@solana/spl-token');
15
16
  var walletStandardWalletAdapterBase = require('@solana/wallet-standard-wallet-adapter-base');
16
17
  var web3_js = require('@solana/web3.js');
17
18
  var stellarSdk = require('@stellar/stellar-sdk');
18
19
  var walletStandard = require('@mysten/wallet-standard');
19
20
  var ethers = require('ethers');
20
- var BigNumber = require('bignumber.js');
21
21
  var countriesList = require('countries-list');
22
22
  var getSymbolFromCurrency = require('currency-symbol-map');
23
23
  var Fuse = require('fuse.js');
@@ -25,6 +25,7 @@ var zustand = require('zustand');
25
25
  var middleware = require('zustand/middleware');
26
26
  var wagmi = require('wagmi');
27
27
  var SafeAppsSDK = require('@safe-global/safe-apps-sdk');
28
+ var dapp = require('@sigilry/dapp');
28
29
  var core$1 = require('@wallet-standard/core');
29
30
  var slushWallet = require('@mysten/slush-wallet');
30
31
  var stargate = require('@cosmjs/stargate');
@@ -78,6 +79,7 @@ const solanaZeroAddress = "11111111111111111111111111111111";
78
79
  const suiZeroAddress = "0x0000000000000000000000000000000000000000";
79
80
  const xrplZeroAddress = "rrrrrrrrrrrrrrrrrrrrrhoLvTp";
80
81
  const stellarZeroAddress = "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF";
82
+ const cantonZeroAddress = "none::12200000000000000000000000000000000000000000000000000000000000000000";
81
83
  const chainTypeToZeroAddressMap = {
82
84
  [squidTypes.ChainType.EVM]: viem.zeroAddress,
83
85
  [squidTypes.ChainType.COSMOS]: cosmosZeroAddress,
@@ -86,6 +88,7 @@ const chainTypeToZeroAddressMap = {
86
88
  [squidTypes.ChainType.SUI]: suiZeroAddress,
87
89
  [squidTypes.ChainType.XRPL]: xrplZeroAddress,
88
90
  [squidTypes.ChainType.STELLAR]: stellarZeroAddress,
91
+ [squidTypes.ChainType.CANTON]: cantonZeroAddress,
89
92
  };
90
93
  const nativeEvmTokenAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
91
94
  const nativeCosmosTokenAddress = "uosmo";
@@ -94,6 +97,7 @@ const nativeBitcoinTokenAddress = "satoshi";
94
97
  const nativeSuiTokenAddress = "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI";
95
98
  const nativeXrplTokenAddress = "xrp";
96
99
  const nativeStellarTokenAddress = "CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA";
100
+ const nativeCantonTokenAddress = "DSO::1220b1431ef217342db44d516bb9befde802be7d8899637d290895fa58880f19accc";
97
101
  // by setting slippage to undefined, it's set to "auto"
98
102
  const defaultSlippage = undefined;
99
103
  const destinationAddressResetValue = "null";
@@ -106,6 +110,8 @@ const DEFAULT_ROUTE_REFETCH_INTERVAL = 30_000;
106
110
  const SOLANA_RPC_URL = "https://meredith-ute2ko-fast-mainnet.helius-rpc.com";
107
111
  const INTEGRATOR_ID = "squid-widget-playground-local-cd33cba6-7e12-4fcc-8d5d-35e286f655ea";
108
112
  const DEFAULT_COUNTRY_CODE = "US";
113
+ // TODO: pending confirmation with Backend team on final URL
114
+ const CANTON_AMULET_REGISTRY_URL = "/api/canton/scan-proxy";
109
115
  const CHAIN_IDS = {
110
116
  // Cosmos
111
117
  OSMOSIS: "osmosis-1",
@@ -157,6 +163,7 @@ const CHAIN_IDS = {
157
163
  XRPL_TESTNET: "xrpl-testnet",
158
164
  STELLAR: "stellar-mainnet",
159
165
  STELLAR_TESTNET: "stellar-testnet",
166
+ CANTON: "canton",
160
167
  };
161
168
  const chainTypeToDefaultChainIdMap = {
162
169
  [squidTypes.ChainType.EVM]: CHAIN_IDS.ETHEREUM,
@@ -166,6 +173,7 @@ const chainTypeToDefaultChainIdMap = {
166
173
  [squidTypes.ChainType.SUI]: CHAIN_IDS.SUI,
167
174
  [squidTypes.ChainType.XRPL]: CHAIN_IDS.XRPL,
168
175
  [squidTypes.ChainType.STELLAR]: CHAIN_IDS.STELLAR,
176
+ [squidTypes.ChainType.CANTON]: CHAIN_IDS.CANTON,
169
177
  };
170
178
  const chainTypeToNativeTokenAddressMap = {
171
179
  [squidTypes.ChainType.EVM]: nativeEvmTokenAddress,
@@ -175,6 +183,7 @@ const chainTypeToNativeTokenAddressMap = {
175
183
  [squidTypes.ChainType.SUI]: nativeSuiTokenAddress,
176
184
  [squidTypes.ChainType.XRPL]: nativeXrplTokenAddress,
177
185
  [squidTypes.ChainType.STELLAR]: nativeStellarTokenAddress,
186
+ [squidTypes.ChainType.CANTON]: nativeCantonTokenAddress,
178
187
  };
179
188
  const defaultConfigValues = {
180
189
  integratorId: INTEGRATOR_ID,
@@ -20557,6 +20566,17 @@ exports.WindowWalletFlag = void 0;
20557
20566
  })(exports.WindowWalletFlag || (exports.WindowWalletFlag = {}));
20558
20567
 
20559
20568
  const walletIconBaseUrl = "https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/wallets";
20569
+ /**
20570
+ * Dynamically accesses a nested property of an object based on a dot-separated string path.
20571
+ * Returns the value of the property if found, otherwise undefined.
20572
+ */
20573
+ const accessProperty = (object, path) => {
20574
+ const value = get$2(object, path);
20575
+ if (value === undefined) {
20576
+ console.error(`Property "${path}" not found while reading object`, object);
20577
+ }
20578
+ return value;
20579
+ };
20560
20580
  const bitcoinWallets = [
20561
20581
  {
20562
20582
  name: "Unisat",
@@ -20853,6 +20873,34 @@ const walletStoreLinks = {
20853
20873
  },
20854
20874
  };
20855
20875
 
20876
+ /**
20877
+ * Wallets to show regardless of whether they're detected.
20878
+ * Useful when we want to link to the browser extension store
20879
+ * for wallets that are automatically discovered (i.e. EVM, SOLANA, CANTON...)
20880
+ */
20881
+ const fallbackWallets = [
20882
+ {
20883
+ chainType: squidTypes.ChainType.CANTON,
20884
+ id: "ldmohiccoioolenadmogclhoklmanpgi",
20885
+ name: "Send Connect",
20886
+ connectorName: "Send Connect",
20887
+ icon: `${walletIconBaseUrl}/canton-send.webp`,
20888
+ links: {
20889
+ chrome: "https://chromewebstore.google.com/detail/send-connect/ldmohiccoioolenadmogclhoklmanpgi",
20890
+ },
20891
+ },
20892
+ {
20893
+ chainType: squidTypes.ChainType.CANTON,
20894
+ id: "lpnfhpbpmlobjlgkdmnjieeihjmihhjd",
20895
+ name: "Console Wallet",
20896
+ connectorName: "Console Wallet",
20897
+ icon: `${walletIconBaseUrl}/canton-console.webp`,
20898
+ links: {
20899
+ chrome: "https://chromewebstore.google.com/detail/console-wallet/lpnfhpbpmlobjlgkdmnjieeihjmihhjd",
20900
+ },
20901
+ },
20902
+ ];
20903
+
20856
20904
  // Validation taken from Squid API repo
20857
20905
  const isBitcoinAddressValid = (address) => {
20858
20906
  try {
@@ -20872,6 +20920,142 @@ const isBitcoinAddressValid = (address) => {
20872
20920
  }
20873
20921
  };
20874
20922
 
20923
+ // Canton PartyID = address
20924
+ const CANTON_PARTY_ID_SEPARATOR = "::";
20925
+ /** Canton Coin's well-known token-standard instrument id (its address carries no id prefix). */
20926
+ const CANTON_AMULET_INSTRUMENT_ID = "Amulet";
20927
+ function isCantonAddressValid(address) {
20928
+ // Canton address format: `name::fingerprint`, where name is an arbitrary string
20929
+ // and fingerprint is a 64-character hex string with a 1220 prefix (SHA-256 hash of the public key)
20930
+ const parts = address.split(CANTON_PARTY_ID_SEPARATOR);
20931
+ if (parts.length !== 2)
20932
+ return false;
20933
+ const [name, fingerprint] = parts;
20934
+ return name.length > 0 && /^1220[0-9a-f]{64}$/.test(fingerprint);
20935
+ }
20936
+ /**
20937
+ * Splice token-standard Holding interface id. A party's balance for an
20938
+ * instrument is the sum of `amount` across active contracts implementing this interface.
20939
+ */
20940
+ const CANTON_HOLDING_INTERFACE_ID = "#splice-api-token-holding-v1:Splice.Api.Token.HoldingV1:Holding";
20941
+ /**
20942
+ * Derive the token-standard instrument `{ admin, id }` from a Squid Canton token
20943
+ * address (use the case-sensitive `originalAddress`), or `null` when the address
20944
+ * is not a valid Canton token address.
20945
+ *
20946
+ * The admin party is the last two `::` segments (`name::fingerprint`); the
20947
+ * instrument id is everything before that. Canton Coin has no id prefix
20948
+ * (`DSO::1220…`) and uses the well-known id `Amulet`.
20949
+ * - `DSO::1220…` -> { admin: "DSO::1220…", id: "Amulet" }
20950
+ * - `USDCx::decentralized-usdc-…::12208…` -> { admin: "decentralized-usdc-…::12208…", id: "USDCx" }
20951
+ */
20952
+ function parseCantonInstrument(address) {
20953
+ const segments = address.split(CANTON_PARTY_ID_SEPARATOR);
20954
+ if (segments.length < 2) {
20955
+ return null;
20956
+ }
20957
+ const admin = segments.slice(-2).join(CANTON_PARTY_ID_SEPARATOR);
20958
+ const idPrefix = segments.slice(0, -2).join(CANTON_PARTY_ID_SEPARATOR);
20959
+ return {
20960
+ admin,
20961
+ id: idPrefix.length > 0 ? idPrefix : CANTON_AMULET_INSTRUMENT_ID,
20962
+ };
20963
+ }
20964
+ /**
20965
+ * Body for `POST /v2/state/active-contracts`, filtered to the party's Holding
20966
+ * contracts with the interface view included (so we can read amount/instrument).
20967
+ *
20968
+ * ACS: Active Contract Set — the ledger's currently-active contracts (created and
20969
+ * not yet archived) as of a ledger offset.
20970
+ */
20971
+ function buildHoldingsAcsRequestBody(partyId, activeAtOffset) {
20972
+ return {
20973
+ activeAtOffset,
20974
+ eventFormat: {
20975
+ verbose: true,
20976
+ filtersByParty: {
20977
+ [partyId]: {
20978
+ cumulative: [
20979
+ {
20980
+ identifierFilter: {
20981
+ InterfaceFilter: {
20982
+ value: {
20983
+ interfaceId: CANTON_HOLDING_INTERFACE_ID,
20984
+ includeInterfaceView: true,
20985
+ includeCreatedEventBlob: false,
20986
+ },
20987
+ },
20988
+ },
20989
+ },
20990
+ ],
20991
+ },
20992
+ },
20993
+ },
20994
+ };
20995
+ }
20996
+ /**
20997
+ * Parse the party's Holding contracts (with contract ids) from a raw
20998
+ * `/v2/state/active-contracts` response
20999
+ * Defensive: skips entries it can't parse.
21000
+ */
21001
+ function parseCantonHoldings(acsResponse) {
21002
+ if (!Array.isArray(acsResponse))
21003
+ return [];
21004
+ const holdings = [];
21005
+ for (const entry of acsResponse) {
21006
+ const createdEvent = entry?.contractEntry?.JsActiveContract
21007
+ ?.createdEvent;
21008
+ const contractId = createdEvent?.contractId;
21009
+ const views = createdEvent?.interfaceViews;
21010
+ if (!contractId || !Array.isArray(views))
21011
+ continue;
21012
+ for (const view of views) {
21013
+ const value = view?.viewValue;
21014
+ const instrumentId = value?.instrumentId;
21015
+ if (!instrumentId?.admin ||
21016
+ instrumentId.id == null ||
21017
+ value.amount == null) {
21018
+ continue;
21019
+ }
21020
+ holdings.push({
21021
+ contractId,
21022
+ instrument: { admin: instrumentId.admin, id: instrumentId.id },
21023
+ amount: String(value.amount),
21024
+ // Locked holdings are not spendable, skip them
21025
+ locked: value.lock != null,
21026
+ });
21027
+ }
21028
+ }
21029
+ return holdings;
21030
+ }
21031
+ /**
21032
+ * Key used to group holdings by instrument.
21033
+ */
21034
+ function instrumentKey(admin, id) {
21035
+ return `${admin}|${id}`;
21036
+ }
21037
+ function cantonInstrumentKey(instrument) {
21038
+ return instrumentKey(instrument.admin, instrument.id);
21039
+ }
21040
+ /**
21041
+ * Group the (unlocked) Holding amounts by instrument from a raw
21042
+ * `/v2/state/active-contracts` response. Returns a map of instrument key
21043
+ * (`admin|id`) -> human-readable decimal string (the token-standard `amount`
21044
+ * is already a Decimal, not base units).
21045
+ */
21046
+ function groupCantonHoldingBalances(acsResponse) {
21047
+ const totals = {};
21048
+ for (const holding of parseCantonHoldings(acsResponse)) {
21049
+ // Locked holdings are not spendable, skip them
21050
+ if (holding.locked)
21051
+ continue;
21052
+ const key = cantonInstrumentKey(holding.instrument);
21053
+ const total = totals[key] ?? new BigNumber(0);
21054
+ totals[key] = total.plus(new BigNumber(holding.amount));
21055
+ }
21056
+ return Object.fromEntries(Object.entries(totals).map(([key, total]) => [key, total.toString(10)]));
21057
+ }
21058
+
20875
21059
  const solanaTokenProgramIdByAddress = {
20876
21060
  [splToken.TOKEN_PROGRAM_ID.toBase58()]: splToken.TOKEN_PROGRAM_ID,
20877
21061
  [splToken.TOKEN_2022_PROGRAM_ID.toBase58()]: splToken.TOKEN_2022_PROGRAM_ID,
@@ -21011,6 +21195,7 @@ const getSourceExplorerTxUrl = (chain, txID) => {
21011
21195
  case CHAIN_IDS.AGORIC:
21012
21196
  case CHAIN_IDS.XRPL:
21013
21197
  case CHAIN_IDS.XRPL_TESTNET:
21198
+ case CHAIN_IDS.CANTON:
21014
21199
  txSuffix = "/transactions/";
21015
21200
  break;
21016
21201
  case CHAIN_IDS.HEDERA:
@@ -21120,10 +21305,16 @@ const simplifyRouteAction = (action) => {
21120
21305
  };
21121
21306
  const fetchSwapTransactionStatus = async ({ transaction, integratorId, apiUrl, }) => {
21122
21307
  const statusEndpoint = `${apiUrl}/v2/status`;
21308
+ const isCanton = transaction?.fromChain === CHAIN_IDS.CANTON;
21309
+ // For Canton, the backend handles all tx detection/submission from the quoteId
21310
+ // alone, so no transactionId is sent — only the quoteId param below.
21311
+ const transactionId = isCanton
21312
+ ? undefined
21313
+ : (transaction?.transactionIdForStatus ?? transaction?.transactionId);
21123
21314
  try {
21124
21315
  const response = await axios.get(statusEndpoint, {
21125
21316
  params: {
21126
- transactionId: transaction?.transactionIdForStatus ?? transaction?.transactionId,
21317
+ transactionId,
21127
21318
  fromChainId: transaction?.fromChain,
21128
21319
  toChainId: transaction?.toChain,
21129
21320
  bridgeType: transaction?.bridgeType,
@@ -21170,7 +21361,7 @@ function isActionCompletedOnSourceTx(action, fromChainId) {
21170
21361
  function sleep(ms) {
21171
21362
  return new Promise((resolve) => setTimeout(resolve, ms));
21172
21363
  }
21173
- const isDepositRoute = (route) => {
21364
+ const isChainflipDepositRoute = (route) => {
21174
21365
  return (!!route &&
21175
21366
  route.transactionRequest?.type === squidTypes.SquidDataType.ChainflipDepositAddress);
21176
21367
  };
@@ -21195,6 +21386,12 @@ function isOnChainTxData(squidData) {
21195
21386
  squidTypes.SquidDataType.DepositAddressWithMemo,
21196
21387
  ].includes(squidData.type);
21197
21388
  }
21389
+ /**
21390
+ * Checks if a route is of type DepositAddressDirectTransfer
21391
+ */
21392
+ function isDepositAddressDirectTransferRoute(squidData) {
21393
+ return squidData.type === squidTypes.SquidDataType.DepositAddressDirectTransfer;
21394
+ }
21198
21395
  function getHistoryTransactionId(tx) {
21199
21396
  switch (tx.txType) {
21200
21397
  case exports.HistoryTxType.SWAP:
@@ -21714,7 +21911,17 @@ const chainTypeToTrimLength = {
21714
21911
  start: 4,
21715
21912
  end: 4,
21716
21913
  },
21914
+ // abc...123::abc...123
21915
+ [squidTypes.ChainType.CANTON]: {
21916
+ start: 3,
21917
+ end: 3,
21918
+ },
21717
21919
  };
21920
+ const truncateWithEllipsis = (value, startLength, endLength) => value.length <= startLength + endLength
21921
+ ? value
21922
+ : value.slice(0, startLength) +
21923
+ "..." +
21924
+ value.slice(value.length - endLength);
21718
21925
  const formatHash = ({ chainType, hash }) => {
21719
21926
  if (!hash)
21720
21927
  return "";
@@ -21727,14 +21934,15 @@ const formatHash = ({ chainType, hash }) => {
21727
21934
  chainTypeFormat = squidTypes.ChainType.COSMOS;
21728
21935
  }
21729
21936
  }
21730
- const trimLengthStart = chainTypeToTrimLength[chainTypeFormat].start;
21731
- const trimLengthEnd = chainTypeToTrimLength[chainTypeFormat].end;
21732
- // return the same hash if its length is less than the trim length
21733
- if (hash.length <= trimLengthStart + trimLengthEnd)
21734
- return hash;
21735
- return (hash.slice(0, trimLengthStart) +
21736
- "..." +
21737
- hash.slice(hash.length - trimLengthEnd, hash.length));
21937
+ const { start, end } = chainTypeToTrimLength[chainTypeFormat];
21938
+ if (chainTypeFormat === squidTypes.ChainType.CANTON &&
21939
+ hash.includes(CANTON_PARTY_ID_SEPARATOR)) {
21940
+ const [namespace, identifier] = hash.split(CANTON_PARTY_ID_SEPARATOR);
21941
+ return (truncateWithEllipsis(namespace, start, end) +
21942
+ CANTON_PARTY_ID_SEPARATOR +
21943
+ truncateWithEllipsis(identifier, start, end));
21944
+ }
21945
+ return truncateWithEllipsis(hash, start, end);
21738
21946
  };
21739
21947
  const isWalletAddressValid = (chainData, address) => {
21740
21948
  if (!address || !chainData?.chainType)
@@ -21754,33 +21962,25 @@ const isWalletAddressValid = (chainData, address) => {
21754
21962
  return isXrplAddressValid(address);
21755
21963
  case squidTypes.ChainType.STELLAR:
21756
21964
  return isStellarAddressValid(address);
21965
+ case squidTypes.ChainType.CANTON:
21966
+ return isCantonAddressValid(address);
21757
21967
  }
21758
21968
  };
21759
21969
  const redirectToExtensionsStore = (wallet) => {
21760
21970
  const { userAgent } = navigator;
21761
21971
  let link;
21762
21972
  if (userAgent.indexOf("Firefox") > -1) {
21763
- link = wallet.url || walletStoreLinks[wallet.connectorId]?.firefox;
21973
+ link =
21974
+ wallet.links?.firefox || walletStoreLinks[wallet.connectorId]?.firefox;
21764
21975
  }
21765
21976
  else if (userAgent.indexOf("Chrome") > -1) {
21766
- link = wallet.url || walletStoreLinks[wallet.connectorId]?.chrome;
21977
+ link = wallet.links?.chrome || walletStoreLinks[wallet.connectorId]?.chrome;
21767
21978
  }
21979
+ link = link || wallet.links?.website;
21768
21980
  if (link && link !== "") {
21769
21981
  window?.open(link, "_blank")?.focus();
21770
21982
  }
21771
21983
  };
21772
- /**
21773
- * Dynamically accesses a nested property of an object based on a dot-separated string path.
21774
- * Returns the value of the property if found, otherwise undefined.
21775
- * e.g. "xfi.keplr" will return window.xfi.keplr
21776
- */
21777
- const accessProperty = (object, path) => {
21778
- const value = get$2(object, path);
21779
- if (value === undefined) {
21780
- console.error(`Property "${path}" not found while reading object`, object);
21781
- }
21782
- return value;
21783
- };
21784
21984
  const definedInWindow = (path, clientWindow) => {
21785
21985
  if (!path || !clientWindow)
21786
21986
  return false;
@@ -21809,6 +22009,32 @@ const populateWallets = (window, wallets) => {
21809
22009
  return wallet;
21810
22010
  });
21811
22011
  };
22012
+ const createUninstalledConnector = () => new Proxy({}, {
22013
+ get(_target, prop) {
22014
+ throw new Error(`Cannot use connector of an uninstalled wallet (accessed "${String(prop)}")`);
22015
+ },
22016
+ });
22017
+ const buildFallbackWallets = (discovered) => {
22018
+ const fallbackKey = (chainType, connectorId) => `${chainType}:${connectorId}`;
22019
+ const discoveredKeys = new Set(discovered.flatMap((wallet) => wallet.isMultiChain
22020
+ ? wallet.supportedNetworks.map((network) => fallbackKey(network.chainType, wallet.connectorId))
22021
+ : [fallbackKey(wallet.type, wallet.connectorId)]));
22022
+ return fallbackWallets
22023
+ .filter((config) => !discoveredKeys.has(fallbackKey(config.chainType, config.id)))
22024
+ .map((config) => ({
22025
+ name: config.name,
22026
+ connectorId: config.id,
22027
+ connectorName: config.connectorName,
22028
+ icon: config.icon,
22029
+ windowFlag: config.id,
22030
+ links: config.links,
22031
+ isInstalled: () => false,
22032
+ skipInstallCheck: false,
22033
+ isMultiChain: false,
22034
+ type: config.chainType,
22035
+ connector: createUninstalledConnector(),
22036
+ }));
22037
+ };
21812
22038
  /**
21813
22039
  * Get the base chain to connect to
21814
22040
  * If only one chain type is selected, use that chain type
@@ -22015,6 +22241,13 @@ const connectByChainType = async (chainType, wallet, defaultChain, params) => {
22015
22241
  connector,
22016
22242
  },
22017
22243
  });
22244
+ case squidTypes.ChainType.CANTON:
22245
+ return params.connectCanton.mutateAsync({
22246
+ wallet: {
22247
+ ...wallet,
22248
+ connector,
22249
+ },
22250
+ });
22018
22251
  }
22019
22252
  };
22020
22253
  const getChainTypesToConnect = (selectedChainTypes, defaultChain, supportedChains) => {
@@ -22051,6 +22284,7 @@ const connectMultiChainWallet = async (params) => {
22051
22284
  connectSui: params.connectSui,
22052
22285
  connectXrpl: params.connectXrpl,
22053
22286
  connectStellar: params.connectStellar,
22287
+ connectCanton: params.connectCanton,
22054
22288
  });
22055
22289
  if (result) {
22056
22290
  results.push({
@@ -22084,6 +22318,7 @@ const connectSingleChainWallet = async (params) => {
22084
22318
  connectSui: params.connectSui,
22085
22319
  connectXrpl: params.connectXrpl,
22086
22320
  connectStellar: params.connectStellar,
22321
+ connectCanton: params.connectCanton,
22087
22322
  });
22088
22323
  return result
22089
22324
  ? {
@@ -22997,7 +23232,7 @@ const handleDestinationAddressOnSwapChange = ({ fromChainId, fromTokenAddress, t
22997
23232
  });
22998
23233
  let destinationTokenAddress = toChainId && !toTokenAddress
22999
23234
  ? defaultToAddress
23000
- : toTokenAddress ?? swapRoute?.toTokenAddress;
23235
+ : (toTokenAddress ?? swapRoute?.toTokenAddress);
23001
23236
  const lowerCaseDestinationTokenAddress = destinationTokenAddress?.toLowerCase();
23002
23237
  if (destinationTokensFiltered.find((t) => t.address === lowerCaseDestinationTokenAddress) === undefined) {
23003
23238
  destinationTokenAddress = defaultToAddress;
@@ -23049,7 +23284,7 @@ const getNewSwapParamsFromInput = ({ inputParams, initialSwapRoute, tokens, chai
23049
23284
  toTokenAddress === initialSwapRoute?.fromTokenAddress;
23050
23285
  const sourceTokenAddress = sameNewDestAndInitialSource || onlySourceChainIdChanged
23051
23286
  ? defaultFromAddress
23052
- : fromTokenAddress ?? initialSwapRoute?.fromTokenAddress;
23287
+ : (fromTokenAddress ?? initialSwapRoute?.fromTokenAddress);
23053
23288
  let destinationTokenAddress = undefined;
23054
23289
  if (!sameNewSourceAndInitialDest) {
23055
23290
  if (onlySourceChainIdChanged) {
@@ -23089,7 +23324,10 @@ const getNewSwapParamsFromInput = ({ inputParams, initialSwapRoute, tokens, chai
23089
23324
  else {
23090
23325
  newFallbackAddress = fallbackAddress ?? initialSwapRoute?.fallbackAddress;
23091
23326
  }
23092
- const newDepositRefundAddress = depositRefundAddress || initialSwapRoute?.depositRefundAddress;
23327
+ const sourceChainChanged = fromChainId !== undefined && fromChainId !== initialSwapRoute?.fromChainId;
23328
+ const newDepositRefundAddress = sourceChainChanged
23329
+ ? undefined
23330
+ : depositRefundAddress || initialSwapRoute?.depositRefundAddress;
23093
23331
  return {
23094
23332
  fromChainId: srcChainId,
23095
23333
  fromTokenAddress: sourceTokenAddress,
@@ -23368,7 +23606,7 @@ const filterViewableTokens = (tokens, config, direction) => {
23368
23606
  };
23369
23607
  const getSecretNetworkBalances = async (chainData, cosmosAddress, squidTokens, keplrTypeWallet) => {
23370
23608
  const squidSecretTokens = squidTokens.filter((t) => t.chainId === CHAIN_IDS.SECRET);
23371
- const { fetchAllSecretBalances } = await Promise.resolve().then(function () { return require('./secretService-B1SDXLS1.js'); });
23609
+ const { fetchAllSecretBalances } = await Promise.resolve().then(function () { return require('./secretService-3g7QoMaM.js'); });
23372
23610
  return fetchAllSecretBalances(chainData, cosmosAddress, squidSecretTokens, keplrTypeWallet);
23373
23611
  };
23374
23612
  function getTokenAssetsKey(token) {
@@ -23395,9 +23633,29 @@ async function fetchAssetsColors() {
23395
23633
  };
23396
23634
  }
23397
23635
  }
23398
- function initializeSquidWithAssetsColors(squid, assetsColors) {
23399
- const evmosChainIds = squid.chains.filter(isEvmosChain).map((c) => c.chainId);
23400
- squid.tokens = squid.tokens.map((token) => {
23636
+ const supportedChainTypes = new Set(Object.values(squidTypes.ChainType));
23637
+ function isSupportedChainType(chainType) {
23638
+ return supportedChainTypes.has(chainType);
23639
+ }
23640
+ /**
23641
+ * Normalizes SDK data after each init/refetch before the rest of hooks consumes it.
23642
+ *
23643
+ * - Removes chains whose chainType is not supported by the local package.
23644
+ * - Drops tokens for those removed chains.
23645
+ * - Converts Evmos chains/tokens to EVM.
23646
+ * - Applies optional asset colors.
23647
+ */
23648
+ function initializeSquidData(squid, assetsColors = {
23649
+ chains: {},
23650
+ tokens: {},
23651
+ }) {
23652
+ const supportedChains = squid.chains.filter((chain) => isSupportedChainType(chain.chainType));
23653
+ const supportedChainIds = new Set(supportedChains.map((chain) => chain.chainId));
23654
+ const evmosChainIds = supportedChains
23655
+ .filter(isEvmosChain)
23656
+ .map((c) => c.chainId);
23657
+ const supportedTokens = squid.tokens.filter((token) => supportedChainIds.has(token.chainId));
23658
+ squid.tokens = supportedTokens.map((token) => {
23401
23659
  const isEvmosToken = evmosChainIds.includes(token.chainId);
23402
23660
  return {
23403
23661
  ...token,
@@ -23406,7 +23664,7 @@ function initializeSquidWithAssetsColors(squid, assetsColors) {
23406
23664
  textColor: assetsColors.tokens[getTokenAssetsKey(token)]?.textColor,
23407
23665
  };
23408
23666
  });
23409
- squid.chains = squid.chains.map((chain) => {
23667
+ squid.chains = supportedChains.map((chain) => {
23410
23668
  const bgColor = assetsColors.chains[chain.chainId]?.bgColor;
23411
23669
  // convert evmos cosmos chains to evm chains
23412
23670
  // TODO: this will be fixed in the backend
@@ -25059,7 +25317,7 @@ class OnrampService {
25059
25317
  });
25060
25318
  return data;
25061
25319
  }
25062
- async getConfiguration({ chains, tokens, }) {
25320
+ async getConfiguration({ tokens, }) {
25063
25321
  const { data } = await axios.get(`${this.baseUrl}/config`);
25064
25322
  // Filter supportedCryptos to only include tokens that match our provided tokens
25065
25323
  const filteredCryptos = data.supportedCryptos.filter((supportedCrypto) => tokens.some((token) => token.address.toLowerCase() ===
@@ -25283,7 +25541,7 @@ const useSquid = () => {
25283
25541
  queryFn: async () => {
25284
25542
  if (squid) {
25285
25543
  await squid?.init();
25286
- initializeSquidWithAssetsColors(squid, assetsColors);
25544
+ initializeSquidData(squid, assetsColors);
25287
25545
  return squid;
25288
25546
  }
25289
25547
  return null;
@@ -25342,7 +25600,7 @@ const useSquidTokens = (direction) => {
25342
25600
  config.availableChains,
25343
25601
  direction,
25344
25602
  ]);
25345
- const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, } = React.useMemo(() => {
25603
+ const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, cantonTokens, } = React.useMemo(() => {
25346
25604
  return tokens?.reduce((acc, token) => {
25347
25605
  switch (token.type) {
25348
25606
  case squidTypes.ChainType.EVM:
@@ -25366,6 +25624,9 @@ const useSquidTokens = (direction) => {
25366
25624
  case squidTypes.ChainType.STELLAR:
25367
25625
  acc.stellarTokens.push(token);
25368
25626
  break;
25627
+ case squidTypes.ChainType.CANTON:
25628
+ acc.cantonTokens.push(token);
25629
+ break;
25369
25630
  }
25370
25631
  return acc;
25371
25632
  }, {
@@ -25376,6 +25637,7 @@ const useSquidTokens = (direction) => {
25376
25637
  suiTokens: [],
25377
25638
  xrplTokens: [],
25378
25639
  stellarTokens: [],
25640
+ cantonTokens: [],
25379
25641
  });
25380
25642
  }, [tokens]);
25381
25643
  const findToken = React.useCallback((address, chainId) => {
@@ -25393,6 +25655,7 @@ const useSquidTokens = (direction) => {
25393
25655
  suiTokens,
25394
25656
  xrplTokens,
25395
25657
  stellarTokens,
25658
+ cantonTokens,
25396
25659
  };
25397
25660
  };
25398
25661
 
@@ -25493,12 +25756,10 @@ const useGetFiatQuote = ({ fiatCurrency, cryptoCurrencyID, amount, region, payme
25493
25756
  */
25494
25757
  const useGetOnRampConfig = () => {
25495
25758
  const service = React.useMemo(() => new OnrampService(), []);
25496
- const { chains } = useSquidChains();
25497
25759
  const { tokens } = useSquidTokens();
25498
25760
  return reactQuery.useQuery({
25499
25761
  queryKey: keys().fiatToCryptoConfig(),
25500
25762
  queryFn: () => service.getConfiguration({
25501
- chains,
25502
25763
  tokens,
25503
25764
  }),
25504
25765
  cacheTime: 1000 * 60 * 60,
@@ -25930,6 +26191,7 @@ const chainTypeToRefetchInterval = {
25930
26191
  [squidTypes.ChainType.SUI]: 1_000,
25931
26192
  [squidTypes.ChainType.XRPL]: 1_000,
25932
26193
  [squidTypes.ChainType.STELLAR]: 1_000,
26194
+ [squidTypes.ChainType.CANTON]: 1_000,
25933
26195
  };
25934
26196
  /**
25935
26197
  * Returns the status refetch interval of a Send transaction
@@ -26196,7 +26458,7 @@ const useSquidChains = (direction) => {
26196
26458
  const chain = findChain(chainId);
26197
26459
  return chain?.chainType;
26198
26460
  }, [findChain]);
26199
- const { evmChains, cosmosChains, suiChains, stellarChains, xrplChains } = React.useMemo(() => {
26461
+ const { evmChains, cosmosChains, suiChains, stellarChains, xrplChains, cantonChains, } = React.useMemo(() => {
26200
26462
  return chains.reduce((acc, chain) => {
26201
26463
  switch (chain.chainType) {
26202
26464
  case squidTypes.ChainType.EVM:
@@ -26214,6 +26476,9 @@ const useSquidChains = (direction) => {
26214
26476
  case squidTypes.ChainType.STELLAR:
26215
26477
  acc.stellarChains.push(chain);
26216
26478
  break;
26479
+ case squidTypes.ChainType.CANTON:
26480
+ acc.cantonChains.push(chain);
26481
+ break;
26217
26482
  }
26218
26483
  return acc;
26219
26484
  }, {
@@ -26222,6 +26487,7 @@ const useSquidChains = (direction) => {
26222
26487
  suiChains: [],
26223
26488
  xrplChains: [],
26224
26489
  stellarChains: [],
26490
+ cantonChains: [],
26225
26491
  });
26226
26492
  }, [chains]);
26227
26493
  const { supportedSourceChains, supportedDestinationChains } = React.useMemo(() => {
@@ -26242,6 +26508,7 @@ const useSquidChains = (direction) => {
26242
26508
  suiChains,
26243
26509
  xrplChains,
26244
26510
  stellarChains,
26511
+ cantonChains,
26245
26512
  getChainType,
26246
26513
  findChain,
26247
26514
  };
@@ -26555,6 +26822,253 @@ const useBitcoinContext = () => {
26555
26822
  return context;
26556
26823
  };
26557
26824
 
26825
+ const REQUEST_TIMEOUT_MS = 60_000;
26826
+ function pickAddress(accounts) {
26827
+ return (accounts.find((a) => a.primary) ?? accounts[0])?.partyId;
26828
+ }
26829
+ /**
26830
+ * Browser-extension Canton connector: wraps one discovered CIP-103 provider
26831
+ * (bound to its announce `target`) and exposes the lifecycle methods.
26832
+ */
26833
+ class CantonBrowserConnector {
26834
+ providerId;
26835
+ name;
26836
+ target;
26837
+ client;
26838
+ listeners = { connect: new Set(), disconnect: new Set() };
26839
+ _accounts = [];
26840
+ constructor(provider, win = window) {
26841
+ this.providerId = provider.id;
26842
+ this.name = provider.name;
26843
+ this.target = provider.target ?? provider.id;
26844
+ this.client = dapp.createCantonClient(new dapp.WindowTransport(win, {
26845
+ target: this.target,
26846
+ timeout: REQUEST_TIMEOUT_MS,
26847
+ }));
26848
+ }
26849
+ get accounts() {
26850
+ return this._accounts;
26851
+ }
26852
+ get address() {
26853
+ return pickAddress(this._accounts);
26854
+ }
26855
+ async connect() {
26856
+ await this.client.connect();
26857
+ const result = await this.refreshAccounts();
26858
+ this.emit("connect", result.address);
26859
+ return result;
26860
+ }
26861
+ /** Silent connect: read accounts without prompting; throws if not connected. */
26862
+ async autoConnect() {
26863
+ const accounts = await this.client.listAccounts();
26864
+ if (!accounts.length) {
26865
+ throw new Error("Canton wallet not connected");
26866
+ }
26867
+ this._accounts = accounts;
26868
+ const address = pickAddress(accounts);
26869
+ this.emit("connect", address);
26870
+ return { address, accounts };
26871
+ }
26872
+ async disconnect() {
26873
+ try {
26874
+ await this.client.disconnect();
26875
+ }
26876
+ finally {
26877
+ this._accounts = [];
26878
+ this.emit("disconnect");
26879
+ }
26880
+ }
26881
+ async ledgerApi(params) {
26882
+ const result = await this.client.ledgerApi(params);
26883
+ return result;
26884
+ }
26885
+ async prepareExecuteAndWait(params) {
26886
+ return this.client.prepareExecuteAndWait(params);
26887
+ }
26888
+ async getAccounts() {
26889
+ this._accounts = await this.client.listAccounts();
26890
+ return this._accounts;
26891
+ }
26892
+ on(event, handler) {
26893
+ this.listeners[event].add(handler);
26894
+ }
26895
+ off(event, handler) {
26896
+ this.listeners[event].delete(handler);
26897
+ }
26898
+ emit(event, ...args) {
26899
+ this.listeners[event].forEach((handler) => handler(...args));
26900
+ }
26901
+ async refreshAccounts() {
26902
+ const accounts = await this.client.listAccounts();
26903
+ this._accounts = accounts;
26904
+ const address = pickAddress(accounts);
26905
+ if (!address) {
26906
+ throw new Error("Canton wallet returned no accounts");
26907
+ }
26908
+ return { address, accounts };
26909
+ }
26910
+ }
26911
+
26912
+ const CANTON_REQUEST_PROVIDER_EVENT = "canton:requestProvider";
26913
+ const CANTON_ANNOUNCE_PROVIDER_EVENT = "canton:announceProvider";
26914
+ const DEFAULT_DISCOVERY_TIMEOUT_MS = 300;
26915
+ /**
26916
+ * CIP-103 browser-wallet discovery (EIP-6963-style).
26917
+ * The wallet dispatches `canton:announceProvider` and dApps
26918
+ * dispatch `canton:requestProvider` to ask installed wallets to re-announce.
26919
+ * Each announcement carries a `target` we route through Sigilry's `WindowTransport`,
26920
+ * so multiple extensions coexist without contending on the `window.canton` global.
26921
+ */
26922
+ async function discoverCantonProviders(timeoutMs = DEFAULT_DISCOVERY_TIMEOUT_MS, win = window) {
26923
+ if (typeof win === "undefined")
26924
+ return [];
26925
+ const discovered = new Map();
26926
+ const handler = (event) => {
26927
+ const detail = event.detail;
26928
+ if (!detail?.id || !detail.name || discovered.has(detail.id))
26929
+ return;
26930
+ discovered.set(detail.id, {
26931
+ id: detail.id,
26932
+ name: detail.name,
26933
+ icon: detail.icon,
26934
+ target: detail.target ?? detail.id,
26935
+ });
26936
+ };
26937
+ win.addEventListener(CANTON_ANNOUNCE_PROVIDER_EVENT, handler);
26938
+ try {
26939
+ win.dispatchEvent(new CustomEvent(CANTON_REQUEST_PROVIDER_EVENT, { detail: {} }));
26940
+ await new Promise((resolve) => setTimeout(resolve, timeoutMs));
26941
+ }
26942
+ finally {
26943
+ win.removeEventListener(CANTON_ANNOUNCE_PROVIDER_EVENT, handler);
26944
+ }
26945
+ return Array.from(discovered.values());
26946
+ }
26947
+
26948
+ /**
26949
+ * Discovers Canton browser-extension wallets via the CIP-103 announce protocol
26950
+ * (on mount and on window focus) and maps each to a {@link CantonWallet}.
26951
+ */
26952
+ function useCantonWallets() {
26953
+ const [wallets, setWallets] = React.useState([]);
26954
+ const connectorCache = React.useRef(new Map());
26955
+ const toWallet = React.useCallback((provider) => {
26956
+ let connector = connectorCache.current.get(provider.id);
26957
+ if (!connector) {
26958
+ connector = new CantonBrowserConnector(provider);
26959
+ connectorCache.current.set(provider.id, connector);
26960
+ }
26961
+ return {
26962
+ name: provider.name,
26963
+ connectorId: provider.id,
26964
+ connectorName: provider.name,
26965
+ icon: provider.icon,
26966
+ windowFlag: provider.id,
26967
+ skipInstallCheck: true,
26968
+ isInstalled: () => true,
26969
+ isMultiChain: false,
26970
+ type: squidTypes.ChainType.CANTON,
26971
+ connector,
26972
+ };
26973
+ }, []);
26974
+ const refresh = React.useCallback(async () => {
26975
+ if (typeof window === "undefined")
26976
+ return;
26977
+ const providers = await discoverCantonProviders();
26978
+ setWallets(providers.map(toWallet));
26979
+ }, [toWallet]);
26980
+ React.useEffect(() => {
26981
+ refresh();
26982
+ if (typeof window === "undefined")
26983
+ return;
26984
+ const onFocus = () => refresh();
26985
+ window.addEventListener("focus", onFocus);
26986
+ return () => window.removeEventListener("focus", onFocus);
26987
+ }, [refresh]);
26988
+ return { wallets };
26989
+ }
26990
+
26991
+ function useCanton() {
26992
+ const disconnectWallet = useWalletStore((store) => store.disconnectWallet);
26993
+ const setConnectedWallet = useWalletStore((store) => store.setConnectedWallet);
26994
+ const { wallets } = useCantonWallets();
26995
+ const connectedCantonWallet = useWalletStore((store) => store.connectedWalletsByChainType[squidTypes.ChainType.CANTON]);
26996
+ const recentCantonWalletId = useWalletStore((store) => store.recentConnectorIds[squidTypes.ChainType.CANTON]);
26997
+ const connectCanton = reactQuery.useMutation(async ({ wallet, }) => {
26998
+ let result;
26999
+ try {
27000
+ // Try to reconnect silently first (existing session, no popup)
27001
+ result = await wallet.connector.autoConnect();
27002
+ }
27003
+ catch {
27004
+ // Otherwise prompt the wallet to connect
27005
+ result = await wallet.connector.connect();
27006
+ }
27007
+ return {
27008
+ wallet,
27009
+ address: result.address,
27010
+ };
27011
+ });
27012
+ const disconnectCanton = React.useCallback(async () => {
27013
+ await connectedCantonWallet.wallet?.connector.disconnect();
27014
+ }, [connectedCantonWallet.wallet?.connector]);
27015
+ const autoConnectCanton = React.useCallback(async () => {
27016
+ const recentCantonWallet = wallets.find((w) => w.connectorId === recentCantonWalletId);
27017
+ if (!recentCantonWallet) {
27018
+ return;
27019
+ }
27020
+ const { address } = await recentCantonWallet.connector.autoConnect();
27021
+ setConnectedWallet(squidTypes.ChainType.CANTON, {
27022
+ wallet: recentCantonWallet,
27023
+ address,
27024
+ });
27025
+ // eslint-disable-next-line react-hooks/exhaustive-deps
27026
+ }, [wallets.map((w) => w.connectorId), recentCantonWalletId]);
27027
+ React.useEffect(() => {
27028
+ const wallet = connectedCantonWallet.wallet;
27029
+ if (!wallet) {
27030
+ return;
27031
+ }
27032
+ function onConnect(newAddress) {
27033
+ if (wallet) {
27034
+ setConnectedWallet(squidTypes.ChainType.CANTON, {
27035
+ wallet,
27036
+ address: newAddress,
27037
+ });
27038
+ }
27039
+ }
27040
+ function onDisconnect() {
27041
+ disconnectWallet(squidTypes.ChainType.CANTON);
27042
+ }
27043
+ wallet.connector.on("connect", onConnect);
27044
+ wallet.connector.on("disconnect", onDisconnect);
27045
+ return () => {
27046
+ wallet.connector.off("connect", onConnect);
27047
+ wallet.connector.off("disconnect", onDisconnect);
27048
+ };
27049
+ }, [disconnectWallet, setConnectedWallet, connectedCantonWallet.wallet]);
27050
+ return {
27051
+ connectCanton,
27052
+ disconnectCanton,
27053
+ autoConnectCanton,
27054
+ signer: connectedCantonWallet.wallet?.connector,
27055
+ wallets,
27056
+ };
27057
+ }
27058
+
27059
+ const CantonContext = React.createContext(undefined);
27060
+ const CantonProvider = ({ children, }) => {
27061
+ const cantonHook = useCanton();
27062
+ return (React.createElement(CantonContext.Provider, { value: cantonHook }, children));
27063
+ };
27064
+ const useCantonContext = () => {
27065
+ const context = React.useContext(CantonContext);
27066
+ if (!context) {
27067
+ throw new Error("useCantonContext must be used within a CantonProvider");
27068
+ }
27069
+ return context;
27070
+ };
27071
+
26558
27072
  function useEvmWallets() {
26559
27073
  const connectors = wagmi.useConnectors();
26560
27074
  const wallets = React.useMemo(() => {
@@ -26766,7 +27280,7 @@ function useStellarWallets() {
26766
27280
  try {
26767
27281
  const { allowAllModules: initializeAllModules } = await import('@creit.tech/stellar-wallets-kit');
26768
27282
  const { LedgerModule } = await import('@creit.tech/stellar-wallets-kit/modules/ledger.module.mjs');
26769
- const { formatStellarWallet } = await Promise.resolve().then(function () { return require('./stellarService.client-C4TLBEpm.js'); });
27283
+ const { formatStellarWallet } = await Promise.resolve().then(function () { return require('./stellarService.client-DLPxIX3n.js'); });
26770
27284
  const modules = [...initializeAllModules(), new LedgerModule()];
26771
27285
  const promises = modules.map(async (module) => {
26772
27286
  const isAvailable = await module.isAvailable();
@@ -27239,17 +27753,24 @@ const useWallets = () => {
27239
27753
  const { wallets: suiWallets } = useSuiContext();
27240
27754
  const { wallets: xrplWallets } = useXrplContext();
27241
27755
  const { wallets: stellarWallets } = useStellarContext();
27756
+ const { wallets: cantonWallets } = useCantonContext();
27242
27757
  const wallets = React.useMemo(() => {
27243
27758
  const singleChainWallets$1 = populateWallets(clientWindow, singleChainWallets);
27244
27759
  const multiChainWallets$1 = populateWallets(clientWindow, multiChainWallets);
27760
+ const discoveredWallets = [
27761
+ ...evmWallets,
27762
+ ...solanaWallets,
27763
+ ...suiWallets,
27764
+ ...cantonWallets,
27765
+ ];
27766
+ const fallbackWallets = buildFallbackWallets(discoveredWallets);
27245
27767
  return mergeWallets({
27246
27768
  singleChainWallets: [
27247
27769
  ...singleChainWallets$1,
27248
- ...evmWallets,
27249
- ...solanaWallets,
27250
- ...suiWallets,
27770
+ ...discoveredWallets,
27251
27771
  ...xrplWallets,
27252
27772
  ...stellarWallets,
27773
+ ...fallbackWallets,
27253
27774
  ],
27254
27775
  multiChainWallets: multiChainWallets$1,
27255
27776
  });
@@ -27260,6 +27781,7 @@ const useWallets = () => {
27260
27781
  suiWallets,
27261
27782
  xrplWallets,
27262
27783
  stellarWallets,
27784
+ cantonWallets,
27263
27785
  ]);
27264
27786
  return {
27265
27787
  wallets,
@@ -27275,6 +27797,7 @@ const useWallet = () => {
27275
27797
  const { connectSui, disconnectSui } = useSuiContext();
27276
27798
  const { connectXrpl, disconnectXrpl } = useXrplContext();
27277
27799
  const { connectStellar, disconnectStellar } = useStellarContext();
27800
+ const { connectCanton, disconnectCanton } = useCantonContext();
27278
27801
  const { findChain } = useSquidChains();
27279
27802
  const { isGnosisConnected, gnosisAddress } = useGnosisContext();
27280
27803
  const destinationAddress = useSwapRoutePersistStore((state) => state.swapRoute?.destinationAddress);
@@ -27311,6 +27834,7 @@ const useWallet = () => {
27311
27834
  connectSui,
27312
27835
  connectXrpl,
27313
27836
  connectStellar,
27837
+ connectCanton,
27314
27838
  selectedChainTypes,
27315
27839
  findChain,
27316
27840
  });
@@ -27359,6 +27883,9 @@ const useWallet = () => {
27359
27883
  case squidTypes.ChainType.STELLAR:
27360
27884
  await disconnectStellar();
27361
27885
  break;
27886
+ case squidTypes.ChainType.CANTON:
27887
+ await disconnectCanton();
27888
+ break;
27362
27889
  default:
27363
27890
  // TODO: Implement disconnect for other chains
27364
27891
  break;
@@ -27465,6 +27992,7 @@ const useMultiChainWallet = (chain) => {
27465
27992
  const suiAddress = connectedAddresses[squidTypes.ChainType.SUI];
27466
27993
  const xrplAddress = connectedAddresses[squidTypes.ChainType.XRPL];
27467
27994
  const stellarAddress = connectedAddresses[squidTypes.ChainType.STELLAR];
27995
+ const cantonAddress = connectedAddresses[squidTypes.ChainType.CANTON];
27468
27996
  // Cosmos is a special case because the address changes on every chain
27469
27997
  // so we can't use the default cosmos connected address
27470
27998
  const { data: cosmosAddress } = useCosmosForChain(chain);
@@ -27552,6 +28080,16 @@ const useMultiChainWallet = (chain) => {
27552
28080
  chainType: chain.chainType,
27553
28081
  }),
27554
28082
  };
28083
+ case squidTypes.ChainType.CANTON:
28084
+ if (!cantonAddress)
28085
+ return {};
28086
+ return {
28087
+ address: cantonAddress,
28088
+ formatted: formatHash({
28089
+ hash: cantonAddress,
28090
+ chainType: chain.chainType,
28091
+ }),
28092
+ };
27555
28093
  }
27556
28094
  }, [
27557
28095
  chain?.chainType,
@@ -27563,6 +28101,7 @@ const useMultiChainWallet = (chain) => {
27563
28101
  suiAddress,
27564
28102
  xrplAddress,
27565
28103
  stellarAddress,
28104
+ cantonAddress,
27566
28105
  ]);
27567
28106
  /**
27568
28107
  * Change current network for desired chain
@@ -28387,6 +28926,8 @@ async function createClient(chain) {
28387
28926
  return new XrplRpcClient(chain.rpc);
28388
28927
  case squidTypes.ChainType.STELLAR:
28389
28928
  return new StellarRpcClient(chain.rpc);
28929
+ case squidTypes.ChainType.CANTON:
28930
+ return null;
28390
28931
  }
28391
28932
  }
28392
28933
 
@@ -29399,6 +29940,54 @@ const getAllStellarTokensBalance = async (userAddress, stellarTokens, stellarCha
29399
29940
  const allResults = await Promise.all(stellarChains.map(getBalancesForChain));
29400
29941
  return allResults.flat();
29401
29942
  };
29943
+ /**
29944
+ * Canton balances are private: they can only be read with a wallet-authorized
29945
+ * `ledgerApi` session (the connected wallet supplies a JWT that can read as the
29946
+ * party). So balance is fetchable only when a Canton wallet is connected, and
29947
+ * only for that wallet's party — there's no address-only read.
29948
+ */
29949
+ const getCantonTokenBalance = async (userAddress, token, cantonConnector) => {
29950
+ if (!token.originalAddress)
29951
+ return "0";
29952
+ const instrument = parseCantonInstrument(token.originalAddress);
29953
+ if (!instrument)
29954
+ return "0";
29955
+ const ledgerEnd = await cantonConnector.ledgerApi({ requestMethod: "get", resource: "/v2/state/ledger-end" });
29956
+ const activeContracts = await cantonConnector.ledgerApi({
29957
+ requestMethod: "post",
29958
+ resource: "/v2/state/active-contracts",
29959
+ body: buildHoldingsAcsRequestBody(userAddress, String(ledgerEnd.offset)),
29960
+ });
29961
+ const grouped = groupCantonHoldingBalances(activeContracts);
29962
+ return grouped[cantonInstrumentKey(instrument)] ?? "0";
29963
+ };
29964
+ /**
29965
+ * Fetch balances for all Canton tokens in one ACS query. Canton balances are
29966
+ * private, so this requires a connected wallet's authorized `ledgerApi`.
29967
+ */
29968
+ async function getAllCantonTokensBalance({ connector, partyId, tokens, }) {
29969
+ const ledgerEnd = await connector.ledgerApi({
29970
+ requestMethod: "get",
29971
+ resource: "/v2/state/ledger-end",
29972
+ });
29973
+ const activeContracts = await connector.ledgerApi({
29974
+ requestMethod: "post",
29975
+ resource: "/v2/state/active-contracts",
29976
+ body: buildHoldingsAcsRequestBody(partyId, String(ledgerEnd.offset)),
29977
+ });
29978
+ const grouped = groupCantonHoldingBalances(activeContracts);
29979
+ return tokens.map((token) => {
29980
+ const instrument = token.originalAddress
29981
+ ? parseCantonInstrument(token.originalAddress)
29982
+ : null;
29983
+ return {
29984
+ ...token,
29985
+ balance: instrument
29986
+ ? grouped[cantonInstrumentKey(instrument)] ?? "0"
29987
+ : "0",
29988
+ };
29989
+ });
29990
+ }
29402
29991
  /**
29403
29992
  * Returns a promise that resolves when the given promise resolves or after the given timeout
29404
29993
  * @param ms - timeout in milliseconds
@@ -29583,9 +30172,29 @@ const useStellarBalance = ({ userAddress, chain, enabled, token, refreshInterval
29583
30172
  });
29584
30173
  return { balance, isLoading };
29585
30174
  };
30175
+ const useCantonBalance = ({ chain, token, userAddress, enabled = true, refreshIntervalMs = DEFAULT_REFRESH_INTERVAL_MS$1, }) => {
30176
+ const cantonConnector = useWalletStore((store) => store.connectedWalletsByChainType[squidTypes.ChainType.CANTON]?.wallet?.connector);
30177
+ const { data: balance = "0", isLoading } = reactQuery.useQuery({
30178
+ queryKey: keys().balance(chain?.chainId, token?.address, userAddress),
30179
+ queryFn: async () => {
30180
+ if (!cantonConnector || !userAddress || !token)
30181
+ return "0";
30182
+ return getCantonTokenBalance(userAddress, token, cantonConnector);
30183
+ },
30184
+ enabled: enabled &&
30185
+ !!cantonConnector &&
30186
+ !!userAddress &&
30187
+ !!token &&
30188
+ chain?.chainType === squidTypes.ChainType.CANTON &&
30189
+ isCantonAddressValid(userAddress),
30190
+ refetchInterval: refreshIntervalMs,
30191
+ retry: 2,
30192
+ });
30193
+ return { balance, isLoading };
30194
+ };
29586
30195
 
29587
30196
  function useNativeTokenForChain(chain) {
29588
- const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, } = useSquidTokens();
30197
+ const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, cantonTokens, } = useSquidTokens();
29589
30198
  const getTokensForChainType = () => {
29590
30199
  if (!chain?.chainType)
29591
30200
  return [];
@@ -29604,6 +30213,8 @@ function useNativeTokenForChain(chain) {
29604
30213
  return xrplTokens;
29605
30214
  case squidTypes.ChainType.STELLAR:
29606
30215
  return stellarTokens;
30216
+ case squidTypes.ChainType.CANTON:
30217
+ return cantonTokens;
29607
30218
  }
29608
30219
  };
29609
30220
  const nativeTokenForChainType = React.useMemo(() => {
@@ -29785,6 +30396,24 @@ const useStellarNativeBalance = ({ address, chain, }) => {
29785
30396
  isLoading,
29786
30397
  };
29787
30398
  };
30399
+ const useCantonNativeBalance = ({ address, chain, }) => {
30400
+ const { nativeToken } = useNativeTokenForChain(chain);
30401
+ const { balance: rawBalance, isLoading } = useCantonBalance({
30402
+ chain,
30403
+ token: nativeToken,
30404
+ userAddress: address,
30405
+ enabled: chain?.chainType === squidTypes.ChainType.CANTON,
30406
+ });
30407
+ const balance = React.useMemo(() => {
30408
+ if (nativeToken?.decimals && rawBalance) {
30409
+ return {
30410
+ decimals: nativeToken.decimals,
30411
+ value: parseToBigInt(rawBalance, nativeToken.decimals),
30412
+ };
30413
+ }
30414
+ }, [nativeToken?.decimals, rawBalance]);
30415
+ return { balance, isLoading };
30416
+ };
29788
30417
  const useNativeBalance = (chain) => {
29789
30418
  const { connectedAddresses } = useWallet();
29790
30419
  const { data: cosmosAddressForChain } = useCosmosForChain(chain);
@@ -29815,6 +30444,10 @@ const useNativeBalance = (chain) => {
29815
30444
  address: connectedAddresses[squidTypes.ChainType.STELLAR],
29816
30445
  chain,
29817
30446
  });
30447
+ const { balance: nativeCantonBalance, isLoading: isCantonLoading } = useCantonNativeBalance({
30448
+ address: connectedAddresses[squidTypes.ChainType.CANTON],
30449
+ chain,
30450
+ });
29818
30451
  const { nativeBalance, nativeBalanceFormatted } = React.useMemo(() => {
29819
30452
  let balance;
29820
30453
  switch (chain?.chainType) {
@@ -29838,6 +30471,10 @@ const useNativeBalance = (chain) => {
29838
30471
  break;
29839
30472
  case squidTypes.ChainType.STELLAR:
29840
30473
  balance = nativeStellarBalance;
30474
+ break;
30475
+ case squidTypes.ChainType.CANTON:
30476
+ balance = nativeCantonBalance;
30477
+ break;
29841
30478
  }
29842
30479
  const balanceFormatted = !!balance
29843
30480
  ? formatBNToReadable(balance.value, balance.decimals)
@@ -29855,6 +30492,7 @@ const useNativeBalance = (chain) => {
29855
30492
  nativeSuiBalance,
29856
30493
  nativeXrplBalance,
29857
30494
  nativeStellarBalance,
30495
+ nativeCantonBalance,
29858
30496
  ]);
29859
30497
  const isLoading = React.useMemo(() => {
29860
30498
  if (!chain?.chainType)
@@ -29874,6 +30512,8 @@ const useNativeBalance = (chain) => {
29874
30512
  return isXrpLoading;
29875
30513
  case squidTypes.ChainType.STELLAR:
29876
30514
  return isStellarLoading;
30515
+ case squidTypes.ChainType.CANTON:
30516
+ return isCantonLoading;
29877
30517
  }
29878
30518
  }, [
29879
30519
  chain?.chainType,
@@ -29884,6 +30524,7 @@ const useNativeBalance = (chain) => {
29884
30524
  isSuiLoading,
29885
30525
  isXrpLoading,
29886
30526
  isStellarLoading,
30527
+ isCantonLoading,
29887
30528
  ]);
29888
30529
  return { nativeBalance, nativeBalanceFormatted, isLoading };
29889
30530
  };
@@ -30098,7 +30739,7 @@ function hederaWalletConnect(parameters) {
30098
30739
  const optionalChains = config.chains.map((x) => x.id);
30099
30740
  if (!optionalChains.length)
30100
30741
  return;
30101
- const { EthereumProvider } = await Promise.resolve().then(function () { return require('./index.es-1XEAWjab.js'); });
30742
+ const { EthereumProvider } = await Promise.resolve().then(function () { return require('./index.es-CuIvGVFi.js'); });
30102
30743
  const rawProvider = await EthereumProvider.init({
30103
30744
  ...restParameters,
30104
30745
  disableProviderPing: true,
@@ -30303,6 +30944,7 @@ const useSigner = ({ chain }) => {
30303
30944
  const { signer: suiSigner } = useSuiContext();
30304
30945
  const { signer: xrplSigner } = useXrplContext();
30305
30946
  const { signer: stellarSigner } = useStellarContext();
30947
+ const { signer: cantonSigner } = useCantonContext();
30306
30948
  const isEvmSignerReady = !!evmSigner;
30307
30949
  const isSolanaSignerReady = !!solanaSigner;
30308
30950
  const isCosmosSignerReady = !!cosmosSigner;
@@ -30310,6 +30952,7 @@ const useSigner = ({ chain }) => {
30310
30952
  const isSuiSignerReady = !!suiSigner;
30311
30953
  const isXrplSignerReady = !!xrplSigner;
30312
30954
  const isStellarSignerReady = !!stellarSigner;
30955
+ const isCantonSignerReady = !!cantonSigner;
30313
30956
  const isSignerReady = React.useMemo(() => {
30314
30957
  if (!chain?.chainType)
30315
30958
  return false;
@@ -30328,6 +30971,8 @@ const useSigner = ({ chain }) => {
30328
30971
  return isXrplSignerReady;
30329
30972
  case squidTypes.ChainType.STELLAR:
30330
30973
  return isStellarSignerReady;
30974
+ case squidTypes.ChainType.CANTON:
30975
+ return isCantonSignerReady;
30331
30976
  }
30332
30977
  }, [
30333
30978
  chain?.chainType,
@@ -30338,6 +30983,7 @@ const useSigner = ({ chain }) => {
30338
30983
  isSuiSignerReady,
30339
30984
  isXrplSignerReady,
30340
30985
  isStellarSignerReady,
30986
+ isCantonSignerReady,
30341
30987
  ]);
30342
30988
  return {
30343
30989
  isSignerReady,
@@ -30348,6 +30994,7 @@ const useSigner = ({ chain }) => {
30348
30994
  suiSigner,
30349
30995
  xrplSigner,
30350
30996
  stellarSigner,
30997
+ cantonSigner,
30351
30998
  };
30352
30999
  };
30353
31000
 
@@ -30777,21 +31424,21 @@ const useSendTransactionStore = zustand.create((set, get) => ({
30777
31424
 
30778
31425
  const useDepositAddressStore = zustand.create((set) => ({
30779
31426
  deposit: null,
30780
- isEnabled: false,
31427
+ selectedPaymentMethod: "connectedWallet",
30781
31428
  setDeposit: (data) => {
30782
31429
  set({ deposit: data });
30783
31430
  },
30784
- toggleDepositFlow: (enabled) => {
30785
- set({ isEnabled: enabled });
31431
+ setPaymentMethod: (method) => {
31432
+ set({ selectedPaymentMethod: method });
30786
31433
  },
30787
31434
  }));
30788
31435
 
30789
31436
  function useDepositAddress(squidRoute) {
30790
- const { isEnabled, depositAddress } = useDepositAddressStore((state) => ({
30791
- isEnabled: state.isEnabled,
31437
+ const { selectedPaymentMethod, depositAddress } = useDepositAddressStore((state) => ({
31438
+ selectedPaymentMethod: state.selectedPaymentMethod,
30792
31439
  depositAddress: state.deposit?.depositAddress,
30793
31440
  }));
30794
- const { setDeposit, toggleDepositFlow, deposit } = useDepositAddressStore();
31441
+ const { setDeposit, setPaymentMethod, deposit } = useDepositAddressStore();
30795
31442
  const { squid } = useSquidStore();
30796
31443
  const { fromChain } = useSwap();
30797
31444
  const isAvailableAsPaymentMethod = React.useMemo(() => {
@@ -30800,41 +31447,55 @@ function useDepositAddress(squidRoute) {
30800
31447
  const chainsSupportingDepositAddress = [
30801
31448
  CHAIN_IDS.BITCOIN,
30802
31449
  CHAIN_IDS.SOLANA,
31450
+ CHAIN_IDS.CANTON,
30803
31451
  ];
30804
31452
  return chainsSupportingDepositAddress.includes(fromChain.chainId);
30805
31453
  }, [fromChain?.chainId]);
30806
- const swapWillGenerateDepositAddress = React.useMemo(() => {
30807
- return (squidRoute?.transactionRequest?.type ===
30808
- squidTypes.SquidDataType.ChainflipDepositAddress);
30809
- }, [squidRoute?.transactionRequest?.type]);
30810
- const enable = React.useCallback(() => {
30811
- toggleDepositFlow(true);
30812
- }, [toggleDepositFlow]);
30813
- const disable = React.useCallback(() => {
30814
- toggleDepositFlow(false);
30815
- }, [toggleDepositFlow]);
31454
+ const routeProvidesDirectDepositAddress = !!squidRoute?.transactionRequest &&
31455
+ isDepositAddressDirectTransferRoute(squidRoute.transactionRequest);
31456
+ const swapWillGenerateDepositAddress = isChainflipDepositRoute(squidRoute) || routeProvidesDirectDepositAddress;
31457
+ const paymentMethod = isAvailableAsPaymentMethod
31458
+ ? selectedPaymentMethod
31459
+ : "connectedWallet";
31460
+ const routeSupportsDepositAddress = !squidRoute?.transactionRequest || swapWillGenerateDepositAddress;
31461
+ const isDepositAddressActive = paymentMethod === "depositAddress" && routeSupportsDepositAddress;
30816
31462
  const closeDepositChannel = React.useCallback(() => {
30817
- toggleDepositFlow(false);
30818
31463
  setDeposit(null);
30819
- }, [toggleDepositFlow, setDeposit]);
31464
+ }, [setDeposit]);
30820
31465
  const getRouteWithDeposit = reactQuery.useMutation(async ({ route }) => {
30821
- if (!squid)
30822
- throw new Error("Squid SDK not initialized");
30823
- const depositAddressResponse = (await squid.executeRoute({
30824
- signer: {},
30825
- route,
30826
- }));
30827
- setDeposit(depositAddressResponse);
30828
- return {
30829
- depositAddress: depositAddressResponse,
30830
- };
31466
+ if (!squid || !route.transactionRequest) {
31467
+ throw new Error("Missing required params");
31468
+ }
31469
+ if (isChainflipDepositRoute(route)) {
31470
+ const depositAddressResponse = (await squid.executeRoute({
31471
+ signer: {},
31472
+ route,
31473
+ }));
31474
+ setDeposit({
31475
+ amount: depositAddressResponse.amount,
31476
+ depositAddress: depositAddressResponse.depositAddress,
31477
+ statusTrackingId: depositAddressResponse.chainflipStatusTrackingId,
31478
+ });
31479
+ return;
31480
+ }
31481
+ else if (isDepositAddressDirectTransferRoute(route.transactionRequest)) {
31482
+ // Canton case
31483
+ const orderHash = route.transactionRequest.data;
31484
+ setDeposit({
31485
+ amount: route.params.fromAmount ?? "",
31486
+ depositAddress: route.transactionRequest.target,
31487
+ statusTrackingId: orderHash,
31488
+ memo: orderHash,
31489
+ });
31490
+ return;
31491
+ }
30831
31492
  });
30832
31493
  return {
30833
- isEnabled,
31494
+ paymentMethod,
31495
+ isDepositAddressActive,
30834
31496
  isAvailableAsPaymentMethod,
30835
31497
  swapWillGenerateDepositAddress,
30836
- enable,
30837
- disable,
31498
+ setPaymentMethod,
30838
31499
  getRouteWithDeposit,
30839
31500
  depositAddress,
30840
31501
  closeDepositChannel,
@@ -30866,8 +31527,9 @@ const useUrlSwapParams = () => {
30866
31527
 
30867
31528
  const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, queryOptions, }) => {
30868
31529
  const { evmChains, cosmosChains, suiChains, xrplChains, stellarChains } = useSquidChains(direction);
30869
- const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, } = useSquidTokens(direction);
31530
+ const { evmTokens, cosmosTokens, solanaTokens, bitcoinTokens, suiTokens, xrplTokens, stellarTokens, cantonTokens, } = useSquidTokens(direction);
30870
31531
  const { keplrTypeWallet } = useCosmosContext();
31532
+ const cantonConnector = useWalletStore((store) => store.connectedWalletsByChainType[squidTypes.ChainType.CANTON]?.wallet?.connector);
30871
31533
  const placeholderData = React.useMemo(() => {
30872
31534
  const tokens = {
30873
31535
  [squidTypes.ChainType.EVM]: evmTokens.map((t) => ({ ...t, balance: "0" })),
@@ -30877,6 +31539,7 @@ const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, qu
30877
31539
  [squidTypes.ChainType.SUI]: suiTokens.map((t) => ({ ...t, balance: "0" })),
30878
31540
  [squidTypes.ChainType.XRPL]: xrplTokens.map((t) => ({ ...t, balance: "0" })),
30879
31541
  [squidTypes.ChainType.STELLAR]: stellarTokens.map((t) => ({ ...t, balance: "0" })),
31542
+ [squidTypes.ChainType.CANTON]: cantonTokens.map((t) => ({ ...t, balance: "0" })),
30880
31543
  };
30881
31544
  if (!chainType) {
30882
31545
  // Return all tokens with zero balance
@@ -30898,6 +31561,7 @@ const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, qu
30898
31561
  suiTokens,
30899
31562
  xrplTokens,
30900
31563
  stellarTokens,
31564
+ cantonTokens,
30901
31565
  ]);
30902
31566
  const isQueryEnabled = React.useMemo(() => {
30903
31567
  // Respect the queryOptions.enabled override if provided
@@ -30920,6 +31584,8 @@ const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, qu
30920
31584
  return xrplTokens.length > 0;
30921
31585
  case squidTypes.ChainType.STELLAR:
30922
31586
  return stellarTokens.length > 0;
31587
+ case squidTypes.ChainType.CANTON:
31588
+ return cantonTokens.length > 0;
30923
31589
  }
30924
31590
  }, [
30925
31591
  chainType,
@@ -30932,6 +31598,7 @@ const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, qu
30932
31598
  suiTokens.length,
30933
31599
  xrplTokens.length,
30934
31600
  stellarTokens.length,
31601
+ cantonTokens.length,
30935
31602
  ]);
30936
31603
  const query = reactQuery.useQuery(keys().allTokensBalance(address, chainType, direction), async () => {
30937
31604
  // Return zero balances if no address
@@ -30971,6 +31638,15 @@ const useAllTokensWithBalanceForChainType = ({ chainType, address, direction, qu
30971
31638
  case squidTypes.ChainType.STELLAR:
30972
31639
  fetchedTokens = await getAllStellarTokensBalance(address, stellarTokens, stellarChains);
30973
31640
  break;
31641
+ case squidTypes.ChainType.CANTON:
31642
+ fetchedTokens = cantonConnector
31643
+ ? await getAllCantonTokensBalance({
31644
+ connector: cantonConnector,
31645
+ partyId: address,
31646
+ tokens: cantonTokens,
31647
+ })
31648
+ : placeholderData.tokens;
31649
+ break;
30974
31650
  default:
30975
31651
  fetchedTokens = placeholderData.tokens;
30976
31652
  break;
@@ -31041,6 +31717,12 @@ const useAllConnectedWalletBalances = ({ direction, queryOptions = {
31041
31717
  direction,
31042
31718
  queryOptions,
31043
31719
  });
31720
+ const cantonBalancesQuery = useAllTokensWithBalanceForChainType({
31721
+ chainType: squidTypes.ChainType.CANTON,
31722
+ address: connectedAddresses?.[squidTypes.ChainType.CANTON],
31723
+ direction,
31724
+ queryOptions,
31725
+ });
31044
31726
  // Create a map of chain type to balance query results
31045
31727
  const balanceQueries = React.useMemo(() => ({
31046
31728
  [squidTypes.ChainType.EVM]: evmBalancesQuery,
@@ -31050,6 +31732,7 @@ const useAllConnectedWalletBalances = ({ direction, queryOptions = {
31050
31732
  [squidTypes.ChainType.SUI]: suiBalancesQuery,
31051
31733
  [squidTypes.ChainType.XRPL]: xrplBalancesQuery,
31052
31734
  [squidTypes.ChainType.STELLAR]: stellarBalancesQuery,
31735
+ [squidTypes.ChainType.CANTON]: cantonBalancesQuery,
31053
31736
  }), [
31054
31737
  evmBalancesQuery,
31055
31738
  cosmosBalancesQuery,
@@ -31058,6 +31741,7 @@ const useAllConnectedWalletBalances = ({ direction, queryOptions = {
31058
31741
  suiBalancesQuery,
31059
31742
  xrplBalancesQuery,
31060
31743
  stellarBalancesQuery,
31744
+ cantonBalancesQuery,
31061
31745
  ]);
31062
31746
  // Combine all tokens from different chains
31063
31747
  const allTokens = React.useMemo(() => Object.values(balanceQueries).flatMap((query) => query.data?.tokens ?? []), [balanceQueries]);
@@ -31139,6 +31823,12 @@ const useMultiChainBalance = ({ chain, token, userAddress, enabled = true, }) =>
31139
31823
  userAddress,
31140
31824
  enabled: chain?.chainType === squidTypes.ChainType.STELLAR && enabled,
31141
31825
  });
31826
+ const { balance: cantonBalance } = useCantonBalance({
31827
+ chain,
31828
+ token,
31829
+ userAddress,
31830
+ enabled: chain?.chainType === squidTypes.ChainType.CANTON && enabled,
31831
+ });
31142
31832
  const balance = React.useMemo(() => {
31143
31833
  if (!chain?.chainType)
31144
31834
  return "0";
@@ -31157,6 +31847,8 @@ const useMultiChainBalance = ({ chain, token, userAddress, enabled = true, }) =>
31157
31847
  return xrplBalance;
31158
31848
  case squidTypes.ChainType.STELLAR:
31159
31849
  return stellarBalance;
31850
+ case squidTypes.ChainType.CANTON:
31851
+ return cantonBalance;
31160
31852
  }
31161
31853
  }, [
31162
31854
  chain?.chainType,
@@ -31167,6 +31859,7 @@ const useMultiChainBalance = ({ chain, token, userAddress, enabled = true, }) =>
31167
31859
  suiBalance,
31168
31860
  xrplBalance,
31169
31861
  stellarBalance,
31862
+ cantonBalance,
31170
31863
  ]);
31171
31864
  return { balance };
31172
31865
  };
@@ -31636,7 +32329,7 @@ const calculateEstimateResults = ({ squidRoute, tokens, fromChain, toChain, coll
31636
32329
  });
31637
32330
  // gas fees + fromAmount (if fromToken is gas token)
31638
32331
  const totalGasBalanceNeeded = networkFeesWei +
31639
- BigInt(chainFeeParams?.fromTokenPaysGasFees ? fromAmount ?? 0 : 0);
32332
+ BigInt(chainFeeParams?.fromTokenPaysGasFees ? (fromAmount ?? 0) : 0);
31640
32333
  const gasBalanceNeeded = gasToken
31641
32334
  ? formatBNToReadable(totalGasBalanceNeeded, gasToken.decimals)
31642
32335
  : undefined;
@@ -31813,7 +32506,7 @@ function useEstimateSendTransaction({ chain, token, amount, balance, from, }) {
31813
32506
  return undefined;
31814
32507
  // gas fees + fromAmount (if fromToken is gas token)
31815
32508
  const totalGasBalanceNeeded = estimatedGas +
31816
- parseToBigInt(chainFeeParams?.fromTokenPaysGasFees ? amount ?? "0" : "0", token.decimals);
32509
+ parseToBigInt(chainFeeParams?.fromTokenPaysGasFees ? (amount ?? "0") : "0", token.decimals);
31817
32510
  return formatBNToReadable(totalGasBalanceNeeded, gasToken.decimals);
31818
32511
  }, [
31819
32512
  amount,
@@ -32265,6 +32958,9 @@ function useSendTransaction({ to, amount, token, chain, }) {
32265
32958
  chain,
32266
32959
  });
32267
32960
  break;
32961
+ case squidTypes.ChainType.CANTON: {
32962
+ throw new Error("Not implemented");
32963
+ }
32268
32964
  }
32269
32965
  return {
32270
32966
  amount,
@@ -32468,6 +33164,8 @@ async function getSendTransactionStatus({ chain, txHash, }) {
32468
33164
  txHash,
32469
33165
  chain,
32470
33166
  });
33167
+ case squidTypes.ChainType.CANTON:
33168
+ throw new Error("Not implemented");
32471
33169
  }
32472
33170
  }
32473
33171
 
@@ -32491,7 +33189,7 @@ const useHistory = (txType) => {
32491
33189
  fromChain: tx.params.fromChain,
32492
33190
  fromToken: tx.params.fromToken,
32493
33191
  fromAddress: tx.params.fromAddress,
32494
- fromAmount: tx.params.fromAmount,
33192
+ fromAmount: tx.params.fromAmount ?? "",
32495
33193
  toChain: tx.params.toChain,
32496
33194
  toToken: tx.params.toToken,
32497
33195
  toAddress: tx.params.toAddress,
@@ -32919,6 +33617,129 @@ const useApproval = ({ squidRoute, }) => {
32919
33617
  };
32920
33618
  };
32921
33619
 
33620
+ const useSwapStatusQuery = ({ transaction, retry = 25, refetchOnWindowFocus = "always", enabled = true, onStatus, onEndStatus, onNotFound, onError, }) => {
33621
+ const config = useConfigStore((state) => state.config);
33622
+ const isInitialized = useConfigStore((state) => state.isInitialized);
33623
+ const [isTransactionComplete, setIsTransactionComplete] = React.useState(false);
33624
+ const [refetchInterval, setRefetchInterval] = React.useState(getSwapTxStatusRefetchInterval(transaction));
33625
+ const { getChainType } = useSquidChains();
33626
+ const fetchTransactionStatusWithLatestConfig = React.useCallback(async () => {
33627
+ const latestConfig = useConfigStore.getState().config;
33628
+ return fetchSwapTransactionStatus({
33629
+ transaction,
33630
+ integratorId: latestConfig.integratorId,
33631
+ apiUrl: latestConfig.apiUrl,
33632
+ });
33633
+ }, [transaction]);
33634
+ const transactionStatusQuery = reactQuery.useQuery(keys().swapTransactionStatus(transaction?.transactionId), fetchTransactionStatusWithLatestConfig, {
33635
+ enabled: enabled &&
33636
+ transaction?.transactionId !== "0" &&
33637
+ !!transaction?.transactionId &&
33638
+ !!transaction.fromAddress &&
33639
+ !!config.apiUrl &&
33640
+ transaction !== undefined &&
33641
+ !isTransactionComplete &&
33642
+ isInitialized,
33643
+ refetchInterval(statusResponse) {
33644
+ if (statusResponse &&
33645
+ transactionEndStatuses.includes(getTransactionStatus(statusResponse) ?? "")) {
33646
+ return false;
33647
+ }
33648
+ return refetchInterval;
33649
+ },
33650
+ retryDelay: getChainType(transaction?.fromChain) === squidTypes.ChainType.COSMOS ? 5000 : 3000,
33651
+ retry: getChainType(transaction?.fromChain) === squidTypes.ChainType.COSMOS ? 6 : retry,
33652
+ refetchOnWindowFocus,
33653
+ onSuccess: (statusResponse) => {
33654
+ WidgetEvents.getInstance().dispatchSwapStatus(statusResponse.squidTransactionStatus ?? "");
33655
+ onStatus?.({
33656
+ status: getTransactionStatus(statusResponse) ?? "",
33657
+ statusResponse,
33658
+ });
33659
+ const endStatus = getTransactionEndStatus({ statusResponse });
33660
+ if (endStatus) {
33661
+ setIsTransactionComplete(true);
33662
+ onEndStatus?.({ status: endStatus, statusResponse });
33663
+ }
33664
+ },
33665
+ onError: (error) => {
33666
+ if (is404Error(error.cause)) {
33667
+ onNotFound?.();
33668
+ return;
33669
+ }
33670
+ setRefetchInterval(-1);
33671
+ setIsTransactionComplete(true);
33672
+ onError?.();
33673
+ },
33674
+ });
33675
+ return {
33676
+ transactionStatusQuery,
33677
+ };
33678
+ };
33679
+
33680
+ // Statuses that indicate the source deposit has been received
33681
+ // and the swap is now progressing.
33682
+ const sourceReceivedStatuses = [
33683
+ // Chainflip
33684
+ "DEPOSIT_RECEIVED",
33685
+ "BROADCAST_REQUESTED",
33686
+ "COMPLETE",
33687
+ "SWAPPING",
33688
+ // Canton (Squid Intents)
33689
+ "awaiting",
33690
+ "success",
33691
+ ];
33692
+ /**
33693
+ * Tracks a deposit address intent before it becomes a persisted swap history item.
33694
+ *
33695
+ * Once the source deposit is received, it registers the transaction in the transaction
33696
+ * and history stores, then signals the view via `onReceived` to navigate.
33697
+ */
33698
+ const useDepositTransactionStatus = ({ transaction, route, retry = 25, refetchOnWindowFocus = "always", enabled = true, onReceived, }) => {
33699
+ const { fromChain, toChain } = useSwap();
33700
+ const { addSwapTransaction } = useHistory();
33701
+ const getTransaction = useTransactionStore((state) => state.getTransaction);
33702
+ const setTransactionStoreState = useTransactionStore((state) => state.setTransactionState);
33703
+ return useSwapStatusQuery({
33704
+ transaction,
33705
+ retry,
33706
+ refetchOnWindowFocus,
33707
+ enabled,
33708
+ onStatus: ({ status }) => {
33709
+ if (!sourceReceivedStatuses.includes(status))
33710
+ return;
33711
+ if (!transaction?.transactionId || !route?.transactionRequest)
33712
+ return;
33713
+ const { transactionId } = transaction;
33714
+ if (getTransaction(transactionId))
33715
+ return;
33716
+ useTransactionStore.setState({
33717
+ txLocalId: transactionId,
33718
+ currentTransaction: undefined,
33719
+ });
33720
+ const tx = {
33721
+ routeType: route.transactionRequest.type,
33722
+ fromChain,
33723
+ toChain,
33724
+ fromAddress: transaction.fromAddress,
33725
+ transactionId,
33726
+ transactionIdForStatus: transaction.transactionIdForStatus,
33727
+ quoteId: transaction.quoteId ?? "",
33728
+ status: exports.TransactionStatus.ONGOING,
33729
+ sourceStatus: exports.TransactionStatus.SUCCESS,
33730
+ timestamp: Date.now(),
33731
+ };
33732
+ setTransactionStoreState(transactionId, tx);
33733
+ addSwapTransaction({
33734
+ ...tx,
33735
+ params: route.params,
33736
+ estimate: route.estimate,
33737
+ });
33738
+ onReceived?.();
33739
+ },
33740
+ });
33741
+ };
33742
+
32922
33743
  const DEFAULT_PROVIDER_IMAGE_URL = "https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/providers/squid.webp";
32923
33744
  const AXELAR_PROVIDER_IMAGE_URL = "https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/providers/axelar.webp";
32924
33745
  const useEstimate = (squidRoute) => {
@@ -35965,6 +36786,342 @@ coin.DecProto = {
35965
36786
 
35966
36787
  } (tx));
35967
36788
 
36789
+ const vParty = (party) => ({ party });
36790
+ const vText = (text) => ({ text });
36791
+ const vNumeric = (numeric) => ({ numeric });
36792
+ const vContractId = (contractId) => ({
36793
+ contractId,
36794
+ });
36795
+ const vList = (elements) => ({
36796
+ list: { elements },
36797
+ });
36798
+ const vRecord = (fields) => ({
36799
+ record: { fields: fields.map(([label, value]) => ({ label, value })) },
36800
+ });
36801
+ const vTextMap = (entries) => ({ textMap: { entries } });
36802
+ const vTimestamp = (isoString) => ({
36803
+ timestamp: String(Math.floor(new Date(isoString).getTime() * 1000)),
36804
+ });
36805
+ function isRecord(value) {
36806
+ return typeof value === "object" && value !== null && !Array.isArray(value);
36807
+ }
36808
+ function normalizeChoiceContextValue(value) {
36809
+ if (typeof value === "string")
36810
+ return value;
36811
+ if (!isRecord(value) || typeof value.tag !== "string")
36812
+ return null;
36813
+ switch (value.tag) {
36814
+ case "AV_Text":
36815
+ case "AV_ContractId":
36816
+ return typeof value.value === "string"
36817
+ ? { tag: value.tag, value: value.value }
36818
+ : null;
36819
+ case "AV_Bool":
36820
+ return typeof value.value === "boolean"
36821
+ ? { tag: value.tag, value: value.value }
36822
+ : null;
36823
+ case "AV_List":
36824
+ if (!Array.isArray(value.value))
36825
+ return null;
36826
+ return {
36827
+ tag: value.tag,
36828
+ value: value.value.flatMap((entry) => {
36829
+ const normalized = normalizeChoiceContextValue(entry);
36830
+ return normalized ? [normalized] : [];
36831
+ }),
36832
+ };
36833
+ default: {
36834
+ const inner = value.value;
36835
+ if (typeof inner === "string" ||
36836
+ typeof inner === "number" ||
36837
+ typeof inner === "boolean" ||
36838
+ inner === null) {
36839
+ return { tag: value.tag, value: inner };
36840
+ }
36841
+ if (Array.isArray(inner)) {
36842
+ return {
36843
+ tag: value.tag,
36844
+ value: inner.flatMap((entry) => {
36845
+ const normalized = normalizeChoiceContextValue(entry);
36846
+ return normalized ? [normalized] : [];
36847
+ }),
36848
+ };
36849
+ }
36850
+ if (!isRecord(inner))
36851
+ return null;
36852
+ const normalizedObject = {};
36853
+ for (const [key, entry] of Object.entries(inner)) {
36854
+ if (typeof entry !== "string" &&
36855
+ typeof entry !== "number" &&
36856
+ typeof entry !== "boolean" &&
36857
+ entry !== null) {
36858
+ return null;
36859
+ }
36860
+ normalizedObject[key] = entry;
36861
+ }
36862
+ return { tag: value.tag, value: normalizedObject };
36863
+ }
36864
+ }
36865
+ }
36866
+ function stringifyChoiceContextValue(value) {
36867
+ return typeof value === "string" ? value : String(value);
36868
+ }
36869
+ function choiceContextValueToAnyValue(value) {
36870
+ if (typeof value === "string") {
36871
+ return {
36872
+ variant: { constructor: "AV_Text", value: vText(value) },
36873
+ };
36874
+ }
36875
+ switch (value.tag) {
36876
+ case "AV_ContractId":
36877
+ if (typeof value.value !== "string") {
36878
+ throw new TypeError("AV_ContractId values must be strings");
36879
+ }
36880
+ return {
36881
+ variant: { constructor: value.tag, value: vContractId(value.value) },
36882
+ };
36883
+ case "AV_Bool":
36884
+ if (typeof value.value !== "boolean") {
36885
+ throw new TypeError("AV_Bool values must be booleans");
36886
+ }
36887
+ return {
36888
+ variant: { constructor: value.tag, value: { bool: value.value } },
36889
+ };
36890
+ case "AV_List":
36891
+ if (!Array.isArray(value.value)) {
36892
+ throw new TypeError("AV_List values must be arrays");
36893
+ }
36894
+ return {
36895
+ variant: {
36896
+ constructor: value.tag,
36897
+ value: vList(value.value.map(choiceContextValueToAnyValue)),
36898
+ },
36899
+ };
36900
+ default:
36901
+ return {
36902
+ variant: {
36903
+ constructor: value.tag,
36904
+ value: vText(stringifyChoiceContextValue(value.value)),
36905
+ },
36906
+ };
36907
+ }
36908
+ }
36909
+
36910
+ /** Metadata key used by Splice token-standard transfers to carry our Squid orderhash memo. */
36911
+ const CANTON_MEMO_KEY = "splice.lfdecentralizedtrust.org/reason";
36912
+ /** Interface id for the transfer factory contract returned by the token registry. */
36913
+ const TRANSFER_FACTORY_INTERFACE_ID = "#splice-api-token-transfer-instruction-v1:Splice.Api.Token.TransferInstructionV1:TransferFactory";
36914
+ /** Choice exercised on the transfer factory to create the token-standard transfer. */
36915
+ const TRANSFER_FACTORY_CHOICE = "TransferFactory_Transfer";
36916
+ /** CIP-056 (non-Amulet) tokens expose a registrar parameterized by admin party. */
36917
+ const CIP056_REGISTRAR_BASE = "https://api.utilities.digitalasset.com/api/token-standard/v0/registrars";
36918
+ const TRANSFER_REQUESTED_AT_SKEW_MS = 60_000;
36919
+ const TRANSFER_EXECUTE_WINDOW_MS = 24 * 60 * 60 * 1000;
36920
+ function resolveCantonRegistryUrl(instrument) {
36921
+ if (instrument.id === CANTON_AMULET_INSTRUMENT_ID) {
36922
+ return CANTON_AMULET_REGISTRY_URL;
36923
+ }
36924
+ return `${CIP056_REGISTRAR_BASE}/${encodeURIComponent(instrument.admin)}`;
36925
+ }
36926
+ /**
36927
+ * Build the plain JSON arguments expected by the registry transfer-factory
36928
+ * endpoint before it adds choice context and disclosed contracts.
36929
+ */
36930
+ function buildTransferChoiceArgs({ sender, receiver, amount, instrument, inputHoldingCids, memo, nowMs, }) {
36931
+ return {
36932
+ expectedAdmin: instrument.admin,
36933
+ transfer: {
36934
+ sender,
36935
+ receiver,
36936
+ amount,
36937
+ instrumentId: { admin: instrument.admin, id: instrument.id },
36938
+ requestedAt: new Date(nowMs - TRANSFER_REQUESTED_AT_SKEW_MS).toISOString(),
36939
+ executeBefore: new Date(nowMs + TRANSFER_EXECUTE_WINDOW_MS).toISOString(),
36940
+ inputHoldingCids,
36941
+ meta: { values: { [CANTON_MEMO_KEY]: memo } },
36942
+ },
36943
+ extraArgs: { context: { values: {} }, meta: { values: {} } },
36944
+ };
36945
+ }
36946
+ /**
36947
+ * Canton's Holding contracts follow Bitcoin-style UTXOs model.
36948
+ *
36949
+ * Pick Holding contract ids covering `amount` for the instrument: prefer a
36950
+ * single exact-amount holding, else accumulate largest-first.
36951
+ */
36952
+ function selectInputHoldingCids(holdings, instrument, amount) {
36953
+ const spendableHoldings = holdings.filter((h) => !h.locked &&
36954
+ h.instrument.admin === instrument.admin &&
36955
+ h.instrument.id === instrument.id);
36956
+ const target = new BigNumber(amount);
36957
+ const exact = spendableHoldings.find((h) => new BigNumber(h.amount).eq(target));
36958
+ if (exact)
36959
+ return [exact.contractId];
36960
+ const sorted = [...spendableHoldings].sort((a, b) => new BigNumber(b.amount).comparedTo(new BigNumber(a.amount)));
36961
+ const selected = [];
36962
+ let sum = new BigNumber(0);
36963
+ for (const holding of sorted) {
36964
+ selected.push(holding.contractId);
36965
+ sum = sum.plus(holding.amount);
36966
+ if (sum.gte(target))
36967
+ break;
36968
+ }
36969
+ if (sum.lt(target)) {
36970
+ throw new Error("Insufficient Canton holdings to cover transfer amount");
36971
+ }
36972
+ return selected;
36973
+ }
36974
+ async function fetchInputHoldingCids(connector, party, instrument, amount) {
36975
+ const ledgerEnd = await connector.ledgerApi({
36976
+ requestMethod: "get",
36977
+ resource: "/v2/state/ledger-end",
36978
+ });
36979
+ const activeContracts = await connector.ledgerApi({
36980
+ requestMethod: "post",
36981
+ resource: "/v2/state/active-contracts",
36982
+ body: buildHoldingsAcsRequestBody(party, String(ledgerEnd.offset)),
36983
+ });
36984
+ return selectInputHoldingCids(parseCantonHoldings(activeContracts), instrument, amount);
36985
+ }
36986
+ /**
36987
+ * Ask the token registry for the transfer factory contract and extra context
36988
+ * required to exercise its transfer choice.
36989
+ */
36990
+ async function fetchTransferFactory(registryUrl, choiceArgs) {
36991
+ const response = await fetch(`${registryUrl}/registry/transfer-instruction/v1/transfer-factory`, {
36992
+ method: "POST",
36993
+ headers: { "Content-Type": "application/json" },
36994
+ body: JSON.stringify({
36995
+ choiceArguments: choiceArgs,
36996
+ excludeDebugFields: true,
36997
+ }),
36998
+ });
36999
+ if (!response.ok) {
37000
+ throw new Error(`Canton transfer-factory request failed (${response.status})`);
37001
+ }
37002
+ return response.json();
37003
+ }
37004
+ /**
37005
+ * Convert transfer choice args into strict Daml Value JSON for the wallet's
37006
+ * prepareExecute ExerciseCommand.
37007
+ */
37008
+ function buildPrepareChoiceArgument(choiceArgs) {
37009
+ const contextValues = Object.entries(choiceArgs.extraArgs.context?.values ?? {})
37010
+ .map(([key, value]) => {
37011
+ const normalized = normalizeChoiceContextValue(value);
37012
+ return normalized
37013
+ ? { key, value: choiceContextValueToAnyValue(normalized) }
37014
+ : undefined;
37015
+ })
37016
+ .filter((entry) => Boolean(entry));
37017
+ return vRecord([
37018
+ ["expectedAdmin", vParty(choiceArgs.expectedAdmin)],
37019
+ [
37020
+ "transfer",
37021
+ vRecord([
37022
+ ["sender", vParty(choiceArgs.transfer.sender)],
37023
+ ["receiver", vParty(choiceArgs.transfer.receiver)],
37024
+ ["amount", vNumeric(choiceArgs.transfer.amount)],
37025
+ [
37026
+ "instrumentId",
37027
+ vRecord([
37028
+ ["admin", vParty(choiceArgs.transfer.instrumentId.admin)],
37029
+ ["id", vText(choiceArgs.transfer.instrumentId.id)],
37030
+ ]),
37031
+ ],
37032
+ ["requestedAt", vTimestamp(choiceArgs.transfer.requestedAt)],
37033
+ ["executeBefore", vTimestamp(choiceArgs.transfer.executeBefore)],
37034
+ [
37035
+ "inputHoldingCids",
37036
+ vList(choiceArgs.transfer.inputHoldingCids.map(vContractId)),
37037
+ ],
37038
+ [
37039
+ "meta",
37040
+ vRecord([
37041
+ [
37042
+ "values",
37043
+ vTextMap(Object.entries(choiceArgs.transfer.meta.values).map(([key, value]) => ({ key, value: vText(value) }))),
37044
+ ],
37045
+ ]),
37046
+ ],
37047
+ ]),
37048
+ ],
37049
+ [
37050
+ "extraArgs",
37051
+ vRecord([
37052
+ ["context", vRecord([["values", vTextMap(contextValues)]])],
37053
+ ["meta", vRecord([["values", vTextMap([])]])],
37054
+ ]),
37055
+ ],
37056
+ ]);
37057
+ }
37058
+ /**
37059
+ * Convert a registry disclosed contract into the wallet submission shape,
37060
+ * dropping debug fields and entries without a usable createdEventBlob.
37061
+ */
37062
+ function toDisclosedContract(raw) {
37063
+ if (typeof raw.createdEventBlob !== "string")
37064
+ return null;
37065
+ return {
37066
+ createdEventBlob: raw.createdEventBlob,
37067
+ contractId: typeof raw.contractId === "string" ? raw.contractId : undefined,
37068
+ synchronizerId: typeof raw.synchronizerId === "string" ? raw.synchronizerId : undefined,
37069
+ };
37070
+ }
37071
+ /**
37072
+ * Build a Splice token-standard transfer of `amount` of `token` from `sender`
37073
+ * to `receiver`, carrying `memo`, ready to hand to a wallet's prepareExecute.
37074
+ * Returns the full prepareExecute params (commandId + commands + actAs +
37075
+ * disclosedContracts).
37076
+ */
37077
+ async function buildCantonTransfer(connector, { sender, receiver, amount, token, memo, nowMs, }) {
37078
+ if (!token.originalAddress) {
37079
+ throw new Error("Canton token originalAddress is required");
37080
+ }
37081
+ const instrument = parseCantonInstrument(token.originalAddress);
37082
+ if (!instrument) {
37083
+ throw new Error(`Invalid Canton token address: ${token.originalAddress}`);
37084
+ }
37085
+ const registryUrl = resolveCantonRegistryUrl(instrument);
37086
+ const inputHoldingCids = await fetchInputHoldingCids(connector, sender, instrument, amount);
37087
+ const choiceArgs = buildTransferChoiceArgs({
37088
+ sender,
37089
+ receiver,
37090
+ amount,
37091
+ instrument,
37092
+ inputHoldingCids,
37093
+ memo,
37094
+ nowMs,
37095
+ });
37096
+ const factory = await fetchTransferFactory(registryUrl, choiceArgs);
37097
+ const choiceContextData = factory.choiceContext.choiceContextData;
37098
+ if (!choiceContextData) {
37099
+ throw new Error("Transfer factory choice context is missing");
37100
+ }
37101
+ choiceArgs.extraArgs.context = choiceContextData;
37102
+ const disclosedContracts = (factory.choiceContext?.disclosedContracts ?? []).flatMap((raw) => {
37103
+ const disclosedContract = toDisclosedContract(raw);
37104
+ return disclosedContract ? [disclosedContract] : [];
37105
+ });
37106
+ // Command ID: client-supplied identifier used to deduplicate submissions
37107
+ const commandId = `canton-${memo}`;
37108
+ return {
37109
+ commandId,
37110
+ commands: [
37111
+ {
37112
+ ExerciseCommand: {
37113
+ templateId: TRANSFER_FACTORY_INTERFACE_ID,
37114
+ contractId: factory.factoryId,
37115
+ choice: TRANSFER_FACTORY_CHOICE,
37116
+ choiceArgument: buildPrepareChoiceArgument(choiceArgs),
37117
+ },
37118
+ },
37119
+ ],
37120
+ actAs: [sender],
37121
+ disclosedContracts,
37122
+ };
37123
+ }
37124
+
35968
37125
  const useExecuteTransaction = (squidRoute) => {
35969
37126
  const { fromChain, toChain, fromToken, toToken, isSameChain } = useSwap();
35970
37127
  // A route completes on source tx only if it's same-chain AND
@@ -35973,7 +37130,7 @@ const useExecuteTransaction = (squidRoute) => {
35973
37130
  !!fromChain &&
35974
37131
  !!squidRoute &&
35975
37132
  squidRoute.estimate.actions.every((a) => isActionCompletedOnSourceTx(a, fromChain.chainId));
35976
- const { evmSigner, cosmosSigner, solanaSigner, bitcoinSigner, suiSigner, xrplSigner, stellarSigner, } = useSigner({
37133
+ const { evmSigner, cosmosSigner, solanaSigner, bitcoinSigner, suiSigner, xrplSigner, stellarSigner, cantonSigner, } = useSigner({
35977
37134
  chain: fromChain,
35978
37135
  });
35979
37136
  const { findToken } = useSquidTokens();
@@ -36228,7 +37385,7 @@ const useExecuteTransaction = (squidRoute) => {
36228
37385
  });
36229
37386
  const swapMutationSolana = reactQuery.useMutation(async ({ id, route }) => {
36230
37387
  try {
36231
- if (!route) {
37388
+ if (!route?.transactionRequest) {
36232
37389
  throw new Error("Route is required");
36233
37390
  }
36234
37391
  if (!solanaSigner) {
@@ -36237,10 +37394,10 @@ const useExecuteTransaction = (squidRoute) => {
36237
37394
  if (!route.params.fromAddress || !route.params.toAddress) {
36238
37395
  throw new Error("From or to address is required");
36239
37396
  }
36240
- const isDirectTransfer = isDepositRoute(route);
37397
+ const isChainflipDirectTransfer = isChainflipDepositRoute(route);
36241
37398
  // Means it's a transfer to a deposit address
36242
37399
  // Instead of a Swap/Contract call using a DEX like Jupiter
36243
- if (isDirectTransfer) {
37400
+ if (isChainflipDirectTransfer) {
36244
37401
  // Get the deposit address from the squidRoute
36245
37402
  const depositData = useDepositAddressStore.getState().deposit;
36246
37403
  // Validate params
@@ -36248,7 +37405,7 @@ const useExecuteTransaction = (squidRoute) => {
36248
37405
  throw new Error("Deposit address is required");
36249
37406
  }
36250
37407
  const signature = await executeSolanaTransfer({
36251
- amount: BigInt(route.params.fromAmount),
37408
+ amount: BigInt(route.params.fromAmount ?? ""),
36252
37409
  target: depositData.depositAddress,
36253
37410
  signer: solanaSigner,
36254
37411
  connection: solanaConnection,
@@ -36258,7 +37415,7 @@ const useExecuteTransaction = (squidRoute) => {
36258
37415
  const txParams = setTransactionState({
36259
37416
  route,
36260
37417
  txHash,
36261
- transactionIdForStatus: depositData.chainflipStatusTrackingId,
37418
+ transactionIdForStatus: depositData.statusTrackingId,
36262
37419
  userAddress: sourceUserAddress,
36263
37420
  status: exports.TransactionStatus.INITIAL_LOADING,
36264
37421
  sourceStatus: exports.TransactionStatus.ONGOING,
@@ -36309,7 +37466,7 @@ const useExecuteTransaction = (squidRoute) => {
36309
37466
  }
36310
37467
  });
36311
37468
  const swapMutationBitcoin = reactQuery.useMutation(async ({ id, route }) => {
36312
- const { depositAddress, amount: sendAmount, chainflipStatusTrackingId, } = useDepositAddressStore.getState().deposit ?? {};
37469
+ const { depositAddress, amount: sendAmount, statusTrackingId, } = useDepositAddressStore.getState().deposit ?? {};
36313
37470
  if (!depositAddress) {
36314
37471
  throw new Error(`Invalid deposit address: ${depositAddress}`);
36315
37472
  }
@@ -36332,7 +37489,7 @@ const useExecuteTransaction = (squidRoute) => {
36332
37489
  txHash,
36333
37490
  // When bridging from Bitcoin we need to send the chainflipId to the status endpoint
36334
37491
  // instead of the Bitcoin transaction hash
36335
- transactionIdForStatus: chainflipStatusTrackingId,
37492
+ transactionIdForStatus: statusTrackingId,
36336
37493
  userAddress: sourceUserAddress,
36337
37494
  status: exports.TransactionStatus.INITIAL_LOADING,
36338
37495
  sourceStatus: exports.TransactionStatus.ONGOING,
@@ -36524,6 +37681,56 @@ const useExecuteTransaction = (squidRoute) => {
36524
37681
  const sentTransaction = await client.sendTransaction(signedTransaction);
36525
37682
  await client.waitForTransaction(sentTransaction.hash);
36526
37683
  }, {});
37684
+ const swapMutationCanton = reactQuery.useMutation(async ({ id, route }) => {
37685
+ if (!route?.transactionRequest) {
37686
+ throw new Error("Route is required");
37687
+ }
37688
+ if (!cantonSigner) {
37689
+ throw new Error("Canton signer is required");
37690
+ }
37691
+ if (!isDepositAddressDirectTransferRoute(route.transactionRequest)) {
37692
+ throw new Error("Invalid Canton route type");
37693
+ }
37694
+ const receiver = route.transactionRequest.target;
37695
+ const orderHash = route.transactionRequest.data;
37696
+ const fromAmount = route.params.fromAmount;
37697
+ const token = findToken(route.params.fromToken, route.params.fromChain);
37698
+ if (!sourceUserAddress || !fromAmount || !token) {
37699
+ throw new Error("Need all parameters");
37700
+ }
37701
+ const amount = formatBNToReadable(fromAmount, token.decimals);
37702
+ dispatchSignatureRequestEvent(route);
37703
+ const transferParams = await buildCantonTransfer(cantonSigner, {
37704
+ sender: sourceUserAddress,
37705
+ receiver,
37706
+ amount,
37707
+ token,
37708
+ memo: orderHash,
37709
+ nowMs: Date.now(),
37710
+ });
37711
+ const result = await cantonSigner.prepareExecuteAndWait(transferParams);
37712
+ const txHash = result.tx?.payload?.updateId ?? "";
37713
+ if (txHash) {
37714
+ resetQueriesAfterTxSigned();
37715
+ }
37716
+ WidgetEvents.getInstance().dispatchSwapExecuteCall(route, txHash);
37717
+ const txParams = setTransactionState({
37718
+ route,
37719
+ txHash: txHash,
37720
+ userAddress: sourceUserAddress,
37721
+ status: exports.TransactionStatus.INITIAL_LOADING,
37722
+ sourceStatus: exports.TransactionStatus.ONGOING,
37723
+ id,
37724
+ });
37725
+ if (txParams) {
37726
+ addSwapTransaction({
37727
+ ...txParams,
37728
+ params: route.params,
37729
+ estimate: route.estimate,
37730
+ });
37731
+ }
37732
+ return txHash;
37733
+ });
36527
37734
  const handleTransactionSuccess = React.useCallback((id) => {
36528
37735
  const currentTx = getTransaction(id);
36529
37736
  queryClient.invalidateQueries(getPrefixKey(exports.QueryKeys.Balances));
@@ -36582,7 +37789,7 @@ const useExecuteTransaction = (squidRoute) => {
36582
37789
  if (!mutationParams.route?.transactionRequest) {
36583
37790
  throw new Error("Route is required");
36584
37791
  }
36585
- const sourceChain = findChain(mutationParams.route.params?.fromChain);
37792
+ const sourceChain = findChain(mutationParams.route.params.fromChain);
36586
37793
  if (!sourceChain)
36587
37794
  throw new Error("Could not find source chain");
36588
37795
  // After getting signature (if needed), continue with the swap flow
@@ -36608,6 +37815,9 @@ const useExecuteTransaction = (squidRoute) => {
36608
37815
  case squidTypes.ChainType.STELLAR: {
36609
37816
  return swapMutationStellar.mutateAsync(mutationParams);
36610
37817
  }
37818
+ case squidTypes.ChainType.CANTON: {
37819
+ return swapMutationCanton.mutateAsync(mutationParams);
37820
+ }
36611
37821
  default:
36612
37822
  throw new Error(`Swap mutation not implemented for chain type: ${sourceChain.chainType}`);
36613
37823
  }
@@ -36780,7 +37990,7 @@ refetchIntervalInBackground = false, refetchInterval = 30000, quoteOnly = true,
36780
37990
  const squid = useSquidStore((state) => state.squid);
36781
37991
  const fallbackAddress = useSwapRoutePersistStore((store) => store.swapRoute?.fallbackAddress);
36782
37992
  const depositRefundAddress = useSwapRoutePersistStore((store) => store.swapRoute?.depositRefundAddress);
36783
- const { isAvailableAsPaymentMethod, isEnabled: isDepositAddressEnabled } = useDepositAddress();
37993
+ const { isDepositAddressActive } = useDepositAddress();
36784
37994
  const getRouteMutation = useGetRoute();
36785
37995
  const { fromChain, toChain, fromPrice, destinationAddress: { address: destinationAddress } = {}, fromToken, toToken, } = useSwap();
36786
37996
  const { connectedAddress: { address: sourceConnectedAddress }, } = useMultiChainWallet(fromChain);
@@ -36788,8 +37998,8 @@ refetchIntervalInBackground = false, refetchInterval = 30000, quoteOnly = true,
36788
37998
  // Tokens will be sent to this address in case of swap failure
36789
37999
  //
36790
38000
  // If deposit address is not selected, we use the connected address as the source address instead
36791
- const sourceUserAddress = isDepositAddressEnabled && isAvailableAsPaymentMethod
36792
- ? depositRefundAddress ?? sourceConnectedAddress
38001
+ const sourceUserAddress = isDepositAddressActive
38002
+ ? (depositRefundAddress ?? sourceConnectedAddress)
36793
38003
  : sourceConnectedAddress;
36794
38004
  const squidRouteQueryKeys = React.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), [
36795
38005
  fromChain?.chainId,
@@ -36933,94 +38143,50 @@ function useSendTransactionStatus({ chain, txHash, }) {
36933
38143
  * Fetch status of a Swap transaction
36934
38144
  */
36935
38145
  const useSwapTransactionStatus = ({ transaction, retry = 25, refetchOnWindowFocus = "always", enabled = true, }) => {
36936
- const config = useConfigStore((state) => state.config);
36937
- const isInitialized = useConfigStore((state) => state.isInitialized);
36938
38146
  const { replaceSwapTransactionStatus } = useHistory();
36939
38147
  const findTransaction = useHistoryStore((state) => state.findTransaction);
36940
- const [isTransactionComplete, setIsTransactionComplete] = React.useState(false);
36941
- const [refetchInterval, setRefetchInterval] = React.useState(getSwapTxStatusRefetchInterval(transaction));
36942
- const { getChainType } = useSquidChains();
36943
38148
  const currentHistoryItem = React.useMemo(() => findTransaction({
36944
38149
  transactionId: transaction?.transactionId,
36945
38150
  txType: exports.HistoryTxType.SWAP,
36946
38151
  }), [findTransaction, transaction?.transactionId]);
36947
- /**
36948
- * Transaction status endpoint
36949
- * Squid api is using axelar endpoint and parsing the response
36950
- * @returns {StatusResponse} Status response
36951
- */
36952
- const fetchTransactionStatusWithLatestConfig = React.useCallback(async () => {
36953
- const latestConfig = useConfigStore.getState().config;
36954
- return fetchSwapTransactionStatus({
36955
- transaction,
36956
- integratorId: latestConfig.integratorId,
36957
- apiUrl: latestConfig.apiUrl,
36958
- });
36959
- }, [transaction]);
36960
- const transactionStatusQuery = reactQuery.useQuery(keys().swapTransactionStatus(transaction?.transactionId), fetchTransactionStatusWithLatestConfig, {
38152
+ const transactionStatusQuery = useSwapStatusQuery({
38153
+ transaction,
38154
+ retry,
38155
+ refetchOnWindowFocus,
36961
38156
  enabled: enabled &&
36962
- transaction?.transactionId !== "0" &&
36963
- !!transaction?.transactionId &&
36964
- !!transaction.fromAddress &&
36965
- !!config.apiUrl &&
36966
- transaction !== undefined &&
36967
- !isTransactionComplete &&
36968
- isInitialized &&
36969
38157
  !!currentHistoryItem &&
36970
38158
  !isHistoryTransactionEnded({
36971
38159
  data: currentHistoryItem?.data,
36972
38160
  txType: exports.HistoryTxType.SWAP,
36973
38161
  }),
36974
- refetchInterval(statusResponse) {
36975
- // If the status response is something telling that the transaction
36976
- // is finished, then store transaction history state if success
36977
- // And return false to indicate refetcher to stop
36978
- if (statusResponse &&
36979
- transactionEndStatuses.includes(getTransactionStatus(statusResponse) ?? "")) {
36980
- return false;
36981
- }
36982
- return refetchInterval; // Had to handle a variable here because after onError, we want the interval to stop
38162
+ onEndStatus: ({ status, statusResponse }) => {
38163
+ if (!transaction?.transactionId)
38164
+ return;
38165
+ replaceSwapTransactionStatus({
38166
+ transactionId: transaction.transactionId,
38167
+ statusResponse,
38168
+ status,
38169
+ });
36983
38170
  },
36984
- // At the moment Cosmos indexing takes more time, so need more time between retries
36985
- retryDelay: getChainType(transaction?.fromChain) === squidTypes.ChainType.COSMOS ? 5000 : 3000,
36986
- retry: getChainType(transaction?.fromChain) === squidTypes.ChainType.COSMOS ? 6 : retry,
36987
- refetchOnWindowFocus,
36988
- onSuccess: (statusResponse) => {
36989
- // Dispatch event
36990
- WidgetEvents.getInstance().dispatchSwapStatus(statusResponse.squidTransactionStatus ?? "");
36991
- const endStatus = getTransactionEndStatus({ statusResponse });
36992
- if (endStatus && transaction?.transactionId) {
36993
- setIsTransactionComplete(true);
36994
- replaceSwapTransactionStatus({
36995
- transactionId: transaction.transactionId,
36996
- statusResponse,
36997
- status: endStatus,
36998
- });
36999
- }
38171
+ onNotFound: () => {
38172
+ if (!transaction?.transactionId)
38173
+ return;
38174
+ replaceSwapTransactionStatus({
38175
+ transactionId: transaction.transactionId,
38176
+ statusResponse: undefined,
38177
+ status: exports.TransactionStatus.NOT_FOUND,
38178
+ });
37000
38179
  },
37001
- onError: (error) => {
37002
- // `fetchTransactionStatus` throws an error with a cause being an AxiosError
37003
- const is404 = is404Error(error.cause);
38180
+ onError: () => {
37004
38181
  if (!transaction?.transactionId)
37005
38182
  return;
37006
- if (is404) {
37007
- replaceSwapTransactionStatus({
37008
- transactionId: transaction.transactionId,
37009
- statusResponse: undefined,
37010
- status: exports.TransactionStatus.NOT_FOUND,
37011
- });
37012
- }
37013
- else {
37014
- setRefetchInterval(-1);
37015
- setIsTransactionComplete(true);
37016
- replaceSwapTransactionStatus({
37017
- transactionId: transaction.transactionId,
37018
- statusResponse: undefined,
37019
- status: exports.TransactionStatus.ERROR,
37020
- });
37021
- }
38183
+ replaceSwapTransactionStatus({
38184
+ transactionId: transaction.transactionId,
38185
+ statusResponse: undefined,
38186
+ status: exports.TransactionStatus.ERROR,
38187
+ });
37022
38188
  },
37023
- });
38189
+ }).transactionStatusQuery;
37024
38190
  return {
37025
38191
  transactionStatusQuery,
37026
38192
  latestStatus: transactionStatusQuery.data
@@ -37419,8 +38585,10 @@ const SquidProvider = ({ children, config, placeholder, }) => {
37419
38585
  }
37420
38586
  if (assetsColorsResponse.status === "fulfilled") {
37421
38587
  useAssetsColorsStore.setState(assetsColorsResponse.value);
37422
- initializeSquidWithAssetsColors(squid, assetsColorsResponse.value);
37423
38588
  }
38589
+ initializeSquidData(squid, assetsColorsResponse.status === "fulfilled"
38590
+ ? assetsColorsResponse.value
38591
+ : undefined);
37424
38592
  const shouldResetSwapRouteStore =
37425
38593
  // reset swap route if specified in config
37426
38594
  !config?.loadPreviousStateFromLocalStorage ||
@@ -37452,8 +38620,8 @@ const SquidProvider = ({ children, config, placeholder, }) => {
37452
38620
  error instanceof Error;
37453
38621
  if (isBackendDown) {
37454
38622
  const maintenanceMessage = isAxios503Error
37455
- ? error.response?.data
37456
- ?.message ?? undefined
38623
+ ? (error.response?.data
38624
+ ?.message ?? undefined)
37457
38625
  : "Unable to connect to Squid. Please check your connection or try again later.";
37458
38626
  // Even with an error, we want wagmi to be defined so that we can display the maintenance mode layout
37459
38627
  // Create wagmi config with mainnet as fallback in maintenance mode
@@ -37488,13 +38656,14 @@ const SquidProvider = ({ children, config, placeholder, }) => {
37488
38656
  }, [initializeSdk]);
37489
38657
  return wagmiConfig ? (React.createElement(wagmi.WagmiProvider, { reconnectOnMount: false, config: wagmiConfig },
37490
38658
  React.createElement(reactQuery.QueryClientProvider, { client: queryClient },
37491
- React.createElement(StellarProvider, null,
37492
- React.createElement(EvmProvider, null,
37493
- React.createElement(XrplProvider, null,
37494
- React.createElement(SuiProvider, null,
37495
- React.createElement(SolanaProvider, null,
37496
- React.createElement(BitcoinProvider, null,
37497
- React.createElement(CosmosProvider, null, children)))))))))) : (placeholder);
38659
+ React.createElement(CantonProvider, null,
38660
+ React.createElement(StellarProvider, null,
38661
+ React.createElement(EvmProvider, null,
38662
+ React.createElement(XrplProvider, null,
38663
+ React.createElement(SuiProvider, null,
38664
+ React.createElement(SolanaProvider, null,
38665
+ React.createElement(BitcoinProvider, null,
38666
+ React.createElement(CosmosProvider, null, children))))))))))) : (placeholder);
37498
38667
  };
37499
38668
 
37500
38669
  exports.CHAIN_IDS = CHAIN_IDS;
@@ -37510,13 +38679,13 @@ exports.SquidProvider = SquidProvider;
37510
38679
  exports.TX_STATUS_CONSTANTS = TX_STATUS_CONSTANTS;
37511
38680
  exports.WidgetEvents = WidgetEvents;
37512
38681
  exports.Wo = Wo;
37513
- exports.accessProperty = accessProperty;
37514
38682
  exports.adaptiveRound = adaptiveRound;
37515
38683
  exports.addEthereumChain = addEthereumChain;
37516
38684
  exports.addTokenToWallet = addTokenToWallet;
37517
38685
  exports.areSameAddress = areSameAddress;
37518
38686
  exports.areTokenSymbolsCompatible = areTokenSymbolsCompatible;
37519
38687
  exports.assetsBaseUrl = assetsBaseUrl;
38688
+ exports.buildFallbackWallets = buildFallbackWallets;
37520
38689
  exports.buildUrlSearchParamsFromSwapEvent = buildUrlSearchParamsFromSwapEvent;
37521
38690
  exports.buildXrplTrustSetTx = buildXrplTrustSetTx;
37522
38691
  exports.calculateTotal24hChange = calculateTotal24hChange;
@@ -37609,13 +38778,14 @@ exports.getXummClient = getXummClient;
37609
38778
  exports.groupTokensByChainId = groupTokensByChainId;
37610
38779
  exports.groupTokensBySymbol = groupTokensBySymbol;
37611
38780
  exports.handleTransactionErrorEvents = handleTransactionErrorEvents;
37612
- exports.initializeSquidWithAssetsColors = initializeSquidWithAssetsColors;
38781
+ exports.initializeSquidData = initializeSquidData;
37613
38782
  exports.is404Error = is404Error;
37614
38783
  exports.isActionCompletedOnSourceTx = isActionCompletedOnSourceTx;
37615
38784
  exports.isChainflipBridgeTransaction = isChainflipBridgeTransaction;
38785
+ exports.isChainflipDepositRoute = isChainflipDepositRoute;
37616
38786
  exports.isCoralBridgeAction = isCoralBridgeAction;
37617
38787
  exports.isCosmosAddressValid = isCosmosAddressValid;
37618
- exports.isDepositRoute = isDepositRoute;
38788
+ exports.isDepositAddressDirectTransferRoute = isDepositAddressDirectTransferRoute;
37619
38789
  exports.isEmptyObject = isEmptyObject;
37620
38790
  exports.isEvmChainNotSupportedError = isEvmChainNotSupportedError;
37621
38791
  exports.isEvmosChain = isEvmosChain;
@@ -37631,6 +38801,7 @@ exports.isStatusError = isStatusError;
37631
38801
  exports.isStellarAddressValid = isStellarAddressValid;
37632
38802
  exports.isStellarIssuedToken = isStellarIssuedToken;
37633
38803
  exports.isStellarToken = isStellarToken;
38804
+ exports.isSupportedChainType = isSupportedChainType;
37634
38805
  exports.isSwapRouteError = isSwapRouteError;
37635
38806
  exports.isUserRejectionError = isUserRejectionError;
37636
38807
  exports.isValidHorizonAsset = isValidHorizonAsset;
@@ -37695,6 +38866,7 @@ exports.useCountryDetails = useCountryDetails;
37695
38866
  exports.useCurrencyDetails = useCurrencyDetails;
37696
38867
  exports.useDebouncedValue = useDebouncedValue;
37697
38868
  exports.useDepositAddress = useDepositAddress;
38869
+ exports.useDepositTransactionStatus = useDepositTransactionStatus;
37698
38870
  exports.useEnsDataForAddress = useEnsDataForAddress;
37699
38871
  exports.useEnsSearch = useEnsSearch;
37700
38872
  exports.useEstimate = useEstimate;
@@ -37761,4 +38933,4 @@ exports.useXrplTrustLine = useXrplTrustLine;
37761
38933
  exports.waitForReceiptWithRetry = waitForReceiptWithRetry;
37762
38934
  exports.walletIconBaseUrl = walletIconBaseUrl;
37763
38935
  exports.walletSupportsChainType = walletSupportsChainType;
37764
- //# sourceMappingURL=index-DcBFug8t.js.map
38936
+ //# sourceMappingURL=index-doLvokYY.js.map