@sodax/skills 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.
- package/.claude-plugin/plugin.json +13 -0
- package/AGENTS.md +81 -0
- package/LICENSE +21 -0
- package/README.md +49 -0
- package/knowledge/dapp-kit/AGENTS.md +50 -0
- package/knowledge/dapp-kit/integration/README.md +49 -0
- package/knowledge/dapp-kit/integration/ai-rules.md +80 -0
- package/knowledge/dapp-kit/integration/architecture.md +276 -0
- package/knowledge/dapp-kit/integration/features/README.md +29 -0
- package/knowledge/dapp-kit/integration/features/auxiliary-services.md +169 -0
- package/knowledge/dapp-kit/integration/features/bitcoin.md +87 -0
- package/knowledge/dapp-kit/integration/features/bridge.md +91 -0
- package/knowledge/dapp-kit/integration/features/dex.md +152 -0
- package/knowledge/dapp-kit/integration/features/migration.md +118 -0
- package/knowledge/dapp-kit/integration/features/money-market.md +144 -0
- package/knowledge/dapp-kit/integration/features/staking.md +123 -0
- package/knowledge/dapp-kit/integration/features/swap.md +101 -0
- package/knowledge/dapp-kit/integration/quickstart.md +188 -0
- package/knowledge/dapp-kit/integration/recipes/README.md +136 -0
- package/knowledge/dapp-kit/integration/recipes/backend-queries.md +157 -0
- package/knowledge/dapp-kit/integration/recipes/bitcoin.md +193 -0
- package/knowledge/dapp-kit/integration/recipes/bridge.md +174 -0
- package/knowledge/dapp-kit/integration/recipes/dex.md +204 -0
- package/knowledge/dapp-kit/integration/recipes/invalidations.md +115 -0
- package/knowledge/dapp-kit/integration/recipes/migration.md +212 -0
- package/knowledge/dapp-kit/integration/recipes/money-market.md +207 -0
- package/knowledge/dapp-kit/integration/recipes/mutation-error-handling.md +118 -0
- package/knowledge/dapp-kit/integration/recipes/observability.md +93 -0
- package/knowledge/dapp-kit/integration/recipes/setup.md +168 -0
- package/knowledge/dapp-kit/integration/recipes/staking.md +202 -0
- package/knowledge/dapp-kit/integration/recipes/swap.md +272 -0
- package/knowledge/dapp-kit/integration/recipes/wallet-connectivity.md +128 -0
- package/knowledge/dapp-kit/integration/reference/README.md +12 -0
- package/knowledge/dapp-kit/integration/reference/glossary.md +190 -0
- package/knowledge/dapp-kit/integration/reference/hooks-index.md +190 -0
- package/knowledge/dapp-kit/integration/reference/public-api.md +110 -0
- package/knowledge/dapp-kit/integration/reference/querykey-conventions.md +179 -0
- package/knowledge/dapp-kit/migration/README.md +60 -0
- package/knowledge/dapp-kit/migration/ai-rules.md +81 -0
- package/knowledge/dapp-kit/migration/breaking-changes/hook-signatures.md +233 -0
- package/knowledge/dapp-kit/migration/breaking-changes/querykey-conventions.md +108 -0
- package/knowledge/dapp-kit/migration/breaking-changes/result-handling.md +211 -0
- package/knowledge/dapp-kit/migration/breaking-changes/sdk-leakage.md +167 -0
- package/knowledge/dapp-kit/migration/checklist.md +89 -0
- package/knowledge/dapp-kit/migration/features/README.md +34 -0
- package/knowledge/dapp-kit/migration/features/auxiliary-services.md +114 -0
- package/knowledge/dapp-kit/migration/features/bitcoin.md +88 -0
- package/knowledge/dapp-kit/migration/features/bridge.md +160 -0
- package/knowledge/dapp-kit/migration/features/dex.md +101 -0
- package/knowledge/dapp-kit/migration/features/migration.md +120 -0
- package/knowledge/dapp-kit/migration/features/money-market.md +139 -0
- package/knowledge/dapp-kit/migration/features/staking.md +109 -0
- package/knowledge/dapp-kit/migration/features/swap.md +133 -0
- package/knowledge/dapp-kit/migration/recipes.md +185 -0
- package/knowledge/dapp-kit/migration/reference/README.md +15 -0
- package/knowledge/dapp-kit/migration/reference/deleted-hooks.md +110 -0
- package/knowledge/dapp-kit/migration/reference/error-shape-crosswalk.md +144 -0
- package/knowledge/dapp-kit/migration/reference/renamed-hooks.md +68 -0
- package/knowledge/sdk/AGENTS.md +41 -0
- package/knowledge/sdk/integration/README.md +41 -0
- package/knowledge/sdk/integration/ai-rules.md +75 -0
- package/knowledge/sdk/integration/architecture.md +533 -0
- package/knowledge/sdk/integration/chain-specifics.md +189 -0
- package/knowledge/sdk/integration/features/README.md +19 -0
- package/knowledge/sdk/integration/features/auxiliary-services.md +189 -0
- package/knowledge/sdk/integration/features/bridge.md +136 -0
- package/knowledge/sdk/integration/features/dex.md +182 -0
- package/knowledge/sdk/integration/features/icx-bnusd-baln.md +181 -0
- package/knowledge/sdk/integration/features/money-market.md +198 -0
- package/knowledge/sdk/integration/features/staking.md +166 -0
- package/knowledge/sdk/integration/features/swap.md +207 -0
- package/knowledge/sdk/integration/quickstart.md +213 -0
- package/knowledge/sdk/integration/recipes/README.md +21 -0
- package/knowledge/sdk/integration/recipes/backend-server-init.md +69 -0
- package/knowledge/sdk/integration/recipes/chain-key-narrowing.md +65 -0
- package/knowledge/sdk/integration/recipes/gas-estimation.md +33 -0
- package/knowledge/sdk/integration/recipes/initialize-sodax.md +78 -0
- package/knowledge/sdk/integration/recipes/raw-tx-flow.md +71 -0
- package/knowledge/sdk/integration/recipes/result-and-errors.md +104 -0
- package/knowledge/sdk/integration/recipes/signed-tx-flow.md +46 -0
- package/knowledge/sdk/integration/recipes/testing.md +101 -0
- package/knowledge/sdk/integration/reference/README.md +18 -0
- package/knowledge/sdk/integration/reference/chain-keys.md +67 -0
- package/knowledge/sdk/integration/reference/error-codes.md +165 -0
- package/knowledge/sdk/integration/reference/glossary.md +32 -0
- package/knowledge/sdk/integration/reference/public-api.md +138 -0
- package/knowledge/sdk/integration/reference/wallet-providers.md +62 -0
- package/knowledge/sdk/migration/README.md +58 -0
- package/knowledge/sdk/migration/ai-rules.md +80 -0
- package/knowledge/sdk/migration/breaking-changes/architecture.md +344 -0
- package/knowledge/sdk/migration/breaking-changes/result-and-errors.md +363 -0
- package/knowledge/sdk/migration/breaking-changes/type-system.md +341 -0
- package/knowledge/sdk/migration/checklist.md +67 -0
- package/knowledge/sdk/migration/features/README.md +35 -0
- package/knowledge/sdk/migration/features/auxiliary-services.md +156 -0
- package/knowledge/sdk/migration/features/bridge.md +128 -0
- package/knowledge/sdk/migration/features/dex.md +143 -0
- package/knowledge/sdk/migration/features/icx-bnusd-baln.md +151 -0
- package/knowledge/sdk/migration/features/money-market.md +214 -0
- package/knowledge/sdk/migration/features/staking.md +138 -0
- package/knowledge/sdk/migration/features/swap.md +198 -0
- package/knowledge/sdk/migration/recipes.md +350 -0
- package/knowledge/sdk/migration/reference/README.md +18 -0
- package/knowledge/sdk/migration/reference/deleted-exports.md +127 -0
- package/knowledge/sdk/migration/reference/error-code-crosswalk.md +104 -0
- package/knowledge/sdk/migration/reference/return-shapes.md +49 -0
- package/knowledge/sdk/migration/reference/sodax-config.md +145 -0
- package/knowledge/wallet-sdk-core/AGENTS.md +43 -0
- package/knowledge/wallet-sdk-core/integration/README.md +108 -0
- package/knowledge/wallet-sdk-core/integration/ai-rules.md +141 -0
- package/knowledge/wallet-sdk-core/integration/architecture.md +212 -0
- package/knowledge/wallet-sdk-core/integration/features/README.md +22 -0
- package/knowledge/wallet-sdk-core/integration/features/bitcoin.md +103 -0
- package/knowledge/wallet-sdk-core/integration/features/evm.md +102 -0
- package/knowledge/wallet-sdk-core/integration/features/icon.md +88 -0
- package/knowledge/wallet-sdk-core/integration/features/injective.md +92 -0
- package/knowledge/wallet-sdk-core/integration/features/near.md +92 -0
- package/knowledge/wallet-sdk-core/integration/features/solana.md +104 -0
- package/knowledge/wallet-sdk-core/integration/features/stacks.md +91 -0
- package/knowledge/wallet-sdk-core/integration/features/stellar.md +95 -0
- package/knowledge/wallet-sdk-core/integration/features/sui.md +96 -0
- package/knowledge/wallet-sdk-core/integration/quickstart.md +259 -0
- package/knowledge/wallet-sdk-core/integration/recipes/README.md +15 -0
- package/knowledge/wallet-sdk-core/integration/recipes/bridge-to-sdk.md +145 -0
- package/knowledge/wallet-sdk-core/integration/recipes/defaults-and-overrides.md +159 -0
- package/knowledge/wallet-sdk-core/integration/recipes/library-exports.md +129 -0
- package/knowledge/wallet-sdk-core/integration/recipes/setup-browser-extension.md +137 -0
- package/knowledge/wallet-sdk-core/integration/recipes/setup-private-key.md +115 -0
- package/knowledge/wallet-sdk-core/integration/recipes/sign-and-broadcast.md +201 -0
- package/knowledge/wallet-sdk-core/integration/recipes/testing.md +163 -0
- package/knowledge/wallet-sdk-core/integration/reference/README.md +13 -0
- package/knowledge/wallet-sdk-core/integration/reference/chain-support.md +65 -0
- package/knowledge/wallet-sdk-core/integration/reference/glossary.md +28 -0
- package/knowledge/wallet-sdk-core/integration/reference/interfaces.md +131 -0
- package/knowledge/wallet-sdk-core/integration/reference/provider-classes.md +54 -0
- package/knowledge/wallet-sdk-core/integration/reference/public-api.md +128 -0
- package/knowledge/wallet-sdk-core/migration/README.md +84 -0
- package/knowledge/wallet-sdk-core/migration/ai-rules.md +139 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/README.md +14 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/base-wallet-provider.md +52 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/defaults-config.md +57 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/folder-layout.md +99 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/library-exports.md +58 -0
- package/knowledge/wallet-sdk-core/migration/checklist.md +62 -0
- package/knowledge/wallet-sdk-core/migration/recipes/README.md +12 -0
- package/knowledge/wallet-sdk-core/migration/recipes/adopt-defaults.md +84 -0
- package/knowledge/wallet-sdk-core/migration/recipes/adopt-library-exports.md +99 -0
- package/knowledge/wallet-sdk-core/migration/reference/README.md +12 -0
- package/knowledge/wallet-sdk-core/migration/reference/added-fields.md +71 -0
- package/knowledge/wallet-sdk-core/migration/reference/deleted-exports.md +35 -0
- package/knowledge/wallet-sdk-core/migration/reference/renamed-symbols.md +31 -0
- package/knowledge/wallet-sdk-core/migration/reference/return-shapes.md +23 -0
- package/knowledge/wallet-sdk-react/AGENTS.md +46 -0
- package/knowledge/wallet-sdk-react/integration/README.md +103 -0
- package/knowledge/wallet-sdk-react/integration/ai-rules.md +136 -0
- package/knowledge/wallet-sdk-react/integration/architecture.md +185 -0
- package/knowledge/wallet-sdk-react/integration/examples/01-minimal-evm.tsx +75 -0
- package/knowledge/wallet-sdk-react/integration/examples/02-multi-chain-modal.tsx +169 -0
- package/knowledge/wallet-sdk-react/integration/examples/03-nextjs-app-router.tsx +99 -0
- package/knowledge/wallet-sdk-react/integration/examples/04-walletconnect-setup.tsx +89 -0
- package/knowledge/wallet-sdk-react/integration/examples/README.md +29 -0
- package/knowledge/wallet-sdk-react/integration/recipes/batch-operations.md +224 -0
- package/knowledge/wallet-sdk-react/integration/recipes/bridge-to-sdk.md +165 -0
- package/knowledge/wallet-sdk-react/integration/recipes/chain-detection.md +259 -0
- package/knowledge/wallet-sdk-react/integration/recipes/connect-button.md +159 -0
- package/knowledge/wallet-sdk-react/integration/recipes/multi-chain-modal.md +203 -0
- package/knowledge/wallet-sdk-react/integration/recipes/setup.md +163 -0
- package/knowledge/wallet-sdk-react/integration/recipes/sign-message.md +138 -0
- package/knowledge/wallet-sdk-react/integration/recipes/sub-path-imports.md +97 -0
- package/knowledge/wallet-sdk-react/integration/recipes/switch-chain.md +144 -0
- package/knowledge/wallet-sdk-react/integration/recipes/walletconnect-setup.md +139 -0
- package/knowledge/wallet-sdk-react/integration/reference/api-surface.md +176 -0
- package/knowledge/wallet-sdk-react/integration/reference/chain-support.md +79 -0
- package/knowledge/wallet-sdk-react/integration/reference/connectors.md +75 -0
- package/knowledge/wallet-sdk-react/integration/reference/hooks.md +212 -0
- package/knowledge/wallet-sdk-react/integration/reference/wallet-brands.md +107 -0
- package/knowledge/wallet-sdk-react/migration/README.md +49 -0
- package/knowledge/wallet-sdk-react/migration/ai-rules.md +144 -0
- package/knowledge/wallet-sdk-react/migration/breaking-changes.md +310 -0
- package/knowledge/wallet-sdk-react/migration/checklist.md +159 -0
- package/knowledge/wallet-sdk-react/migration/recipes/connect-button.md +170 -0
- package/knowledge/wallet-sdk-react/migration/recipes/multi-chain-modal.md +245 -0
- package/knowledge/wallet-sdk-react/migration/recipes/ssr-setup.md +165 -0
- package/knowledge/wallet-sdk-react/migration/recipes/walletconnect-migration.md +170 -0
- package/knowledge/wallet-sdk-react/migration/reference/components.md +75 -0
- package/knowledge/wallet-sdk-react/migration/reference/config.md +339 -0
- package/knowledge/wallet-sdk-react/migration/reference/hooks.md +336 -0
- package/knowledge/wallet-sdk-react/migration/reference/imports.md +158 -0
- package/package.json +59 -0
- package/skills/sodax-dapp-kit-integration/SKILL.md +71 -0
- package/skills/sodax-dapp-kit-migration/SKILL.md +58 -0
- package/skills/sodax-sdk-integration/SKILL.md +66 -0
- package/skills/sodax-sdk-migration/SKILL.md +75 -0
- package/skills/sodax-wallet-sdk-core-integration/SKILL.md +55 -0
- package/skills/sodax-wallet-sdk-core-migration/SKILL.md +56 -0
- package/skills/sodax-wallet-sdk-react-integration/SKILL.md +80 -0
- package/skills/sodax-wallet-sdk-react-migration/SKILL.md +71 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# `SodaxConfig` constructor reshape
|
|
2
|
+
|
|
3
|
+
The v2 `Sodax` constructor accepts a `DeepPartial<SodaxConfig>`. Several config fields renamed, moved, or were added between v1 and v2; if your project passed a custom config, check these.
|
|
4
|
+
|
|
5
|
+
## v2 `SodaxConfig` shape (source of truth)
|
|
6
|
+
|
|
7
|
+
Defined in `@sodax/types` (`packages/types/src/sodax-config/sodax-config.ts`):
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
type SodaxConfig = {
|
|
11
|
+
fee: PartnerFee | undefined; // global partner fee (overridable per-feature)
|
|
12
|
+
chains: Record<SpokeChainKey, SpokeChainConfig>; // per-spoke-chain config (rpcUrl + tx polling + chain-specific shape)
|
|
13
|
+
swaps: SwapsConfig; // supported swap tokens per chain
|
|
14
|
+
moneyMarket: MoneyMarketConfig; // money market service config
|
|
15
|
+
bridge: BridgeConfig; // bridge partner-fee override
|
|
16
|
+
dex: DexConfig; // DEX service config
|
|
17
|
+
hub: HubConfig; // hub-chain (Sonic) provider config
|
|
18
|
+
api: ApiConfig; // backend API endpoint
|
|
19
|
+
solver: SolverConfig; // intent solver endpoint + contracts
|
|
20
|
+
relay: RelayConfig; // intent-relay endpoint
|
|
21
|
+
};
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
A matching default `sodaxConfig` const is exported from the same module — `new Sodax()` deep-merges your `DeepPartial<SodaxConfig>` over it.
|
|
25
|
+
|
|
26
|
+
## v1 shape (for reference)
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
// v1 — packages/sdk/src/shared/entities/Sodax.ts
|
|
30
|
+
type SodaxConfig = {
|
|
31
|
+
swaps?: SolverConfigParams; // { intentsContract, solverApiEndpoint, protocolIntentsContract?, partnerFee? }
|
|
32
|
+
moneyMarket?: MoneyMarketConfigParams;
|
|
33
|
+
migration?: MigrationServiceConfig;
|
|
34
|
+
bridge?: BridgeServiceConfig;
|
|
35
|
+
dex?: DexServiceConfig;
|
|
36
|
+
hubProviderConfig?: EvmHubProviderConfig; // { hubRpcUrl, chainConfig }
|
|
37
|
+
relayerApiEndpoint?: HttpUrl; // single URL string
|
|
38
|
+
backendApiConfig?: BackendApiConfig;
|
|
39
|
+
partners?: PartnerServiceConfig;
|
|
40
|
+
sharedConfig?: typeof defaultSharedConfig;
|
|
41
|
+
};
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
All v1 fields were **optional**. v1 had **no** top-level `rpcConfig` on `SodaxConfig` — RPC URLs were a separate prop accepted by the framework-layer `SodaxProvider` (alongside the `config` prop carrying `SodaxConfig`); the `Sodax` class constructor itself never received `rpcConfig`.
|
|
45
|
+
|
|
46
|
+
## v1 → v2 field map
|
|
47
|
+
|
|
48
|
+
| v1 location | v2 location | Notes |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| `SodaxConfig.swaps` (`SolverConfigParams` — `{ intentsContract, solverApiEndpoint, protocolIntentsContract?, partnerFee? }`) | **Split into two:** `SodaxConfig.solver: SolverConfig` (`{ intentsContract, solverApiEndpoint, protocolIntentsContract }`) and `SodaxConfig.swaps: SwapsConfig` (supported tokens per chain — new in v2). | v1 partner-fee inside `SolverConfigParams` moves to the global `SodaxConfig.fee` slot or per-feature configs. |
|
|
51
|
+
| `SodaxConfig.hubProviderConfig` (`EvmHubProviderConfig` — `{ hubRpcUrl, chainConfig }`) | **`SodaxConfig.hub`** (`HubConfig` — full hub addresses + native token + bnUSD + polling + RPC URL). | Field renamed `hubProviderConfig` → `hub`. Shape expanded: v1 just had RPC URL + chain config; v2 ships the full hub-contract address map. |
|
|
52
|
+
| `SodaxConfig.moneyMarket` (`MoneyMarketConfigParams`) | `SodaxConfig.moneyMarket` (`MoneyMarketConfig` — required, shape changed). | Reshape, see `@sodax/types/src/common/common.ts` MoneyMarketConfig. |
|
|
53
|
+
| `SodaxConfig.bridge` (`BridgeServiceConfig`) | `SodaxConfig.bridge` (`BridgeConfig` — `{ partnerFee }`). | Reshape; smaller. |
|
|
54
|
+
| `SodaxConfig.dex` (`DexServiceConfig`) | `SodaxConfig.dex` (`DexConfig`). | Reshape. |
|
|
55
|
+
| `SodaxConfig.relayerApiEndpoint: HttpUrl` (string) | **`SodaxConfig.relay`** (`RelayConfig` — object with relayer URL + chain-id map). | Renamed + reshaped from string to object. |
|
|
56
|
+
| `SodaxConfig.backendApiConfig` (`BackendApiConfig`) | **`SodaxConfig.api`** (`ApiConfig`). | Renamed. |
|
|
57
|
+
| (Separate `rpcConfig` prop on the framework-layer SodaxProvider, NOT a `SodaxConfig` field) | **`SodaxConfig.chains`** (`Record<SpokeChainKey, SpokeChainConfig>`). | v2 absorbs RPC URLs + polling + chain-specific extras into the `SodaxConfig.chains` mapped type. v1's separate `rpcConfig` provider prop is gone. The standalone `RpcConfig` type still ships from `@sodax/types` for utility use (e.g. the demo's `providers.tsx` declares a local `RpcConfig` then maps values into `chains`), but it is not a `SodaxConfig` field. |
|
|
58
|
+
| `SodaxConfig.migration` (`MigrationServiceConfig`) | **Removed.** Migration service runs with hard-coded defaults. | No replacement on `SodaxConfig`. v2 surfaces customization via per-method params on `sodax.migration.*`, not constructor config — see [`../features/icx-bnusd-baln.md`](../features/icx-bnusd-baln.md). |
|
|
59
|
+
| `SodaxConfig.partners` (`PartnerServiceConfig`) | **Removed.** Partner service runs with defaults. | Per-claim partner-fee config now flows via call-level params on `sodax.partners.*` methods. |
|
|
60
|
+
| `SodaxConfig.sharedConfig` (`typeof defaultSharedConfig`) | **Removed.** | Absorbed into `ConfigService` + per-chain `SpokeChainConfig`. Override individual chains via `SodaxConfig.chains[key]`. |
|
|
61
|
+
| (none in v1) | **`SodaxConfig.fee: PartnerFee \| undefined`** (new). | Global partner-fee, applies to all features unless overridden by feature-level config (`bridge.partnerFee`, money market, etc.). |
|
|
62
|
+
| (v1 had no top-level `configService` injection slot on `SodaxConfig` — `ConfigService` was always constructed internally from `backendApiConfig` + `sharedConfig`.) | Same — `ConfigService` is internal. v2 does **not** expose a typed slot to inject a custom `IConfigApi` either. To swap the backend in tests, point `SodaxConfig.api.baseURL` at a mock server. | See Pitfall below. |
|
|
63
|
+
|
|
64
|
+
Migration:
|
|
65
|
+
|
|
66
|
+
```diff
|
|
67
|
+
- // v1 — typical SodaxConfig literal
|
|
68
|
+
- const sodaxConfig = {
|
|
69
|
+
- hubProviderConfig: { hubRpcUrl: 'https://…', chainConfig: getHubChainConfig() },
|
|
70
|
+
- moneyMarket: getMoneyMarketConfig(hubChainId),
|
|
71
|
+
- swaps: {
|
|
72
|
+
- intentsContract: '0x…',
|
|
73
|
+
- solverApiEndpoint: 'https://…',
|
|
74
|
+
- protocolIntentsContract: '0x…',
|
|
75
|
+
- partnerFee: { address: '0x…', percentage: 10 },
|
|
76
|
+
- },
|
|
77
|
+
- relayerApiEndpoint: 'https://relay.example.com',
|
|
78
|
+
- } satisfies SodaxConfig;
|
|
79
|
+
- // RPC URLs were passed as a SEPARATE prop on the framework-layer SodaxProvider
|
|
80
|
+
- // (alongside the sodaxConfig). The Sodax constructor itself never saw rpcConfig.
|
|
81
|
+
|
|
82
|
+
+ // v2 — DeepPartial<SodaxConfig> passed directly to new Sodax(...)
|
|
83
|
+
+ const sodax = new Sodax({
|
|
84
|
+
+ hub: { /* HubConfig — usually omit, default ships full hub addresses */ },
|
|
85
|
+
+ solver: {
|
|
86
|
+
+ intentsContract: '0x…',
|
|
87
|
+
+ solverApiEndpoint: 'https://…',
|
|
88
|
+
+ protocolIntentsContract: '0x…',
|
|
89
|
+
+ },
|
|
90
|
+
+ swaps: {
|
|
91
|
+
+ supportedTokens: { /* per-chain table */ },
|
|
92
|
+
+ },
|
|
93
|
+
+ relay: { /* RelayConfig — relayer URL + chain-id map */ },
|
|
94
|
+
+ fee: { address: '0x…', percentage: 10 }, // global partner fee (moved out of swaps)
|
|
95
|
+
+ chains: {
|
|
96
|
+
+ [ChainKeys.SONIC_MAINNET]: { rpcUrl: 'https://…' },
|
|
97
|
+
+ [ChainKeys.ARBITRUM_MAINNET]: { rpcUrl: 'https://…' },
|
|
98
|
+
+ [ChainKeys.BITCOIN_MAINNET]: { /* BitcoinSpokeChainConfig shape */ },
|
|
99
|
+
+ // …
|
|
100
|
+
+ },
|
|
101
|
+
+ });
|
|
102
|
+
+ await sodax.config.initialize();
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Per-chain `SpokeChainConfig` shape
|
|
106
|
+
|
|
107
|
+
`SodaxConfig.chains` is keyed by `SpokeChainKey`; each entry's value type varies by chain family. The user-overridable surface (`rpcUrl`, polling config, chain-specific extras) is the same set of fields `RpcConfig` covers in v1, but nested inside `SpokeChainConfig` rather than flat. Inspect the type at:
|
|
108
|
+
|
|
109
|
+
- `packages/types/src/chains/chains.ts` — `SpokeChainConfig` discriminated union
|
|
110
|
+
- `packages/types/src/common/common.ts` — `BitcoinRpcConfig`, `StellarRpcConfig`, `InjectiveRpcConfig` (used inside the EVM-non-EVM branches)
|
|
111
|
+
|
|
112
|
+
See [`../breaking-changes/type-system.md`](../breaking-changes/type-system.md) § 5 for the chain-family-specific entry shapes.
|
|
113
|
+
|
|
114
|
+
### Pitfall
|
|
115
|
+
|
|
116
|
+
If you previously injected a custom `ConfigService` for testing (a v1 escape hatch), v2 doesn't accept one at the top level — and unlike what earlier doc versions claimed, **v2 also doesn't expose a typed slot to inject a custom `IConfigApi`**. The realistic options:
|
|
117
|
+
|
|
118
|
+
- Point `SodaxConfig.api.baseURL` at a local mock backend server.
|
|
119
|
+
- Construct your own `BackendApiService`-compatible object in your app/test bootstrap and swap it in where you control the `Sodax` instance.
|
|
120
|
+
|
|
121
|
+
The `SodaxConfig.api` field is `ApiConfig` (`{ baseURL, timeout, headers }`) — there is no `api.api` sub-field for IConfigApi injection.
|
|
122
|
+
|
|
123
|
+
### Pitfall — module-scope reads
|
|
124
|
+
|
|
125
|
+
If your code reads hub addresses or default configs **before** the `Sodax` instance exists (module-scope constants), use the re-exported defaults from `@sodax/types` (also flow through `@sodax/sdk` since it re-exports the entire types surface):
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
import { hubConfig, sodaxConfig } from '@sodax/sdk';
|
|
129
|
+
|
|
130
|
+
const HUB_WALLET = hubConfig.addresses.hubWallet; // module-scope OK
|
|
131
|
+
const DEFAULT_RELAY = sodaxConfig.relay; // module-scope OK
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`hubConfig` / `sodaxConfig` are the **packaged defaults** — the same values `ConfigService` falls back to if the backend is unreachable. Once you have a `Sodax` instance, prefer `sodax.config.getHubChainConfig()` / `sodax.config.*` so backend-driven updates take effect.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
## Cross-references
|
|
140
|
+
|
|
141
|
+
- [`README.md`](README.md) — migration reference index.
|
|
142
|
+
- [`../README.md`](../README.md) — migration overview.
|
|
143
|
+
- [`../checklist.md`](../checklist.md) — top-level migration checklist.
|
|
144
|
+
- [`../breaking-changes/type-system.md`](../breaking-changes/type-system.md) § 5 — per-chain config entry shapes.
|
|
145
|
+
- [`deleted-exports.md`](deleted-exports.md) — `getHubChainConfig()` and other deleted symbols.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Knowledge tree — `@sodax/wallet-sdk-core`
|
|
2
|
+
|
|
3
|
+
Long-form knowledge supporting the `@sodax/wallet-sdk-core` skills under `@sodax/skills`. The action-oriented entry points are the SKILL.md files in the sibling `skills/` directory:
|
|
4
|
+
|
|
5
|
+
- New code → `packages/skills/skills/sodax-wallet-sdk-core-integration/SKILL.md`
|
|
6
|
+
- Porting v1 → `packages/skills/skills/sodax-wallet-sdk-core-migration/SKILL.md`
|
|
7
|
+
|
|
8
|
+
**Don't read this tree top-to-bottom.** Load files from the **Workflow** section of the relevant SKILL.md.
|
|
9
|
+
|
|
10
|
+
## Package summary
|
|
11
|
+
|
|
12
|
+
`@sodax/wallet-sdk-core` is the **low-level** wallet layer of the SODAX stack — one provider class per chain family (9 in total: EVM, Solana, Sui, Bitcoin, Stellar, ICON, Injective, NEAR, Stacks). Each class accepts either a **private-key** config (server-side scripts, CI, Node) or a **browser-extension** config (consumer dApps with pre-built clients/wallet kits), signs transactions, and broadcasts them.
|
|
13
|
+
|
|
14
|
+
It is **not** a React layer (that is `@sodax/wallet-sdk-react`) and **not** a hooks layer (that is `@sodax/dapp-kit`). Most React consumers never touch this package directly — they get a typed `IXxxWalletProvider` via `useWalletProvider(...)` and hand it to `@sodax/sdk` calls. Direct usage of `wallet-sdk-core` is the right choice for backend / Node scripts, custom non-React browser flows, and tests that need to sign with a deterministic key.
|
|
15
|
+
|
|
16
|
+
The package name did **not** change across versions — both v1 and v2 publish as `@sodax/wallet-sdk-core`. All v1 → v2 surface changes are additive (no renames, no deletions). The only mechanical migration is replacing deep imports from v1's flat `wallet-providers/*.ts` layout with barrel imports.
|
|
17
|
+
|
|
18
|
+
## Layout
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
knowledge/wallet-sdk-core/
|
|
22
|
+
├── AGENTS.md # You are here
|
|
23
|
+
├── integration/ # New code (per-chain provider setup)
|
|
24
|
+
│ ├── README.md
|
|
25
|
+
│ ├── ai-rules.md
|
|
26
|
+
│ ├── architecture.md # BaseWalletProvider, discriminants, defaults merge
|
|
27
|
+
│ ├── quickstart.md # Minimal per-chain copy-paste examples
|
|
28
|
+
│ ├── features/ # Per-chain config table, methods, gotchas (9 chains)
|
|
29
|
+
│ ├── recipes/ # setup-private-key, setup-browser-extension, sign-and-broadcast, defaults-and-overrides, library-exports, bridge-to-sdk, testing
|
|
30
|
+
│ └── reference/ # Public API, provider classes, interfaces, chain support, glossary
|
|
31
|
+
└── migration/ # Additive v1 → v2 (mostly deep-import → barrel cleanup)
|
|
32
|
+
├── README.md
|
|
33
|
+
├── ai-rules.md
|
|
34
|
+
├── checklist.md
|
|
35
|
+
├── breaking-changes/ # folder-layout, defaults-config, base-wallet-provider, library-exports
|
|
36
|
+
├── recipes/ # adopt-defaults, adopt-library-exports (optional)
|
|
37
|
+
└── reference/ # added-fields, deleted-exports (empty), renamed-symbols (empty), return-shapes
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Cross-references
|
|
41
|
+
|
|
42
|
+
- SDK calls: `packages/skills/knowledge/sdk/integration/recipes/raw-tx-flow.md` and `signed-tx-flow.md` show how the wallet provider plugs into `@sodax/sdk` payloads.
|
|
43
|
+
- React equivalent: `packages/skills/knowledge/wallet-sdk-react/` (use `useWalletProvider({ xChainId })` instead of constructing providers directly).
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Integration: First-time setup (Human-readable overview)
|
|
2
|
+
|
|
3
|
+
This folder helps you integrate `@sodax/wallet-sdk-core` into a fresh project — most commonly a Node script, a backend service, or a custom non-React frontend. It is the **human-facing** entry point for new integrations. If you are a coding agent, read [`ai-rules.md`](./ai-rules.md) first.
|
|
4
|
+
|
|
5
|
+
If you are upgrading from an older version of the package instead, see `../migration/`.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What this package does
|
|
10
|
+
|
|
11
|
+
`@sodax/wallet-sdk-core` is a **low-level multi-chain wallet provider layer**. For each of the 9 chain families that SODAX supports it ships **one provider class** that:
|
|
12
|
+
|
|
13
|
+
- Accepts a **discriminated union config** — `PrivateKey*WalletConfig | BrowserExtension*WalletConfig`.
|
|
14
|
+
- Extends a small `BaseWalletProvider` to merge per-call options over a typed `defaults` shape.
|
|
15
|
+
- Implements the chain-specific `IXxxWalletProvider` interface from `@sodax/types`, so it can be passed straight into `@sodax/sdk` calls.
|
|
16
|
+
|
|
17
|
+
It is intentionally framework-agnostic — Node ≥ 20.12, browser, edge runtimes are all supported (tsup `esbuildOptions.platform: 'neutral'`).
|
|
18
|
+
|
|
19
|
+
| Chain family | Provider class | Underlying chain SDK |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| EVM (12 chains) | `EvmWalletProvider` | `viem` |
|
|
22
|
+
| Solana | `SolanaWalletProvider` | `@solana/web3.js` |
|
|
23
|
+
| Sui | `SuiWalletProvider` | `@mysten/sui` + `@mysten/wallet-standard` |
|
|
24
|
+
| Bitcoin | `BitcoinWalletProvider` | `bitcoinjs-lib` (+ `ecpair`, `secp256k1`) |
|
|
25
|
+
| Stellar | `StellarWalletProvider` | `@stellar/stellar-sdk` |
|
|
26
|
+
| ICON | `IconWalletProvider` | `icon-sdk-js` |
|
|
27
|
+
| Injective | `InjectiveWalletProvider` | `@injectivelabs/sdk-ts` + `@injectivelabs/wallet-core` |
|
|
28
|
+
| NEAR | `NearWalletProvider` | `near-api-js` + `@hot-labs/near-connect` |
|
|
29
|
+
| Stacks | `StacksWalletProvider` | `@stacks/transactions` + `@stacks/connect` |
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Recommended path (in order)
|
|
34
|
+
|
|
35
|
+
If this is your first time using the package:
|
|
36
|
+
|
|
37
|
+
1. [`architecture.md`](./architecture.md) — read once before any recipe. Explains `BaseWalletProvider`, the `defaults` shallow-merge model, dual-config discriminants, and the `library-exports` indirection. Picking the wrong config variant is the most common mistake — the mental model prevents it.
|
|
38
|
+
2. [`quickstart.md`](./quickstart.md) — minimal end-to-end example for the chain you need. Copy, edit, run.
|
|
39
|
+
3. [`features/<chain>.md`](./features/) — chain-specific config table, methods, and gotchas (one file per chain).
|
|
40
|
+
4. Pick the right recipes:
|
|
41
|
+
- [`recipes/setup-private-key.md`](./recipes/setup-private-key.md) — server-side / CI flow.
|
|
42
|
+
- [`recipes/setup-browser-extension.md`](./recipes/setup-browser-extension.md) — consumer dApp flow.
|
|
43
|
+
- [`recipes/bridge-to-sdk.md`](./recipes/bridge-to-sdk.md) — hand off the provider to `@sodax/sdk` calls.
|
|
44
|
+
- [`recipes/defaults-and-overrides.md`](./recipes/defaults-and-overrides.md) — merge semantics for the `defaults` config.
|
|
45
|
+
- [`recipes/library-exports.md`](./recipes/library-exports.md) — re-importing upstream chain-SDK types without a direct dep.
|
|
46
|
+
- [`recipes/sign-and-broadcast.md`](./recipes/sign-and-broadcast.md) — typical send-transaction flow per chain.
|
|
47
|
+
- [`recipes/testing.md`](./recipes/testing.md) — mocking providers in unit tests.
|
|
48
|
+
5. Reference docs (lookup as needed):
|
|
49
|
+
- [`reference/public-api.md`](./reference/public-api.md) — every named export from the package root.
|
|
50
|
+
- [`reference/provider-classes.md`](./reference/provider-classes.md) — provider × config × interface table.
|
|
51
|
+
- [`reference/interfaces.md`](./reference/interfaces.md) — `IXxxWalletProvider` method signatures.
|
|
52
|
+
- [`reference/chain-support.md`](./reference/chain-support.md) — chain family → spoke chain keys.
|
|
53
|
+
- [`reference/glossary.md`](./reference/glossary.md) — terms used across the docs.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Install
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pnpm add @sodax/wallet-sdk-core @sodax/types
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Most consumers will also need `@sodax/sdk` (for the hub/spoke services that accept the wallet provider) and one or more chain SDKs (for browser-extension wallet objects). Re-export the types you need via `library-exports` — see [`recipes/library-exports.md`](./recipes/library-exports.md).
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Two configuration modes
|
|
68
|
+
|
|
69
|
+
Every provider class supports **two** construction modes. Picking the wrong one is the most common integration mistake.
|
|
70
|
+
|
|
71
|
+
| Mode | When to use | Discriminant style |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| **Private-key** | Node scripts, CI tests, indexers, bots — anywhere you possess the raw key | Either field presence (EVM, Solana, Sui, ICON, Injective, NEAR, Stacks) OR `type: 'PRIVATE_KEY'` (Bitcoin, Stellar) |
|
|
74
|
+
| **Browser-extension** | Consumer dApps where a wallet extension provides a pre-built client / signer | Either field presence (different fields from PK variant) OR `type: 'BROWSER_EXTENSION'` (Bitcoin, Stellar) |
|
|
75
|
+
|
|
76
|
+
For a chain-by-chain breakdown of the exact discriminant shape, see [`features/`](./features/) and [`architecture.md`](./architecture.md) § "Discriminant variants".
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Pair with `@sodax/sdk` and `@sodax/wallet-sdk-react`
|
|
81
|
+
|
|
82
|
+
The most common stack:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
@sodax/sdk ← business logic (swaps, lending, staking, …)
|
|
86
|
+
@sodax/wallet-sdk-react ← React layer that surfaces a typed IXxxWalletProvider via hooks
|
|
87
|
+
@sodax/wallet-sdk-core ← this package — concrete provider classes
|
|
88
|
+
@sodax/types ← shared type definitions
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
In a React dApp you usually consume this package **indirectly** — `useWalletProvider({ xChainId })` (from `@sodax/wallet-sdk-react`) returns a typed `IXxxWalletProvider` that comes from a `wallet-sdk-core` instance under the hood. You only construct provider classes from `wallet-sdk-core` directly when running scripts, tests, or non-React clients.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Conventions worth knowing
|
|
96
|
+
|
|
97
|
+
- **`defaults` is optional but powerful.** Every provider accepts a `defaults` config slice; per-call options shallow-merge over it. Use it to encode env-level fixed choices (RPC commitment, default gas, default memo) once.
|
|
98
|
+
- **Shallow merge, not deep.** Nested objects in `defaults` are **replaced wholesale** by per-call options of the same key. See `src/utils/merge.ts` and [`recipes/defaults-and-overrides.md`](./recipes/defaults-and-overrides.md).
|
|
99
|
+
- **`library-exports` removes upstream deps.** You can `import type { WalletClient } from '@sodax/wallet-sdk-core'` instead of taking a direct dep on `viem`. See [`recipes/library-exports.md`](./recipes/library-exports.md).
|
|
100
|
+
- **The barrel is the source of truth.** Internal utilities (`shallowMerge`, helper functions) are **not** exported. If something isn't on `@sodax/wallet-sdk-core`'s root, do not deep-import it.
|
|
101
|
+
- **No `as unknown as` casts.** The discriminated unions are precise — if TypeScript complains, your config is wrong, not the type.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Getting help
|
|
106
|
+
|
|
107
|
+
- API surface lookup: [`reference/`](./reference/).
|
|
108
|
+
- Bug or missing feature: [open an issue](https://github.com/icon-project/sodax-sdks/issues).
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# AI Rules — Fresh Integration
|
|
2
|
+
|
|
3
|
+
You are integrating `@sodax/wallet-sdk-core` into a user's project for the first time. Follow this protocol exactly.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Workflow (do these in order)
|
|
8
|
+
|
|
9
|
+
### 1. Survey the project
|
|
10
|
+
|
|
11
|
+
Before changing anything, gather context:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Runtime — Node script? React dApp? Edge runtime?
|
|
15
|
+
cat <user>/package.json | grep -E '"type|"main|"module'
|
|
16
|
+
|
|
17
|
+
# Node version — must be >= 18
|
|
18
|
+
cat <user>/.nvmrc 2>/dev/null
|
|
19
|
+
node --version
|
|
20
|
+
|
|
21
|
+
# Is the user already using @sodax/wallet-sdk-react?
|
|
22
|
+
cat <user>/package.json | grep '"@sodax/wallet-sdk-react'
|
|
23
|
+
|
|
24
|
+
# Are upstream chain SDKs already direct deps? (may indicate they don't yet know about library-exports)
|
|
25
|
+
cat <user>/package.json | grep -E '"viem"|"@solana/web3.js"|"@mysten/sui"|"@stellar/stellar-sdk"|"@stacks/transactions"|"@injectivelabs"|"near-api-js"|"bitcoinjs-lib"|"icon-sdk-js"'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**If Node < 20.12**, stop and tell the user — this package requires Node ≥ 20.12.
|
|
29
|
+
|
|
30
|
+
**If the user is already using `@sodax/wallet-sdk-react` in the same project**, ask whether they really need to construct providers directly. In a React app the answer is usually **no**: `useWalletProvider({ xChainId })` returns the typed provider for them. Direct construction is only correct for scripts, tests, or non-React clients.
|
|
31
|
+
|
|
32
|
+
### 2. Pick the right mode
|
|
33
|
+
|
|
34
|
+
For **each** chain the user wants to integrate, decide between:
|
|
35
|
+
|
|
36
|
+
| Mode | When to pick | Stop and ask if... |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| **Private-key** | A Node script, CI runner, indexer, or test that legitimately possesses a raw key. | The user pastes a real-looking key in a frontend file. Never embed a private key in a browser bundle. |
|
|
39
|
+
| **Browser-extension** | A dApp where a wallet extension (MetaMask, Phantom, Xverse, Hana, Freighter, Leather, …) provides the signing primitives. | The user has neither a key nor a wallet adapter on hand. They probably want `@sodax/wallet-sdk-react` instead. |
|
|
40
|
+
|
|
41
|
+
Ask the user which mode applies **before** writing code. Default to **private-key** for `apps/node`-style scripts and **browser-extension** for `apps/web`-style dApps.
|
|
42
|
+
|
|
43
|
+
### 3. Apply the matching recipe
|
|
44
|
+
|
|
45
|
+
- Private-key flow → [`recipes/setup-private-key.md`](./recipes/setup-private-key.md).
|
|
46
|
+
- Browser-extension flow → [`recipes/setup-browser-extension.md`](./recipes/setup-browser-extension.md).
|
|
47
|
+
|
|
48
|
+
Each recipe is self-contained — install snippet, config, first method call, verification.
|
|
49
|
+
|
|
50
|
+
### 4. Hand off to `@sodax/sdk` if needed
|
|
51
|
+
|
|
52
|
+
If the user wants to swap / bridge / stake / lend / migrate, they need to pass the provider to `@sodax/sdk` calls. Apply [`recipes/bridge-to-sdk.md`](./recipes/bridge-to-sdk.md). Do not invent your own bridging pattern.
|
|
53
|
+
|
|
54
|
+
### 5. Add advanced features as separate steps
|
|
55
|
+
|
|
56
|
+
Only after the basic flow works should you add:
|
|
57
|
+
|
|
58
|
+
- Default config slices ([`recipes/defaults-and-overrides.md`](./recipes/defaults-and-overrides.md))
|
|
59
|
+
- Importing upstream chain types via `library-exports` ([`recipes/library-exports.md`](./recipes/library-exports.md))
|
|
60
|
+
- Sign + broadcast flow for the chain ([`recipes/sign-and-broadcast.md`](./recipes/sign-and-broadcast.md))
|
|
61
|
+
- Mocking providers in tests ([`recipes/testing.md`](./recipes/testing.md))
|
|
62
|
+
|
|
63
|
+
Each is independent — apply only what the user asked for.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## DO
|
|
68
|
+
|
|
69
|
+
- **DO** use the discriminated union types in your `import` statement so TypeScript narrows the config correctly:
|
|
70
|
+
```ts
|
|
71
|
+
import { EvmWalletProvider, type EvmWalletConfig } from '@sodax/wallet-sdk-core';
|
|
72
|
+
```
|
|
73
|
+
- **DO** use chain key constants from `@sodax/types` (`ChainKeys.SONIC_MAINNET`, `ChainKeys.BSC_MAINNET`, …) instead of magic numbers / strings.
|
|
74
|
+
- **DO** re-export upstream chain types via `library-exports` (`import type { WalletClient } from '@sodax/wallet-sdk-core'`) — keeps direct chain-SDK deps out of `package.json`.
|
|
75
|
+
- **DO** pass an `IXxxWalletProvider` (the **interface** from `@sodax/types`), not the concrete class, to SDK calls. Interfaces are how the SDK stays decoupled from this package.
|
|
76
|
+
- **DO** put RPC URLs, network selectors, default gas, etc. in the `defaults` config slice — one place, one source of truth.
|
|
77
|
+
- **DO** consult [`features/<chain>.md`](./features/) for the chain you are integrating before writing the constructor call. Each chain has slightly different field names.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## DO NOT
|
|
82
|
+
|
|
83
|
+
- **DO NOT** embed a private key in a frontend bundle. Browser-extension config exists for a reason.
|
|
84
|
+
- **DO NOT** import from `@sodax/wallet-sdk-core/src/...` deep paths. Only the package root is public.
|
|
85
|
+
- **DO NOT** deep-import the internal `shallowMerge` from `src/utils/merge.ts`. It is intentionally not exported.
|
|
86
|
+
- **DO NOT** extend `BaseWalletProvider` in user code unless you are adding a brand-new chain to this package. That is a maintainer-only path.
|
|
87
|
+
- **DO NOT** widen the discriminated union with a cast (e.g. `as EvmWalletConfig`). If TypeScript complains, your fields are wrong — fix the fields.
|
|
88
|
+
- **DO NOT** mutate `defaults` after construction. Providers freeze the `defaults` reference; later mutations are silently ignored.
|
|
89
|
+
- **DO NOT** mix discriminant styles for a chain. Bitcoin and Stellar **require** an uppercase `type: 'PRIVATE_KEY' | 'BROWSER_EXTENSION'`; every other chain uses **field presence**. See [`architecture.md`](./architecture.md) § "Discriminant variants".
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Stop conditions (defer to user)
|
|
94
|
+
|
|
95
|
+
| Signal | Why stop |
|
|
96
|
+
|---|---|
|
|
97
|
+
| User asks for a chain family not in [chain support](./reference/chain-support.md) | Adding a new chain is a maintainer task, not user-app integration. |
|
|
98
|
+
| User wants to extend `BaseWalletProvider` directly | Maintainer-only path. Confirm scope first. |
|
|
99
|
+
| User wants to deep-merge `defaults` with per-call options | Not supported — merge is **shallow** by design. See [`recipes/defaults-and-overrides.md`](./recipes/defaults-and-overrides.md). If the user really needs deep merge, they must combine before passing. |
|
|
100
|
+
| User wants to inject a custom `Transport` / `Connection` / `SuiClient` in private-key mode | Some chains expose this via `defaults`; others don't. Check the chain's [feature file](./features/) first. |
|
|
101
|
+
| User wants to use a wallet brand the chain SDK does not support | Out of scope — wallet brand support lives in the upstream chain SDK / kit. |
|
|
102
|
+
| User is in a React app and wants to construct providers in components | Almost always wrong. Direct user to `@sodax/wallet-sdk-react`'s `useWalletProvider` hook. |
|
|
103
|
+
| User asks "how do I sign with X without a key and without an extension" | They probably want a custom signer — this package does not currently model that. Flag as out of scope. |
|
|
104
|
+
|
|
105
|
+
When stopping, **quote the file/line** of the offending code and present the user with concrete options.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Verification protocol (after every recipe)
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# 1. Type check passes
|
|
113
|
+
pnpm checkTs
|
|
114
|
+
|
|
115
|
+
# 2. No deep imports
|
|
116
|
+
grep -rn "@sodax/wallet-sdk-core/" <user-src> | grep -v "from '@sodax/wallet-sdk-core'"
|
|
117
|
+
# expect empty — only barrel imports allowed
|
|
118
|
+
|
|
119
|
+
# 3. No direct upstream chain-SDK imports for types that library-exports provides
|
|
120
|
+
grep -rn "from 'viem'" <user-src> | grep -E "WalletClient|PublicClient|TransactionReceipt"
|
|
121
|
+
# if any match, suggest re-importing via @sodax/wallet-sdk-core
|
|
122
|
+
|
|
123
|
+
# 4. Sample call works
|
|
124
|
+
# (manual — run a one-shot sign + broadcast on testnet)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
If steps 1–3 pass and the user confirms step 4, the recipe is done.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Done criteria
|
|
132
|
+
|
|
133
|
+
The integration is complete when:
|
|
134
|
+
|
|
135
|
+
- [ ] `pnpm checkTs` exits clean.
|
|
136
|
+
- [ ] The user has at least one provider instance constructed via the correct discriminated union variant.
|
|
137
|
+
- [ ] Types are imported from `@sodax/wallet-sdk-core` (and `@sodax/types`) only — no deep paths.
|
|
138
|
+
- [ ] If using `@sodax/sdk`: the provider is passed via the `IXxxWalletProvider` interface, not the concrete class.
|
|
139
|
+
- [ ] A sign + broadcast (or get-address) call has succeeded against testnet or a local mock.
|
|
140
|
+
|
|
141
|
+
Do not declare integration done before all of the above are true.
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# Architecture — Mental Model
|
|
2
|
+
|
|
3
|
+
This file explains **why** `@sodax/wallet-sdk-core` is shaped the way it is. Read it once before applying recipes — knowing the model lets you handle ambiguous user code without guessing.
|
|
4
|
+
|
|
5
|
+
If you are looking for "how do I do X", go to [`recipes/`](./recipes/) or [`features/`](./features/). This file is purely conceptual.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The shape of the package
|
|
10
|
+
|
|
11
|
+
`@sodax/wallet-sdk-core` is a **uniform low-level wallet layer over heterogeneous chain SDKs**. For each of the 9 chain families that SODAX supports, the package ships:
|
|
12
|
+
|
|
13
|
+
1. A `*WalletProvider` **class** that implements a chain-specific interface (`IEvmWalletProvider`, `ISolanaWalletProvider`, …) imported from `@sodax/types`.
|
|
14
|
+
2. A discriminated-union **config type** (`*WalletConfig = PrivateKey* | BrowserExtension*`).
|
|
15
|
+
3. A `*WalletDefaults` type — the per-method default option shape merged into each call.
|
|
16
|
+
|
|
17
|
+
Each provider class extends a small abstract `BaseWalletProvider<TDefaults>`. That base holds the `defaults` reference and exposes two helpers:
|
|
18
|
+
|
|
19
|
+
- `mergePolicy(key, options)` — shallow-merges per-call options over `defaults[key]`. Used when defaults are grouped per method (e.g. `defaults.sendTransaction`).
|
|
20
|
+
- `mergeDefaults(options)` — shallow-merges per-call options over the entire flat `defaults`. Used when defaults are not grouped.
|
|
21
|
+
|
|
22
|
+
Subclasses do three things on top:
|
|
23
|
+
|
|
24
|
+
1. Declare a `chainType` literal (`'EVM' as const`, `'BITCOIN' as const`, …).
|
|
25
|
+
2. Discriminate the config and initialize chain-specific state (viem client, Solana `Connection`, `SuiClient`, …).
|
|
26
|
+
3. Implement the chain-specific interface methods (`sendTransaction`, `signTransaction`, …).
|
|
27
|
+
|
|
28
|
+
Consumers only ever see the public surface: construct the class with one of the union variants, call its methods, and hand the instance to `@sodax/sdk` via its `IXxxWalletProvider` interface.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## File-system tour
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
src/
|
|
36
|
+
├── index.ts # Barrel: re-exports wallet-providers + types
|
|
37
|
+
├── types/
|
|
38
|
+
│ ├── index.ts # Re-exports library-exports
|
|
39
|
+
│ └── library-exports.ts # Re-exported types (and a few enums) from upstream chain SDKs
|
|
40
|
+
├── utils/ # Internal — shallowMerge; NOT re-exported
|
|
41
|
+
│ ├── index.ts
|
|
42
|
+
│ ├── merge.ts
|
|
43
|
+
│ └── merge.test.ts
|
|
44
|
+
└── wallet-providers/
|
|
45
|
+
├── index.ts # Barrel: re-exports every provider folder
|
|
46
|
+
├── BaseWalletProvider.ts # Abstract base class
|
|
47
|
+
├── evm/
|
|
48
|
+
│ ├── EvmWalletProvider.ts
|
|
49
|
+
│ ├── EvmWalletProvider.test.ts
|
|
50
|
+
│ ├── types.ts
|
|
51
|
+
│ └── index.ts
|
|
52
|
+
├── solana/ { …same shape… }
|
|
53
|
+
├── sui/ { …same shape… }
|
|
54
|
+
├── bitcoin/ { …same shape… }
|
|
55
|
+
├── stellar/ { …same shape… }
|
|
56
|
+
├── icon/ { …same shape… }
|
|
57
|
+
├── injective/{ …same shape… }
|
|
58
|
+
├── near/ { …same shape… }
|
|
59
|
+
└── stacks/ { …same shape… }
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Three things to internalize:
|
|
63
|
+
|
|
64
|
+
1. **The package root is the only public surface.** `src/utils/*` is internal — `shallowMerge` etc. are deliberately not re-exported.
|
|
65
|
+
2. **Each chain is folder-isolated.** Adding a new chain means creating a folder under `src/wallet-providers/<chain>/` and listing it in `wallet-providers/index.ts`. Nothing else changes.
|
|
66
|
+
3. **`types/library-exports.ts` is the indirection point** between upstream chain SDKs and consumers. Re-exporting from here means consumer apps don't need direct deps on `viem`, `@mysten/sui`, etc. for type-only usage.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## `BaseWalletProvider` and the `defaults` model
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
abstract class BaseWalletProvider<TDefaults extends object> {
|
|
74
|
+
protected readonly defaults: TDefaults;
|
|
75
|
+
|
|
76
|
+
constructor(defaults: TDefaults | undefined) {
|
|
77
|
+
this.defaults = (defaults ?? {}) as TDefaults;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
abstract getWalletAddress(): Promise<string>;
|
|
81
|
+
|
|
82
|
+
protected mergePolicy<K extends keyof TDefaults>(key: K, options?: …): … { /* shallowMerge */ }
|
|
83
|
+
protected mergeDefaults(options?: Partial<TDefaults>): TDefaults { /* shallowMerge */ }
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Three rules govern the `defaults` model:
|
|
88
|
+
|
|
89
|
+
1. **Every field of `TDefaults` is optional.** The constructor falls back to `{}` if the consumer omits `defaults` entirely. Required fields would silently arrive as `undefined` at runtime without TypeScript catching it — see the JSDoc comment in `BaseWalletProvider.ts`.
|
|
90
|
+
2. **Merge is shallow.** Top-level keys merge; nested objects are **replaced wholesale**. If `defaults.sendTransaction = { gas: 3_000_000n, nonce: 0 }` and the caller passes `{ gas: 5_000_000n }`, the merged policy is `{ gas: 5_000_000n }` — `nonce` is dropped. See `src/utils/merge.ts`. The behaviour is intentional: deep merge would silently smuggle stale fields across call sites.
|
|
91
|
+
3. **`undefined` layers and `undefined` values are skipped.** Passing `{ field: undefined }` does **not** override an earlier layer — the merge treats `undefined` as "no opinion".
|
|
92
|
+
|
|
93
|
+
Two helpers exist because chains group their defaults differently:
|
|
94
|
+
|
|
95
|
+
- **Per-method grouping** — `mergePolicy('sendTransaction', options)` looks up `defaults.sendTransaction` and merges `options` over it. Used by EVM (`sendTransaction`, `waitForTransactionReceipt`), Sui (`signAndExecuteTxn`, `getCoins`).
|
|
96
|
+
- **Flat grouping** — `mergeDefaults(options)` merges `options` over the whole `defaults` object. Used by chains whose `defaults` is a flat record (Bitcoin's `{ defaultFinalize }`, Stellar's `{ pollInterval, pollTimeout, networkPassphrase }`).
|
|
97
|
+
|
|
98
|
+
For a concrete worked example see [`recipes/defaults-and-overrides.md`](./recipes/defaults-and-overrides.md).
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Discriminant variants
|
|
103
|
+
|
|
104
|
+
Every chain supports two construction modes — but the discriminant **looks different per chain**. The rule of thumb:
|
|
105
|
+
|
|
106
|
+
| Discriminant style | Chains | Example |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| **Field presence** (no `type` field) | EVM, Solana, Sui, ICON, Injective, NEAR, Stacks | EVM: `privateKey + chainId` → private-key. `walletClient + publicClient` → browser-extension. |
|
|
109
|
+
| **Explicit uppercase `type`** | Bitcoin, Stellar | `{ type: 'PRIVATE_KEY', … }` vs `{ type: 'BROWSER_EXTENSION', … }` |
|
|
110
|
+
|
|
111
|
+
Why the inconsistency: the field-presence form is shorter for the common case but only works when the two variants share **zero** required-field overlap. Bitcoin and Stellar have shared required fields (`network`, `walletsKit` shapes that overlap with PK fields) that would make field presence ambiguous, so they use explicit `type`.
|
|
112
|
+
|
|
113
|
+
Two more wrinkles to know about:
|
|
114
|
+
|
|
115
|
+
- **Sui uses `mnemonics`, not `privateKey`.** The library derives an Ed25519 keypair from the mnemonic phrase. There is no raw-secret-key option.
|
|
116
|
+
- **Injective uses a nested `secret` object.** Because Injective can be constructed from **either** a private key **or** a BIP-39 mnemonic, the private-key variant nests credentials under `secret: { privateKey } | { mnemonics }` instead of placing them at the top level. The type is named `SecretInjectiveWalletConfig` (not `PrivateKey*`) to reflect this.
|
|
117
|
+
|
|
118
|
+
For chain-by-chain breakdowns see [`features/`](./features/).
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## `library-exports` — the upstream-SDK indirection
|
|
123
|
+
|
|
124
|
+
`src/types/library-exports.ts` re-exports a curated set of types (and a few runtime values) from each upstream chain SDK:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
// viem types
|
|
128
|
+
export type { Account, Address, Chain, Transport, PublicClient, WalletClient,
|
|
129
|
+
HttpTransportConfig, PublicClientConfig, WalletClientConfig,
|
|
130
|
+
SendTransactionParameters, WaitForTransactionReceiptParameters,
|
|
131
|
+
TransactionReceipt } from 'viem';
|
|
132
|
+
|
|
133
|
+
// Sui types
|
|
134
|
+
export type { SuiTransactionBlockResponseOptions } from '@mysten/sui/client';
|
|
135
|
+
export type { Transaction, TransactionArgument } from '@mysten/sui/transactions';
|
|
136
|
+
export type { SuiWalletFeatures, WalletAccount, WalletWithFeatures } from '@mysten/wallet-standard';
|
|
137
|
+
|
|
138
|
+
// Solana types
|
|
139
|
+
export type { Commitment, ConnectionConfig, SendOptions } from '@solana/web3.js';
|
|
140
|
+
|
|
141
|
+
// Injective types
|
|
142
|
+
export type { Network } from '@injectivelabs/networks';
|
|
143
|
+
export type { ChainId, EvmChainId } from '@injectivelabs/ts-types';
|
|
144
|
+
export type { MsgBroadcaster } from '@injectivelabs/wallet-core';
|
|
145
|
+
|
|
146
|
+
// Stellar (also re-exports the `Networks` runtime value)
|
|
147
|
+
export { Networks } from '@stellar/stellar-sdk';
|
|
148
|
+
|
|
149
|
+
// Stacks (also re-exports the `PostConditionMode` enum)
|
|
150
|
+
export { PostConditionMode } from '@stacks/transactions';
|
|
151
|
+
export type { ClarityValue, PostConditionModeName } from '@stacks/transactions';
|
|
152
|
+
export type { StacksNetwork } from '@stacks/network';
|
|
153
|
+
export type { StacksProvider } from '@stacks/connect';
|
|
154
|
+
|
|
155
|
+
// Near
|
|
156
|
+
export type { KeyPairString } from 'near-api-js';
|
|
157
|
+
export type { NearConnector } from '@hot-labs/near-connect';
|
|
158
|
+
|
|
159
|
+
// Bitcoin
|
|
160
|
+
export type { Network as BitcoinJsNetwork } from 'bitcoinjs-lib/src/networks.js';
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Consumers can import the types they need directly from `@sodax/wallet-sdk-core` instead of adding `viem`, `@mysten/sui`, etc. to their `package.json`:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
import type { WalletClient, PublicClient, TransactionReceipt } from '@sodax/wallet-sdk-core';
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Note the file name: `library-exports`, not `library-types`. It deliberately re-exports a small number of **runtime** values (`Networks`, `PostConditionMode`) — hence the broader name.
|
|
170
|
+
|
|
171
|
+
For the typical reasons to use it (and when not to), see [`recipes/library-exports.md`](./recipes/library-exports.md).
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## The `IXxxWalletProvider` interface — your handoff to `@sodax/sdk`
|
|
176
|
+
|
|
177
|
+
Each provider class implements a chain-specific interface from `@sodax/types`:
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
class EvmWalletProvider extends BaseWalletProvider<EvmWalletDefaults> implements IEvmWalletProvider { … }
|
|
181
|
+
class BitcoinWalletProvider extends BaseWalletProvider<BitcoinWalletDefaults> implements IBitcoinWalletProvider { … }
|
|
182
|
+
// …and so on
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
When you call `@sodax/sdk` methods, the SDK expects the **interface**, not the concrete class:
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
import type { IEvmWalletProvider } from '@sodax/types';
|
|
189
|
+
|
|
190
|
+
async function deposit(evmProvider: IEvmWalletProvider) { /* … */ }
|
|
191
|
+
|
|
192
|
+
const evm = new EvmWalletProvider({ … });
|
|
193
|
+
await deposit(evm); // ✅ EvmWalletProvider implements IEvmWalletProvider
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
This indirection is how the SDK stays decoupled from `wallet-sdk-core`. In a React app, `useWalletProvider({ xChainId })` from `@sodax/wallet-sdk-react` returns the interface directly — the React layer constructs the concrete class internally.
|
|
197
|
+
|
|
198
|
+
For the full interface signatures, see [`reference/interfaces.md`](./reference/interfaces.md).
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Things that look weird until you know why
|
|
203
|
+
|
|
204
|
+
- **`InjectiveWalletConfig` is `BrowserExtensionInjectiveWalletConfig | SecretInjectiveWalletConfig`** — note the `Secret*` (not `PrivateKey*`) name. It also accepts mnemonics, hence the broader name. See [`features/injective.md`](./features/injective.md).
|
|
205
|
+
- **EVM in browser-extension mode ignores `defaults.transport`, `defaults.publicClient`, and `defaults.walletClient`.** Because the consumer supplied pre-built clients, these defaults are no-ops — the provider logs a one-time `console.warn`. Pass them only in private-key mode. See `EvmWalletProvider.ts`.
|
|
206
|
+
- **HyperEVM is defined inside this package.** `viem/chains` does not ship a HyperEVM config, so `wallet-providers/evm/EvmWalletProvider.ts` exports a `hyper` chain object via `defineChain`. You shouldn't need to import it directly — `getEvmViemChain(ChainKeys.HYPEREVM_MAINNET)` returns it.
|
|
207
|
+
- **`getEvmViemChain(key)` is exhaustively typed.** The default branch is a `never`-assertion — if `@sodax/types` adds a new `EvmChainKey` value, this function fails to typecheck until the case is added. That's by design.
|
|
208
|
+
- **Sui browser-extension mode requires THREE objects** — `client`, `wallet`, and `account`. Many wallet adapters expose the first two but not the third. See [`features/sui.md`](./features/sui.md).
|
|
209
|
+
- **Stellar requires `rpcUrl` in both modes** (technically optional, but defaults to a public RPC). Use a private RPC for production.
|
|
210
|
+
- **Bitcoin in private-key mode also takes an optional `addressType`** (P2WPKH / P2TR / …). Browser-extension mode infers it from the wallet kit.
|
|
211
|
+
|
|
212
|
+
Everything else is covered by [`features/`](./features/) on a per-chain basis.
|