@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,440 @@
|
|
|
1
|
+
# Adding a New Chain
|
|
2
|
+
|
|
3
|
+
This document is the contributor workflow for onboarding a new chain family (e.g. Aptos, Cosmos, …) into `@sodax/wallet-sdk-react`. Most steps are mechanical because the central abstractions (`ChainMeta`, `chainRegistry`, sub-path exports) auto-derive downstream types — adding a chain is mostly **filling in entries**, not rewriting hooks.
|
|
4
|
+
|
|
5
|
+
Prerequisite: read [`ARCHITECTURE.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/ARCHITECTURE.md) first, especially the [Provider-managed vs non-provider](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/ARCHITECTURE.md#provider-managed-vs-non-provider-chains) split — that decision drives the rest of this guide.
|
|
6
|
+
|
|
7
|
+
## Table of contents
|
|
8
|
+
|
|
9
|
+
1. [Decision tree — provider-managed or not?](#decision-tree--provider-managed-or-not)
|
|
10
|
+
2. [Step 1 — types in `@sodax/types`](#step-1--types-in-sodaxtypes)
|
|
11
|
+
3. [Step 2 — wallet provider in `@sodax/wallet-sdk-core`](#step-2--wallet-provider-in-sodaxwallet-sdk-core)
|
|
12
|
+
4. [Step 3 — `XService` + `XConnector` in `xchains/<chain>/`](#step-3--xservice--xconnector-in-xchainschain)
|
|
13
|
+
5. [Step 4 — `xchains/<chain>/index.ts` barrel for sub-path export](#step-4--xchainschainindexts-barrel-for-sub-path-export)
|
|
14
|
+
6. [Step 5 — `ChainMeta` entry in `types/config.ts`](#step-5--chainmeta-entry-in-typesconfigts)
|
|
15
|
+
7. [Step 6 — register in `chainRegistry`](#step-6--register-in-chainregistry)
|
|
16
|
+
8. [Step 7 — provider-managed only — Provider/Hydrator/Actions trio](#step-7--provider-managed-only--providerhydratoractions-trio)
|
|
17
|
+
9. [Step 8 — barrel surface (`src/index.ts`)](#step-8--barrel-surface-srcindexts)
|
|
18
|
+
10. [Step 9 — tests](#step-9--tests)
|
|
19
|
+
11. [Verification checklist](#verification-checklist)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Decision tree — provider-managed or not?
|
|
24
|
+
|
|
25
|
+
Set `providerManaged: true` if **any** of these is true:
|
|
26
|
+
|
|
27
|
+
- The chain ships a React adapter library (wagmi, `@solana/wallet-adapter-react`, `@mysten/dapp-kit`, etc.) that you want to use.
|
|
28
|
+
- The wallet-side SDK requires a long-lived React context to register handlers and survive component re-renders.
|
|
29
|
+
- Wallet discovery is reactive (EIP-6963 announcements, dynamic adapter registration) and you want components to re-render automatically.
|
|
30
|
+
|
|
31
|
+
Set `providerManaged: false` if:
|
|
32
|
+
|
|
33
|
+
- You can probe `window.<wallet>` synchronously per-call.
|
|
34
|
+
- Connection lifecycle is short-lived (call `connect()`, get an account back, no React context needed).
|
|
35
|
+
- The native SDK is plain TS classes/functions with no React glue (e.g. `sats-connect`, `icon-sdk-js`).
|
|
36
|
+
|
|
37
|
+
**Mixing** — you can have a non-provider chain whose `discoverConnectors` is async (Stellar). That's still `providerManaged: false` because the connectors are static after discovery; the React adapter pattern isn't used.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Step 1 — types in `@sodax/types`
|
|
42
|
+
|
|
43
|
+
Add the chain's identity and types to `packages/types/src/`:
|
|
44
|
+
|
|
45
|
+
1. **Chain key** in [`packages/types/src/chains/chain-keys.ts`](https://github.com/icon-project/sodax-sdks/blob/main/packages/types/src/chains/chain-keys.ts):
|
|
46
|
+
```typescript
|
|
47
|
+
export const ChainKeys = {
|
|
48
|
+
...
|
|
49
|
+
APTOS_MAINNET: 'aptos',
|
|
50
|
+
};
|
|
51
|
+
```
|
|
52
|
+
2. **Chain type** in `ChainTypeArr`:
|
|
53
|
+
```typescript
|
|
54
|
+
export const ChainTypeArr = [..., 'APTOS'] as const;
|
|
55
|
+
```
|
|
56
|
+
3. **Chain key type alias**:
|
|
57
|
+
```typescript
|
|
58
|
+
export type AptosChainKey = typeof ChainKeys.APTOS_MAINNET;
|
|
59
|
+
```
|
|
60
|
+
4. **Chain info entry** in [`packages/types/src/chains/chains.ts`](https://github.com/icon-project/sodax-sdks/blob/main/packages/types/src/chains/chains.ts) (`baseChainInfo`):
|
|
61
|
+
```typescript
|
|
62
|
+
[ChainKeys.APTOS_MAINNET]: { type: 'APTOS', chainId: '0x1' /* or numeric */, displayName: 'Aptos' }
|
|
63
|
+
```
|
|
64
|
+
5. **Wallet provider interface** in `packages/types/src/aptos.ts`:
|
|
65
|
+
```typescript
|
|
66
|
+
export interface IAptosWalletProvider extends WalletAddressProvider {
|
|
67
|
+
readonly chainType: 'APTOS';
|
|
68
|
+
// chain-specific methods: signAndSubmitTransaction, signMessage, ...
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
6. **Add to root barrel** if you want it re-exported from `@sodax/types`, or leave as a sub-package export per [`packages/types/CLAUDE.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/types/CLAUDE.md).
|
|
72
|
+
|
|
73
|
+
The `ChainKey` and `ChainType` unions auto-derive — once these entries land, downstream code in `@sodax/sdk` and `@sodax/wallet-sdk-react` sees the new chain at the type level.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Step 2 — wallet provider in `@sodax/wallet-sdk-core`
|
|
78
|
+
|
|
79
|
+
Add `packages/wallet-sdk-core/src/wallet-providers/aptos/`:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
aptos/
|
|
83
|
+
├── AptosWalletProvider.ts
|
|
84
|
+
├── AptosWalletProvider.test.ts
|
|
85
|
+
├── types.ts # PrivateKey<chain>WalletConfig + BrowserExtension<chain>WalletConfig + AptosWalletDefaults
|
|
86
|
+
└── index.ts # Barrel re-export
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`AptosWalletProvider` extends `BaseWalletProvider<AptosWalletDefaults>` and implements `IAptosWalletProvider`. Discriminated config — pick a discriminant pattern:
|
|
90
|
+
|
|
91
|
+
- **Field presence** (no `type` field): `privateKey` field present vs. absent. Most chains use this.
|
|
92
|
+
- **Explicit `type`**: `'PRIVATE_KEY'` | `'BROWSER_EXTENSION'`. Use when both modes share fields that would clash without a discriminant (Bitcoin, Stellar).
|
|
93
|
+
|
|
94
|
+
See [`packages/wallet-sdk-core/CLAUDE.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-core/CLAUDE.md#config-variants-discriminants) for the canonical patterns.
|
|
95
|
+
|
|
96
|
+
Re-export from `packages/wallet-sdk-core/src/wallet-providers/index.ts`:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
export * from './aptos/index.js';
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Step 3 — `XService` + `XConnector` in `xchains/<chain>/`
|
|
105
|
+
|
|
106
|
+
Create `packages/wallet-sdk-react/src/xchains/aptos/`:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
aptos/
|
|
110
|
+
├── AptosXService.ts
|
|
111
|
+
├── AptosXConnector.ts
|
|
112
|
+
├── AptosXConnector.test.ts
|
|
113
|
+
└── index.ts
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### `AptosXService`
|
|
117
|
+
|
|
118
|
+
Singleton that owns the connector list and exposes balance reads. Extend the abstract `XService`:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
import type { XToken } from '@sodax/types';
|
|
122
|
+
import { XService } from '@/core/index.js';
|
|
123
|
+
|
|
124
|
+
export class AptosXService extends XService {
|
|
125
|
+
private static instance: AptosXService | undefined;
|
|
126
|
+
|
|
127
|
+
static getInstance(rpcConfig?: { rpcUrl?: string }): AptosXService {
|
|
128
|
+
if (!AptosXService.instance) AptosXService.instance = new AptosXService(rpcConfig);
|
|
129
|
+
return AptosXService.instance;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// chain-specific state (RPC client, etc.)
|
|
133
|
+
|
|
134
|
+
async getBalance(address: string, xToken: XToken): Promise<bigint> {
|
|
135
|
+
// …
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### `AptosXConnector`
|
|
141
|
+
|
|
142
|
+
Extend `XConnector`. The base class provides `id`, `icon`, `isInstalled = true` defaults; override `isInstalled` / `installUrl` for browser-extension-backed connectors:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { XConnector } from '@/core/index.js';
|
|
146
|
+
import type { XAccount } from '@/types/index.js';
|
|
147
|
+
|
|
148
|
+
export class AptosWalletXConnector extends XConnector {
|
|
149
|
+
constructor() {
|
|
150
|
+
super('APTOS', 'Aptos Wallet', 'aptos.wallet');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
override get isInstalled(): boolean {
|
|
154
|
+
return typeof window !== 'undefined' && 'aptos' in window;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
override get installUrl(): string {
|
|
158
|
+
return 'https://chrome.google.com/webstore/detail/...';
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async connect(): Promise<XAccount | undefined> {
|
|
162
|
+
const account = await window.aptos.connect();
|
|
163
|
+
return account ? { address: account.address, xChainType: 'APTOS', publicKey: account.publicKey } : undefined;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async disconnect(): Promise<void> {
|
|
167
|
+
await window.aptos.disconnect();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
For chains with multiple wallets (Bitcoin: Unisat / Xverse / OKX; Injective: MetaMask / Keplr / Leap), create one `XConnector` subclass per wallet and have an abstract intermediate base if shared logic exists (Bitcoin uses `BitcoinXConnector` abstract).
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Step 4 — `xchains/<chain>/index.ts` barrel for sub-path export
|
|
177
|
+
|
|
178
|
+
Create the barrel that powers `@sodax/wallet-sdk-react/xchains/aptos`:
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
// src/xchains/aptos/index.ts
|
|
182
|
+
export { AptosXService } from './AptosXService.js';
|
|
183
|
+
export { AptosWalletXConnector } from './AptosXConnector.js';
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
`tsup.config.ts` already picks up `src/xchains/*/index.ts` via glob — **no config edit needed**. The sub-path export will resolve as `@sodax/wallet-sdk-react/xchains/aptos`.
|
|
187
|
+
|
|
188
|
+
See [`SUB_PATH_EXPORTS.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/SUB_PATH_EXPORTS.md) for the export plumbing.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Step 5 — `ChainMeta` entry in `types/config.ts`
|
|
193
|
+
|
|
194
|
+
[`ChainMeta`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/src/types/config.ts) is the **single source of truth** for per-chain-type metadata. `SodaxWalletConfig`, `ChainTypeConfig<T>`, `ChainEntry<K>`, `WalletDefaultsByKey<K>` all derive from it automatically.
|
|
195
|
+
|
|
196
|
+
Add **one entry**:
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
export type AptosChainEntry = SimpleChainEntry<AptosWalletDefaults>;
|
|
200
|
+
|
|
201
|
+
export type ChainMeta = {
|
|
202
|
+
EVM: { ... };
|
|
203
|
+
// ...
|
|
204
|
+
APTOS: {
|
|
205
|
+
keys: AptosChainKey; // from @sodax/types
|
|
206
|
+
entry: AptosChainEntry; // { rpcUrl?, defaults? } (or richer if chain has multi-field RPC)
|
|
207
|
+
defaults: AptosWalletDefaults;
|
|
208
|
+
adapter: {}; // {} for non-provider chains; AptosAdapterFields if provider-managed
|
|
209
|
+
};
|
|
210
|
+
};
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
If the chain has multi-field RPC (Stellar's horizon + soroban, Bitcoin's RPC + Radfi), define a custom entry shape that extends `*RpcConfig` from `@sodax/types`:
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
export type AptosChainEntry = AptosRpcConfig & { defaults?: AptosWalletDefaults };
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
If provider-managed, define `AptosAdapterFields` (one value per React provider — wagmi-config-level settings, not per-chain):
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
export type AptosAdapterFields = {
|
|
223
|
+
network?: 'mainnet' | 'testnet' | 'devnet';
|
|
224
|
+
autoConnect?: boolean;
|
|
225
|
+
};
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Add the per-chain-type alias for external typing convenience:
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
export type AptosTypeConfig = ChainTypeConfig<'APTOS'>;
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Step 6 — register in `chainRegistry`
|
|
237
|
+
|
|
238
|
+
Add an entry to [`chainRegistry`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/src/chainRegistry.ts):
|
|
239
|
+
|
|
240
|
+
### Non-provider chain
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
APTOS: defineChain({
|
|
244
|
+
createService: walletConfig =>
|
|
245
|
+
AptosXService.getInstance({ rpcUrl: getRpcUrl(walletConfig?.APTOS?.chains?.[ChainKeys.APTOS_MAINNET]) }),
|
|
246
|
+
displayName: 'Aptos',
|
|
247
|
+
defaultConnectors: () => [new AptosWalletXConnector()],
|
|
248
|
+
providerManaged: false,
|
|
249
|
+
// Optional — provide createActions if signMessage needs custom dispatch (Bitcoin's BIP-322/ECDSA)
|
|
250
|
+
createActions: (service, getStore) => ({
|
|
251
|
+
...createDefaultActions('APTOS', service, getStore),
|
|
252
|
+
signMessage: async (message: string) => {
|
|
253
|
+
// chain-specific signing logic
|
|
254
|
+
},
|
|
255
|
+
}),
|
|
256
|
+
// Optional — provide createWalletProvider if the chain needs a wallet provider in `walletProviders` map
|
|
257
|
+
createWalletProvider: (service, getStore) => {
|
|
258
|
+
const connection = getStore().xConnections.APTOS;
|
|
259
|
+
if (!connection?.xConnectorId) return undefined;
|
|
260
|
+
const defaults = getEntryDefaults<typeof ChainKeys.APTOS_MAINNET>(
|
|
261
|
+
getStore().walletConfig?.APTOS?.chains?.[ChainKeys.APTOS_MAINNET],
|
|
262
|
+
);
|
|
263
|
+
return new AptosWalletProvider({ /* ... */, defaults });
|
|
264
|
+
},
|
|
265
|
+
// Optional — provide discoverConnectors if connectors require async detection
|
|
266
|
+
discoverConnectors: async (service, getStore) => {
|
|
267
|
+
const wallets = await detectInstalledAptosWallets();
|
|
268
|
+
const connectors = wallets.map(w => new AptosWalletXConnector(w));
|
|
269
|
+
service.setXConnectors(connectors);
|
|
270
|
+
getStore().setXConnectors('APTOS', connectors);
|
|
271
|
+
},
|
|
272
|
+
}),
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Provider-managed chain
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
APTOS: defineChain({
|
|
279
|
+
createService: () => AptosXService.getInstance(),
|
|
280
|
+
displayName: 'Aptos',
|
|
281
|
+
defaultConnectors: () => [], // ignored — connectors come from the React adapter
|
|
282
|
+
providerManaged: true,
|
|
283
|
+
// No createActions / createWalletProvider — the Hydrator handles both.
|
|
284
|
+
}),
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Step 7 — provider-managed only — Provider/Hydrator/Actions trio
|
|
290
|
+
|
|
291
|
+
Skip this step for `providerManaged: false`.
|
|
292
|
+
|
|
293
|
+
Create `packages/wallet-sdk-react/src/providers/aptos/`:
|
|
294
|
+
|
|
295
|
+
```
|
|
296
|
+
aptos/
|
|
297
|
+
├── AptosProvider.tsx # Wraps native React adapter
|
|
298
|
+
├── AptosHydrator.tsx # Sole writer of connection state + walletProviders
|
|
299
|
+
├── AptosActions.tsx # Registers ChainActions (connect/disconnect/signMessage)
|
|
300
|
+
├── AptosHydrator.test.tsx
|
|
301
|
+
└── index.ts
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### `<AptosProvider>`
|
|
305
|
+
|
|
306
|
+
Wraps the chain's native React provider:
|
|
307
|
+
|
|
308
|
+
```tsx
|
|
309
|
+
import { type ReactNode } from 'react';
|
|
310
|
+
import { AptosProvider as NativeProvider } from 'aptos-adapter-react';
|
|
311
|
+
import { AptosHydrator } from './AptosHydrator.js';
|
|
312
|
+
import { AptosActions } from './AptosActions.js';
|
|
313
|
+
import type { AptosTypeConfig } from '@/types/config.js';
|
|
314
|
+
|
|
315
|
+
type AptosProviderProps = {
|
|
316
|
+
children: ReactNode;
|
|
317
|
+
config: AptosTypeConfig;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
export const AptosProvider = ({ children, config }: AptosProviderProps) => (
|
|
321
|
+
<NativeProvider network={config.network ?? 'mainnet'} autoConnect={config.autoConnect ?? true}>
|
|
322
|
+
<AptosHydrator />
|
|
323
|
+
<AptosActions />
|
|
324
|
+
{children}
|
|
325
|
+
</NativeProvider>
|
|
326
|
+
);
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### `<AptosHydrator>`
|
|
330
|
+
|
|
331
|
+
Sole writer. Subscribes to native SDK hooks; writes through `setXConnection` / `setWalletProvider`. **Never** writes inside an event handler — only inside `useEffect` reactions to native state.
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
import { useAccount } from 'aptos-adapter-react';
|
|
335
|
+
|
|
336
|
+
export const AptosHydrator = () => {
|
|
337
|
+
const { address, status, connector } = useAccount();
|
|
338
|
+
const setXConnection = useXWalletStore(s => s.setXConnection);
|
|
339
|
+
const unsetXConnection = useXWalletStore(s => s.unsetXConnection);
|
|
340
|
+
|
|
341
|
+
useEffect(() => {
|
|
342
|
+
if (status === 'connected' && address) {
|
|
343
|
+
setXConnection('APTOS', { xAccount: { address, xChainType: 'APTOS' }, xConnectorId: connector.id });
|
|
344
|
+
} else if (status === 'disconnected') {
|
|
345
|
+
unsetXConnection('APTOS');
|
|
346
|
+
}
|
|
347
|
+
}, [address, status, connector]);
|
|
348
|
+
|
|
349
|
+
// ... build wallet provider similarly via useMemo + setWalletProvider
|
|
350
|
+
|
|
351
|
+
return null;
|
|
352
|
+
};
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### `<AptosActions>`
|
|
356
|
+
|
|
357
|
+
Registers `ChainActions` using **refs** to native SDK functions, so the registered closures always call the latest function without re-registering:
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
const connectRef = useRef(connectAsync);
|
|
361
|
+
useEffect(() => { connectRef.current = connectAsync; }, [connectAsync]);
|
|
362
|
+
|
|
363
|
+
useEffect(() => {
|
|
364
|
+
registerChainActions('APTOS', {
|
|
365
|
+
connect: async (id) => connectRef.current({ connector: id }),
|
|
366
|
+
disconnect: async () => disconnectRef.current(),
|
|
367
|
+
// ...
|
|
368
|
+
});
|
|
369
|
+
}, []); // empty deps — register once
|
|
370
|
+
|
|
371
|
+
return null;
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Mount in `SodaxWalletProvider.tsx`
|
|
375
|
+
|
|
376
|
+
```tsx
|
|
377
|
+
{frozen.APTOS && (
|
|
378
|
+
<AptosProvider config={frozen.APTOS}>
|
|
379
|
+
{content}
|
|
380
|
+
</AptosProvider>
|
|
381
|
+
)}
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## Step 8 — barrel surface (`src/index.ts`)
|
|
387
|
+
|
|
388
|
+
**Do NOT** add `export * from './xchains/aptos'` to the root `src/index.ts`. Concrete classes stay behind sub-path imports.
|
|
389
|
+
|
|
390
|
+
If consumers need a **type** from the barrel for type-only ergonomics, add an explicit `export type` line:
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
// src/index.ts
|
|
394
|
+
export type { AptosWalletAddressType } from './xchains/aptos/index.js';
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
This keeps runtime classes off the barrel but lets consumers `import type { AptosWalletAddressType } from '@sodax/wallet-sdk-react'` without going through the deep import for a type-only reference.
|
|
398
|
+
|
|
399
|
+
See [`SUB_PATH_EXPORTS.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/SUB_PATH_EXPORTS.md) for why concrete classes are deep-imported.
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## Step 9 — tests
|
|
404
|
+
|
|
405
|
+
Required test surface per `vitest.config.ts`:
|
|
406
|
+
|
|
407
|
+
- `AptosXConnector.test.ts` — connector constructor, `connect/disconnect`, `isInstalled`/`installUrl` window probes
|
|
408
|
+
- `AptosXService.test.ts` (or co-located) — singleton behavior, balance reads
|
|
409
|
+
- `AptosWalletProvider.test.ts` (in wallet-sdk-core) — config variants, defaults merge, core method dispatch
|
|
410
|
+
- `AptosHydrator.test.tsx` (provider-managed only) — fake adapter state → assert store writes
|
|
411
|
+
|
|
412
|
+
Pattern reference: [`EvmHydrator.test.tsx`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/src/providers/evm/EvmHydrator.test.tsx).
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## Verification checklist
|
|
417
|
+
|
|
418
|
+
Before opening a PR, walk through each item:
|
|
419
|
+
|
|
420
|
+
- [ ] `pnpm checkTs` passes — `SodaxWalletConfig.APTOS` is recognized; `useWalletProvider({ xChainType: 'APTOS' })` returns the right type.
|
|
421
|
+
- [ ] `pnpm test` passes for new files.
|
|
422
|
+
- [ ] `pnpm build:packages` produces `dist/xchains/aptos/index.{mjs,cjs,d.ts}`.
|
|
423
|
+
- [ ] `import { AptosXService } from '@sodax/wallet-sdk-react/xchains/aptos'` resolves in a consumer app.
|
|
424
|
+
- [ ] `import { AptosXService } from '@sodax/wallet-sdk-react'` is **not** available (intentional — concrete classes stay behind deep imports).
|
|
425
|
+
- [ ] Adding `APTOS: {}` to `SodaxWalletConfig` mounts the chain; omitting the slot skips it.
|
|
426
|
+
- [ ] `useEnabledChains()` includes `'APTOS'` only when the slot is present.
|
|
427
|
+
- [ ] Connect → disconnect cycle updates `xConnections.APTOS` correctly; `localStorage` persists.
|
|
428
|
+
- [ ] On reload, `cleanupDisabledConnections` removes `xConnections.APTOS` if the slot is later removed.
|
|
429
|
+
- [ ] Documentation: add an entry to the connector reference in [`CONNECTORS.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECTORS.md) and the chain-type tables in [`CONFIGURE_PROVIDER.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONFIGURE_PROVIDER.md).
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## Related docs
|
|
434
|
+
|
|
435
|
+
- [Architecture](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/ARCHITECTURE.md) — store + registry + Hydrator pattern
|
|
436
|
+
- [Sub-path Exports](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/SUB_PATH_EXPORTS.md) — barrel vs deep-import boundary
|
|
437
|
+
- [Configure SodaxWalletProvider](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONFIGURE_PROVIDER.md) — config schema (auto-extends from `ChainMeta`)
|
|
438
|
+
- [Connectors](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECTORS.md) — IXConnector contract + sub-path map
|
|
439
|
+
- [`packages/wallet-sdk-core/CLAUDE.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-core/CLAUDE.md) — wallet provider class patterns
|
|
440
|
+
- [`packages/types/CLAUDE.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/types/CLAUDE.md) — interface conventions
|