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