@sodax/wallet-sdk-core 2.0.0-rc.3 → 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/README.md +1 -2
- package/dist/index.cjs +1 -4
- package/dist/index.mjs +1 -4
- package/package.json +18 -11
- package/ai-exported/AGENTS.md +0 -139
- package/ai-exported/integration/README.md +0 -108
- package/ai-exported/integration/ai-rules.md +0 -141
- package/ai-exported/integration/architecture.md +0 -212
- package/ai-exported/integration/features/README.md +0 -22
- package/ai-exported/integration/features/bitcoin.md +0 -103
- package/ai-exported/integration/features/evm.md +0 -102
- package/ai-exported/integration/features/icon.md +0 -88
- package/ai-exported/integration/features/injective.md +0 -92
- package/ai-exported/integration/features/near.md +0 -92
- package/ai-exported/integration/features/solana.md +0 -104
- package/ai-exported/integration/features/stacks.md +0 -91
- package/ai-exported/integration/features/stellar.md +0 -95
- package/ai-exported/integration/features/sui.md +0 -96
- package/ai-exported/integration/quickstart.md +0 -259
- package/ai-exported/integration/recipes/README.md +0 -15
- package/ai-exported/integration/recipes/bridge-to-sdk.md +0 -145
- package/ai-exported/integration/recipes/defaults-and-overrides.md +0 -159
- package/ai-exported/integration/recipes/library-exports.md +0 -129
- package/ai-exported/integration/recipes/setup-browser-extension.md +0 -137
- package/ai-exported/integration/recipes/setup-private-key.md +0 -115
- package/ai-exported/integration/recipes/sign-and-broadcast.md +0 -201
- package/ai-exported/integration/recipes/testing.md +0 -163
- package/ai-exported/integration/reference/README.md +0 -13
- package/ai-exported/integration/reference/chain-support.md +0 -65
- package/ai-exported/integration/reference/glossary.md +0 -28
- package/ai-exported/integration/reference/interfaces.md +0 -131
- package/ai-exported/integration/reference/provider-classes.md +0 -54
- package/ai-exported/integration/reference/public-api.md +0 -128
- package/ai-exported/migration/README.md +0 -84
- package/ai-exported/migration/ai-rules.md +0 -139
- package/ai-exported/migration/breaking-changes/README.md +0 -14
- package/ai-exported/migration/breaking-changes/base-wallet-provider.md +0 -52
- package/ai-exported/migration/breaking-changes/defaults-config.md +0 -57
- package/ai-exported/migration/breaking-changes/folder-layout.md +0 -99
- package/ai-exported/migration/breaking-changes/library-exports.md +0 -58
- package/ai-exported/migration/checklist.md +0 -62
- package/ai-exported/migration/recipes/README.md +0 -12
- package/ai-exported/migration/recipes/adopt-defaults.md +0 -84
- package/ai-exported/migration/recipes/adopt-library-exports.md +0 -99
- package/ai-exported/migration/reference/README.md +0 -12
- package/ai-exported/migration/reference/added-fields.md +0 -71
- package/ai-exported/migration/reference/deleted-exports.md +0 -35
- package/ai-exported/migration/reference/renamed-symbols.md +0 -31
- package/ai-exported/migration/reference/return-shapes.md +0 -23
- package/dist/index.cjs.map +0 -1
- 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)
|