Accounts: HD vs PK

The two account kinds — HD (one BIP-39 mnemonic, many derivation slots) and PK (individually imported private keys) — and the capability differences between them.

An account is a named, password-protected key holder inside a workspace. Every account is one of two kinds, fixed at creation and exposed as account.organizationType:

  • HD — backed by a single BIP-39 mnemonic. Each derivation slot yields one EVM address and one Solana address from independent BIP-44 paths, so the same mnemonic drives an unbounded number of wallets.
  • PK — backed by individually imported private keys. Each importPrivateKey() call adds one wallet; there is no shared mnemonic.

Accounts are created through ws.accounts.create(...). The kind is inferred from the secret you pass — a valid mnemonic makes an HD account, a recognizable private key makes a PK account — or forced with opts.kind.

Creating an account

create-account.ts
import { Workspace } from "wative-core";

const ws = await Workspace.open({ path: "./my-wallet", password: "wsp-pwd" });

// HD: the secret is a BIP-39 mnemonic
const hd = await ws.accounts.create("Desk", "wsp-pwd", mnemonic);

// PK: the secret is a private key; force the kind to be explicit
const pk = await ws.accounts.create(
  "External Hot Wallet",
  "wsp-pwd",
  "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d",
  undefined,
  { kind: "PK" },
);

Signature

ws.accounts.create(
  displayName: string,
  password: string,
  secret: string,
  defaultNetwork?: NetworkLike,
  opts?: { kind?: AccountOrgType; hasOwnPassword?: boolean },
): Promise<Account>
ParameterTypeNotes
displayNamestring4–64 characters. The on-disk slug (account.slug) is derived from it.
passwordstringThe password the account's secrets are sealed under (see passwords below).
secretstringA BIP-39 mnemonic (HD) or a private key (PK). The kind is inferred from its shape unless opts.kind overrides it.
defaultNetworkNetworkLikeOptional. A network slug, chain id, hex chain id, or Network instance. Defaults to ethereum. See Account Reference.
opts.kindAccountOrgType"HD" or "PK". Forces the kind instead of inferring it from secret.
opts.hasOwnPasswordbooleanDefaults to true. See passwords below.

Capability differences

CapabilityHDPK
Backing secretone BIP-39 mnemonicindividually imported private keys
Wallet 0 at createderived from the mnemonicthe imported secret
deriveWallets(n)yesno — throws UNSUPPORTED_OP
sliceWallets(n)yesno — throws UNSUPPORTED_OP
importPrivateKey()noyes
dumpMnemonic()yesno — throws
setDisabledSlots() / setDisabledAddressNos()yesno — throws UNSUPPORTED_OP
wallets.drop()yes (retires the freed BIP-32 index)yes
Addresses per walletone EVM + one Solana, from independent BIP-44 pathsthe imported key plus its cross-curve sibling

The two kinds share the whole session and password surface — tryUnlock, resetPassword, lock, setDefaultNetwork, rename, drop, filterAddress. Those live in Account Reference.

Per-account vs shared passwords

Each account carries its own encryption password by default (hasOwnPassword: true). You unlock it with tryUnlock(itsPassword).

Pass hasOwnPassword: false to make the account share the workspace password instead. Its secrets are then sealed under the workspace password, so it must be created with that same password, and it unlocks with a no-argument tryUnlock() that falls back to the workspace password.

password-modes.ts
// Own password — unlock with its own credential
const sub = await ws.accounts.create("SubAccount", "sub-pwd", mnemonic, undefined, {
  hasOwnPassword: true,
});
await sub.tryUnlock("sub-pwd");

// Shared password — must be created with the workspace password
const shared = await ws.accounts.create("Shared", "wsp-pwd", mnemonic, undefined, {
  hasOwnPassword: false,
});
await shared.tryUnlock(); // falls back to the workspace password

Password rotation, the hasOwnPassword field, and checkPassword are covered in Account Reference.

Last updated on