wative-core 2.4.4 → 2.4.6
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 +22 -0
- package/README.md +38 -12
- 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-BHHQ3D_6.d.cts → container-provider-CCBOKuHv.d.cts} +1 -1
- package/dist/{container-provider-BlCZxRdL.d.ts → container-provider-COf_p1JR.d.ts} +1 -1
- package/dist/{evm-aNe3xFxN.d.ts → evm-B5b_UPYy.d.ts} +1 -1
- package/dist/{evm-Budo2tT1.d.cts → evm-BMB0sT3U.d.cts} +1 -1
- package/dist/{file-sink-GGSUbddN.d.cts → file-sink-778TcqKz.d.cts} +2 -2
- package/dist/{file-sink-mJ2y6o7H.d.ts → file-sink-Bu1YeJSR.d.ts} +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +9 -7
- package/dist/index.d.ts +9 -7
- package/dist/index.js +1 -1
- package/dist/index.node.cjs +1 -1
- package/dist/index.node.d.cts +6 -6
- package/dist/index.node.d.ts +6 -6
- 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-CXjYOYxt.d.cts → svm-BRKxogvC.d.cts} +1 -1
- package/dist/{svm-Cndg5tXR.d.ts → svm-CZ-D916M.d.ts} +1 -1
- package/dist/{workspace-bxOhg4wh.d.cts → workspace-Clmfomrc.d.cts} +24 -4
- package/dist/{workspace-bxOhg4wh.d.ts → workspace-Clmfomrc.d.ts} +24 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
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.6] — 2026-09-11
|
|
6
|
+
|
|
7
|
+
Fixes across signing, contracts and storage, and corrections to the documentation.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- What a transaction is signed over is fixed the moment signing starts rather than when it ends, so editing the recipient, amount or data part-way through can no longer change what gets signed. An address left unusable by a send whose outcome never came back now recovers on its own within the same session.
|
|
11
|
+
- The one-call contract helpers use the address you pass them. A completed EVM transaction reports the fee it actually paid, and a failed one reports the reason the network gave.
|
|
12
|
+
- A storage backend is held by one workspace at a time. Locking or closing a workspace hands its backend back, so you can reopen the same one; what is refused is unlocking a workspace whose backend another workspace has taken in the meantime. Two networks whose node addresses differ only cosmetically — a trailing slash, a fragment — count as the same network.
|
|
13
|
+
- The README's transaction examples called for a number of confirmations that is not supported and would always fail, and its description of reading records straight off a storage backend was the reverse of what happens. Both are corrected, along with the obligations a custom backend must meet.
|
|
14
|
+
|
|
15
|
+
## [2.4.5] — 2026-09-10
|
|
16
|
+
|
|
17
|
+
Safer handling of references you hold, of account names, and of sending transactions.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
- `workspace.close()` — finish with a workspace and release its storage, where `lock()` only ends the session. A closed workspace reports `closed` and refuses further use. `closeAllRpcClients()` is now exported, for releasing cached RPC clients when you are done with them.
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
- A `Network`, `workspace.accounts` or `workspace.networks` you obtained before locking can no longer be used to make changes after unlocking — re-read them from the workspace. `networks.add` and `networks.update` refuse the built-in `Network` objects; pass your own instance for that slug.
|
|
24
|
+
- `accounts.create` and `accounts.add` refuse a name another handle on the same storage already holds, whichever storage backend you use. Changing an account's default network now reports a failed save instead of appearing to succeed.
|
|
25
|
+
- Two transactions sent together can no longer both go out under one nonce, and an address stays usable after a lock. `rpcUrl` is validated when you assign it, not only when you pass it in, and is fixed once the transaction is prepared. A failed `Workspace.open()` leaves no storage open, `close()` can be retried, and a second file log keeps its own files.
|
|
26
|
+
|
|
5
27
|
## [2.4.4] — 2026-08-12
|
|
6
28
|
|
|
7
29
|
Correctness fixes across signing, storage and the network layer.
|
package/README.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Wative Core 2
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/wative-core)
|
|
4
|
-
[](https://github.com/braady/wative-core/actions/workflows/ci.yml)
|
|
5
4
|
[](https://nodejs.org)
|
|
6
5
|
[](./LICENSE)
|
|
7
6
|
|
|
@@ -321,7 +320,7 @@ The library is organized around seven things you'll work with:
|
|
|
321
320
|
- **`Address`** — an on-chain identity. Sign messages, build transactions, send them.
|
|
322
321
|
- **`Network`** — chain metadata. 10 networks ship pre-loaded.
|
|
323
322
|
- **`Asset`** — token metadata. 25 tokens ship pre-loaded.
|
|
324
|
-
- **`Transaction`** — `EvmTransaction` or `SvmTransaction`. Subscribe to lifecycle events (`change` / `confirmed` / `failed`) or await terminal states (`whenSubmitted` / `whenMined` / `whenConfirmed` / `whenFinalized`). Tracking stops at first inclusion, so `whenFinalized()` rejects `UNSUPPORTED_OP` unless the node reported finality directly.
|
|
323
|
+
- **`Transaction`** — `EvmTransaction` or `SvmTransaction`. Subscribe to lifecycle events (`change` / `confirmed` / `failed`) or await terminal states (`whenSubmitted` / `whenMined` / `whenConfirmed` / `whenFinalized`). Tracking stops at first inclusion, so `whenConfirmed(n)` with `n > 1` rejects `UNSUPPORTED_OP` — call it with no argument and poll `receipt.blockNumber` against the chain head if you need depth — and `whenFinalized()` rejects `UNSUPPORTED_OP` unless the node reported finality directly.
|
|
325
324
|
|
|
326
325
|
Everything is encrypted on disk under your workspace password.
|
|
327
326
|
|
|
@@ -484,7 +483,7 @@ tracker.on("confirmed", (receipt) => console.log("confirmed", receipt));
|
|
|
484
483
|
tracker.on("failed", (err) => console.error("failed", err));
|
|
485
484
|
|
|
486
485
|
const hash = await tracker.whenSubmitted();
|
|
487
|
-
const receipt = await tracker.whenConfirmed(
|
|
486
|
+
const receipt = await tracker.whenConfirmed(); // no argument — see note below
|
|
488
487
|
|
|
489
488
|
const sim = await evmAddr.simulateTransaction(tx);
|
|
490
489
|
console.log(sim.gasUsed);
|
|
@@ -566,7 +565,7 @@ const evmTx = new EvmTransaction({
|
|
|
566
565
|
await evmAddr.signTransaction(evmTx);
|
|
567
566
|
const evmTracker = await evmAddr.sendTransaction(evmTx);
|
|
568
567
|
|
|
569
|
-
const receipt = await evmTracker.whenConfirmed(
|
|
568
|
+
const receipt = await evmTracker.whenConfirmed();
|
|
570
569
|
```
|
|
571
570
|
|
|
572
571
|
For Solana transactions, build instructions with `@solana/web3.js` (or your preferred Solana toolkit) and pass them to `new SvmTransaction({ from, recipient, amount, instructions })`. The signing, sending, and tracker lifecycle then mirror the EVM flow.
|
|
@@ -642,25 +641,31 @@ const ws = await Workspace.open({ provider, password });
|
|
|
642
641
|
|
|
643
642
|
Everything a workspace persists is a `Record` — an account, a network, an asset, the config. You mostly work with the domain objects (`Account`, `Network`, …) and never touch a Record directly; you need this when you write a custom backend, or when you read records straight off a provider.
|
|
644
643
|
|
|
645
|
-
A Record
|
|
644
|
+
A Record loaded from an **unlocked** provider arrives **already decrypted** — the
|
|
645
|
+
provider opens it with the workspace password as it hands it back. Only a record
|
|
646
|
+
sealed under its own separate password comes back locked:
|
|
646
647
|
|
|
647
648
|
```ts
|
|
648
649
|
const record = await provider.loadRecord("ACCOUNTS", "alice");
|
|
649
650
|
|
|
650
|
-
record.locked; //
|
|
651
|
-
record.value; // throws RECORD_LOCKED
|
|
652
|
-
|
|
653
|
-
record.unlock(password); // decrypts in memory
|
|
651
|
+
record.locked; // false — the workspace password opened it
|
|
654
652
|
record.value; // your data
|
|
655
653
|
|
|
656
654
|
record.value.displayName = "Alice Desk";
|
|
657
655
|
await record.save(); // re-encrypts and writes back
|
|
656
|
+
|
|
657
|
+
// A record sealed under its OWN password is the locked case:
|
|
658
|
+
const sealed = await provider.loadRecord("ACCOUNTS", "bob");
|
|
659
|
+
sealed.locked; // true
|
|
660
|
+
sealed.value; // throws RECORD_LOCKED
|
|
661
|
+
sealed.unlock(ownPwd); // decrypts in memory
|
|
662
|
+
sealed.value; // your data
|
|
658
663
|
```
|
|
659
664
|
|
|
660
665
|
| member | behaviour |
|
|
661
666
|
|---|---|
|
|
662
|
-
| `locked` | `true` until `unlock()` succeeds |
|
|
663
|
-
| `value` | throws `RECORD_LOCKED` while locked |
|
|
667
|
+
| `locked` | `false` when the workspace password opened the record; `true` when it did not, until `unlock()` succeeds |
|
|
668
|
+
| `value` | your data when unlocked; throws `RECORD_LOCKED` while locked |
|
|
664
669
|
| `unlock(password)` | `BAD_PASSWORD` if wrong, `DECRYPT_FAILED` if the record cannot be read at all |
|
|
665
670
|
| `save()` | throws if locked, or if the workspace that issued it has since been locked |
|
|
666
671
|
|
|
@@ -733,7 +738,28 @@ class MyDatabaseProvider extends Provider {
|
|
|
733
738
|
const ws = await Workspace.open({ provider: new MyDatabaseProvider("postgres://..."), password: "wsp-pwd" });
|
|
734
739
|
```
|
|
735
740
|
|
|
736
|
-
`Workspace.open()` accepts any `Provider` subclass
|
|
741
|
+
`Workspace.open()` accepts any `Provider` subclass, and no library code branches
|
|
742
|
+
on which one you passed.
|
|
743
|
+
|
|
744
|
+
Two obligations the abstract signatures do not state, and one set of defaults you
|
|
745
|
+
may need to override:
|
|
746
|
+
|
|
747
|
+
- **`loadRecord` must distinguish "absent" from "unreadable".** A record that is
|
|
748
|
+
not there MUST reject with `RECORD_NOT_FOUND`. A record that is there but
|
|
749
|
+
cannot be decrypted MUST come back as a locked `Record`, not as a throw and not
|
|
750
|
+
by being omitted. A provider that returns a locked `Record` for a row it does
|
|
751
|
+
not have makes every name look taken, and no account can be created at all.
|
|
752
|
+
- **`loadRecords` must include the rows it could not open**, as locked `Record`s.
|
|
753
|
+
`Workspace` derives its damaged-record list from exactly that.
|
|
754
|
+
- **`occupiedAccountStems()` defaults to empty**, which is right for a store
|
|
755
|
+
whose keys collide only on exact equality. On a store whose collision rule is
|
|
756
|
+
wider — a case-insensitive filesystem, an S3-style key space, a
|
|
757
|
+
`utf8_general_ci` column — override it to return the lowercased stems.
|
|
758
|
+
Otherwise a damaged `Alice-Desk` row leaves `alice-desk` looking free and
|
|
759
|
+
account creation is refused as a name collision. Your bytes are safe either
|
|
760
|
+
way; the caller just cannot create the account. `accountRecordExists()` and
|
|
761
|
+
`unreadableRecordSlugs()` carry defaults in the same family — see their JSDoc
|
|
762
|
+
before overriding either.
|
|
737
763
|
|
|
738
764
|
## Imports from sub-paths
|
|
739
765
|
|