]> git.codecow.com Git - libnemo.git/commitdiff
Replace async-await with Promise chains.
authorChris Duncan <chris@zoso.dev>
Sat, 30 Aug 2025 04:03:50 +0000 (21:03 -0700)
committerChris Duncan <chris@zoso.dev>
Sat, 30 Aug 2025 04:03:50 +0000 (21:03 -0700)
src/lib/crypto/bip44.ts

index 59210ba4d994a251a8115b5c10cbcd74276b5d3c..adcdfaa26533c45098278e9580ceec8bb736a546 100644 (file)
@@ -19,43 +19,62 @@ export class Bip44 {
        * @param {number} account - Account number between 0 and 2^31-1
        * @returns {Promise<ArrayBuffer>} Private child key for the account
        */
-       static async ckd (seed: ArrayBuffer, coin: number, account: number, chain?: number, address?: number): Promise<ArrayBuffer> {
+       static ckd (seed: ArrayBuffer, coin: number, account: number, chain?: number, address?: number): Promise<ArrayBuffer | undefined> {
                if (seed.byteLength < 16 || seed.byteLength > 64) {
                        throw new RangeError(`Invalid seed length`)
                }
                if (!Number.isSafeInteger(account) || account < 0 || account > 0x7fffffff) {
                        throw new RangeError(`Invalid child key index 0x${account.toString(16)}`)
                }
-               const masterKey = await this.slip10(SLIP10_ED25519, seed)
-               const purposeKey = await this.CKDpriv(masterKey, BIP44_PURPOSE + HARDENED_OFFSET)
-               const coinKey = await this.CKDpriv(purposeKey, coin + HARDENED_OFFSET)
-               const accountKey = await this.CKDpriv(coinKey, account + HARDENED_OFFSET)
-               if (chain == null) return accountKey.privateKey
-               const chainKey = await this.CKDpriv(accountKey, chain + HARDENED_OFFSET)
-               if (address == null) return chainKey.privateKey
-               const addressKey = await this.CKDpriv(chainKey, address + HARDENED_OFFSET)
-               return addressKey.privateKey
+               return this.slip10(SLIP10_ED25519, seed)
+                       .then(masterKey => {
+                               return this.CKDpriv(masterKey, BIP44_PURPOSE + HARDENED_OFFSET)
+                                       .then(purposeKey => {
+                                               return this.CKDpriv(purposeKey, coin + HARDENED_OFFSET)
+                                                       .then(coinKey => {
+                                                               return this.CKDpriv(coinKey, account + HARDENED_OFFSET)
+                                                                       .then(accountKey => {
+                                                                               if (chain == null) return accountKey.privateKey
+                                                                               this.CKDpriv(accountKey, chain + HARDENED_OFFSET)
+                                                                                       .then(chainKey => {
+                                                                                               if (address == null) return chainKey.privateKey
+                                                                                               this.CKDpriv(chainKey, address + HARDENED_OFFSET)
+                                                                                                       .then(addressKey => {
+                                                                                                               return addressKey.privateKey
+                                                                                                       })
+                                                                                       })
+                                                                       })
+                                                       })
+                                       })
+                       })
+                       .catch(err => {
+                               throw new Error('Failed to derive BIP-44 account', { cause: err })
+                       })
        }
 
-       static async slip10 (curve: string, S: ArrayBuffer): Promise<ExtendedKey> {
+       static slip10 (curve: string, S: ArrayBuffer): Promise<ExtendedKey> {
                const key = new Uint8Array(new TextEncoder().encode(curve))
                const data = new Uint8Array(S)
-               const I = await this.hmac(key, data)
-               const IL = I.buffer.slice(0, I.length / 2)
-               const IR = I.buffer.slice(I.length / 2)
-               return ({ privateKey: IL, chainCode: IR })
+               return this.hmac(key, data)
+                       .then(I => {
+                               const IL = I.slice(0, I.byteLength / 2)
+                               const IR = I.slice(I.byteLength / 2)
+                               return ({ privateKey: IL, chainCode: IR })
+                       })
        }
 
-       static async CKDpriv ({ privateKey, chainCode }: ExtendedKey, index: number): Promise<ExtendedKey> {
+       static CKDpriv ({ privateKey, chainCode }: ExtendedKey, index: number): Promise<ExtendedKey> {
                const key = new Uint8Array(chainCode)
                const data = new Uint8Array(37)
                data.set([0])
                data.set(this.ser256(privateKey), 1)
                data.set(this.ser32(index), 33)
-               const I = await this.hmac(key, data)
-               const IL = I.buffer.slice(0, I.length / 2)
-               const IR = I.buffer.slice(I.length / 2)
-               return ({ privateKey: IL, chainCode: IR })
+               return this.hmac(key, data)
+                       .then(I => {
+                               const IL = I.slice(0, I.byteLength / 2)
+                               const IR = I.slice(I.byteLength / 2)
+                               return ({ privateKey: IL, chainCode: IR })
+                       })
        }
 
        static ser32 (integer: number): Uint8Array<ArrayBuffer> {
@@ -80,9 +99,13 @@ export class Bip44 {
                return new Uint8Array(integer)
        }
 
-       static async hmac (key: Uint8Array<ArrayBuffer>, data: Uint8Array<ArrayBuffer>): Promise<Uint8Array<ArrayBuffer>> {
-               const pk = await crypto.subtle.importKey('raw', key, { name: 'HMAC', hash: 'SHA-512' }, false, ['sign'])
-               const signature = await crypto.subtle.sign('HMAC', pk, data)
-               return new Uint8Array(signature)
+       static hmac (key: Uint8Array<ArrayBuffer>, data: Uint8Array<ArrayBuffer>): Promise<ArrayBuffer> {
+               return crypto.subtle.importKey('raw', key, { name: 'HMAC', hash: 'SHA-512' }, false, ['sign'])
+                       .then(pk => {
+                               return crypto.subtle.sign('HMAC', pk, data)
+                                       .then(signature => {
+                                               return signature
+                                       })
+                       })
        }
 }