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

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, three 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
wallet.suiAddress | nullplaceholder VM — a base Address, no signer yet
const signer = wallet.evm; // EvmSigner | null
if (signer) signer.signMessage("hello");

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

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 collection

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