]> git.codecow.com Git - libnemo.git/commitdiff
Simplify promise chain.
authorChris Duncan <chris@zoso.dev>
Sat, 30 Aug 2025 07:32:14 +0000 (00:32 -0700)
committerChris Duncan <chris@zoso.dev>
Sat, 30 Aug 2025 07:32:14 +0000 (00:32 -0700)
src/lib/crypto/bip44.ts

index 80420685c50beda14c54840fdd7a342ce3aee777..deb200c5793e373fe713bd8e4e292be1160e67f0 100644 (file)
@@ -29,39 +29,25 @@ export class Bip44 {
                if (!Number.isSafeInteger(account) || account < 0 || account > 0x7fffffff) {
                        throw new RangeError(`Invalid account index 0x${account.toString(16)}`)
                }
-               if (change != null && (!Number.isSafeInteger(change) || change < 0 || change > 1)) {
+               if (change !== undefined && (!Number.isSafeInteger(change) || change < 0 || change > 1)) {
                        throw new RangeError(`Invalid change index 0x${account.toString(16)}`)
                }
-               if (address != null && (!Number.isSafeInteger(address) || address < 0 || address > 0x7fffffff)) {
+               if (address !== undefined && (!Number.isSafeInteger(address) || address < 0 || address > 0x7fffffff)) {
                        throw new RangeError(`Invalid address index 0x${account.toString(16)}`)
                }
-               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 (change == null) return accountKey.privateKey
-                                                                               return this.#CKDpriv(accountKey, change + HARDENED_OFFSET)
-                                                                                       .then(chainKey => {
-                                                                                               if (address == null) return chainKey.privateKey
-                                                                                               return this.#CKDpriv(chainKey, address + HARDENED_OFFSET)
-                                                                                                       .then(addressKey => {
-                                                                                                               return addressKey.privateKey
-                                                                                                       })
-                                                                                       })
-                                                                       })
-                                                       })
-                                       })
-                       })
+               return this.slip10(SLIP10_ED25519, seed)
+                       .then(masterKey => this.CKDpriv(masterKey, BIP44_PURPOSE))
+                       .then(purposeKey => this.CKDpriv(purposeKey, coin))
+                       .then(coinKey => this.CKDpriv(coinKey, account))
+                       .then(accountKey => this.CKDpriv(accountKey, change))
+                       .then(chainKey => this.CKDpriv(chainKey, address))
+                       .then(addressKey => addressKey.privateKey)
        }
 
-       static #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)
-               return this.#hmac(key, data)
+               return this.hmac(key, data)
                        .then(I => {
                                const IL = I.slice(0, I.byteLength / 2)
                                const IR = I.slice(I.byteLength / 2)
@@ -69,13 +55,17 @@ export class Bip44 {
                        })
        }
 
-       static #CKDpriv ({ privateKey, chainCode }: ExtendedKey, index: number): Promise<ExtendedKey> {
+       static CKDpriv ({ privateKey, chainCode }: ExtendedKey, index?: number): Promise<ExtendedKey> {
+               if (index === undefined) {
+                       return Promise.resolve({ privateKey, chainCode })
+               }
+               index += HARDENED_OFFSET
                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)
-               return this.#hmac(key, data)
+               data.set(this.ser256(privateKey), 1)
+               data.set(this.ser32(index), 33)
+               return this.hmac(key, data)
                        .then(I => {
                                const IL = I.slice(0, I.byteLength / 2)
                                const IR = I.slice(I.byteLength / 2)
@@ -83,17 +73,17 @@ export class Bip44 {
                        })
        }
 
-       static #ser32 (integer: number): Uint8Array<ArrayBuffer> {
+       static ser32 (integer: number): Uint8Array<ArrayBuffer> {
                const view = new DataView(new ArrayBuffer(4))
                view.setUint32(0, integer, false)
                return new Uint8Array(view.buffer)
        }
 
-       static #ser256 (integer: ArrayBuffer): Uint8Array<ArrayBuffer> {
+       static ser256 (integer: ArrayBuffer): Uint8Array<ArrayBuffer> {
                return new Uint8Array(integer)
        }
 
-       static #hmac (key: Uint8Array<ArrayBuffer>, data: Uint8Array<ArrayBuffer>): Promise<ArrayBuffer> {
+       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)