AccountsPK Accounts

PK Accounts

Imported-key accounts — importPrivateKey() with the vm inferred from the key format (EVM hex, Solana base58, solana-keygen JSON), one secret controlling both chains, and duplicate-import rejection.

A PK account holds individually imported private keys. There is no shared mnemonic — each key becomes its own wallet. A PK account is created by passing a private key as the secret (and, to be explicit, opts.kind: "PK"); that key is auto-imported as wallet 0.

Create from a private key

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

const EVM_PK = "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d";

const ws = await Workspace.open({ path: "./my-wallet", password: "wsp-pwd" });
const acc = await ws.accounts.create("External Hot Wallet", "wsp-pwd", EVM_PK, undefined, {
  kind: "PK",
});

acc.organizationType;              // "PK"
acc.wallets.length;                // 1 — the imported key as wallet 0
acc.wallets[0].addresses[0].vm;    // "evm" — the imported key's own chain
acc.wallets[0].addresses[1].vm;    // "svm" — the cross-curve sibling

Importing more keys

importPrivateKey(pk, vm?) adds one wallet per call. The imported key's own chain is always addresses[0]; the cross-curve sibling, when it exists, is appended after it.

pk-import.ts
const SVM_PK =
  "xtGWcHvQsr5ue8zG2F5fm31bW8vyn597Y92gUWaZZg3S1Z6FeJMATL8KU3xJMGbLfALnokcct9y5wYtCRrwNXZW";

const wallet = await acc.importPrivateKey(SVM_PK, "svm");
acc.wallets.length;         // 2
wallet.addresses[0].vm;     // "svm"
wallet.addresses[1].vm;     // "evm"

Signature

importPrivateKey(pk: string, vm?: ChainVM): Promise<Wallet>

vm is optional. When omitted, the chain is read off the key's own encoding — the two formats are disjoint. Pass it explicitly to override the inference, or to get a clear rejection when you already know what the key should be.

Accepted key formats

FormatExample shapeInferred vm
EVM hex64 hex chars, 0x prefix optionalevm
Solana base5864-byte base58 stringsvm
solana-keygen JSONJSON.stringify([...64 byte values])svm
pk-formats.ts
// EVM hex (0x optional)
const evm = await acc.importPrivateKey(
  "0x6cbed15c793ce57650b9877cf6fa156fbef513c4e6134f022a85b1ffdd59b2a1",
);
evm.addresses[0].vm; // "evm"

// Solana base58
const svm = await acc.importPrivateKey(SVM_PK_2);
svm.addresses[0].vm; // "svm"

// solana-keygen JSON byte array
const fromKeygen = await acc.importPrivateKey(JSON.stringify(svmKeygenBytes));
fromKeygen.addresses[0].vm; // "svm"

One secret, both chains

A single imported key produces addresses on both chains. A secp256k1 private key is 32 bytes and an ed25519 seed is 32 arbitrary bytes, so the same secret material seeds the other curve, and the wallet gets a sibling address on the opposite chain.

The EVM → Solana direction always succeeds. The Solana → EVM direction can, astronomically rarely, fail (secp256k1 only accepts a scalar in range); when the sibling cannot exist the import still succeeds with a single address rather than erroring.

Rejections

SituationError code
Secret is not a recognizable private keyINVALID_PRIVATE_KEY
An out-of-range key (e.g. all-zero EVM key)INVALID_PRIVATE_KEY
Importing an identity the account already holdsPARAMETER_ERROR
Dropping the account's last walletUNSUPPORTED_OP
pk-rejections.ts
// Not a key
await acc.importPrivateKey("definitely-not-a-key");
// → WativeError { code: "INVALID_PRIVATE_KEY" }

// Out-of-range EVM key
await acc.importPrivateKey("0x" + "0".repeat(64), "evm");
// → WativeError { code: "INVALID_PRIVATE_KEY" }

// Duplicate identity (already held by this account)
await acc.importPrivateKey(EVM_PK, "evm");
// → WativeError { code: "PARAMETER_ERROR" }

Dropping wallets

Remove a wallet with acc.wallets.drop(wallet). An account must always keep at least one wallet, so dropping the last one throws UNSUPPORTED_OP.

pk-drop.ts
await acc.importPrivateKey(SVM_PK, "svm");

await acc.wallets.drop(acc.wallets[1]);
acc.wallets.length; // 1

await acc.wallets.drop(acc.wallets[0]);
// → WativeError { code: "UNSUPPORTED_OP" }  (last wallet)

For the full account surface — sessions, passwords, default network — see Account Reference.

Last updated on