@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,212 +0,0 @@
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.
@@ -1,22 +0,0 @@
1
- # Per-chain feature docs
2
-
3
- One file per chain family. Each file documents:
4
-
5
- - The provider class and the discriminated union of accepted configs.
6
- - The `*Defaults` shape.
7
- - The methods exposed on the provider (and how they merge defaults).
8
- - Common gotchas specific to the chain.
9
-
10
- | Chain family | Provider | Discriminant style | Underlying SDK |
11
- |---|---|---|---|
12
- | [EVM](./evm.md) | `EvmWalletProvider` | Field presence (no `type`) | `viem` |
13
- | [Solana](./solana.md) | `SolanaWalletProvider` | Field presence | `@solana/web3.js` |
14
- | [Sui](./sui.md) | `SuiWalletProvider` | Field presence (uses `mnemonics`) | `@mysten/sui` + `@mysten/wallet-standard` |
15
- | [Bitcoin](./bitcoin.md) | `BitcoinWalletProvider` | Explicit `type` | `bitcoinjs-lib`, `ecpair`, `secp256k1` |
16
- | [Stellar](./stellar.md) | `StellarWalletProvider` | Explicit `type` | `@stellar/stellar-sdk` |
17
- | [ICON](./icon.md) | `IconWalletProvider` | Field presence | `icon-sdk-js` |
18
- | [Injective](./injective.md)| `InjectiveWalletProvider` | Field presence (uses `secret` wrapper) | `@injectivelabs/sdk-ts`, `@injectivelabs/wallet-core` |
19
- | [NEAR](./near.md) | `NearWalletProvider` | Field presence | `near-api-js` + `@hot-labs/near-connect` |
20
- | [Stacks](./stacks.md) | `StacksWalletProvider` | Field presence | `@stacks/transactions`, `@stacks/connect` |
21
-
22
- For the mental model behind these tables — why discriminants differ, how `defaults` merges, what `library-exports` re-exports — see [`../architecture.md`](../architecture.md).
@@ -1,103 +0,0 @@
1
- # Bitcoin — `BitcoinWalletProvider`
2
-
3
- Backed by `bitcoinjs-lib` (PSBT signing), `ecpair`, and `@bitcoinerlab/secp256k1`.
4
-
5
- | | |
6
- |---|---|
7
- | Class | `BitcoinWalletProvider` |
8
- | Interface | `IBitcoinWalletProvider` (from `@sodax/types`) |
9
- | Discriminant style | **Explicit uppercase `type`** (`'PRIVATE_KEY' \| 'BROWSER_EXTENSION'`) |
10
- | Underlying SDK | `bitcoinjs-lib`, `ecpair`, `bip322-js` |
11
-
12
- ---
13
-
14
- ## Config
15
-
16
- ```ts
17
- type BitcoinWalletConfig = PrivateKeyBitcoinWalletConfig | BrowserExtensionBitcoinWalletConfig;
18
-
19
- type PrivateKeyBitcoinWalletConfig = {
20
- type: 'PRIVATE_KEY';
21
- privateKey: Hex; // `0x…` from @sodax/types
22
- network: 'TESTNET' | 'MAINNET';
23
- addressType?: BtcAddressType; // P2WPKH / P2TR / P2SH / P2PKH — default chosen by lib
24
- defaults?: BitcoinWalletDefaults;
25
- };
26
-
27
- type BrowserExtensionBitcoinWalletConfig = {
28
- type: 'BROWSER_EXTENSION';
29
- walletsKit: BitcoinWalletsKit; // consumer-provided adapter
30
- network: 'TESTNET' | 'MAINNET';
31
- defaults?: BitcoinWalletDefaults;
32
- };
33
-
34
- interface BitcoinWalletsKit {
35
- getAccounts(): Promise<string[]>;
36
- signPsbt(psbtHex: string): Promise<{ psbtHex: string }>;
37
- signMessage(message: string): Promise<string>;
38
- signEcdsaMessage(message: string): Promise<string>;
39
- signBip322Message(message: string): Promise<string>;
40
- getPublicKey(): Promise<string>;
41
- sendBitcoin?(toAddress: string, satoshis: number): Promise<string>;
42
- }
43
- ```
44
-
45
- | Mode discriminant | How to detect |
46
- |---|---|
47
- | Private-key | `config.type === 'PRIVATE_KEY'` |
48
- | Browser-extension | `config.type === 'BROWSER_EXTENSION'` |
49
-
50
- ---
51
-
52
- ## `BitcoinWalletDefaults`
53
-
54
- ```ts
55
- type BitcoinWalletDefaults = {
56
- defaultFinalize?: boolean; // default true — finalise after signing
57
- };
58
- ```
59
-
60
- Read directly via `this.defaults.defaultFinalize` — no `mergePolicy` / `mergeDefaults` call. Per-call `finalize` argument on `signTransaction` overrides the default; if both are omitted the implementation falls back to `true`.
61
-
62
- ---
63
-
64
- ## Methods
65
-
66
- | Method | Signature | Returns |
67
- |---|---|---|
68
- | `getWalletAddress` | `() => Promise<string>` | BTC address (per address type) |
69
- | `getPublicKey` | `() => Promise<string>` | hex public key |
70
- | `getAddressType` | `(address: string) => Promise<BtcAddressType>` | inferred type |
71
- | `signTransaction` | `(psbtBase64: string, finalize?: boolean) => Promise<string>` | signed PSBT (or finalised tx hex) |
72
- | `signEcdsaMessage` | `(message: string) => Promise<string>` | ECDSA signature |
73
- | `signBip322Message` | `(message: string) => Promise<string>` | BIP-322 signature |
74
- | `getPayment` | `(keyPair, addressType) => bitcoin.Payment` | bitcoinjs `Payment` (PK mode helper) |
75
- | `sendBitcoin` | `(toAddress: string, satoshis: bigint) => Promise<string>` | tx hash — only available in browser-extension mode if `walletsKit.sendBitcoin` is implemented |
76
-
77
- ---
78
-
79
- ## Public fields
80
-
81
- | Field | Type | Notes |
82
- |---|---|---|
83
- | `chainType` | `'BITCOIN'` (literal) | Discriminant. |
84
-
85
- `wallet`, `network` are private. Read the network via the constructor argument.
86
-
87
- ---
88
-
89
- ## Gotchas
90
-
91
- - **The discriminant is `type`, uppercase.** Bitcoin and Stellar use this style — every other chain uses field presence. Easy to confuse.
92
- - **`addressType` is optional in PK mode.** If you omit it, bitcoinjs picks a default (typically P2WPKH on mainnet). Browser-extension mode infers it from the wallet kit.
93
- - **PSBT inputs are base64-encoded** when passed to `signTransaction`. In browser-extension mode the same base64 string is forwarded to `walletsKit.signPsbt`; the kit's parameter is misleadingly named `psbtHex` but receives base64. The kit returns a signed PSBT which the provider parses as hex when finalising.
94
- - **`sendBitcoin` is optional on the wallet kit.** Some browser-extension wallets (Xverse / Unisat) implement it; others don't. Guard on its presence.
95
- - **`signEcdsaMessage` vs `signBip322Message`** — choose based on what your verifier expects. BIP-322 is the more modern, structured signature spec; ECDSA is the legacy `signmessage` RPC behavior.
96
-
97
- ---
98
-
99
- ## See also
100
-
101
- - [`recipes/setup-private-key.md`](../recipes/setup-private-key.md)
102
- - [`recipes/setup-browser-extension.md`](../recipes/setup-browser-extension.md)
103
- - [`recipes/sign-and-broadcast.md`](../recipes/sign-and-broadcast.md)
@@ -1,102 +0,0 @@
1
- # EVM — `EvmWalletProvider`
2
-
3
- Backed by [viem](https://viem.sh). One class covers all **12** SODAX EVM spoke chains via `getEvmViemChain()`.
4
-
5
- | | |
6
- |---|---|
7
- | Class | `EvmWalletProvider` |
8
- | Interface | `IEvmWalletProvider` (from `@sodax/types`) |
9
- | Discriminant style | **Field presence** (no `type` field) |
10
- | Underlying SDK | `viem` |
11
- | Supported chains | Sonic (hub), Ethereum, Arbitrum, Base, BSC, Optimism, Polygon, Avalanche, HyperEVM, Lightlink, Redbelly, Kaia |
12
-
13
- ---
14
-
15
- ## Config
16
-
17
- ```ts
18
- type EvmWalletConfig = PrivateKeyEvmWalletConfig | BrowserExtensionEvmWalletConfig;
19
-
20
- type PrivateKeyEvmWalletConfig = {
21
- privateKey: `0x${string}`;
22
- chainId: EvmChainKey; // ChainKeys.SONIC_MAINNET, …
23
- rpcUrl?: `http${string}`; // defaults to viem chain's first public RPC
24
- defaults?: EvmWalletDefaults;
25
- };
26
-
27
- type BrowserExtensionEvmWalletConfig = {
28
- walletClient: WalletClient<Transport, Chain, Account>; // pre-built by wagmi / consumer
29
- publicClient: PublicClient;
30
- defaults?: EvmWalletDefaults;
31
- };
32
- ```
33
-
34
- | Mode discriminant | How to detect |
35
- |---|---|
36
- | Private-key | `'privateKey' in config` AND `config.privateKey.startsWith('0x')` |
37
- | Browser-extension | `'walletClient' in config` AND `'publicClient' in config` |
38
-
39
- Helper predicates `isPrivateKeyEvmWalletConfig` and `isBrowserExtensionEvmWalletConfig` are exported.
40
-
41
- ---
42
-
43
- ## `EvmWalletDefaults`
44
-
45
- ```ts
46
- type EvmWalletDefaults = {
47
- publicClient?: Partial<Omit<PublicClientConfig, 'transport' | 'chain'>>;
48
- walletClient?: Partial<Omit<WalletClientConfig, 'transport' | 'chain' | 'account'>>;
49
- transport?: HttpTransportConfig;
50
- sendTransaction?: EvmSendTransactionPolicy; // Omit<Partial<SendTransactionParameters>, keyof EvmRawTransaction>
51
- waitForTransactionReceipt?: EvmWaitForTransactionReceiptPolicy; // Partial<Omit<WaitForTransactionReceiptParameters, 'hash'>>
52
- };
53
- ```
54
-
55
- | Default slice | Used by | Effective only in |
56
- |---|---|---|
57
- | `publicClient`, `walletClient`, `transport` | constructor | Private-key mode |
58
- | `sendTransaction` | `sendTransaction()` | Both modes |
59
- | `waitForTransactionReceipt` | `waitForTransactionReceipt()` | Both modes |
60
-
61
- > In browser-extension mode, `publicClient` / `walletClient` / `transport` defaults are **ignored** — the provider logs a one-time `console.warn`. Pass them only in private-key mode.
62
-
63
- ---
64
-
65
- ## Methods
66
-
67
- | Method | Signature | Returns | Default slice merged |
68
- |---|---|---|---|
69
- | `getWalletAddress` | `() => Promise<Address>` | viem `Address` (`` `0x${string}` ``) | — |
70
- | `sendTransaction` | `(txData: EvmRawTransaction, options?: EvmSendTransactionPolicy) => Promise<Hash>` | viem `Hash` | `defaults.sendTransaction` |
71
- | `waitForTransactionReceipt` | `(txHash: Hash, options?: EvmWaitForTransactionReceiptPolicy) => Promise<EvmRawTransactionReceipt>` | bigint-stringified receipt | `defaults.waitForTransactionReceipt` |
72
-
73
- The serialised receipt converts all `bigint` fields to `string` so it can be `JSON.stringify`'d safely. This is enforced at the type level — `EvmRawTransactionReceipt` (from `@sodax/types`) is the stringified shape.
74
-
75
- ---
76
-
77
- ## Public fields
78
-
79
- | Field | Type | Notes |
80
- |---|---|---|
81
- | `chainType` | `'EVM'` (literal) | Discriminant for `IXxxWalletProvider` unions. |
82
- | `publicClient` | `PublicClient` | Either built from `rpcUrl` (PK mode) or the caller's instance (browser mode). |
83
-
84
- `walletClient` is private — call `sendTransaction()` instead of touching it directly.
85
-
86
- ---
87
-
88
- ## Gotchas
89
-
90
- - **`getEvmViemChain` is exhaustive.** If `@sodax/types` adds a new `EvmChainKey`, this function fails to typecheck until the case is added — by design.
91
- - **HyperEVM is defined inside this package.** `viem/chains` does not ship a HyperEVM config; `wallet-providers/evm/EvmWalletProvider.ts` exports `hyper` via `defineChain`. You shouldn't need it directly — `getEvmViemChain(ChainKeys.HYPEREVM_MAINNET)` returns it.
92
- - **`rpcUrl` falls back to the viem chain's first public RPC.** Fine for testing — replace with a private RPC for production.
93
- - **No nonce management.** The provider does not auto-increment / serialise sends. If you fire multiple txs in parallel from the same account, manage nonces yourself via `defaults.sendTransaction.nonce` or per-call `options.nonce`.
94
-
95
- ---
96
-
97
- ## See also
98
-
99
- - [`recipes/setup-private-key.md`](../recipes/setup-private-key.md)
100
- - [`recipes/setup-browser-extension.md`](../recipes/setup-browser-extension.md)
101
- - [`recipes/sign-and-broadcast.md`](../recipes/sign-and-broadcast.md)
102
- - [`recipes/defaults-and-overrides.md`](../recipes/defaults-and-overrides.md)
@@ -1,88 +0,0 @@
1
- # ICON — `IconWalletProvider`
2
-
3
- Backed by `icon-sdk-js`. Browser-extension mode targets the Hana wallet's `postMessage` JSON-RPC bridge.
4
-
5
- | | |
6
- |---|---|
7
- | Class | `IconWalletProvider` |
8
- | Interface | `IIconWalletProvider` (from `@sodax/types`) |
9
- | Discriminant style | **Field presence** (no `type` field) |
10
- | Underlying SDK | `icon-sdk-js` |
11
-
12
- ---
13
-
14
- ## Config
15
-
16
- ```ts
17
- type IconWalletConfig = PrivateKeyIconWalletConfig | BrowserExtensionIconWalletConfig;
18
-
19
- type PrivateKeyIconWalletConfig = {
20
- privateKey: `0x${string}`;
21
- rpcUrl: `http${string}`;
22
- defaults?: IconWalletDefaults;
23
- };
24
-
25
- type BrowserExtensionIconWalletConfig = {
26
- walletAddress?: IconEoaAddress; // `hx…` — optional; resolved at first sign call if omitted
27
- rpcUrl: `http${string}`;
28
- defaults?: IconWalletDefaults;
29
- };
30
- ```
31
-
32
- | Mode discriminant | How to detect |
33
- |---|---|
34
- | Private-key | `'privateKey' in config` |
35
- | Browser-extension | `'walletAddress' in config` OR `!('privateKey' in config)` (defaults to browser-extension when key absent) |
36
-
37
- > `rpcUrl` is **required in both modes** — ICON has no public-RPC fallback in the provider.
38
-
39
- ---
40
-
41
- ## `IconWalletDefaults`
42
-
43
- ```ts
44
- type IconWalletDefaults = {
45
- stepLimit?: number; // default 3_000_000
46
- version?: string; // default '0x3'
47
- timestampProvider?: () => number; // default Date.now() * 1000 (microseconds)
48
- jsonRpcId?: number; // default 99999 (browser-extension event ID)
49
- };
50
- ```
51
-
52
- ---
53
-
54
- ## Methods
55
-
56
- | Method | Signature | Returns | Default slice merged |
57
- |---|---|---|---|
58
- | `getWalletAddress` | `() => Promise<IconEoaAddress>` | `hx…` address | — |
59
- | `sendTransaction` | `(tx: IcxCallTransaction, options?: IconWalletDefaults) => Promise<Hash>` | tx hash | `defaults` (flat merge via `mergeDefaults`) |
60
- | `waitForTransactionReceipt` | `(txHash: Hash) => Promise<IconTransactionResult>` | tx result | — |
61
-
62
- ---
63
-
64
- ## Public fields
65
-
66
- | Field | Type | Notes |
67
- |---|---|---|
68
- | `chainType` | `'ICON'` (literal) | Discriminant. |
69
- | `iconService` | `IconService` | Underlying SDK service — exposed for advanced use. |
70
-
71
- `wallet` is private.
72
-
73
- ---
74
-
75
- ## Gotchas
76
-
77
- - **Browser-extension mode talks to Hana via `window.postMessage`.** Events use a request-ID — collisions can occur if you fire many parallel calls; tune `defaults.jsonRpcId` if you control the consumer.
78
- - **`walletAddress` is optional in browser-extension mode.** When omitted, the provider issues a `REQUEST_ADDRESS` event on first use to resolve it. For deterministic behavior in scripts, pass it explicitly.
79
- - **Address type is branded — `IconEoaAddress` (`hx…`) vs `IconAddress` (`hx… | cx…`).** EOA only at the wallet level; contracts (`cx…`) appear inside tx params, not as the signer.
80
- - **Timestamps are microseconds.** `timestampProvider` returns microseconds, not milliseconds — the default is `Date.now() * 1000`.
81
-
82
- ---
83
-
84
- ## See also
85
-
86
- - [`recipes/setup-private-key.md`](../recipes/setup-private-key.md)
87
- - [`recipes/setup-browser-extension.md`](../recipes/setup-browser-extension.md)
88
- - [`recipes/sign-and-broadcast.md`](../recipes/sign-and-broadcast.md)
@@ -1,92 +0,0 @@
1
- # Injective — `InjectiveWalletProvider`
2
-
3
- Backed by `@injectivelabs/sdk-ts` (signing / msg construction) and `@injectivelabs/wallet-core` (`MsgBroadcaster` for browser flows).
4
-
5
- | | |
6
- |---|---|
7
- | Class | `InjectiveWalletProvider` |
8
- | Interface | `IInjectiveWalletProvider` (from `@sodax/types`) |
9
- | Discriminant style | **Field presence** — but PK variant uses a nested `secret` wrapper |
10
- | Underlying SDK | `@injectivelabs/sdk-ts`, `@injectivelabs/wallet-core`, `@injectivelabs/networks`, `@injectivelabs/ts-types` |
11
-
12
- ---
13
-
14
- ## Config
15
-
16
- ```ts
17
- type InjectiveWalletConfig = BrowserExtensionInjectiveWalletConfig | SecretInjectiveWalletConfig;
18
-
19
- type BrowserExtensionInjectiveWalletConfig = {
20
- msgBroadcaster: MsgBroadcaster; // pre-configured by consumer
21
- defaults?: InjectiveWalletDefaults;
22
- };
23
-
24
- type SecretInjectiveWalletConfig = {
25
- secret: { privateKey: string } | { mnemonics: string };
26
- chainId: ChainId; // from @injectivelabs/ts-types
27
- network: Network; // from @injectivelabs/networks
28
- evmOptions?: { evmChainId: EvmChainId; rpcUrl: `http${string}` }; // reserved — currently unused
29
- defaults?: InjectiveWalletDefaults;
30
- };
31
- ```
32
-
33
- | Mode discriminant | How to detect |
34
- |---|---|
35
- | Browser-extension | `'msgBroadcaster' in config` |
36
- | Secret (private-key OR mnemonics) | `'secret' in config` |
37
-
38
- > Note the naming: the second variant is `SecretInjectiveWalletConfig` (not `PrivateKey…`) because it accepts **either** a private key **or** a BIP-39 mnemonic at the `secret` slot. The dual credential shape mirrors `PrivateKey.fromPrivateKey` / `PrivateKey.fromMnemonic` in `@injectivelabs/sdk-ts`.
39
-
40
- ---
41
-
42
- ## `InjectiveWalletDefaults`
43
-
44
- ```ts
45
- type InjectiveWalletDefaults = {
46
- defaultFunds?: InjectiveCoin[]; // attached to getRawTransaction/execute if caller omits
47
- defaultMemo?: string; // default tx memo
48
- sequence?: number; // createTransaction override — default 0
49
- accountNumber?: number; // createTransaction override — default 0
50
- };
51
- ```
52
-
53
- > `MsgBroadcaster` options apply at **construction time only** (private-key path). The upstream `MsgBroadcasterWithPk` does not support post-construction reconfig.
54
-
55
- ---
56
-
57
- ## Methods
58
-
59
- | Method | Signature | Returns |
60
- |---|---|---|
61
- | `getWalletAddress` | `() => Promise<InjectiveEoaAddress>` | `inj1…` address |
62
- | `getWalletPubKey` | `() => Promise<string>` | hex pubkey |
63
- | `getRawTransaction` | `(…) => Promise<…>` | unsigned tx — useful for inspection / external signing |
64
- | `execute` | `(…) => Promise<…>` | broadcast result |
65
-
66
- `getRawTransaction` and `execute` merge `defaults.defaultFunds`, `defaults.defaultMemo`, `defaults.sequence`, `defaults.accountNumber` into the produced tx where the caller omits them.
67
-
68
- ---
69
-
70
- ## Public fields
71
-
72
- | Field | Type | Notes |
73
- |---|---|---|
74
- | `chainType` | `'INJECTIVE'` (literal) | Discriminant. |
75
- | `wallet` | `InjectiveWallet` | `{ msgBroadcaster: MsgBroadcaster \| MsgBroadcasterWithPk }` — exposed for advanced consumers. |
76
-
77
- ---
78
-
79
- ## Gotchas
80
-
81
- - **`secret` is mandatory in the PK variant.** A top-level `privateKey` field is **not** accepted — wrap in `{ secret: { privateKey } }`. Same shape in v1 and v2; if you see top-level `privateKey` in user code, it was always wrong.
82
- - **`evmOptions` is reserved.** It is declared in the type but **not currently read** by the provider. It exists to keep the config shape stable while EVM sidecar support on Injective is in development.
83
- - **`chainId` and `network` must agree.** Pass `Mainnet` + `injective-1` for mainnet, `Testnet` + `injective-888` for testnet. Mismatched pairs cause broadcasting errors that look like RPC failures.
84
- - **`sequence` / `accountNumber` defaults are zero.** Override via `defaults` or per call when the on-chain account state differs (otherwise broadcasting fails with "incorrect account sequence").
85
-
86
- ---
87
-
88
- ## See also
89
-
90
- - [`recipes/setup-private-key.md`](../recipes/setup-private-key.md)
91
- - [`recipes/setup-browser-extension.md`](../recipes/setup-browser-extension.md)
92
- - [`recipes/sign-and-broadcast.md`](../recipes/sign-and-broadcast.md)