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