HD Accounts
Mnemonic-backed accounts — deriveWallets(n), sliceWallets(n) and dumpMnemonic() — where each slot yields one EVM and one Solana address from independent BIP-44 paths.
An HD account is backed by a single BIP-39 mnemonic. Every derivation slot produces one wallet holding two addresses — one EVM, one Solana — derived from independent BIP-44 paths. Because the slots are deterministic, the same mnemonic reproduces the same addresses on any device.
Create from a mnemonic
Pass a valid BIP-39 mnemonic as the secret. The kind is inferred as HD, so opts.kind is optional. Wallet 0 is derived during create().
import { Workspace } from "wative-core";
const MNEMONIC =
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
const ws = await Workspace.open({ path: "./my-wallet", password: "wsp-pwd" });
const acc = await ws.accounts.create("Desk", "wsp-pwd", MNEMONIC);
acc.wallets.length; // 1 — wallet 0 derived at create timeNeed a fresh phrase rather than an existing one? See Generating Mnemonics.
Derive and slice
deriveWallets(count) appends count new slots. sliceWallets(fromIndex) is its inverse: it drops every wallet whose BIP-32 index is >= fromIndex.
const acc = await ws.accounts.create("Desk", "wsp-pwd", MNEMONIC);
await acc.deriveWallets(10);
acc.wallets.length; // 11 — wallet 0 plus 10 derived
await acc.sliceWallets(6);
acc.wallets.length; // 6| Method | Signature | Behavior |
|---|---|---|
deriveWallets | deriveWallets(count: number): Promise<{ before: number; after: number }> | Appends count slots. Transactional — all-or-nothing; a failure adds nothing and does not persist. count is 1–10,000. |
sliceWallets | sliceWallets(fromIndex: number): Promise<{ before: number; after: number; dropped: number }> | Drops every wallet with index >= fromIndex. fromIndex is a finite integer >= 1. |
sliceWallets extends the account's retired-index set with the freed range, so a later deriveWallets(n) continues past the highest dropped index rather than re-deriving the identical addresses back into the freed slots.
An account must always keep at least one wallet holding at least one key. A sliceWallets call that would remove every wallet — or leave the account with no addresses — throws UNSUPPORTED_OP. To remove the account entirely, call account.drop() instead.
Both methods are HD-only. Calling them on a PK account throws UNSUPPORTED_OP; use importPrivateKey() and wallets.drop() there instead (see PK Accounts).
Dump the mnemonic
dumpMnemonic() returns the decrypted phrase. The account must be HD and unlocked.
const acc = await ws.accounts.create("Desk", "wsp-pwd", MNEMONIC);
acc.dumpMnemonic(); // === MNEMONICCalled on a PK account, or on a locked account, it throws. It returns a string.
One slot, two independent keys
Each HD slot yields two addresses on different chains, and their private keys are independent — they come from two different BIP-44 derivation paths over the shared seed (m/44'/60'/… for EVM, m/44'/501'/… for Solana). This is the key distinction from a PK wallet, whose two addresses reuse one secret across both curves.
const acc = await ws.accounts.create("Persistent", "wsp-pwd", MNEMONIC);
await acc.deriveWallets(2);
const first = acc.wallets[0].addresses[0].publicKey; // stable across lock + reopenAddresses persist and re-derive identically after a lock and reopen:
await ws.lock();
const reopened = (await Workspace.open({ path: "./my-wallet", password: "wsp-pwd" }))
.accounts.bySlug(acc.slug);
reopened.wallets.length; // unchanged
reopened.wallets[0].addresses[0].publicKey; // === firstThe full session surface — tryUnlock, resetPassword, setDefaultNetwork, lock, drop — and the disabledSlots retirement mechanism are documented in Account Reference.