From: Chris Duncan Date: Thu, 16 Oct 2025 02:26:21 +0000 (-0700) Subject: Refactor account load to work from single inputs. X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=234079fccd83e93791c82382acafd3d74c8a8aa6;p=libnemo.git Refactor account load to work from single inputs. --- diff --git a/src/lib/account/index.ts b/src/lib/account/index.ts index ac15c20..6b6d88a 100644 --- a/src/lib/account/index.ts +++ b/src/lib/account/index.ts @@ -2,9 +2,7 @@ //! SPDX-License-Identifier: GPL-3.0-or-later import { Block } from '../block' -import { ACCOUNT_KEY_BYTE_LENGTH, ACCOUNT_KEY_HEX_LENGTH } from '../constants' -import { bytes, hex } from '../convert' -import { NanoNaCl } from '../crypto' +import { bytes } from '../convert' import { Rpc } from '../rpc' import { Address } from './address' import { _load } from './load' @@ -246,7 +244,15 @@ export class Account { * @returns {(Account | Account[] | Promise)} Promise for array of new Account objects */ static load (input: string | Uint8Array | KeyPair | (string | Uint8Array | KeyPair)[], type?: 'private'): Account | Account[] | Promise { - return _load(input, type) + const isInputArray = Array.isArray(input) + const inputs = isInputArray ? input : [input] + this.#isInternal = true + const accounts = inputs.map((input) => { + const { address, publicKey, index } = _load(input, type) + return new this(address, publicKey, index) + }) + this.#isInternal = false + return isInputArray ? accounts : accounts[0] } /** diff --git a/src/lib/account/load.ts b/src/lib/account/load.ts index b897bc9..1835f4d 100644 --- a/src/lib/account/load.ts +++ b/src/lib/account/load.ts @@ -2,19 +2,16 @@ //! SPDX-License-Identifier: GPL-3.0-or-later import { Account, KeyPair } from '../account' -import { Address } from './address' import { ACCOUNT_KEY_BYTE_LENGTH, ACCOUNT_KEY_HEX_LENGTH } from '../constants' import { hex } from '../convert' import { NanoNaCl } from '../crypto' +import { Address } from './address' -export function _load (input: string | Uint8Array | KeyPair | (string | Uint8Array | KeyPair)[], type?: 'private'): Account | Account[] | Promise { - const isInputArray = Array.isArray(input) - const inputs = isInputArray ? input : [input] - if (isKeyPairs(inputs) && type === 'private') { - return fromPrivate(inputs) - .then(r => isInputArray ? r : r[0]) +export function _load (input: string | Uint8Array | KeyPair, type?: 'private'): { address: Address, publicKey: Uint8Array, index?: number } { + if (isKeyPair(input) && type === 'private') { + return fromPrivate(input) } else { - return isInputArray ? fromPublic(inputs) : fromPublic(inputs)[0] + return fromPublic(input) } } @@ -25,31 +22,24 @@ export function _load (input: string | Uint8Array | KeyPair | (stri * @param {KeyPair} keypairs - Indexes and keys of the accounts * @returns {Promise} Promise for new Account objects */ -async function fromPrivate (keypairs: KeyPair[]): Promise { +function fromPrivate (keypair: KeyPair) { try { - const accounts: Account[] = [] - for (let keypair of keypairs) { - let { index, privateKey } = keypair - if (index == null) { - throw new RangeError('Index missing for Account') - } - if (typeof privateKey === 'string' && RegExp(`^[A-F0-9]{${ACCOUNT_KEY_HEX_LENGTH}}$`, 'i').test(privateKey)) { - privateKey = hex.toBytes(privateKey) - } - if (!(privateKey instanceof Uint8Array) || privateKey.every(v => v === 0)) { - throw new TypeError('Invalid private key') - } - if (privateKey.byteLength !== ACCOUNT_KEY_BYTE_LENGTH) { - throw new TypeError(`Private key must be ${ACCOUNT_KEY_BYTE_LENGTH} bytes`) - } - const publicKey = await NanoNaCl.convert(privateKey) - const address = new Address(publicKey) - this.#isInternal = true - const account = new this(address, publicKey, index) - this.#isInternal = false - accounts.push(account) + let { index, privateKey } = keypair + if (index == null) { + throw new RangeError('Index missing for Account') + } + if (typeof privateKey === 'string' && RegExp(`^[A-F0-9]{${ACCOUNT_KEY_HEX_LENGTH}}$`, 'i').test(privateKey)) { + privateKey = hex.toBytes(privateKey) + } + if (!(privateKey instanceof Uint8Array) || privateKey.every(v => v === 0)) { + throw new TypeError('Invalid private key') + } + if (privateKey.byteLength !== ACCOUNT_KEY_BYTE_LENGTH) { + throw new TypeError(`Private key must be ${ACCOUNT_KEY_BYTE_LENGTH} bytes`) } - return accounts + const publicKey = NanoNaCl.convert(privateKey) + const address = new Address(publicKey) + return { address, publicKey, index } } catch (err) { throw new Error('Failed to import Accounts from private keys', { cause: err }) } @@ -62,38 +52,29 @@ async function fromPrivate (keypairs: KeyPair[]): Promise { * @param {(string | Uint8Array|KeyPair)[]} input - Public keys or addresses of the accounts * @returns {Account[]} The instantiated Account objects */ -function fromPublic (input: (string | Uint8Array | KeyPair)[] | unknown): Account[] { +function fromPublic (input: string | Uint8Array | KeyPair | unknown) { try { - const keypairs = isKeyPairs(input) + const keypair = isKeyPair(input) ? input - : isKeys(input) - ? input.map(i => { return { publicKey: i } as KeyPair }) - : [] - if (keypairs.length === 0) { + : isKey(input) + ? { publicKey: input } as KeyPair + : undefined + if (keypair == null) { throw new TypeError('Invalid public input for Account') } - - const accounts: Account[] = [] - for (let keypair of keypairs) { - if (keypair.publicKey == null) { - throw new TypeError('Account address or public key is required', { cause: keypair.publicKey }) - } - const { index } = keypair - const address = new Address(keypair.publicKey) - const publicKey = address.toPublicKey() - this.#isInternal = true - const account = new this(address, publicKey, index) - this.#isInternal = false - accounts.push(account) + if (keypair.publicKey == null) { + throw new TypeError('Account address or public key is required', { cause: keypair.publicKey }) } - return accounts + const { index } = keypair + const address = new Address(keypair.publicKey) + const publicKey = address.toPublicKey() + return { address, publicKey, index } } catch (err) { console.error(err) throw new TypeError('Failed to import Account from public data', { cause: { err } }) } } - function isKeyPair (input: unknown): input is KeyPair { if (typeof input === 'object') { const obj = input as { [key: string]: unknown } @@ -110,30 +91,6 @@ function isKeyPair (input: unknown): input is KeyPair { return false } - -function isKeyPairs (input: unknown): input is KeyPair[] { - if (Array.isArray(input)) { - for (const i of input) { - if (!isKeyPair(i)) { - return false - } - } - } - return true -} - - function isKey (input: unknown): input is string | Uint8Array { return typeof input === 'string' || (input instanceof Uint8Array && 'buffer' in input) } - -function isKeys (input: unknown): input is (string | Uint8Array)[] { - if (Array.isArray(input)) { - for (const i of input) { - if (!isKey(i)) { - return false - } - } - } - return true -}