Polkadot Apps
    Preparing search index...

    Module @polkadot-apps/keys

    @polkadot-apps/keys

    Hierarchical key derivation and session key management for Polkadot accounts.

    pnpm add @polkadot-apps/keys
    

    Peer dependencies are pulled in automatically via the monorepo workspace:

    • @polkadot-apps/crypto -- symmetric encryption and HKDF
    • @polkadot-apps/address -- SS58 and H160 address encoding
    • @polkadot-apps/storage -- persistence for session keys
    • polkadot-api -- PolkadotSigner type
    import { KeyManager } from "@polkadot-apps/keys";

    // Derive a key manager from a wallet signature
    const km = KeyManager.fromSignature(signature, signerAddress);

    // Derive a symmetric encryption key for a specific context
    const encKey = km.deriveSymmetricKey("document:abc123");

    // Derive a Substrate account
    const account = km.deriveAccount("voting-proxy");
    console.log(account.ss58Address);

    Holds a 32-byte master key in memory and derives child keys via HKDF-SHA256. Does not persist anything -- persistence is the caller's responsibility.

    From a cryptographic signature (most common). Derives the master key via HKDF-SHA256 with IKM=signature, salt=options.salt (default "polkadot-apps-keys-v1"), info=signerAddress.

    import { KeyManager } from "@polkadot-apps/keys";

    const km = KeyManager.fromSignature(signature, signerAddress);

    // With custom salt
    const km2 = KeyManager.fromSignature(signature, signerAddress, {
    salt: "my-app-v2",
    });

    The signature parameter accepts a Uint8Array or a hex string (with or without 0x prefix). It must be at least 32 bytes.

    From a raw 32-byte key (for restoring from storage or testing):

    const km = KeyManager.fromRawKey(masterKeyBytes);
    

    Returns a 32-byte key via HKDF-SHA256 with IKM=masterKey, salt="", info=context.

    const encryptionKey = km.deriveSymmetricKey("document:abc123");
    const signingKey = km.deriveSymmetricKey("hmac:notifications");

    Derives an Sr25519 account for a given context. Internally runs HKDF(masterKey, "", "account:" + context) to produce a 32-byte seed, then derives an Sr25519 keypair at //0.

    const account = km.deriveAccount("voting-proxy");
    console.log(account.ss58Address); // generic prefix 42
    console.log(account.h160Address); // 0x...

    // With Polkadot network prefix
    const polkadotAccount = km.deriveAccount("staking", 0);

    Returns Curve25519 (encryption) and Ed25519 (signing) keypairs derived from the master key.

    import { nacl } from "@polkadot-apps/crypto";

    const kp = km.deriveKeypairs();

    // Encrypt for another party
    const nonce = nacl.randomBytes(24);
    const encrypted = nacl.box(message, nonce, recipientPubKey, kp.encryption.secretKey);

    // Sign a message
    const signed = nacl.sign(message, kp.signing.secretKey);
    const raw = km.exportKey(); // Uint8Array (32 bytes), safe to persist
    

    Manages a BIP39 mnemonic-derived Sr25519 account with automatic persistence via a KvStore.

    import { SessionKeyManager } from "@polkadot-apps/keys";
    import { createKvStore } from "@polkadot-apps/storage";

    const store = await createKvStore({ prefix: "session-key" });
    const skm = new SessionKeyManager({ store });

    // Load existing or create a new session key
    const { mnemonic, account } = await skm.getOrCreate();
    console.log(account.ss58Address);

    Pass a name to isolate different session keys in the same store.

    const main = new SessionKeyManager({ store, name: "main" });
    const burner = new SessionKeyManager({ store, name: "burner" });

    const mainKey = await main.getOrCreate();
    const burnerKey = await burner.getOrCreate();
    const info = skm.fromMnemonic("abandon abandon abandon ...");
    console.log(info.account.ss58Address);
    await skm.clear(); // removes mnemonic from the store
    

    Standalone function to derive an account from a BIP39 mnemonic.

    import { seedToAccount } from "@polkadot-apps/keys";

    const account = seedToAccount(mnemonic);

    // With custom derivation path, SS58 prefix, and key type
    const edAccount = seedToAccount(mnemonic, "//1", 0, "ed25519");
    Method Signature Returns
    KeyManager.fromSignature (signature: Uint8Array | string, signerAddress: string, options?: { salt?: string }) KeyManager
    KeyManager.fromRawKey (masterKey: Uint8Array) KeyManager
    km.deriveSymmetricKey (context: string) Uint8Array (32 bytes)
    km.deriveAccount (context: string, ss58Prefix?: number) DerivedAccount
    km.deriveKeypairs () DerivedKeypairs
    km.exportKey () Uint8Array (32 bytes)
    Method Signature Returns
    constructor (options: { store: KvStore, name?: string }) SessionKeyManager
    skm.create () Promise<SessionKeyInfo>
    skm.get () Promise<SessionKeyInfo | null>
    skm.getOrCreate () Promise<SessionKeyInfo>
    skm.fromMnemonic (mnemonic: string) SessionKeyInfo
    skm.clear () Promise<void>
    Function Signature Returns
    seedToAccount (mnemonic: string, derivationPath?: string, ss58Prefix?: number, keyType?: "sr25519" | "ed25519") DerivedAccount

    Default values: derivationPath = "//0", ss58Prefix = 42, keyType = "sr25519".

    interface DerivedAccount {
    publicKey: Uint8Array;
    ss58Address: SS58String;
    h160Address: `0x${string}`;
    signer: PolkadotSigner;
    }

    interface DerivedKeypairs {
    encryption: { publicKey: Uint8Array; secretKey: Uint8Array };
    signing: { publicKey: Uint8Array; secretKey: Uint8Array };
    }

    interface SessionKeyInfo {
    mnemonic: string;
    account: DerivedAccount;
    }

    Apache-2.0

    Classes

    KeyManager
    SessionKeyManager

    Interfaces

    DerivedAccount
    DerivedKeypairs
    SessionKeyInfo

    Functions

    seedToAccount