]> git.codecow.com Git - libnemo.git/commitdiff
Start migrating account load functions.
authorChris Duncan <chris@zoso.dev>
Tue, 14 Oct 2025 18:41:16 +0000 (11:41 -0700)
committerChris Duncan <chris@zoso.dev>
Tue, 14 Oct 2025 18:41:16 +0000 (11:41 -0700)
src/lib/account/index.ts
src/lib/account/load.ts [new file with mode: 0644]

index 7c780a962e0655540c521a1f003491d6080b360e..ac15c20e6be35921d69968f4a6ce8a4db07a925a 100644 (file)
@@ -7,10 +7,11 @@ import { bytes, hex } from '../convert'
 import { NanoNaCl } from '../crypto'\r
 import { Rpc } from '../rpc'\r
 import { Address } from './address'\r
+import { _load } from './load'\r
 import { _refresh } from './refresh'\r
 import { _validate } from './validate'\r
 \r
-type KeyPair = {\r
+export type KeyPair = {\r
        index?: number\r
        privateKey?: string | Uint8Array<ArrayBuffer>\r
        publicKey?: string | Uint8Array<ArrayBuffer>\r
@@ -245,14 +246,7 @@ export class Account {
        * @returns {(Account | Account[] | Promise<Account | Account[]>)} Promise for array of new Account objects\r
        */\r
        static load (input: string | Uint8Array<ArrayBuffer> | KeyPair | (string | Uint8Array<ArrayBuffer> | KeyPair)[], type?: 'private'): Account | Account[] | Promise<Account | Account[]> {\r
-               const isInputArray = Array.isArray(input)\r
-               const inputs = isInputArray ? input : [input]\r
-               if (this.#isKeyPairs(inputs) && type === 'private') {\r
-                       return this.#fromPrivate(inputs)\r
-                               .then(r => isInputArray ? r : r[0])\r
-               } else {\r
-                       return isInputArray ? this.#fromPublic(inputs) : this.#fromPublic(inputs)[0]\r
-               }\r
+               return _load(input, type)\r
        }\r
 \r
        /**\r
@@ -277,121 +271,4 @@ export class Account {
        static validate (address: string): asserts address is string {\r
                return _validate(address)\r
        }\r
-\r
-       /**\r
-       * Instantiates an Account object from its private key which is used to derive\r
-       * the corresponding public key and then discarded.\r
-       *\r
-       * @param {KeyPair} keypairs - Indexes and keys of the accounts\r
-       * @returns {Promise<Account[]>} Promise for new Account objects\r
-       */\r
-       static async #fromPrivate (keypairs: KeyPair[]): Promise<Account[]> {\r
-               try {\r
-                       const accounts: Account[] = []\r
-                       for (let keypair of keypairs) {\r
-                               let { index, privateKey } = keypair\r
-                               if (index == null) {\r
-                                       throw new RangeError('Index missing for Account')\r
-                               }\r
-                               if (typeof privateKey === 'string' && RegExp(`^[A-F0-9]{${ACCOUNT_KEY_HEX_LENGTH}}$`, 'i').test(privateKey)) {\r
-                                       privateKey = hex.toBytes(privateKey)\r
-                               }\r
-                               if (!(privateKey instanceof Uint8Array) || privateKey.every(v => v === 0)) {\r
-                                       throw new TypeError('Invalid private key')\r
-                               }\r
-                               if (privateKey.byteLength !== ACCOUNT_KEY_BYTE_LENGTH) {\r
-                                       throw new TypeError(`Private key must be ${ACCOUNT_KEY_BYTE_LENGTH} bytes`)\r
-                               }\r
-                               const publicKey = await NanoNaCl.convert(privateKey)\r
-                               const address = new Address(publicKey)\r
-                               this.#isInternal = true\r
-                               const account = new this(address, publicKey, index)\r
-                               this.#isInternal = false\r
-                               accounts.push(account)\r
-                       }\r
-                       return accounts\r
-               } catch (err) {\r
-                       throw new Error('Failed to import Accounts from private keys', { cause: err })\r
-               }\r
-       }\r
-\r
-       /**\r
-       * Instantiates Account objects from public data, each specifying either its\r
-       * public key or its Nano address.\r
-       *\r
-       * @param {(string | Uint8Array<ArrayBuffer>|KeyPair)[]} input - Public keys or addresses of the accounts\r
-       * @returns {Account[]} The instantiated Account objects\r
-       */\r
-       static #fromPublic (input: (string | Uint8Array<ArrayBuffer> | KeyPair)[] | unknown): Account[] {\r
-               try {\r
-                       const keypairs = this.#isKeyPairs(input)\r
-                               ? input\r
-                               : this.#isKeys(input)\r
-                                       ? input.map(i => { return { publicKey: i } as KeyPair })\r
-                                       : []\r
-                       if (keypairs.length === 0) {\r
-                               throw new TypeError('Invalid public input for Account')\r
-                       }\r
-\r
-                       const accounts: Account[] = []\r
-                       for (let keypair of keypairs) {\r
-                               if (keypair.publicKey == null) {\r
-                                       throw new TypeError('Account address or public key is required', { cause: keypair.publicKey })\r
-                               }\r
-                               const { index } = keypair\r
-                               const address = new Address(keypair.publicKey)\r
-                               const publicKey = address.toPublicKey()\r
-                               this.#isInternal = true\r
-                               const account = new this(address, publicKey, index)\r
-                               this.#isInternal = false\r
-                               accounts.push(account)\r
-                       }\r
-                       return accounts\r
-               } catch (err) {\r
-                       console.error(err)\r
-                       throw new TypeError('Failed to import Account from public data', { cause: { err } })\r
-               }\r
-       }\r
-\r
-       static #isKey (input: unknown): input is string | Uint8Array<ArrayBuffer> {\r
-               return typeof input === 'string' || (input instanceof Uint8Array && 'buffer' in input)\r
-       }\r
-\r
-       static #isKeys (input: unknown): input is (string | Uint8Array<ArrayBuffer>)[] {\r
-               if (Array.isArray(input)) {\r
-                       for (const i of input) {\r
-                               if (!this.#isKey(i)) {\r
-                                       return false\r
-                               }\r
-                       }\r
-               }\r
-               return true\r
-       }\r
-\r
-       static #isKeyPair (input: unknown): input is KeyPair {\r
-               if (typeof input === 'object') {\r
-                       const obj = input as { [key: string]: unknown }\r
-                       if ('index' in obj && typeof obj.index === 'number') {\r
-                               return true\r
-                       }\r
-                       if ('publicKey' in obj && this.#isKey(obj.publicKey)) {\r
-                               return true\r
-                       }\r
-                       if ('privateKey' in obj && this.#isKey(obj.privateKey)) {\r
-                               return true\r
-                       }\r
-               }\r
-               return false\r
-       }\r
-\r
-       static #isKeyPairs (input: unknown): input is KeyPair[] {\r
-               if (Array.isArray(input)) {\r
-                       for (const i of input) {\r
-                               if (!this.#isKeyPair(i)) {\r
-                                       return false\r
-                               }\r
-                       }\r
-               }\r
-               return true\r
-       }\r
 }\r
diff --git a/src/lib/account/load.ts b/src/lib/account/load.ts
new file mode 100644 (file)
index 0000000..b897bc9
--- /dev/null
@@ -0,0 +1,139 @@
+//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
+//! 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'
+
+export function _load (input: string | Uint8Array<ArrayBuffer> | KeyPair | (string | Uint8Array<ArrayBuffer> | KeyPair)[], type?: 'private'): Account | Account[] | Promise<Account | Account[]> {
+       const isInputArray = Array.isArray(input)
+       const inputs = isInputArray ? input : [input]
+       if (isKeyPairs(inputs) && type === 'private') {
+               return fromPrivate(inputs)
+                       .then(r => isInputArray ? r : r[0])
+       } else {
+               return isInputArray ? fromPublic(inputs) : fromPublic(inputs)[0]
+       }
+}
+
+/**
+* Instantiates an Account object from its private key which is used to derive
+* the corresponding public key and then discarded.
+*
+* @param {KeyPair} keypairs - Indexes and keys of the accounts
+* @returns {Promise<Account[]>} Promise for new Account objects
+*/
+async function fromPrivate (keypairs: KeyPair[]): Promise<Account[]> {
+       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)
+               }
+               return accounts
+       } catch (err) {
+               throw new Error('Failed to import Accounts from private keys', { cause: err })
+       }
+}
+
+/**
+* Instantiates Account objects from public data, each specifying either its
+* public key or its Nano address.
+*
+* @param {(string | Uint8Array<ArrayBuffer>|KeyPair)[]} input - Public keys or addresses of the accounts
+* @returns {Account[]} The instantiated Account objects
+*/
+function fromPublic (input: (string | Uint8Array<ArrayBuffer> | KeyPair)[] | unknown): Account[] {
+       try {
+               const keypairs = isKeyPairs(input)
+                       ? input
+                       : isKeys(input)
+                               ? input.map(i => { return { publicKey: i } as KeyPair })
+                               : []
+               if (keypairs.length === 0) {
+                       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)
+               }
+               return accounts
+       } 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 }
+               if ('index' in obj && typeof obj.index === 'number') {
+                       return true
+               }
+               if ('publicKey' in obj && isKey(obj.publicKey)) {
+                       return true
+               }
+               if ('privateKey' in obj && isKey(obj.privateKey)) {
+                       return true
+               }
+       }
+       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<ArrayBuffer> {
+       return typeof input === 'string' || (input instanceof Uint8Array && 'buffer' in input)
+}
+
+function isKeys (input: unknown): input is (string | Uint8Array<ArrayBuffer>)[] {
+       if (Array.isArray(input)) {
+               for (const i of input) {
+                       if (!isKey(i)) {
+                               return false
+                       }
+               }
+       }
+       return true
+}