From: Chris Duncan Date: Fri, 18 Jul 2025 13:07:40 +0000 (-0700) Subject: Process derived public keys from wallet in single call. X-Git-Tag: v0.10.5~56^2~2 X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=f7a381c4c887bb5901a7e16fe82bd4aad9f39955;p=libnemo.git Process derived public keys from wallet in single call. --- diff --git a/src/lib/account.ts b/src/lib/account.ts index 8ca64d6..08ac884 100644 --- a/src/lib/account.ts +++ b/src/lib/account.ts @@ -86,48 +86,48 @@ export class Account { * Instantiates an Account object from its Nano address. * * @param {string} addresses - Address of the account - * @returns {Account} The instantiated Account object + * @returns {Account} A new Account object */ static import (address: string): Account /** * Instantiates Account objects from their Nano addresses. * * @param {string[]} addresses - Addresses of the accounts - * @returns {Account[]} The instantiated Account objects + * @returns {Account[]} Array of new Account objects */ static import (addresses: string[]): Account[] /** * Instantiates an Account object from its public key. It is unable to sign * blocks or messages since it has no private key. * - * @param {string} publicKey - Public key of the account - * @returns {Account} The instantiated Account object + * @param {Key} publicKey - Public key of the account + * @returns {Account} A new Account object */ - static import (publicKey: string): Account + static import (publicKey: Key): Account /** - * Instantiates an Account object from its public key. It is unable to sign - * blocks or messages since it has no private key. + * Instantiates Account objects from their public keys. They are unable to sign + * blocks or messages since they have no private key. * - * @param {Uint8Array} publicKey - Public key of the account - * @returns {Account} The instantiated Account object + * @param {Key[]} publicKeys - Public keys of the accounts + * @returns {Account[]} Array of new Account objects */ - static import (publicKey: Uint8Array): Account + static import (publicKeys: Key[]): Account[] /** - * Instantiates Account objects from their public keys. They are unable to sign - * blocks or messages since they have no private key. + * Instantiates an Account object from its public key. It is unable to sign + * blocks or messages since it has no private key. * - * @param {string[]} publicKeys - Public keys of the accounts - * @returns {Account[]} The instantiated Account objects + * @param {KeyPair} keypair - Index and keys of the account + * @returns {Account} A new Account object */ - static import (publicKeys: string[]): Account[] + static import (keypair: KeyPair): Account /** * Instantiates Account objects from their public keys. They are unable to sign * blocks or messages since they have no private key. * - * @param {Uint8Array[]} publicKeys - Public keys of the accounts - * @returns {Account[]} The instantiated Account objects + * @param {KeyPair[]} keypairs - Indexes and keys of the accounts + * @returns {Account[]} Array of new Account objects */ - static import (publicKeys: Uint8Array[]): Account[] + static import (keypairs: KeyPair[]): Account[] /** * Instantiates an Account object from its private key which is then encrypted * and stored in IndexedDB. The corresponding public key will automatically be @@ -135,7 +135,7 @@ export class Account { * * @param {KeyPair} keypair - Index and keys of the account * @param {Key} password - Used to encrypt the private key - * @returns {Account} A new Account object + * @returns {Promise} Promise for a new Account object */ static async import (keypair: KeyPair, password: Key): Promise /** @@ -145,7 +145,7 @@ export class Account { * * @param {KeyPair[]} keypairs - Indexes and keys of the accounts * @param {Key} password - Used to encrypt the private keys - * @returns {Account[]} The instantiated Account objects + * @returns {Promise} Promise for array of new Account objects */ static async import (keypairs: KeyPair[], password: Key): Promise static import (input: Key | Key[] | KeyPair | KeyPair[], password?: Key): Account | Account[] | Promise { @@ -383,16 +383,17 @@ export class Account { * Instantiates Account objects from public data, each specifying either its * public key or its Nano address. * - * @param {(string[]|Uint8Array[])} input - Public keys or addresses of the accounts + * @param {Key[]} input - Public keys or addresses of the accounts * @returns {Account[]} The instantiated Account objects */ - static #fromPublic (input: KeyPair[] | unknown): Account[] { - if (!this.#isKeys(input)) { + static #fromPublic (input: Key[] | KeyPair[] | unknown): Account[] { + if (!this.#isKeys(input) && !this.#isKeyPairs(input)) { throw new TypeError('Invalid public input for Account') } const accounts: Account[] = [] let address: string let publicKey: Uint8Array + let index for (let i of input) { let keyError, addressError try { @@ -412,16 +413,23 @@ export class Account { throw new TypeError('Failed to import Account from public data', { cause: { keyError, addressError } }) } } + if (this.#isKeyPair(i)) { + index = i.index ?? undefined + } this.#isInternal = true - accounts.push(new this(address, publicKey)) + accounts.push(new this(address, publicKey, index)) } return accounts } + static #isKey (input: unknown): input is Key { + return typeof input === 'string' || (input instanceof Uint8Array && 'buffer' in input) + } + static #isKeys (input: unknown): input is Key[] { if (Array.isArray(input)) { for (const i of input) { - if (typeof i !== 'string' && !(i instanceof Uint8Array && 'buffer' in i)) { + if (!this.#isKey(i)) { return false } } @@ -429,19 +437,31 @@ export class Account { return true } + static #isKeyPair (input: unknown): input is KeyPair { + if (typeof input === 'object') { + const obj = input as { [key: string]: unknown } + if ('index' in obj && typeof obj.index === 'number') { + return true + } + if ('privateKey' in obj && this.#isKey(obj.privateKey)) { + return true + } + if ('publicKey' in obj && this.#isKey(obj.privateKey)) { + return true + } + } + return false + } + static #isKeyPairs (input: unknown): input is KeyPair[] { if (Array.isArray(input)) { for (const i of input) { - if (typeof i !== 'object') { + if (!this.#isKeyPair(i)) { return false } - const obj = i as { [key: string]: unknown } - if ('index' in obj || 'privateKey' in obj || 'publicKey' in obj) { - return true - } } } - return false + return true } /** diff --git a/src/lib/wallets/wallet.ts b/src/lib/wallets/wallet.ts index fa46e43..28c2823 100644 --- a/src/lib/wallets/wallet.ts +++ b/src/lib/wallets/wallet.ts @@ -102,7 +102,8 @@ export abstract class Wallet { } if (indexes.length > 0) { const keypairs = await this.ckd(indexes) - const privateKeys = [] + const privateKeys: KeyPair[] = [] + const publicKeys: KeyPair[] = [] for (const keypair of keypairs) { const { index, privateKey, publicKey } = keypair if (index == null) { @@ -110,15 +111,14 @@ export abstract class Wallet { } if (privateKey != null) { privateKeys.push(keypair) - } else if (typeof publicKey === 'string') { - output[index] = Account.import(publicKey) - } else if (publicKey instanceof Uint8Array) { - output[index] = Account.import(publicKey) + } else if (publicKey != null) { + publicKeys.push(keypair) } - this.#accounts[index] = output[index] } const privateAccounts = await Account.import(privateKeys, this.seed) - for (const a of privateAccounts) { + const publicAccounts = Account.import(publicKeys) + const accounts = [...privateAccounts, ...publicAccounts] + for (const a of accounts) { if (a.index == null) { throw new RangeError('Index missing for Account') }