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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +1 -2
  2. package/dist/index.cjs +1 -4
  3. package/dist/index.mjs +1 -4
  4. package/package.json +18 -11
  5. package/ai-exported/AGENTS.md +0 -139
  6. package/ai-exported/integration/README.md +0 -108
  7. package/ai-exported/integration/ai-rules.md +0 -141
  8. package/ai-exported/integration/architecture.md +0 -212
  9. package/ai-exported/integration/features/README.md +0 -22
  10. package/ai-exported/integration/features/bitcoin.md +0 -103
  11. package/ai-exported/integration/features/evm.md +0 -102
  12. package/ai-exported/integration/features/icon.md +0 -88
  13. package/ai-exported/integration/features/injective.md +0 -92
  14. package/ai-exported/integration/features/near.md +0 -92
  15. package/ai-exported/integration/features/solana.md +0 -104
  16. package/ai-exported/integration/features/stacks.md +0 -91
  17. package/ai-exported/integration/features/stellar.md +0 -95
  18. package/ai-exported/integration/features/sui.md +0 -96
  19. package/ai-exported/integration/quickstart.md +0 -259
  20. package/ai-exported/integration/recipes/README.md +0 -15
  21. package/ai-exported/integration/recipes/bridge-to-sdk.md +0 -145
  22. package/ai-exported/integration/recipes/defaults-and-overrides.md +0 -159
  23. package/ai-exported/integration/recipes/library-exports.md +0 -129
  24. package/ai-exported/integration/recipes/setup-browser-extension.md +0 -137
  25. package/ai-exported/integration/recipes/setup-private-key.md +0 -115
  26. package/ai-exported/integration/recipes/sign-and-broadcast.md +0 -201
  27. package/ai-exported/integration/recipes/testing.md +0 -163
  28. package/ai-exported/integration/reference/README.md +0 -13
  29. package/ai-exported/integration/reference/chain-support.md +0 -65
  30. package/ai-exported/integration/reference/glossary.md +0 -28
  31. package/ai-exported/integration/reference/interfaces.md +0 -131
  32. package/ai-exported/integration/reference/provider-classes.md +0 -54
  33. package/ai-exported/integration/reference/public-api.md +0 -128
  34. package/ai-exported/migration/README.md +0 -84
  35. package/ai-exported/migration/ai-rules.md +0 -139
  36. package/ai-exported/migration/breaking-changes/README.md +0 -14
  37. package/ai-exported/migration/breaking-changes/base-wallet-provider.md +0 -52
  38. package/ai-exported/migration/breaking-changes/defaults-config.md +0 -57
  39. package/ai-exported/migration/breaking-changes/folder-layout.md +0 -99
  40. package/ai-exported/migration/breaking-changes/library-exports.md +0 -58
  41. package/ai-exported/migration/checklist.md +0 -62
  42. package/ai-exported/migration/recipes/README.md +0 -12
  43. package/ai-exported/migration/recipes/adopt-defaults.md +0 -84
  44. package/ai-exported/migration/recipes/adopt-library-exports.md +0 -99
  45. package/ai-exported/migration/reference/README.md +0 -12
  46. package/ai-exported/migration/reference/added-fields.md +0 -71
  47. package/ai-exported/migration/reference/deleted-exports.md +0 -35
  48. package/ai-exported/migration/reference/renamed-symbols.md +0 -31
  49. package/ai-exported/migration/reference/return-shapes.md +0 -23
  50. package/dist/index.cjs.map +0 -1
  51. package/dist/index.mjs.map +0 -1
@@ -1,259 +0,0 @@
1
- # Quickstart — Copy/paste examples
2
-
3
- Minimal end-to-end snippets per chain family. Pick the chain you need, copy the snippet, and run it. Each snippet covers **both** modes (private-key + browser-extension).
4
-
5
- For chain-specific gotchas (Sui's mnemonics, Injective's `secret` wrapper, …) see [`features/<chain>.md`](./features/). For the mental model see [`architecture.md`](./architecture.md).
6
-
7
- ---
8
-
9
- ## Install
10
-
11
- ```bash
12
- pnpm add @sodax/wallet-sdk-core @sodax/types
13
- ```
14
-
15
- If you plan to call `@sodax/sdk` after constructing the provider, also add it:
16
-
17
- ```bash
18
- pnpm add @sodax/sdk
19
- ```
20
-
21
- ---
22
-
23
- ## EVM (12 chains)
24
-
25
- ```ts
26
- import { EvmWalletProvider } from '@sodax/wallet-sdk-core';
27
- import { ChainKeys } from '@sodax/types';
28
-
29
- // Private-key (Node / scripts / CI)
30
- const evmPk = new EvmWalletProvider({
31
- privateKey: '0x…',
32
- chainId: ChainKeys.SONIC_MAINNET,
33
- rpcUrl: 'https://rpc.soniclabs.com',
34
- defaults: {
35
- sendTransaction: { gas: 3_000_000n },
36
- },
37
- });
38
- console.log(await evmPk.getWalletAddress());
39
-
40
- // Browser-extension (consumer supplies viem clients)
41
- const evmBrowser = new EvmWalletProvider({
42
- walletClient: myViemWalletClient, // from wagmi / viem
43
- publicClient: myViemPublicClient,
44
- });
45
- ```
46
-
47
- See [`features/evm.md`](./features/evm.md).
48
-
49
- ---
50
-
51
- ## Solana
52
-
53
- ```ts
54
- import { SolanaWalletProvider } from '@sodax/wallet-sdk-core';
55
-
56
- // Private-key — secret key bytes (Uint8Array length 64)
57
- const solanaPk = new SolanaWalletProvider({
58
- privateKey: new Uint8Array(64),
59
- endpoint: 'https://api.mainnet-beta.solana.com',
60
- defaults: {
61
- connectionCommitment: 'confirmed',
62
- sendOptions: { skipPreflight: false },
63
- },
64
- });
65
-
66
- // Browser-extension — wallet adapter context
67
- const solanaBrowser = new SolanaWalletProvider({
68
- wallet: {
69
- publicKey: myPublicKey, // PublicKey | null
70
- signTransaction: mySignTransaction, // SignerWalletAdapterProps['signTransaction'] | undefined
71
- },
72
- endpoint: 'https://api.mainnet-beta.solana.com',
73
- });
74
- ```
75
-
76
- See [`features/solana.md`](./features/solana.md).
77
-
78
- ---
79
-
80
- ## Sui
81
-
82
- ```ts
83
- import { SuiWalletProvider } from '@sodax/wallet-sdk-core';
84
-
85
- // Private-key — DERIVED FROM MNEMONIC, not a raw key
86
- const suiPk = new SuiWalletProvider({
87
- rpcUrl: 'https://fullnode.mainnet.sui.io:443',
88
- mnemonics: 'word1 word2 … word12',
89
- });
90
-
91
- // Browser-extension — wallet-standard wallet
92
- const suiBrowser = new SuiWalletProvider({
93
- client: mySuiClient, // SuiClient
94
- wallet: myWalletWithSuiFeatures, // WalletWithFeatures<Partial<SuiWalletFeatures>>
95
- account: myActiveWalletAccount, // WalletAccount
96
- });
97
- ```
98
-
99
- See [`features/sui.md`](./features/sui.md).
100
-
101
- ---
102
-
103
- ## Bitcoin
104
-
105
- ```ts
106
- import { BitcoinWalletProvider } from '@sodax/wallet-sdk-core';
107
-
108
- // Private-key — uses explicit uppercase `type`
109
- const btcPk = new BitcoinWalletProvider({
110
- type: 'PRIVATE_KEY',
111
- privateKey: '0x…',
112
- network: 'TESTNET',
113
- addressType: 'P2WPKH', // optional
114
- defaults: { defaultFinalize: true },
115
- });
116
-
117
- // Browser-extension — uses explicit uppercase `type`
118
- const btcBrowser = new BitcoinWalletProvider({
119
- type: 'BROWSER_EXTENSION',
120
- walletsKit: myBitcoinWalletsKit, // Xverse / Unisat / OKX adapter
121
- network: 'TESTNET',
122
- });
123
- ```
124
-
125
- See [`features/bitcoin.md`](./features/bitcoin.md).
126
-
127
- ---
128
-
129
- ## Stellar
130
-
131
- ```ts
132
- import { StellarWalletProvider } from '@sodax/wallet-sdk-core';
133
-
134
- // Private-key — explicit uppercase `type`
135
- const stellarPk = new StellarWalletProvider({
136
- type: 'PRIVATE_KEY',
137
- privateKey: '0x…',
138
- network: 'PUBLIC', // 'PUBLIC' | 'TESTNET'
139
- rpcUrl: 'https://horizon.stellar.org',
140
- });
141
-
142
- // Browser-extension — explicit uppercase `type`
143
- const stellarBrowser = new StellarWalletProvider({
144
- type: 'BROWSER_EXTENSION',
145
- walletsKit: myStellarWalletsKit, // Freighter / xBull / Lobstr kit
146
- network: 'PUBLIC',
147
- });
148
- ```
149
-
150
- See [`features/stellar.md`](./features/stellar.md).
151
-
152
- ---
153
-
154
- ## ICON
155
-
156
- ```ts
157
- import { IconWalletProvider } from '@sodax/wallet-sdk-core';
158
-
159
- // Private-key (Node / scripts / CI)
160
- const iconPk = new IconWalletProvider({
161
- privateKey: '0x…',
162
- rpcUrl: 'https://ctz.solidwallet.io/api/v3',
163
- });
164
-
165
- // Browser-extension — Hana wallet
166
- const iconBrowser = new IconWalletProvider({
167
- walletAddress: 'hx…', // optional; resolved at first signing call if omitted
168
- rpcUrl: 'https://ctz.solidwallet.io/api/v3',
169
- });
170
- ```
171
-
172
- See [`features/icon.md`](./features/icon.md).
173
-
174
- ---
175
-
176
- ## Injective
177
-
178
- ```ts
179
- import { InjectiveWalletProvider } from '@sodax/wallet-sdk-core';
180
- import type { ChainId, Network } from '@sodax/wallet-sdk-core';
181
-
182
- // Secret-credential variant: private key
183
- const injectivePk = new InjectiveWalletProvider({
184
- secret: { privateKey: '…' },
185
- chainId: 'injective-1' as ChainId,
186
- network: 'Mainnet' as Network,
187
- });
188
-
189
- // Secret-credential variant: mnemonic
190
- const injectiveMnemonic = new InjectiveWalletProvider({
191
- secret: { mnemonics: 'word1 word2 …' },
192
- chainId: 'injective-1' as ChainId,
193
- network: 'Mainnet' as Network,
194
- });
195
-
196
- // Browser-extension — caller supplies a configured MsgBroadcaster
197
- const injectiveBrowser = new InjectiveWalletProvider({
198
- msgBroadcaster: myMsgBroadcaster,
199
- });
200
- ```
201
-
202
- > Note: the private-key variant uses a nested `secret` wrapper instead of a top-level `privateKey`. See [`features/injective.md`](./features/injective.md).
203
-
204
- ---
205
-
206
- ## NEAR
207
-
208
- ```ts
209
- import { NearWalletProvider } from '@sodax/wallet-sdk-core';
210
-
211
- // Private-key — accountId + raw key
212
- const nearPk = new NearWalletProvider({
213
- rpcUrl: 'https://rpc.mainnet.near.org',
214
- accountId: 'alice.near',
215
- privateKey: 'ed25519:…',
216
- });
217
-
218
- // Browser-extension — NearConnector
219
- const nearBrowser = new NearWalletProvider({
220
- wallet: myNearConnector, // from @hot-labs/near-connect
221
- });
222
- ```
223
-
224
- See [`features/near.md`](./features/near.md).
225
-
226
- ---
227
-
228
- ## Stacks
229
-
230
- ```ts
231
- import { StacksWalletProvider } from '@sodax/wallet-sdk-core';
232
-
233
- // Private-key (Node / scripts / CI)
234
- const stacksPk = new StacksWalletProvider({
235
- privateKey: '…',
236
- endpoint: 'https://api.mainnet.hiro.so',
237
- });
238
-
239
- // Browser-extension — Leather / Xverse / Asigna
240
- const stacksBrowser = new StacksWalletProvider({
241
- address: 'SP…',
242
- endpoint: 'https://api.mainnet.hiro.so',
243
- provider: myStacksProvider, // StacksProvider from @stacks/connect
244
- });
245
- ```
246
-
247
- See [`features/stacks.md`](./features/stacks.md).
248
-
249
- ---
250
-
251
- ## Next steps
252
-
253
- After construction:
254
-
255
- - **Get the wallet address** — every provider exposes `getWalletAddress(): Promise<string>` (narrowed to a chain-specific brand by subclasses).
256
- - **Sign and broadcast** — see [`recipes/sign-and-broadcast.md`](./recipes/sign-and-broadcast.md) for the per-chain flow.
257
- - **Hand off to `@sodax/sdk`** — see [`recipes/bridge-to-sdk.md`](./recipes/bridge-to-sdk.md).
258
- - **Tune defaults** — see [`recipes/defaults-and-overrides.md`](./recipes/defaults-and-overrides.md).
259
- - **Avoid direct chain-SDK deps** — see [`recipes/library-exports.md`](./recipes/library-exports.md).
@@ -1,15 +0,0 @@
1
- # Recipes
2
-
3
- Self-contained, task-oriented guides. Each recipe has paired before/after code, prerequisites, and verification steps.
4
-
5
- | Recipe | When to use | Depends on |
6
- |---|---|---|
7
- | [`setup-private-key.md`](./setup-private-key.md) | Construct a provider from a raw key (Node scripts, CI, tests). | none |
8
- | [`setup-browser-extension.md`](./setup-browser-extension.md) | Construct a provider from a wallet-extension adapter (consumer dApps). | none |
9
- | [`bridge-to-sdk.md`](./bridge-to-sdk.md) | Pass the provider to `@sodax/sdk` calls. | a setup recipe |
10
- | [`defaults-and-overrides.md`](./defaults-and-overrides.md) | Configure the `defaults` slice and understand shallow-merge semantics. | a setup recipe |
11
- | [`library-exports.md`](./library-exports.md) | Avoid direct deps on `viem`, `@mysten/sui`, etc. by re-importing types from `@sodax/wallet-sdk-core`. | none |
12
- | [`sign-and-broadcast.md`](./sign-and-broadcast.md) | Typical raw-tx flow per chain. | a setup recipe |
13
- | [`testing.md`](./testing.md) | Mock providers in unit tests. | none |
14
-
15
- Pick the recipe that matches the user's task. Recipes are intentionally short and self-contained — do **not** chain more than 2 in one apply.
@@ -1,145 +0,0 @@
1
- # Recipe: Bridge to `@sodax/sdk`
2
-
3
- Pass the constructed provider to `@sodax/sdk` so the SDK can sign and submit hub/spoke transactions on the user's behalf.
4
-
5
- **Depends on:** a constructed provider (see [`setup-private-key.md`](./setup-private-key.md) or [`setup-browser-extension.md`](./setup-browser-extension.md)).
6
-
7
- ---
8
-
9
- ## The contract: `IXxxWalletProvider`
10
-
11
- `@sodax/sdk` consumes the chain-specific **interfaces** from `@sodax/types`, not the concrete classes. This is the indirection that keeps the SDK decoupled from `wallet-sdk-core`:
12
-
13
- ```ts
14
- import type {
15
- IEvmWalletProvider,
16
- ISolanaWalletProvider,
17
- ISuiWalletProvider,
18
- IBitcoinWalletProvider,
19
- IStellarWalletProvider,
20
- IIconWalletProvider,
21
- IInjectiveWalletProvider,
22
- INearWalletProvider,
23
- IStacksWalletProvider,
24
- } from '@sodax/types';
25
- ```
26
-
27
- Each `*WalletProvider` class from `wallet-sdk-core` `implements` the matching interface. So:
28
-
29
- ```ts
30
- import { EvmWalletProvider } from '@sodax/wallet-sdk-core';
31
- import type { IEvmWalletProvider } from '@sodax/types';
32
-
33
- const evm: IEvmWalletProvider = new EvmWalletProvider({ /* … */ });
34
- ```
35
-
36
- In your SDK call signatures, take the **interface**, not the class:
37
-
38
- ```ts
39
- // ✅ DO
40
- async function deposit(wallet: IEvmWalletProvider) { /* … */ }
41
-
42
- // ❌ DON'T — couples the function to the implementation
43
- async function deposit(wallet: EvmWalletProvider) { /* … */ }
44
- ```
45
-
46
- ---
47
-
48
- ## Pattern: pass the provider to a `Sodax` feature service
49
-
50
- Construct the wallet provider once, instantiate the `Sodax` facade, and pass the provider as `walletProvider` to the feature method you want (swap, bridge, money market, staking, …). The `Sodax` facade owns the per-chain spoke services internally — you do **not** construct `*SpokeService` yourself.
51
-
52
- ```ts
53
- import { Sodax } from '@sodax/sdk';
54
- import { EvmWalletProvider } from '@sodax/wallet-sdk-core';
55
- import { ChainKeys } from '@sodax/types';
56
-
57
- const walletProvider = new EvmWalletProvider({
58
- privateKey: process.env.EVM_PK as `0x${string}`,
59
- chainId: ChainKeys.SONIC_MAINNET,
60
- rpcUrl: process.env.EVM_RPC,
61
- });
62
-
63
- const sodax = new Sodax(/* optional SodaxConfig — see @sodax/sdk docs */);
64
-
65
- // Example: supply to the money market on BSC. The wallet provider goes in
66
- // at the feature-method call, not at facade construction.
67
- const result = await sodax.moneyMarket.supply({
68
- params: {
69
- srcChainKey: ChainKeys.BSC_MAINNET,
70
- srcAddress: await walletProvider.getWalletAddress(),
71
- token: '0x…',
72
- amount: 1_000n,
73
- action: 'supply',
74
- },
75
- walletProvider, // ← the IEvmWalletProvider
76
- });
77
- ```
78
-
79
- The same shape applies to `sodax.swaps.*`, `sodax.bridge.*`, `sodax.staking.*`, `sodax.migration.*`, etc. — each feature service method that needs signing takes a `walletProvider` argument typed to the chain-specific interface.
80
-
81
- > If you need the underlying spoke service for advanced read-only operations, get it via `sodax.spoke.getSpokeService(chainKey)` — but never `new EvmSpokeService(...)` yourself.
82
-
83
- For SDK-level recipes (initialise the `Sodax` facade, configure hub provider, raw-tx flows, error handling) see `@sodax/sdk`'s `ai-exported/`.
84
-
85
- ---
86
-
87
- ## Pattern: React layer (typical)
88
-
89
- In a React dApp you almost never construct providers manually. `@sodax/wallet-sdk-react` returns the typed interface for you, and `@sodax/dapp-kit` wraps SDK calls into hooks:
90
-
91
- ```tsx
92
- import { useWalletProvider } from '@sodax/wallet-sdk-react';
93
- import { useSwap } from '@sodax/dapp-kit';
94
- import { ChainKeys } from '@sodax/types';
95
-
96
- function SwapButton() {
97
- const evm = useWalletProvider({ xChainId: ChainKeys.SONIC_MAINNET });
98
- // evm: IEvmWalletProvider | undefined
99
-
100
- const swap = useSwap();
101
-
102
- return (
103
- <button
104
- disabled={!evm}
105
- onClick={() => evm && swap.mutateAsync({ /* params */, walletProvider: evm })}
106
- >
107
- Swap
108
- </button>
109
- );
110
- }
111
- ```
112
-
113
- The hook narrows on `xChainId`, returns the chain-specific interface, and is `undefined` until the user is connected on that family. Refer to `@sodax/wallet-sdk-react`'s own docs for the full pattern.
114
-
115
- ---
116
-
117
- ## Patterns to avoid
118
-
119
- | Anti-pattern | Why bad | Replacement |
120
- |---|---|---|
121
- | Re-constructing the provider in every call site | Wastes work, can drop default config | Construct once, pass the instance around |
122
- | Typing functions on the concrete class (`EvmWalletProvider`) | Couples to `wallet-sdk-core` | Use the `IXxxWalletProvider` interface |
123
- | Casting between provider classes (`as ISolanaWalletProvider`) | Hides a chain-type mismatch | Pick the right provider for the chain at the call site |
124
- | Storing the provider in a long-lived Zustand / Redux store | Provider holds live SDK clients / network connections | Store the **config** (e.g. PK + chainId), construct on demand |
125
-
126
- ---
127
-
128
- ## Verification
129
-
130
- ```bash
131
- # 1. Type check passes
132
- pnpm checkTs
133
-
134
- # 2. SDK calls type-check against the interface, not the class
135
- grep -rn "IEvmWalletProvider\|ISolanaWalletProvider\|IBitcoinWalletProvider" <user-src>
136
- # expect at least one match in your function signatures
137
- ```
138
-
139
- ---
140
-
141
- ## Next steps
142
-
143
- - [`defaults-and-overrides.md`](./defaults-and-overrides.md) — fine-tune the `defaults` slice for tx options.
144
- - [`library-exports.md`](./library-exports.md) — type-only re-exports to avoid upstream chain-SDK deps.
145
- - [`testing.md`](./testing.md) — mocking providers in tests.
@@ -1,159 +0,0 @@
1
- # Recipe: Defaults and per-call overrides
2
-
3
- Configure the `defaults` slice and understand the shallow-merge semantics shared by every provider.
4
-
5
- **Depends on:** [`setup-private-key.md`](./setup-private-key.md) or [`setup-browser-extension.md`](./setup-browser-extension.md).
6
-
7
- ---
8
-
9
- ## Mental model
10
-
11
- Every provider class extends `BaseWalletProvider<TDefaults>`. `defaults` is captured at construction time; per-call `options` are shallow-merged over the relevant slice at call time:
12
-
13
- ```
14
- final = shallowMerge(defaults[key], options) // mergePolicy('key', options)
15
- OR
16
- = shallowMerge(defaults, options) // mergeDefaults(options)
17
- ```
18
-
19
- Two helpers, two shapes:
20
-
21
- | Helper | When the chain uses it | Example |
22
- |---|---|---|
23
- | `mergePolicy('foo', opts)` | `defaults` is **grouped per method** | EVM: `defaults.sendTransaction`, `defaults.waitForTransactionReceipt` |
24
- | `mergeDefaults(opts)` | `defaults` is **flat** | Bitcoin: `defaultFinalize`; Stellar: `pollInterval`, `pollTimeout` |
25
-
26
- For the helper each chain uses, see [`../features/<chain>.md`](../features/).
27
-
28
- ---
29
-
30
- ## Shallow, not deep
31
-
32
- Top-level keys merge; **nested objects are replaced wholesale**.
33
-
34
- ```ts
35
- const provider = new EvmWalletProvider({
36
- // …
37
- defaults: {
38
- sendTransaction: { gas: 3_000_000n, nonce: 0 },
39
- },
40
- });
41
-
42
- await provider.sendTransaction(txData, { gas: 5_000_000n });
43
- // ^^^^^^^^^^^^^^^^
44
- // Final policy: { gas: 5_000_000n } ← nonce is DROPPED
45
- ```
46
-
47
- If you need `nonce` to persist, include it in the per-call options:
48
-
49
- ```ts
50
- await provider.sendTransaction(txData, { gas: 5_000_000n, nonce: 0 });
51
- ```
52
-
53
- Or split the default so each tunable lives at the top level — see `src/utils/merge.ts` for the implementation. The behavior is intentional: deep merge would silently smuggle stale fields across call sites.
54
-
55
- ---
56
-
57
- ## `undefined` is "no opinion"
58
-
59
- The merge skips:
60
-
61
- - `undefined` **layers** entirely (no options object → use defaults verbatim).
62
- - `undefined` **values** inside a layer (`{ gas: undefined }` does **not** override the previous layer).
63
-
64
- ```ts
65
- const policy: Partial<EvmSendTransactionPolicy> = { gas: undefined };
66
- await provider.sendTransaction(txData, policy);
67
- // gas falls back to defaults.sendTransaction.gas
68
- ```
69
-
70
- This is useful when threading options through optional parameters — `undefined` reads as "use the default".
71
-
72
- ---
73
-
74
- ## Where to put what
75
-
76
- | Tunable | Goes where | Why |
77
- |---|---|---|
78
- | Env-level constants (RPC URL, default gas, default commitment) | `defaults` at construction | One place, captured at startup |
79
- | Per-call tweaks (this tx needs more gas) | per-call `options` argument | Localized, doesn't leak into other calls |
80
- | Anything that changes after construction (active network in PK mode) | re-construct the provider | `defaults` is frozen at startup |
81
-
82
- You **cannot** mutate `defaults` after construction — `BaseWalletProvider` captures the reference into a `protected readonly` field. Later mutations have no effect.
83
-
84
- ---
85
-
86
- ## Worked example: EVM with two default slices
87
-
88
- ```ts
89
- import { EvmWalletProvider } from '@sodax/wallet-sdk-core';
90
- import { ChainKeys } from '@sodax/types';
91
-
92
- const provider = new EvmWalletProvider({
93
- privateKey: process.env.PK as `0x${string}`,
94
- chainId: ChainKeys.SONIC_MAINNET,
95
- defaults: {
96
- // Slice grouped by method — merged via mergePolicy('sendTransaction', …)
97
- sendTransaction: { gas: 3_000_000n },
98
-
99
- // Another method-grouped slice
100
- waitForTransactionReceipt: { confirmations: 1, timeout: 60_000 },
101
-
102
- // Constructor-time slices (private-key mode only — ignored in browser-extension mode)
103
- transport: { batch: { batchSize: 10 } },
104
- },
105
- });
106
-
107
- // Default gas: 3M. This call bumps to 5M.
108
- const hash = await provider.sendTransaction(tx, { gas: 5_000_000n });
109
-
110
- // Default 1 confirmation, 60s timeout. This call overrides both.
111
- const receipt = await provider.waitForTransactionReceipt(hash, {
112
- confirmations: 2,
113
- timeout: 30_000,
114
- });
115
- ```
116
-
117
- ---
118
-
119
- ## Browser-extension warning
120
-
121
- In **browser-extension** mode the constructor-time slices (`transport`, `publicClient`, `walletClient` on EVM; analogous on other chains) are **ignored** — the consumer already supplied built clients, so there is nothing for the provider to configure. A one-time `console.warn` is logged.
122
-
123
- ```
124
- [EvmWalletProvider] defaults.{transport,publicClient,walletClient} ignored in browser-extension mode.
125
- ```
126
-
127
- This is informational, not a bug. The method-grouped slices (`sendTransaction`, `waitForTransactionReceipt`, …) still apply in both modes.
128
-
129
- ---
130
-
131
- ## Verification
132
-
133
- ```ts
134
- // Assert that defaults applied — run on a testnet
135
- const hash = await provider.sendTransaction(tx); // no per-call options
136
- // Then read the receipt and confirm gas matches your default
137
- ```
138
-
139
- ```bash
140
- pnpm checkTs
141
- ```
142
-
143
- ---
144
-
145
- ## Common pitfalls
146
-
147
- | Pitfall | Symptom | Fix |
148
- |---|---|---|
149
- | Expecting deep merge | A nested field was "dropped" | The whole object was replaced. Include both fields in the per-call options. |
150
- | Mutating `defaults` after construction | Tunable doesn't take effect | Reconstruct the provider, or pass the new value per call. |
151
- | Setting transport defaults in browser-extension mode | Warning logged, no effect | Move them out — they only apply in PK mode. |
152
- | Putting RPC URL in `defaults` | RPC URL is a top-level config field on every chain, not a `defaults` slice | Use `rpcUrl: '…'` at the config root (PK mode), or pass `publicClient` / `client` directly (browser-extension mode). |
153
-
154
- ---
155
-
156
- ## See also
157
-
158
- - [`../architecture.md`](../architecture.md) § `BaseWalletProvider` and the `defaults` model.
159
- - [`../features/`](../features/) — per-chain `*Defaults` shape and which helper each chain uses.