Wallets & AddressesWallets

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:

wallets.ts
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. On an HD account, shortening with sliceWallets frees the tail indices rather than retiring them: because derivation is deterministic, a later deriveWallets that reaches a freed index again re-derives the identical addresses.

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 | null

wallet.disabled

wallet.disabled is a read-only boolean — true when the wallet's derivation index is marked disabled on its account. Disabling is a soft, reversible marker: it does not change the wallet's keys or addresses. A disabled wallet is hidden from account.getWalletList() by default (pass force: true to include it) and is gated from key use — dumpPrivateKey, message and typed-data signing, and signing or sending a transaction all throw WALLET_DISABLED until the wallet is re-enabled.

wallet-disabled.ts
await acc.deriveWallets(1);
const w = acc.wallets[1];
w.disabled; // false

await acc.disableAddressNos([w.id]);
w.disabled;                    // true
w.dumpPrivateKey("evm");       // → WativeError { code: "WALLET_DISABLED" }

await acc.enableAddressNos([w.id]);
w.disabled; // false

Addresses

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, two convenience getters return the first matching address already narrowed to its signer subtype:

GetterReturnsNotes
wallet.evmEvmSigner | nullfirst vm === "evm" address
wallet.svmSvmSigner | nullfirst vm === "svm" address
const signer = wallet.evm; // EvmSigner | null
if (signer) signer.signMessage("hello");

VM-agnostic accessors

When you don't want to name the chain, two accessors follow the owning account's default network instead of a fixed VM:

AccessorReturnsNotes
wallet.vmVmTokenthe VM of the account's default network — the chain wallet.address selects. Tracks account.setDefaultNetwork.
wallet.addressAddress | nullthis wallet's address for wallet.vm (i.e. the wallet.evm / wallet.svm the VM selects), or null when the wallet has no address for that VM.
acc.defaultNetwork; // "ethereum" (an EVM network)
wallet.vm;          // "evm"
wallet.address;     // same object as wallet.evm

await acc.setDefaultNetwork("solana");
wallet.vm;          // "svm" — follows the default
wallet.address;     // now the SVM address (wallet.svm)

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.

MemberSignatureDescription
tagsreadonly string[]a frozen copy of the current tags
hasTag(tag)booleantrue 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

wallet.drop() applies to private-key accounts only. It wipes the wallet's imported key and removes it from the account. Two entry points reach the same drop — call either:

await wallet.drop();            // on the wallet itself
await acc.wallets.drop(wallet); // through the account's collection

On an HD account both forms throw UNSUPPORTED_OP: an HD account's wallets are consecutive derivation indices, so shorten it from the tail with account.sliceWallets(fromIndex) — which frees the indices it removes — or hide an index with account.disableSlots(...).

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 collection

Every 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.

Last updated on