Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | 2x 44x 44x 32x 32x 32x 12x 1x 11x 11x 40x 1x 39x 39x 39x 39x 43x 29x 8x 9x 5x 2x 3x | import {
english,
generateMnemonic,
mnemonicToAccount,
privateKeyToAccount,
generatePrivateKey,
} from 'viem/accounts';
import type { HDAccount, LocalAccount } from 'viem/accounts';
import type { EncryptedMnemonicData } from './mnemonic-crypto.ts';
import type { Address } from '../types.ts';
const harden = globalThis.harden ?? (<T>(value: T): T => value);
/**
* Options for initializing a keyring.
*
* Throwaway keyrings are intentionally ephemeral: each call to `makeKeyring`
* generates a fresh private key, so the key does not survive a vat restart.
* Baggage only persists `{ type: 'throwaway' }`; callers that need key
* stability across restarts must use `type: 'srp'`.
*/
export type KeyringInitOptions =
| { type: 'srp'; mnemonic: string; addressIndex?: number }
| { type: 'throwaway' };
/**
* Encrypted keyring init data stored in baggage when a password is used.
*/
export type EncryptedKeyringInit = EncryptedMnemonicData & {
type: 'srp';
/** BIP-44 address index used when the keyring was first initialized. */
addressIndex?: number;
};
/**
* The shape of keyring init data stored in baggage — either plaintext or encrypted.
*/
export type StoredKeyringInit = KeyringInitOptions | EncryptedKeyringInit;
/**
* A keyring manages private keys and signing. Keys never leave this module.
*/
export type Keyring = {
getAccounts: () => Address[];
deriveAccount: (index: number) => Address;
getAccount: (address: Address) => LocalAccount | undefined;
hasKeys: () => boolean;
getMnemonic: () => string | undefined;
};
/**
* Create a new keyring from an SRP mnemonic or a throwaway key.
*
* @param options - Initialization options.
* @returns The keyring instance.
*/
export function makeKeyring(options: KeyringInitOptions): Keyring {
const accounts = new Map<Address, LocalAccount>();
let mnemonic: string | undefined;
if (options.type === 'srp') {
mnemonic = options.mnemonic;
const startIndex = options.addressIndex ?? 0;
deriveAccountInternal(startIndex);
} else {
// eslint-disable-next-line n/no-unsupported-features/node-builtins
if (!globalThis.crypto?.getRandomValues) {
throw new Error(
'Throwaway keyring requires the "crypto" global endowment; ' +
"add 'crypto' to this vat's globals in cluster-config.ts",
);
}
const account = privateKeyToAccount(generatePrivateKey());
accounts.set(account.address.toLowerCase() as Address, account);
}
/**
* Derive an account at the given BIP-44 index.
*
* @param index - The address index to derive.
* @returns The derived account address.
*/
function deriveAccountInternal(index: number): Address {
if (!mnemonic) {
throw new Error('Cannot derive accounts from a throwaway keyring');
}
const account: HDAccount = mnemonicToAccount(mnemonic, {
addressIndex: index,
});
const address = account.address.toLowerCase() as Address;
accounts.set(address, account);
return address;
}
return harden({
getAccounts(): Address[] {
return [...accounts.keys()];
},
deriveAccount(index: number): Address {
return deriveAccountInternal(index);
},
getAccount(address: Address): LocalAccount | undefined {
return accounts.get(address.toLowerCase() as Address);
},
hasKeys(): boolean {
return accounts.size > 0;
},
getMnemonic(): string | undefined {
return mnemonic;
},
});
}
/**
* Generate a new random BIP-39 mnemonic phrase (12 words).
*
* @returns The mnemonic string.
*/
export function generateMnemonicPhrase(): string {
return generateMnemonic(english);
}
|