@sodax/wallet-sdk-react 1.5.6-beta → 2.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -145
- package/ai-exported/AGENTS.md +122 -0
- package/ai-exported/integration/README.md +102 -0
- package/ai-exported/integration/ai-rules.md +136 -0
- package/ai-exported/integration/architecture.md +181 -0
- package/ai-exported/integration/examples/01-minimal-evm.tsx +75 -0
- package/ai-exported/integration/examples/02-multi-chain-modal.tsx +169 -0
- package/ai-exported/integration/examples/03-nextjs-app-router.tsx +99 -0
- package/ai-exported/integration/examples/04-walletconnect-setup.tsx +89 -0
- package/ai-exported/integration/examples/README.md +29 -0
- package/ai-exported/integration/recipes/batch-operations.md +223 -0
- package/ai-exported/integration/recipes/bridge-to-sdk.md +164 -0
- package/ai-exported/integration/recipes/chain-detection.md +254 -0
- package/ai-exported/integration/recipes/connect-button.md +156 -0
- package/ai-exported/integration/recipes/multi-chain-modal.md +199 -0
- package/ai-exported/integration/recipes/setup.md +158 -0
- package/ai-exported/integration/recipes/sign-message.md +137 -0
- package/ai-exported/integration/recipes/sub-path-imports.md +95 -0
- package/ai-exported/integration/recipes/switch-chain.md +141 -0
- package/ai-exported/integration/recipes/walletconnect-setup.md +139 -0
- package/ai-exported/integration/reference/api-surface.md +175 -0
- package/ai-exported/integration/reference/chain-support.md +78 -0
- package/ai-exported/integration/reference/connectors.md +74 -0
- package/ai-exported/integration/reference/hooks.md +204 -0
- package/ai-exported/integration/reference/wallet-brands.md +106 -0
- package/ai-exported/migration/README.md +49 -0
- package/ai-exported/migration/ai-rules.md +144 -0
- package/ai-exported/migration/breaking-changes.md +305 -0
- package/ai-exported/migration/checklist.md +159 -0
- package/ai-exported/migration/recipes/connect-button.md +166 -0
- package/ai-exported/migration/recipes/multi-chain-modal.md +244 -0
- package/ai-exported/migration/recipes/ssr-setup.md +162 -0
- package/ai-exported/migration/recipes/walletconnect-migration.md +168 -0
- package/ai-exported/migration/reference/components.md +73 -0
- package/ai-exported/migration/reference/config.md +307 -0
- package/ai-exported/migration/reference/hooks.md +278 -0
- package/ai-exported/migration/reference/imports.md +157 -0
- package/dist/XConnector-B9YQTVJ4.d.ts +146 -0
- package/dist/chunk-2BOUGCJ7.mjs +150 -0
- package/dist/chunk-2BOUGCJ7.mjs.map +1 -0
- package/dist/chunk-66BAUK56.mjs +202 -0
- package/dist/chunk-66BAUK56.mjs.map +1 -0
- package/dist/chunk-7ULB6DW4.mjs +102 -0
- package/dist/chunk-7ULB6DW4.mjs.map +1 -0
- package/dist/chunk-BKJB527E.mjs +125 -0
- package/dist/chunk-BKJB527E.mjs.map +1 -0
- package/dist/chunk-BXJLBR4G.mjs +88 -0
- package/dist/chunk-BXJLBR4G.mjs.map +1 -0
- package/dist/chunk-E5IAZ7E6.mjs +186 -0
- package/dist/chunk-E5IAZ7E6.mjs.map +1 -0
- package/dist/chunk-MAQ47Q52.mjs +33 -0
- package/dist/chunk-MAQ47Q52.mjs.map +1 -0
- package/dist/chunk-MXZVF5HR.mjs +34 -0
- package/dist/chunk-MXZVF5HR.mjs.map +1 -0
- package/dist/chunk-N5A2TMF6.mjs +33 -0
- package/dist/chunk-N5A2TMF6.mjs.map +1 -0
- package/dist/chunk-NY7U7OJW.mjs +64 -0
- package/dist/chunk-NY7U7OJW.mjs.map +1 -0
- package/dist/chunk-PJLEJVAU.mjs +140 -0
- package/dist/chunk-PJLEJVAU.mjs.map +1 -0
- package/dist/chunk-PLCA4ZDJ.mjs +1585 -0
- package/dist/chunk-PLCA4ZDJ.mjs.map +1 -0
- package/dist/chunk-TZMKDXFA.mjs +3 -0
- package/dist/chunk-TZMKDXFA.mjs.map +1 -0
- package/dist/chunk-X2MHIWXO.mjs +100 -0
- package/dist/chunk-X2MHIWXO.mjs.map +1 -0
- package/dist/chunk-XZ7CHO2S.mjs +41 -0
- package/dist/chunk-XZ7CHO2S.mjs.map +1 -0
- package/dist/config-OlnzyEUE.d.ts +146 -0
- package/dist/index.cjs +2784 -1594
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +768 -1498
- package/dist/index.mjs +463 -2004
- package/dist/index.mjs.map +1 -1
- package/dist/xchains/bitcoin/index.cjs +1927 -0
- package/dist/xchains/bitcoin/index.cjs.map +1 -0
- package/dist/xchains/bitcoin/index.d.ts +125 -0
- package/dist/xchains/bitcoin/index.mjs +16 -0
- package/dist/xchains/bitcoin/index.mjs.map +1 -0
- package/dist/xchains/evm/index.cjs +316 -0
- package/dist/xchains/evm/index.cjs.map +1 -0
- package/dist/xchains/evm/index.d.ts +39 -0
- package/dist/xchains/evm/index.mjs +5 -0
- package/dist/xchains/evm/index.mjs.map +1 -0
- package/dist/xchains/icon/index.cjs +311 -0
- package/dist/xchains/icon/index.cjs.map +1 -0
- package/dist/xchains/icon/index.d.ts +37 -0
- package/dist/xchains/icon/index.mjs +7 -0
- package/dist/xchains/icon/index.mjs.map +1 -0
- package/dist/xchains/injective/index.cjs +223 -0
- package/dist/xchains/injective/index.cjs.map +1 -0
- package/dist/xchains/injective/index.d.ts +35 -0
- package/dist/xchains/injective/index.mjs +5 -0
- package/dist/xchains/injective/index.mjs.map +1 -0
- package/dist/xchains/near/index.cjs +190 -0
- package/dist/xchains/near/index.cjs.map +1 -0
- package/dist/xchains/near/index.d.ts +34 -0
- package/dist/xchains/near/index.mjs +6 -0
- package/dist/xchains/near/index.mjs.map +1 -0
- package/dist/xchains/solana/index.cjs +186 -0
- package/dist/xchains/solana/index.cjs.map +1 -0
- package/dist/xchains/solana/index.d.ts +26 -0
- package/dist/xchains/solana/index.mjs +7 -0
- package/dist/xchains/solana/index.mjs.map +1 -0
- package/dist/xchains/stacks/index.cjs +240 -0
- package/dist/xchains/stacks/index.cjs.map +1 -0
- package/dist/xchains/stacks/index.d.ts +36 -0
- package/dist/xchains/stacks/index.mjs +5 -0
- package/dist/xchains/stacks/index.mjs.map +1 -0
- package/dist/xchains/stellar/index.cjs +322 -0
- package/dist/xchains/stellar/index.cjs.map +1 -0
- package/dist/xchains/stellar/index.d.ts +44 -0
- package/dist/xchains/stellar/index.mjs +6 -0
- package/dist/xchains/stellar/index.mjs.map +1 -0
- package/dist/xchains/sui/index.cjs +248 -0
- package/dist/xchains/sui/index.cjs.map +1 -0
- package/dist/xchains/sui/index.d.ts +37 -0
- package/dist/xchains/sui/index.mjs +7 -0
- package/dist/xchains/sui/index.mjs.map +1 -0
- package/docs/ADDING_A_NEW_CHAIN.md +440 -0
- package/docs/ARCHITECTURE.md +291 -0
- package/docs/BATCH_OPERATIONS.md +267 -0
- package/docs/CHAIN_DETECTION.md +216 -0
- package/docs/CONFIGURE_PROVIDER.md +360 -0
- package/docs/CONNECTORS.md +247 -0
- package/docs/CONNECT_FLOW.md +276 -0
- package/docs/EVM_SWITCH_CHAIN.md +161 -0
- package/docs/SIGN_MESSAGE.md +213 -0
- package/docs/SUB_PATH_EXPORTS.md +246 -0
- package/docs/WALLETCONNECT.md +154 -0
- package/docs/WALLET_MODAL.md +331 -0
- package/docs/WALLET_PROVIDER_BRIDGE.md +226 -0
- package/package.json +34 -9
- package/skills/SKILLS.md +84 -0
- package/skills/bridge-to-sdk.md +148 -0
- package/skills/connect-button.md +116 -0
- package/skills/evm-only-walletconnect.md +111 -0
- package/skills/multi-chain-modal.md +178 -0
- package/skills/setup.md +107 -0
- package/dist/index.d.cts +0 -1579
- package/src/Hydrate.ts +0 -65
- package/src/SodaxWalletProvider.tsx +0 -97
- package/src/actions/getXChainType.ts +0 -8
- package/src/actions/getXService.ts +0 -33
- package/src/actions/index.ts +0 -2
- package/src/assets/wallets/hana.svg +0 -6
- package/src/assets/wallets/havah.svg +0 -76
- package/src/assets/wallets/keplr.svg +0 -30
- package/src/assets/wallets/metamask.svg +0 -60
- package/src/assets/wallets/phantom.svg +0 -4
- package/src/assets/wallets/sui.svg +0 -20
- package/src/core/XConnector.ts +0 -54
- package/src/core/XService.ts +0 -85
- package/src/core/index.ts +0 -2
- package/src/hooks/index.ts +0 -11
- package/src/hooks/useEthereumChainId.ts +0 -44
- package/src/hooks/useEvmSwitchChain.ts +0 -91
- package/src/hooks/useWalletProvider.ts +0 -206
- package/src/hooks/useXAccount.ts +0 -51
- package/src/hooks/useXAccounts.ts +0 -56
- package/src/hooks/useXBalances.ts +0 -65
- package/src/hooks/useXConnect.ts +0 -118
- package/src/hooks/useXConnection.ts +0 -72
- package/src/hooks/useXConnectors.ts +0 -72
- package/src/hooks/useXDisconnect.ts +0 -73
- package/src/hooks/useXService.ts +0 -8
- package/src/hooks/useXSignMessage.ts +0 -82
- package/src/index.ts +0 -19
- package/src/types/index.ts +0 -22
- package/src/useXWagmiStore.ts +0 -116
- package/src/utils/index.ts +0 -21
- package/src/xchains/bitcoin/BitcoinXConnector.ts +0 -34
- package/src/xchains/bitcoin/BitcoinXService.ts +0 -40
- package/src/xchains/bitcoin/OKXXConnector.ts +0 -117
- package/src/xchains/bitcoin/UnisatXConnector.ts +0 -117
- package/src/xchains/bitcoin/XverseXConnector.ts +0 -232
- package/src/xchains/bitcoin/index.ts +0 -7
- package/src/xchains/bitcoin/useBitcoinXConnectors.ts +0 -14
- package/src/xchains/evm/EvmXConnector.ts +0 -27
- package/src/xchains/evm/EvmXService.ts +0 -211
- package/src/xchains/evm/index.ts +0 -3
- package/src/xchains/icon/IconHanaXConnector.ts +0 -39
- package/src/xchains/icon/IconXService.ts +0 -117
- package/src/xchains/icon/actions.ts +0 -28
- package/src/xchains/icon/iconex/index.tsx +0 -46
- package/src/xchains/icon/index.ts +0 -2
- package/src/xchains/injective/InjectiveXConnector.ts +0 -60
- package/src/xchains/injective/InjectiveXService.ts +0 -62
- package/src/xchains/injective/actions.ts +0 -32
- package/src/xchains/injective/index.ts +0 -2
- package/src/xchains/near/NearXConnector.ts +0 -42
- package/src/xchains/near/NearXService.ts +0 -46
- package/src/xchains/near/useNearXConnectors.ts +0 -23
- package/src/xchains/solana/SolanaXConnector.ts +0 -26
- package/src/xchains/solana/SolanaXService.ts +0 -46
- package/src/xchains/solana/index.ts +0 -2
- package/src/xchains/stacks/StacksXConnector.ts +0 -63
- package/src/xchains/stacks/StacksXService.ts +0 -59
- package/src/xchains/stacks/constants.ts +0 -42
- package/src/xchains/stacks/index.ts +0 -4
- package/src/xchains/stacks/useStacksXConnectors.ts +0 -7
- package/src/xchains/stellar/CustomSorobanServer.ts +0 -93
- package/src/xchains/stellar/StellarWalletsKitXConnector.ts +0 -53
- package/src/xchains/stellar/StellarXService.ts +0 -93
- package/src/xchains/stellar/actions.ts +0 -24
- package/src/xchains/stellar/index.tsx +0 -2
- package/src/xchains/stellar/useStellarXConnectors.ts +0 -21
- package/src/xchains/stellar/utils.ts +0 -49
- package/src/xchains/sui/SuiXConnector.ts +0 -28
- package/src/xchains/sui/SuiXService.ts +0 -66
- package/src/xchains/sui/index.ts +0 -2
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Wallet Provider Bridge
|
|
2
|
+
|
|
3
|
+
`@sodax/wallet-sdk-react` is the bridge between the connected browser wallet and the chain-agnostic SDK call surface in `@sodax/sdk`. After a user connects a wallet, `useWalletProvider` returns a typed `IXxxWalletProvider` (from `@sodax/sdk`) that you pass directly into any SDK method — the SDK signs and broadcasts via that provider.
|
|
4
|
+
|
|
5
|
+
The canonical interfaces are defined in [`@sodax/sdk`](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/src/index.ts) (`IEvmWalletProvider`, `ISolanaWalletProvider`, …) and re-exported through `@sodax/wallet-sdk-core`.
|
|
6
|
+
|
|
7
|
+
## Table of contents
|
|
8
|
+
|
|
9
|
+
1. [Why a bridge layer](#why-a-bridge-layer)
|
|
10
|
+
2. [`useWalletProvider` — typed provider for one chain](#usewalletprovider--typed-provider-for-one-chain)
|
|
11
|
+
3. [End-to-end example](#end-to-end-example)
|
|
12
|
+
4. [Service hooks (`useXService` / `useXServices`)](#service-hooks-usexservice--usexservices)
|
|
13
|
+
5. [How wallet providers are populated](#how-wallet-providers-are-populated)
|
|
14
|
+
6. [Disabled chains return `undefined`](#disabled-chains-return-undefined)
|
|
15
|
+
7. [Bypassing the bridge — when to skip `useWalletProvider`](#bypassing-the-bridge--when-to-skip-usewalletprovider)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Why a bridge layer
|
|
20
|
+
|
|
21
|
+
`@sodax/sdk` is wallet-library-agnostic — it accepts any object implementing the per-chain `IXxxWalletProvider` interface (see [`packages/sdk/docs/WALLET_PROVIDERS.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/WALLET_PROVIDERS.md)). The implementation can come from:
|
|
22
|
+
|
|
23
|
+
- **Browser dApp** — `@sodax/wallet-sdk-react` Hydrators wrap `wagmi` / `@solana/wallet-adapter` / `@mysten/dapp-kit` etc. into provider instances and store them in the Zustand store. `useWalletProvider` reads them out.
|
|
24
|
+
- **Server / script / bot** — `@sodax/wallet-sdk-core` exposes the same provider classes (`EvmWalletProvider`, `SolanaWalletProvider`, …) constructed directly from a private key. No React, no wallet-sdk-react.
|
|
25
|
+
|
|
26
|
+
`useWalletProvider` is the React-side bridge. It hides the per-chain construction details and gives you a typed handle that fits the SDK call slot exactly:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
// SDK call shape (signed mode)
|
|
30
|
+
sodax.swaps.swap({
|
|
31
|
+
params: { srcChainKey: ChainKeys.BSC_MAINNET, /* ... */ },
|
|
32
|
+
walletProvider, // must satisfy IEvmWalletProvider for BSC
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET })` returns exactly `IEvmWalletProvider | undefined` — TypeScript narrows the return type from the chain key.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## `useWalletProvider` — typed provider for one chain
|
|
41
|
+
|
|
42
|
+
Two overloads, mutually exclusive: pass `xChainId` (a `SpokeChainKey`) **or** `xChainType` (a `ChainType`), never both.
|
|
43
|
+
|
|
44
|
+
### By chain id — narrowest typing
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { useWalletProvider } from '@sodax/wallet-sdk-react';
|
|
48
|
+
import { ChainKeys } from '@sodax/types';
|
|
49
|
+
|
|
50
|
+
const walletProvider = useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET });
|
|
51
|
+
// walletProvider: IEvmWalletProvider | undefined
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The chain id (`BSC_MAINNET`, `SOLANA_MAINNET`, etc.) resolves to its family at compile time via `GetChainType<S>` and the return type is the matching `IXxxWalletProvider`.
|
|
55
|
+
|
|
56
|
+
### By chain type — family-level typing
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
const evmProvider = useWalletProvider({ xChainType: 'EVM' });
|
|
60
|
+
// evmProvider: IEvmWalletProvider | undefined
|
|
61
|
+
|
|
62
|
+
const solProvider = useWalletProvider({ xChainType: 'SOLANA' });
|
|
63
|
+
// solProvider: ISolanaWalletProvider | undefined
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Use this when the surrounding component is family-level (e.g. an EVM dashboard that doesn't care which specific EVM chain is active). For EVM specifically, one wagmi connection covers all configured EVM networks — the same provider is returned for every `xChainId` in the EVM family.
|
|
67
|
+
|
|
68
|
+
### No-arg form
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
const wp = useWalletProvider();
|
|
72
|
+
// wp: undefined — no chain specified
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Both fields are optional but at least one must be set for the hook to return anything.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## End-to-end example
|
|
80
|
+
|
|
81
|
+
Connect once, then drive an SDK call with the resulting provider:
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import { useWalletProvider, useXAccount } from '@sodax/wallet-sdk-react';
|
|
85
|
+
import { useSodaxContext } from '@sodax/dapp-kit'; // or hold a Sodax instance directly
|
|
86
|
+
import { ChainKeys } from '@sodax/types';
|
|
87
|
+
import type { CreateIntentParams } from '@sodax/sdk';
|
|
88
|
+
|
|
89
|
+
function SwapButton({ params }: { params: CreateIntentParams<typeof ChainKeys.BSC_MAINNET> }) {
|
|
90
|
+
const walletProvider = useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET });
|
|
91
|
+
const account = useXAccount({ xChainId: ChainKeys.BSC_MAINNET });
|
|
92
|
+
const { sodax } = useSodaxContext();
|
|
93
|
+
|
|
94
|
+
const handleSwap = async () => {
|
|
95
|
+
if (!walletProvider) return;
|
|
96
|
+
const result = await sodax.swaps.swap({
|
|
97
|
+
params,
|
|
98
|
+
walletProvider, // typed as IEvmWalletProvider — matches BSC src chain
|
|
99
|
+
});
|
|
100
|
+
if (!result.ok) {
|
|
101
|
+
console.error('swap failed:', result.error);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
console.log('swap submitted:', result.value);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<button onClick={handleSwap} disabled={!walletProvider || !account.address}>
|
|
109
|
+
Swap
|
|
110
|
+
</button>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The same pattern works for every SDK feature service — `sodax.bridge.bridge`, `sodax.moneyMarket.supply`, `sodax.staking.stake`, `sodax.dex.deposit`, etc. See [`packages/sdk/docs/`](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/) for per-feature method signatures.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Service hooks (`useXService` / `useXServices`)
|
|
120
|
+
|
|
121
|
+
Lower-level than `useWalletProvider` — these expose the chain's `XService` instance, used for:
|
|
122
|
+
|
|
123
|
+
- Reading per-chain balances (`xService.getBalance(address, xToken)`)
|
|
124
|
+
- Listing connectors (`xService.getXConnectors()`)
|
|
125
|
+
- Looking up a connector by id (`xService.getXConnectorById(id)`)
|
|
126
|
+
- Custom integrations against the `IXService` contract
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { useXService, useXServices } from '@sodax/wallet-sdk-react';
|
|
130
|
+
|
|
131
|
+
const evmService = useXService({ xChainType: 'EVM' });
|
|
132
|
+
// evmService: XService | undefined — chain-specific instance (EvmXService)
|
|
133
|
+
|
|
134
|
+
const allServices = useXServices();
|
|
135
|
+
// allServices: Partial<Record<ChainType, XService>>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
For typed access, depend on the public [`IXService`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/src/types/interfaces.ts) interface rather than the concrete `XService` class. Concrete classes (`EvmXService`, `BitcoinXService`, …) are not exported from the package barrel; if you need a concrete class for `instanceof`, use the deep-import sub-path — see [`CONNECTORS.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECTORS.md).
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## How wallet providers are populated
|
|
143
|
+
|
|
144
|
+
The store's `walletProviders` map is populated by two distinct mechanisms depending on chain type:
|
|
145
|
+
|
|
146
|
+
### Provider-managed chains (EVM, Solana, Sui)
|
|
147
|
+
|
|
148
|
+
The chain's **Hydrator** is the sole writer. It subscribes to the native SDK hooks (e.g. `useAccount` from wagmi) and writes a fresh `EvmWalletProvider` (from `@sodax/wallet-sdk-core`) into the store every time the underlying client changes:
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
wagmi connection observed → EvmHydrator constructs EvmWalletProvider({ walletClient, publicClient })
|
|
152
|
+
│
|
|
153
|
+
↓
|
|
154
|
+
store.walletProviders.EVM = provider
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
`useWalletProvider({ xChainType: 'EVM' })` reads that slot — no chain-specific switch case in user code.
|
|
158
|
+
|
|
159
|
+
### Non-provider chains (Bitcoin, ICON, Injective, Stellar, NEAR, Stacks)
|
|
160
|
+
|
|
161
|
+
The provider is created as a side-effect of `setXConnection()` inside the store. When `useXConnect` resolves a successful connection, the store's setter constructs the chain-specific provider (`BitcoinWalletProvider`, `IconWalletProvider`, …) and writes it to `walletProviders`.
|
|
162
|
+
|
|
163
|
+
In both cases, the bridge layer owns the construction — consumers never call `new EvmWalletProvider(...)` themselves in dApp code.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Disabled chains return `undefined`
|
|
168
|
+
|
|
169
|
+
If `xChainType` resolves to a chain that isn't enabled in `SodaxWalletProvider` config, `useWalletProvider` returns `undefined` and logs a one-time warning per chain:
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
[useWalletProvider] chain "BITCOIN" is not enabled in SodaxWalletProvider config.chains — returning undefined
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
This is by design — `useWalletProvider` is meant to be called unconditionally inside components, and chains can be disabled without changing the call sites. Always null-check the return value:
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const walletProvider = useWalletProvider({ xChainId: ChainKeys.BITCOIN_MAINNET });
|
|
179
|
+
if (!walletProvider) return null; // chain disabled, or no wallet connected for that chain yet
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The warning fires only once per chain per session — repeated disabled-chain reads don't spam the console.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Bypassing the bridge — when to skip `useWalletProvider`
|
|
187
|
+
|
|
188
|
+
Skip the bridge in two cases:
|
|
189
|
+
|
|
190
|
+
**Server / Node.js scripts** — no React, no wallet-sdk-react. Use `@sodax/wallet-sdk-core` directly:
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
import { Sodax } from '@sodax/sdk';
|
|
194
|
+
import { EvmWalletProvider } from '@sodax/wallet-sdk-core';
|
|
195
|
+
import { ChainKeys } from '@sodax/types';
|
|
196
|
+
|
|
197
|
+
const sodax = new Sodax();
|
|
198
|
+
const walletProvider = new EvmWalletProvider({
|
|
199
|
+
privateKey: process.env.PRIVATE_KEY!,
|
|
200
|
+
chainId: ChainKeys.BSC_MAINNET,
|
|
201
|
+
rpcUrl: 'https://bsc-dataseed.binance.org',
|
|
202
|
+
});
|
|
203
|
+
const result = await sodax.swaps.swap({ params: /* ... */, walletProvider });
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Raw transactions** — when you only need unsigned transaction data (for gas estimation, manual relay, or external signing). SDK methods that accept `raw: true` don't need a wallet provider:
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
const result = await sodax.swaps.createIntent({
|
|
210
|
+
params,
|
|
211
|
+
raw: true, // no walletProvider — returns unsigned tx
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
See [`packages/sdk/docs/SWAPS.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/SWAPS.md) for the full raw-vs-signed matrix per method.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Related docs
|
|
220
|
+
|
|
221
|
+
- [Configure SodaxWalletProvider](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONFIGURE_PROVIDER.md) — chain-type slots and per-chain wallet defaults
|
|
222
|
+
- [Connect Flow](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECT_FLOW.md) — discover, connect, read, disconnect
|
|
223
|
+
- [Connectors](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECTORS.md) — `IXConnector`, deep imports, custom connectors
|
|
224
|
+
- [SDK Wallet Providers Reference](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/WALLET_PROVIDERS.md) — `IXxxWalletProvider` interfaces, custom implementations
|
|
225
|
+
- [SDK Swaps](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/SWAPS.md) — example consumer of a wallet provider
|
|
226
|
+
- [`@sodax/wallet-sdk-core`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-core/README.md) — Node-side provider construction
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sodax/wallet-sdk-react",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0-rc.1",
|
|
5
5
|
"description": "Wallet SDK of Sodax",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.cjs",
|
|
@@ -9,18 +9,33 @@
|
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|
|
12
|
-
"
|
|
12
|
+
"README.md",
|
|
13
|
+
"docs",
|
|
14
|
+
"skills",
|
|
15
|
+
"ai-exported"
|
|
13
16
|
],
|
|
14
17
|
"exports": {
|
|
15
18
|
".": {
|
|
16
19
|
"types": "./dist/index.d.ts",
|
|
17
20
|
"import": "./dist/index.mjs",
|
|
18
21
|
"require": "./dist/index.cjs"
|
|
22
|
+
},
|
|
23
|
+
"./xchains/*": {
|
|
24
|
+
"types": "./dist/xchains/*/index.d.ts",
|
|
25
|
+
"import": "./dist/xchains/*/index.mjs",
|
|
26
|
+
"require": "./dist/xchains/*/index.cjs"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"typesVersions": {
|
|
30
|
+
"*": {
|
|
31
|
+
"xchains/*": [
|
|
32
|
+
"./dist/xchains/*/index.d.ts"
|
|
33
|
+
]
|
|
19
34
|
}
|
|
20
35
|
},
|
|
21
36
|
"repository": {
|
|
22
37
|
"type": "git",
|
|
23
|
-
"url": "https://github.com/icon-project/sodax-
|
|
38
|
+
"url": "https://github.com/icon-project/sodax-sdks"
|
|
24
39
|
},
|
|
25
40
|
"dependencies": {
|
|
26
41
|
"@stacks/connect": "8.2.6",
|
|
@@ -43,7 +58,8 @@
|
|
|
43
58
|
"@solana/wallet-adapter-react": "0.15.35",
|
|
44
59
|
"@solana/wallet-adapter-wallets": "0.19.30",
|
|
45
60
|
"@solana/web3.js": "1.98.0",
|
|
46
|
-
"@stellar/stellar-sdk": "
|
|
61
|
+
"@stellar/stellar-sdk": "15.1.0",
|
|
62
|
+
"@walletconnect/ethereum-provider": "^2.23.9",
|
|
47
63
|
"icon-sdk-js": "1.5.3",
|
|
48
64
|
"immer": "10.1.1",
|
|
49
65
|
"sats-connect": "^4.2.1",
|
|
@@ -51,15 +67,19 @@
|
|
|
51
67
|
"wagmi": "2.16.9",
|
|
52
68
|
"zustand": "4.5.2",
|
|
53
69
|
"bs58": "6.0.0",
|
|
54
|
-
"@sodax/types": "
|
|
55
|
-
"@sodax/wallet-sdk-core": "
|
|
70
|
+
"@sodax/types": "2.0.0-rc.1",
|
|
71
|
+
"@sodax/wallet-sdk-core": "2.0.0-rc.1"
|
|
56
72
|
},
|
|
57
73
|
"devDependencies": {
|
|
74
|
+
"@testing-library/react": "^16.1.0",
|
|
58
75
|
"@types/react": "^19.0.8",
|
|
76
|
+
"@types/react-dom": "^19.0.3",
|
|
77
|
+
"happy-dom": "^20.8.9",
|
|
59
78
|
"knip": "5.30.5",
|
|
79
|
+
"react-dom": "19.1.4",
|
|
60
80
|
"tsup": "8.5.0",
|
|
61
81
|
"typescript": "5.5.4",
|
|
62
|
-
"vitest": "
|
|
82
|
+
"vitest": "2.1.9"
|
|
63
83
|
},
|
|
64
84
|
"peerDependencies": {
|
|
65
85
|
"@tanstack/react-query": "5.x",
|
|
@@ -69,12 +89,17 @@
|
|
|
69
89
|
"node": ">=18.0.0"
|
|
70
90
|
},
|
|
71
91
|
"scripts": {
|
|
72
|
-
"build": "tsup",
|
|
92
|
+
"build": "NODE_OPTIONS=--max-old-space-size=8192 tsup",
|
|
73
93
|
"dev": "tsup --watch ./src",
|
|
74
94
|
"clean": "rm -rf dist && rm -rf node_modules && rm -rf .turbo",
|
|
75
95
|
"pretty": "biome format . --write",
|
|
76
96
|
"checkTs": "tsc --noEmit",
|
|
97
|
+
"checkTs:examples": "tsc --noEmit -p tsconfig.examples.json",
|
|
98
|
+
"test": "vitest run",
|
|
77
99
|
"knip": "knip",
|
|
78
|
-
"lint": "biome lint . --write"
|
|
100
|
+
"lint": "biome lint . --write",
|
|
101
|
+
"check:ai-exported": "bash ./scripts/check-ai-exported.sh",
|
|
102
|
+
"check:ai-links": "bash ./scripts/check-ai-links.sh",
|
|
103
|
+
"check:ai-imports": "bash ./scripts/check-ai-imports.sh"
|
|
79
104
|
}
|
|
80
105
|
}
|
package/skills/SKILLS.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# @sodax/wallet-sdk-react Skills
|
|
2
|
+
|
|
3
|
+
Scaffolding guides that let you wire SODAX wallet connectivity into a React app in one prompt. Built for and tested with [Claude Code](https://docs.anthropic.com/en/docs/claude-code) — point it at a skill file and it generates the correct providers, hooks, and types.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
Skills ship with the npm package. After installing `@sodax/wallet-sdk-react`:
|
|
8
|
+
|
|
9
|
+
**1. Set up providers** (do this first)
|
|
10
|
+
|
|
11
|
+
> Read `node_modules/@sodax/wallet-sdk-react/skills/setup.md` and wire `SodaxWalletProvider` into my app.
|
|
12
|
+
|
|
13
|
+
**2. Pick a connect UX**
|
|
14
|
+
|
|
15
|
+
> Read `node_modules/@sodax/wallet-sdk-react/skills/connect-button.md` and add a single-chain connect button.
|
|
16
|
+
|
|
17
|
+
> Read `node_modules/@sodax/wallet-sdk-react/skills/multi-chain-modal.md` and add a multi-chain wallet modal.
|
|
18
|
+
|
|
19
|
+
**3. Add advanced features as needed**
|
|
20
|
+
|
|
21
|
+
> Read `node_modules/@sodax/wallet-sdk-react/skills/evm-only-walletconnect.md` and enable WalletConnect for enterprise custody (Fireblocks, etc.).
|
|
22
|
+
|
|
23
|
+
> Read `node_modules/@sodax/wallet-sdk-react/skills/bridge-to-sdk.md` and pass the connected wallet provider to a `@sodax/sdk` swap call.
|
|
24
|
+
|
|
25
|
+
The pattern is always: `Read node_modules/@sodax/wallet-sdk-react/skills/<skill>.md` + what you want to build.
|
|
26
|
+
|
|
27
|
+
### Tips
|
|
28
|
+
|
|
29
|
+
- One skill per prompt gets better results than asking for everything at once.
|
|
30
|
+
- Always do setup before any other skill.
|
|
31
|
+
- Pair `connect-button.md` (one chain at a time) OR `multi-chain-modal.md` (chain picker + connector picker) — they're alternatives, not additive.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
*Internal devs working in this monorepo: use `skills/<skill>.md` instead of the `node_modules` path, and reference sibling docs in `docs/` for the underlying API.*
|
|
36
|
+
|
|
37
|
+
## Dependency Graph
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
setup
|
|
41
|
+
├── connect-button (single-chain connect/disconnect)
|
|
42
|
+
├── multi-chain-modal (modal-driven multi-chain UX)
|
|
43
|
+
├── evm-only-walletconnect (Fireblocks / custody opt-in)
|
|
44
|
+
└── bridge-to-sdk (pass walletProvider to @sodax/sdk calls)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Skill Index
|
|
48
|
+
|
|
49
|
+
| Skill | File | Description | Depends On |
|
|
50
|
+
|-------|------|-------------|------------|
|
|
51
|
+
| Setup | [setup.md](setup.md) | Install + wire `SodaxWalletProvider` with chain-type slots | None |
|
|
52
|
+
| Connect Button | [connect-button.md](connect-button.md) | `useXConnectors` + `useXConnect` + `useXDisconnect` for one chain | `setup` |
|
|
53
|
+
| Multi-chain Modal | [multi-chain-modal.md](multi-chain-modal.md) | `useWalletModal` headless state machine + `useChainGroups` | `setup` |
|
|
54
|
+
| EVM-only WalletConnect | [evm-only-walletconnect.md](evm-only-walletconnect.md) | Enable WalletConnect for Fireblocks / Ledger / mobile-only wallets | `setup` |
|
|
55
|
+
| Bridge to SDK | [bridge-to-sdk.md](bridge-to-sdk.md) | `useWalletProvider` → typed `IXxxWalletProvider` for `@sodax/sdk` calls | `setup`, one of `connect-button` / `multi-chain-modal` |
|
|
56
|
+
|
|
57
|
+
## Conventions
|
|
58
|
+
|
|
59
|
+
### Single object parameter
|
|
60
|
+
|
|
61
|
+
Every hook in `@sodax/wallet-sdk-react` accepts one options object:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
useXConnectors({ xChainType: 'EVM' });
|
|
65
|
+
useXAccount({ xChainId: ChainKeys.BSC_MAINNET });
|
|
66
|
+
useWalletProvider({ xChainType: 'EVM' });
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`useXAccount` / `useWalletProvider` accept either `xChainId` (chain key) **or** `xChainType` (family) — never both.
|
|
70
|
+
|
|
71
|
+
### Mutation pattern (`useXConnect`)
|
|
72
|
+
|
|
73
|
+
`useXConnect` is a React Query mutation. Pass an `IXConnector` to `mutate` / `mutateAsync`:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
const { mutateAsync: connect } = useXConnect();
|
|
77
|
+
await connect(connector);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
For provider-managed chains (EVM/Solana/Sui), the resolved value is `undefined` — read the connected account via `useXAccount` after the mutation lands. See [Connect Flow caveat](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECT_FLOW.md#provider-managed-chains-caveat).
|
|
81
|
+
|
|
82
|
+
### Persisted connections
|
|
83
|
+
|
|
84
|
+
Connections survive page reloads via `localStorage` (key `xwagmi-store`). Gate UI on hydration to avoid flicker — `useConnectedChains().status === 'ready'` is the official signal.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Skill: Bridge to SDK
|
|
2
|
+
|
|
3
|
+
Pass the user's connected wallet to `@sodax/sdk` calls — `useWalletProvider` returns a typed `IXxxWalletProvider` ready to plug into any SDK method.
|
|
4
|
+
|
|
5
|
+
**Depends on:** [setup.md](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/skills/setup.md), one of [connect-button.md](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/skills/connect-button.md) / [multi-chain-modal.md](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/skills/multi-chain-modal.md)
|
|
6
|
+
|
|
7
|
+
## Hooks
|
|
8
|
+
|
|
9
|
+
| Hook | Purpose |
|
|
10
|
+
|------|---------|
|
|
11
|
+
| `useWalletProvider({ xChainId })` | Typed `IXxxWalletProvider` (chain-narrowed by chain id) |
|
|
12
|
+
| `useWalletProvider({ xChainType })` | Family-level provider (same shape for every chain id in family) |
|
|
13
|
+
| `useXAccount({ xChainId })` | Read connected address |
|
|
14
|
+
| `useXService({ xChainType })` | Lower-level — chain `XService` instance for advanced reads |
|
|
15
|
+
|
|
16
|
+
Pass either `xChainId` (a `SpokeChainKey`) or `xChainType` (a `ChainType`), never both.
|
|
17
|
+
|
|
18
|
+
## Pattern — drive an SDK swap from a connected wallet
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { useWalletProvider, useXAccount } from '@sodax/wallet-sdk-react';
|
|
22
|
+
import { Sodax, ChainKeys } from '@sodax/sdk';
|
|
23
|
+
import type { CreateIntentParams } from '@sodax/sdk';
|
|
24
|
+
|
|
25
|
+
const sodax = new Sodax(); // or hold one in context / pass via @sodax/dapp-kit
|
|
26
|
+
|
|
27
|
+
export function SwapButton({ params }: { params: CreateIntentParams<typeof ChainKeys.BSC_MAINNET> }) {
|
|
28
|
+
const walletProvider = useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET });
|
|
29
|
+
const account = useXAccount({ xChainId: ChainKeys.BSC_MAINNET });
|
|
30
|
+
|
|
31
|
+
const handleSwap = async () => {
|
|
32
|
+
if (!walletProvider) return;
|
|
33
|
+
const result = await sodax.swaps.swap({
|
|
34
|
+
params,
|
|
35
|
+
walletProvider, // typed as IEvmWalletProvider — must match BSC src chain
|
|
36
|
+
});
|
|
37
|
+
if (!result.ok) {
|
|
38
|
+
console.error('swap failed:', result.error);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
console.log('swap submitted:', result.value);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<button onClick={handleSwap} disabled={!walletProvider || !account.address}>
|
|
46
|
+
Swap
|
|
47
|
+
</button>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The pattern works for every SDK feature service:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
sodax.swaps.swap({ params, walletProvider });
|
|
56
|
+
sodax.bridge.bridge({ params, walletProvider });
|
|
57
|
+
sodax.moneyMarket.supply({ params, walletProvider });
|
|
58
|
+
sodax.staking.stake({ params, walletProvider });
|
|
59
|
+
sodax.dex.deposit({ params, walletProvider });
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
See [`packages/sdk/docs/`](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/) for per-feature method signatures.
|
|
63
|
+
|
|
64
|
+
## TypeScript narrowing
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import { useWalletProvider } from '@sodax/wallet-sdk-react';
|
|
68
|
+
import { ChainKeys } from '@sodax/types';
|
|
69
|
+
|
|
70
|
+
// By chain id — narrowest typing
|
|
71
|
+
const evm = useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET });
|
|
72
|
+
// evm: IEvmWalletProvider | undefined
|
|
73
|
+
|
|
74
|
+
const sol = useWalletProvider({ xChainId: ChainKeys.SOLANA_MAINNET });
|
|
75
|
+
// sol: ISolanaWalletProvider | undefined
|
|
76
|
+
|
|
77
|
+
// By chain type — family-level (one wagmi connection covers all EVM chains)
|
|
78
|
+
const evmFamily = useWalletProvider({ xChainType: 'EVM' });
|
|
79
|
+
// evmFamily: IEvmWalletProvider | undefined
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The chain-narrowing is automatic — passing the wrong wallet provider type to an SDK call (e.g. `ISolanaWalletProvider` to a `srcChainKey: BSC_MAINNET` swap) is a **compile error**.
|
|
83
|
+
|
|
84
|
+
## EVM — single connection across all networks
|
|
85
|
+
|
|
86
|
+
`useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET })` and `useWalletProvider({ xChainId: ChainKeys.ARBITRUM_MAINNET })` return the **same** `EvmWalletProvider` instance — wagmi maintains one connection across all configured EVM networks. To switch the **active** EVM network, see [`useEvmSwitchChain`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/EVM_SWITCH_CHAIN.md):
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
import { useEvmSwitchChain } from '@sodax/wallet-sdk-react';
|
|
90
|
+
|
|
91
|
+
const { isWrongChain, handleSwitchChain } = useEvmSwitchChain({
|
|
92
|
+
xChainId: ChainKeys.BSC_MAINNET,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
if (isWrongChain) {
|
|
96
|
+
return <button onClick={handleSwitchChain}>Switch to BSC</button>;
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Disabled chains return `undefined`
|
|
101
|
+
|
|
102
|
+
If `xChainType` resolves to a chain not enabled in `SodaxWalletProvider` config, `useWalletProvider` returns `undefined` and logs a one-time warning:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
[useWalletProvider] chain "BITCOIN" is not enabled in SodaxWalletProvider config.chains — returning undefined
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Always null-check before passing to an SDK call.
|
|
109
|
+
|
|
110
|
+
## Raw transactions — skip the bridge
|
|
111
|
+
|
|
112
|
+
If you only need unsigned transaction data (manual relay, gas estimation, external signing), pass `raw: true` to the SDK and skip `walletProvider`:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
const result = await sodax.swaps.createIntent({
|
|
116
|
+
params,
|
|
117
|
+
raw: true, // walletProvider must be absent — compile error if passed
|
|
118
|
+
});
|
|
119
|
+
// result.value.tx is an EvmRawTransaction
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
See [`packages/sdk/docs/SWAPS.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/SWAPS.md) for the full raw-vs-signed matrix per method.
|
|
123
|
+
|
|
124
|
+
## Server / scripts — use `@sodax/wallet-sdk-core` directly
|
|
125
|
+
|
|
126
|
+
For Node.js scripts / bots, skip wallet-sdk-react entirely:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { Sodax } from '@sodax/sdk';
|
|
130
|
+
import { EvmWalletProvider } from '@sodax/wallet-sdk-core';
|
|
131
|
+
import { ChainKeys } from '@sodax/types';
|
|
132
|
+
|
|
133
|
+
const sodax = new Sodax();
|
|
134
|
+
const walletProvider = new EvmWalletProvider({
|
|
135
|
+
privateKey: process.env.PRIVATE_KEY!,
|
|
136
|
+
chainId: ChainKeys.BSC_MAINNET,
|
|
137
|
+
rpcUrl: 'https://bsc-dataseed.binance.org',
|
|
138
|
+
});
|
|
139
|
+
const result = await sodax.swaps.swap({ params, walletProvider });
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Reference docs
|
|
143
|
+
|
|
144
|
+
- [Wallet Provider Bridge](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/WALLET_PROVIDER_BRIDGE.md) — `useWalletProvider` + `useXService` reference
|
|
145
|
+
- [SDK Wallet Providers Reference](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/WALLET_PROVIDERS.md) — per-chain `IXxxWalletProvider` interfaces
|
|
146
|
+
- [SDK Swaps](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/SWAPS.md) — example consumer of a wallet provider
|
|
147
|
+
- [EVM Switch Chain](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/EVM_SWITCH_CHAIN.md) — switch active EVM network
|
|
148
|
+
- [`packages/dapp-kit`](https://github.com/icon-project/sodax-sdks/blob/main/packages/dapp-kit/README.md) — higher-level React hooks that wrap SDK calls + `useWalletProvider`
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Skill: Connect Button
|
|
2
|
+
|
|
3
|
+
Single-chain connect/disconnect button — pick a connector, connect, read the account, disconnect.
|
|
4
|
+
|
|
5
|
+
**Depends on:** [setup.md](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/skills/setup.md)
|
|
6
|
+
|
|
7
|
+
## Hooks
|
|
8
|
+
|
|
9
|
+
| Hook | Purpose |
|
|
10
|
+
|------|---------|
|
|
11
|
+
| `useXConnectors({ xChainType })` | List available connectors for the chain family |
|
|
12
|
+
| `useXConnect()` | React Query mutation — `mutate(connector)` |
|
|
13
|
+
| `useXAccount({ xChainType })` | Read connected account (always returns object — `address` is `undefined` when disconnected) |
|
|
14
|
+
| `useXDisconnect()` | Returns `(args) => Promise<void>` |
|
|
15
|
+
| `sortConnectors(list, { preferred })` | Optional — rank installed/preferred wallets first |
|
|
16
|
+
|
|
17
|
+
## Connect button
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import {
|
|
21
|
+
useXConnectors,
|
|
22
|
+
useXConnect,
|
|
23
|
+
useXAccount,
|
|
24
|
+
useXDisconnect,
|
|
25
|
+
sortConnectors,
|
|
26
|
+
type IXConnector,
|
|
27
|
+
} from '@sodax/wallet-sdk-react';
|
|
28
|
+
|
|
29
|
+
const PREFERRED = ['hana', 'metamask'] as const;
|
|
30
|
+
|
|
31
|
+
export function EvmConnectButton() {
|
|
32
|
+
const raw = useXConnectors({ xChainType: 'EVM' });
|
|
33
|
+
const connectors = sortConnectors(raw, { preferred: PREFERRED });
|
|
34
|
+
const { mutateAsync: connect, isPending, error } = useXConnect();
|
|
35
|
+
const account = useXAccount({ xChainType: 'EVM' });
|
|
36
|
+
const disconnect = useXDisconnect();
|
|
37
|
+
|
|
38
|
+
if (account.address) {
|
|
39
|
+
return (
|
|
40
|
+
<div>
|
|
41
|
+
<code>{account.address}</code>
|
|
42
|
+
<button onClick={() => disconnect({ xChainType: 'EVM' })}>Disconnect</button>
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div>
|
|
49
|
+
{connectors.map((connector) => (
|
|
50
|
+
<button
|
|
51
|
+
key={connector.id}
|
|
52
|
+
onClick={() => connect(connector).catch(() => {})}
|
|
53
|
+
disabled={isPending}
|
|
54
|
+
>
|
|
55
|
+
{connector.icon && <img src={connector.icon} alt="" width={20} height={20} />}
|
|
56
|
+
{connector.name}
|
|
57
|
+
{!connector.isInstalled && ' (not installed)'}
|
|
58
|
+
</button>
|
|
59
|
+
))}
|
|
60
|
+
{error && <p style={{ color: 'red' }}>{error.message}</p>}
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Install CTA for missing wallets
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
{connectors.map((connector) =>
|
|
70
|
+
connector.isInstalled ? (
|
|
71
|
+
<button key={connector.id} onClick={() => connect(connector)}>
|
|
72
|
+
{connector.name}
|
|
73
|
+
</button>
|
|
74
|
+
) : (
|
|
75
|
+
<a key={connector.id} href={connector.installUrl} target="_blank" rel="noreferrer">
|
|
76
|
+
Install {connector.name}
|
|
77
|
+
</a>
|
|
78
|
+
),
|
|
79
|
+
)}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`isInstalled` reads `window.*` at render time (no extra subscription). For batch install detection across wallet brands, use [`useIsWalletInstalled`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CHAIN_DETECTION.md#useiswalletinstalled--install-detection).
|
|
83
|
+
|
|
84
|
+
## Caveat — provider-managed chains resolve with `undefined`
|
|
85
|
+
|
|
86
|
+
For EVM, Solana, and Sui, `connect(connector)` resolves with `undefined` because connection state is set by the chain's Hydrator after the native SDK reports `connected`. Always read the account via `useXAccount`, not the mutation's return value:
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const { mutateAsync: connect } = useXConnect();
|
|
90
|
+
const account = useXAccount({ xChainType: 'EVM' });
|
|
91
|
+
|
|
92
|
+
await connect(connector); // resolves with undefined for EVM
|
|
93
|
+
// account.address is populated on the next render
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Non-provider chains (Bitcoin, ICON, Injective, Stellar, NEAR, Stacks) return the resolved `XAccount` from `connect()` — but reading via `useXAccount` works for both, so default to it.
|
|
97
|
+
|
|
98
|
+
## Multiple chains, one button
|
|
99
|
+
|
|
100
|
+
For a "connect EVM + Solana + Bitcoin in one click" pattern, use [`useBatchConnect`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/BATCH_OPERATIONS.md):
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import { useBatchConnect } from '@sodax/wallet-sdk-react';
|
|
104
|
+
|
|
105
|
+
const { run, status } = useBatchConnect({ connectors: ['hana'] });
|
|
106
|
+
// Connects every chain Hana supports — sequential, errors collected.
|
|
107
|
+
<button onClick={run} disabled={status === 'running'}>
|
|
108
|
+
Connect Hana on all chains
|
|
109
|
+
</button>;
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Reference docs
|
|
113
|
+
|
|
114
|
+
- [Connect Flow](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECT_FLOW.md) — full lifecycle reference + error handling
|
|
115
|
+
- [Connectors](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECTORS.md) — `IXConnector` shape, deep imports for concrete classes
|
|
116
|
+
- [Batch Operations](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/BATCH_OPERATIONS.md) — multi-chain connect by wallet identifier
|