Wallets
The Wallet class — a derivation slot (HD) or one imported key (PK) — holding wallet.addresses (one Address per (vm, network)), tags via addTag(), and drop() through the account's wallet collection.
A Wallet is one key slot on an Account: either a single HD derivation index (m/44'/…/0'/0/{id}) or one imported private key. It owns the on-chain identities derived from that key — one Address per (vm, network) — plus a small set of tags. The mnemonic never lives here; it belongs to the account.
You obtain wallets from an account's wallets collection, never by constructing one:
import { Workspace } from "wative-core";
// The canonical all-zero BIP-39 phrase — publicly known, never fund it.
const MNEMONIC =
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
const ws = await Workspace.open({ path: "./vault", password: "wsp-pwd" });
const acc = await ws.accounts.create("Desk", "wsp-pwd", MNEMONIC);
const wallet = acc.wallets[0];wallet.id
wallet.id is a read-only, non-negative integer — the HD derivation index for an HD account, or the import slot for a PK account. It is the value used to derive the wallet's addresses and, once retired by a drop, is never reissued.
acc.wallets[0].id; // 0
acc.wallets[1].id; // 1 (after acc.deriveWallets(2))The id is also the lookup key on the account's collection:
acc.wallets.byId(0); // Wallet | nullAddresses
wallet.addresses is a read-only list of the wallet's Address objects — exactly one per (vm, network). A wallet may hold several addresses that share a vm on different networks, but never two of the same vm on the same network.
wallet.addresses.length; // number of (vm, network) identities
wallet.addresses.map((a) => a.vm); // e.g. ["evm", "svm"]Finding an address by VM
The example tests locate an address by filtering the list:
const evm = wallet.addresses.find((a) => a.vm === "evm");
const svm = wallet.addresses.find((a) => a.vm === "svm");For the two chains that ship with a signer, three convenience getters return the first matching address already narrowed to its signer subtype:
| Getter | Returns | Notes |
|---|---|---|
wallet.evm | EvmSigner | null | first vm === "evm" address |
wallet.svm | SvmSigner | null | first vm === "svm" address |
wallet.sui | Address | null | placeholder VM — a base Address, no signer yet |
const signer = wallet.evm; // EvmSigner | null
if (signer) signer.signMessage("hello");wallet.evm / wallet.svm hand back the exact EvmSigner / SvmSigner instance the wallet holds — the same object unlock keys and that carries the per-chain signing and transaction methods. wallet.sui returns a base Address because the Sui VM has no registered signer in this build.
A JSON snapshot
wallet.toJson() returns a plain, JSON-friendly array pairing each address's publicKey with its network:
wallet.toJson();
// [{ vm: "evm", publicKey: "0x…", network: { slug, chainId, name } }, …]Tags
Tags are short, free-form labels on a wallet. They are canonicalized on write (Unicode NFC, whitespace collapsed and trimmed, disallowed characters rejected), so labels that differ only in normalization or case-adjacent whitespace collapse to one entry. A wallet holds at most 64 tags.
| Member | Signature | Description |
|---|---|---|
tags | readonly string[] | a frozen copy of the current tags |
hasTag(tag) | boolean | true if the canonical form is present; never throws |
addTag(tag) | Promise<void> | validate, dedupe, persist; rejects an invalid tag or the 65th |
removeTag(tag) | Promise<void> | remove by canonical form; a no-op if absent |
clearTags() | Promise<void> | remove every tag |
await wallet.addTag("primary");
wallet.hasTag("primary"); // true
await wallet.removeTag("primary");addTag, removeTag and clearTags are asynchronous because each persists through the account's mutation queue; on a persist failure the in-memory tags roll back to their prior state.
Dropping a wallet
Removing a wallet wipes its private keys and retires its derivation index so the same key is never re-derived. Two entry points do the same thing — call either:
await wallet.drop(); // on the wallet itself
await acc.wallets.drop(wallet); // through the account's collectionAn account must always keep at least one wallet holding at least one address. Dropping the account's last wallet (or the wallet carrying its only addresses) is refused with an UNSUPPORTED_OP error — to remove the whole account, call account.drop() instead. See Accounts.
Read-only enforcement
wallet.addresses — like account.wallets — is a live, read-only view of the underlying array. The ReadonlyArray type is a compile-time claim; at runtime, any structural write through the view is refused with an UNSUPPORTED_OP error rather than silently mutating a list the next persist would write to disk:
wallet.addresses.push(x); // throws — the collection is read-only
wallet.addresses.length = 0; // throws
delete wallet.addresses[0]; // throws
acc.wallets.length = 0; // throws — same guard on the wallet collectionEvery mutating door is closed — index assignment, push / splice / sort / reverse, Object.freeze, preventExtensions and prototype changes all reject. Use the collection's own methods (acc.wallets.add, acc.wallets.drop, acc.deriveWallets) and the wallet's tag methods to change state.
wallet.dumpPrivateKey(vm) returns the decrypted private key for a VM and throws ACCOUNT_LOCKED while the account is locked. Treat its result as highly sensitive — see Security.