wative-core 2.4.1 → 2.4.2
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/CHANGELOG.md +39 -0
- package/README.md +47 -32
- package/dist/artifacts/evm/index.cjs +1 -1
- package/dist/artifacts/evm/index.d.cts +2 -2
- package/dist/artifacts/evm/index.d.ts +2 -2
- package/dist/artifacts/evm/index.js +1 -1
- package/dist/artifacts/svm/index.cjs +1 -1
- package/dist/artifacts/svm/index.d.cts +3 -3
- package/dist/artifacts/svm/index.d.ts +3 -3
- package/dist/artifacts/svm/index.js +1 -1
- package/dist/{container-provider--npoeR2N.d.ts → container-provider-B8M0ylrK.d.ts} +1 -1
- package/dist/{container-provider-Ca_5z1uQ.d.cts → container-provider-YxyMpkhG.d.cts} +1 -1
- package/dist/{evm-EHpaW_sK.d.ts → evm-Bo3Dy492.d.ts} +1 -1
- package/dist/{evm-hSJJOVG3.d.cts → evm-DA6Sh6jv.d.cts} +1 -1
- package/dist/{file-sink-Bk5zYHw-.d.ts → file-sink-Be5iLbuT.d.ts} +2 -2
- package/dist/{file-sink-7ZAutH45.d.cts → file-sink-KCCpKHRj.d.cts} +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +1 -1
- package/dist/index.node.cjs +1 -1
- package/dist/index.node.d.cts +5 -5
- package/dist/index.node.d.ts +5 -5
- package/dist/index.node.js +1 -1
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.d.cts +3 -3
- package/dist/node/index.d.ts +3 -3
- package/dist/node/index.js +1 -1
- package/dist/{svm-B5q8YaV9.d.ts → svm-B51NevS8.d.ts} +1 -1
- package/dist/{svm-CXFwmeMo.d.cts → svm-DswX6XRv.d.cts} +1 -1
- package/dist/{workspace-kq3QyAgm.d.cts → workspace-CBxKR80D.d.cts} +2 -1
- package/dist/{workspace-kq3QyAgm.d.ts → workspace-CBxKR80D.d.ts} +2 -1
- package/examples/03-pk-account.test.cjs +65 -0
- package/examples/README.md +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `wative-core` are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
4
|
|
|
5
|
+
## [2.4.2] — 2026-08-11
|
|
6
|
+
|
|
7
|
+
Importing a private key gets easier and does more: you no longer have to say
|
|
8
|
+
which chain a key is for, more of the formats you actually hold are accepted,
|
|
9
|
+
and one import now gives you an address on both chains.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- **BREAKING. A PK wallet now holds two addresses instead of one.** Importing a
|
|
13
|
+
key gives you an address on the chain that key is for, plus one on the other
|
|
14
|
+
chain seeded by the same 32 secret bytes. The chain you imported for stays at
|
|
15
|
+
`addresses[0]`, so code reading that position is unaffected — but
|
|
16
|
+
`addresses.length` is now 2, and totals derived from it will differ.
|
|
17
|
+
|
|
18
|
+
⚠️ **One secret controls both addresses.** There is only one key to import,
|
|
19
|
+
so both addresses come from it, and whoever learns that key holds both
|
|
20
|
+
chains. This is not how an HD account behaves: there a slot's two addresses
|
|
21
|
+
come from two derivation paths and are independent keys. Use an HD account,
|
|
22
|
+
or import a separate key per chain, if you need that separation.
|
|
23
|
+
|
|
24
|
+
Wallets already stored keep the single address they were written with. Only
|
|
25
|
+
new imports are paired.
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- **`importPrivateKey(pk)` no longer needs a `vm`.** The accepted formats do not
|
|
29
|
+
overlap — 64 hex characters for EVM, 80–96 base58 for Solana — so the chain is
|
|
30
|
+
read off the key. Passing `vm` explicitly still works and still wins.
|
|
31
|
+
- **`solana-keygen` JSON byte arrays are accepted.** The contents of
|
|
32
|
+
`~/.config/solana/id.json` can be handed to `importPrivateKey` as-is, instead
|
|
33
|
+
of being converted to base58 by hand first.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
- **An out-of-range EVM private key is now `INVALID_PRIVATE_KEY`.** 32 bytes of
|
|
37
|
+
hex is not necessarily a key: zero, and anything at or above the secp256k1
|
|
38
|
+
group order, previously reached the curve library and surfaced as a bare
|
|
39
|
+
`Error` with no `code`, thrown from inside a queued mutation. It is refused at
|
|
40
|
+
the boundary now, like every other malformed key.
|
|
41
|
+
- Corrected the README's account diagrams, which described a PK wallet as
|
|
42
|
+
carrying exactly one address as though it were a structural rule.
|
|
43
|
+
|
|
5
44
|
## [2.4.1] — 2026-08-11
|
|
6
45
|
|
|
7
46
|
One breaking item, and it is the kind worth reading before upgrading: a
|
package/README.md
CHANGED
|
@@ -44,28 +44,64 @@ Account "Trading Desk" (HD) one mnemonic
|
|
|
44
44
|
└── … account.deriveWallets(n)
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
**PK** — imported keys.
|
|
48
|
-
|
|
47
|
+
**PK** — imported keys. Each import allocates its own `Wallet`, and that wallet
|
|
48
|
+
gets an address on **both** chains: the key signs on its own curve, and the same
|
|
49
|
+
32 secret bytes seed a keypair on the other one. The chain you imported for
|
|
50
|
+
comes first.
|
|
49
51
|
|
|
50
52
|
```
|
|
51
53
|
Account "Cold Storage" (PK) no mnemonic
|
|
52
54
|
├── Wallet 0 the key passed to accounts.create()
|
|
53
|
-
│
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
│ ├── Address vm: "evm" 0x90F8bf6A… the imported key
|
|
56
|
+
│ └── Address vm: "svm" HaWmh8svNQ… same secret, other curve
|
|
57
|
+
├── Wallet 1 account.importPrivateKey(evmKey)
|
|
58
|
+
│ ├── Address vm: "evm" 0xFFcf8FDE…
|
|
59
|
+
│ └── Address vm: "svm" Fgdy5QRxtP…
|
|
60
|
+
└── Wallet 2 account.importPrivateKey(svmKey)
|
|
61
|
+
├── Address vm: "svm" 3QVq8D876h… the imported key
|
|
62
|
+
└── Address vm: "evm" 0x1a740984… same secret, other curve
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
A PK account can hold as many keys as you like, on any mix of chains — but it
|
|
66
|
+
refuses the same identity twice, on either chain.
|
|
67
|
+
|
|
68
|
+
> ⚠️ **One secret controls both addresses in a PK wallet.** There is only one
|
|
69
|
+
> key to import, so both addresses come from it. Whoever learns that key holds
|
|
70
|
+
> both chains.
|
|
71
|
+
>
|
|
72
|
+
> This is not how an HD account works. There, a slot's two addresses come from
|
|
73
|
+
> two different derivation paths — the mnemonic is shared, the private keys are
|
|
74
|
+
> independent. If you want independent keys per chain, use an HD account, or
|
|
75
|
+
> import a separate key for each and read `addresses[0]` of each wallet.
|
|
76
|
+
|
|
77
|
+
> **`wallet.addresses` is a list.** It holds one address per `(vm, network)`
|
|
78
|
+
> pair and is free to carry several. Read it rather than assuming a position:
|
|
79
|
+
>
|
|
80
|
+
> ```ts
|
|
81
|
+
> const evm = wallet.addresses.find((a) => a.vm === "evm");
|
|
82
|
+
> ```
|
|
83
|
+
|
|
84
|
+
**Which chain a key is for is read off the key** — `vm` is optional:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
await acc.importPrivateKey(evmKey); // 64 hex chars -> evm
|
|
88
|
+
await acc.importPrivateKey(solanaKey); // base58 -> svm
|
|
89
|
+
await acc.importPrivateKey(readFileSync("id.json")); // solana-keygen -> svm
|
|
90
|
+
await acc.importPrivateKey(key, "evm"); // or say so explicitly
|
|
58
91
|
```
|
|
59
92
|
|
|
60
|
-
|
|
61
|
-
|
|
93
|
+
The formats do not overlap, so this is a decision rather than a guess. A value
|
|
94
|
+
that is neither is refused with `INVALID_PRIVATE_KEY` — including 32 bytes of
|
|
95
|
+
hex that is not a valid secp256k1 scalar, and a bare 32-byte base58 value,
|
|
96
|
+
which is indistinguishable from a Solana *public* key.
|
|
62
97
|
|
|
63
98
|
| | HD | PK |
|
|
64
99
|
| ---------------------- | ----------------------------- | ------------------------------- |
|
|
65
100
|
| Created from | a BIP-39 mnemonic | one private key |
|
|
66
101
|
| Grows with | `deriveWallets(n)` | `importPrivateKey(pk, vm)` |
|
|
67
102
|
| A `Wallet` is | a derivation slot | one imported key |
|
|
68
|
-
| Addresses per `Wallet`
|
|
103
|
+
| Addresses per `Wallet` | **2** — one evm, one svm | **2** — imported chain first |
|
|
104
|
+
| Those two addresses | independent keys, two paths | **one key, both curves** |
|
|
69
105
|
| `dumpMnemonic()` | ✔ | throws `UNSUPPORTED_OP` |
|
|
70
106
|
| `sliceWallets(n)` | ✔ | throws `UNSUPPORTED_OP` |
|
|
71
107
|
| `importPrivateKey()` | throws `UNSUPPORTED_OP` | ✔ |
|
|
@@ -150,7 +186,6 @@ await ws.lock();
|
|
|
150
186
|
| Storage | encrypted files on disk | IndexedDB |
|
|
151
187
|
| Where it lives | `Workspace.open({ path })`, or default | `IdbProvider.create(name)` |
|
|
152
188
|
| Extra setup | none | `Buffer` polyfill |
|
|
153
|
-
| Keys can vanish| no | yes — storage is evictable |
|
|
154
189
|
|
|
155
190
|
`HybridProvider`, `HybridProviderV3` and `FileSink` are re-exported from the
|
|
156
191
|
package root in Node.
|
|
@@ -233,17 +268,6 @@ produces the same keys.
|
|
|
233
268
|
Nothing to install: it runs on a bundled WebAssembly build by default, with no
|
|
234
269
|
native binary and no build step.
|
|
235
270
|
|
|
236
|
-
### Browser: grant `'wasm-unsafe-eval'`
|
|
237
|
-
|
|
238
|
-
```
|
|
239
|
-
Content-Security-Policy: script-src 'self' 'wasm-unsafe-eval'
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
Optional. Without it nothing breaks and nothing throws — key derivation falls
|
|
243
|
-
back to a slower implementation that produces identical results, so unlocking a
|
|
244
|
-
wallet with a dozen addresses takes tens of seconds instead of about one. Grant
|
|
245
|
-
it if that matters to you. `argon2BackendInfo()` reports which one ran.
|
|
246
|
-
|
|
247
271
|
### One derivation per container: `HybridProviderV3` (Node only)
|
|
248
272
|
|
|
249
273
|
```ts
|
|
@@ -262,15 +286,6 @@ It is the Node default where `@node-rs/argon2` is installed, and Node-only: that
|
|
|
262
286
|
package has no browser build. Construct it yourself only to pick a location, or
|
|
263
287
|
to be sure you get it rather than the fallback.
|
|
264
288
|
|
|
265
|
-
Two things to plan for:
|
|
266
|
-
|
|
267
|
-
- **An existing workspace does not get faster on its own.** Secrets written
|
|
268
|
-
before the switch keep their own keys, so they keep costing one derivation
|
|
269
|
-
each. `account.resetPassword(old, new)` rewrites them.
|
|
270
|
-
- ⚠️ **Older versions of this library cannot open a V3 workspace**, and there is
|
|
271
|
-
no way back. Once a workspace has been opened with V3, keep using a version
|
|
272
|
-
that supports it.
|
|
273
|
-
|
|
274
289
|
### Checking which implementation ran
|
|
275
290
|
|
|
276
291
|
```ts
|
|
@@ -312,7 +327,7 @@ The library is organized around seven things you'll work with:
|
|
|
312
327
|
|
|
313
328
|
- **`Workspace`** — your top-level container. Holds the password, your accounts, your network and asset list, and a built-in logger.
|
|
314
329
|
- **`Account`** — either an HD account (one BIP-39 mnemonic, can derive many wallets) or a PK account (raw private keys you import one at a time). Each account can have its own password or share the workspace password.
|
|
315
|
-
- **`Wallet`** — a unit inside an account
|
|
330
|
+
- **`Wallet`** — a unit inside an account, holding one address per `(vm, network)`. Both kinds give you an EVM and a Solana address: an HD slot derives one per chain from the mnemonic, an import derives its sibling from the imported key. Treat `wallet.addresses` as the list it is.
|
|
316
331
|
- **`Address`** — an on-chain identity. Sign messages, build transactions, send them.
|
|
317
332
|
- **`Network`** — chain metadata. 10 networks ship pre-loaded.
|
|
318
333
|
- **`Asset`** — token metadata. 25 tokens ship pre-loaded.
|