@sodax/wallet-sdk-react 2.0.0-rc.2 → 2.0.0-rc.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +12 -5
  2. package/dist/{chunk-BKJB527E.mjs → chunk-3QETHO6P.mjs} +1 -3
  3. package/dist/{chunk-PJLEJVAU.mjs → chunk-42LTUHMZ.mjs} +1 -3
  4. package/dist/{chunk-NY7U7OJW.mjs → chunk-7V7O3Q7Y.mjs} +0 -2
  5. package/dist/{chunk-BXJLBR4G.mjs → chunk-C6M34IVL.mjs} +2 -4
  6. package/dist/{chunk-XZ7CHO2S.mjs → chunk-FSOGMSJH.mjs} +2 -4
  7. package/dist/{chunk-X2MHIWXO.mjs → chunk-IFXZQW4C.mjs} +0 -2
  8. package/dist/{chunk-7ULB6DW4.mjs → chunk-JQ4H4GJ5.mjs} +3 -5
  9. package/dist/{chunk-N5A2TMF6.mjs → chunk-LKSSME2J.mjs} +2 -4
  10. package/dist/{chunk-PLCA4ZDJ.mjs → chunk-LUKR7YKV.mjs} +54 -30
  11. package/dist/{chunk-MXZVF5HR.mjs → chunk-NAKCAL2M.mjs} +0 -2
  12. package/dist/chunk-QMXBY3UI.mjs +1 -0
  13. package/dist/{chunk-MAQ47Q52.mjs → chunk-TACW7Z4D.mjs} +0 -2
  14. package/dist/{chunk-2BOUGCJ7.mjs → chunk-WPZOLGVB.mjs} +4 -6
  15. package/dist/{chunk-66BAUK56.mjs → chunk-X7BHR7WS.mjs} +2 -4
  16. package/dist/{chunk-E5IAZ7E6.mjs → chunk-Z5GXDHGL.mjs} +9 -5
  17. package/dist/{config-OlnzyEUE.d.ts → config-GVKK8IfY.d.ts} +6 -1
  18. package/dist/index.d.ts +4 -4
  19. package/dist/index.mjs +20 -31
  20. package/dist/xchains/bitcoin/index.mjs +14 -16
  21. package/dist/xchains/evm/index.d.ts +1 -1
  22. package/dist/xchains/evm/index.mjs +3 -5
  23. package/dist/xchains/icon/index.mjs +5 -7
  24. package/dist/xchains/injective/index.mjs +3 -5
  25. package/dist/xchains/near/index.mjs +4 -6
  26. package/dist/xchains/solana/index.mjs +5 -7
  27. package/dist/xchains/stacks/index.mjs +3 -5
  28. package/dist/xchains/stellar/index.mjs +4 -6
  29. package/dist/xchains/sui/index.mjs +5 -7
  30. package/docs/ADDING_A_NEW_CHAIN.md +1 -1
  31. package/docs/SUB_PATH_EXPORTS.md +14 -42
  32. package/package.json +32 -23
  33. package/ai-exported/AGENTS.md +0 -122
  34. package/ai-exported/integration/README.md +0 -102
  35. package/ai-exported/integration/ai-rules.md +0 -136
  36. package/ai-exported/integration/architecture.md +0 -181
  37. package/ai-exported/integration/examples/01-minimal-evm.tsx +0 -75
  38. package/ai-exported/integration/examples/02-multi-chain-modal.tsx +0 -169
  39. package/ai-exported/integration/examples/03-nextjs-app-router.tsx +0 -99
  40. package/ai-exported/integration/examples/04-walletconnect-setup.tsx +0 -89
  41. package/ai-exported/integration/examples/README.md +0 -29
  42. package/ai-exported/integration/recipes/batch-operations.md +0 -223
  43. package/ai-exported/integration/recipes/bridge-to-sdk.md +0 -164
  44. package/ai-exported/integration/recipes/chain-detection.md +0 -254
  45. package/ai-exported/integration/recipes/connect-button.md +0 -156
  46. package/ai-exported/integration/recipes/multi-chain-modal.md +0 -199
  47. package/ai-exported/integration/recipes/setup.md +0 -158
  48. package/ai-exported/integration/recipes/sign-message.md +0 -137
  49. package/ai-exported/integration/recipes/sub-path-imports.md +0 -95
  50. package/ai-exported/integration/recipes/switch-chain.md +0 -141
  51. package/ai-exported/integration/recipes/walletconnect-setup.md +0 -139
  52. package/ai-exported/integration/reference/api-surface.md +0 -175
  53. package/ai-exported/integration/reference/chain-support.md +0 -78
  54. package/ai-exported/integration/reference/connectors.md +0 -74
  55. package/ai-exported/integration/reference/hooks.md +0 -204
  56. package/ai-exported/integration/reference/wallet-brands.md +0 -106
  57. package/ai-exported/migration/README.md +0 -49
  58. package/ai-exported/migration/ai-rules.md +0 -144
  59. package/ai-exported/migration/breaking-changes.md +0 -305
  60. package/ai-exported/migration/checklist.md +0 -159
  61. package/ai-exported/migration/recipes/connect-button.md +0 -166
  62. package/ai-exported/migration/recipes/multi-chain-modal.md +0 -244
  63. package/ai-exported/migration/recipes/ssr-setup.md +0 -162
  64. package/ai-exported/migration/recipes/walletconnect-migration.md +0 -168
  65. package/ai-exported/migration/reference/components.md +0 -73
  66. package/ai-exported/migration/reference/config.md +0 -307
  67. package/ai-exported/migration/reference/hooks.md +0 -278
  68. package/ai-exported/migration/reference/imports.md +0 -157
  69. package/dist/chunk-2BOUGCJ7.mjs.map +0 -1
  70. package/dist/chunk-66BAUK56.mjs.map +0 -1
  71. package/dist/chunk-7ULB6DW4.mjs.map +0 -1
  72. package/dist/chunk-BKJB527E.mjs.map +0 -1
  73. package/dist/chunk-BXJLBR4G.mjs.map +0 -1
  74. package/dist/chunk-E5IAZ7E6.mjs.map +0 -1
  75. package/dist/chunk-MAQ47Q52.mjs.map +0 -1
  76. package/dist/chunk-MXZVF5HR.mjs.map +0 -1
  77. package/dist/chunk-N5A2TMF6.mjs.map +0 -1
  78. package/dist/chunk-NY7U7OJW.mjs.map +0 -1
  79. package/dist/chunk-PJLEJVAU.mjs.map +0 -1
  80. package/dist/chunk-PLCA4ZDJ.mjs.map +0 -1
  81. package/dist/chunk-TZMKDXFA.mjs +0 -3
  82. package/dist/chunk-TZMKDXFA.mjs.map +0 -1
  83. package/dist/chunk-X2MHIWXO.mjs.map +0 -1
  84. package/dist/chunk-XZ7CHO2S.mjs.map +0 -1
  85. package/dist/index.cjs +0 -3337
  86. package/dist/index.cjs.map +0 -1
  87. package/dist/index.mjs.map +0 -1
  88. package/dist/xchains/bitcoin/index.cjs +0 -1927
  89. package/dist/xchains/bitcoin/index.cjs.map +0 -1
  90. package/dist/xchains/bitcoin/index.mjs.map +0 -1
  91. package/dist/xchains/evm/index.cjs +0 -316
  92. package/dist/xchains/evm/index.cjs.map +0 -1
  93. package/dist/xchains/evm/index.mjs.map +0 -1
  94. package/dist/xchains/icon/index.cjs +0 -311
  95. package/dist/xchains/icon/index.cjs.map +0 -1
  96. package/dist/xchains/icon/index.mjs.map +0 -1
  97. package/dist/xchains/injective/index.cjs +0 -223
  98. package/dist/xchains/injective/index.cjs.map +0 -1
  99. package/dist/xchains/injective/index.mjs.map +0 -1
  100. package/dist/xchains/near/index.cjs +0 -190
  101. package/dist/xchains/near/index.cjs.map +0 -1
  102. package/dist/xchains/near/index.mjs.map +0 -1
  103. package/dist/xchains/solana/index.cjs +0 -186
  104. package/dist/xchains/solana/index.cjs.map +0 -1
  105. package/dist/xchains/solana/index.mjs.map +0 -1
  106. package/dist/xchains/stacks/index.cjs +0 -240
  107. package/dist/xchains/stacks/index.cjs.map +0 -1
  108. package/dist/xchains/stacks/index.mjs.map +0 -1
  109. package/dist/xchains/stellar/index.cjs +0 -322
  110. package/dist/xchains/stellar/index.cjs.map +0 -1
  111. package/dist/xchains/stellar/index.mjs.map +0 -1
  112. package/dist/xchains/sui/index.cjs +0 -248
  113. package/dist/xchains/sui/index.cjs.map +0 -1
  114. package/dist/xchains/sui/index.mjs.map +0 -1
  115. package/skills/SKILLS.md +0 -84
  116. package/skills/bridge-to-sdk.md +0 -148
  117. package/skills/connect-button.md +0 -116
  118. package/skills/evm-only-walletconnect.md +0 -111
  119. package/skills/multi-chain-modal.md +0 -178
  120. package/skills/setup.md +0 -107
package/dist/index.cjs DELETED
@@ -1,3337 +0,0 @@
1
- 'use strict';
2
-
3
- var types = require('@sodax/types');
4
- var zustand = require('zustand');
5
- var middleware = require('zustand/middleware');
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');
10
- var viem = require('viem');
11
- var actions = require('wagmi/actions');
12
- var wagmi = require('wagmi');
13
- var chains$1 = require('wagmi/chains');
14
- var web3_js = require('@solana/web3.js');
15
- var splToken = require('@solana/spl-token');
16
- var stellarWalletsKit = require('@creit.tech/stellar-wallets-kit');
17
- var StellarSdk = require('@stellar/stellar-sdk');
18
- var IconSdkRaw = require('icon-sdk-js');
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');
26
- var reactQuery = require('@tanstack/react-query');
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');
37
- var client = require('@mysten/sui/client');
38
-
39
- function _interopNamespace(e) {
40
- if (e && e.__esModule) return e;
41
- var n = Object.create(null);
42
- if (e) {
43
- Object.keys(e).forEach(function (k) {
44
- if (k !== 'default') {
45
- var d = Object.getOwnPropertyDescriptor(e, k);
46
- Object.defineProperty(n, k, d.get ? d : {
47
- enumerable: true,
48
- get: function () { return e[k]; }
49
- });
50
- }
51
- });
52
- }
53
- n.default = e;
54
- return Object.freeze(n);
55
- }
56
-
57
- var StellarSdk__namespace = /*#__PURE__*/_interopNamespace(StellarSdk);
58
- var IconSdkRaw__namespace = /*#__PURE__*/_interopNamespace(IconSdkRaw);
59
-
60
- // src/actions/getXChainType.ts
61
- function getXChainType(xChainId) {
62
- if (!xChainId) {
63
- return void 0;
64
- }
65
- return types.baseChainInfo[xChainId].type;
66
- }
67
-
68
- // src/core/XService.ts
69
- var XService = class {
70
- /** The blockchain type this service handles */
71
- xChainType;
72
- /** Available wallet connectors for this chain */
73
- xConnectors = [];
74
- constructor(xChainType) {
75
- this.xChainType = xChainType;
76
- }
77
- /**
78
- * Gets the balance of a specific token for an address
79
- * @param address The wallet address to check
80
- * @param xToken The token to get the balance for
81
- * @returns Promise resolving to the token balance as a bigint
82
- */
83
- async getBalance(address, xToken) {
84
- return 0n;
85
- }
86
- /**
87
- * Gets balances for multiple tokens for an address
88
- * @param address The wallet address to check
89
- * @param xTokens Array of tokens to get balances for
90
- * @returns Promise resolving to object mapping token addresses to balances
91
- */
92
- async getBalances(address, xTokens) {
93
- if (!address) return {};
94
- const balancePromises = xTokens.map(async (xToken) => {
95
- const balance = await this.getBalance(address, xToken);
96
- return { address: xToken.address, balance };
97
- });
98
- const balances = await Promise.all(balancePromises);
99
- return balances.reduce((acc, { address: address2, balance }) => {
100
- acc[address2] = balance;
101
- return acc;
102
- }, {});
103
- }
104
- /**
105
- * Gets all available connectors for this chain
106
- */
107
- getXConnectors() {
108
- return this.xConnectors;
109
- }
110
- /**
111
- * Sets the available connectors for this chain
112
- */
113
- setXConnectors(xConnectors) {
114
- this.xConnectors = xConnectors;
115
- }
116
- /**
117
- * Gets a specific connector by its ID
118
- * @param xConnectorId The connector ID to look up
119
- * @returns The matching connector or undefined if not found
120
- */
121
- getXConnectorById(xConnectorId) {
122
- return this.getXConnectors().find((xConnector) => xConnector.id === xConnectorId);
123
- }
124
- };
125
-
126
- // src/core/XConnector.ts
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;
136
- constructor(xChainType, name, id) {
137
- this.xChainType = xChainType;
138
- this.name = name;
139
- this._id = id;
140
- }
141
- /** Get the unique identifier for this connector */
142
- get id() {
143
- return this._id;
144
- }
145
- /** Get the optional icon URL for this wallet provider */
146
- get icon() {
147
- return this._icon;
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
- }
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
198
- var isNativeToken = (xToken) => {
199
- const nativeAddresses = [
200
- "cx0000000000000000000000000000000000000000",
201
- "0x0000000000000000000000000000000000000000",
202
- "inj",
203
- "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI",
204
- "hx0000000000000000000000000000000000000000",
205
- "11111111111111111111111111111111",
206
- // solana
207
- "CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA",
208
- // stellar
209
- "ST000000000000000000002AMW42H.nativetoken",
210
- // stacks
211
- "0:0"
212
- // bitcoin
213
- ];
214
- return nativeAddresses.includes(xToken.address);
215
- };
216
- var getWagmiChainId = (xChainId) => {
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;
222
- };
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
- }
245
- }
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();
294
- }
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;
315
- }
316
- async getBalance(address, xToken) {
317
- if (!address) return 0n;
318
- if (!this.wagmiConfig) return 0n;
319
- const chainId = getWagmiChainId(xToken.chainKey);
320
- if (isNativeToken(xToken)) {
321
- return this._getChainBalance(address, chainId);
322
- }
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);
370
- }
371
- };
372
-
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;
380
- }
381
- async connect() {
382
- return;
383
- }
384
- async disconnect() {
385
- return;
386
- }
387
- get id() {
388
- return this.connector.id;
389
- }
390
- get icon() {
391
- if (!this.connector.icon && this.connector.type === "walletConnect") {
392
- return WALLETCONNECT_ICON;
393
- }
394
- return this.connector.icon;
395
- }
396
- };
397
- var SolanaXService = class _SolanaXService extends XService {
398
- static instance;
399
- connection;
400
- wallet;
401
- constructor() {
402
- super("SOLANA");
403
- }
404
- static getInstance() {
405
- if (!_SolanaXService.instance) {
406
- _SolanaXService.instance = new _SolanaXService();
407
- }
408
- return _SolanaXService.instance;
409
- }
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
- }
427
- }
428
- };
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);
449
- }
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");
471
- }
472
- static getInstance() {
473
- if (!_SuiXService.instance) {
474
- _SuiXService.instance = new _SuiXService();
475
- }
476
- return _SuiXService.instance;
477
- }
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;
485
- }
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
491
- });
492
- }
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";
502
- }
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 {};
523
- }
524
- }
525
- };
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 };
541
- }
542
- getXService() {
543
- return SuiXService.getInstance();
544
- }
545
- async connect() {
546
- return;
547
- }
548
- async disconnect() {
549
- }
550
- get icon() {
551
- return this.wallet.icon;
552
- }
553
- };
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;
561
- }
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}`);
581
- }
582
- return response.json().then((json) => StellarSdk.rpc.parseRawSimulation(json.result));
583
- }
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);
605
- }
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);
625
- }
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)}`);
637
- }
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"
669
- }
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, {});
693
- }
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
- }
704
- }
705
- return _StellarXService.instance;
706
- }
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);
737
- }
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;
746
- }
747
- getXService() {
748
- return StellarXService.getInstance();
749
- }
750
- async connect() {
751
- const kit = this.getXService().walletsKit;
752
- if (!this._wallet) {
753
- return;
754
- }
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();
760
- return {
761
- address,
762
- xChainType: this.xChainType
763
- };
764
- }
765
- async disconnect() {
766
- }
767
- get icon() {
768
- return this._wallet.icon;
769
- }
770
- get isInstalled() {
771
- return this._wallet.isAvailable;
772
- }
773
- get installUrl() {
774
- return this._wallet.url;
775
- }
776
- };
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
- );
793
- }
794
- static getInstance(rpcUrl) {
795
- if (!_IconXService.instance) {
796
- _IconXService.instance = new _IconXService(rpcUrl);
797
- }
798
- return _IconXService.instance;
799
- }
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);
815
- }
816
- }
817
- async getBalances(address, xTokens) {
818
- if (!address) return {};
819
- const balances = {};
820
- const nativeXToken = xTokens.find((xToken) => isNativeToken(xToken));
821
- const nonNativeXTokens = xTokens.filter((xToken) => !isNativeToken(xToken));
822
- if (nativeXToken) {
823
- const balance = await this.iconService.getBalance(address).execute();
824
- balances[nativeXToken.address] = BigInt(balance.toFixed());
825
- }
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"))
836
- );
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);
844
- }
845
- };
846
-
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;
880
- }
881
- async connect() {
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;
899
- }
900
- async disconnect() {
901
- console.log("HanaIconXConnector disconnected");
902
- }
903
- get icon() {
904
- return WALLET_METADATA.hana.icon;
905
- }
906
- };
907
- var InjectiveXService = class _InjectiveXService extends XService {
908
- static instance;
909
- walletStrategy;
910
- indexerGrpcAccountPortfolioApi;
911
- chainGrpcWasmApi;
912
- msgBroadcaster;
913
- constructor(rpcConfig) {
914
- super("INJECTIVE");
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
- };
921
- this.walletStrategy = new walletStrategy.WalletStrategy({
922
- chainId: tsTypes.ChainId.Mainnet,
923
- strategies: {},
924
- evmOptions: {
925
- evmChainId: chains$1.mainnet.id,
926
- rpcUrl: chains$1.mainnet.rpcUrls.default.http[0]
927
- }
928
- });
929
- this.indexerGrpcAccountPortfolioApi = new sdkTs.IndexerGrpcAccountPortfolioApi(endpoints.indexer);
930
- this.chainGrpcWasmApi = new sdkTs.ChainGrpcWasmApi(endpoints.grpc);
931
- this.msgBroadcaster = new walletCore.MsgBroadcaster({
932
- walletStrategy: this.walletStrategy,
933
- network: networks.Network.Mainnet,
934
- endpoints
935
- });
936
- }
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) {
944
- if (!_InjectiveXService.instance) {
945
- _InjectiveXService.instance = new _InjectiveXService(rpcConfig);
946
- }
947
- return _InjectiveXService.instance;
948
- }
949
- async getBalance(address, xToken) {
950
- if (!address) return 0n;
951
- const portfolio = await this.indexerGrpcAccountPortfolioApi.fetchAccountPortfolioBalances(address);
952
- const xTokenAddress = xToken.address;
953
- const balance = portfolio.bankBalancesList.find((_balance) => _balance.denom === xTokenAddress);
954
- if (balance) {
955
- return BigInt(balance.amount);
956
- }
957
- return 0n;
958
- }
959
- };
960
- var WALLET_ICONS = {
961
- metamask: "https://raw.githubusercontent.com/balancednetwork/icons/master/wallets/metamask.svg",
962
- keplr: "https://raw.githubusercontent.com/balancednetwork/icons/master/wallets/keplr.svg",
963
- leap: "https://assets.leapwallet.io/logos/leap-cosmos-logo.svg",
964
- rabby: "https://raw.githubusercontent.com/RabbyHub/logo/master/symbol.svg",
965
- phantom: "https://raw.githubusercontent.com/balancednetwork/icons/master/wallets/phantom.svg",
966
- "okx-wallet": "https://static.okx.com/cdn/assets/imgs/247/58E63FEA47A2B7D7.png",
967
- "trust-wallet": "https://trustwallet.com/assets/images/media/assets/twLogo.svg"
968
- };
969
- var InjectiveXConnector = class extends XConnector {
970
- wallet;
971
- constructor(name, wallet) {
972
- super("INJECTIVE", name, wallet);
973
- this.wallet = wallet;
974
- }
975
- getXService() {
976
- return InjectiveXService.getInstance();
977
- }
978
- async connect() {
979
- if (walletBase.isCosmosBrowserWallet(this.wallet) && !walletCosmos.isCosmosWalletInstalled(this.wallet)) {
980
- console.warn(`[InjectiveXConnector] connect: ${this.wallet} cosmos wallet not installed`);
981
- return void 0;
982
- }
983
- const walletStrategy = this.getXService().walletStrategy;
984
- await walletStrategy.setWallet(this.wallet);
985
- const addresses = await walletStrategy.getAddresses();
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;
996
- return {
997
- address,
998
- xChainType: this.xChainType
999
- };
1000
- }
1001
- async disconnect() {
1002
- if (walletBase.isEvmBrowserWallet(this.wallet)) {
1003
- const walletStrategy = this.getXService().walletStrategy;
1004
- await walletStrategy.setWallet(this.wallet);
1005
- await walletStrategy.disconnect();
1006
- }
1007
- }
1008
- get icon() {
1009
- return WALLET_ICONS[this.wallet];
1010
- }
1011
- get isInstalled() {
1012
- if (walletBase.isCosmosBrowserWallet(this.wallet)) {
1013
- return walletCosmos.isCosmosWalletInstalled(this.wallet);
1014
- }
1015
- return true;
1016
- }
1017
- };
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;
1026
- }
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;
1032
- }
1033
- return _BitcoinXService.instance;
1034
- }
1035
- async getBalance(address, xToken) {
1036
- if (!address) return 0n;
1037
- try {
1038
- if (isNativeToken(xToken)) {
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);
1044
- }
1045
- } catch {
1046
- return 0n;
1047
- }
1048
- return 0n;
1049
- }
1050
- };
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;
1058
- }
1059
- getXService() {
1060
- return BitcoinXService.getInstance();
1061
- }
1062
- };
1063
- var UnisatWalletProvider = class {
1064
- chainType = "BITCOIN";
1065
- cachedAddress;
1066
- defaults;
1067
- constructor(address, defaults) {
1068
- this.cachedAddress = address;
1069
- this.defaults = defaults;
1070
- }
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 {
1082
- }
1083
- return this.cachedAddress;
1084
- }
1085
- async getPublicKey() {
1086
- return this.unisat.getPublicKey();
1087
- }
1088
- async getAddressType(_address) {
1089
- const address = await this.getWalletAddress();
1090
- return types.detectBitcoinAddressType(address);
1091
- }
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;
1097
- }
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`);
1107
- }
1108
- return this.unisat.sendBitcoin(toAddress, Number(satoshis));
1109
- }
1110
- };
1111
- var UnisatXConnector = class _UnisatXConnector extends BitcoinXConnector {
1112
- walletProvider;
1113
- constructor(defaults) {
1114
- super("Unisat", "unisat", defaults);
1115
- }
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;
1127
- }
1128
- async connect() {
1129
- if (!window.unisat) {
1130
- throw new Error("Unisat wallet is not installed");
1131
- }
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;
1137
- }
1138
- this.walletProvider = new UnisatWalletProvider(address, this.defaults);
1139
- return {
1140
- address,
1141
- xChainType: "BITCOIN"
1142
- };
1143
- }
1144
- async disconnect() {
1145
- this.walletProvider = void 0;
1146
- }
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);
1153
- }
1154
- };
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;
1164
- }
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;
1184
- }
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;
1193
- }
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)
1246
- }
1247
- ]
1248
- });
1249
- if (response.status === "error") {
1250
- throw new Error(response.error?.message || "Xverse sendTransfer failed");
1251
- }
1252
- return response.result.txid;
1253
- }
1254
- };
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;
1264
- }
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
- }
1271
- }
1272
- static isAvailable() {
1273
- return typeof window !== "undefined" && !!window.BitcoinProvider;
1274
- }
1275
- get isInstalled() {
1276
- return _XverseXConnector.isAvailable();
1277
- }
1278
- get installUrl() {
1279
- return WALLET_METADATA.xverse.installUrl;
1280
- }
1281
- get icon() {
1282
- return WALLET_METADATA.xverse.icon;
1283
- }
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
- };
1309
- }
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() {
1336
- try {
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)
1757
- });
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);
1799
- } catch (err) {
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;
2196
- }
2197
- return _NearXService.instance;
2198
- }
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);
2204
- }
2205
- const res = await provider.callFunction({
2206
- contractId: xToken.address,
2207
- method: "ft_balance_of",
2208
- args: { account_id: address }
2209
- });
2210
- return BigInt(res ?? 0);
2211
- }
2212
- };
2213
-
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();
2223
- }
2224
- async connect() {
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;
2231
- }
2232
- return {
2233
- address: accounts[0].accountId,
2234
- xChainType: this.xChainType
2235
- };
2236
- }
2237
- async disconnect() {
2238
- const walletSelector = this.getXService().walletSelector;
2239
- await walletSelector.disconnect(this._wallet);
2240
- }
2241
- get icon() {
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
- }
2293
- }
2294
- };
2295
- function getProviderFromId(id) {
2296
- return id.split(".").reduce((acc, part) => acc?.[part], window);
2297
- }
2298
- var StacksXConnector = class extends XConnector {
2299
- config;
2300
- constructor(config) {
2301
- super("STACKS", config.name, config.id);
2302
- this.config = config;
2303
- }
2304
- async connect() {
2305
- const provider = this.getProvider();
2306
- if (!provider) {
2307
- throw new Error(`${this.config.name} is not installed. Install the extension and reload the page.`);
2308
- }
2309
- const response = await connect.request({ provider }, "stx_getAddresses");
2310
- const stxAddress = response.addresses.find((a) => a.purpose === "stacks");
2311
- if (!stxAddress) {
2312
- console.warn(
2313
- `[StacksXConnector] ${this.config.name}: no address with purpose="stacks" returned from stx_getAddresses`,
2314
- response.addresses
2315
- );
2316
- return void 0;
2317
- }
2318
- return {
2319
- address: stxAddress.address,
2320
- xChainType: this.xChainType
2321
- };
2322
- }
2323
- async disconnect() {
2324
- connect.disconnect();
2325
- }
2326
- get icon() {
2327
- return this.config.icon;
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
- }
2336
- getProvider() {
2337
- return getProviderFromId(this.config.id);
2338
- }
2339
- };
2340
-
2341
- // src/xchains/stacks/constants.ts
2342
- var LEATHER_ICON = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYuODM4NyIgZmlsbD0iIzEyMTAwRiIvPgo8cGF0aCBkPSJNNzQuOTE3MSA1Mi43MTE0QzgyLjQ3NjYgNTEuNTQwOCA5My40MDg3IDQzLjU4MDQgOTMuNDA4NyAzNy4zNzYxQzkzLjQwODcgMzUuNTAzMSA5MS44OTY4IDM0LjIxNTQgODkuNjg3MSAzNC4yMTU0Qzg1LjUwMDQgMzQuMjE1NCA3OC40MDYxIDQwLjUzNjggNzQuOTE3MSA1Mi43MTE0Wk0zOS45MTEgODMuNDk5MUMzMC4wMjU2IDgzLjQ5OTEgMjkuMjExNSA5My4zMzI0IDM5LjA5NjkgOTMuMzMyNEM0My41MTYzIDkzLjMzMjQgNDguODY2MSA5MS41NzY0IDUxLjY1NzMgODguNDE1N0M0Ny41ODY4IDg0LjkwMzggNDQuMjE0MSA4My40OTkxIDM5LjkxMSA4My40OTkxWk0xMDIuODI5IDc5LjI4NDhDMTAzLjQxIDk1Ljc5MDcgOTUuMDM2OSAxMDUuMDM5IDgwLjg0ODQgMTA1LjAzOUM3Mi40NzQ4IDEwNS4wMzkgNjguMjg4MSAxMDEuODc4IDU5LjMzMyA5Ni4wMjQ5QzU0LjY4MSAxMDEuMTc2IDQ1Ljg0MjMgMTA1LjAzOSAzOC41MTU0IDEwNS4wMzlDMTMuMjc4NSAxMDUuMDM5IDE0LjMyNTIgNzIuODQ2MyA0MC4wMjczIDcyLjg0NjNDNDUuMzc3MSA3Mi44NDYzIDQ5LjkxMjggNzQuMjUxMSA1NS43Mjc3IDc3Ljg4TDU5LjU2NTYgNjQuNDE3N0M0My43NDg5IDYwLjA4NjQgMzUuODQwNSA0Ny45MTE4IDQzLjYzMjYgMzAuNDY5M0g1Ni4xOTI5QzQ5LjIxNSA0Mi4wNTg2IDUzLjk4MzIgNTEuNjU3OCA2Mi44MjIgNTIuNzExNEM2Ny41OTAzIDM1LjczNzIgNzcuODI0NiAyMi41MDkgOTEuNDMxNiAyMi41MDlDOTkuMTA3NCAyMi41MDkgMTA1LjE1NSAyNy41NDI4IDEwNS4xNTUgMzYuNjczN0MxMDUuMTU1IDUxLjMwNjYgODYuMDgxOSA2My4yNDcxIDcxLjY2MDcgNjQuNDE3N0w2NS43Mjk1IDg1LjM3MjFDNzIuNDc0OCA5My4yMTUzIDkxLjE5OSAxMDAuODI0IDkxLjE5OSA3OS4yODQ4SDEwMi44MjlaIiBmaWxsPSIjRjVGMUVEIi8+Cjwvc3ZnPgo=";
2343
- var XVERSE_ICON = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MDAiIGhlaWdodD0iNjAwIj48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGZpbGw9IiMxNzE3MTciIGQ9Ik0wIDBoNjAwdjYwMEgweiIvPjxwYXRoIGZpbGw9IiNGRkYiIGZpbGwtcnVsZT0ibm9uemVybyIgZD0iTTQ0MCA0MzUuNHYtNTFjMC0yLS44LTMuOS0yLjItNS4zTDIyMCAxNjIuMmE3LjYgNy42IDAgMCAwLTUuNC0yLjJoLTUxLjFjLTIuNSAwLTQuNiAyLTQuNiA0LjZ2NDcuM2MwIDIgLjggNCAyLjIgNS40bDc4LjIgNzcuOGE0LjYgNC42IDAgMCAxIDAgNi41bC03OSA3OC43Yy0xIC45LTEuNCAyLTEuNCAzLjJ2NTJjMCAyLjQgMiA0LjUgNC42IDQuNUgyNDljMi42IDAgNC42LTIgNC42LTQuNlY0MDVjMC0xLjIuNS0yLjQgMS40LTMuM2w0Mi40LTQyLjJhNC42IDQuNiAwIDAgMSA2LjQgMGw3OC43IDc4LjRhNy42IDcuNiAwIDAgMCA1LjQgMi4yaDQ3LjVjMi41IDAgNC42LTIgNC42LTQuNloiLz48cGF0aCBmaWxsPSIjRUU3QTMwIiBmaWxsLXJ1bGU9Im5vbnplcm8iIGQ9Ik0zMjUuNiAyMjcuMmg0Mi44YzIuNiAwIDQuNiAyLjEgNC42IDQuNnY0Mi42YzAgNCA1IDYuMSA4IDMuMmw1OC43LTU4LjVjLjgtLjggMS4zLTIgMS4zLTMuMnYtNTEuMmMwLTIuNi0yLTQuNi00LjYtNC42TDM4NCAxNjBjLTEuMiAwLTIuNC41LTMuMyAxLjNsLTU4LjQgNTguMWE0LjYgNC42IDAgMCAwIDMuMiA3LjhaIi8+PC9nPjwvc3ZnPg==";
2344
- var ASIGNA_ICON = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMDEwMCIgZD0iTTAgMGgzMnYzMkgweiIvPjxwYXRoIGZpbGw9InVybCgjYSkiIGQ9Ik0xNS4xMSA1LjU1YTMgMyAwIDAgMC0xLjgyIDEuM2wtLjA1LjA4LS40My43Mi0uMDcuMTEtLjUuODUtLjA1LjA5LTEuMjkgMi4xOC0uMDQuMDctLjQ3LjgtLjA2LjEtLjQ2Ljc4LS4wNy4xMS0xLjYzIDIuNzYtLjA3LjExLS4zOC42Ni0uMDUuMDgtLjczIDEuMjQtLjM1LjYtLjQuNjctLjA1LjA5TDUuMSAyMC43bC0uMTEuMTgtLjE0LjIzLS4wNy4xMy0uMzMuNTUtLjA0LjA3di4wMWExLjI2IDEuMjYgMCAwIDAtLjE0LjQ3IDEuMzEgMS4zMSAwIDAgMCAxLjI0IDEuNGgxLjVsLjA1LS4wNi4wNC0uMDYuODctMS4yMS4wNS0uMDguNzctMS4wNy4wNS0uMDcuNC0uNTcuMDUtLjA2LjI0LS4zNGExLjUyIDEuNTIgMCAwIDEgMS4zOS0uNjIgMS41IDEuNSAwIDAgMSAuNjQuMiAxLjQ3IDEuNDcgMCAwIDEgLjczIDEuMjcgMS40NCAxLjQ0IDAgMCAxLS4yNy44NGwtLjYzLjg4LS4wNS4wNy0uMzIuNDUtLjA2LjA4LS4wOC4xMi0uMTIuMTYtLjA1LjA4aDIuMTNhMi4zMiAyLjMyIDAgMCAwIDEuNzctLjk2bDEuMTgtMS42My43Ny0xLjA4IDEuMy0xLjhhMS4yNCAxLjI0IDAgMCAxIC41NS0uNDNsLjA4LS4wM2ExLjMgMS4zIDAgMCAxIC4zLS4wNiAxLjI4IDEuMjggMCAwIDEgMS4xNS41NGwuMTEuMmExLjEzIDEuMTMgMCAwIDEgLjEuNDEgMS4xOSAxLjE5IDAgMCAxLS4yMy43N2wtLjAzLjA1LS41Ny44LS43Ljk4LS4yNy4zN2ExLjIyIDEuMjIgMCAwIDAtLjIuNSAxLjA1IDEuMDUgMCAwIDAtLjAyLjIzdi4wNmExLjE3IDEuMTcgMCAwIDAgLjE0LjQzbC4wMi4wNS4wNy4xYTEuNDQgMS40NCAwIDAgMCAuMS4xMWwuMDUuMDYuMDEuMDFhMS44IDEuOCAwIDAgMCAuMTQuMWMwIC4wMi4wMi4wMy4wNC4wM2ExIDEgMCAwIDAgLjA4LjA1bC4wNy4wNGExLjI1IDEuMjUgMCAwIDAgLjUuMWg2LjljLjEgMCAuMi0uMDEuMjktLjAzbC4wNi0uMDJhMS4yNyAxLjI3IDAgMCAwIC4yNy0uMS41Ny41NyAwIDAgMCAuMDctLjAzIDEuMjEgMS4yMSAwIDAgMCAuMjYtLjE5bC4wOC0uMDdhLjkyLjkyIDAgMCAwIC4xNS0uMTkgMS41NSAxLjU1IDAgMCAwIC4wOS0uMTdsLjAyLS4wNWExLjIyIDEuMjIgMCAwIDAgLjA4LS4yNnYtLjA0bC4wMi0uMDh2LS4wOGExLjMyIDEuMzIgMCAwIDAtLjItLjc0bC0xLjYtMi42NC0uMDYtLjEtLjItLjMyLS4zMy0uNTR2LS4wMWwtLjA1LS4wOC0xLjMtMi4xNS0uMDctLjEtLjA0LS4wNi0uOC0xLjMyLS4wNC0uMDctLjItLjM0LS4xLS4xNC0uMS0uMTYtLjUzLS45LS4xMy0uMi0uMDktLjE0LTIuMTctMy41Ny0uMDQtLjA3LS43Mi0xLjE5LS4wNS0uMDctLjQtLjY1YTIuNjUgMi42NSAwIDAgMC0uMy0uNCAyLjk2IDIuOTYgMCAwIDAtLjk3LS43NCAzLjA0IDMuMDQgMCAwIDAtMS4zLS4zYy0uMjUgMC0uNS4wNC0uNzQuMVoiLz48cGF0aCBmaWxsPSJ1cmwoI2IpIiBkPSJNMTkgMTYuM2E1LjQ1IDUuNDUgMCAwIDAtLjgzIDEuNTZsLS4wNC4xNWExLjM2IDEuMzYgMCAwIDEgLjI4LS4xNiAxLjI0IDEuMjQgMCAwIDEgLjM4LS4wOGguMWExLjI4IDEuMjggMCAwIDEgMS4wNS41NGMuMDQuMDYuMDguMTMuMS4yYTEuMjQgMS4yNCAwIDAgMSAuMDkuMjcgMS4xOSAxLjE5IDAgMCAxLS4yLjkxbC0uMDQuMDUtLjU3Ljc5LS43Ljk5LS4yNy4zN2ExLjIzIDEuMjMgMCAwIDAtLjIuNDIgMS4wNiAxLjA2IDAgMCAwLS4wMi4zMXYuMDZhMS4xNyAxLjE3IDAgMCAwIC4xNi40Ny45My45MyAwIDAgMCAuMDcuMSAxLjUgMS41IDAgMCAwIC4xLjEybC4wNS4wNmguMDFhMS45NCAxLjk0IDAgMCAwIC4wOS4wOCAxIDEgMCAwIDAgLjE3LjFsLjA3LjA0YTEuMjUgMS4yNSAwIDAgMCAuNS4xaDYuOWMuMSAwIC4yIDAgLjI4LS4wMmwuMDctLjAyYTEuMzIgMS4zMiAwIDAgMCAuMzQtLjEzbC4xNi0uMS4wMy0uMDNhMS4yOSAxLjI5IDAgMCAwIC4yLS4yIDIuNDMgMi40MyAwIDAgMCAuMTItLjE3Yy4wMy0uMDMuMDUtLjA4LjA3LS4xMmwuMDItLjA1YTEuMjEgMS4yMSAwIDAgMCAuMDktLjN2LS4wOGwuMDEtLjA5YTEuMzIgMS4zMiAwIDAgMC0uMi0uNzNsLTEuNi0yLjY0LS4wNi0uMS0uMi0uMzItLjMzLS41NHYtLjAybC0uMDUtLjA3LTEuMy0yLjE1LS4xMi0uMDctLjA3LS4wNGE0Ljk0IDQuOTQgMCAwIDAtMi40Ni0uNjdjLTEuMDMgMC0xLjc2LjU3LTIuMjYgMS4yWiIvPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0xMi4yOSAyMS4wOGMwIC4yOS0uMDkuNTgtLjI3Ljg0bC0xLjMxIDEuODRIN2wyLjUyLTMuNTNhMS41NCAxLjU0IDAgMCAxIDIuMS0uMzZjLjQzLjI4LjY2Ljc0LjY2IDEuMloiLz48cGF0aCBmaWxsPSIjMDAwIiBkPSJNMTEuMTYgMjEuMjVhLjU2LjU2IDAgMCAxLS41Ny41NS41Ni41NiAwIDAgMS0uNTctLjU2LjU2LjU2IDAgMCAxIC41Ny0uNTUuNTYuNTYgMCAwIDEgLjU3LjU2WiIvPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0iYSIgeDE9IjE1LjIzIiB4Mj0iMTkuMyIgeTE9IjI1Ljc4IiB5Mj0iNi4xMSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiM2NTIyRjQiLz48c3RvcCBvZmZzZXQ9Ii41NSIgc3RvcC1jb2xvcj0iIzlCNkJGRiIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI0E1ODVGRiIvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSJiIiB4MT0iMjIuNTkiIHgyPSIyNC44IiB5MT0iMjQuNzEiIHkyPSIxNS41MyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiM0MjFGOEIiLz48c3RvcCBvZmZzZXQ9Ii41NSIgc3RvcC1jb2xvcj0iIzcyMzBGRiIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzk3NzNGRiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjwvc3ZnPg==";
2345
- var FORDEFI_ICON = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDIiIGhlaWdodD0iNDIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZmlsbD0iIzEwMTExNCIgZD0iTTAgMGg0MnY0MkgweiIvPgogIDxwYXRoIGQ9Ik0xOS40NyAyNi44OUg1djMuNTdhNC41NyA0LjU3IDAgMCAwIDQuNTggNC41N2g1LjgzbDQuMDYtOC4xNFoiIGZpbGw9IiM3OTk0RkYiLz4KICA8cGF0aCBkPSJNNSAxNy40aDI3LjU4bC0zLjIgNi43OEg1VjE3LjRaIiBmaWxsPSIjNDg2REZGIi8+CiAgPHBhdGggZD0iTTE0LjY3IDdINXY3LjY4aDMzVjdoLTkuNjd2NS43NGgtMlY3aC05LjY3djUuNzRoLTEuOTlWN1oiIGZpbGw9IiM1Q0QxRkEiLz4KPC9zdmc+Cg==";
2346
- var STACKS_PROVIDERS = [
2347
- {
2348
- id: "LeatherProvider",
2349
- name: "Leather",
2350
- icon: LEATHER_ICON,
2351
- installUrl: "https://chrome.google.com/webstore/detail/hiro-wallet/ldinpeekobnhjjdofggfgjlcehhmanlj"
2352
- },
2353
- {
2354
- id: "XverseProviders.BitcoinProvider",
2355
- name: "Xverse Wallet",
2356
- icon: XVERSE_ICON,
2357
- installUrl: "https://chrome.google.com/webstore/detail/xverse-wallet/idnnbdplmphpflfnlkomgpfbpcgelopg"
2358
- },
2359
- {
2360
- id: "AsignaProvider",
2361
- name: "Asigna Multisig",
2362
- icon: ASIGNA_ICON,
2363
- installUrl: "https://stx.asigna.io/"
2364
- },
2365
- {
2366
- id: "FordefiProviders.UtxoProvider",
2367
- name: "Fordefi",
2368
- icon: FORDEFI_ICON,
2369
- installUrl: "https://chromewebstore.google.com/detail/fordefi/hcmehenccjdmfbojapcbcofkgdpbnlle"
2370
- }
2371
- ];
2372
-
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) => {
2631
- const xServices = {};
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
- }
2653
- }
2654
- }
2655
- return { xServices, xConnectorsByChain, enabledChains, chainActions };
2656
- };
2657
-
2658
- // src/useXWalletStore.ts
2659
- var useXWalletStore = zustand.create()(
2660
- middleware.devtools(
2661
- middleware.persist(
2662
- immer.immer((set, get) => ({
2663
- xServices: {},
2664
- xConnections: {},
2665
- xConnectorsByChain: {},
2666
- enabledChains: [],
2667
- chainActions: {},
2668
- walletProviders: {},
2669
- walletConfig: void 0,
2670
- userDisconnected: {},
2671
- setXConnection: (xChainType, xConnection) => {
2672
- set((state) => {
2673
- state.xConnections[xChainType] = xConnection;
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
- }
2683
- },
2684
- unsetXConnection: (xChainType) => {
2685
- set((state) => {
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];
2741
- });
2742
- }
2743
- })),
2744
- {
2745
- // key kept as 'xwagmi-store' for backward compat — existing users won't lose persisted connections on upgrade
2746
- name: "xwagmi-store",
2747
- storage: middleware.createJSONStorage(() => localStorage),
2748
- partialize: (state) => ({
2749
- xConnections: state.xConnections,
2750
- userDisconnected: state.userDisconnected
2751
- })
2752
- }
2753
- ),
2754
- { name: "xwagmi-store" }
2755
- )
2756
- );
2757
-
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;
2765
- }
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;
2781
- }
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;
2865
- }
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);
2878
- }
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;
2885
- }
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.");
2905
- }
2906
- }
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
- };
2915
-
2916
- // src/xchains/solana/SolanaXConnector.ts
2917
- var SolanaXConnector = class extends XConnector {
2918
- wallet;
2919
- constructor(wallet) {
2920
- super("SOLANA", wallet?.adapter.name, wallet?.adapter.name);
2921
- this.wallet = wallet;
2922
- }
2923
- getXService() {
2924
- return SolanaXService.getInstance();
2925
- }
2926
- async connect() {
2927
- return;
2928
- }
2929
- async disconnect() {
2930
- }
2931
- get icon() {
2932
- return this.wallet?.adapter.icon;
2933
- }
2934
- get isInstalled() {
2935
- const state = this.wallet?.readyState;
2936
- return state === "Installed" || state === "Loadable";
2937
- }
2938
- get installUrl() {
2939
- return this.wallet?.adapter.url;
2940
- }
2941
- };
2942
-
2943
- // src/providers/solana/SolanaHydrator.tsx
2944
- var SolanaHydrator = () => {
2945
- const { connection } = walletAdapterReact.useConnection();
2946
- const solanaWallet = walletAdapterReact.useWallet();
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]
2953
- );
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;
2962
- });
2963
- const solanaConnectors = react.useMemo(
2964
- () => solanaWallet.wallets.filter((wallet) => wallet.readyState === "Installed").map((wallet) => new SolanaXConnector(wallet)),
2965
- [solanaWallet.wallets]
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;
2999
- };
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
- );
3016
- return void 0;
3017
- }
3018
- walletRef.current.select(wallet.adapter.name);
3019
- if (wallet.adapter.connected) {
3020
- return void 0;
3021
- }
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);
3050
- });
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");
3061
- }
3062
- const signature = await walletRef.current.signMessage(new TextEncoder().encode(message));
3063
- return Buffer.from(signature).toString("base64");
3064
- }
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
- });
3123
- }
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();
3135
- const { mutateAsync: signPersonalMessage } = dappKit.useSignPersonalMessage();
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)
3161
- );
3162
- return void 0;
3163
- }
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;
3175
- }
3176
- });
3177
- }, [registerChainActions]);
3178
- return null;
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
- };
3190
-
3191
- // src/xchains/icon/actions.ts
3192
- var reconnectIcon = async () => {
3193
- const iconConnection = useXWalletStore.getState().xConnections.ICON;
3194
- if (!iconConnection) return;
3195
- const recentXConnectorId = iconConnection.xConnectorId;
3196
- const detail = await request({
3197
- type: "REQUEST_ADDRESS" /* REQUEST_ADDRESS */
3198
- });
3199
- if (detail?.type === "RESPONSE_ADDRESS" /* RESPONSE_ADDRESS */) {
3200
- useXWalletStore.getState().setXConnection("ICON", {
3201
- xAccount: {
3202
- address: detail?.payload,
3203
- xChainType: "ICON"
3204
- },
3205
- xConnectorId: recentXConnectorId
3206
- });
3207
- }
3208
- };
3209
- function isWallet(value) {
3210
- return Object.values(walletBase.Wallet).some((v) => v === value);
3211
- }
3212
- var reconnectInjective = async () => {
3213
- const injectiveConnection = useXWalletStore.getState().xConnections.INJECTIVE;
3214
- if (!injectiveConnection) return;
3215
- const recentXConnectorId = injectiveConnection.xConnectorId;
3216
- if (!isWallet(recentXConnectorId)) {
3217
- console.warn(`[Injective] Stale wallet ID skipped: ${recentXConnectorId}`);
3218
- return;
3219
- }
3220
- const walletStrategy = InjectiveXService.getInstance().walletStrategy;
3221
- await walletStrategy.setWallet(recentXConnectorId);
3222
- const addresses = await walletStrategy.getAddresses();
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
3232
- });
3233
- };
3234
-
3235
- // src/xchains/stellar/actions.ts
3236
- var reconnectStellar = async () => {
3237
- const stellarConnection = useXWalletStore.getState().xConnections.STELLAR;
3238
- if (!stellarConnection) return;
3239
- const recentXConnectorId = stellarConnection.xConnectorId;
3240
- const stellarWalletKit = StellarXService.getInstance().walletsKit;
3241
- stellarWalletKit.setWallet(recentXConnectorId);
3242
- const { address } = await stellarWalletKit.getAddress();
3243
- useXWalletStore.getState().setXConnection("STELLAR", {
3244
- xAccount: {
3245
- address,
3246
- xChainType: "STELLAR"
3247
- },
3248
- xConnectorId: recentXConnectorId
3249
- });
3250
- };
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 });
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 });
3298
- };
3299
-
3300
- exports.SodaxWalletProvider = SodaxWalletProvider;
3301
- exports.WalletConfigProvider = WalletConfigProvider;
3302
- exports.XConnector = XConnector;
3303
- exports.XService = XService;
3304
- exports.getEntryDefaults = getEntryDefaults;
3305
- exports.getRpcUrl = getRpcUrl;
3306
- exports.getWagmiChainId = getWagmiChainId;
3307
- exports.getXChainType = getXChainType;
3308
- exports.getXService = getXService;
3309
- exports.isNativeToken = isNativeToken;
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;
3319
- exports.useEvmSwitchChain = useEvmSwitchChain;
3320
- exports.useIsChainEnabled = useIsChainEnabled;
3321
- exports.useIsWalletInstalled = useIsWalletInstalled;
3322
- exports.useWalletConfig = useWalletConfig;
3323
- exports.useWalletModal = useWalletModal;
3324
- exports.useWalletProvider = useWalletProvider;
3325
- exports.useXAccount = useXAccount;
3326
- exports.useXAccounts = useXAccounts;
3327
- exports.useXConnect = useXConnect;
3328
- exports.useXConnection = useXConnection;
3329
- exports.useXConnections = useXConnections;
3330
- exports.useXConnectors = useXConnectors;
3331
- exports.useXConnectorsByChain = useXConnectorsByChain;
3332
- exports.useXDisconnect = useXDisconnect;
3333
- exports.useXService = useXService;
3334
- exports.useXServices = useXServices;
3335
- exports.useXSignMessage = useXSignMessage;
3336
- //# sourceMappingURL=index.cjs.map
3337
- //# sourceMappingURL=index.cjs.map