@sodax/wallet-sdk-react 1.5.7-beta → 2.0.0-rc.1
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/README.md +103 -145
- package/ai-exported/AGENTS.md +122 -0
- package/ai-exported/integration/README.md +102 -0
- package/ai-exported/integration/ai-rules.md +136 -0
- package/ai-exported/integration/architecture.md +181 -0
- package/ai-exported/integration/examples/01-minimal-evm.tsx +75 -0
- package/ai-exported/integration/examples/02-multi-chain-modal.tsx +169 -0
- package/ai-exported/integration/examples/03-nextjs-app-router.tsx +99 -0
- package/ai-exported/integration/examples/04-walletconnect-setup.tsx +89 -0
- package/ai-exported/integration/examples/README.md +29 -0
- package/ai-exported/integration/recipes/batch-operations.md +223 -0
- package/ai-exported/integration/recipes/bridge-to-sdk.md +164 -0
- package/ai-exported/integration/recipes/chain-detection.md +254 -0
- package/ai-exported/integration/recipes/connect-button.md +156 -0
- package/ai-exported/integration/recipes/multi-chain-modal.md +199 -0
- package/ai-exported/integration/recipes/setup.md +158 -0
- package/ai-exported/integration/recipes/sign-message.md +137 -0
- package/ai-exported/integration/recipes/sub-path-imports.md +95 -0
- package/ai-exported/integration/recipes/switch-chain.md +141 -0
- package/ai-exported/integration/recipes/walletconnect-setup.md +139 -0
- package/ai-exported/integration/reference/api-surface.md +175 -0
- package/ai-exported/integration/reference/chain-support.md +78 -0
- package/ai-exported/integration/reference/connectors.md +74 -0
- package/ai-exported/integration/reference/hooks.md +204 -0
- package/ai-exported/integration/reference/wallet-brands.md +106 -0
- package/ai-exported/migration/README.md +49 -0
- package/ai-exported/migration/ai-rules.md +144 -0
- package/ai-exported/migration/breaking-changes.md +305 -0
- package/ai-exported/migration/checklist.md +159 -0
- package/ai-exported/migration/recipes/connect-button.md +166 -0
- package/ai-exported/migration/recipes/multi-chain-modal.md +244 -0
- package/ai-exported/migration/recipes/ssr-setup.md +162 -0
- package/ai-exported/migration/recipes/walletconnect-migration.md +168 -0
- package/ai-exported/migration/reference/components.md +73 -0
- package/ai-exported/migration/reference/config.md +307 -0
- package/ai-exported/migration/reference/hooks.md +278 -0
- package/ai-exported/migration/reference/imports.md +157 -0
- package/dist/XConnector-B9YQTVJ4.d.ts +146 -0
- package/dist/chunk-2BOUGCJ7.mjs +150 -0
- package/dist/chunk-2BOUGCJ7.mjs.map +1 -0
- package/dist/chunk-66BAUK56.mjs +202 -0
- package/dist/chunk-66BAUK56.mjs.map +1 -0
- package/dist/chunk-7ULB6DW4.mjs +102 -0
- package/dist/chunk-7ULB6DW4.mjs.map +1 -0
- package/dist/chunk-BKJB527E.mjs +125 -0
- package/dist/chunk-BKJB527E.mjs.map +1 -0
- package/dist/chunk-BXJLBR4G.mjs +88 -0
- package/dist/chunk-BXJLBR4G.mjs.map +1 -0
- package/dist/chunk-E5IAZ7E6.mjs +186 -0
- package/dist/chunk-E5IAZ7E6.mjs.map +1 -0
- package/dist/chunk-MAQ47Q52.mjs +33 -0
- package/dist/chunk-MAQ47Q52.mjs.map +1 -0
- package/dist/chunk-MXZVF5HR.mjs +34 -0
- package/dist/chunk-MXZVF5HR.mjs.map +1 -0
- package/dist/chunk-N5A2TMF6.mjs +33 -0
- package/dist/chunk-N5A2TMF6.mjs.map +1 -0
- package/dist/chunk-NY7U7OJW.mjs +64 -0
- package/dist/chunk-NY7U7OJW.mjs.map +1 -0
- package/dist/chunk-PJLEJVAU.mjs +140 -0
- package/dist/chunk-PJLEJVAU.mjs.map +1 -0
- package/dist/chunk-PLCA4ZDJ.mjs +1585 -0
- package/dist/chunk-PLCA4ZDJ.mjs.map +1 -0
- package/dist/chunk-TZMKDXFA.mjs +3 -0
- package/dist/chunk-TZMKDXFA.mjs.map +1 -0
- package/dist/chunk-X2MHIWXO.mjs +100 -0
- package/dist/chunk-X2MHIWXO.mjs.map +1 -0
- package/dist/chunk-XZ7CHO2S.mjs +41 -0
- package/dist/chunk-XZ7CHO2S.mjs.map +1 -0
- package/dist/config-OlnzyEUE.d.ts +146 -0
- package/dist/index.cjs +2784 -1594
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +768 -1498
- package/dist/index.mjs +463 -2004
- package/dist/index.mjs.map +1 -1
- package/dist/xchains/bitcoin/index.cjs +1927 -0
- package/dist/xchains/bitcoin/index.cjs.map +1 -0
- package/dist/xchains/bitcoin/index.d.ts +125 -0
- package/dist/xchains/bitcoin/index.mjs +16 -0
- package/dist/xchains/bitcoin/index.mjs.map +1 -0
- package/dist/xchains/evm/index.cjs +316 -0
- package/dist/xchains/evm/index.cjs.map +1 -0
- package/dist/xchains/evm/index.d.ts +39 -0
- package/dist/xchains/evm/index.mjs +5 -0
- package/dist/xchains/evm/index.mjs.map +1 -0
- package/dist/xchains/icon/index.cjs +311 -0
- package/dist/xchains/icon/index.cjs.map +1 -0
- package/dist/xchains/icon/index.d.ts +37 -0
- package/dist/xchains/icon/index.mjs +7 -0
- package/dist/xchains/icon/index.mjs.map +1 -0
- package/dist/xchains/injective/index.cjs +223 -0
- package/dist/xchains/injective/index.cjs.map +1 -0
- package/dist/xchains/injective/index.d.ts +35 -0
- package/dist/xchains/injective/index.mjs +5 -0
- package/dist/xchains/injective/index.mjs.map +1 -0
- package/dist/xchains/near/index.cjs +190 -0
- package/dist/xchains/near/index.cjs.map +1 -0
- package/dist/xchains/near/index.d.ts +34 -0
- package/dist/xchains/near/index.mjs +6 -0
- package/dist/xchains/near/index.mjs.map +1 -0
- package/dist/xchains/solana/index.cjs +186 -0
- package/dist/xchains/solana/index.cjs.map +1 -0
- package/dist/xchains/solana/index.d.ts +26 -0
- package/dist/xchains/solana/index.mjs +7 -0
- package/dist/xchains/solana/index.mjs.map +1 -0
- package/dist/xchains/stacks/index.cjs +240 -0
- package/dist/xchains/stacks/index.cjs.map +1 -0
- package/dist/xchains/stacks/index.d.ts +36 -0
- package/dist/xchains/stacks/index.mjs +5 -0
- package/dist/xchains/stacks/index.mjs.map +1 -0
- package/dist/xchains/stellar/index.cjs +322 -0
- package/dist/xchains/stellar/index.cjs.map +1 -0
- package/dist/xchains/stellar/index.d.ts +44 -0
- package/dist/xchains/stellar/index.mjs +6 -0
- package/dist/xchains/stellar/index.mjs.map +1 -0
- package/dist/xchains/sui/index.cjs +248 -0
- package/dist/xchains/sui/index.cjs.map +1 -0
- package/dist/xchains/sui/index.d.ts +37 -0
- package/dist/xchains/sui/index.mjs +7 -0
- package/dist/xchains/sui/index.mjs.map +1 -0
- package/docs/ADDING_A_NEW_CHAIN.md +440 -0
- package/docs/ARCHITECTURE.md +291 -0
- package/docs/BATCH_OPERATIONS.md +267 -0
- package/docs/CHAIN_DETECTION.md +216 -0
- package/docs/CONFIGURE_PROVIDER.md +360 -0
- package/docs/CONNECTORS.md +247 -0
- package/docs/CONNECT_FLOW.md +276 -0
- package/docs/EVM_SWITCH_CHAIN.md +161 -0
- package/docs/SIGN_MESSAGE.md +213 -0
- package/docs/SUB_PATH_EXPORTS.md +246 -0
- package/docs/WALLETCONNECT.md +154 -0
- package/docs/WALLET_MODAL.md +331 -0
- package/docs/WALLET_PROVIDER_BRIDGE.md +226 -0
- package/package.json +34 -9
- package/skills/SKILLS.md +84 -0
- package/skills/bridge-to-sdk.md +148 -0
- package/skills/connect-button.md +116 -0
- package/skills/evm-only-walletconnect.md +111 -0
- package/skills/multi-chain-modal.md +178 -0
- package/skills/setup.md +107 -0
- package/dist/index.d.cts +0 -1579
- package/src/Hydrate.ts +0 -65
- package/src/SodaxWalletProvider.tsx +0 -97
- package/src/actions/getXChainType.ts +0 -8
- package/src/actions/getXService.ts +0 -33
- package/src/actions/index.ts +0 -2
- package/src/assets/wallets/hana.svg +0 -6
- package/src/assets/wallets/havah.svg +0 -76
- package/src/assets/wallets/keplr.svg +0 -30
- package/src/assets/wallets/metamask.svg +0 -60
- package/src/assets/wallets/phantom.svg +0 -4
- package/src/assets/wallets/sui.svg +0 -20
- package/src/core/XConnector.ts +0 -54
- package/src/core/XService.ts +0 -85
- package/src/core/index.ts +0 -2
- package/src/hooks/index.ts +0 -11
- package/src/hooks/useEthereumChainId.ts +0 -44
- package/src/hooks/useEvmSwitchChain.ts +0 -91
- package/src/hooks/useWalletProvider.ts +0 -206
- package/src/hooks/useXAccount.ts +0 -51
- package/src/hooks/useXAccounts.ts +0 -56
- package/src/hooks/useXBalances.ts +0 -65
- package/src/hooks/useXConnect.ts +0 -118
- package/src/hooks/useXConnection.ts +0 -72
- package/src/hooks/useXConnectors.ts +0 -72
- package/src/hooks/useXDisconnect.ts +0 -73
- package/src/hooks/useXService.ts +0 -8
- package/src/hooks/useXSignMessage.ts +0 -82
- package/src/index.ts +0 -19
- package/src/types/index.ts +0 -22
- package/src/useXWagmiStore.ts +0 -116
- package/src/utils/index.ts +0 -21
- package/src/xchains/bitcoin/BitcoinXConnector.ts +0 -34
- package/src/xchains/bitcoin/BitcoinXService.ts +0 -40
- package/src/xchains/bitcoin/OKXXConnector.ts +0 -117
- package/src/xchains/bitcoin/UnisatXConnector.ts +0 -117
- package/src/xchains/bitcoin/XverseXConnector.ts +0 -232
- package/src/xchains/bitcoin/index.ts +0 -7
- package/src/xchains/bitcoin/useBitcoinXConnectors.ts +0 -14
- package/src/xchains/evm/EvmXConnector.ts +0 -27
- package/src/xchains/evm/EvmXService.ts +0 -211
- package/src/xchains/evm/index.ts +0 -3
- package/src/xchains/icon/IconHanaXConnector.ts +0 -39
- package/src/xchains/icon/IconXService.ts +0 -117
- package/src/xchains/icon/actions.ts +0 -28
- package/src/xchains/icon/iconex/index.tsx +0 -46
- package/src/xchains/icon/index.ts +0 -2
- package/src/xchains/injective/InjectiveXConnector.ts +0 -60
- package/src/xchains/injective/InjectiveXService.ts +0 -62
- package/src/xchains/injective/actions.ts +0 -32
- package/src/xchains/injective/index.ts +0 -2
- package/src/xchains/near/NearXConnector.ts +0 -42
- package/src/xchains/near/NearXService.ts +0 -46
- package/src/xchains/near/useNearXConnectors.ts +0 -23
- package/src/xchains/solana/SolanaXConnector.ts +0 -26
- package/src/xchains/solana/SolanaXService.ts +0 -46
- package/src/xchains/solana/index.ts +0 -2
- package/src/xchains/stacks/StacksXConnector.ts +0 -63
- package/src/xchains/stacks/StacksXService.ts +0 -59
- package/src/xchains/stacks/constants.ts +0 -42
- package/src/xchains/stacks/index.ts +0 -4
- package/src/xchains/stacks/useStacksXConnectors.ts +0 -7
- package/src/xchains/stellar/CustomSorobanServer.ts +0 -93
- package/src/xchains/stellar/StellarWalletsKitXConnector.ts +0 -53
- package/src/xchains/stellar/StellarXService.ts +0 -93
- package/src/xchains/stellar/actions.ts +0 -24
- package/src/xchains/stellar/index.tsx +0 -2
- package/src/xchains/stellar/useStellarXConnectors.ts +0 -21
- package/src/xchains/stellar/utils.ts +0 -49
- package/src/xchains/sui/SuiXConnector.ts +0 -28
- package/src/xchains/sui/SuiXService.ts +0 -66
- package/src/xchains/sui/index.ts +0 -2
package/dist/index.cjs
CHANGED
|
@@ -1,41 +1,40 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var types = require('@sodax/types');
|
|
4
|
-
var nearConnect = require('@hot-labs/near-connect');
|
|
5
|
-
var nearApiJs = require('near-api-js');
|
|
6
|
-
var transactions = require('@stacks/transactions');
|
|
7
|
-
var network = require('@stacks/network');
|
|
8
|
-
var satsConnect = require('sats-connect');
|
|
9
|
-
var React2 = require('react');
|
|
10
|
-
var dappKit = require('@mysten/dapp-kit');
|
|
11
|
-
var walletAdapterReact = require('@solana/wallet-adapter-react');
|
|
12
|
-
var wagmi = require('wagmi');
|
|
13
4
|
var zustand = require('zustand');
|
|
14
5
|
var middleware = require('zustand/middleware');
|
|
15
6
|
var immer = require('zustand/middleware/immer');
|
|
7
|
+
var walletSdkCore = require('@sodax/wallet-sdk-core');
|
|
8
|
+
var walletBase = require('@injectivelabs/wallet-base');
|
|
9
|
+
var sdkTs = require('@injectivelabs/sdk-ts');
|
|
16
10
|
var viem = require('viem');
|
|
17
11
|
var actions = require('wagmi/actions');
|
|
18
|
-
var
|
|
19
|
-
var
|
|
20
|
-
var sdkTs = require('@injectivelabs/sdk-ts');
|
|
21
|
-
var tsTypes = require('@injectivelabs/ts-types');
|
|
22
|
-
var walletCore = require('@injectivelabs/wallet-core');
|
|
23
|
-
var walletStrategy = require('@injectivelabs/wallet-strategy');
|
|
24
|
-
var walletBase = require('@injectivelabs/wallet-base');
|
|
25
|
-
var walletCosmos = require('@injectivelabs/wallet-cosmos');
|
|
12
|
+
var wagmi = require('wagmi');
|
|
13
|
+
var chains$1 = require('wagmi/chains');
|
|
26
14
|
var web3_js = require('@solana/web3.js');
|
|
27
15
|
var splToken = require('@solana/spl-token');
|
|
28
16
|
var stellarWalletsKit = require('@creit.tech/stellar-wallets-kit');
|
|
29
17
|
var StellarSdk = require('@stellar/stellar-sdk');
|
|
30
18
|
var IconSdkRaw = require('icon-sdk-js');
|
|
31
|
-
var
|
|
19
|
+
var networks = require('@injectivelabs/networks');
|
|
20
|
+
var tsTypes = require('@injectivelabs/ts-types');
|
|
21
|
+
var walletCore = require('@injectivelabs/wallet-core');
|
|
22
|
+
var walletStrategy = require('@injectivelabs/wallet-strategy');
|
|
23
|
+
var walletCosmos = require('@injectivelabs/wallet-cosmos');
|
|
24
|
+
var satsConnect = require('sats-connect');
|
|
25
|
+
var react = require('react');
|
|
32
26
|
var reactQuery = require('@tanstack/react-query');
|
|
33
|
-
var chains
|
|
34
|
-
var
|
|
27
|
+
var chains = require('viem/chains');
|
|
28
|
+
var nearConnect = require('@hot-labs/near-connect');
|
|
29
|
+
var nearApiJs = require('near-api-js');
|
|
30
|
+
var transactions = require('@stacks/transactions');
|
|
31
|
+
var network = require('@stacks/network');
|
|
32
|
+
var connect = require('@stacks/connect');
|
|
33
|
+
var connectors = require('wagmi/connectors');
|
|
34
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
35
|
+
var walletAdapterReact = require('@solana/wallet-adapter-react');
|
|
36
|
+
var dappKit = require('@mysten/dapp-kit');
|
|
35
37
|
var client = require('@mysten/sui/client');
|
|
36
|
-
var walletAdapterWallets = require('@solana/wallet-adapter-wallets');
|
|
37
|
-
|
|
38
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
39
38
|
|
|
40
39
|
function _interopNamespace(e) {
|
|
41
40
|
if (e && e.__esModule) return e;
|
|
@@ -55,7 +54,6 @@ function _interopNamespace(e) {
|
|
|
55
54
|
return Object.freeze(n);
|
|
56
55
|
}
|
|
57
56
|
|
|
58
|
-
var React2__default = /*#__PURE__*/_interopDefault(React2);
|
|
59
57
|
var StellarSdk__namespace = /*#__PURE__*/_interopNamespace(StellarSdk);
|
|
60
58
|
var IconSdkRaw__namespace = /*#__PURE__*/_interopNamespace(IconSdkRaw);
|
|
61
59
|
|
|
@@ -69,9 +67,11 @@ function getXChainType(xChainId) {
|
|
|
69
67
|
|
|
70
68
|
// src/core/XService.ts
|
|
71
69
|
var XService = class {
|
|
70
|
+
/** The blockchain type this service handles */
|
|
71
|
+
xChainType;
|
|
72
|
+
/** Available wallet connectors for this chain */
|
|
73
|
+
xConnectors = [];
|
|
72
74
|
constructor(xChainType) {
|
|
73
|
-
/** Available wallet connectors for this chain */
|
|
74
|
-
this.xConnectors = [];
|
|
75
75
|
this.xChainType = xChainType;
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
@@ -122,106 +122,17 @@ var XService = class {
|
|
|
122
122
|
return this.getXConnectors().find((xConnector) => xConnector.id === xConnectorId);
|
|
123
123
|
}
|
|
124
124
|
};
|
|
125
|
-
var NearXService = class _NearXService extends XService {
|
|
126
|
-
constructor() {
|
|
127
|
-
super("NEAR");
|
|
128
|
-
this.walletSelector = new nearConnect.NearConnector({
|
|
129
|
-
network: "mainnet",
|
|
130
|
-
logger: console,
|
|
131
|
-
autoConnect: true,
|
|
132
|
-
excludedWallets: ["okx-wallet"]
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
static getInstance() {
|
|
136
|
-
if (!_NearXService.instance) {
|
|
137
|
-
_NearXService.instance = new _NearXService();
|
|
138
|
-
}
|
|
139
|
-
return _NearXService.instance;
|
|
140
|
-
}
|
|
141
|
-
async getBalance(address, xToken) {
|
|
142
|
-
const url = "https://1rpc.io/near";
|
|
143
|
-
const provider = new nearApiJs.JsonRpcProvider({ url });
|
|
144
|
-
if (xToken.symbol === "NEAR") {
|
|
145
|
-
const account = await provider.viewAccount({ accountId: address ?? "" });
|
|
146
|
-
return BigInt(account.amount);
|
|
147
|
-
}
|
|
148
|
-
const res = await provider.callFunction({ contractId: xToken.address, method: "ft_balance_of", args: { account_id: address } });
|
|
149
|
-
return BigInt(res ?? 0);
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
var StacksXService = class _StacksXService extends XService {
|
|
153
|
-
constructor() {
|
|
154
|
-
super("STACKS");
|
|
155
|
-
this.network = network.networkFrom("mainnet");
|
|
156
|
-
}
|
|
157
|
-
static getInstance() {
|
|
158
|
-
if (!_StacksXService.instance) {
|
|
159
|
-
_StacksXService.instance = new _StacksXService();
|
|
160
|
-
}
|
|
161
|
-
return _StacksXService.instance;
|
|
162
|
-
}
|
|
163
|
-
async getBalance(address, xToken) {
|
|
164
|
-
if (!address) return 0n;
|
|
165
|
-
if (xToken.symbol === "STX") {
|
|
166
|
-
const url = `${this.network?.client.baseUrl}/extended/v1/address/${address}/balances`;
|
|
167
|
-
try {
|
|
168
|
-
const response = await fetch(url);
|
|
169
|
-
if (!response.ok) {
|
|
170
|
-
throw new Error(`Error fetching data: ${response.statusText}`);
|
|
171
|
-
}
|
|
172
|
-
const data = await response.json();
|
|
173
|
-
return BigInt(data.stx.balance);
|
|
174
|
-
} catch (error) {
|
|
175
|
-
console.error("Error fetching STX balance:", error);
|
|
176
|
-
return 0n;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
const [contractAddress, contractName] = xToken.address.split(".");
|
|
180
|
-
try {
|
|
181
|
-
const result = await transactions.fetchCallReadOnlyFunction({
|
|
182
|
-
contractAddress,
|
|
183
|
-
contractName,
|
|
184
|
-
functionName: "get-balance",
|
|
185
|
-
functionArgs: [transactions.Cl.principal(address)],
|
|
186
|
-
network: this.network,
|
|
187
|
-
senderAddress: address
|
|
188
|
-
});
|
|
189
|
-
return result.value.value;
|
|
190
|
-
} catch (error) {
|
|
191
|
-
console.error("Error fetching token balance:", error);
|
|
192
|
-
return 0n;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
// src/actions/getXService.ts
|
|
198
|
-
function getXService(xChainType) {
|
|
199
|
-
switch (xChainType) {
|
|
200
|
-
case "BITCOIN":
|
|
201
|
-
return BitcoinXService.getInstance();
|
|
202
|
-
case "EVM":
|
|
203
|
-
return EvmXService.getInstance();
|
|
204
|
-
case "SUI":
|
|
205
|
-
return SuiXService.getInstance();
|
|
206
|
-
case "SOLANA":
|
|
207
|
-
return SolanaXService.getInstance();
|
|
208
|
-
case "ICON":
|
|
209
|
-
return IconXService.getInstance();
|
|
210
|
-
case "INJECTIVE":
|
|
211
|
-
return InjectiveXService.getInstance();
|
|
212
|
-
case "STELLAR":
|
|
213
|
-
return StellarXService.getInstance();
|
|
214
|
-
case "NEAR":
|
|
215
|
-
return NearXService.getInstance();
|
|
216
|
-
case "STACKS":
|
|
217
|
-
return StacksXService.getInstance();
|
|
218
|
-
default:
|
|
219
|
-
throw new Error(`Unsupported chain type: ${xChainType}`);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
125
|
|
|
223
126
|
// src/core/XConnector.ts
|
|
224
127
|
var XConnector = class {
|
|
128
|
+
/** The blockchain type this connector supports */
|
|
129
|
+
xChainType;
|
|
130
|
+
/** Display name of the wallet provider */
|
|
131
|
+
name;
|
|
132
|
+
/** Unique identifier for the connector */
|
|
133
|
+
_id;
|
|
134
|
+
/** Optional icon URL for the wallet provider */
|
|
135
|
+
_icon;
|
|
225
136
|
constructor(xChainType, name, id) {
|
|
226
137
|
this.xChainType = xChainType;
|
|
227
138
|
this.name = name;
|
|
@@ -235,7 +146,55 @@ var XConnector = class {
|
|
|
235
146
|
get icon() {
|
|
236
147
|
return this._icon;
|
|
237
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* True when the wallet extension backing this connector is installed.
|
|
151
|
+
* Default: true (for provider-managed chains where connector presence already
|
|
152
|
+
* implies install — EVM via EIP-6963, Solana/Sui via adapter discovery).
|
|
153
|
+
* Subclasses backed by extension injection (Bitcoin, ICON, Stacks) override
|
|
154
|
+
* this with a window probe.
|
|
155
|
+
*/
|
|
156
|
+
get isInstalled() {
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
/** URL to install the wallet extension when missing. Subclasses override. */
|
|
160
|
+
get installUrl() {
|
|
161
|
+
return void 0;
|
|
162
|
+
}
|
|
238
163
|
};
|
|
164
|
+
function getEntryDefaults(entry) {
|
|
165
|
+
if (!entry || typeof entry === "string") return void 0;
|
|
166
|
+
return entry.defaults;
|
|
167
|
+
}
|
|
168
|
+
function getRpcUrl(entry) {
|
|
169
|
+
if (!entry || typeof entry === "string") return void 0;
|
|
170
|
+
return entry.rpcUrl;
|
|
171
|
+
}
|
|
172
|
+
function resolveEvmDefaults(activeChainId, evmChains) {
|
|
173
|
+
const key = types.getEvmChainKeyByChainId(activeChainId);
|
|
174
|
+
if (!key || !evmChains) return void 0;
|
|
175
|
+
return evmChains[key]?.defaults;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// src/utils/sortConnectors.ts
|
|
179
|
+
function sortConnectors(connectors, options = {}) {
|
|
180
|
+
const { preferred = [] } = options;
|
|
181
|
+
const preferredIndex = new Map(preferred.map((id, i) => [id, i]));
|
|
182
|
+
return [...connectors].map((connector, originalIndex) => ({ connector, originalIndex })).sort((a, b) => {
|
|
183
|
+
const aPref = preferredIndex.get(a.connector.id);
|
|
184
|
+
const bPref = preferredIndex.get(b.connector.id);
|
|
185
|
+
if (aPref !== bPref) {
|
|
186
|
+
if (aPref === void 0) return 1;
|
|
187
|
+
if (bPref === void 0) return -1;
|
|
188
|
+
return aPref - bPref;
|
|
189
|
+
}
|
|
190
|
+
if (a.connector.isInstalled !== b.connector.isInstalled) {
|
|
191
|
+
return a.connector.isInstalled ? -1 : 1;
|
|
192
|
+
}
|
|
193
|
+
return a.originalIndex - b.originalIndex;
|
|
194
|
+
}).map(({ connector }) => connector);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// src/utils/index.ts
|
|
239
198
|
var isNativeToken = (xToken) => {
|
|
240
199
|
const nativeAddresses = [
|
|
241
200
|
"cx0000000000000000000000000000000000000000",
|
|
@@ -255,516 +214,716 @@ var isNativeToken = (xToken) => {
|
|
|
255
214
|
return nativeAddresses.includes(xToken.address);
|
|
256
215
|
};
|
|
257
216
|
var getWagmiChainId = (xChainId) => {
|
|
258
|
-
|
|
217
|
+
const chainId = types.baseChainInfo[xChainId].chainId;
|
|
218
|
+
if (typeof chainId !== "number") {
|
|
219
|
+
throw new Error(`[wallet-sdk-react] getWagmiChainId: expected numeric chainId, got ${typeof chainId}`);
|
|
220
|
+
}
|
|
221
|
+
return chainId;
|
|
259
222
|
};
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
223
|
+
var hyper = /* @__PURE__ */ viem.defineChain({
|
|
224
|
+
id: 999,
|
|
225
|
+
name: "HyperEVM",
|
|
226
|
+
nativeCurrency: {
|
|
227
|
+
decimals: 18,
|
|
228
|
+
name: "HYPE",
|
|
229
|
+
symbol: "HYPE"
|
|
230
|
+
},
|
|
231
|
+
rpcUrls: {
|
|
232
|
+
default: { http: ["https://rpc.hyperliquid.xyz/evm"] }
|
|
233
|
+
},
|
|
234
|
+
blockExplorers: {
|
|
235
|
+
default: {
|
|
236
|
+
name: "HyperEVMScan",
|
|
237
|
+
url: "https://hyperevmscan.io/"
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
contracts: {
|
|
241
|
+
multicall3: {
|
|
242
|
+
address: "0xcA11bde05977b3631167028862bE2a173976CA11",
|
|
243
|
+
blockCreated: 13051
|
|
244
|
+
}
|
|
266
245
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
246
|
+
});
|
|
247
|
+
var createWagmiConfig = (evmChains, options) => {
|
|
248
|
+
return wagmi.createConfig({
|
|
249
|
+
chains: [
|
|
250
|
+
chains$1.mainnet,
|
|
251
|
+
chains$1.avalanche,
|
|
252
|
+
chains$1.arbitrum,
|
|
253
|
+
chains$1.base,
|
|
254
|
+
chains$1.bsc,
|
|
255
|
+
chains$1.sonic,
|
|
256
|
+
chains$1.optimism,
|
|
257
|
+
chains$1.polygon,
|
|
258
|
+
hyper,
|
|
259
|
+
chains$1.lightlinkPhoenix,
|
|
260
|
+
chains$1.kaia,
|
|
261
|
+
chains$1.redbellyMainnet
|
|
262
|
+
],
|
|
263
|
+
connectors: options?.connectors ?? [],
|
|
264
|
+
ssr: options?.ssr,
|
|
265
|
+
transports: {
|
|
266
|
+
[chains$1.mainnet.id]: wagmi.http(getRpcUrl(evmChains?.[types.ChainKeys.ETHEREUM_MAINNET])),
|
|
267
|
+
[chains$1.avalanche.id]: wagmi.http(getRpcUrl(evmChains?.[types.ChainKeys.AVALANCHE_MAINNET])),
|
|
268
|
+
[chains$1.arbitrum.id]: wagmi.http(getRpcUrl(evmChains?.[types.ChainKeys.ARBITRUM_MAINNET])),
|
|
269
|
+
[chains$1.base.id]: wagmi.http(getRpcUrl(evmChains?.[types.ChainKeys.BASE_MAINNET])),
|
|
270
|
+
[chains$1.bsc.id]: wagmi.http(getRpcUrl(evmChains?.[types.ChainKeys.BSC_MAINNET])),
|
|
271
|
+
[chains$1.sonic.id]: wagmi.http(getRpcUrl(evmChains?.[types.ChainKeys.SONIC_MAINNET])),
|
|
272
|
+
[chains$1.optimism.id]: wagmi.http(getRpcUrl(evmChains?.[types.ChainKeys.OPTIMISM_MAINNET])),
|
|
273
|
+
[chains$1.polygon.id]: wagmi.http(getRpcUrl(evmChains?.[types.ChainKeys.POLYGON_MAINNET])),
|
|
274
|
+
[hyper.id]: wagmi.http(getRpcUrl(evmChains?.[types.ChainKeys.HYPEREVM_MAINNET])),
|
|
275
|
+
[chains$1.lightlinkPhoenix.id]: wagmi.http(getRpcUrl(evmChains?.[types.ChainKeys.LIGHTLINK_MAINNET])),
|
|
276
|
+
[chains$1.redbellyMainnet.id]: wagmi.http(getRpcUrl(evmChains?.[types.ChainKeys.REDBELLY_MAINNET])),
|
|
277
|
+
[chains$1.kaia.id]: wagmi.http(getRpcUrl(evmChains?.[types.ChainKeys.KAIA_MAINNET]))
|
|
278
|
+
},
|
|
279
|
+
storage: wagmi.createStorage({
|
|
280
|
+
storage: wagmi.cookieStorage,
|
|
281
|
+
key: "sodax"
|
|
282
|
+
})
|
|
283
|
+
});
|
|
284
|
+
};
|
|
285
|
+
var EvmXService = class _EvmXService extends XService {
|
|
286
|
+
static instance;
|
|
287
|
+
wagmiConfig;
|
|
288
|
+
constructor() {
|
|
289
|
+
super("EVM");
|
|
290
|
+
}
|
|
291
|
+
static getInstance() {
|
|
292
|
+
if (!_EvmXService.instance) {
|
|
293
|
+
_EvmXService.instance = new _EvmXService();
|
|
272
294
|
}
|
|
273
|
-
return
|
|
295
|
+
return _EvmXService.instance;
|
|
296
|
+
}
|
|
297
|
+
// get erc20 token balance in a chain (evm chain only)
|
|
298
|
+
async _getTokenBalance(address, chainId, tokenAddress) {
|
|
299
|
+
const publicClient = actions.getPublicClient(this.wagmiConfig, { chainId });
|
|
300
|
+
if (!publicClient) throw new Error("Public client not found");
|
|
301
|
+
const balance = await publicClient.readContract({
|
|
302
|
+
abi: viem.erc20Abi,
|
|
303
|
+
address: tokenAddress,
|
|
304
|
+
functionName: "balanceOf",
|
|
305
|
+
args: [address]
|
|
306
|
+
});
|
|
307
|
+
return balance || 0n;
|
|
308
|
+
}
|
|
309
|
+
//get native balance of the chain (evm chain only)
|
|
310
|
+
async _getChainBalance(address, chainId) {
|
|
311
|
+
const balance = await actions.getPublicClient(this.wagmiConfig, { chainId })?.getBalance({
|
|
312
|
+
address
|
|
313
|
+
});
|
|
314
|
+
return balance || 0n;
|
|
274
315
|
}
|
|
275
316
|
async getBalance(address, xToken) {
|
|
276
317
|
if (!address) return 0n;
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
const utxos = await response.json();
|
|
282
|
-
const totalBalance = utxos.reduce((sum, utxo) => sum + utxo.value, 0);
|
|
283
|
-
return BigInt(totalBalance);
|
|
284
|
-
}
|
|
285
|
-
} catch {
|
|
286
|
-
return 0n;
|
|
318
|
+
if (!this.wagmiConfig) return 0n;
|
|
319
|
+
const chainId = getWagmiChainId(xToken.chainKey);
|
|
320
|
+
if (isNativeToken(xToken)) {
|
|
321
|
+
return this._getChainBalance(address, chainId);
|
|
287
322
|
}
|
|
288
|
-
|
|
323
|
+
throw new Error(`Unsupported token: ${xToken.symbol}`);
|
|
324
|
+
}
|
|
325
|
+
async getBalances(address, xTokens) {
|
|
326
|
+
if (!address) return {};
|
|
327
|
+
if (!this.wagmiConfig) return {};
|
|
328
|
+
const nativeTokenBalancePromises = xTokens.filter((xToken) => isNativeToken(xToken)).map(async (xToken) => {
|
|
329
|
+
const balance = await this.getBalance(address, xToken);
|
|
330
|
+
return { symbol: xToken.symbol, address: xToken.address, balance };
|
|
331
|
+
});
|
|
332
|
+
const nativeTokenBalances = await Promise.all(nativeTokenBalancePromises);
|
|
333
|
+
const tokenMap = nativeTokenBalances.reduce(
|
|
334
|
+
(map, { address: address2, balance }) => {
|
|
335
|
+
if (balance) map[address2] = balance;
|
|
336
|
+
return map;
|
|
337
|
+
},
|
|
338
|
+
{}
|
|
339
|
+
);
|
|
340
|
+
const nonNativeXTokens = xTokens.filter((xToken) => !isNativeToken(xToken));
|
|
341
|
+
const firstToken = xTokens[0];
|
|
342
|
+
if (!firstToken) return tokenMap;
|
|
343
|
+
const chainKey = firstToken.chainKey;
|
|
344
|
+
const viemChain = this.wagmiConfig.chains.find((chain) => chain.id === getWagmiChainId(chainKey));
|
|
345
|
+
const chainId = getWagmiChainId(chainKey);
|
|
346
|
+
const publicClient = actions.getPublicClient(this.wagmiConfig, { chainId });
|
|
347
|
+
if (!publicClient) throw new Error("Public client not found");
|
|
348
|
+
if (viemChain?.contracts?.multicall3) {
|
|
349
|
+
const result = await publicClient.multicall({
|
|
350
|
+
contracts: nonNativeXTokens.map((token) => ({
|
|
351
|
+
abi: viem.erc20Abi,
|
|
352
|
+
address: token.address,
|
|
353
|
+
functionName: "balanceOf",
|
|
354
|
+
args: [address]
|
|
355
|
+
}))
|
|
356
|
+
});
|
|
357
|
+
return nonNativeXTokens.reduce((acc, token, index) => {
|
|
358
|
+
const resultValue = result?.[index]?.result;
|
|
359
|
+
acc[token.address] = resultValue !== void 0 && resultValue !== null ? BigInt(resultValue) : 0n;
|
|
360
|
+
return acc;
|
|
361
|
+
}, tokenMap);
|
|
362
|
+
}
|
|
363
|
+
const nonNativeTokenBalances = await Promise.all(
|
|
364
|
+
nonNativeXTokens.map((token) => this._getTokenBalance(address, chainId, token.address))
|
|
365
|
+
);
|
|
366
|
+
return nonNativeXTokens.reduce((acc, token, idx) => {
|
|
367
|
+
acc[token.address] = nonNativeTokenBalances[idx] ?? 0n;
|
|
368
|
+
return acc;
|
|
369
|
+
}, tokenMap);
|
|
289
370
|
}
|
|
290
371
|
};
|
|
291
372
|
|
|
292
|
-
// src/xchains/
|
|
293
|
-
var
|
|
294
|
-
|
|
295
|
-
|
|
373
|
+
// src/xchains/evm/EvmXConnector.ts
|
|
374
|
+
var WALLETCONNECT_ICON = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath fill='%233B99FC' d='M9.58 11.58c3.55-3.47 9.29-3.47 12.84 0l.43.42a.44.44 0 0 1 0 .63l-1.46 1.43a.23.23 0 0 1-.32 0l-.59-.57a6.72 6.72 0 0 0-9.36 0l-.63.61a.23.23 0 0 1-.32 0L8.71 12.7a.44.44 0 0 1 0-.63l.87-.5Zm15.87 2.95 1.3 1.28a.44.44 0 0 1 0 .63l-5.87 5.74a.46.46 0 0 1-.64 0l-4.17-4.08a.11.11 0 0 0-.16 0l-4.17 4.08a.46.46 0 0 1-.64 0l-5.87-5.74a.44.44 0 0 1 0-.63l1.3-1.28a.46.46 0 0 1 .64 0l4.17 4.08a.11.11 0 0 0 .16 0l4.17-4.08a.46.46 0 0 1 .64 0l4.17 4.08a.11.11 0 0 0 .16 0l4.17-4.08a.46.46 0 0 1 .64 0Z'/%3E%3C/svg%3E";
|
|
375
|
+
var EvmXConnector = class extends XConnector {
|
|
376
|
+
connector;
|
|
377
|
+
constructor(connector) {
|
|
378
|
+
super("EVM", connector.name, connector.id);
|
|
379
|
+
this.connector = connector;
|
|
296
380
|
}
|
|
297
|
-
|
|
298
|
-
return
|
|
381
|
+
async connect() {
|
|
382
|
+
return;
|
|
299
383
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
constructor(unisat, address) {
|
|
303
|
-
this.unisat = unisat;
|
|
304
|
-
this.cachedAddress = address;
|
|
384
|
+
async disconnect() {
|
|
385
|
+
return;
|
|
305
386
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const accounts = await this.unisat.getAccounts();
|
|
309
|
-
if (accounts[0]) this.cachedAddress = accounts[0];
|
|
310
|
-
} catch {
|
|
311
|
-
}
|
|
312
|
-
return this.cachedAddress;
|
|
313
|
-
}
|
|
314
|
-
async getPublicKey() {
|
|
315
|
-
return this.unisat.getPublicKey();
|
|
316
|
-
}
|
|
317
|
-
async getAddressType(_address) {
|
|
318
|
-
const address = await this.getWalletAddress();
|
|
319
|
-
return types.detectBitcoinAddressType(address);
|
|
320
|
-
}
|
|
321
|
-
async signTransaction(psbtBase64, finalize = false) {
|
|
322
|
-
const psbtHex = Buffer.from(psbtBase64, "base64").toString("hex");
|
|
323
|
-
const signedHex = await this.unisat.signPsbt(psbtHex, { autoFinalized: finalize });
|
|
324
|
-
return signedHex;
|
|
325
|
-
}
|
|
326
|
-
async signEcdsaMessage(message) {
|
|
327
|
-
return this.unisat.signMessage(message, "ecdsa");
|
|
328
|
-
}
|
|
329
|
-
async signBip322Message(message) {
|
|
330
|
-
return this.unisat.signMessage(message, "bip322-simple");
|
|
387
|
+
get id() {
|
|
388
|
+
return this.connector.id;
|
|
331
389
|
}
|
|
332
|
-
|
|
333
|
-
if (
|
|
334
|
-
|
|
390
|
+
get icon() {
|
|
391
|
+
if (!this.connector.icon && this.connector.type === "walletConnect") {
|
|
392
|
+
return WALLETCONNECT_ICON;
|
|
335
393
|
}
|
|
336
|
-
return this.
|
|
394
|
+
return this.connector.icon;
|
|
337
395
|
}
|
|
338
396
|
};
|
|
339
|
-
var
|
|
397
|
+
var SolanaXService = class _SolanaXService extends XService {
|
|
398
|
+
static instance;
|
|
399
|
+
connection;
|
|
400
|
+
wallet;
|
|
340
401
|
constructor() {
|
|
341
|
-
super("
|
|
342
|
-
}
|
|
343
|
-
static isAvailable() {
|
|
344
|
-
return typeof window !== "undefined" && !!window.unisat;
|
|
345
|
-
}
|
|
346
|
-
get icon() {
|
|
347
|
-
return "https://avatars.githubusercontent.com/u/125119198?s=200&v=4";
|
|
402
|
+
super("SOLANA");
|
|
348
403
|
}
|
|
349
|
-
|
|
350
|
-
if (!
|
|
351
|
-
|
|
404
|
+
static getInstance() {
|
|
405
|
+
if (!_SolanaXService.instance) {
|
|
406
|
+
_SolanaXService.instance = new _SolanaXService();
|
|
352
407
|
}
|
|
353
|
-
|
|
354
|
-
const address = accounts[0];
|
|
355
|
-
if (!address) return void 0;
|
|
356
|
-
this.walletProvider = new UnisatWalletProvider(window.unisat, address);
|
|
357
|
-
return {
|
|
358
|
-
address,
|
|
359
|
-
xChainType: "BITCOIN"
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
async disconnect() {
|
|
363
|
-
this.walletProvider = void 0;
|
|
364
|
-
}
|
|
365
|
-
getWalletProvider() {
|
|
366
|
-
return this.walletProvider;
|
|
408
|
+
return _SolanaXService.instance;
|
|
367
409
|
}
|
|
368
|
-
|
|
369
|
-
if (!
|
|
370
|
-
|
|
410
|
+
async getBalance(address, xToken) {
|
|
411
|
+
if (!address) return BigInt(0);
|
|
412
|
+
const connection = this.connection;
|
|
413
|
+
if (!connection) {
|
|
414
|
+
return BigInt(0);
|
|
415
|
+
}
|
|
416
|
+
try {
|
|
417
|
+
if (isNativeToken(xToken)) {
|
|
418
|
+
const newBalance = await connection.getBalance(new web3_js.PublicKey(address));
|
|
419
|
+
return BigInt(newBalance);
|
|
420
|
+
}
|
|
421
|
+
const tokenAccountPubkey = splToken.getAssociatedTokenAddressSync(new web3_js.PublicKey(xToken.address), new web3_js.PublicKey(address));
|
|
422
|
+
const tokenAccount = await splToken.getAccount(connection, tokenAccountPubkey);
|
|
423
|
+
return BigInt(tokenAccount.amount);
|
|
424
|
+
} catch {
|
|
425
|
+
return BigInt(0);
|
|
426
|
+
}
|
|
371
427
|
}
|
|
372
428
|
};
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
429
|
+
|
|
430
|
+
// src/shared/guards.ts
|
|
431
|
+
function isRecord(value) {
|
|
432
|
+
return typeof value === "object" && value !== null;
|
|
433
|
+
}
|
|
434
|
+
function hasStringProperty(value, key) {
|
|
435
|
+
return isRecord(value) && typeof value[key] === "string";
|
|
436
|
+
}
|
|
437
|
+
function hasOptionalStringProperty(value, key) {
|
|
438
|
+
return isRecord(value) && (value[key] === void 0 || typeof value[key] === "string");
|
|
439
|
+
}
|
|
440
|
+
function hasBooleanProperty(value, key) {
|
|
441
|
+
return isRecord(value) && typeof value[key] === "boolean";
|
|
442
|
+
}
|
|
443
|
+
function hasFunctionProperty(value, key) {
|
|
444
|
+
return isRecord(value) && typeof value[key] === "function";
|
|
445
|
+
}
|
|
446
|
+
function assert(condition, message) {
|
|
447
|
+
if (!condition) {
|
|
448
|
+
throw new Error(message);
|
|
386
449
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
450
|
+
}
|
|
451
|
+
function assertSuiProviderShape(caller, client, wallet, account) {
|
|
452
|
+
const clientOk = isRecord(client) && hasFunctionProperty(client, "executeTransactionBlock") && hasFunctionProperty(client, "devInspectTransactionBlock") && hasFunctionProperty(client, "getCoins");
|
|
453
|
+
assert(clientOk, `[${caller}] invalid Sui client shape`);
|
|
454
|
+
const walletOk = isRecord(wallet) && hasStringProperty(wallet, "name");
|
|
455
|
+
assert(walletOk, `[${caller}] invalid Sui wallet shape`);
|
|
456
|
+
const accountOk = isRecord(account) && hasStringProperty(account, "address");
|
|
457
|
+
assert(accountOk, `[${caller}] invalid Sui account shape`);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// src/xchains/sui/SuiXService.ts
|
|
461
|
+
var SuiXService = class _SuiXService extends XService {
|
|
462
|
+
static instance;
|
|
463
|
+
// Hydrated by SuiHydrator. Start undefined because wallet may not be connected yet.
|
|
464
|
+
// suiClient is typed structurally for the methods we call directly.
|
|
465
|
+
// suiWallet/suiAccount are opaque — stored and passed through to SuiWalletProvider.
|
|
466
|
+
suiClient;
|
|
467
|
+
suiWallet;
|
|
468
|
+
suiAccount;
|
|
469
|
+
constructor() {
|
|
470
|
+
super("SUI");
|
|
406
471
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
const signingIndexes = Array.from({ length: inputCount }, (_, i) => i);
|
|
411
|
-
const response = await request3("signPsbt", {
|
|
412
|
-
psbt: psbtBase64,
|
|
413
|
-
broadcast: false,
|
|
414
|
-
signInputs: {
|
|
415
|
-
[this.address]: signingIndexes
|
|
416
|
-
}
|
|
417
|
-
});
|
|
418
|
-
if (response.status === "error") {
|
|
419
|
-
throw new Error(response.error?.message || "Xverse PSBT signing failed");
|
|
420
|
-
}
|
|
421
|
-
const result = response.result;
|
|
422
|
-
if (finalize) {
|
|
423
|
-
return Buffer.from(result.psbt, "base64").toString("hex");
|
|
472
|
+
static getInstance() {
|
|
473
|
+
if (!_SuiXService.instance) {
|
|
474
|
+
_SuiXService.instance = new _SuiXService();
|
|
424
475
|
}
|
|
425
|
-
return
|
|
476
|
+
return _SuiXService.instance;
|
|
426
477
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
if (response.status === "error") {
|
|
435
|
-
throw new Error(response.error?.message || "Xverse ECDSA signing failed");
|
|
478
|
+
createWalletProvider() {
|
|
479
|
+
if (!this.suiClient || !this.suiWallet || !this.suiAccount) {
|
|
480
|
+
console.warn(
|
|
481
|
+
"[SuiXService] createWalletProvider: missing dependencies \u2014 wallet not connected yet",
|
|
482
|
+
{ hasClient: !!this.suiClient, hasWallet: !!this.suiWallet, hasAccount: !!this.suiAccount }
|
|
483
|
+
);
|
|
484
|
+
return void 0;
|
|
436
485
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
address: this.address,
|
|
443
|
-
message,
|
|
444
|
-
protocol: satsConnect.MessageSigningProtocols.BIP322
|
|
486
|
+
assertSuiProviderShape("SuiXService", this.suiClient, this.suiWallet, this.suiAccount);
|
|
487
|
+
return new walletSdkCore.SuiWalletProvider({
|
|
488
|
+
client: this.suiClient,
|
|
489
|
+
wallet: this.suiWallet,
|
|
490
|
+
account: this.suiAccount
|
|
445
491
|
});
|
|
446
|
-
if (response.status === "error") {
|
|
447
|
-
throw new Error(response.error?.message || "Xverse BIP322 signing failed");
|
|
448
|
-
}
|
|
449
|
-
return response.result.signature;
|
|
450
492
|
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
493
|
+
// getBalance is not used because getBalances uses getAllBalances which returns all balances
|
|
494
|
+
async getBalances(address, xTokens) {
|
|
495
|
+
if (!address || !this.suiClient) return {};
|
|
496
|
+
const client = this.suiClient;
|
|
497
|
+
try {
|
|
498
|
+
const balancePromises = xTokens.map(async (xToken) => {
|
|
499
|
+
let coinType = isNativeToken(xToken) ? "0x2::sui::SUI" : xToken.address;
|
|
500
|
+
if (coinType === "0x03917a812fe4a6d6bc779c5ab53f8a80ba741f8af04121193fc44e0f662e2ceb::balanced_dollar::BALANCED_DOLLAR") {
|
|
501
|
+
coinType = "0x3917a812fe4a6d6bc779c5ab53f8a80ba741f8af04121193fc44e0f662e2ceb::balanced_dollar::BALANCED_DOLLAR";
|
|
458
502
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
503
|
+
const balance = await client.getBalance({
|
|
504
|
+
owner: address,
|
|
505
|
+
coinType
|
|
506
|
+
});
|
|
507
|
+
return {
|
|
508
|
+
address: xToken.address,
|
|
509
|
+
balance: balance ? BigInt(balance.totalBalance) : void 0
|
|
510
|
+
};
|
|
511
|
+
});
|
|
512
|
+
const results = await Promise.all(balancePromises);
|
|
513
|
+
const tokenMap = {};
|
|
514
|
+
results.forEach((result) => {
|
|
515
|
+
if (result.balance !== void 0) {
|
|
516
|
+
tokenMap[result.address] = result.balance;
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
return tokenMap;
|
|
520
|
+
} catch (error) {
|
|
521
|
+
console.error("[wallet-sdk-react] SUI getBalances failed:", error);
|
|
522
|
+
return {};
|
|
463
523
|
}
|
|
464
|
-
return response.result.txid;
|
|
465
524
|
}
|
|
466
525
|
};
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
return typeof window !== "undefined" && !!window.BitcoinProvider;
|
|
526
|
+
|
|
527
|
+
// src/xchains/sui/SuiXConnector.ts
|
|
528
|
+
var isSuiWalletInfo = (value) => {
|
|
529
|
+
return isRecord(value) && hasStringProperty(value, "name") && // Some wallets may not expose `id` — in that case we fall back to `name` for stability.
|
|
530
|
+
// We still validate if it exists.
|
|
531
|
+
hasOptionalStringProperty(value, "id") && hasOptionalStringProperty(value, "icon");
|
|
532
|
+
};
|
|
533
|
+
var SuiXConnector = class extends XConnector {
|
|
534
|
+
wallet;
|
|
535
|
+
constructor(wallet) {
|
|
536
|
+
assert(isSuiWalletInfo(wallet), "[SuiXConnector] invalid wallet object");
|
|
537
|
+
const id = wallet.id ?? wallet.name;
|
|
538
|
+
assert(typeof id === "string" && id.length > 0, "[SuiXConnector] invalid wallet id");
|
|
539
|
+
super("SUI", wallet.name, id);
|
|
540
|
+
this.wallet = { id, name: wallet.name, icon: wallet.icon };
|
|
483
541
|
}
|
|
484
|
-
|
|
485
|
-
return
|
|
542
|
+
getXService() {
|
|
543
|
+
return SuiXService.getInstance();
|
|
486
544
|
}
|
|
487
545
|
async connect() {
|
|
488
|
-
|
|
489
|
-
throw new Error("Xverse wallet is not installed");
|
|
490
|
-
}
|
|
491
|
-
const { request: request3 } = await import('sats-connect');
|
|
492
|
-
const response = await request3("getAccounts", {
|
|
493
|
-
purposes: [this.addressPurpose],
|
|
494
|
-
message: "Connect to Sodax"
|
|
495
|
-
});
|
|
496
|
-
if (response.status === "error") {
|
|
497
|
-
throw new Error(response.error?.message || "Xverse connection failed");
|
|
498
|
-
}
|
|
499
|
-
const accounts = response.result;
|
|
500
|
-
const paymentAccount = accounts.find((a) => a.purpose === this.addressPurpose) || accounts[0];
|
|
501
|
-
if (!paymentAccount) return void 0;
|
|
502
|
-
this.walletProvider = new XverseWalletProvider(
|
|
503
|
-
paymentAccount.address,
|
|
504
|
-
paymentAccount.publicKey
|
|
505
|
-
);
|
|
506
|
-
return {
|
|
507
|
-
address: paymentAccount.address,
|
|
508
|
-
publicKey: paymentAccount.publicKey,
|
|
509
|
-
xChainType: "BITCOIN"
|
|
510
|
-
};
|
|
546
|
+
return;
|
|
511
547
|
}
|
|
512
548
|
async disconnect() {
|
|
513
|
-
this.walletProvider = void 0;
|
|
514
|
-
}
|
|
515
|
-
getWalletProvider() {
|
|
516
|
-
return this.walletProvider;
|
|
517
549
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
return new XverseWalletProvider(xAccount.address, xAccount.publicKey);
|
|
550
|
+
get icon() {
|
|
551
|
+
return this.wallet.icon;
|
|
521
552
|
}
|
|
522
553
|
};
|
|
523
|
-
var
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
554
|
+
var CustomSorobanServer = class extends StellarSdk.rpc.Server {
|
|
555
|
+
customHeaders;
|
|
556
|
+
constructor(serverUrl, customHeaders) {
|
|
557
|
+
super(serverUrl, {
|
|
558
|
+
allowHttp: true
|
|
559
|
+
});
|
|
560
|
+
this.customHeaders = customHeaders;
|
|
527
561
|
}
|
|
528
|
-
async
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
562
|
+
async simulateTransaction(tx) {
|
|
563
|
+
const requestOptions = {
|
|
564
|
+
method: "POST",
|
|
565
|
+
headers: {
|
|
566
|
+
"Content-Type": "application/json",
|
|
567
|
+
...this.customHeaders
|
|
568
|
+
},
|
|
569
|
+
body: JSON.stringify({
|
|
570
|
+
id: 1,
|
|
571
|
+
jsonrpc: "2.0",
|
|
572
|
+
method: "simulateTransaction",
|
|
573
|
+
params: {
|
|
574
|
+
transaction: tx.toXDR()
|
|
575
|
+
}
|
|
576
|
+
})
|
|
577
|
+
};
|
|
578
|
+
const response = await fetch(`${this.serverURL}`, requestOptions);
|
|
579
|
+
if (!response.ok) {
|
|
580
|
+
throw new Error(`HTTP error simulating TX! status: ${response.status}`);
|
|
533
581
|
}
|
|
534
|
-
return
|
|
582
|
+
return response.json().then((json) => StellarSdk.rpc.parseRawSimulation(json.result));
|
|
535
583
|
}
|
|
536
|
-
async
|
|
537
|
-
|
|
584
|
+
async sendTransaction(tx) {
|
|
585
|
+
const requestOptions = {
|
|
586
|
+
method: "POST",
|
|
587
|
+
headers: {
|
|
588
|
+
"Content-Type": "application/json",
|
|
589
|
+
...this.customHeaders
|
|
590
|
+
},
|
|
591
|
+
body: JSON.stringify({
|
|
592
|
+
id: 1,
|
|
593
|
+
jsonrpc: "2.0",
|
|
594
|
+
method: "sendTransaction",
|
|
595
|
+
params: {
|
|
596
|
+
transaction: tx.toXDR()
|
|
597
|
+
}
|
|
598
|
+
})
|
|
599
|
+
};
|
|
600
|
+
const response = await fetch(`${this.serverURL}`, requestOptions);
|
|
601
|
+
if (!response.ok) {
|
|
602
|
+
throw new Error(`HTTP error submitting TX! status: ${response.status}`);
|
|
603
|
+
}
|
|
604
|
+
return response.json().then((json) => json.result);
|
|
538
605
|
}
|
|
539
|
-
async
|
|
540
|
-
const
|
|
541
|
-
|
|
606
|
+
async getTransaction(hash) {
|
|
607
|
+
const requestOptions = {
|
|
608
|
+
method: "POST",
|
|
609
|
+
headers: {
|
|
610
|
+
"Content-Type": "application/json",
|
|
611
|
+
...this.customHeaders
|
|
612
|
+
},
|
|
613
|
+
body: JSON.stringify({
|
|
614
|
+
id: 1,
|
|
615
|
+
jsonrpc: "2.0",
|
|
616
|
+
method: "getTransaction",
|
|
617
|
+
params: { hash }
|
|
618
|
+
})
|
|
619
|
+
};
|
|
620
|
+
const response = await fetch(`${this.serverURL}`, requestOptions);
|
|
621
|
+
if (!response.ok) {
|
|
622
|
+
throw new Error(`HTTP error getting TX! status: ${response.status}`);
|
|
623
|
+
}
|
|
624
|
+
return response.json().then((json) => json.result);
|
|
542
625
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
626
|
+
};
|
|
627
|
+
var CustomSorobanServer_default = CustomSorobanServer;
|
|
628
|
+
var accountToScVal = (account) => new StellarSdk.Address(account).toScVal();
|
|
629
|
+
var simulateTx = (tx, server) => server.simulateTransaction(tx);
|
|
630
|
+
var getTokenBalance = async (address, tokenId, txBuilder, server) => {
|
|
631
|
+
const params = [accountToScVal(address)];
|
|
632
|
+
const contract = new StellarSdk.Contract(tokenId);
|
|
633
|
+
const tx = txBuilder.addOperation(contract.call("balance", ...params)).setTimeout(StellarSdk.TimeoutInfinite).build();
|
|
634
|
+
const result = await simulateTx(tx, server);
|
|
635
|
+
if (!StellarSdk.rpc.Api.isSimulationSuccess(result)) {
|
|
636
|
+
throw new Error(`Simulation failed: ${JSON.stringify(result)}`);
|
|
546
637
|
}
|
|
547
|
-
|
|
548
|
-
|
|
638
|
+
return result.result ? StellarSdk.scValToBigInt(result.result.retval) : 0n;
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
// src/constants.ts
|
|
642
|
+
var SUI_DEFAULT_NETWORK = "mainnet";
|
|
643
|
+
var SUI_DEFAULT_AUTO_CONNECT = true;
|
|
644
|
+
var EVM_DEFAULT_RECONNECT_ON_MOUNT = false;
|
|
645
|
+
var EVM_DEFAULT_SSR = true;
|
|
646
|
+
var SOLANA_DEFAULT_AUTO_CONNECT = true;
|
|
647
|
+
var SOLANA_DEFAULT_RPC_URL = "https://api.mainnet-beta.solana.com";
|
|
648
|
+
var SOLANA_METAMASK_CONNECT_TIMEOUT_MS = 3e4;
|
|
649
|
+
var BITCOIN_DEFAULT_RPC_URL = "https://mempool.space/api";
|
|
650
|
+
var STELLAR_DEFAULT_HORIZON_RPC_URL = "https://horizon.stellar.org";
|
|
651
|
+
var STELLAR_DEFAULT_SOROBAN_RPC_URL = "https://rpc.ankr.com/stellar_soroban";
|
|
652
|
+
var NEAR_DEFAULT_RPC_URL = "https://1rpc.io/near";
|
|
653
|
+
var WALLET_METADATA = {
|
|
654
|
+
unisat: {
|
|
655
|
+
installUrl: "https://chromewebstore.google.com/detail/unisat-wallet/ppbibelpcjmhbdihakflkdcoccbgbkpo",
|
|
656
|
+
icon: "https://avatars.githubusercontent.com/u/125119198?s=200&v=4"
|
|
657
|
+
},
|
|
658
|
+
xverse: {
|
|
659
|
+
installUrl: "https://chromewebstore.google.com/detail/xverse-bitcoin-crypto-wal/idnnbdplmphpflfnlkomgpfbpcgelopg",
|
|
660
|
+
icon: "https://cdn.brandfetch.io/iddzGN5Rcv/w/400/h/400/theme/dark/icon.jpeg?c=1bxid64Mup7aczewSAYMX&t=1771902357797"
|
|
661
|
+
},
|
|
662
|
+
okx: {
|
|
663
|
+
installUrl: "https://chromewebstore.google.com/detail/okx-wallet/mcohilncbfahbmgdjkbpemcciiolgcge",
|
|
664
|
+
icon: "https://static.okx.com/cdn/assets/imgs/247/58E63FEA47A2B7D7.png"
|
|
665
|
+
},
|
|
666
|
+
hana: {
|
|
667
|
+
installUrl: "https://chromewebstore.google.com/detail/hana-wallet/jfdlamikmbghhapbgfoogdffldioobgl",
|
|
668
|
+
icon: "https://raw.githubusercontent.com/balancednetwork/icons/master/wallets/hana.svg"
|
|
549
669
|
}
|
|
550
|
-
|
|
551
|
-
|
|
670
|
+
};
|
|
671
|
+
|
|
672
|
+
// src/xchains/stellar/StellarXService.ts
|
|
673
|
+
var STELLAR_BASE_RESERVE_STROOPS = 5e6;
|
|
674
|
+
function parseXlmBalanceToStroops(balanceStr) {
|
|
675
|
+
const parts = balanceStr.split(".");
|
|
676
|
+
const whole = parts[0] ?? "0";
|
|
677
|
+
const frac = (parts[1] ?? "").padEnd(7, "0").slice(0, 7);
|
|
678
|
+
return BigInt(whole + frac);
|
|
679
|
+
}
|
|
680
|
+
var StellarXService = class _StellarXService extends XService {
|
|
681
|
+
static instance;
|
|
682
|
+
walletsKit;
|
|
683
|
+
server;
|
|
684
|
+
sorobanServer;
|
|
685
|
+
constructor(horizonRpcUrl, sorobanRpcUrl) {
|
|
686
|
+
super("STELLAR");
|
|
687
|
+
this.walletsKit = new stellarWalletsKit.StellarWalletsKit({
|
|
688
|
+
network: stellarWalletsKit.WalletNetwork.PUBLIC,
|
|
689
|
+
modules: stellarWalletsKit.allowAllModules()
|
|
690
|
+
});
|
|
691
|
+
this.server = new StellarSdk__namespace.Horizon.Server(horizonRpcUrl ?? STELLAR_DEFAULT_HORIZON_RPC_URL, { allowHttp: true });
|
|
692
|
+
this.sorobanServer = new CustomSorobanServer_default(sorobanRpcUrl ?? STELLAR_DEFAULT_SOROBAN_RPC_URL, {});
|
|
552
693
|
}
|
|
553
|
-
|
|
554
|
-
if (
|
|
555
|
-
|
|
694
|
+
static getInstance(horizonRpcUrl, sorobanRpcUrl) {
|
|
695
|
+
if (!_StellarXService.instance) {
|
|
696
|
+
_StellarXService.instance = new _StellarXService(horizonRpcUrl, sorobanRpcUrl);
|
|
697
|
+
} else {
|
|
698
|
+
if (horizonRpcUrl) {
|
|
699
|
+
_StellarXService.instance.server = new StellarSdk__namespace.Horizon.Server(horizonRpcUrl, { allowHttp: true });
|
|
700
|
+
}
|
|
701
|
+
if (sorobanRpcUrl) {
|
|
702
|
+
_StellarXService.instance.sorobanServer = new CustomSorobanServer_default(sorobanRpcUrl, {});
|
|
703
|
+
}
|
|
556
704
|
}
|
|
557
|
-
return
|
|
705
|
+
return _StellarXService.instance;
|
|
558
706
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
707
|
+
async getBalance(address, xToken) {
|
|
708
|
+
if (!address) return BigInt(0);
|
|
709
|
+
const stellarAccount = await this.server.loadAccount(address);
|
|
710
|
+
if (xToken.symbol === "XLM") {
|
|
711
|
+
const xlmBalance = stellarAccount.balances.find((balance) => balance.asset_type === "native");
|
|
712
|
+
if (xlmBalance) {
|
|
713
|
+
const rawBalanceStroops = parseXlmBalanceToStroops(xlmBalance.balance);
|
|
714
|
+
const sellingLiabilitiesStroops = xlmBalance.selling_liabilities ? parseXlmBalanceToStroops(xlmBalance.selling_liabilities) : BigInt(0);
|
|
715
|
+
const reserveFields = stellarAccount;
|
|
716
|
+
const subentryCount = reserveFields.subentry_count ?? 0;
|
|
717
|
+
const numSponsoring = reserveFields.num_sponsoring ?? 0;
|
|
718
|
+
const numSponsored = reserveFields.num_sponsored ?? 0;
|
|
719
|
+
const reserveCount = Math.max(0, 2 + subentryCount + numSponsoring - numSponsored);
|
|
720
|
+
const minBalanceStroops = BigInt(reserveCount) * BigInt(STELLAR_BASE_RESERVE_STROOPS) + sellingLiabilitiesStroops;
|
|
721
|
+
const availableStroops = rawBalanceStroops > minBalanceStroops ? rawBalanceStroops - minBalanceStroops : BigInt(0);
|
|
722
|
+
return availableStroops;
|
|
723
|
+
}
|
|
724
|
+
} else {
|
|
725
|
+
try {
|
|
726
|
+
const txBuilder = new StellarSdk__namespace.TransactionBuilder(stellarAccount, {
|
|
727
|
+
fee: StellarSdk__namespace.BASE_FEE,
|
|
728
|
+
networkPassphrase: StellarSdk__namespace.Networks.PUBLIC
|
|
729
|
+
});
|
|
730
|
+
const balance = await getTokenBalance(address, xToken.address, txBuilder, this.sorobanServer);
|
|
731
|
+
return balance;
|
|
732
|
+
} catch (e) {
|
|
733
|
+
console.error(`Error while fetching token on Stellar: ${xToken.symbol}, Error: ${e}`);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
return BigInt(0);
|
|
563
737
|
}
|
|
564
|
-
|
|
565
|
-
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
// src/xchains/stellar/StellarWalletsKitXConnector.ts
|
|
741
|
+
var StellarWalletsKitXConnector = class extends XConnector {
|
|
742
|
+
_wallet;
|
|
743
|
+
constructor(wallet) {
|
|
744
|
+
super("STELLAR", wallet.name, wallet.id);
|
|
745
|
+
this._wallet = wallet;
|
|
566
746
|
}
|
|
567
|
-
|
|
568
|
-
return
|
|
747
|
+
getXService() {
|
|
748
|
+
return StellarXService.getInstance();
|
|
569
749
|
}
|
|
570
750
|
async connect() {
|
|
571
|
-
const
|
|
572
|
-
if (!
|
|
573
|
-
|
|
751
|
+
const kit = this.getXService().walletsKit;
|
|
752
|
+
if (!this._wallet) {
|
|
753
|
+
return;
|
|
574
754
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
755
|
+
if (!this._wallet.isAvailable) {
|
|
756
|
+
throw new Error(`${this._wallet.name} is not installed. Install the wallet and reload the page.`);
|
|
757
|
+
}
|
|
758
|
+
kit.setWallet(this._wallet.id);
|
|
759
|
+
const { address } = await kit.getAddress();
|
|
578
760
|
return {
|
|
579
761
|
address,
|
|
580
|
-
xChainType:
|
|
762
|
+
xChainType: this.xChainType
|
|
581
763
|
};
|
|
582
764
|
}
|
|
583
765
|
async disconnect() {
|
|
584
|
-
this.walletProvider = void 0;
|
|
585
766
|
}
|
|
586
|
-
|
|
587
|
-
return this.
|
|
767
|
+
get icon() {
|
|
768
|
+
return this._wallet.icon;
|
|
588
769
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
if (!okx || !xAccount.address) return void 0;
|
|
592
|
-
return new OKXWalletProvider(okx, xAccount.address);
|
|
770
|
+
get isInstalled() {
|
|
771
|
+
return this._wallet.isAvailable;
|
|
593
772
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
id: 999,
|
|
597
|
-
name: "HyperEVM",
|
|
598
|
-
nativeCurrency: {
|
|
599
|
-
decimals: 18,
|
|
600
|
-
name: "HYPE",
|
|
601
|
-
symbol: "HYPE"
|
|
602
|
-
},
|
|
603
|
-
rpcUrls: {
|
|
604
|
-
default: { http: ["https://rpc.hyperliquid.xyz/evm"] }
|
|
605
|
-
},
|
|
606
|
-
blockExplorers: {
|
|
607
|
-
default: {
|
|
608
|
-
name: "HyperEVMScan",
|
|
609
|
-
url: "https://hyperevmscan.io/"
|
|
610
|
-
}
|
|
611
|
-
},
|
|
612
|
-
contracts: {
|
|
613
|
-
multicall3: {
|
|
614
|
-
address: "0xcA11bde05977b3631167028862bE2a173976CA11",
|
|
615
|
-
blockCreated: 13051
|
|
616
|
-
}
|
|
773
|
+
get installUrl() {
|
|
774
|
+
return this._wallet.url;
|
|
617
775
|
}
|
|
618
|
-
});
|
|
619
|
-
var createWagmiConfig = (config, options) => {
|
|
620
|
-
return wagmi.createConfig({
|
|
621
|
-
chains: [
|
|
622
|
-
chains.mainnet,
|
|
623
|
-
chains.avalanche,
|
|
624
|
-
chains.arbitrum,
|
|
625
|
-
chains.base,
|
|
626
|
-
chains.bsc,
|
|
627
|
-
chains.sonic,
|
|
628
|
-
chains.optimism,
|
|
629
|
-
chains.polygon,
|
|
630
|
-
hyper,
|
|
631
|
-
chains.lightlinkPhoenix,
|
|
632
|
-
chains.kaia,
|
|
633
|
-
chains.redbellyMainnet
|
|
634
|
-
],
|
|
635
|
-
ssr: options?.ssr,
|
|
636
|
-
transports: {
|
|
637
|
-
[chains.mainnet.id]: wagmi.http(config[types.ETHEREUM_MAINNET_CHAIN_ID]),
|
|
638
|
-
[chains.avalanche.id]: wagmi.http(config[types.AVALANCHE_MAINNET_CHAIN_ID]),
|
|
639
|
-
[chains.arbitrum.id]: wagmi.http(config[types.ARBITRUM_MAINNET_CHAIN_ID]),
|
|
640
|
-
[chains.base.id]: wagmi.http(config[types.BASE_MAINNET_CHAIN_ID]),
|
|
641
|
-
[chains.bsc.id]: wagmi.http(config[types.BSC_MAINNET_CHAIN_ID]),
|
|
642
|
-
[chains.sonic.id]: wagmi.http(config[types.SONIC_MAINNET_CHAIN_ID]),
|
|
643
|
-
[chains.optimism.id]: wagmi.http(config[types.OPTIMISM_MAINNET_CHAIN_ID]),
|
|
644
|
-
[chains.polygon.id]: wagmi.http(config[types.POLYGON_MAINNET_CHAIN_ID]),
|
|
645
|
-
[hyper.id]: wagmi.http(config[types.HYPEREVM_MAINNET_CHAIN_ID]),
|
|
646
|
-
[chains.lightlinkPhoenix.id]: wagmi.http(config[types.LIGHTLINK_MAINNET_CHAIN_ID]),
|
|
647
|
-
[chains.redbellyMainnet.id]: wagmi.http(config[types.REDBELLY_MAINNET_CHAIN_ID]),
|
|
648
|
-
[chains.kaia.id]: wagmi.http(config[types.KAIA_MAINNET_CHAIN_ID])
|
|
649
|
-
},
|
|
650
|
-
storage: wagmi.createStorage({
|
|
651
|
-
storage: wagmi.cookieStorage,
|
|
652
|
-
key: "sodax"
|
|
653
|
-
})
|
|
654
|
-
});
|
|
655
776
|
};
|
|
656
|
-
var
|
|
657
|
-
|
|
658
|
-
|
|
777
|
+
var IconSdk = "default" in IconSdkRaw__namespace.default ? IconSdkRaw__namespace.default : IconSdkRaw__namespace;
|
|
778
|
+
var { IconService: IconServiceConstructor, Builder: IconBuilder, Converter: IconConverter } = IconSdk;
|
|
779
|
+
var CHAIN_INFO = {
|
|
780
|
+
[1 /* MAINNET */]: {
|
|
781
|
+
APIEndpoint: "https://ctz.solidwallet.io/api/v3"}
|
|
782
|
+
};
|
|
783
|
+
var IconXService = class _IconXService extends XService {
|
|
784
|
+
static instance;
|
|
785
|
+
iconService;
|
|
786
|
+
constructor(rpcUrl) {
|
|
787
|
+
super("ICON");
|
|
788
|
+
const mainnetInfo = CHAIN_INFO[1 /* MAINNET */];
|
|
789
|
+
if (!mainnetInfo) throw new Error("ICON mainnet chain info not found");
|
|
790
|
+
this.iconService = new IconServiceConstructor(
|
|
791
|
+
new IconServiceConstructor.HttpProvider(rpcUrl ?? mainnetInfo.APIEndpoint)
|
|
792
|
+
);
|
|
659
793
|
}
|
|
660
|
-
|
|
661
|
-
|
|
794
|
+
static getInstance(rpcUrl) {
|
|
795
|
+
if (!_IconXService.instance) {
|
|
796
|
+
_IconXService.instance = new _IconXService(rpcUrl);
|
|
797
|
+
}
|
|
798
|
+
return _IconXService.instance;
|
|
662
799
|
}
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
800
|
+
async getAggregateData(requireSuccess, calls) {
|
|
801
|
+
const rawTx = new IconBuilder.CallBuilder().to("cxa4aa9185e23558cff990f494c1fd2845f6cbf741").method("tryAggregate").params({ requireSuccess: IconConverter.toHex(requireSuccess ? 1 : 0), calls }).build();
|
|
802
|
+
try {
|
|
803
|
+
const result = await this.iconService.call(rawTx).execute();
|
|
804
|
+
const aggs = result["returnData"];
|
|
805
|
+
const data = aggs.map((agg) => {
|
|
806
|
+
if (agg["success"] === "0x0") {
|
|
807
|
+
return null;
|
|
808
|
+
}
|
|
809
|
+
return agg["returnData"];
|
|
810
|
+
});
|
|
811
|
+
return data;
|
|
812
|
+
} catch (err) {
|
|
813
|
+
console.error(err);
|
|
814
|
+
return Array(calls.length).fill(null);
|
|
666
815
|
}
|
|
667
|
-
return _EvmXService.instance;
|
|
668
|
-
}
|
|
669
|
-
// get erc20 token balance in a chain (evm chain only)
|
|
670
|
-
async _getTokenBalance(address, chainId, tokenAddress) {
|
|
671
|
-
const publicClient = actions.getPublicClient(this.wagmiConfig, { chainId });
|
|
672
|
-
if (!publicClient) throw new Error("Public client not found");
|
|
673
|
-
const balance = await publicClient.readContract({
|
|
674
|
-
abi: viem.erc20Abi,
|
|
675
|
-
address: tokenAddress,
|
|
676
|
-
functionName: "balanceOf",
|
|
677
|
-
args: [address]
|
|
678
|
-
});
|
|
679
|
-
return balance || 0n;
|
|
680
|
-
}
|
|
681
|
-
//get native balance of the chain (evm chain only)
|
|
682
|
-
async _getChainBalance(address, chainId) {
|
|
683
|
-
const balance = await actions.getPublicClient(this.wagmiConfig, { chainId })?.getBalance({
|
|
684
|
-
address
|
|
685
|
-
});
|
|
686
|
-
return balance || 0n;
|
|
687
|
-
}
|
|
688
|
-
async getBalance(address, xToken) {
|
|
689
|
-
if (!address) return 0n;
|
|
690
|
-
if (!this.wagmiConfig) return 0n;
|
|
691
|
-
const chainId = getWagmiChainId(xToken.xChainId);
|
|
692
|
-
if (isNativeToken(xToken)) {
|
|
693
|
-
return this._getChainBalance(address, chainId);
|
|
694
|
-
}
|
|
695
|
-
throw new Error(`Unsupported token: ${xToken.symbol}`);
|
|
696
816
|
}
|
|
697
817
|
async getBalances(address, xTokens) {
|
|
698
818
|
if (!address) return {};
|
|
699
|
-
|
|
700
|
-
const
|
|
701
|
-
const balance = await this.getBalance(address, xToken);
|
|
702
|
-
return { symbol: xToken.symbol, address: xToken.address, balance };
|
|
703
|
-
});
|
|
704
|
-
const nativeTokenBalances = await Promise.all(nativeTokenBalancePromises);
|
|
705
|
-
const tokenMap = nativeTokenBalances.reduce((map, { address: address2, balance }) => {
|
|
706
|
-
if (balance) map[address2] = balance;
|
|
707
|
-
return map;
|
|
708
|
-
}, {});
|
|
819
|
+
const balances = {};
|
|
820
|
+
const nativeXToken = xTokens.find((xToken) => isNativeToken(xToken));
|
|
709
821
|
const nonNativeXTokens = xTokens.filter((xToken) => !isNativeToken(xToken));
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
const publicClient = actions.getPublicClient(this.wagmiConfig, { chainId });
|
|
714
|
-
if (!publicClient) throw new Error("Public client not found");
|
|
715
|
-
if (viemChain?.contracts?.multicall3) {
|
|
716
|
-
const result = await publicClient.multicall({
|
|
717
|
-
contracts: nonNativeXTokens.map((token) => ({
|
|
718
|
-
abi: viem.erc20Abi,
|
|
719
|
-
address: token.address,
|
|
720
|
-
functionName: "balanceOf",
|
|
721
|
-
args: [address]
|
|
722
|
-
}))
|
|
723
|
-
});
|
|
724
|
-
return nonNativeXTokens.reduce((acc, token, index) => {
|
|
725
|
-
acc[token.address] = result?.[index]?.result?.toString() || "0";
|
|
726
|
-
return acc;
|
|
727
|
-
}, tokenMap);
|
|
822
|
+
if (nativeXToken) {
|
|
823
|
+
const balance = await this.iconService.getBalance(address).execute();
|
|
824
|
+
balances[nativeXToken.address] = BigInt(balance.toFixed());
|
|
728
825
|
}
|
|
729
|
-
const
|
|
730
|
-
|
|
826
|
+
const cds = nonNativeXTokens.map((token) => {
|
|
827
|
+
return {
|
|
828
|
+
target: token.address,
|
|
829
|
+
method: "balanceOf",
|
|
830
|
+
params: [address]
|
|
831
|
+
};
|
|
832
|
+
});
|
|
833
|
+
const data = await this.getAggregateData(
|
|
834
|
+
false,
|
|
835
|
+
cds.filter((cd) => cd.target.startsWith("cx"))
|
|
731
836
|
);
|
|
732
|
-
return nonNativeXTokens.reduce((
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
837
|
+
return nonNativeXTokens.reduce((agg, token, idx) => {
|
|
838
|
+
const balance = data[idx];
|
|
839
|
+
if (balance) {
|
|
840
|
+
balances[token.address] = BigInt(balance);
|
|
841
|
+
}
|
|
842
|
+
return agg;
|
|
843
|
+
}, balances);
|
|
736
844
|
}
|
|
737
845
|
};
|
|
738
846
|
|
|
739
|
-
// src/xchains/
|
|
740
|
-
var
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
847
|
+
// src/xchains/icon/iconex/index.tsx
|
|
848
|
+
var ICONEX_RELAY_RESPONSE = "ICONEX_RELAY_RESPONSE";
|
|
849
|
+
var ICONEX_RELAY_REQUEST = "ICONEX_RELAY_REQUEST";
|
|
850
|
+
var request = (event) => {
|
|
851
|
+
return new Promise((resolve, reject) => {
|
|
852
|
+
const handler = (evt) => {
|
|
853
|
+
window.removeEventListener(ICONEX_RELAY_RESPONSE, handler);
|
|
854
|
+
resolve(evt.detail);
|
|
855
|
+
};
|
|
856
|
+
window.addEventListener(ICONEX_RELAY_RESPONSE, handler);
|
|
857
|
+
window.dispatchEvent(
|
|
858
|
+
new CustomEvent(ICONEX_RELAY_REQUEST, {
|
|
859
|
+
detail: event
|
|
860
|
+
})
|
|
861
|
+
);
|
|
862
|
+
});
|
|
863
|
+
};
|
|
864
|
+
|
|
865
|
+
// src/xchains/icon/IconHanaXConnector.ts
|
|
866
|
+
var isHanaWallet = (value) => {
|
|
867
|
+
return isRecord(value) && (value.available === void 0 || hasBooleanProperty(value, "available"));
|
|
868
|
+
};
|
|
869
|
+
var IconHanaXConnector = class extends XConnector {
|
|
870
|
+
constructor() {
|
|
871
|
+
super("ICON", "Hana Wallet", "hana");
|
|
872
|
+
}
|
|
873
|
+
get isInstalled() {
|
|
874
|
+
if (typeof window === "undefined") return false;
|
|
875
|
+
const hanaWallet = window.hanaWallet;
|
|
876
|
+
return isHanaWallet(hanaWallet) && hanaWallet.available === true;
|
|
877
|
+
}
|
|
878
|
+
get installUrl() {
|
|
879
|
+
return WALLET_METADATA.hana.installUrl;
|
|
744
880
|
}
|
|
745
881
|
async connect() {
|
|
746
|
-
|
|
882
|
+
const hanaWallet = window.hanaWallet;
|
|
883
|
+
assert(isHanaWallet(hanaWallet) || hanaWallet === void 0, "[IconHanaXConnector] invalid window.hanaWallet type");
|
|
884
|
+
if (!hanaWallet || !hanaWallet.available) {
|
|
885
|
+
window.open(WALLET_METADATA.hana.installUrl, "_blank", "noopener,noreferrer");
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
const detail = await request({
|
|
889
|
+
type: "REQUEST_ADDRESS" /* REQUEST_ADDRESS */
|
|
890
|
+
});
|
|
891
|
+
if (detail?.type === "RESPONSE_ADDRESS" /* RESPONSE_ADDRESS */) {
|
|
892
|
+
return {
|
|
893
|
+
address: detail?.payload,
|
|
894
|
+
xChainType: this.xChainType
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
console.warn("[IconHanaXConnector] connect: unexpected response from Hana wallet", detail);
|
|
898
|
+
return void 0;
|
|
747
899
|
}
|
|
748
900
|
async disconnect() {
|
|
749
|
-
|
|
750
|
-
}
|
|
751
|
-
get id() {
|
|
752
|
-
return this.connector.id;
|
|
901
|
+
console.log("HanaIconXConnector disconnected");
|
|
753
902
|
}
|
|
754
903
|
get icon() {
|
|
755
|
-
return
|
|
904
|
+
return WALLET_METADATA.hana.icon;
|
|
756
905
|
}
|
|
757
906
|
};
|
|
758
907
|
var InjectiveXService = class _InjectiveXService extends XService {
|
|
759
|
-
|
|
908
|
+
static instance;
|
|
909
|
+
walletStrategy;
|
|
910
|
+
indexerGrpcAccountPortfolioApi;
|
|
911
|
+
chainGrpcWasmApi;
|
|
912
|
+
msgBroadcaster;
|
|
913
|
+
constructor(rpcConfig) {
|
|
760
914
|
super("INJECTIVE");
|
|
761
|
-
const
|
|
915
|
+
const defaults = networks.getNetworkEndpoints(networks.Network.Mainnet);
|
|
916
|
+
const endpoints = {
|
|
917
|
+
...defaults,
|
|
918
|
+
indexer: rpcConfig?.indexer || defaults.indexer,
|
|
919
|
+
grpc: rpcConfig?.grpc || defaults.grpc
|
|
920
|
+
};
|
|
762
921
|
this.walletStrategy = new walletStrategy.WalletStrategy({
|
|
763
922
|
chainId: tsTypes.ChainId.Mainnet,
|
|
764
923
|
strategies: {},
|
|
765
924
|
evmOptions: {
|
|
766
|
-
evmChainId: chains.mainnet.id,
|
|
767
|
-
rpcUrl: chains.mainnet.rpcUrls.default.http[0]
|
|
925
|
+
evmChainId: chains$1.mainnet.id,
|
|
926
|
+
rpcUrl: chains$1.mainnet.rpcUrls.default.http[0]
|
|
768
927
|
}
|
|
769
928
|
});
|
|
770
929
|
this.indexerGrpcAccountPortfolioApi = new sdkTs.IndexerGrpcAccountPortfolioApi(endpoints.indexer);
|
|
@@ -775,9 +934,15 @@ var InjectiveXService = class _InjectiveXService extends XService {
|
|
|
775
934
|
endpoints
|
|
776
935
|
});
|
|
777
936
|
}
|
|
778
|
-
|
|
937
|
+
/**
|
|
938
|
+
* @param rpcConfig - Only applied on first call. Subsequent calls return the
|
|
939
|
+
* existing instance unchanged — gRPC/Indexer clients are built in the
|
|
940
|
+
* constructor and can't be rebuilt at runtime. Pass the desired endpoints
|
|
941
|
+
* via `SodaxWalletProvider.config.rpcConfig` once at app init.
|
|
942
|
+
*/
|
|
943
|
+
static getInstance(rpcConfig) {
|
|
779
944
|
if (!_InjectiveXService.instance) {
|
|
780
|
-
_InjectiveXService.instance = new _InjectiveXService();
|
|
945
|
+
_InjectiveXService.instance = new _InjectiveXService(rpcConfig);
|
|
781
946
|
}
|
|
782
947
|
return _InjectiveXService.instance;
|
|
783
948
|
}
|
|
@@ -802,6 +967,7 @@ var WALLET_ICONS = {
|
|
|
802
967
|
"trust-wallet": "https://trustwallet.com/assets/images/media/assets/twLogo.svg"
|
|
803
968
|
};
|
|
804
969
|
var InjectiveXConnector = class extends XConnector {
|
|
970
|
+
wallet;
|
|
805
971
|
constructor(name, wallet) {
|
|
806
972
|
super("INJECTIVE", name, wallet);
|
|
807
973
|
this.wallet = wallet;
|
|
@@ -811,13 +977,22 @@ var InjectiveXConnector = class extends XConnector {
|
|
|
811
977
|
}
|
|
812
978
|
async connect() {
|
|
813
979
|
if (walletBase.isCosmosBrowserWallet(this.wallet) && !walletCosmos.isCosmosWalletInstalled(this.wallet)) {
|
|
980
|
+
console.warn(`[InjectiveXConnector] connect: ${this.wallet} cosmos wallet not installed`);
|
|
814
981
|
return void 0;
|
|
815
982
|
}
|
|
816
983
|
const walletStrategy = this.getXService().walletStrategy;
|
|
817
984
|
await walletStrategy.setWallet(this.wallet);
|
|
818
985
|
const addresses = await walletStrategy.getAddresses();
|
|
819
|
-
if (!addresses?.length)
|
|
820
|
-
|
|
986
|
+
if (!addresses?.length) {
|
|
987
|
+
console.warn(`[InjectiveXConnector] connect: ${this.wallet} returned no addresses`);
|
|
988
|
+
return void 0;
|
|
989
|
+
}
|
|
990
|
+
const firstAddress = addresses[0];
|
|
991
|
+
if (!firstAddress) {
|
|
992
|
+
console.warn(`[InjectiveXConnector] connect: ${this.wallet} returned empty addresses array`);
|
|
993
|
+
return void 0;
|
|
994
|
+
}
|
|
995
|
+
const address = walletBase.isEvmBrowserWallet(this.wallet) ? sdkTs.getInjectiveAddress(firstAddress) : firstAddress;
|
|
821
996
|
return {
|
|
822
997
|
address,
|
|
823
998
|
xChainType: this.xChainType
|
|
@@ -833,392 +1008,1295 @@ var InjectiveXConnector = class extends XConnector {
|
|
|
833
1008
|
get icon() {
|
|
834
1009
|
return WALLET_ICONS[this.wallet];
|
|
835
1010
|
}
|
|
1011
|
+
get isInstalled() {
|
|
1012
|
+
if (walletBase.isCosmosBrowserWallet(this.wallet)) {
|
|
1013
|
+
return walletCosmos.isCosmosWalletInstalled(this.wallet);
|
|
1014
|
+
}
|
|
1015
|
+
return true;
|
|
1016
|
+
}
|
|
836
1017
|
};
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
1018
|
+
|
|
1019
|
+
// src/xchains/bitcoin/BitcoinXService.ts
|
|
1020
|
+
var BitcoinXService = class _BitcoinXService extends XService {
|
|
1021
|
+
static instance;
|
|
1022
|
+
rpcUrl;
|
|
1023
|
+
constructor(rpcUrl = BITCOIN_DEFAULT_RPC_URL) {
|
|
1024
|
+
super("BITCOIN");
|
|
1025
|
+
this.rpcUrl = rpcUrl;
|
|
840
1026
|
}
|
|
841
|
-
static getInstance() {
|
|
842
|
-
if (!
|
|
843
|
-
|
|
1027
|
+
static getInstance(rpcUrl) {
|
|
1028
|
+
if (!_BitcoinXService.instance) {
|
|
1029
|
+
_BitcoinXService.instance = new _BitcoinXService(rpcUrl);
|
|
1030
|
+
} else if (rpcUrl && rpcUrl !== _BitcoinXService.instance.rpcUrl) {
|
|
1031
|
+
_BitcoinXService.instance.rpcUrl = rpcUrl;
|
|
844
1032
|
}
|
|
845
|
-
return
|
|
1033
|
+
return _BitcoinXService.instance;
|
|
846
1034
|
}
|
|
847
1035
|
async getBalance(address, xToken) {
|
|
848
|
-
if (!address) return
|
|
849
|
-
const connection = this.connection;
|
|
850
|
-
if (!connection) {
|
|
851
|
-
return BigInt(0);
|
|
852
|
-
}
|
|
1036
|
+
if (!address) return 0n;
|
|
853
1037
|
try {
|
|
854
1038
|
if (isNativeToken(xToken)) {
|
|
855
|
-
const
|
|
856
|
-
|
|
1039
|
+
const response = await fetch(`${this.rpcUrl}/address/${address}/utxo`);
|
|
1040
|
+
if (!response.ok) return 0n;
|
|
1041
|
+
const utxos = await response.json();
|
|
1042
|
+
const totalBalance = utxos.reduce((sum, utxo) => sum + utxo.value, 0);
|
|
1043
|
+
return BigInt(totalBalance);
|
|
857
1044
|
}
|
|
858
|
-
const tokenAccountPubkey = splToken.getAssociatedTokenAddressSync(new web3_js.PublicKey(xToken.address), new web3_js.PublicKey(address));
|
|
859
|
-
const tokenAccount = await splToken.getAccount(connection, tokenAccountPubkey);
|
|
860
|
-
return BigInt(tokenAccount.amount);
|
|
861
1045
|
} catch {
|
|
862
|
-
return
|
|
1046
|
+
return 0n;
|
|
863
1047
|
}
|
|
1048
|
+
return 0n;
|
|
864
1049
|
}
|
|
865
1050
|
};
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
1051
|
+
|
|
1052
|
+
// src/xchains/bitcoin/BitcoinXConnector.ts
|
|
1053
|
+
var BitcoinXConnector = class extends XConnector {
|
|
1054
|
+
defaults;
|
|
1055
|
+
constructor(name, id, defaults) {
|
|
1056
|
+
super("BITCOIN", name, id);
|
|
1057
|
+
this.defaults = defaults;
|
|
872
1058
|
}
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
method: "POST",
|
|
876
|
-
headers: {
|
|
877
|
-
"Content-Type": "application/json",
|
|
878
|
-
...this.customHeaders
|
|
879
|
-
},
|
|
880
|
-
body: JSON.stringify({
|
|
881
|
-
id: 1,
|
|
882
|
-
jsonrpc: "2.0",
|
|
883
|
-
method: "simulateTransaction",
|
|
884
|
-
params: {
|
|
885
|
-
transaction: tx.toXDR()
|
|
886
|
-
}
|
|
887
|
-
})
|
|
888
|
-
};
|
|
889
|
-
const response = await fetch(`${this.serverURL}`, requestOptions);
|
|
890
|
-
if (!response.ok) {
|
|
891
|
-
throw new Error(`HTTP error simulating TX! status: ${response.status}`);
|
|
892
|
-
}
|
|
893
|
-
return response.json().then((json) => json.result);
|
|
1059
|
+
getXService() {
|
|
1060
|
+
return BitcoinXService.getInstance();
|
|
894
1061
|
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
id: 1,
|
|
904
|
-
jsonrpc: "2.0",
|
|
905
|
-
method: "sendTransaction",
|
|
906
|
-
params: {
|
|
907
|
-
transaction: tx.toXDR()
|
|
908
|
-
}
|
|
909
|
-
})
|
|
910
|
-
};
|
|
911
|
-
const response = await fetch(`${this.serverURL}`, requestOptions);
|
|
912
|
-
if (!response.ok) {
|
|
913
|
-
throw new Error(`HTTP error submitting TX! status: ${response.status}`);
|
|
914
|
-
}
|
|
915
|
-
return response.json().then((json) => json.result);
|
|
1062
|
+
};
|
|
1063
|
+
var UnisatWalletProvider = class {
|
|
1064
|
+
chainType = "BITCOIN";
|
|
1065
|
+
cachedAddress;
|
|
1066
|
+
defaults;
|
|
1067
|
+
constructor(address, defaults) {
|
|
1068
|
+
this.cachedAddress = address;
|
|
1069
|
+
this.defaults = defaults;
|
|
916
1070
|
}
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
params: { hash }
|
|
929
|
-
})
|
|
930
|
-
};
|
|
931
|
-
const response = await fetch(`${this.serverURL}`, requestOptions);
|
|
932
|
-
if (!response.ok) {
|
|
933
|
-
throw new Error(`HTTP error getting TX! status: ${response.status}`);
|
|
1071
|
+
// Lazy resolve so the provider can be constructed before the extension finishes injecting `window.unisat` (post-refresh rehydrate path).
|
|
1072
|
+
get unisat() {
|
|
1073
|
+
const u = window.unisat;
|
|
1074
|
+
if (!u) throw new Error("Unisat wallet not available");
|
|
1075
|
+
return u;
|
|
1076
|
+
}
|
|
1077
|
+
async getWalletAddress() {
|
|
1078
|
+
try {
|
|
1079
|
+
const accounts = await this.unisat.getAccounts();
|
|
1080
|
+
if (accounts[0]) this.cachedAddress = accounts[0];
|
|
1081
|
+
} catch {
|
|
934
1082
|
}
|
|
935
|
-
return
|
|
1083
|
+
return this.cachedAddress;
|
|
936
1084
|
}
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
var accountToScVal = (account) => new StellarSdk.Address(account).toScVal();
|
|
940
|
-
var simulateTx = async (tx, server) => {
|
|
941
|
-
const response = await server.simulateTransaction(tx);
|
|
942
|
-
if (response !== void 0) {
|
|
943
|
-
return response;
|
|
1085
|
+
async getPublicKey() {
|
|
1086
|
+
return this.unisat.getPublicKey();
|
|
944
1087
|
}
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
const params = [accountToScVal(address)];
|
|
949
|
-
const contract = new StellarSdk.Contract(tokenId);
|
|
950
|
-
const tx = txBuilder.addOperation(contract.call("balance", ...params)).setTimeout(StellarSdk.TimeoutInfinite).build();
|
|
951
|
-
const result = await simulateTx(tx, server);
|
|
952
|
-
return result.results ? StellarSdk.scValToBigInt(StellarSdk.xdr.ScVal.fromXDR(result.results[0].xdr, "base64")) : 0n;
|
|
953
|
-
};
|
|
954
|
-
|
|
955
|
-
// src/xchains/stellar/StellarXService.ts
|
|
956
|
-
var STELLAR_BASE_RESERVE_STROOPS = 5e6;
|
|
957
|
-
function parseXlmBalanceToStroops(balanceStr) {
|
|
958
|
-
const parts = balanceStr.split(".");
|
|
959
|
-
const whole = parts[0] ?? "0";
|
|
960
|
-
const frac = (parts[1] ?? "").padEnd(7, "0").slice(0, 7);
|
|
961
|
-
return BigInt(whole + frac);
|
|
962
|
-
}
|
|
963
|
-
var StellarXService = class _StellarXService extends XService {
|
|
964
|
-
constructor() {
|
|
965
|
-
super("STELLAR");
|
|
966
|
-
this.walletsKit = new stellarWalletsKit.StellarWalletsKit({
|
|
967
|
-
network: stellarWalletsKit.WalletNetwork.PUBLIC,
|
|
968
|
-
modules: stellarWalletsKit.allowAllModules()
|
|
969
|
-
});
|
|
970
|
-
this.server = new StellarSdk__namespace.Horizon.Server("https://horizon.stellar.org", { allowHttp: true });
|
|
971
|
-
this.sorobanServer = new CustomSorobanServer_default("https://rpc.ankr.com/stellar_soroban", {});
|
|
1088
|
+
async getAddressType(_address) {
|
|
1089
|
+
const address = await this.getWalletAddress();
|
|
1090
|
+
return types.detectBitcoinAddressType(address);
|
|
972
1091
|
}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
}
|
|
977
|
-
return
|
|
1092
|
+
async signTransaction(psbtBase64, finalize) {
|
|
1093
|
+
const effectiveFinalize = finalize ?? this.defaults?.defaultFinalize ?? false;
|
|
1094
|
+
const psbtHex = Buffer.from(psbtBase64, "base64").toString("hex");
|
|
1095
|
+
const signedHex = await this.unisat.signPsbt(psbtHex, { autoFinalized: effectiveFinalize });
|
|
1096
|
+
return signedHex;
|
|
978
1097
|
}
|
|
979
|
-
async
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
const subentryCount = reserveFields.subentry_count ?? 0;
|
|
989
|
-
const numSponsoring = reserveFields.num_sponsoring ?? 0;
|
|
990
|
-
const numSponsored = reserveFields.num_sponsored ?? 0;
|
|
991
|
-
const reserveCount = Math.max(0, 2 + subentryCount + numSponsoring - numSponsored);
|
|
992
|
-
const minBalanceStroops = BigInt(reserveCount) * BigInt(STELLAR_BASE_RESERVE_STROOPS) + sellingLiabilitiesStroops;
|
|
993
|
-
const availableStroops = rawBalanceStroops > minBalanceStroops ? rawBalanceStroops - minBalanceStroops : BigInt(0);
|
|
994
|
-
return availableStroops;
|
|
995
|
-
}
|
|
996
|
-
} else {
|
|
997
|
-
try {
|
|
998
|
-
const txBuilder = new StellarSdk__namespace.TransactionBuilder(stellarAccount, {
|
|
999
|
-
fee: StellarSdk__namespace.BASE_FEE,
|
|
1000
|
-
networkPassphrase: StellarSdk__namespace.Networks.PUBLIC
|
|
1001
|
-
});
|
|
1002
|
-
const balance = await getTokenBalance(address, xToken.address, txBuilder, this.sorobanServer);
|
|
1003
|
-
return balance;
|
|
1004
|
-
} catch (e) {
|
|
1005
|
-
console.error(`Error while fetching token on Stellar: ${xToken.symbol}, Error: ${e}`);
|
|
1006
|
-
}
|
|
1098
|
+
async signEcdsaMessage(message) {
|
|
1099
|
+
return this.unisat.signMessage(message, "ecdsa");
|
|
1100
|
+
}
|
|
1101
|
+
async signBip322Message(message) {
|
|
1102
|
+
return this.unisat.signMessage(message, "bip322-simple");
|
|
1103
|
+
}
|
|
1104
|
+
async sendBitcoin(toAddress, satoshis) {
|
|
1105
|
+
if (satoshis > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
1106
|
+
throw new Error(`Amount ${satoshis} satoshis exceeds safe integer range`);
|
|
1007
1107
|
}
|
|
1008
|
-
return
|
|
1108
|
+
return this.unisat.sendBitcoin(toAddress, Number(satoshis));
|
|
1009
1109
|
}
|
|
1010
1110
|
};
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
super("STELLAR", wallet.name, wallet.id);
|
|
1016
|
-
this._wallet = wallet;
|
|
1111
|
+
var UnisatXConnector = class _UnisatXConnector extends BitcoinXConnector {
|
|
1112
|
+
walletProvider;
|
|
1113
|
+
constructor(defaults) {
|
|
1114
|
+
super("Unisat", "unisat", defaults);
|
|
1017
1115
|
}
|
|
1018
|
-
|
|
1019
|
-
return
|
|
1116
|
+
static isAvailable() {
|
|
1117
|
+
return typeof window !== "undefined" && !!window.unisat;
|
|
1118
|
+
}
|
|
1119
|
+
get isInstalled() {
|
|
1120
|
+
return _UnisatXConnector.isAvailable();
|
|
1121
|
+
}
|
|
1122
|
+
get installUrl() {
|
|
1123
|
+
return WALLET_METADATA.unisat.installUrl;
|
|
1124
|
+
}
|
|
1125
|
+
get icon() {
|
|
1126
|
+
return WALLET_METADATA.unisat.icon;
|
|
1020
1127
|
}
|
|
1021
1128
|
async connect() {
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
return;
|
|
1129
|
+
if (!window.unisat) {
|
|
1130
|
+
throw new Error("Unisat wallet is not installed");
|
|
1025
1131
|
}
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1132
|
+
const accounts = await window.unisat.requestAccounts();
|
|
1133
|
+
const address = accounts[0];
|
|
1134
|
+
if (!address) {
|
|
1135
|
+
console.warn("[UnisatXConnector] connect: requestAccounts returned no address");
|
|
1136
|
+
return void 0;
|
|
1029
1137
|
}
|
|
1030
|
-
|
|
1031
|
-
const { address } = await kit.getAddress();
|
|
1138
|
+
this.walletProvider = new UnisatWalletProvider(address, this.defaults);
|
|
1032
1139
|
return {
|
|
1033
1140
|
address,
|
|
1034
|
-
xChainType:
|
|
1141
|
+
xChainType: "BITCOIN"
|
|
1035
1142
|
};
|
|
1036
1143
|
}
|
|
1037
1144
|
async disconnect() {
|
|
1145
|
+
this.walletProvider = void 0;
|
|
1038
1146
|
}
|
|
1039
|
-
|
|
1040
|
-
return this.
|
|
1147
|
+
getWalletProvider() {
|
|
1148
|
+
return this.walletProvider;
|
|
1149
|
+
}
|
|
1150
|
+
recreateWalletProvider(xAccount) {
|
|
1151
|
+
if (!xAccount.address) return void 0;
|
|
1152
|
+
return new UnisatWalletProvider(xAccount.address, this.defaults);
|
|
1041
1153
|
}
|
|
1042
1154
|
};
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1155
|
+
var XverseWalletProvider = class {
|
|
1156
|
+
chainType = "BITCOIN";
|
|
1157
|
+
address;
|
|
1158
|
+
publicKey;
|
|
1159
|
+
defaults;
|
|
1160
|
+
constructor(address, publicKey, defaults) {
|
|
1161
|
+
this.address = address;
|
|
1162
|
+
this.publicKey = publicKey;
|
|
1163
|
+
this.defaults = defaults;
|
|
1049
1164
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1165
|
+
async getWalletAddress() {
|
|
1166
|
+
return this.address;
|
|
1167
|
+
}
|
|
1168
|
+
async getPublicKey() {
|
|
1169
|
+
return this.publicKey;
|
|
1170
|
+
}
|
|
1171
|
+
async getAddressType(_address) {
|
|
1172
|
+
return types.detectBitcoinAddressType(this.address);
|
|
1173
|
+
}
|
|
1174
|
+
/**
|
|
1175
|
+
* Parse a base64-encoded PSBT to count the number of inputs.
|
|
1176
|
+
* Reads the unsigned transaction from the PSBT global section.
|
|
1177
|
+
*/
|
|
1178
|
+
countPsbtInputs(psbtBase64) {
|
|
1179
|
+
const data = Buffer.from(psbtBase64, "base64");
|
|
1180
|
+
let offset = 5;
|
|
1181
|
+
const keyLen = data[offset++] ?? 0;
|
|
1182
|
+
if (keyLen !== 1 || data[offset++] !== 0) {
|
|
1183
|
+
return 1;
|
|
1053
1184
|
}
|
|
1054
|
-
|
|
1185
|
+
const firstByte = data[offset++] ?? 0;
|
|
1186
|
+
if (firstByte === 253) offset += 2;
|
|
1187
|
+
else if (firstByte === 254) offset += 4;
|
|
1188
|
+
else if (firstByte === 255) offset += 8;
|
|
1189
|
+
offset += 4;
|
|
1190
|
+
const inputByte = data[offset] ?? 0;
|
|
1191
|
+
if (inputByte < 253) return inputByte;
|
|
1192
|
+
return 1;
|
|
1055
1193
|
}
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1194
|
+
async signTransaction(psbtBase64, finalize) {
|
|
1195
|
+
const effectiveFinalize = finalize ?? this.defaults?.defaultFinalize ?? false;
|
|
1196
|
+
const { request: request3 } = await import('sats-connect');
|
|
1197
|
+
const inputCount = this.countPsbtInputs(psbtBase64);
|
|
1198
|
+
const signingIndexes = Array.from({ length: inputCount }, (_, i) => i);
|
|
1199
|
+
const response = await request3("signPsbt", {
|
|
1200
|
+
psbt: psbtBase64,
|
|
1201
|
+
broadcast: false,
|
|
1202
|
+
signInputs: {
|
|
1203
|
+
[this.address]: signingIndexes
|
|
1204
|
+
}
|
|
1205
|
+
});
|
|
1206
|
+
if (response.status === "error") {
|
|
1207
|
+
throw new Error(response.error?.message || "Xverse PSBT signing failed");
|
|
1208
|
+
}
|
|
1209
|
+
const result = response.result;
|
|
1210
|
+
if (effectiveFinalize) {
|
|
1211
|
+
return Buffer.from(result.psbt, "base64").toString("hex");
|
|
1212
|
+
}
|
|
1213
|
+
return result.psbt;
|
|
1214
|
+
}
|
|
1215
|
+
async signEcdsaMessage(message) {
|
|
1216
|
+
const { request: request3 } = await import('sats-connect');
|
|
1217
|
+
const response = await request3("signMessage", {
|
|
1218
|
+
address: this.address,
|
|
1219
|
+
message,
|
|
1220
|
+
protocol: satsConnect.MessageSigningProtocols.ECDSA
|
|
1221
|
+
});
|
|
1222
|
+
if (response.status === "error") {
|
|
1223
|
+
throw new Error(response.error?.message || "Xverse ECDSA signing failed");
|
|
1224
|
+
}
|
|
1225
|
+
return response.result.signature;
|
|
1226
|
+
}
|
|
1227
|
+
async signBip322Message(message) {
|
|
1228
|
+
const { request: request3 } = await import('sats-connect');
|
|
1229
|
+
const response = await request3("signMessage", {
|
|
1230
|
+
address: this.address,
|
|
1231
|
+
message,
|
|
1232
|
+
protocol: satsConnect.MessageSigningProtocols.BIP322
|
|
1233
|
+
});
|
|
1234
|
+
if (response.status === "error") {
|
|
1235
|
+
throw new Error(response.error?.message || "Xverse BIP322 signing failed");
|
|
1236
|
+
}
|
|
1237
|
+
return response.result.signature;
|
|
1238
|
+
}
|
|
1239
|
+
async sendBitcoin(toAddress, satoshis) {
|
|
1240
|
+
const { request: request3 } = await import('sats-connect');
|
|
1241
|
+
const response = await request3("sendTransfer", {
|
|
1242
|
+
recipients: [
|
|
1243
|
+
{
|
|
1244
|
+
address: toAddress,
|
|
1245
|
+
amount: Number(satoshis)
|
|
1079
1246
|
}
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
return {};
|
|
1247
|
+
]
|
|
1248
|
+
});
|
|
1249
|
+
if (response.status === "error") {
|
|
1250
|
+
throw new Error(response.error?.message || "Xverse sendTransfer failed");
|
|
1085
1251
|
}
|
|
1252
|
+
return response.result.txid;
|
|
1086
1253
|
}
|
|
1087
1254
|
};
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1255
|
+
var XVERSE_ADDRESS_TYPE_KEY = "xverse-address-type";
|
|
1256
|
+
var XverseXConnector = class _XverseXConnector extends BitcoinXConnector {
|
|
1257
|
+
walletProvider;
|
|
1258
|
+
/** Address purpose used when connecting. Taproot (Ordinals) by default to match Radfi. */
|
|
1259
|
+
addressPurpose;
|
|
1260
|
+
constructor(defaults) {
|
|
1261
|
+
super("Xverse", "xverse", defaults);
|
|
1262
|
+
const saved = typeof window !== "undefined" ? localStorage.getItem(XVERSE_ADDRESS_TYPE_KEY) : null;
|
|
1263
|
+
this.addressPurpose = saved === "segwit" ? satsConnect.AddressPurpose.Payment : satsConnect.AddressPurpose.Ordinals;
|
|
1094
1264
|
}
|
|
1095
|
-
|
|
1096
|
-
|
|
1265
|
+
/** Set address purpose and persist to localStorage. */
|
|
1266
|
+
setAddressPurpose(type) {
|
|
1267
|
+
this.addressPurpose = type === "taproot" ? satsConnect.AddressPurpose.Ordinals : satsConnect.AddressPurpose.Payment;
|
|
1268
|
+
if (typeof window !== "undefined") {
|
|
1269
|
+
localStorage.setItem(XVERSE_ADDRESS_TYPE_KEY, type);
|
|
1270
|
+
}
|
|
1097
1271
|
}
|
|
1098
|
-
|
|
1099
|
-
return;
|
|
1272
|
+
static isAvailable() {
|
|
1273
|
+
return typeof window !== "undefined" && !!window.BitcoinProvider;
|
|
1100
1274
|
}
|
|
1101
|
-
|
|
1275
|
+
get isInstalled() {
|
|
1276
|
+
return _XverseXConnector.isAvailable();
|
|
1102
1277
|
}
|
|
1103
|
-
get
|
|
1104
|
-
return
|
|
1278
|
+
get installUrl() {
|
|
1279
|
+
return WALLET_METADATA.xverse.installUrl;
|
|
1105
1280
|
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
var { IconService: IconServiceConstructor, Builder: IconBuilder, Converter: IconConverter } = IconSdk;
|
|
1109
|
-
var CHAIN_INFO = {
|
|
1110
|
-
[1 /* MAINNET */]: {
|
|
1111
|
-
APIEndpoint: "https://ctz.solidwallet.io/api/v3"}
|
|
1112
|
-
};
|
|
1113
|
-
var IconXService = class _IconXService extends XService {
|
|
1114
|
-
constructor() {
|
|
1115
|
-
super("ICON");
|
|
1116
|
-
this.iconService = new IconServiceConstructor(
|
|
1117
|
-
new IconServiceConstructor.HttpProvider(CHAIN_INFO[1 /* MAINNET */].APIEndpoint)
|
|
1118
|
-
);
|
|
1281
|
+
get icon() {
|
|
1282
|
+
return WALLET_METADATA.xverse.icon;
|
|
1119
1283
|
}
|
|
1120
|
-
|
|
1121
|
-
if (!
|
|
1122
|
-
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1284
|
+
async connect() {
|
|
1285
|
+
if (!_XverseXConnector.isAvailable()) {
|
|
1286
|
+
throw new Error("Xverse wallet is not installed");
|
|
1287
|
+
}
|
|
1288
|
+
const { request: request3 } = await import('sats-connect');
|
|
1289
|
+
const response = await request3("getAccounts", {
|
|
1290
|
+
purposes: [this.addressPurpose],
|
|
1291
|
+
message: "Connect to Sodax"
|
|
1292
|
+
});
|
|
1293
|
+
if (response.status === "error") {
|
|
1294
|
+
throw new Error(response.error?.message || "Xverse connection failed");
|
|
1295
|
+
}
|
|
1296
|
+
const accounts = response.result;
|
|
1297
|
+
const paymentAccount = accounts.find((a) => a.purpose === this.addressPurpose) || accounts[0];
|
|
1298
|
+
if (!paymentAccount) return void 0;
|
|
1299
|
+
this.walletProvider = new XverseWalletProvider(
|
|
1300
|
+
paymentAccount.address,
|
|
1301
|
+
paymentAccount.publicKey,
|
|
1302
|
+
this.defaults
|
|
1303
|
+
);
|
|
1304
|
+
return {
|
|
1305
|
+
address: paymentAccount.address,
|
|
1306
|
+
publicKey: paymentAccount.publicKey,
|
|
1307
|
+
xChainType: "BITCOIN"
|
|
1308
|
+
};
|
|
1125
1309
|
}
|
|
1126
|
-
async
|
|
1127
|
-
|
|
1310
|
+
async disconnect() {
|
|
1311
|
+
this.walletProvider = void 0;
|
|
1312
|
+
}
|
|
1313
|
+
getWalletProvider() {
|
|
1314
|
+
return this.walletProvider;
|
|
1315
|
+
}
|
|
1316
|
+
recreateWalletProvider(xAccount) {
|
|
1317
|
+
if (!xAccount.address || !xAccount.publicKey) return void 0;
|
|
1318
|
+
return new XverseWalletProvider(xAccount.address, xAccount.publicKey, this.defaults);
|
|
1319
|
+
}
|
|
1320
|
+
};
|
|
1321
|
+
var OKXWalletProvider = class {
|
|
1322
|
+
chainType = "BITCOIN";
|
|
1323
|
+
cachedAddress;
|
|
1324
|
+
defaults;
|
|
1325
|
+
constructor(address, defaults) {
|
|
1326
|
+
this.cachedAddress = address;
|
|
1327
|
+
this.defaults = defaults;
|
|
1328
|
+
}
|
|
1329
|
+
// Lazy resolve so the provider can be constructed before the extension finishes injecting `window.okxwallet` (post-refresh rehydrate path).
|
|
1330
|
+
get okx() {
|
|
1331
|
+
const o = window.okxwallet?.bitcoin;
|
|
1332
|
+
if (!o) throw new Error("OKX wallet not available");
|
|
1333
|
+
return o;
|
|
1334
|
+
}
|
|
1335
|
+
async getWalletAddress() {
|
|
1128
1336
|
try {
|
|
1129
|
-
const
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1337
|
+
const accounts = await this.okx.getAccounts();
|
|
1338
|
+
if (accounts[0]) this.cachedAddress = accounts[0];
|
|
1339
|
+
} catch {
|
|
1340
|
+
}
|
|
1341
|
+
return this.cachedAddress;
|
|
1342
|
+
}
|
|
1343
|
+
async getPublicKey() {
|
|
1344
|
+
return this.okx.getPublicKey();
|
|
1345
|
+
}
|
|
1346
|
+
async getAddressType(_address) {
|
|
1347
|
+
const address = await this.getWalletAddress();
|
|
1348
|
+
return types.detectBitcoinAddressType(address);
|
|
1349
|
+
}
|
|
1350
|
+
async signTransaction(psbtBase64, finalize) {
|
|
1351
|
+
const effectiveFinalize = finalize ?? this.defaults?.defaultFinalize ?? false;
|
|
1352
|
+
const psbtHex = Buffer.from(psbtBase64, "base64").toString("hex");
|
|
1353
|
+
return this.okx.signPsbt(psbtHex, { autoFinalized: effectiveFinalize });
|
|
1354
|
+
}
|
|
1355
|
+
async signEcdsaMessage(message) {
|
|
1356
|
+
return this.okx.signMessage(message, "ecdsa");
|
|
1357
|
+
}
|
|
1358
|
+
async signBip322Message(message) {
|
|
1359
|
+
return this.okx.signMessage(message, "bip322-simple");
|
|
1360
|
+
}
|
|
1361
|
+
async sendBitcoin(toAddress, satoshis) {
|
|
1362
|
+
if (satoshis > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
1363
|
+
throw new Error(`Amount ${satoshis} satoshis exceeds safe integer range`);
|
|
1364
|
+
}
|
|
1365
|
+
return this.okx.sendBitcoin(toAddress, Number(satoshis));
|
|
1366
|
+
}
|
|
1367
|
+
};
|
|
1368
|
+
var OKXXConnector = class _OKXXConnector extends BitcoinXConnector {
|
|
1369
|
+
walletProvider;
|
|
1370
|
+
constructor(defaults) {
|
|
1371
|
+
super("OKX Wallet", "okx-bitcoin", defaults);
|
|
1372
|
+
}
|
|
1373
|
+
static isAvailable() {
|
|
1374
|
+
return typeof window !== "undefined" && !!window.okxwallet?.bitcoin;
|
|
1375
|
+
}
|
|
1376
|
+
get isInstalled() {
|
|
1377
|
+
return _OKXXConnector.isAvailable();
|
|
1378
|
+
}
|
|
1379
|
+
get installUrl() {
|
|
1380
|
+
return WALLET_METADATA.okx.installUrl;
|
|
1381
|
+
}
|
|
1382
|
+
get icon() {
|
|
1383
|
+
return WALLET_METADATA.okx.icon;
|
|
1384
|
+
}
|
|
1385
|
+
async connect() {
|
|
1386
|
+
const okx = window.okxwallet?.bitcoin;
|
|
1387
|
+
if (!okx) {
|
|
1388
|
+
throw new Error("OKX wallet is not installed");
|
|
1389
|
+
}
|
|
1390
|
+
const { address } = await okx.connect();
|
|
1391
|
+
if (!address) {
|
|
1392
|
+
console.warn("[OKXXConnector] connect: okx.connect() returned no address");
|
|
1393
|
+
return void 0;
|
|
1394
|
+
}
|
|
1395
|
+
this.walletProvider = new OKXWalletProvider(address, this.defaults);
|
|
1396
|
+
return {
|
|
1397
|
+
address,
|
|
1398
|
+
xChainType: "BITCOIN"
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1401
|
+
async disconnect() {
|
|
1402
|
+
this.walletProvider = void 0;
|
|
1403
|
+
}
|
|
1404
|
+
getWalletProvider() {
|
|
1405
|
+
return this.walletProvider;
|
|
1406
|
+
}
|
|
1407
|
+
recreateWalletProvider(xAccount) {
|
|
1408
|
+
if (!xAccount.address) return void 0;
|
|
1409
|
+
return new OKXWalletProvider(xAccount.address, this.defaults);
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
|
|
1413
|
+
// src/hooks/useXConnection.ts
|
|
1414
|
+
function useXConnection({ xChainType } = {}) {
|
|
1415
|
+
return useXWalletStore((state) => xChainType ? state.xConnections?.[xChainType] : void 0);
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
// src/hooks/useXAccount.ts
|
|
1419
|
+
function useXAccount({ xChainId, xChainType }) {
|
|
1420
|
+
assert(!(xChainId && xChainType), "[useXAccount] pass either xChainId or xChainType, not both");
|
|
1421
|
+
assert(xChainId || xChainType, "[useXAccount] pass xChainId or xChainType");
|
|
1422
|
+
const target = xChainType ?? getXChainType(xChainId);
|
|
1423
|
+
const xConnection = useXConnection({ xChainType: target });
|
|
1424
|
+
return react.useMemo(
|
|
1425
|
+
() => xConnection?.xAccount ?? { address: void 0, xChainType: target },
|
|
1426
|
+
[target, xConnection]
|
|
1427
|
+
);
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
// src/hooks/useEnabledChains.ts
|
|
1431
|
+
function useEnabledChains() {
|
|
1432
|
+
return useXWalletStore((state) => state.enabledChains);
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
// src/hooks/useXConnections.ts
|
|
1436
|
+
function useXConnections() {
|
|
1437
|
+
return useXWalletStore((state) => state.xConnections);
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
// src/hooks/useXAccounts.ts
|
|
1441
|
+
function useXAccounts() {
|
|
1442
|
+
const enabledChains = useEnabledChains();
|
|
1443
|
+
const xConnections = useXConnections();
|
|
1444
|
+
return react.useMemo(() => {
|
|
1445
|
+
const result = {};
|
|
1446
|
+
for (const xChainType of enabledChains) {
|
|
1447
|
+
const xConnection = xConnections[xChainType];
|
|
1448
|
+
result[xChainType] = xConnection?.xAccount ?? { address: void 0, xChainType };
|
|
1449
|
+
}
|
|
1450
|
+
return result;
|
|
1451
|
+
}, [enabledChains, xConnections]);
|
|
1452
|
+
}
|
|
1453
|
+
function useXConnect() {
|
|
1454
|
+
const setXConnection = useXWalletStore((state) => state.setXConnection);
|
|
1455
|
+
const actionsRegistry = useXWalletStore((state) => state.chainActions);
|
|
1456
|
+
return reactQuery.useMutation({
|
|
1457
|
+
mutationFn: async (xConnector) => {
|
|
1458
|
+
const chainActions = actionsRegistry[xConnector.xChainType];
|
|
1459
|
+
if (!chainActions) {
|
|
1460
|
+
throw new Error(`Chain "${xConnector.xChainType}" is not enabled or ChainActions not registered`);
|
|
1461
|
+
}
|
|
1462
|
+
const xAccount = await chainActions.connect(xConnector.id);
|
|
1463
|
+
if (xAccount) {
|
|
1464
|
+
setXConnection(xConnector.xChainType, {
|
|
1465
|
+
xAccount,
|
|
1466
|
+
xConnectorId: xConnector.id
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
return xAccount;
|
|
1470
|
+
}
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
// src/hooks/useXConnectors.ts
|
|
1475
|
+
var warnedChains = /* @__PURE__ */ new Set();
|
|
1476
|
+
function useXConnectors({ xChainType } = {}) {
|
|
1477
|
+
return useXWalletStore((state) => {
|
|
1478
|
+
if (!xChainType) return [];
|
|
1479
|
+
if (!state.enabledChains.includes(xChainType) && !warnedChains.has(xChainType)) {
|
|
1480
|
+
warnedChains.add(xChainType);
|
|
1481
|
+
console.warn(
|
|
1482
|
+
`[useXConnectors] chain "${xChainType}" is not enabled in SodaxWalletProvider config.chains \u2014 returning empty list`
|
|
1483
|
+
);
|
|
1484
|
+
}
|
|
1485
|
+
return state.xConnectorsByChain[xChainType] ?? [];
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
// src/hooks/useXConnectorsByChain.ts
|
|
1490
|
+
function useXConnectorsByChain() {
|
|
1491
|
+
return useXWalletStore((state) => state.xConnectorsByChain);
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
// src/utils/matchConnectorIdentifier.ts
|
|
1495
|
+
var SHORT_IDENTIFIER_THRESHOLD = 3;
|
|
1496
|
+
var warnedShortIdentifiers = /* @__PURE__ */ new Set();
|
|
1497
|
+
function matchesConnectorIdentifier(connector, identifier) {
|
|
1498
|
+
const needle = identifier.toLowerCase();
|
|
1499
|
+
if (needle.length > 0 && needle.length < SHORT_IDENTIFIER_THRESHOLD && !warnedShortIdentifiers.has(needle)) {
|
|
1500
|
+
warnedShortIdentifiers.add(needle);
|
|
1501
|
+
console.warn(
|
|
1502
|
+
`[matchesConnectorIdentifier] identifier "${identifier}" is ${needle.length} chars \u2014 substring matching on short strings frequently hits unintended connectors. Use a more distinctive wallet brand name, or match a single connector via useXConnectors(chainType).find(c => c.id === '...') directly.`
|
|
1503
|
+
);
|
|
1504
|
+
}
|
|
1505
|
+
return connector.id.toLowerCase().includes(needle) || connector.name.toLowerCase().includes(needle);
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
// src/hooks/useIsWalletInstalled.ts
|
|
1509
|
+
function useIsWalletInstalled(options) {
|
|
1510
|
+
const xConnectorsByChain = useXWalletStore((s) => s.xConnectorsByChain);
|
|
1511
|
+
return isAnyConnectorInstalled(options, xConnectorsByChain);
|
|
1512
|
+
}
|
|
1513
|
+
function isAnyConnectorInstalled(options, xConnectorsByChain) {
|
|
1514
|
+
const { connectors: identifiers, chainType } = options;
|
|
1515
|
+
if (identifiers === void 0 && chainType === void 0) {
|
|
1516
|
+
console.warn(
|
|
1517
|
+
"[useIsWalletInstalled] called without `connectors` or `chainType` \u2014 returning `false`. Supply at least one filter."
|
|
1518
|
+
);
|
|
1519
|
+
return false;
|
|
1520
|
+
}
|
|
1521
|
+
if (identifiers && identifiers.length === 0) return false;
|
|
1522
|
+
const chainsToScan = chainType ? [xConnectorsByChain[chainType]] : Object.values(xConnectorsByChain);
|
|
1523
|
+
for (const chainConnectors of chainsToScan) {
|
|
1524
|
+
if (!chainConnectors) continue;
|
|
1525
|
+
for (const connector of chainConnectors) {
|
|
1526
|
+
if (!connector.isInstalled) continue;
|
|
1527
|
+
if (!identifiers) return true;
|
|
1528
|
+
if (identifiers.some((id) => matchesConnectorIdentifier(connector, id))) return true;
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
return false;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
// src/utils/chainOrder.ts
|
|
1535
|
+
function compareChainByOrder(a, b, order) {
|
|
1536
|
+
const ia = order.indexOf(a);
|
|
1537
|
+
const ib = order.indexOf(b);
|
|
1538
|
+
if (ia === -1 && ib === -1) return a.localeCompare(b);
|
|
1539
|
+
if (ia === -1) return 1;
|
|
1540
|
+
if (ib === -1) return -1;
|
|
1541
|
+
return ia - ib;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
// src/hooks/useChainGroups.ts
|
|
1545
|
+
function getSpokeChainKeysByType(chainType) {
|
|
1546
|
+
const ids = [];
|
|
1547
|
+
for (const chainKey of types.CHAIN_KEYS) {
|
|
1548
|
+
if (types.baseChainInfo[chainKey].type === chainType) ids.push(chainKey);
|
|
1549
|
+
}
|
|
1550
|
+
return ids;
|
|
1551
|
+
}
|
|
1552
|
+
function buildChainGroups(enabledChains, xConnections, registry = chainRegistry, order) {
|
|
1553
|
+
const chains = order ? [...enabledChains].sort((a, b) => compareChainByOrder(a, b, order)) : enabledChains;
|
|
1554
|
+
return chains.map((chainType) => {
|
|
1555
|
+
const factory = registry[chainType];
|
|
1556
|
+
const connection = xConnections[chainType];
|
|
1557
|
+
return {
|
|
1558
|
+
chainType,
|
|
1559
|
+
chainIds: getSpokeChainKeysByType(chainType),
|
|
1560
|
+
displayName: factory?.displayName ?? chainType,
|
|
1561
|
+
iconUrl: factory?.iconUrl,
|
|
1562
|
+
isConnected: !!connection?.xAccount.address,
|
|
1563
|
+
account: connection?.xAccount,
|
|
1564
|
+
connectorId: connection?.xConnectorId
|
|
1565
|
+
};
|
|
1566
|
+
});
|
|
1567
|
+
}
|
|
1568
|
+
function useChainGroups({ order } = {}) {
|
|
1569
|
+
const enabledChains = useEnabledChains();
|
|
1570
|
+
const xConnections = useXConnections();
|
|
1571
|
+
return react.useMemo(
|
|
1572
|
+
() => buildChainGroups(enabledChains, xConnections, chainRegistry, order),
|
|
1573
|
+
[enabledChains, xConnections, order]
|
|
1574
|
+
);
|
|
1575
|
+
}
|
|
1576
|
+
function buildConnectedChains(xConnections, xConnectorsByChain, isReady = true, order) {
|
|
1577
|
+
const chains = [];
|
|
1578
|
+
for (const chainType of types.ChainTypeArr) {
|
|
1579
|
+
const connection = xConnections[chainType];
|
|
1580
|
+
if (!connection?.xAccount.address) continue;
|
|
1581
|
+
const connectors = xConnectorsByChain[chainType] ?? [];
|
|
1582
|
+
const connector = connectors.find((c) => c.id === connection.xConnectorId);
|
|
1583
|
+
chains.push({
|
|
1584
|
+
chainType,
|
|
1585
|
+
account: connection.xAccount,
|
|
1586
|
+
connectorId: connection.xConnectorId,
|
|
1587
|
+
connectorName: connector?.name,
|
|
1588
|
+
connectorIcon: connector?.icon
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
if (order) {
|
|
1592
|
+
chains.sort((a, b) => compareChainByOrder(a.chainType, b.chainType, order));
|
|
1593
|
+
}
|
|
1594
|
+
return {
|
|
1595
|
+
chains,
|
|
1596
|
+
total: chains.length,
|
|
1597
|
+
status: isReady ? "ready" : "loading"
|
|
1598
|
+
};
|
|
1599
|
+
}
|
|
1600
|
+
function subscribeHydration(onChange) {
|
|
1601
|
+
const unsubHydrate = useXWalletStore.persist.onHydrate(onChange);
|
|
1602
|
+
const unsubFinish = useXWalletStore.persist.onFinishHydration(onChange);
|
|
1603
|
+
return () => {
|
|
1604
|
+
unsubHydrate();
|
|
1605
|
+
unsubFinish();
|
|
1606
|
+
};
|
|
1607
|
+
}
|
|
1608
|
+
function useConnectedChains({ order } = {}) {
|
|
1609
|
+
const xConnections = useXConnections();
|
|
1610
|
+
const xConnectorsByChain = useXConnectorsByChain();
|
|
1611
|
+
const isReady = react.useSyncExternalStore(
|
|
1612
|
+
subscribeHydration,
|
|
1613
|
+
() => useXWalletStore.persist.hasHydrated(),
|
|
1614
|
+
() => false
|
|
1615
|
+
);
|
|
1616
|
+
return react.useMemo(
|
|
1617
|
+
() => buildConnectedChains(xConnections, xConnectorsByChain, isReady, order),
|
|
1618
|
+
[xConnections, xConnectorsByChain, isReady, order]
|
|
1619
|
+
);
|
|
1620
|
+
}
|
|
1621
|
+
function useXDisconnect() {
|
|
1622
|
+
const actionsRegistry = useXWalletStore((state) => state.chainActions);
|
|
1623
|
+
return react.useCallback(
|
|
1624
|
+
async ({ xChainType }) => {
|
|
1625
|
+
const chainActions = actionsRegistry[xChainType];
|
|
1626
|
+
if (chainActions) {
|
|
1627
|
+
await chainActions.disconnect();
|
|
1628
|
+
} else {
|
|
1629
|
+
console.warn(
|
|
1630
|
+
`[useXDisconnect] No chain actions registered for "${xChainType}". Is it enabled in config.chains?`
|
|
1631
|
+
);
|
|
1632
|
+
}
|
|
1633
|
+
},
|
|
1634
|
+
[actionsRegistry]
|
|
1635
|
+
);
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
// src/hooks/useConnectionFlow.ts
|
|
1639
|
+
function useConnectionFlow() {
|
|
1640
|
+
const mutation = useXConnect();
|
|
1641
|
+
const disconnect2 = useXDisconnect();
|
|
1642
|
+
const [error, setError] = react.useState(null);
|
|
1643
|
+
const [activeConnector, setActiveConnector] = react.useState(null);
|
|
1644
|
+
const lastConnectorRef = react.useRef(null);
|
|
1645
|
+
const connect = react.useCallback(
|
|
1646
|
+
async (connector) => {
|
|
1647
|
+
lastConnectorRef.current = connector;
|
|
1648
|
+
setActiveConnector(connector);
|
|
1649
|
+
setError(null);
|
|
1650
|
+
try {
|
|
1651
|
+
return await mutation.mutateAsync(connector);
|
|
1652
|
+
} catch (raw) {
|
|
1653
|
+
setError(raw instanceof Error ? raw : new Error(String(raw)));
|
|
1654
|
+
return void 0;
|
|
1655
|
+
}
|
|
1656
|
+
},
|
|
1657
|
+
[mutation]
|
|
1658
|
+
);
|
|
1659
|
+
const retry = react.useCallback(async () => {
|
|
1660
|
+
const last = lastConnectorRef.current;
|
|
1661
|
+
if (!last) return void 0;
|
|
1662
|
+
return connect(last);
|
|
1663
|
+
}, [connect]);
|
|
1664
|
+
const reset = react.useCallback(() => {
|
|
1665
|
+
mutation.reset();
|
|
1666
|
+
setError(null);
|
|
1667
|
+
setActiveConnector(null);
|
|
1668
|
+
lastConnectorRef.current = null;
|
|
1669
|
+
}, [mutation]);
|
|
1670
|
+
const status = error ? "error" : mutation.isPending ? "connecting" : mutation.isSuccess ? "success" : "idle";
|
|
1671
|
+
return {
|
|
1672
|
+
status,
|
|
1673
|
+
error,
|
|
1674
|
+
activeConnector,
|
|
1675
|
+
activeChainType: activeConnector?.xChainType ?? null,
|
|
1676
|
+
connect,
|
|
1677
|
+
disconnect: disconnect2,
|
|
1678
|
+
retry,
|
|
1679
|
+
reset
|
|
1680
|
+
};
|
|
1681
|
+
}
|
|
1682
|
+
function resolveBatchTargets(connectors, connectorsByChain) {
|
|
1683
|
+
const targets = [];
|
|
1684
|
+
for (const chainType of types.ChainTypeArr) {
|
|
1685
|
+
const chainConnectors = connectorsByChain[chainType];
|
|
1686
|
+
if (!chainConnectors?.length) continue;
|
|
1687
|
+
for (const identifier of connectors) {
|
|
1688
|
+
const match = chainConnectors.find((c) => matchesConnectorIdentifier(c, identifier));
|
|
1689
|
+
if (match) targets.push({ chainType, connector: match });
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
return targets;
|
|
1693
|
+
}
|
|
1694
|
+
async function runBatchConnect(targets, helpers) {
|
|
1695
|
+
const successful = [];
|
|
1696
|
+
const failed = [];
|
|
1697
|
+
const skipped = [];
|
|
1698
|
+
const finalized = /* @__PURE__ */ new Set();
|
|
1699
|
+
const pendingError = /* @__PURE__ */ new Map();
|
|
1700
|
+
const emit = (event) => {
|
|
1701
|
+
if (!helpers.onProgress) return;
|
|
1702
|
+
try {
|
|
1703
|
+
helpers.onProgress(event);
|
|
1704
|
+
} catch (err) {
|
|
1705
|
+
console.error("[useBatchConnect] onProgress threw:", err);
|
|
1706
|
+
}
|
|
1707
|
+
};
|
|
1708
|
+
for (const target of targets) {
|
|
1709
|
+
if (finalized.has(target.chainType)) continue;
|
|
1710
|
+
if (helpers.skipConnected && helpers.isConnected(target.chainType)) {
|
|
1711
|
+
skipped.push(target.chainType);
|
|
1712
|
+
finalized.add(target.chainType);
|
|
1713
|
+
emit({ chainType: target.chainType, outcome: "skipped" });
|
|
1714
|
+
continue;
|
|
1715
|
+
}
|
|
1716
|
+
try {
|
|
1717
|
+
await helpers.connect(target.connector);
|
|
1718
|
+
successful.push(target.chainType);
|
|
1719
|
+
finalized.add(target.chainType);
|
|
1720
|
+
pendingError.delete(target.chainType);
|
|
1721
|
+
emit({ chainType: target.chainType, outcome: "success" });
|
|
1722
|
+
} catch (raw) {
|
|
1723
|
+
const error = raw instanceof Error ? raw : new Error(String(raw));
|
|
1724
|
+
pendingError.set(target.chainType, error);
|
|
1725
|
+
emit({ chainType: target.chainType, outcome: "failure", error });
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
for (const [chainType, error] of pendingError) {
|
|
1729
|
+
if (!finalized.has(chainType)) failed.push({ chainType, error });
|
|
1730
|
+
}
|
|
1731
|
+
return { successful, failed, skipped };
|
|
1732
|
+
}
|
|
1733
|
+
function useBatchConnect({
|
|
1734
|
+
connectors,
|
|
1735
|
+
skipConnected = false,
|
|
1736
|
+
onProgress
|
|
1737
|
+
}) {
|
|
1738
|
+
assert(Array.isArray(connectors), "useBatchConnect: connectors must be an array");
|
|
1739
|
+
const { mutateAsync: connect } = useXConnect();
|
|
1740
|
+
const xConnectorsByChain = useXConnectorsByChain();
|
|
1741
|
+
const xConnections = useXConnections();
|
|
1742
|
+
const [status, setStatus] = react.useState("idle");
|
|
1743
|
+
const [result, setResult] = react.useState(null);
|
|
1744
|
+
const inFlightRef = react.useRef(null);
|
|
1745
|
+
const onProgressRef = react.useRef(onProgress);
|
|
1746
|
+
onProgressRef.current = onProgress;
|
|
1747
|
+
const run = react.useCallback(async () => {
|
|
1748
|
+
if (inFlightRef.current) return inFlightRef.current;
|
|
1749
|
+
const batchPromise = (async () => {
|
|
1750
|
+
setStatus("running");
|
|
1751
|
+
const targets = resolveBatchTargets(connectors, xConnectorsByChain);
|
|
1752
|
+
const finalResult = await runBatchConnect(targets, {
|
|
1753
|
+
connect,
|
|
1754
|
+
isConnected: (chainType) => !!xConnections[chainType]?.xAccount.address,
|
|
1755
|
+
skipConnected,
|
|
1756
|
+
onProgress: (event) => onProgressRef.current?.(event)
|
|
1136
1757
|
});
|
|
1137
|
-
|
|
1758
|
+
setResult(finalResult);
|
|
1759
|
+
setStatus("done");
|
|
1760
|
+
return finalResult;
|
|
1761
|
+
})();
|
|
1762
|
+
inFlightRef.current = batchPromise;
|
|
1763
|
+
try {
|
|
1764
|
+
return await batchPromise;
|
|
1765
|
+
} finally {
|
|
1766
|
+
inFlightRef.current = null;
|
|
1767
|
+
}
|
|
1768
|
+
}, [connect, connectors, xConnectorsByChain, xConnections, skipConnected]);
|
|
1769
|
+
const reset = react.useCallback(() => {
|
|
1770
|
+
setStatus("idle");
|
|
1771
|
+
setResult(null);
|
|
1772
|
+
}, []);
|
|
1773
|
+
return { run, status, result, reset };
|
|
1774
|
+
}
|
|
1775
|
+
function resolveDisconnectTargets(connectors, xConnections, xConnectorsByChain) {
|
|
1776
|
+
const targets = [];
|
|
1777
|
+
for (const chainType of types.ChainTypeArr) {
|
|
1778
|
+
const connection = xConnections[chainType];
|
|
1779
|
+
if (!connection?.xAccount.address) continue;
|
|
1780
|
+
if (!connectors) {
|
|
1781
|
+
targets.push(chainType);
|
|
1782
|
+
continue;
|
|
1783
|
+
}
|
|
1784
|
+
const activeConnector = xConnectorsByChain[chainType]?.find((c) => c.id === connection.xConnectorId);
|
|
1785
|
+
if (!activeConnector) continue;
|
|
1786
|
+
if (connectors.some((identifier) => matchesConnectorIdentifier(activeConnector, identifier))) {
|
|
1787
|
+
targets.push(chainType);
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
return targets;
|
|
1791
|
+
}
|
|
1792
|
+
async function runBatchDisconnect(chainTypes, disconnect2, onProgress) {
|
|
1793
|
+
const successful = [];
|
|
1794
|
+
const failed = [];
|
|
1795
|
+
const emit = (event) => {
|
|
1796
|
+
if (!onProgress) return;
|
|
1797
|
+
try {
|
|
1798
|
+
onProgress(event);
|
|
1138
1799
|
} catch (err) {
|
|
1139
|
-
console.error(err);
|
|
1140
|
-
|
|
1800
|
+
console.error("[useBatchDisconnect] onProgress threw:", err);
|
|
1801
|
+
}
|
|
1802
|
+
};
|
|
1803
|
+
for (const chainType of chainTypes) {
|
|
1804
|
+
try {
|
|
1805
|
+
await disconnect2({ xChainType: chainType });
|
|
1806
|
+
successful.push(chainType);
|
|
1807
|
+
emit({ chainType, outcome: "success" });
|
|
1808
|
+
} catch (raw) {
|
|
1809
|
+
const error = raw instanceof Error ? raw : new Error(String(raw));
|
|
1810
|
+
failed.push({ chainType, error });
|
|
1811
|
+
emit({ chainType, outcome: "failure", error });
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
return { successful, failed };
|
|
1815
|
+
}
|
|
1816
|
+
function useBatchDisconnect({
|
|
1817
|
+
connectors,
|
|
1818
|
+
onProgress
|
|
1819
|
+
} = {}) {
|
|
1820
|
+
const disconnect2 = useXDisconnect();
|
|
1821
|
+
const xConnections = useXConnections();
|
|
1822
|
+
const xConnectorsByChain = useXConnectorsByChain();
|
|
1823
|
+
const [status, setStatus] = react.useState("idle");
|
|
1824
|
+
const [result, setResult] = react.useState(null);
|
|
1825
|
+
const inFlightRef = react.useRef(null);
|
|
1826
|
+
const onProgressRef = react.useRef(onProgress);
|
|
1827
|
+
onProgressRef.current = onProgress;
|
|
1828
|
+
const run = react.useCallback(async () => {
|
|
1829
|
+
if (inFlightRef.current) return inFlightRef.current;
|
|
1830
|
+
const batchPromise = (async () => {
|
|
1831
|
+
setStatus("running");
|
|
1832
|
+
const targets = resolveDisconnectTargets(connectors, xConnections, xConnectorsByChain);
|
|
1833
|
+
const finalResult = await runBatchDisconnect(targets, disconnect2, (event) => onProgressRef.current?.(event));
|
|
1834
|
+
setResult(finalResult);
|
|
1835
|
+
setStatus("done");
|
|
1836
|
+
return finalResult;
|
|
1837
|
+
})();
|
|
1838
|
+
inFlightRef.current = batchPromise;
|
|
1839
|
+
try {
|
|
1840
|
+
return await batchPromise;
|
|
1841
|
+
} finally {
|
|
1842
|
+
inFlightRef.current = null;
|
|
1843
|
+
}
|
|
1844
|
+
}, [connectors, disconnect2, xConnections, xConnectorsByChain]);
|
|
1845
|
+
const reset = react.useCallback(() => {
|
|
1846
|
+
setStatus("idle");
|
|
1847
|
+
setResult(null);
|
|
1848
|
+
}, []);
|
|
1849
|
+
return { run, status, result, reset };
|
|
1850
|
+
}
|
|
1851
|
+
var useWalletModalStore = zustand.create()(
|
|
1852
|
+
middleware.devtools(
|
|
1853
|
+
immer.immer((set) => ({
|
|
1854
|
+
walletModal: { kind: "closed" },
|
|
1855
|
+
open: () => {
|
|
1856
|
+
set((state) => {
|
|
1857
|
+
state.walletModal = { kind: "chainSelect" };
|
|
1858
|
+
});
|
|
1859
|
+
},
|
|
1860
|
+
close: () => {
|
|
1861
|
+
set((state) => {
|
|
1862
|
+
state.walletModal = { kind: "closed" };
|
|
1863
|
+
});
|
|
1864
|
+
},
|
|
1865
|
+
back: () => {
|
|
1866
|
+
set((state) => {
|
|
1867
|
+
const current = state.walletModal;
|
|
1868
|
+
switch (current.kind) {
|
|
1869
|
+
case "walletSelect":
|
|
1870
|
+
state.walletModal = { kind: "chainSelect" };
|
|
1871
|
+
return;
|
|
1872
|
+
case "connecting":
|
|
1873
|
+
case "error":
|
|
1874
|
+
state.walletModal = { kind: "walletSelect", chainType: current.chainType };
|
|
1875
|
+
return;
|
|
1876
|
+
case "success":
|
|
1877
|
+
state.walletModal = { kind: "closed" };
|
|
1878
|
+
return;
|
|
1879
|
+
}
|
|
1880
|
+
});
|
|
1881
|
+
},
|
|
1882
|
+
selectChain: (chainType) => {
|
|
1883
|
+
set((state) => {
|
|
1884
|
+
state.walletModal = { kind: "walletSelect", chainType };
|
|
1885
|
+
});
|
|
1886
|
+
},
|
|
1887
|
+
setConnecting: (chainType, connector) => {
|
|
1888
|
+
set((state) => {
|
|
1889
|
+
state.walletModal = { kind: "connecting", chainType, connector };
|
|
1890
|
+
});
|
|
1891
|
+
},
|
|
1892
|
+
setSuccess: (chainType, connector, account) => {
|
|
1893
|
+
set((state) => {
|
|
1894
|
+
state.walletModal = { kind: "success", chainType, connector, account };
|
|
1895
|
+
});
|
|
1896
|
+
},
|
|
1897
|
+
setError: (chainType, connector, error) => {
|
|
1898
|
+
set((state) => {
|
|
1899
|
+
state.walletModal = { kind: "error", chainType, connector, error };
|
|
1900
|
+
});
|
|
1901
|
+
}
|
|
1902
|
+
})),
|
|
1903
|
+
{ name: "wallet-modal-store" }
|
|
1904
|
+
)
|
|
1905
|
+
);
|
|
1906
|
+
|
|
1907
|
+
// src/hooks/useWalletModal.ts
|
|
1908
|
+
var DEFAULT_HYDRATION_TIMEOUT_MS = 5e3;
|
|
1909
|
+
function waitForXConnection(chainType, expectedConnectorId, timeoutMs = DEFAULT_HYDRATION_TIMEOUT_MS) {
|
|
1910
|
+
return new Promise((resolve) => {
|
|
1911
|
+
let settled = false;
|
|
1912
|
+
const matches = (connection) => connection?.xConnectorId === expectedConnectorId && !!connection?.xAccount?.address;
|
|
1913
|
+
const finish = (account) => {
|
|
1914
|
+
if (settled) return;
|
|
1915
|
+
settled = true;
|
|
1916
|
+
clearTimeout(timer);
|
|
1917
|
+
unsubscribe();
|
|
1918
|
+
resolve(account);
|
|
1919
|
+
};
|
|
1920
|
+
const timer = setTimeout(() => finish(void 0), timeoutMs);
|
|
1921
|
+
const unsubscribe = useXWalletStore.subscribe((state) => {
|
|
1922
|
+
const connection = state.xConnections[chainType];
|
|
1923
|
+
if (matches(connection)) finish(connection?.xAccount);
|
|
1924
|
+
});
|
|
1925
|
+
const initial = useXWalletStore.getState().xConnections[chainType];
|
|
1926
|
+
if (matches(initial)) finish(initial?.xAccount);
|
|
1927
|
+
});
|
|
1928
|
+
}
|
|
1929
|
+
function useWalletModal({
|
|
1930
|
+
onConnected,
|
|
1931
|
+
hydrationTimeoutMs
|
|
1932
|
+
} = {}) {
|
|
1933
|
+
const state = useWalletModalStore((s) => s.walletModal);
|
|
1934
|
+
const open = useWalletModalStore((s) => s.open);
|
|
1935
|
+
const close = useWalletModalStore((s) => s.close);
|
|
1936
|
+
const back = useWalletModalStore((s) => s.back);
|
|
1937
|
+
const selectChain = useWalletModalStore((s) => s.selectChain);
|
|
1938
|
+
const setConnecting = useWalletModalStore((s) => s.setConnecting);
|
|
1939
|
+
const setSuccess = useWalletModalStore((s) => s.setSuccess);
|
|
1940
|
+
const setError = useWalletModalStore((s) => s.setError);
|
|
1941
|
+
const { mutateAsync: connect } = useXConnect();
|
|
1942
|
+
const inFlightRef = react.useRef(null);
|
|
1943
|
+
const selectWallet = react.useCallback(
|
|
1944
|
+
async (connector) => {
|
|
1945
|
+
if (inFlightRef.current?.connector === connector) {
|
|
1946
|
+
return inFlightRef.current.promise;
|
|
1947
|
+
}
|
|
1948
|
+
if (!connector.isInstalled) {
|
|
1949
|
+
const installHint = connector.installUrl ? " Install the extension and reload the page." : "";
|
|
1950
|
+
setError(
|
|
1951
|
+
connector.xChainType,
|
|
1952
|
+
connector,
|
|
1953
|
+
new Error(`${connector.name} is not installed.${installHint}`)
|
|
1954
|
+
);
|
|
1955
|
+
return void 0;
|
|
1956
|
+
}
|
|
1957
|
+
const isStillCurrent = () => {
|
|
1958
|
+
const current = useWalletModalStore.getState().walletModal;
|
|
1959
|
+
return current.kind === "connecting" && current.connector === connector;
|
|
1960
|
+
};
|
|
1961
|
+
const promise = (async () => {
|
|
1962
|
+
setConnecting(connector.xChainType, connector);
|
|
1963
|
+
try {
|
|
1964
|
+
const direct = await connect(connector);
|
|
1965
|
+
if (!isStillCurrent()) return void 0;
|
|
1966
|
+
const account = direct?.address ? direct : await waitForXConnection(connector.xChainType, connector.id, hydrationTimeoutMs);
|
|
1967
|
+
if (!isStillCurrent()) return void 0;
|
|
1968
|
+
if (account?.address) {
|
|
1969
|
+
setSuccess(connector.xChainType, connector, account);
|
|
1970
|
+
try {
|
|
1971
|
+
await onConnected?.(connector.xChainType, account);
|
|
1972
|
+
} catch (callbackError) {
|
|
1973
|
+
console.error("[useWalletModal] onConnected threw \u2014 connection is still successful:", callbackError);
|
|
1974
|
+
}
|
|
1975
|
+
return account;
|
|
1976
|
+
}
|
|
1977
|
+
setError(
|
|
1978
|
+
connector.xChainType,
|
|
1979
|
+
connector,
|
|
1980
|
+
new Error("Connection did not complete. Did you close the wallet popup?")
|
|
1981
|
+
);
|
|
1982
|
+
return void 0;
|
|
1983
|
+
} catch (raw) {
|
|
1984
|
+
if (!isStillCurrent()) return void 0;
|
|
1985
|
+
const error = raw instanceof Error ? raw : new Error(String(raw));
|
|
1986
|
+
setError(connector.xChainType, connector, error);
|
|
1987
|
+
return void 0;
|
|
1988
|
+
} finally {
|
|
1989
|
+
if (inFlightRef.current?.connector === connector) {
|
|
1990
|
+
inFlightRef.current = null;
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
})();
|
|
1994
|
+
inFlightRef.current = { connector, promise };
|
|
1995
|
+
return promise;
|
|
1996
|
+
},
|
|
1997
|
+
[connect, onConnected, hydrationTimeoutMs, setConnecting, setError, setSuccess]
|
|
1998
|
+
);
|
|
1999
|
+
const retry = react.useCallback(async () => {
|
|
2000
|
+
if (state.kind !== "error") return void 0;
|
|
2001
|
+
return selectWallet(state.connector);
|
|
2002
|
+
}, [state, selectWallet]);
|
|
2003
|
+
return { state, open, close, back, selectChain, selectWallet, retry };
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
// src/hooks/useXService.ts
|
|
2007
|
+
function useXService({ xChainType } = {}) {
|
|
2008
|
+
const xService = useXWalletStore((state) => xChainType ? state.xServices[xChainType] : void 0);
|
|
2009
|
+
return xService;
|
|
2010
|
+
}
|
|
2011
|
+
|
|
2012
|
+
// src/hooks/useXServices.ts
|
|
2013
|
+
function useXServices() {
|
|
2014
|
+
return useXWalletStore((state) => state.xServices);
|
|
2015
|
+
}
|
|
2016
|
+
var WalletConfigContext = react.createContext(null);
|
|
2017
|
+
var WalletConfigProvider = WalletConfigContext.Provider;
|
|
2018
|
+
function useWalletConfig() {
|
|
2019
|
+
const config = react.useContext(WalletConfigContext);
|
|
2020
|
+
if (!config) {
|
|
2021
|
+
throw new Error("useWalletConfig must be used within SodaxWalletProvider");
|
|
2022
|
+
}
|
|
2023
|
+
return config;
|
|
2024
|
+
}
|
|
2025
|
+
function useIsChainEnabled(chainType) {
|
|
2026
|
+
const config = useWalletConfig();
|
|
2027
|
+
return config[chainType] !== void 0;
|
|
2028
|
+
}
|
|
2029
|
+
function useEnabledChainTypes() {
|
|
2030
|
+
const config = useWalletConfig();
|
|
2031
|
+
return Object.keys(config).filter((t) => config[t] !== void 0);
|
|
2032
|
+
}
|
|
2033
|
+
function useEthereumChainId() {
|
|
2034
|
+
const xService = useXService({ xChainType: "INJECTIVE" });
|
|
2035
|
+
const injectiveXService = xService instanceof InjectiveXService ? xService : void 0;
|
|
2036
|
+
const [ethereumChainId, setEthereumChainId] = react.useState(null);
|
|
2037
|
+
react.useEffect(() => {
|
|
2038
|
+
if (!injectiveXService?.walletStrategy?.getWallet()) return;
|
|
2039
|
+
const walletStrategy = injectiveXService.walletStrategy;
|
|
2040
|
+
if (walletStrategy.getWallet() !== walletBase.Wallet.Metamask) return;
|
|
2041
|
+
const getEthereumChainId = async () => {
|
|
2042
|
+
try {
|
|
2043
|
+
const chainId = await walletStrategy.getEthereumChainId();
|
|
2044
|
+
setEthereumChainId(Number.parseInt(chainId));
|
|
2045
|
+
} catch (error) {
|
|
2046
|
+
console.warn("Failed to get Ethereum chain ID:", error);
|
|
2047
|
+
}
|
|
2048
|
+
};
|
|
2049
|
+
getEthereumChainId();
|
|
2050
|
+
try {
|
|
2051
|
+
const strategy = walletStrategy.getStrategy();
|
|
2052
|
+
const isEvmStrategy = isRecord(strategy) && hasFunctionProperty(strategy, "onChainIdChanged");
|
|
2053
|
+
assert(isEvmStrategy, "[useEthereumChainId] walletStrategy.getStrategy() is not an EvmWalletStrategy");
|
|
2054
|
+
strategy.onChainIdChanged(getEthereumChainId);
|
|
2055
|
+
} catch (error) {
|
|
2056
|
+
console.warn("Failed to subscribe to chain ID changes:", error);
|
|
2057
|
+
}
|
|
2058
|
+
}, [injectiveXService?.walletStrategy]);
|
|
2059
|
+
return ethereumChainId;
|
|
2060
|
+
}
|
|
2061
|
+
var EVM_DISABLED_RESULT = { isWrongChain: false, handleSwitchChain: () => {
|
|
2062
|
+
} };
|
|
2063
|
+
var isEip1193Provider = (value) => {
|
|
2064
|
+
return isRecord(value) && hasFunctionProperty(value, "request") && hasFunctionProperty(value, "on");
|
|
2065
|
+
};
|
|
2066
|
+
var getInjectedEthereumProvider = () => {
|
|
2067
|
+
const maybeEthereum = window.ethereum;
|
|
2068
|
+
assert(isEip1193Provider(maybeEthereum), "[useEvmSwitchChain] window.ethereum is not an EIP-1193 provider");
|
|
2069
|
+
return maybeEthereum;
|
|
2070
|
+
};
|
|
2071
|
+
var switchEthereumChain = async () => {
|
|
2072
|
+
const metamaskProvider = getInjectedEthereumProvider();
|
|
2073
|
+
return await Promise.race([
|
|
2074
|
+
metamaskProvider.request({
|
|
2075
|
+
method: "wallet_switchEthereumChain",
|
|
2076
|
+
params: [{ chainId: "0x1" }]
|
|
2077
|
+
}),
|
|
2078
|
+
new Promise((resolve) => {
|
|
2079
|
+
const handler = (chainId) => {
|
|
2080
|
+
if (chainId === "0x1") {
|
|
2081
|
+
metamaskProvider.removeListener("chainChanged", handler);
|
|
2082
|
+
resolve();
|
|
2083
|
+
}
|
|
2084
|
+
};
|
|
2085
|
+
metamaskProvider.on("chainChanged", handler);
|
|
2086
|
+
})
|
|
2087
|
+
]);
|
|
2088
|
+
};
|
|
2089
|
+
function useEvmSwitchChain({ xChainId }) {
|
|
2090
|
+
const evmEnabled = useIsChainEnabled("EVM");
|
|
2091
|
+
if (!evmEnabled) {
|
|
2092
|
+
return EVM_DISABLED_RESULT;
|
|
2093
|
+
}
|
|
2094
|
+
return useEvmSwitchChainInner({ xChainId });
|
|
2095
|
+
}
|
|
2096
|
+
function useEvmSwitchChainInner({ xChainId }) {
|
|
2097
|
+
const xChainType = getXChainType(xChainId);
|
|
2098
|
+
const expectedChainId = types.baseChainInfo[xChainId].chainId;
|
|
2099
|
+
if (xChainType === "EVM") {
|
|
2100
|
+
assert(typeof expectedChainId === "number", "[useEvmSwitchChain] EVM chain must have numeric chainId");
|
|
2101
|
+
}
|
|
2102
|
+
const xService = useXService({ xChainType: "INJECTIVE" });
|
|
2103
|
+
const injectiveXService = xService instanceof InjectiveXService ? xService : void 0;
|
|
2104
|
+
const ethereumChainId = useEthereumChainId();
|
|
2105
|
+
const { chainId } = wagmi.useAccount();
|
|
2106
|
+
const isWrongChain = react.useMemo(() => {
|
|
2107
|
+
return xChainType === "EVM" && chainId !== expectedChainId || xChainType === "INJECTIVE" && injectiveXService !== void 0 && injectiveXService.walletStrategy.getWallet() === walletBase.Wallet.Metamask && ethereumChainId !== chains.mainnet.id;
|
|
2108
|
+
}, [xChainType, chainId, expectedChainId, ethereumChainId, injectiveXService]);
|
|
2109
|
+
const { switchChain } = wagmi.useSwitchChain();
|
|
2110
|
+
const handleSwitchChain = react.useCallback(() => {
|
|
2111
|
+
if (xChainType === "INJECTIVE") {
|
|
2112
|
+
switchEthereumChain();
|
|
2113
|
+
} else if (xChainType === "EVM" && typeof expectedChainId === "number") {
|
|
2114
|
+
switchChain({ chainId: expectedChainId });
|
|
2115
|
+
}
|
|
2116
|
+
}, [switchChain, expectedChainId, xChainType]);
|
|
2117
|
+
return react.useMemo(
|
|
2118
|
+
() => ({
|
|
2119
|
+
isWrongChain,
|
|
2120
|
+
handleSwitchChain
|
|
2121
|
+
}),
|
|
2122
|
+
[isWrongChain, handleSwitchChain]
|
|
2123
|
+
);
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2126
|
+
// src/hooks/useWalletProvider.ts
|
|
2127
|
+
var warnedChains2 = /* @__PURE__ */ new Set();
|
|
2128
|
+
function useWalletProvider({
|
|
2129
|
+
xChainId,
|
|
2130
|
+
xChainType
|
|
2131
|
+
} = {}) {
|
|
2132
|
+
assert(!(xChainId && xChainType), "[useWalletProvider] pass either xChainId or xChainType, not both");
|
|
2133
|
+
const target = xChainType ?? (xChainId ? getXChainType(xChainId) : void 0);
|
|
2134
|
+
return useXWalletStore((state) => {
|
|
2135
|
+
if (!target) return void 0;
|
|
2136
|
+
if (!state.enabledChains.includes(target) && !warnedChains2.has(target)) {
|
|
2137
|
+
warnedChains2.add(target);
|
|
2138
|
+
console.warn(
|
|
2139
|
+
`[useWalletProvider] chain "${target}" is not enabled in SodaxWalletProvider config.chains \u2014 returning undefined`
|
|
2140
|
+
);
|
|
2141
|
+
}
|
|
2142
|
+
return state.getWalletProvider(target);
|
|
2143
|
+
});
|
|
2144
|
+
}
|
|
2145
|
+
function useXSignMessage() {
|
|
2146
|
+
const actionsRegistry = useXWalletStore((state) => state.chainActions);
|
|
2147
|
+
return reactQuery.useMutation({
|
|
2148
|
+
mutationFn: async ({ xChainType, message }) => {
|
|
2149
|
+
const chainActions = actionsRegistry[xChainType];
|
|
2150
|
+
if (!chainActions?.signMessage) {
|
|
2151
|
+
console.warn(`[useXSignMessage] signMessage not supported for chain "${xChainType}"`);
|
|
2152
|
+
return void 0;
|
|
2153
|
+
}
|
|
2154
|
+
return await chainActions.signMessage(message);
|
|
2155
|
+
}
|
|
2156
|
+
});
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
// src/xchains/bitcoin/bitcoinSignGuards.ts
|
|
2160
|
+
function hasSignBip322(c) {
|
|
2161
|
+
return "signBip322Message" in c && typeof c.signBip322Message === "function";
|
|
2162
|
+
}
|
|
2163
|
+
function hasSignEcdsa(c) {
|
|
2164
|
+
return "signEcdsaMessage" in c && typeof c.signEcdsaMessage === "function";
|
|
2165
|
+
}
|
|
2166
|
+
var NearXService = class _NearXService extends XService {
|
|
2167
|
+
static instance;
|
|
2168
|
+
walletSelector;
|
|
2169
|
+
rpcUrl;
|
|
2170
|
+
/**
|
|
2171
|
+
* @param rpcUrl - Used by `getBalance` via `JsonRpcProvider({ url: rpcUrl })`.
|
|
2172
|
+
* Does NOT affect `walletSelector` — `@hot-labs/near-connect` only accepts
|
|
2173
|
+
* the network preset name (`'mainnet'`/`'testnet'`) and fetches RPC internally.
|
|
2174
|
+
* Custom RPC is therefore read-only for balance queries.
|
|
2175
|
+
*/
|
|
2176
|
+
constructor(rpcUrl = NEAR_DEFAULT_RPC_URL) {
|
|
2177
|
+
super("NEAR");
|
|
2178
|
+
this.rpcUrl = rpcUrl;
|
|
2179
|
+
this.walletSelector = new nearConnect.NearConnector({
|
|
2180
|
+
network: "mainnet",
|
|
2181
|
+
logger: console,
|
|
2182
|
+
autoConnect: true,
|
|
2183
|
+
excludedWallets: ["okx-wallet"]
|
|
2184
|
+
});
|
|
2185
|
+
}
|
|
2186
|
+
/**
|
|
2187
|
+
* @param rpcUrl - Re-applied on every call (matches StacksXService semantics).
|
|
2188
|
+
* `rpcUrl` only drives `getBalance` via a per-call `JsonRpcProvider`, so it's
|
|
2189
|
+
* safe to update at runtime — no persistent chain client to rebuild.
|
|
2190
|
+
*/
|
|
2191
|
+
static getInstance(rpcUrl) {
|
|
2192
|
+
if (!_NearXService.instance) {
|
|
2193
|
+
_NearXService.instance = new _NearXService(rpcUrl);
|
|
2194
|
+
} else if (rpcUrl) {
|
|
2195
|
+
_NearXService.instance.rpcUrl = rpcUrl;
|
|
1141
2196
|
}
|
|
2197
|
+
return _NearXService.instance;
|
|
1142
2198
|
}
|
|
1143
|
-
async
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
if (nativeXToken) {
|
|
1149
|
-
const balance = await this.iconService.getBalance(address).execute();
|
|
1150
|
-
balances[nativeXToken.address] = BigInt(balance.toFixed());
|
|
2199
|
+
async getBalance(address, xToken) {
|
|
2200
|
+
const provider = new nearApiJs.JsonRpcProvider({ url: this.rpcUrl });
|
|
2201
|
+
if (xToken.symbol === "NEAR") {
|
|
2202
|
+
const account = await provider.viewAccount({ accountId: address ?? "" });
|
|
2203
|
+
return BigInt(account.amount);
|
|
1151
2204
|
}
|
|
1152
|
-
const
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
params: [address]
|
|
1157
|
-
};
|
|
2205
|
+
const res = await provider.callFunction({
|
|
2206
|
+
contractId: xToken.address,
|
|
2207
|
+
method: "ft_balance_of",
|
|
2208
|
+
args: { account_id: address }
|
|
1158
2209
|
});
|
|
1159
|
-
|
|
1160
|
-
false,
|
|
1161
|
-
cds.filter((cd) => cd.target.startsWith("cx"))
|
|
1162
|
-
);
|
|
1163
|
-
return nonNativeXTokens.reduce((agg, token, idx) => {
|
|
1164
|
-
const balance = data[idx];
|
|
1165
|
-
balances[token.address] = BigInt(balance);
|
|
1166
|
-
return agg;
|
|
1167
|
-
}, balances);
|
|
2210
|
+
return BigInt(res ?? 0);
|
|
1168
2211
|
}
|
|
1169
2212
|
};
|
|
1170
2213
|
|
|
1171
|
-
// src/xchains/
|
|
1172
|
-
var
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
window.addEventListener(ICONEX_RELAY_RESPONSE, handler);
|
|
1181
|
-
window.dispatchEvent(
|
|
1182
|
-
new CustomEvent(ICONEX_RELAY_REQUEST, {
|
|
1183
|
-
detail: event
|
|
1184
|
-
})
|
|
1185
|
-
);
|
|
1186
|
-
});
|
|
1187
|
-
};
|
|
1188
|
-
|
|
1189
|
-
// src/xchains/icon/IconHanaXConnector.ts
|
|
1190
|
-
var IconHanaXConnector = class extends XConnector {
|
|
1191
|
-
constructor() {
|
|
1192
|
-
super("ICON", "Hana Wallet", "hana");
|
|
2214
|
+
// src/xchains/near/NearXConnector.ts
|
|
2215
|
+
var NearXConnector = class extends XConnector {
|
|
2216
|
+
_wallet;
|
|
2217
|
+
constructor(wallet) {
|
|
2218
|
+
super("NEAR", wallet.manifest.name, wallet.manifest.id);
|
|
2219
|
+
this._wallet = wallet;
|
|
2220
|
+
}
|
|
2221
|
+
getXService() {
|
|
2222
|
+
return NearXService.getInstance();
|
|
1193
2223
|
}
|
|
1194
2224
|
async connect() {
|
|
1195
|
-
const
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
type: "REQUEST_ADDRESS" /* REQUEST_ADDRESS */
|
|
1202
|
-
});
|
|
1203
|
-
if (detail?.type === "RESPONSE_ADDRESS" /* RESPONSE_ADDRESS */) {
|
|
1204
|
-
return {
|
|
1205
|
-
address: detail?.payload,
|
|
1206
|
-
xChainType: this.xChainType
|
|
1207
|
-
};
|
|
2225
|
+
const walletSelector = this.getXService().walletSelector;
|
|
2226
|
+
const wallet = await walletSelector.connect({ walletId: this._wallet.manifest.id });
|
|
2227
|
+
const accounts = await wallet.getAccounts();
|
|
2228
|
+
if (accounts.length === 0 || accounts[0] === void 0) {
|
|
2229
|
+
console.warn(`[NearXConnector] connect: ${this._wallet.manifest.name} returned no accounts`);
|
|
2230
|
+
return void 0;
|
|
1208
2231
|
}
|
|
1209
|
-
return
|
|
2232
|
+
return {
|
|
2233
|
+
address: accounts[0].accountId,
|
|
2234
|
+
xChainType: this.xChainType
|
|
2235
|
+
};
|
|
1210
2236
|
}
|
|
1211
2237
|
async disconnect() {
|
|
1212
|
-
|
|
2238
|
+
const walletSelector = this.getXService().walletSelector;
|
|
2239
|
+
await walletSelector.disconnect(this._wallet);
|
|
1213
2240
|
}
|
|
1214
2241
|
get icon() {
|
|
1215
|
-
return
|
|
2242
|
+
return this._wallet.manifest.icon;
|
|
2243
|
+
}
|
|
2244
|
+
};
|
|
2245
|
+
var StacksXService = class _StacksXService extends XService {
|
|
2246
|
+
static instance;
|
|
2247
|
+
network;
|
|
2248
|
+
constructor(network$1) {
|
|
2249
|
+
super("STACKS");
|
|
2250
|
+
this.network = network.networkFrom(network$1 || "mainnet");
|
|
2251
|
+
}
|
|
2252
|
+
static getInstance(network$1) {
|
|
2253
|
+
if (!_StacksXService.instance) {
|
|
2254
|
+
_StacksXService.instance = new _StacksXService(network$1);
|
|
2255
|
+
} else if (network$1) {
|
|
2256
|
+
_StacksXService.instance.network = network.networkFrom(network$1);
|
|
2257
|
+
}
|
|
2258
|
+
return _StacksXService.instance;
|
|
2259
|
+
}
|
|
2260
|
+
async getBalance(address, xToken) {
|
|
2261
|
+
if (!address) return 0n;
|
|
2262
|
+
if (xToken.symbol === "STX") {
|
|
2263
|
+
const url = `${this.network.client.baseUrl}/extended/v1/address/${address}/balances`;
|
|
2264
|
+
try {
|
|
2265
|
+
const response = await fetch(url);
|
|
2266
|
+
if (!response.ok) {
|
|
2267
|
+
throw new Error(`Error fetching data: ${response.statusText}`);
|
|
2268
|
+
}
|
|
2269
|
+
const data = await response.json();
|
|
2270
|
+
return BigInt(data.stx.balance);
|
|
2271
|
+
} catch (error) {
|
|
2272
|
+
console.error("Error fetching STX balance:", error);
|
|
2273
|
+
return 0n;
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
const parts = xToken.address.split(".");
|
|
2277
|
+
const contractAddress = parts[0] ?? "";
|
|
2278
|
+
const contractName = parts[1] ?? "";
|
|
2279
|
+
try {
|
|
2280
|
+
const result = await transactions.fetchCallReadOnlyFunction({
|
|
2281
|
+
contractAddress,
|
|
2282
|
+
contractName,
|
|
2283
|
+
functionName: "get-balance",
|
|
2284
|
+
functionArgs: [transactions.Cl.principal(address)],
|
|
2285
|
+
network: this.network,
|
|
2286
|
+
senderAddress: address
|
|
2287
|
+
});
|
|
2288
|
+
return result.value.value;
|
|
2289
|
+
} catch (error) {
|
|
2290
|
+
console.error("Error fetching token balance:", error);
|
|
2291
|
+
return 0n;
|
|
2292
|
+
}
|
|
1216
2293
|
}
|
|
1217
2294
|
};
|
|
1218
2295
|
function getProviderFromId(id) {
|
|
1219
2296
|
return id.split(".").reduce((acc, part) => acc?.[part], window);
|
|
1220
2297
|
}
|
|
1221
2298
|
var StacksXConnector = class extends XConnector {
|
|
2299
|
+
config;
|
|
1222
2300
|
constructor(config) {
|
|
1223
2301
|
super("STACKS", config.name, config.id);
|
|
1224
2302
|
this.config = config;
|
|
@@ -1226,14 +2304,15 @@ var StacksXConnector = class extends XConnector {
|
|
|
1226
2304
|
async connect() {
|
|
1227
2305
|
const provider = this.getProvider();
|
|
1228
2306
|
if (!provider) {
|
|
1229
|
-
|
|
1230
|
-
window.open(this.config.installUrl, "_blank");
|
|
1231
|
-
}
|
|
1232
|
-
return void 0;
|
|
2307
|
+
throw new Error(`${this.config.name} is not installed. Install the extension and reload the page.`);
|
|
1233
2308
|
}
|
|
1234
2309
|
const response = await connect.request({ provider }, "stx_getAddresses");
|
|
1235
2310
|
const stxAddress = response.addresses.find((a) => a.purpose === "stacks");
|
|
1236
2311
|
if (!stxAddress) {
|
|
2312
|
+
console.warn(
|
|
2313
|
+
`[StacksXConnector] ${this.config.name}: no address with purpose="stacks" returned from stx_getAddresses`,
|
|
2314
|
+
response.addresses
|
|
2315
|
+
);
|
|
1237
2316
|
return void 0;
|
|
1238
2317
|
}
|
|
1239
2318
|
return {
|
|
@@ -1247,6 +2326,13 @@ var StacksXConnector = class extends XConnector {
|
|
|
1247
2326
|
get icon() {
|
|
1248
2327
|
return this.config.icon;
|
|
1249
2328
|
}
|
|
2329
|
+
get isInstalled() {
|
|
2330
|
+
if (typeof window === "undefined") return false;
|
|
2331
|
+
return getProviderFromId(this.config.id) !== void 0;
|
|
2332
|
+
}
|
|
2333
|
+
get installUrl() {
|
|
2334
|
+
return this.config.installUrl;
|
|
2335
|
+
}
|
|
1250
2336
|
getProvider() {
|
|
1251
2337
|
return getProviderFromId(this.config.id);
|
|
1252
2338
|
}
|
|
@@ -1283,258 +2369,553 @@ var STACKS_PROVIDERS = [
|
|
|
1283
2369
|
installUrl: "https://chromewebstore.google.com/detail/fordefi/hcmehenccjdmfbojapcbcofkgdpbnlle"
|
|
1284
2370
|
}
|
|
1285
2371
|
];
|
|
1286
|
-
function useStacksXConnectors() {
|
|
1287
|
-
return React2.useMemo(() => STACKS_PROVIDERS.map((config) => new StacksXConnector(config)), []);
|
|
1288
|
-
}
|
|
1289
2372
|
|
|
1290
|
-
// src/
|
|
1291
|
-
|
|
2373
|
+
// src/chainRegistry.ts
|
|
2374
|
+
function defineChain2(factory) {
|
|
2375
|
+
return factory;
|
|
2376
|
+
}
|
|
2377
|
+
function narrowConnectors(items, chainType) {
|
|
2378
|
+
return items.filter((item) => {
|
|
2379
|
+
if (!(item instanceof XConnector)) {
|
|
2380
|
+
console.warn(
|
|
2381
|
+
`[chainRegistry] ${chainType} connector "${item.id}" must extend XConnector \u2014 skipping. Implement the abstract XConnector class instead of raw IXConnector for full SDK support.`
|
|
2382
|
+
);
|
|
2383
|
+
return false;
|
|
2384
|
+
}
|
|
2385
|
+
return true;
|
|
2386
|
+
});
|
|
2387
|
+
}
|
|
2388
|
+
function readConnectorsOverride(chainType, walletConfig) {
|
|
2389
|
+
return walletConfig?.[chainType]?.connectors;
|
|
2390
|
+
}
|
|
2391
|
+
function hasChainOfType(chainType, walletConfig) {
|
|
2392
|
+
return walletConfig[chainType] !== void 0;
|
|
2393
|
+
}
|
|
2394
|
+
var createDefaultActions = (chainType, service, getStore) => ({
|
|
2395
|
+
connect: async (xConnectorId) => {
|
|
2396
|
+
const connector = service.getXConnectorById(xConnectorId);
|
|
2397
|
+
return connector?.connect();
|
|
2398
|
+
},
|
|
2399
|
+
disconnect: async () => {
|
|
2400
|
+
const store = getStore();
|
|
2401
|
+
const connectorId = store.xConnections[chainType]?.xConnectorId;
|
|
2402
|
+
const connector = connectorId ? service.getXConnectorById(connectorId) : void 0;
|
|
2403
|
+
try {
|
|
2404
|
+
await connector?.disconnect();
|
|
2405
|
+
} finally {
|
|
2406
|
+
store.unsetXConnection(chainType);
|
|
2407
|
+
}
|
|
2408
|
+
},
|
|
2409
|
+
getConnectors: () => getStore().xConnectorsByChain[chainType] ?? [],
|
|
2410
|
+
getConnection: () => getStore().xConnections[chainType]
|
|
2411
|
+
});
|
|
2412
|
+
var chainRegistry = {
|
|
2413
|
+
EVM: defineChain2({
|
|
2414
|
+
createService: () => EvmXService.getInstance(),
|
|
2415
|
+
displayName: "EVM",
|
|
2416
|
+
defaultConnectors: () => [],
|
|
2417
|
+
providerManaged: true
|
|
2418
|
+
}),
|
|
2419
|
+
SUI: defineChain2({
|
|
2420
|
+
createService: () => SuiXService.getInstance(),
|
|
2421
|
+
displayName: "Sui",
|
|
2422
|
+
defaultConnectors: () => [],
|
|
2423
|
+
providerManaged: true
|
|
2424
|
+
}),
|
|
2425
|
+
SOLANA: defineChain2({
|
|
2426
|
+
createService: () => SolanaXService.getInstance(),
|
|
2427
|
+
displayName: "Solana",
|
|
2428
|
+
defaultConnectors: () => [],
|
|
2429
|
+
providerManaged: true
|
|
2430
|
+
}),
|
|
2431
|
+
BITCOIN: defineChain2({
|
|
2432
|
+
createService: (walletConfig) => BitcoinXService.getInstance(getRpcUrl(walletConfig?.BITCOIN?.chains?.[types.ChainKeys.BITCOIN_MAINNET])),
|
|
2433
|
+
displayName: "Bitcoin",
|
|
2434
|
+
defaultConnectors: (walletConfig) => {
|
|
2435
|
+
const defaults = getEntryDefaults(
|
|
2436
|
+
walletConfig?.BITCOIN?.chains?.[types.ChainKeys.BITCOIN_MAINNET]
|
|
2437
|
+
);
|
|
2438
|
+
return [new UnisatXConnector(defaults), new XverseXConnector(defaults), new OKXXConnector(defaults)];
|
|
2439
|
+
},
|
|
2440
|
+
providerManaged: false,
|
|
2441
|
+
createActions: (service, getStore) => ({
|
|
2442
|
+
...createDefaultActions("BITCOIN", service, getStore),
|
|
2443
|
+
signMessage: async (message) => {
|
|
2444
|
+
const store = getStore();
|
|
2445
|
+
const connection = store.xConnections.BITCOIN;
|
|
2446
|
+
const connector = connection?.xConnectorId ? service.getXConnectorById(connection.xConnectorId) : void 0;
|
|
2447
|
+
if (!(connector instanceof BitcoinXConnector)) {
|
|
2448
|
+
throw new Error("Bitcoin wallet not connected");
|
|
2449
|
+
}
|
|
2450
|
+
const address = connection?.xAccount.address;
|
|
2451
|
+
if (!address) throw new Error("Bitcoin address not found");
|
|
2452
|
+
const addressType = types.detectBitcoinAddressType(address);
|
|
2453
|
+
switch (addressType) {
|
|
2454
|
+
case "P2WPKH":
|
|
2455
|
+
case "P2TR": {
|
|
2456
|
+
if (!hasSignBip322(connector)) {
|
|
2457
|
+
throw new Error(`${connector.id} does not support BIP-322 signing`);
|
|
2458
|
+
}
|
|
2459
|
+
return connector.signBip322Message(message);
|
|
2460
|
+
}
|
|
2461
|
+
case "P2SH":
|
|
2462
|
+
case "P2PKH": {
|
|
2463
|
+
if (!hasSignEcdsa(connector)) {
|
|
2464
|
+
throw new Error(`${connector.id} does not support ECDSA signing`);
|
|
2465
|
+
}
|
|
2466
|
+
return connector.signEcdsaMessage(message);
|
|
2467
|
+
}
|
|
2468
|
+
default: {
|
|
2469
|
+
const _exhaustiveCheck = addressType;
|
|
2470
|
+
throw new Error(`Unhandled Bitcoin address type: ${_exhaustiveCheck}`);
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
}),
|
|
2475
|
+
createWalletProvider: (service, getStore) => {
|
|
2476
|
+
const store = getStore();
|
|
2477
|
+
const connection = store.xConnections.BITCOIN;
|
|
2478
|
+
if (!connection?.xConnectorId) return void 0;
|
|
2479
|
+
const connector = service.getXConnectorById(connection.xConnectorId);
|
|
2480
|
+
if (!(connector instanceof BitcoinXConnector)) return void 0;
|
|
2481
|
+
return connector.recreateWalletProvider(connection.xAccount);
|
|
2482
|
+
}
|
|
2483
|
+
}),
|
|
2484
|
+
INJECTIVE: defineChain2({
|
|
2485
|
+
createService: (walletConfig) => InjectiveXService.getInstance(walletConfig?.INJECTIVE?.chains?.[types.ChainKeys.INJECTIVE_MAINNET]),
|
|
2486
|
+
displayName: "Injective",
|
|
2487
|
+
defaultConnectors: () => [
|
|
2488
|
+
new InjectiveXConnector("MetaMask", walletBase.Wallet.Metamask),
|
|
2489
|
+
new InjectiveXConnector("Keplr", walletBase.Wallet.Keplr),
|
|
2490
|
+
new InjectiveXConnector("Leap", walletBase.Wallet.Leap)
|
|
2491
|
+
],
|
|
2492
|
+
providerManaged: false,
|
|
2493
|
+
createActions: (service, getStore) => ({
|
|
2494
|
+
...createDefaultActions("INJECTIVE", service, getStore),
|
|
2495
|
+
signMessage: async (message) => {
|
|
2496
|
+
const store = getStore();
|
|
2497
|
+
const address = store.xConnections.INJECTIVE?.xAccount.address;
|
|
2498
|
+
if (!address) throw new Error("Injective address not found");
|
|
2499
|
+
const ethereumAddress = sdkTs.getEthereumAddress(address);
|
|
2500
|
+
const walletStrategy = service.walletStrategy;
|
|
2501
|
+
const res = await walletStrategy.signArbitrary(
|
|
2502
|
+
walletStrategy.getWallet() === walletBase.Wallet.Metamask ? ethereumAddress : address,
|
|
2503
|
+
message
|
|
2504
|
+
);
|
|
2505
|
+
if (!res) throw new Error("Injective signature not found");
|
|
2506
|
+
return res;
|
|
2507
|
+
}
|
|
2508
|
+
}),
|
|
2509
|
+
createWalletProvider: (service, getStore) => {
|
|
2510
|
+
if (!service) return void 0;
|
|
2511
|
+
const defaults = getEntryDefaults(
|
|
2512
|
+
getStore().walletConfig?.INJECTIVE?.chains?.[types.ChainKeys.INJECTIVE_MAINNET]
|
|
2513
|
+
);
|
|
2514
|
+
return new walletSdkCore.InjectiveWalletProvider({ msgBroadcaster: service.msgBroadcaster, defaults });
|
|
2515
|
+
}
|
|
2516
|
+
}),
|
|
2517
|
+
STELLAR: defineChain2({
|
|
2518
|
+
createService: (walletConfig) => {
|
|
2519
|
+
const stellarRpc = walletConfig?.STELLAR?.chains?.[types.ChainKeys.STELLAR_MAINNET];
|
|
2520
|
+
return StellarXService.getInstance(stellarRpc?.horizonRpcUrl, stellarRpc?.sorobanRpcUrl);
|
|
2521
|
+
},
|
|
2522
|
+
displayName: "Stellar",
|
|
2523
|
+
defaultConnectors: () => [],
|
|
2524
|
+
providerManaged: false,
|
|
2525
|
+
discoverConnectors: async (service, getStore) => {
|
|
2526
|
+
const STELLAR_DISCOVER_DELAYS_MS = [0, 100, 500];
|
|
2527
|
+
let lastIds = "";
|
|
2528
|
+
for (const delay of STELLAR_DISCOVER_DELAYS_MS) {
|
|
2529
|
+
if (delay) await new Promise((r) => setTimeout(r, delay));
|
|
2530
|
+
const wallets = await service.walletsKit.getSupportedWallets();
|
|
2531
|
+
const connectors = wallets.filter((w) => w.isAvailable).map((w) => new StellarWalletsKitXConnector(w));
|
|
2532
|
+
const ids = connectors.map((c) => c.id).sort().join(",");
|
|
2533
|
+
if (ids === lastIds) break;
|
|
2534
|
+
lastIds = ids;
|
|
2535
|
+
service.setXConnectors(connectors);
|
|
2536
|
+
getStore().setXConnectors("STELLAR", connectors);
|
|
2537
|
+
}
|
|
2538
|
+
},
|
|
2539
|
+
createActions: (service, getStore) => ({
|
|
2540
|
+
...createDefaultActions("STELLAR", service, getStore),
|
|
2541
|
+
signMessage: async (message) => {
|
|
2542
|
+
const res = await service.walletsKit.signMessage(message);
|
|
2543
|
+
return res.signedMessage;
|
|
2544
|
+
}
|
|
2545
|
+
}),
|
|
2546
|
+
createWalletProvider: (service, getStore) => {
|
|
2547
|
+
if (!service?.walletsKit) return void 0;
|
|
2548
|
+
const defaults = getEntryDefaults(
|
|
2549
|
+
getStore().walletConfig?.STELLAR?.chains?.[types.ChainKeys.STELLAR_MAINNET]
|
|
2550
|
+
);
|
|
2551
|
+
return new walletSdkCore.StellarWalletProvider({
|
|
2552
|
+
type: "BROWSER_EXTENSION",
|
|
2553
|
+
walletsKit: service.walletsKit,
|
|
2554
|
+
network: "PUBLIC",
|
|
2555
|
+
defaults
|
|
2556
|
+
});
|
|
2557
|
+
}
|
|
2558
|
+
}),
|
|
2559
|
+
// ICON: signMessage not implemented — Hana wallet does not expose a signing API.
|
|
2560
|
+
// connect/disconnect use createDefaultActions (no createActions override needed).
|
|
2561
|
+
ICON: defineChain2({
|
|
2562
|
+
createService: (walletConfig) => IconXService.getInstance(getRpcUrl(walletConfig?.ICON?.chains?.[types.ChainKeys.ICON_MAINNET])),
|
|
2563
|
+
displayName: "ICON",
|
|
2564
|
+
defaultConnectors: () => [new IconHanaXConnector()],
|
|
2565
|
+
providerManaged: false,
|
|
2566
|
+
createWalletProvider: (_service, getStore) => {
|
|
2567
|
+
const store = getStore();
|
|
2568
|
+
const address = store.xConnections.ICON?.xAccount.address;
|
|
2569
|
+
if (!address) return void 0;
|
|
2570
|
+
const chainInfo = CHAIN_INFO[1 /* MAINNET */];
|
|
2571
|
+
if (!chainInfo) throw new Error("ICON mainnet chain info not found");
|
|
2572
|
+
const defaults = getEntryDefaults(
|
|
2573
|
+
store.walletConfig?.ICON?.chains?.[types.ChainKeys.ICON_MAINNET]
|
|
2574
|
+
);
|
|
2575
|
+
return new walletSdkCore.IconWalletProvider({
|
|
2576
|
+
walletAddress: address,
|
|
2577
|
+
rpcUrl: chainInfo.APIEndpoint,
|
|
2578
|
+
defaults
|
|
2579
|
+
});
|
|
2580
|
+
}
|
|
2581
|
+
}),
|
|
2582
|
+
NEAR: defineChain2({
|
|
2583
|
+
createService: (walletConfig) => NearXService.getInstance(getRpcUrl(walletConfig?.NEAR?.chains?.[types.ChainKeys.NEAR_MAINNET])),
|
|
2584
|
+
displayName: "NEAR",
|
|
2585
|
+
defaultConnectors: () => [],
|
|
2586
|
+
providerManaged: false,
|
|
2587
|
+
discoverConnectors: async (service, getStore) => {
|
|
2588
|
+
await service.walletSelector.whenManifestLoaded;
|
|
2589
|
+
const connectors = service.walletSelector.availableWallets.map((w) => new NearXConnector(w));
|
|
2590
|
+
service.setXConnectors(connectors);
|
|
2591
|
+
getStore().setXConnectors("NEAR", connectors);
|
|
2592
|
+
},
|
|
2593
|
+
createActions: (service, getStore) => ({
|
|
2594
|
+
...createDefaultActions("NEAR", service, getStore),
|
|
2595
|
+
disconnect: async () => {
|
|
2596
|
+
try {
|
|
2597
|
+
service.walletSelector.disconnect();
|
|
2598
|
+
} finally {
|
|
2599
|
+
getStore().unsetXConnection("NEAR");
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
}),
|
|
2603
|
+
createWalletProvider: (service, getStore) => {
|
|
2604
|
+
if (!service?.walletSelector) return void 0;
|
|
2605
|
+
const defaults = getEntryDefaults(
|
|
2606
|
+
getStore().walletConfig?.NEAR?.chains?.[types.ChainKeys.NEAR_MAINNET]
|
|
2607
|
+
);
|
|
2608
|
+
return new walletSdkCore.NearWalletProvider({ wallet: service.walletSelector, defaults });
|
|
2609
|
+
}
|
|
2610
|
+
}),
|
|
2611
|
+
STACKS: defineChain2({
|
|
2612
|
+
createService: (walletConfig) => StacksXService.getInstance(walletConfig?.STACKS?.chains?.[types.ChainKeys.STACKS_MAINNET]),
|
|
2613
|
+
displayName: "Stacks",
|
|
2614
|
+
defaultConnectors: () => STACKS_PROVIDERS.map((c) => new StacksXConnector(c)),
|
|
2615
|
+
providerManaged: false,
|
|
2616
|
+
createWalletProvider: (service, getStore) => {
|
|
2617
|
+
const store = getStore();
|
|
2618
|
+
const connection = store.xConnections.STACKS;
|
|
2619
|
+
const address = connection?.xAccount.address;
|
|
2620
|
+
if (!address) return void 0;
|
|
2621
|
+
const connector = connection?.xConnectorId ? service.getXConnectorById(connection.xConnectorId) : void 0;
|
|
2622
|
+
const provider = connector instanceof StacksXConnector ? connector.getProvider() : void 0;
|
|
2623
|
+
const defaults = getEntryDefaults(
|
|
2624
|
+
store.walletConfig?.STACKS?.chains?.[types.ChainKeys.STACKS_MAINNET]
|
|
2625
|
+
);
|
|
2626
|
+
return new walletSdkCore.StacksWalletProvider({ address, provider, defaults });
|
|
2627
|
+
}
|
|
2628
|
+
})
|
|
2629
|
+
};
|
|
2630
|
+
var createChainServices = (walletConfig, getStore) => {
|
|
1292
2631
|
const xServices = {};
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
case "INJECTIVE":
|
|
1315
|
-
xServices[xChainType] = InjectiveXService.getInstance();
|
|
1316
|
-
xServices[xChainType].setXConnectors([
|
|
1317
|
-
// EVM wallets (auto-detected via EIP-6963)
|
|
1318
|
-
new InjectiveXConnector("MetaMask", walletBase.Wallet.Metamask),
|
|
1319
|
-
// Cosmos wallets (detected via window globals)
|
|
1320
|
-
new InjectiveXConnector("Keplr", walletBase.Wallet.Keplr),
|
|
1321
|
-
new InjectiveXConnector("Leap", walletBase.Wallet.Leap)
|
|
1322
|
-
]);
|
|
1323
|
-
break;
|
|
1324
|
-
case "STELLAR":
|
|
1325
|
-
xServices[xChainType] = StellarXService.getInstance();
|
|
1326
|
-
xServices[xChainType].setXConnectors([]);
|
|
1327
|
-
break;
|
|
1328
|
-
case "ICON":
|
|
1329
|
-
xServices[xChainType] = IconXService.getInstance();
|
|
1330
|
-
xServices[xChainType].setXConnectors([new IconHanaXConnector()]);
|
|
1331
|
-
break;
|
|
1332
|
-
case "NEAR":
|
|
1333
|
-
xServices[xChainType] = NearXService.getInstance();
|
|
1334
|
-
xServices[xChainType].setXConnectors([]);
|
|
1335
|
-
break;
|
|
1336
|
-
case "STACKS":
|
|
1337
|
-
xServices[xChainType] = StacksXService.getInstance();
|
|
1338
|
-
xServices[xChainType].setXConnectors(STACKS_PROVIDERS.map((config) => new StacksXConnector(config)));
|
|
1339
|
-
break;
|
|
2632
|
+
const xConnectorsByChain = {};
|
|
2633
|
+
const enabledChains = [];
|
|
2634
|
+
const chainActions = {};
|
|
2635
|
+
for (const chainType of types.ChainTypeArr) {
|
|
2636
|
+
if (!hasChainOfType(chainType, walletConfig)) continue;
|
|
2637
|
+
const factory = chainRegistry[chainType];
|
|
2638
|
+
if (!factory) continue;
|
|
2639
|
+
const service = factory.createService(walletConfig);
|
|
2640
|
+
xServices[chainType] = service;
|
|
2641
|
+
enabledChains.push(chainType);
|
|
2642
|
+
if (!factory.providerManaged) {
|
|
2643
|
+
const override = readConnectorsOverride(chainType, walletConfig);
|
|
2644
|
+
const connectors = override ? narrowConnectors(override, chainType) : factory.defaultConnectors(walletConfig);
|
|
2645
|
+
service.setXConnectors(connectors);
|
|
2646
|
+
xConnectorsByChain[chainType] = connectors;
|
|
2647
|
+
chainActions[chainType] = factory.createActions ? factory.createActions(service, getStore) : createDefaultActions(chainType, service, getStore);
|
|
2648
|
+
if (factory.discoverConnectors) {
|
|
2649
|
+
factory.discoverConnectors(service, getStore).catch((err) => {
|
|
2650
|
+
console.warn(`[wallet-sdk-react] discoverConnectors failed for ${chainType}:`, err);
|
|
2651
|
+
});
|
|
2652
|
+
}
|
|
1340
2653
|
}
|
|
1341
|
-
}
|
|
1342
|
-
return xServices;
|
|
2654
|
+
}
|
|
2655
|
+
return { xServices, xConnectorsByChain, enabledChains, chainActions };
|
|
1343
2656
|
};
|
|
1344
|
-
|
|
2657
|
+
|
|
2658
|
+
// src/useXWalletStore.ts
|
|
2659
|
+
var useXWalletStore = zustand.create()(
|
|
1345
2660
|
middleware.devtools(
|
|
1346
2661
|
middleware.persist(
|
|
1347
2662
|
immer.immer((set, get) => ({
|
|
1348
|
-
xServices:
|
|
2663
|
+
xServices: {},
|
|
1349
2664
|
xConnections: {},
|
|
2665
|
+
xConnectorsByChain: {},
|
|
2666
|
+
enabledChains: [],
|
|
2667
|
+
chainActions: {},
|
|
2668
|
+
walletProviders: {},
|
|
2669
|
+
walletConfig: void 0,
|
|
2670
|
+
userDisconnected: {},
|
|
1350
2671
|
setXConnection: (xChainType, xConnection) => {
|
|
1351
2672
|
set((state) => {
|
|
1352
2673
|
state.xConnections[xChainType] = xConnection;
|
|
1353
2674
|
});
|
|
2675
|
+
const factory = chainRegistry[xChainType]?.createWalletProvider;
|
|
2676
|
+
if (factory) {
|
|
2677
|
+
const service = get().xServices[xChainType];
|
|
2678
|
+
if (service) {
|
|
2679
|
+
const provider = factory(service, () => get());
|
|
2680
|
+
get().setWalletProvider(xChainType, provider);
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
1354
2683
|
},
|
|
1355
2684
|
unsetXConnection: (xChainType) => {
|
|
1356
2685
|
set((state) => {
|
|
1357
2686
|
delete state.xConnections[xChainType];
|
|
2687
|
+
delete state.walletProviders[xChainType];
|
|
2688
|
+
});
|
|
2689
|
+
},
|
|
2690
|
+
setXConnectors: (xChainType, connectors) => {
|
|
2691
|
+
set((state) => {
|
|
2692
|
+
state.xConnectorsByChain[xChainType] = connectors;
|
|
2693
|
+
});
|
|
2694
|
+
},
|
|
2695
|
+
registerChainActions: (xChainType, actions) => {
|
|
2696
|
+
set((state) => {
|
|
2697
|
+
state.chainActions[xChainType] = actions;
|
|
2698
|
+
});
|
|
2699
|
+
},
|
|
2700
|
+
setWalletProvider: (xChainType, provider) => {
|
|
2701
|
+
set((state) => {
|
|
2702
|
+
if (provider) {
|
|
2703
|
+
state.walletProviders[xChainType] = provider;
|
|
2704
|
+
} else {
|
|
2705
|
+
delete state.walletProviders[xChainType];
|
|
2706
|
+
}
|
|
2707
|
+
});
|
|
2708
|
+
},
|
|
2709
|
+
getWalletProvider: (xChainType) => {
|
|
2710
|
+
if (!xChainType) return void 0;
|
|
2711
|
+
return get().walletProviders[xChainType];
|
|
2712
|
+
},
|
|
2713
|
+
initChainServices: (walletConfig) => {
|
|
2714
|
+
const result = createChainServices(walletConfig, () => get());
|
|
2715
|
+
set((state) => {
|
|
2716
|
+
state.xServices = result.xServices;
|
|
2717
|
+
state.enabledChains = result.enabledChains;
|
|
2718
|
+
Object.assign(state.xConnectorsByChain, result.xConnectorsByChain);
|
|
2719
|
+
Object.assign(state.chainActions, result.chainActions);
|
|
2720
|
+
});
|
|
2721
|
+
set({ walletConfig });
|
|
2722
|
+
},
|
|
2723
|
+
cleanupDisabledConnections: () => {
|
|
2724
|
+
set((state) => {
|
|
2725
|
+
for (const chainType of types.ChainTypeArr) {
|
|
2726
|
+
if (state.xConnections[chainType] && !state.enabledChains.includes(chainType)) {
|
|
2727
|
+
delete state.xConnections[chainType];
|
|
2728
|
+
delete state.walletProviders[chainType];
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
});
|
|
2732
|
+
},
|
|
2733
|
+
markUserDisconnected: (xChainType) => {
|
|
2734
|
+
set((state) => {
|
|
2735
|
+
state.userDisconnected[xChainType] = true;
|
|
2736
|
+
});
|
|
2737
|
+
},
|
|
2738
|
+
clearUserDisconnected: (xChainType) => {
|
|
2739
|
+
set((state) => {
|
|
2740
|
+
delete state.userDisconnected[xChainType];
|
|
1358
2741
|
});
|
|
1359
2742
|
}
|
|
1360
2743
|
})),
|
|
1361
2744
|
{
|
|
2745
|
+
// key kept as 'xwagmi-store' for backward compat — existing users won't lose persisted connections on upgrade
|
|
1362
2746
|
name: "xwagmi-store",
|
|
1363
2747
|
storage: middleware.createJSONStorage(() => localStorage),
|
|
1364
|
-
partialize: (state) => ({
|
|
2748
|
+
partialize: (state) => ({
|
|
2749
|
+
xConnections: state.xConnections,
|
|
2750
|
+
userDisconnected: state.userDisconnected
|
|
2751
|
+
})
|
|
1365
2752
|
}
|
|
1366
2753
|
),
|
|
1367
2754
|
{ name: "xwagmi-store" }
|
|
1368
2755
|
)
|
|
1369
2756
|
);
|
|
1370
2757
|
|
|
1371
|
-
// src/
|
|
1372
|
-
function
|
|
1373
|
-
const
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
const solanaWallet = walletAdapterReact.useWallet();
|
|
1379
|
-
const xConnection2 = React2.useMemo(() => {
|
|
1380
|
-
if (!xChainType) {
|
|
1381
|
-
return void 0;
|
|
1382
|
-
}
|
|
1383
|
-
switch (xChainType) {
|
|
1384
|
-
case "EVM":
|
|
1385
|
-
return {
|
|
1386
|
-
xAccount: { address: evmAddress, xChainType },
|
|
1387
|
-
xConnectorId: evmConnections?.[0]?.connector.id
|
|
1388
|
-
};
|
|
1389
|
-
case "SUI":
|
|
1390
|
-
if (suiCurrentWallet.currentWallet && suiCurrentWallet.connectionStatus === "connected") {
|
|
1391
|
-
return {
|
|
1392
|
-
xAccount: { address: suiAccount?.address, xChainType },
|
|
1393
|
-
xConnectorId: suiCurrentWallet.currentWallet.name
|
|
1394
|
-
};
|
|
1395
|
-
}
|
|
1396
|
-
return void 0;
|
|
1397
|
-
case "SOLANA":
|
|
1398
|
-
if (solanaWallet.connected) {
|
|
1399
|
-
return {
|
|
1400
|
-
xAccount: { address: solanaWallet.publicKey?.toString(), xChainType },
|
|
1401
|
-
xConnectorId: `${solanaWallet.wallet?.adapter.name}`
|
|
1402
|
-
};
|
|
1403
|
-
}
|
|
1404
|
-
return void 0;
|
|
1405
|
-
default:
|
|
1406
|
-
return xConnection;
|
|
1407
|
-
}
|
|
1408
|
-
}, [xChainType, xConnection, evmAddress, suiAccount, evmConnections, suiCurrentWallet, solanaWallet]);
|
|
1409
|
-
return xConnection2;
|
|
1410
|
-
}
|
|
1411
|
-
|
|
1412
|
-
// src/hooks/useXAccount.ts
|
|
1413
|
-
function isChainType(chainIdentifier) {
|
|
1414
|
-
return types.ChainTypeArr.includes(chainIdentifier);
|
|
1415
|
-
}
|
|
1416
|
-
function useXAccount(chainIdentifier) {
|
|
1417
|
-
const resolvedChainType = chainIdentifier ? isChainType(chainIdentifier) ? chainIdentifier : getXChainType(chainIdentifier) : void 0;
|
|
1418
|
-
const xConnection = useXConnection(resolvedChainType);
|
|
1419
|
-
const xAccount = React2.useMemo(() => {
|
|
1420
|
-
if (!resolvedChainType) {
|
|
1421
|
-
return {
|
|
1422
|
-
address: void 0,
|
|
1423
|
-
xChainType: void 0
|
|
1424
|
-
};
|
|
1425
|
-
}
|
|
1426
|
-
return xConnection?.xAccount || { address: void 0, xChainType: resolvedChainType };
|
|
1427
|
-
}, [resolvedChainType, xConnection]);
|
|
1428
|
-
return xAccount;
|
|
2758
|
+
// src/actions/getXService.ts
|
|
2759
|
+
function getXService(xChainType) {
|
|
2760
|
+
const service = useXWalletStore.getState().xServices[xChainType];
|
|
2761
|
+
if (!service) {
|
|
2762
|
+
throw new Error(`XService for chain type "${xChainType}" is not initialized. Is the chain enabled in config?`);
|
|
2763
|
+
}
|
|
2764
|
+
return service;
|
|
1429
2765
|
}
|
|
1430
|
-
|
|
1431
|
-
const
|
|
1432
|
-
const
|
|
1433
|
-
const { address
|
|
1434
|
-
const
|
|
1435
|
-
const
|
|
1436
|
-
const
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
xChainType
|
|
1446
|
-
};
|
|
1447
|
-
}
|
|
1448
|
-
}
|
|
1449
|
-
if (evmAddress) {
|
|
1450
|
-
result["EVM"] = {
|
|
1451
|
-
address: evmAddress,
|
|
1452
|
-
xChainType: "EVM"
|
|
1453
|
-
};
|
|
1454
|
-
}
|
|
1455
|
-
if (suiAccount) {
|
|
1456
|
-
result["SUI"] = {
|
|
1457
|
-
address: suiAccount.address,
|
|
1458
|
-
xChainType: "SUI"
|
|
1459
|
-
};
|
|
1460
|
-
}
|
|
1461
|
-
if (solanaWallet.publicKey) {
|
|
1462
|
-
result["SOLANA"] = {
|
|
1463
|
-
address: solanaWallet.publicKey.toString(),
|
|
1464
|
-
xChainType: "SOLANA"
|
|
1465
|
-
};
|
|
2766
|
+
var EvmHydrator = () => {
|
|
2767
|
+
const wagmiConfig = wagmi.useConfig();
|
|
2768
|
+
const connectors = wagmi.useConnectors();
|
|
2769
|
+
const { address, status, connector } = wagmi.useAccount();
|
|
2770
|
+
const evmPublicClient = wagmi.usePublicClient();
|
|
2771
|
+
const { data: evmWalletClient } = wagmi.useWalletClient();
|
|
2772
|
+
const setXConnection = useXWalletStore((state) => state.setXConnection);
|
|
2773
|
+
const unsetXConnection = useXWalletStore((state) => state.unsetXConnection);
|
|
2774
|
+
const setWalletProvider = useXWalletStore((state) => state.setWalletProvider);
|
|
2775
|
+
const userDisconnectedEvm = useXWalletStore((state) => state.userDisconnected.EVM);
|
|
2776
|
+
const { reconnect } = wagmi.useReconnect();
|
|
2777
|
+
const walletConfig = useWalletConfig();
|
|
2778
|
+
react.useEffect(() => {
|
|
2779
|
+
if (wagmiConfig) {
|
|
2780
|
+
EvmXService.getInstance().wagmiConfig = wagmiConfig;
|
|
1466
2781
|
}
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
const
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
2782
|
+
}, [wagmiConfig]);
|
|
2783
|
+
const evmConnectors = react.useMemo(() => connectors.map((c) => new EvmXConnector(c)), [connectors]);
|
|
2784
|
+
react.useEffect(() => {
|
|
2785
|
+
EvmXService.getInstance().setXConnectors(evmConnectors);
|
|
2786
|
+
useXWalletStore.getState().setXConnectors("EVM", evmConnectors);
|
|
2787
|
+
}, [evmConnectors]);
|
|
2788
|
+
const [hydrated, setHydrated] = react.useState(() => useXWalletStore.persist.hasHydrated());
|
|
2789
|
+
react.useEffect(() => {
|
|
2790
|
+
if (hydrated) return;
|
|
2791
|
+
const unsub = useXWalletStore.persist.onFinishHydration(() => setHydrated(true));
|
|
2792
|
+
return unsub;
|
|
2793
|
+
}, [hydrated]);
|
|
2794
|
+
react.useEffect(() => {
|
|
2795
|
+
if (!hydrated) return;
|
|
2796
|
+
if (status !== "disconnected") return;
|
|
2797
|
+
const state = useXWalletStore.getState();
|
|
2798
|
+
if (!state.xConnections.EVM) return;
|
|
2799
|
+
if (state.userDisconnected.EVM) return;
|
|
2800
|
+
reconnect();
|
|
2801
|
+
}, [hydrated, connectors, status, reconnect]);
|
|
2802
|
+
const wasConnectedRef = react.useRef(false);
|
|
2803
|
+
react.useEffect(() => {
|
|
2804
|
+
if (status === "connecting" || status === "reconnecting") return;
|
|
2805
|
+
if (status === "connected" && address && connector) {
|
|
2806
|
+
if (userDisconnectedEvm) return;
|
|
2807
|
+
wasConnectedRef.current = true;
|
|
2808
|
+
setXConnection("EVM", {
|
|
2809
|
+
xAccount: { address, xChainType: "EVM" },
|
|
2810
|
+
xConnectorId: connector.id
|
|
2811
|
+
});
|
|
2812
|
+
} else if (status === "disconnected" && wasConnectedRef.current) {
|
|
2813
|
+
wasConnectedRef.current = false;
|
|
2814
|
+
unsetXConnection("EVM");
|
|
2815
|
+
}
|
|
2816
|
+
}, [address, status, connector, userDisconnectedEvm, setXConnection, unsetXConnection]);
|
|
2817
|
+
const walletProvider = react.useMemo(() => {
|
|
2818
|
+
if (!evmPublicClient || !evmWalletClient) return void 0;
|
|
2819
|
+
if (userDisconnectedEvm) return void 0;
|
|
2820
|
+
const defaults = resolveEvmDefaults(evmWalletClient.chain.id, walletConfig.EVM?.chains);
|
|
2821
|
+
return new walletSdkCore.EvmWalletProvider({
|
|
2822
|
+
walletClient: evmWalletClient,
|
|
2823
|
+
publicClient: evmPublicClient,
|
|
2824
|
+
defaults
|
|
2825
|
+
});
|
|
2826
|
+
}, [evmPublicClient, evmWalletClient, walletConfig.EVM?.chains, userDisconnectedEvm]);
|
|
2827
|
+
react.useEffect(() => {
|
|
2828
|
+
setWalletProvider("EVM", walletProvider);
|
|
2829
|
+
}, [walletProvider, setWalletProvider]);
|
|
2830
|
+
return null;
|
|
2831
|
+
};
|
|
2832
|
+
var EvmActions = () => {
|
|
2833
|
+
const wagmiConfig = wagmi.useConfig();
|
|
2834
|
+
const { connectAsync } = wagmi.useConnect();
|
|
2835
|
+
const { disconnectAsync } = wagmi.useDisconnect();
|
|
2836
|
+
const { signMessageAsync } = wagmi.useSignMessage();
|
|
2837
|
+
const registerChainActions = useXWalletStore((state) => state.registerChainActions);
|
|
2838
|
+
const connectRef = react.useRef(connectAsync);
|
|
2839
|
+
const disconnectRef = react.useRef(disconnectAsync);
|
|
2840
|
+
const signMessageRef = react.useRef(signMessageAsync);
|
|
2841
|
+
const wagmiConfigRef = react.useRef(wagmiConfig);
|
|
2842
|
+
react.useEffect(() => {
|
|
2843
|
+
connectRef.current = connectAsync;
|
|
2844
|
+
disconnectRef.current = disconnectAsync;
|
|
2845
|
+
signMessageRef.current = signMessageAsync;
|
|
2846
|
+
wagmiConfigRef.current = wagmiConfig;
|
|
2847
|
+
}, [connectAsync, disconnectAsync, signMessageAsync, wagmiConfig]);
|
|
2848
|
+
react.useEffect(() => {
|
|
2849
|
+
registerChainActions("EVM", {
|
|
2850
|
+
connect: async (xConnectorId) => {
|
|
2851
|
+
const connector = wagmiConfigRef.current.connectors.find((c) => c.id === xConnectorId);
|
|
2852
|
+
if (!connector) {
|
|
2853
|
+
console.warn(
|
|
2854
|
+
`[EvmActions] connect: connector "${xConnectorId}" not found in wagmi config`,
|
|
2855
|
+
wagmiConfigRef.current.connectors.map((c) => c.id)
|
|
2856
|
+
);
|
|
2857
|
+
return void 0;
|
|
2858
|
+
}
|
|
2859
|
+
useXWalletStore.getState().clearUserDisconnected("EVM");
|
|
2860
|
+
try {
|
|
2861
|
+
await connectRef.current({ connector });
|
|
2862
|
+
} catch (error) {
|
|
2863
|
+
if (error instanceof Error && error.name === "ConnectorAlreadyConnectedError") {
|
|
2864
|
+
return void 0;
|
|
1518
2865
|
}
|
|
1519
|
-
|
|
2866
|
+
throw error;
|
|
2867
|
+
}
|
|
2868
|
+
return void 0;
|
|
2869
|
+
},
|
|
2870
|
+
disconnect: async () => {
|
|
2871
|
+
const store = useXWalletStore.getState();
|
|
2872
|
+
store.unsetXConnection("EVM");
|
|
2873
|
+
store.markUserDisconnected("EVM");
|
|
2874
|
+
try {
|
|
2875
|
+
await disconnectRef.current();
|
|
2876
|
+
} catch (error) {
|
|
2877
|
+
console.warn("[EvmActions] wagmi disconnect failed (zustand already cleared):", error);
|
|
1520
2878
|
}
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
2879
|
+
},
|
|
2880
|
+
getConnectors: () => useXWalletStore.getState().xConnectorsByChain.EVM ?? [],
|
|
2881
|
+
getConnection: () => useXWalletStore.getState().xConnections.EVM,
|
|
2882
|
+
signMessage: async (message) => {
|
|
2883
|
+
const signature = await signMessageRef.current({ message });
|
|
2884
|
+
return signature;
|
|
1524
2885
|
}
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
2886
|
+
});
|
|
2887
|
+
}, [registerChainActions]);
|
|
2888
|
+
return null;
|
|
2889
|
+
};
|
|
2890
|
+
var EvmProvider = ({ children, config }) => {
|
|
2891
|
+
const reconnectOnMount = config.reconnectOnMount ?? EVM_DEFAULT_RECONNECT_ON_MOUNT;
|
|
2892
|
+
const ssr = config.ssr ?? EVM_DEFAULT_SSR;
|
|
2893
|
+
const queryClientRef = react.useRef(null);
|
|
2894
|
+
if (!queryClientRef.current) {
|
|
2895
|
+
queryClientRef.current = new reactQuery.QueryClient();
|
|
2896
|
+
}
|
|
2897
|
+
const walletConnectConfig = config.walletConnect;
|
|
2898
|
+
const wagmiConfig = react.useMemo(() => {
|
|
2899
|
+
const connectors$1 = [];
|
|
2900
|
+
if (walletConnectConfig) {
|
|
2901
|
+
if (walletConnectConfig.projectId) {
|
|
2902
|
+
connectors$1.push(connectors.walletConnect({ showQrModal: true, ...walletConnectConfig }));
|
|
2903
|
+
} else {
|
|
2904
|
+
console.warn("[wallet-sdk-react] walletConnect.projectId is required \u2014 WalletConnect connector skipped.");
|
|
1530
2905
|
}
|
|
1531
|
-
return xAccount;
|
|
1532
2906
|
}
|
|
1533
|
-
|
|
1534
|
-
}
|
|
2907
|
+
return createWagmiConfig(config.chains, { ssr, connectors: connectors$1 });
|
|
2908
|
+
}, [config.chains, reconnectOnMount, ssr, walletConnectConfig]);
|
|
2909
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClientRef.current, children: /* @__PURE__ */ jsxRuntime.jsxs(wagmi.WagmiProvider, { reconnectOnMount, config: wagmiConfig, initialState: config.initialState, children: [
|
|
2910
|
+
/* @__PURE__ */ jsxRuntime.jsx(EvmHydrator, {}),
|
|
2911
|
+
/* @__PURE__ */ jsxRuntime.jsx(EvmActions, {}),
|
|
2912
|
+
children
|
|
2913
|
+
] }) });
|
|
2914
|
+
};
|
|
1535
2915
|
|
|
1536
2916
|
// src/xchains/solana/SolanaXConnector.ts
|
|
1537
2917
|
var SolanaXConnector = class extends XConnector {
|
|
2918
|
+
wallet;
|
|
1538
2919
|
constructor(wallet) {
|
|
1539
2920
|
super("SOLANA", wallet?.adapter.name, wallet?.adapter.name);
|
|
1540
2921
|
this.wallet = wallet;
|
|
@@ -1550,598 +2931,407 @@ var SolanaXConnector = class extends XConnector {
|
|
|
1550
2931
|
get icon() {
|
|
1551
2932
|
return this.wallet?.adapter.icon;
|
|
1552
2933
|
}
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
return reactQuery.useQuery({
|
|
1557
|
-
queryKey: ["stellar-wallets", xService],
|
|
1558
|
-
queryFn: async () => {
|
|
1559
|
-
if (!xService) {
|
|
1560
|
-
return [];
|
|
1561
|
-
}
|
|
1562
|
-
const wallets = await xService.walletsKit.getSupportedWallets();
|
|
1563
|
-
return wallets.filter((wallet) => wallet.isAvailable).map((wallet) => new StellarWalletsKitXConnector(wallet));
|
|
1564
|
-
}
|
|
1565
|
-
});
|
|
1566
|
-
};
|
|
1567
|
-
|
|
1568
|
-
// src/hooks/useXService.ts
|
|
1569
|
-
function useXService(xChainType) {
|
|
1570
|
-
const xService = useXWagmiStore((state) => xChainType ? state.xServices[xChainType] : void 0);
|
|
1571
|
-
return xService;
|
|
1572
|
-
}
|
|
1573
|
-
|
|
1574
|
-
// src/xchains/near/NearXConnector.ts
|
|
1575
|
-
var NearXConnector = class extends XConnector {
|
|
1576
|
-
constructor(wallet) {
|
|
1577
|
-
super("NEAR", wallet.manifest.name, wallet.manifest.id);
|
|
1578
|
-
this._wallet = wallet;
|
|
1579
|
-
}
|
|
1580
|
-
getXService() {
|
|
1581
|
-
return NearXService.getInstance();
|
|
1582
|
-
}
|
|
1583
|
-
async connect() {
|
|
1584
|
-
const walletSelector = this.getXService().walletSelector;
|
|
1585
|
-
const wallet = await walletSelector.connect({ walletId: this._wallet.manifest.id });
|
|
1586
|
-
const accounts = await wallet.getAccounts();
|
|
1587
|
-
if (accounts.length === 0 || accounts[0] === void 0) {
|
|
1588
|
-
return void 0;
|
|
1589
|
-
}
|
|
1590
|
-
return {
|
|
1591
|
-
address: accounts[0].accountId,
|
|
1592
|
-
xChainType: this.xChainType
|
|
1593
|
-
};
|
|
1594
|
-
}
|
|
1595
|
-
async disconnect() {
|
|
1596
|
-
const walletSelector = this.getXService().walletSelector;
|
|
1597
|
-
await walletSelector.disconnect(this._wallet);
|
|
2934
|
+
get isInstalled() {
|
|
2935
|
+
const state = this.wallet?.readyState;
|
|
2936
|
+
return state === "Installed" || state === "Loadable";
|
|
1598
2937
|
}
|
|
1599
|
-
get
|
|
1600
|
-
return this.
|
|
2938
|
+
get installUrl() {
|
|
2939
|
+
return this.wallet?.adapter.url;
|
|
1601
2940
|
}
|
|
1602
2941
|
};
|
|
1603
2942
|
|
|
1604
|
-
// src/
|
|
1605
|
-
var
|
|
1606
|
-
const
|
|
1607
|
-
return reactQuery.useQuery({
|
|
1608
|
-
queryKey: ["near-wallets"],
|
|
1609
|
-
queryFn: async () => {
|
|
1610
|
-
if (!xService) {
|
|
1611
|
-
return [];
|
|
1612
|
-
}
|
|
1613
|
-
await xService.walletSelector.whenManifestLoaded;
|
|
1614
|
-
const wallets = xService.walletSelector.availableWallets;
|
|
1615
|
-
return wallets.map((wallet) => new NearXConnector(wallet));
|
|
1616
|
-
}
|
|
1617
|
-
});
|
|
1618
|
-
};
|
|
1619
|
-
|
|
1620
|
-
// src/hooks/useXConnectors.ts
|
|
1621
|
-
function useXConnectors(xChainType) {
|
|
1622
|
-
const xService = useXService(xChainType);
|
|
1623
|
-
const evmConnectors = wagmi.useConnectors();
|
|
1624
|
-
const suiWallets = dappKit.useWallets();
|
|
1625
|
-
const { data: stellarXConnectors } = useStellarXConnectors();
|
|
1626
|
-
const { data: nearXConnectors } = useNearXConnectors();
|
|
1627
|
-
const stacksXConnectors = useStacksXConnectors();
|
|
1628
|
-
const { wallets: solanaWallets } = walletAdapterReact.useWallet();
|
|
1629
|
-
const xConnectors = React2.useMemo(() => {
|
|
1630
|
-
if (!xChainType || !xService) {
|
|
1631
|
-
return [];
|
|
1632
|
-
}
|
|
1633
|
-
switch (xChainType) {
|
|
1634
|
-
case "EVM":
|
|
1635
|
-
return evmConnectors.map((connector) => new EvmXConnector(connector));
|
|
1636
|
-
case "SUI":
|
|
1637
|
-
return suiWallets.map((wallet) => new SuiXConnector(wallet));
|
|
1638
|
-
case "STELLAR":
|
|
1639
|
-
return stellarXConnectors || [];
|
|
1640
|
-
case "SOLANA":
|
|
1641
|
-
return solanaWallets.filter((wallet) => wallet.readyState === "Installed").map((wallet) => new SolanaXConnector(wallet));
|
|
1642
|
-
case "NEAR":
|
|
1643
|
-
return nearXConnectors || [];
|
|
1644
|
-
case "STACKS":
|
|
1645
|
-
return stacksXConnectors;
|
|
1646
|
-
default:
|
|
1647
|
-
return xService.getXConnectors();
|
|
1648
|
-
}
|
|
1649
|
-
}, [
|
|
1650
|
-
xService,
|
|
1651
|
-
xChainType,
|
|
1652
|
-
evmConnectors,
|
|
1653
|
-
suiWallets,
|
|
1654
|
-
stellarXConnectors,
|
|
1655
|
-
solanaWallets,
|
|
1656
|
-
nearXConnectors,
|
|
1657
|
-
stacksXConnectors
|
|
1658
|
-
]);
|
|
1659
|
-
return xConnectors;
|
|
1660
|
-
}
|
|
1661
|
-
function useXDisconnect() {
|
|
1662
|
-
const xConnections = useXWagmiStore((state) => state.xConnections);
|
|
1663
|
-
const unsetXConnection = useXWagmiStore((state) => state.unsetXConnection);
|
|
1664
|
-
const { disconnectAsync } = wagmi.useDisconnect();
|
|
1665
|
-
const { mutateAsync: suiDisconnectAsync } = dappKit.useDisconnectWallet();
|
|
2943
|
+
// src/providers/solana/SolanaHydrator.tsx
|
|
2944
|
+
var SolanaHydrator = () => {
|
|
2945
|
+
const { connection } = walletAdapterReact.useConnection();
|
|
1666
2946
|
const solanaWallet = walletAdapterReact.useWallet();
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
case "SUI":
|
|
1674
|
-
await suiDisconnectAsync();
|
|
1675
|
-
break;
|
|
1676
|
-
case "SOLANA":
|
|
1677
|
-
await solanaWallet.disconnect();
|
|
1678
|
-
break;
|
|
1679
|
-
case "NEAR": {
|
|
1680
|
-
const nearXService = getXService("NEAR");
|
|
1681
|
-
nearXService.walletSelector.disconnect();
|
|
1682
|
-
break;
|
|
1683
|
-
}
|
|
1684
|
-
default: {
|
|
1685
|
-
const xService = getXService(xChainType);
|
|
1686
|
-
const xConnectorId = xConnections[xChainType]?.xConnectorId;
|
|
1687
|
-
const xConnector = xConnectorId ? xService.getXConnectorById(xConnectorId) : void 0;
|
|
1688
|
-
await xConnector?.disconnect();
|
|
1689
|
-
break;
|
|
1690
|
-
}
|
|
1691
|
-
}
|
|
1692
|
-
unsetXConnection(xChainType);
|
|
1693
|
-
},
|
|
1694
|
-
[xConnections, unsetXConnection, disconnectAsync, suiDisconnectAsync, solanaWallet]
|
|
2947
|
+
const setXConnection = useXWalletStore((state) => state.setXConnection);
|
|
2948
|
+
const unsetXConnection = useXWalletStore((state) => state.unsetXConnection);
|
|
2949
|
+
const setWalletProvider = useXWalletStore((state) => state.setWalletProvider);
|
|
2950
|
+
const walletConfig = useWalletConfig();
|
|
2951
|
+
const solanaDefaults = getEntryDefaults(
|
|
2952
|
+
walletConfig.SOLANA?.chains?.[types.ChainKeys.SOLANA_MAINNET]
|
|
1695
2953
|
);
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
queryKey: ["xBalances", xChainId, xTokens.map((x) => x.symbol), address],
|
|
1705
|
-
queryFn: async () => {
|
|
1706
|
-
if (!xService) {
|
|
1707
|
-
return {};
|
|
1708
|
-
}
|
|
1709
|
-
const balances = await xService.getBalances(address, xTokens);
|
|
1710
|
-
return balances;
|
|
1711
|
-
},
|
|
1712
|
-
enabled: !!xService && !!address && (xTokens?.length ?? 0) > 0,
|
|
1713
|
-
refetchInterval: 5e3
|
|
2954
|
+
react.useEffect(() => {
|
|
2955
|
+
if (connection) {
|
|
2956
|
+
SolanaXService.getInstance().connection = connection;
|
|
2957
|
+
}
|
|
2958
|
+
}, [connection]);
|
|
2959
|
+
const solanaWalletRef = react.useRef(solanaWallet);
|
|
2960
|
+
react.useEffect(() => {
|
|
2961
|
+
solanaWalletRef.current = solanaWallet;
|
|
1714
2962
|
});
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
const [ethereumChainId, setEthereumChainId] = React2__default.default.useState(null);
|
|
1719
|
-
React2.useEffect(() => {
|
|
1720
|
-
if (!injectiveXService?.walletStrategy?.getWallet()) return;
|
|
1721
|
-
const walletStrategy = injectiveXService.walletStrategy;
|
|
1722
|
-
if (walletStrategy.getWallet() !== walletBase.Wallet.Metamask) return;
|
|
1723
|
-
const getEthereumChainId = async () => {
|
|
1724
|
-
try {
|
|
1725
|
-
const chainId = await walletStrategy.getEthereumChainId();
|
|
1726
|
-
setEthereumChainId(Number.parseInt(chainId));
|
|
1727
|
-
} catch (e) {
|
|
1728
|
-
console.warn("Failed to get Ethereum chain ID:", e);
|
|
1729
|
-
}
|
|
1730
|
-
};
|
|
1731
|
-
getEthereumChainId();
|
|
1732
|
-
try {
|
|
1733
|
-
walletStrategy.getStrategy().onChainIdChanged(getEthereumChainId);
|
|
1734
|
-
} catch (e) {
|
|
1735
|
-
console.warn("Failed to subscribe to chain ID changes:", e);
|
|
1736
|
-
}
|
|
1737
|
-
}, [injectiveXService?.walletStrategy]);
|
|
1738
|
-
return ethereumChainId;
|
|
1739
|
-
}
|
|
1740
|
-
var switchEthereumChain = async () => {
|
|
1741
|
-
const metamaskProvider = window.ethereum;
|
|
1742
|
-
return await Promise.race([
|
|
1743
|
-
metamaskProvider.request({
|
|
1744
|
-
method: "wallet_switchEthereumChain",
|
|
1745
|
-
params: [{ chainId: "0x1" }]
|
|
1746
|
-
}),
|
|
1747
|
-
new Promise(
|
|
1748
|
-
(resolve) => metamaskProvider.on("change", ({ chain }) => {
|
|
1749
|
-
if (chain?.id === 1) {
|
|
1750
|
-
resolve();
|
|
1751
|
-
}
|
|
1752
|
-
})
|
|
1753
|
-
)
|
|
1754
|
-
]);
|
|
1755
|
-
};
|
|
1756
|
-
var useEvmSwitchChain = (expectedXChainId) => {
|
|
1757
|
-
const xChainType = getXChainType(expectedXChainId);
|
|
1758
|
-
const expectedChainId = types.baseChainInfo[expectedXChainId].chainId;
|
|
1759
|
-
const injectiveXService = useXService("INJECTIVE");
|
|
1760
|
-
const ethereumChainId = useEthereumChainId();
|
|
1761
|
-
const { chainId } = wagmi.useAccount();
|
|
1762
|
-
const isWrongChain = React2.useMemo(() => {
|
|
1763
|
-
return xChainType === "EVM" && chainId !== expectedChainId || xChainType === "INJECTIVE" && injectiveXService && injectiveXService.walletStrategy.getWallet() === walletBase.Wallet.Metamask && ethereumChainId !== chains$1.mainnet.id;
|
|
1764
|
-
}, [xChainType, chainId, expectedChainId, ethereumChainId, injectiveXService]);
|
|
1765
|
-
const { switchChain } = wagmi.useSwitchChain();
|
|
1766
|
-
const handleSwitchChain = React2.useCallback(() => {
|
|
1767
|
-
if (xChainType === "INJECTIVE") {
|
|
1768
|
-
switchEthereumChain();
|
|
1769
|
-
} else {
|
|
1770
|
-
switchChain({ chainId: expectedChainId });
|
|
1771
|
-
}
|
|
1772
|
-
}, [switchChain, expectedChainId, xChainType]);
|
|
1773
|
-
return React2.useMemo(
|
|
1774
|
-
() => ({
|
|
1775
|
-
isWrongChain,
|
|
1776
|
-
handleSwitchChain
|
|
1777
|
-
}),
|
|
1778
|
-
[isWrongChain, handleSwitchChain]
|
|
2963
|
+
const solanaConnectors = react.useMemo(
|
|
2964
|
+
() => solanaWallet.wallets.filter((wallet) => wallet.readyState === "Installed").map((wallet) => new SolanaXConnector(wallet)),
|
|
2965
|
+
[solanaWallet.wallets]
|
|
1779
2966
|
);
|
|
2967
|
+
react.useEffect(() => {
|
|
2968
|
+
SolanaXService.getInstance().setXConnectors(solanaConnectors);
|
|
2969
|
+
useXWalletStore.getState().setXConnectors("SOLANA", solanaConnectors);
|
|
2970
|
+
}, [solanaConnectors]);
|
|
2971
|
+
const wasConnectedRef = react.useRef(!!useXWalletStore.getState().xConnections.SOLANA);
|
|
2972
|
+
react.useEffect(() => {
|
|
2973
|
+
if (solanaWallet.connected && solanaWallet.publicKey) {
|
|
2974
|
+
wasConnectedRef.current = true;
|
|
2975
|
+
setXConnection("SOLANA", {
|
|
2976
|
+
xAccount: { address: solanaWallet.publicKey.toString(), xChainType: "SOLANA" },
|
|
2977
|
+
xConnectorId: `${solanaWallet.wallet?.adapter.name}`
|
|
2978
|
+
});
|
|
2979
|
+
} else if (wasConnectedRef.current) {
|
|
2980
|
+
wasConnectedRef.current = false;
|
|
2981
|
+
unsetXConnection("SOLANA");
|
|
2982
|
+
}
|
|
2983
|
+
}, [solanaWallet.connected, solanaWallet.publicKey, solanaWallet.wallet, setXConnection, unsetXConnection]);
|
|
2984
|
+
const walletProvider = react.useMemo(() => {
|
|
2985
|
+
if (solanaWallet.connected && solanaWallet.publicKey && solanaWallet.wallet && connection) {
|
|
2986
|
+
return new walletSdkCore.SolanaWalletProvider({
|
|
2987
|
+
wallet: solanaWallet,
|
|
2988
|
+
endpoint: connection.rpcEndpoint,
|
|
2989
|
+
defaults: solanaDefaults
|
|
2990
|
+
});
|
|
2991
|
+
}
|
|
2992
|
+
return void 0;
|
|
2993
|
+
}, [solanaWallet.connected, solanaWallet.publicKey, solanaWallet.wallet, connection, solanaDefaults]);
|
|
2994
|
+
react.useEffect(() => {
|
|
2995
|
+
SolanaXService.getInstance().wallet = solanaWalletRef.current;
|
|
2996
|
+
setWalletProvider("SOLANA", walletProvider);
|
|
2997
|
+
}, [walletProvider, setWalletProvider]);
|
|
2998
|
+
return null;
|
|
1780
2999
|
};
|
|
1781
|
-
|
|
1782
|
-
const
|
|
1783
|
-
const
|
|
1784
|
-
const
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
return void 0;
|
|
1798
|
-
}
|
|
1799
|
-
return new walletSdkCore.EvmWalletProvider({
|
|
1800
|
-
walletClient: evmWalletClient,
|
|
1801
|
-
publicClient: evmPublicClient
|
|
1802
|
-
});
|
|
1803
|
-
}
|
|
1804
|
-
case "SUI": {
|
|
1805
|
-
const suiXService = xService;
|
|
1806
|
-
const { client, wallet, account } = {
|
|
1807
|
-
client: suiXService.suiClient,
|
|
1808
|
-
wallet: suiXService.suiWallet,
|
|
1809
|
-
account: suiXService.suiAccount
|
|
1810
|
-
};
|
|
1811
|
-
return new walletSdkCore.SuiWalletProvider({ client, wallet, account });
|
|
1812
|
-
}
|
|
1813
|
-
case "ICON": {
|
|
1814
|
-
const { walletAddress, rpcUrl } = {
|
|
1815
|
-
walletAddress: xAccount.address,
|
|
1816
|
-
rpcUrl: CHAIN_INFO[1 /* MAINNET */].APIEndpoint
|
|
1817
|
-
};
|
|
1818
|
-
return new walletSdkCore.IconWalletProvider({
|
|
1819
|
-
walletAddress,
|
|
1820
|
-
rpcUrl
|
|
1821
|
-
});
|
|
1822
|
-
}
|
|
1823
|
-
case "INJECTIVE": {
|
|
1824
|
-
const injectiveXService = xService;
|
|
1825
|
-
if (!injectiveXService) {
|
|
1826
|
-
return void 0;
|
|
1827
|
-
}
|
|
1828
|
-
return new walletSdkCore.InjectiveWalletProvider({
|
|
1829
|
-
msgBroadcaster: injectiveXService.msgBroadcaster
|
|
1830
|
-
});
|
|
1831
|
-
}
|
|
1832
|
-
case "STELLAR": {
|
|
1833
|
-
const stellarXService = xService;
|
|
1834
|
-
if (!stellarXService.walletsKit) {
|
|
1835
|
-
return void 0;
|
|
1836
|
-
}
|
|
1837
|
-
return new walletSdkCore.StellarWalletProvider({
|
|
1838
|
-
type: "BROWSER_EXTENSION",
|
|
1839
|
-
walletsKit: stellarXService.walletsKit,
|
|
1840
|
-
network: "PUBLIC"
|
|
1841
|
-
});
|
|
1842
|
-
}
|
|
1843
|
-
case "SOLANA": {
|
|
1844
|
-
const solanaXService = xService;
|
|
1845
|
-
if (!solanaXService.wallet) {
|
|
3000
|
+
var SolanaActions = () => {
|
|
3001
|
+
const solanaWallet = walletAdapterReact.useWallet();
|
|
3002
|
+
const registerChainActions = useXWalletStore((state) => state.registerChainActions);
|
|
3003
|
+
const walletRef = react.useRef(solanaWallet);
|
|
3004
|
+
react.useEffect(() => {
|
|
3005
|
+
walletRef.current = solanaWallet;
|
|
3006
|
+
}, [solanaWallet]);
|
|
3007
|
+
react.useEffect(() => {
|
|
3008
|
+
registerChainActions("SOLANA", {
|
|
3009
|
+
connect: async (xConnectorId) => {
|
|
3010
|
+
const wallet = walletRef.current.wallets.find((w) => w.adapter.name === xConnectorId);
|
|
3011
|
+
if (!wallet) {
|
|
3012
|
+
console.warn(
|
|
3013
|
+
`[SolanaActions] connect: wallet "${xConnectorId}" not found in adapter list`,
|
|
3014
|
+
walletRef.current.wallets.map((w) => w.adapter.name)
|
|
3015
|
+
);
|
|
1846
3016
|
return void 0;
|
|
1847
3017
|
}
|
|
1848
|
-
|
|
3018
|
+
walletRef.current.select(wallet.adapter.name);
|
|
3019
|
+
if (wallet.adapter.connected) {
|
|
1849
3020
|
return void 0;
|
|
1850
3021
|
}
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
3022
|
+
await new Promise((resolve, reject) => {
|
|
3023
|
+
const timeout = setTimeout(() => {
|
|
3024
|
+
cleanup();
|
|
3025
|
+
reject(new Error("Wallet connection timeout"));
|
|
3026
|
+
}, SOLANA_METAMASK_CONNECT_TIMEOUT_MS);
|
|
3027
|
+
const onConnect = () => {
|
|
3028
|
+
cleanup();
|
|
3029
|
+
resolve();
|
|
3030
|
+
};
|
|
3031
|
+
const onError = (err) => {
|
|
3032
|
+
cleanup();
|
|
3033
|
+
reject(err);
|
|
3034
|
+
};
|
|
3035
|
+
const cleanup = () => {
|
|
3036
|
+
clearTimeout(timeout);
|
|
3037
|
+
wallet.adapter.off("connect", onConnect);
|
|
3038
|
+
wallet.adapter.off("error", onError);
|
|
3039
|
+
};
|
|
3040
|
+
wallet.adapter.on("connect", onConnect);
|
|
3041
|
+
wallet.adapter.on("error", onError);
|
|
3042
|
+
setTimeout(() => {
|
|
3043
|
+
if (!wallet.adapter.connected && !wallet.adapter.connecting) {
|
|
3044
|
+
walletRef.current.connect().catch((err) => {
|
|
3045
|
+
cleanup();
|
|
3046
|
+
reject(err);
|
|
3047
|
+
});
|
|
3048
|
+
}
|
|
3049
|
+
}, 0);
|
|
1854
3050
|
});
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
return void 0;
|
|
1866
|
-
}
|
|
1867
|
-
return new walletSdkCore.NearWalletProvider({ wallet: nearXService.walletSelector });
|
|
1868
|
-
}
|
|
1869
|
-
case "STACKS": {
|
|
1870
|
-
const address = xAccount.address;
|
|
1871
|
-
if (!address) {
|
|
1872
|
-
return void 0;
|
|
3051
|
+
return void 0;
|
|
3052
|
+
},
|
|
3053
|
+
disconnect: async () => {
|
|
3054
|
+
await walletRef.current.disconnect();
|
|
3055
|
+
},
|
|
3056
|
+
getConnectors: () => useXWalletStore.getState().xConnectorsByChain.SOLANA ?? [],
|
|
3057
|
+
getConnection: () => useXWalletStore.getState().xConnections.SOLANA,
|
|
3058
|
+
signMessage: async (message) => {
|
|
3059
|
+
if (!walletRef.current.signMessage) {
|
|
3060
|
+
throw new Error("Solana wallet not connected");
|
|
1873
3061
|
}
|
|
1874
|
-
const
|
|
1875
|
-
return
|
|
3062
|
+
const signature = await walletRef.current.signMessage(new TextEncoder().encode(message));
|
|
3063
|
+
return Buffer.from(signature).toString("base64");
|
|
1876
3064
|
}
|
|
1877
|
-
|
|
1878
|
-
|
|
3065
|
+
});
|
|
3066
|
+
}, [registerChainActions]);
|
|
3067
|
+
return null;
|
|
3068
|
+
};
|
|
3069
|
+
var emptyWallets = [];
|
|
3070
|
+
var SolanaProvider = ({ children, config }) => {
|
|
3071
|
+
const autoConnect = config.autoConnect ?? SOLANA_DEFAULT_AUTO_CONNECT;
|
|
3072
|
+
const endpoint = config.chains?.[types.ChainKeys.SOLANA_MAINNET]?.rpcUrl ?? SOLANA_DEFAULT_RPC_URL;
|
|
3073
|
+
return /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReact.ConnectionProvider, { endpoint, children: /* @__PURE__ */ jsxRuntime.jsxs(walletAdapterReact.WalletProvider, { wallets: emptyWallets, autoConnect, children: [
|
|
3074
|
+
/* @__PURE__ */ jsxRuntime.jsx(SolanaHydrator, {}),
|
|
3075
|
+
/* @__PURE__ */ jsxRuntime.jsx(SolanaActions, {}),
|
|
3076
|
+
children
|
|
3077
|
+
] }) });
|
|
3078
|
+
};
|
|
3079
|
+
var SuiHydrator = () => {
|
|
3080
|
+
const suiClient = dappKit.useSuiClient();
|
|
3081
|
+
const { currentWallet } = dappKit.useCurrentWallet();
|
|
3082
|
+
const suiAccount = dappKit.useCurrentAccount();
|
|
3083
|
+
const suiWallets = dappKit.useWallets();
|
|
3084
|
+
const setXConnection = useXWalletStore((state) => state.setXConnection);
|
|
3085
|
+
const unsetXConnection = useXWalletStore((state) => state.unsetXConnection);
|
|
3086
|
+
const setWalletProvider = useXWalletStore((state) => state.setWalletProvider);
|
|
3087
|
+
const walletConfig = useWalletConfig();
|
|
3088
|
+
const suiDefaults = getEntryDefaults(walletConfig.SUI?.chains?.[types.ChainKeys.SUI_MAINNET]);
|
|
3089
|
+
react.useEffect(() => {
|
|
3090
|
+
const service = SuiXService.getInstance();
|
|
3091
|
+
if (suiClient) service.suiClient = suiClient;
|
|
3092
|
+
if (currentWallet) service.suiWallet = currentWallet;
|
|
3093
|
+
if (suiAccount) service.suiAccount = suiAccount;
|
|
3094
|
+
}, [suiClient, currentWallet, suiAccount]);
|
|
3095
|
+
const suiConnectors = react.useMemo(() => suiWallets.map((wallet) => new SuiXConnector(wallet)), [suiWallets]);
|
|
3096
|
+
react.useEffect(() => {
|
|
3097
|
+
SuiXService.getInstance().setXConnectors(suiConnectors);
|
|
3098
|
+
useXWalletStore.getState().setXConnectors("SUI", suiConnectors);
|
|
3099
|
+
}, [suiConnectors]);
|
|
3100
|
+
const wasConnectedRef = react.useRef(!!useXWalletStore.getState().xConnections.SUI);
|
|
3101
|
+
react.useEffect(() => {
|
|
3102
|
+
if (currentWallet && suiAccount?.address) {
|
|
3103
|
+
wasConnectedRef.current = true;
|
|
3104
|
+
setXConnection("SUI", {
|
|
3105
|
+
xAccount: { address: suiAccount.address, xChainType: "SUI" },
|
|
3106
|
+
// Match SuiXConnector.id derivation: prefer Wallet Standard `id`, fall back to `name`.
|
|
3107
|
+
xConnectorId: currentWallet.id ?? currentWallet.name
|
|
3108
|
+
});
|
|
3109
|
+
} else if (wasConnectedRef.current) {
|
|
3110
|
+
wasConnectedRef.current = false;
|
|
3111
|
+
unsetXConnection("SUI");
|
|
3112
|
+
}
|
|
3113
|
+
}, [currentWallet, suiAccount, setXConnection, unsetXConnection]);
|
|
3114
|
+
const walletProvider = react.useMemo(() => {
|
|
3115
|
+
if (suiClient && currentWallet && suiAccount) {
|
|
3116
|
+
assertSuiProviderShape("SuiHydrator", suiClient, currentWallet, suiAccount);
|
|
3117
|
+
return new walletSdkCore.SuiWalletProvider({
|
|
3118
|
+
client: suiClient,
|
|
3119
|
+
wallet: currentWallet,
|
|
3120
|
+
account: suiAccount,
|
|
3121
|
+
defaults: suiDefaults
|
|
3122
|
+
});
|
|
1879
3123
|
}
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
}
|
|
1891
|
-
function useXSignMessage() {
|
|
1892
|
-
const { signMessage } = walletAdapterReact.useWallet();
|
|
1893
|
-
const { signMessageAsync: evmSignMessage } = wagmi.useSignMessage();
|
|
3124
|
+
return void 0;
|
|
3125
|
+
}, [suiClient, currentWallet, suiAccount, suiDefaults]);
|
|
3126
|
+
react.useEffect(() => {
|
|
3127
|
+
setWalletProvider("SUI", walletProvider);
|
|
3128
|
+
}, [walletProvider, setWalletProvider]);
|
|
3129
|
+
return null;
|
|
3130
|
+
};
|
|
3131
|
+
var SuiActions = () => {
|
|
3132
|
+
const suiWallets = dappKit.useWallets();
|
|
3133
|
+
const { mutateAsync: suiConnectAsync } = dappKit.useConnectWallet();
|
|
3134
|
+
const { mutateAsync: suiDisconnectAsync } = dappKit.useDisconnectWallet();
|
|
1894
3135
|
const { mutateAsync: signPersonalMessage } = dappKit.useSignPersonalMessage();
|
|
1895
|
-
const
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
}
|
|
1921
|
-
case "INJECTIVE": {
|
|
1922
|
-
if (!injectiveAddress) {
|
|
1923
|
-
throw new Error("Injective address not found");
|
|
1924
|
-
}
|
|
1925
|
-
const ethereumAddress = sdkTs.getEthereumAddress(injectiveAddress);
|
|
1926
|
-
const walletStrategy = InjectiveXService.getInstance().walletStrategy;
|
|
1927
|
-
const res = await walletStrategy.signArbitrary(
|
|
1928
|
-
walletStrategy.getWallet() === walletBase.Wallet.Metamask ? ethereumAddress : injectiveAddress,
|
|
1929
|
-
message
|
|
3136
|
+
const registerChainActions = useXWalletStore((state) => state.registerChainActions);
|
|
3137
|
+
const connectRef = react.useRef(suiConnectAsync);
|
|
3138
|
+
const disconnectRef = react.useRef(suiDisconnectAsync);
|
|
3139
|
+
const signMessageRef = react.useRef(signPersonalMessage);
|
|
3140
|
+
const walletsRef = react.useRef(suiWallets);
|
|
3141
|
+
react.useEffect(() => {
|
|
3142
|
+
connectRef.current = suiConnectAsync;
|
|
3143
|
+
}, [suiConnectAsync]);
|
|
3144
|
+
react.useEffect(() => {
|
|
3145
|
+
disconnectRef.current = suiDisconnectAsync;
|
|
3146
|
+
}, [suiDisconnectAsync]);
|
|
3147
|
+
react.useEffect(() => {
|
|
3148
|
+
signMessageRef.current = signPersonalMessage;
|
|
3149
|
+
}, [signPersonalMessage]);
|
|
3150
|
+
react.useEffect(() => {
|
|
3151
|
+
walletsRef.current = suiWallets;
|
|
3152
|
+
}, [suiWallets]);
|
|
3153
|
+
react.useEffect(() => {
|
|
3154
|
+
registerChainActions("SUI", {
|
|
3155
|
+
connect: async (xConnectorId) => {
|
|
3156
|
+
const wallet = walletsRef.current.find((w) => (w.id ?? w.name) === xConnectorId);
|
|
3157
|
+
if (!wallet) {
|
|
3158
|
+
console.warn(
|
|
3159
|
+
`[SuiActions] connect: wallet "${xConnectorId}" not found in adapter list`,
|
|
3160
|
+
walletsRef.current.map((w) => w.name)
|
|
1930
3161
|
);
|
|
1931
|
-
|
|
1932
|
-
throw new Error("Injective signature not found");
|
|
1933
|
-
}
|
|
1934
|
-
signature = res;
|
|
1935
|
-
break;
|
|
3162
|
+
return void 0;
|
|
1936
3163
|
}
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
3164
|
+
await connectRef.current({ wallet });
|
|
3165
|
+
return void 0;
|
|
3166
|
+
},
|
|
3167
|
+
disconnect: async () => {
|
|
3168
|
+
await disconnectRef.current();
|
|
3169
|
+
},
|
|
3170
|
+
getConnectors: () => useXWalletStore.getState().xConnectorsByChain.SUI ?? [],
|
|
3171
|
+
getConnection: () => useXWalletStore.getState().xConnections.SUI,
|
|
3172
|
+
signMessage: async (message) => {
|
|
3173
|
+
const res = await signMessageRef.current({ message: new Uint8Array(new TextEncoder().encode(message)) });
|
|
3174
|
+
return res.signature;
|
|
1940
3175
|
}
|
|
1941
|
-
return signature;
|
|
1942
|
-
}
|
|
1943
|
-
});
|
|
1944
|
-
}
|
|
1945
|
-
|
|
1946
|
-
// src/xchains/bitcoin/useBitcoinXConnectors.ts
|
|
1947
|
-
function useBitcoinXConnectors() {
|
|
1948
|
-
const xService = useXService("BITCOIN");
|
|
1949
|
-
return React2.useMemo(() => {
|
|
1950
|
-
return xService?.getXConnectors() || [];
|
|
1951
|
-
}, [xService]);
|
|
1952
|
-
}
|
|
1953
|
-
var Hydrate = ({ rpcConfig }) => {
|
|
1954
|
-
const suiClient = dappKit.useSuiClient();
|
|
1955
|
-
React2.useEffect(() => {
|
|
1956
|
-
if (suiClient) {
|
|
1957
|
-
SuiXService.getInstance().suiClient = suiClient;
|
|
1958
|
-
}
|
|
1959
|
-
}, [suiClient]);
|
|
1960
|
-
const { currentWallet: suiWallet } = dappKit.useCurrentWallet();
|
|
1961
|
-
React2.useEffect(() => {
|
|
1962
|
-
if (suiWallet) {
|
|
1963
|
-
SuiXService.getInstance().suiWallet = suiWallet;
|
|
1964
|
-
}
|
|
1965
|
-
}, [suiWallet]);
|
|
1966
|
-
const suiAccount = dappKit.useCurrentAccount();
|
|
1967
|
-
React2.useEffect(() => {
|
|
1968
|
-
if (suiAccount) {
|
|
1969
|
-
SuiXService.getInstance().suiAccount = suiAccount;
|
|
1970
|
-
}
|
|
1971
|
-
}, [suiAccount]);
|
|
1972
|
-
const { connection: solanaConnection } = walletAdapterReact.useConnection();
|
|
1973
|
-
const solanaWallet = walletAdapterReact.useWallet();
|
|
1974
|
-
React2.useEffect(() => {
|
|
1975
|
-
if (solanaConnection) {
|
|
1976
|
-
SolanaXService.getInstance().connection = solanaConnection;
|
|
1977
|
-
}
|
|
1978
|
-
}, [solanaConnection]);
|
|
1979
|
-
React2.useEffect(() => {
|
|
1980
|
-
if (solanaWallet) {
|
|
1981
|
-
SolanaXService.getInstance().wallet = solanaWallet;
|
|
1982
|
-
}
|
|
1983
|
-
}, [solanaWallet]);
|
|
1984
|
-
const wagmiConfig = wagmi.useConfig();
|
|
1985
|
-
React2.useEffect(() => {
|
|
1986
|
-
if (wagmiConfig) {
|
|
1987
|
-
EvmXService.getInstance().wagmiConfig = wagmiConfig;
|
|
1988
|
-
}
|
|
1989
|
-
}, [wagmiConfig]);
|
|
1990
|
-
React2.useEffect(() => {
|
|
1991
|
-
StacksXService.getInstance().network = network.createNetwork({
|
|
1992
|
-
network: "mainnet",
|
|
1993
|
-
client: { baseUrl: rpcConfig.stacks ?? "https://api.mainnet.hiro.so" }
|
|
1994
3176
|
});
|
|
1995
|
-
}, [
|
|
3177
|
+
}, [registerChainActions]);
|
|
1996
3178
|
return null;
|
|
1997
3179
|
};
|
|
3180
|
+
var SuiProvider = ({ children, config }) => {
|
|
3181
|
+
const autoConnect = config.autoConnect ?? SUI_DEFAULT_AUTO_CONNECT;
|
|
3182
|
+
const network = config.network ?? SUI_DEFAULT_NETWORK;
|
|
3183
|
+
const rpcUrl = config.chains?.[types.ChainKeys.SUI_MAINNET]?.rpcUrl ?? client.getFullnodeUrl(network);
|
|
3184
|
+
return /* @__PURE__ */ jsxRuntime.jsx(dappKit.SuiClientProvider, { networks: { [network]: { url: rpcUrl } }, defaultNetwork: network, children: /* @__PURE__ */ jsxRuntime.jsxs(dappKit.WalletProvider, { autoConnect, children: [
|
|
3185
|
+
/* @__PURE__ */ jsxRuntime.jsx(SuiHydrator, {}),
|
|
3186
|
+
/* @__PURE__ */ jsxRuntime.jsx(SuiActions, {}),
|
|
3187
|
+
children
|
|
3188
|
+
] }) });
|
|
3189
|
+
};
|
|
1998
3190
|
|
|
1999
3191
|
// src/xchains/icon/actions.ts
|
|
2000
3192
|
var reconnectIcon = async () => {
|
|
2001
|
-
const iconConnection =
|
|
3193
|
+
const iconConnection = useXWalletStore.getState().xConnections.ICON;
|
|
2002
3194
|
if (!iconConnection) return;
|
|
2003
3195
|
const recentXConnectorId = iconConnection.xConnectorId;
|
|
2004
3196
|
const detail = await request({
|
|
2005
3197
|
type: "REQUEST_ADDRESS" /* REQUEST_ADDRESS */
|
|
2006
3198
|
});
|
|
2007
3199
|
if (detail?.type === "RESPONSE_ADDRESS" /* RESPONSE_ADDRESS */) {
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
xChainType: "ICON"
|
|
2015
|
-
},
|
|
2016
|
-
xConnectorId: recentXConnectorId
|
|
2017
|
-
}
|
|
2018
|
-
}
|
|
3200
|
+
useXWalletStore.getState().setXConnection("ICON", {
|
|
3201
|
+
xAccount: {
|
|
3202
|
+
address: detail?.payload,
|
|
3203
|
+
xChainType: "ICON"
|
|
3204
|
+
},
|
|
3205
|
+
xConnectorId: recentXConnectorId
|
|
2019
3206
|
});
|
|
2020
3207
|
}
|
|
2021
3208
|
};
|
|
3209
|
+
function isWallet(value) {
|
|
3210
|
+
return Object.values(walletBase.Wallet).some((v) => v === value);
|
|
3211
|
+
}
|
|
2022
3212
|
var reconnectInjective = async () => {
|
|
2023
|
-
const injectiveConnection =
|
|
3213
|
+
const injectiveConnection = useXWalletStore.getState().xConnections.INJECTIVE;
|
|
2024
3214
|
if (!injectiveConnection) return;
|
|
2025
3215
|
const recentXConnectorId = injectiveConnection.xConnectorId;
|
|
3216
|
+
if (!isWallet(recentXConnectorId)) {
|
|
3217
|
+
console.warn(`[Injective] Stale wallet ID skipped: ${recentXConnectorId}`);
|
|
3218
|
+
return;
|
|
3219
|
+
}
|
|
2026
3220
|
const walletStrategy = InjectiveXService.getInstance().walletStrategy;
|
|
2027
3221
|
await walletStrategy.setWallet(recentXConnectorId);
|
|
2028
3222
|
const addresses = await walletStrategy.getAddresses();
|
|
2029
|
-
const
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
xConnectorId: recentXConnectorId
|
|
2039
|
-
}
|
|
2040
|
-
}
|
|
3223
|
+
const firstAddress = addresses?.[0];
|
|
3224
|
+
if (!firstAddress) return;
|
|
3225
|
+
const address = walletBase.isEvmBrowserWallet(recentXConnectorId) ? sdkTs.getInjectiveAddress(firstAddress) : firstAddress;
|
|
3226
|
+
useXWalletStore.getState().setXConnection("INJECTIVE", {
|
|
3227
|
+
xAccount: {
|
|
3228
|
+
address,
|
|
3229
|
+
xChainType: "INJECTIVE"
|
|
3230
|
+
},
|
|
3231
|
+
xConnectorId: recentXConnectorId
|
|
2041
3232
|
});
|
|
2042
3233
|
};
|
|
2043
3234
|
|
|
2044
3235
|
// src/xchains/stellar/actions.ts
|
|
2045
3236
|
var reconnectStellar = async () => {
|
|
2046
|
-
const stellarConnection =
|
|
3237
|
+
const stellarConnection = useXWalletStore.getState().xConnections.STELLAR;
|
|
2047
3238
|
if (!stellarConnection) return;
|
|
2048
3239
|
const recentXConnectorId = stellarConnection.xConnectorId;
|
|
2049
3240
|
const stellarWalletKit = StellarXService.getInstance().walletsKit;
|
|
2050
3241
|
stellarWalletKit.setWallet(recentXConnectorId);
|
|
2051
3242
|
const { address } = await stellarWalletKit.getAddress();
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
xChainType: "STELLAR"
|
|
2059
|
-
},
|
|
2060
|
-
xConnectorId: recentXConnectorId
|
|
2061
|
-
}
|
|
2062
|
-
}
|
|
3243
|
+
useXWalletStore.getState().setXConnection("STELLAR", {
|
|
3244
|
+
xAccount: {
|
|
3245
|
+
address,
|
|
3246
|
+
xChainType: "STELLAR"
|
|
3247
|
+
},
|
|
3248
|
+
xConnectorId: recentXConnectorId
|
|
2063
3249
|
});
|
|
2064
3250
|
};
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
3251
|
+
|
|
3252
|
+
// src/hooks/useInitChainServices.ts
|
|
3253
|
+
function useInitChainServices(walletConfig) {
|
|
3254
|
+
const initChainServices = useXWalletStore((state) => state.initChainServices);
|
|
3255
|
+
const cleanupDisabledConnections = useXWalletStore((state) => state.cleanupDisabledConnections);
|
|
3256
|
+
react.useEffect(() => {
|
|
3257
|
+
initChainServices(walletConfig);
|
|
3258
|
+
const afterHydration = () => {
|
|
3259
|
+
cleanupDisabledConnections();
|
|
3260
|
+
const store = useXWalletStore.getState();
|
|
3261
|
+
for (const chainType of Object.keys(store.xConnections)) {
|
|
3262
|
+
if (!chainRegistry[chainType]?.createWalletProvider) continue;
|
|
3263
|
+
const conn = store.xConnections[chainType];
|
|
3264
|
+
if (conn) store.setXConnection(chainType, conn);
|
|
3265
|
+
}
|
|
3266
|
+
if (walletConfig.ICON) {
|
|
3267
|
+
reconnectIcon().catch((error) => console.warn("[wallet-sdk-react] ICON reconnect failed:", error));
|
|
3268
|
+
}
|
|
3269
|
+
if (walletConfig.INJECTIVE) {
|
|
3270
|
+
reconnectInjective().catch((error) => console.warn("[wallet-sdk-react] Injective reconnect failed:", error));
|
|
3271
|
+
}
|
|
3272
|
+
if (walletConfig.STELLAR) {
|
|
3273
|
+
reconnectStellar().catch((error) => console.warn("[wallet-sdk-react] Stellar reconnect failed:", error));
|
|
3274
|
+
}
|
|
3275
|
+
};
|
|
3276
|
+
if (useXWalletStore.persist.hasHydrated()) {
|
|
3277
|
+
afterHydration();
|
|
3278
|
+
} else {
|
|
3279
|
+
useXWalletStore.persist.onFinishHydration(afterHydration);
|
|
3280
|
+
}
|
|
3281
|
+
}, []);
|
|
3282
|
+
}
|
|
3283
|
+
var SodaxWalletProvider = ({ children, config }) => {
|
|
3284
|
+
const configRef = react.useRef(config);
|
|
3285
|
+
const frozen = configRef.current;
|
|
3286
|
+
useInitChainServices(frozen);
|
|
3287
|
+
let content = /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
3288
|
+
if (frozen.SOLANA) {
|
|
3289
|
+
content = /* @__PURE__ */ jsxRuntime.jsx(SolanaProvider, { config: frozen.SOLANA, children: content });
|
|
2076
3290
|
}
|
|
3291
|
+
if (frozen.SUI) {
|
|
3292
|
+
content = /* @__PURE__ */ jsxRuntime.jsx(SuiProvider, { config: frozen.SUI, children: content });
|
|
3293
|
+
}
|
|
3294
|
+
if (frozen.EVM) {
|
|
3295
|
+
content = /* @__PURE__ */ jsxRuntime.jsx(EvmProvider, { config: frozen.EVM, children: content });
|
|
3296
|
+
}
|
|
3297
|
+
return /* @__PURE__ */ jsxRuntime.jsx(WalletConfigProvider, { value: frozen, children: content });
|
|
2077
3298
|
};
|
|
2078
|
-
var SodaxWalletProvider = ({ children, rpcConfig, options, initialState }) => {
|
|
2079
|
-
const wagmi$1 = React2.useMemo(() => ({ ...defaultOptions.wagmi, ...options?.wagmi }), [options?.wagmi]);
|
|
2080
|
-
const wagmiConfig = React2.useMemo(() => {
|
|
2081
|
-
return createWagmiConfig(rpcConfig, wagmi$1);
|
|
2082
|
-
}, [rpcConfig, wagmi$1]);
|
|
2083
|
-
const wallets = React2.useMemo(() => [new walletAdapterWallets.UnsafeBurnerWalletAdapter()], []);
|
|
2084
|
-
const solana = React2.useMemo(() => ({ ...defaultOptions.solana, ...options?.solana }), [options?.solana]);
|
|
2085
|
-
const sui = React2.useMemo(() => ({ ...defaultOptions.sui, ...options?.sui }), [options?.sui]);
|
|
2086
|
-
return /* @__PURE__ */ React2__default.default.createElement(reactQuery.QueryClientProvider, { client: queryClient }, /* @__PURE__ */ React2__default.default.createElement(wagmi.WagmiProvider, { reconnectOnMount: wagmi$1.reconnectOnMount, config: wagmiConfig, initialState }, /* @__PURE__ */ React2__default.default.createElement(dappKit.SuiClientProvider, { networks: { mainnet: { url: client.getFullnodeUrl("mainnet") } }, defaultNetwork: "mainnet" }, /* @__PURE__ */ React2__default.default.createElement(dappKit.WalletProvider, { autoConnect: sui.autoConnect }, /* @__PURE__ */ React2__default.default.createElement(walletAdapterReact.ConnectionProvider, { endpoint: rpcConfig["solana"] ?? "https://api.mainnet-beta.solana.com" }, /* @__PURE__ */ React2__default.default.createElement(walletAdapterReact.WalletProvider, { wallets, autoConnect: solana.autoConnect }, /* @__PURE__ */ React2__default.default.createElement(Hydrate, { rpcConfig }), children))))));
|
|
2087
|
-
};
|
|
2088
|
-
reconnectIcon();
|
|
2089
|
-
reconnectInjective();
|
|
2090
|
-
reconnectStellar();
|
|
2091
|
-
|
|
2092
|
-
// src/types/index.ts
|
|
2093
|
-
var WalletId = /* @__PURE__ */ ((WalletId2) => {
|
|
2094
|
-
WalletId2["METAMASK"] = "metamask";
|
|
2095
|
-
WalletId2["HANA"] = "hana";
|
|
2096
|
-
WalletId2["PHANTOM"] = "phantom";
|
|
2097
|
-
WalletId2["SUI"] = "sui";
|
|
2098
|
-
WalletId2["KEPLR"] = "keplr";
|
|
2099
|
-
return WalletId2;
|
|
2100
|
-
})(WalletId || {});
|
|
2101
3299
|
|
|
2102
|
-
exports.BitcoinXConnector = BitcoinXConnector;
|
|
2103
|
-
exports.BitcoinXService = BitcoinXService;
|
|
2104
|
-
exports.EvmXConnector = EvmXConnector;
|
|
2105
|
-
exports.EvmXService = EvmXService;
|
|
2106
|
-
exports.IconHanaXConnector = IconHanaXConnector;
|
|
2107
|
-
exports.IconXService = IconXService;
|
|
2108
|
-
exports.InjectiveXConnector = InjectiveXConnector;
|
|
2109
|
-
exports.InjectiveXService = InjectiveXService;
|
|
2110
|
-
exports.OKXXConnector = OKXXConnector;
|
|
2111
|
-
exports.STACKS_PROVIDERS = STACKS_PROVIDERS;
|
|
2112
3300
|
exports.SodaxWalletProvider = SodaxWalletProvider;
|
|
2113
|
-
exports.
|
|
2114
|
-
exports.SolanaXService = SolanaXService;
|
|
2115
|
-
exports.StacksXConnector = StacksXConnector;
|
|
2116
|
-
exports.StacksXService = StacksXService;
|
|
2117
|
-
exports.StellarWalletsKitXConnector = StellarWalletsKitXConnector;
|
|
2118
|
-
exports.StellarXService = StellarXService;
|
|
2119
|
-
exports.SuiXConnector = SuiXConnector;
|
|
2120
|
-
exports.SuiXService = SuiXService;
|
|
2121
|
-
exports.UnisatXConnector = UnisatXConnector;
|
|
2122
|
-
exports.WalletId = WalletId;
|
|
3301
|
+
exports.WalletConfigProvider = WalletConfigProvider;
|
|
2123
3302
|
exports.XConnector = XConnector;
|
|
2124
3303
|
exports.XService = XService;
|
|
2125
|
-
exports.
|
|
2126
|
-
exports.
|
|
2127
|
-
exports.createWagmiConfig = createWagmiConfig;
|
|
3304
|
+
exports.getEntryDefaults = getEntryDefaults;
|
|
3305
|
+
exports.getRpcUrl = getRpcUrl;
|
|
2128
3306
|
exports.getWagmiChainId = getWagmiChainId;
|
|
2129
3307
|
exports.getXChainType = getXChainType;
|
|
2130
3308
|
exports.getXService = getXService;
|
|
2131
3309
|
exports.isNativeToken = isNativeToken;
|
|
2132
|
-
exports.
|
|
3310
|
+
exports.resolveEvmDefaults = resolveEvmDefaults;
|
|
3311
|
+
exports.sortConnectors = sortConnectors;
|
|
3312
|
+
exports.useBatchConnect = useBatchConnect;
|
|
3313
|
+
exports.useBatchDisconnect = useBatchDisconnect;
|
|
3314
|
+
exports.useChainGroups = useChainGroups;
|
|
3315
|
+
exports.useConnectedChains = useConnectedChains;
|
|
3316
|
+
exports.useConnectionFlow = useConnectionFlow;
|
|
3317
|
+
exports.useEnabledChainTypes = useEnabledChainTypes;
|
|
3318
|
+
exports.useEnabledChains = useEnabledChains;
|
|
2133
3319
|
exports.useEvmSwitchChain = useEvmSwitchChain;
|
|
2134
|
-
exports.
|
|
3320
|
+
exports.useIsChainEnabled = useIsChainEnabled;
|
|
3321
|
+
exports.useIsWalletInstalled = useIsWalletInstalled;
|
|
3322
|
+
exports.useWalletConfig = useWalletConfig;
|
|
3323
|
+
exports.useWalletModal = useWalletModal;
|
|
2135
3324
|
exports.useWalletProvider = useWalletProvider;
|
|
2136
3325
|
exports.useXAccount = useXAccount;
|
|
2137
3326
|
exports.useXAccounts = useXAccounts;
|
|
2138
|
-
exports.useXBalances = useXBalances;
|
|
2139
3327
|
exports.useXConnect = useXConnect;
|
|
2140
3328
|
exports.useXConnection = useXConnection;
|
|
3329
|
+
exports.useXConnections = useXConnections;
|
|
2141
3330
|
exports.useXConnectors = useXConnectors;
|
|
3331
|
+
exports.useXConnectorsByChain = useXConnectorsByChain;
|
|
2142
3332
|
exports.useXDisconnect = useXDisconnect;
|
|
2143
3333
|
exports.useXService = useXService;
|
|
3334
|
+
exports.useXServices = useXServices;
|
|
2144
3335
|
exports.useXSignMessage = useXSignMessage;
|
|
2145
|
-
exports.useXWagmiStore = useXWagmiStore;
|
|
2146
3336
|
//# sourceMappingURL=index.cjs.map
|
|
2147
3337
|
//# sourceMappingURL=index.cjs.map
|