]> zoso.dev Git - libnemo.git/commitdiff
Tabs.
authorChris Duncan <chris@zoso.dev>
Wed, 20 Nov 2024 01:09:16 +0000 (17:09 -0800)
committerChris Duncan <chris@zoso.dev>
Wed, 20 Nov 2024 01:09:16 +0000 (17:09 -0800)
src/lib/entropy.ts
src/lib/rpc.ts
test/TEST_VECTORS.js

index 3437fbd4162e3c4e0e17c93e71706bbbf5520a0c..da51f0f060a44d1d4db5803e7b77c60730aa216f 100644 (file)
@@ -18,103 +18,103 @@ const MOD = 4
 * brand new source of entropy will be generated at the maximum size of 256 bits.
 */
 export class Entropy {
-  #bits: string
-  #buffer: ArrayBuffer
-  #bytes: Uint8Array
-  #hex: string
+       #bits: string
+       #buffer: ArrayBuffer
+       #bytes: Uint8Array
+       #hex: string
 
-  get bits () { return this.#bits }
-  get buffer () { return this.#buffer }
-  get bytes () { return this.#bytes }
-  get hex () { return this.#hex }
+       get bits () { return this.#bits }
+       get buffer () { return this.#buffer }
+       get bytes () { return this.#bytes }
+       get hex () { return this.#hex }
 
-  /**
-  * Generate 256 bits of entropy.
-  */
-  constructor ()
-  /**
-  * Generate between 16-32 bytes of entropy.
-  * @param {number} size - Number of bytes to generate
-  */
-  constructor (size: number)
-  /**
-  * Import existing entropy and validate it.
-  * @param {string} hex - Hexadecimal string
-  */
-  constructor (hex: string)
-  /**
-  * Import existing entropy and validate it.
-  * @param {ArrayBuffer} buffer - Byte buffer
-  */
-  constructor (buffer: ArrayBuffer)
-  /**
-  * Import existing entropy and validate it.
-  * @param {Uint8Array} bytes - Byte array
-  */
-  constructor (bytes: Uint8Array)
-  constructor (input?: number | string | ArrayBuffer | Uint8Array) {
-    if (typeof input === 'number' && input > 0) {
-      if (input < MIN || input > MAX) {
-        throw new RangeError(`Entropy must be ${MIN}-${MAX} bytes`)
-      }
-      if (input % MOD !== 0) {
-        throw new RangeError(`Entropy must be a multiple of ${MOD} bytes`)
-      }
-      this.#bytes = crypto.getRandomValues(new Uint8Array(input))
-      this.#hex = bytes.toHex(this.#bytes)
-      this.#bits = hex.toBin(this.#hex)
-      this.#buffer = this.#bytes.buffer
-      return
-    }
+       /**
+       * Generate 256 bits of entropy.
+       */
+       constructor ()
+       /**
+       * Generate between 16-32 bytes of entropy.
+       * @param {number} size - Number of bytes to generate
+       */
+       constructor (size: number)
+       /**
+       * Import existing entropy and validate it.
+       * @param {string} hex - Hexadecimal string
+       */
+       constructor (hex: string)
+       /**
+       * Import existing entropy and validate it.
+       * @param {ArrayBuffer} buffer - Byte buffer
+       */
+       constructor (buffer: ArrayBuffer)
+       /**
+       * Import existing entropy and validate it.
+       * @param {Uint8Array} bytes - Byte array
+       */
+       constructor (bytes: Uint8Array)
+       constructor (input?: number | string | ArrayBuffer | Uint8Array) {
+               if (typeof input === 'number' && input > 0) {
+                       if (input < MIN || input > MAX) {
+                               throw new RangeError(`Entropy must be ${MIN}-${MAX} bytes`)
+                       }
+                       if (input % MOD !== 0) {
+                               throw new RangeError(`Entropy must be a multiple of ${MOD} bytes`)
+                       }
+                       this.#bytes = crypto.getRandomValues(new Uint8Array(input))
+                       this.#hex = bytes.toHex(this.#bytes)
+                       this.#bits = hex.toBin(this.#hex)
+                       this.#buffer = this.#bytes.buffer
+                       return
+               }
 
-    if (typeof input === 'string' && input.length > 0) {
-      if (input.length < MIN * 2 || input.length > MAX * 2) {
-        throw new RangeError(`Entropy must be ${MIN * 2}-${MAX * 2} characters`)
-      }
-      if (input.length % MOD * 2 !== 0) {
-        throw new RangeError(`Entropy must be a multiple of ${MOD * 2} characters`)
-      }
-      this.#hex = input
-      if (!/^[0-9a-fA-F]+$/i.test(this.#hex)) {
-        throw new RangeError('Entropy contains invalid hexadecimal characters')
-      }
-      this.#bytes = hex.toBytes(this.#hex)
-      this.#bits = hex.toBin(this.#hex)
-      this.#buffer = this.#bytes.buffer
-      return
-    }
+               if (typeof input === 'string' && input.length > 0) {
+                       if (input.length < MIN * 2 || input.length > MAX * 2) {
+                               throw new RangeError(`Entropy must be ${MIN * 2}-${MAX * 2} characters`)
+                       }
+                       if (input.length % MOD * 2 !== 0) {
+                               throw new RangeError(`Entropy must be a multiple of ${MOD * 2} characters`)
+                       }
+                       this.#hex = input
+                       if (!/^[0-9a-fA-F]+$/i.test(this.#hex)) {
+                               throw new RangeError('Entropy contains invalid hexadecimal characters')
+                       }
+                       this.#bytes = hex.toBytes(this.#hex)
+                       this.#bits = hex.toBin(this.#hex)
+                       this.#buffer = this.#bytes.buffer
+                       return
+               }
 
-    if (input instanceof ArrayBuffer && input.byteLength > 0) {
-      if (input.byteLength < MIN || input.byteLength > MAX) {
-        throw new Error(`Entropy must be ${MIN}-${MAX} bytes`)
-      }
-      if (input.byteLength % MOD !== 0) {
-        throw new RangeError(`Entropy must be a multiple of ${MOD} bytes`)
-      }
-      this.#buffer = input
-      this.#bytes = new Uint8Array(this.#buffer)
-      this.#bits = bytes.toBin(this.#bytes)
-      this.#hex = bytes.toHex(this.#bytes)
-      return
-    }
+               if (input instanceof ArrayBuffer && input.byteLength > 0) {
+                       if (input.byteLength < MIN || input.byteLength > MAX) {
+                               throw new Error(`Entropy must be ${MIN}-${MAX} bytes`)
+                       }
+                       if (input.byteLength % MOD !== 0) {
+                               throw new RangeError(`Entropy must be a multiple of ${MOD} bytes`)
+                       }
+                       this.#buffer = input
+                       this.#bytes = new Uint8Array(this.#buffer)
+                       this.#bits = bytes.toBin(this.#bytes)
+                       this.#hex = bytes.toHex(this.#bytes)
+                       return
+               }
 
-    if (input instanceof Uint8Array && input.length > 0) {
-      if (input.length < MIN || input.length > MAX) {
-        throw new Error(`Entropy must be ${MIN}-${MAX} bytes`)
-      }
-      if (input.length % MOD !== 0) {
-        throw new RangeError(`Entropy must be a multiple of ${MOD} bytes`)
-      }
-      this.#bytes = input
-      this.#bits = bytes.toBin(this.#bytes)
-      this.#buffer = this.#bytes.buffer
-      this.#hex = bytes.toHex(this.#bytes)
-      return
-    }
+               if (input instanceof Uint8Array && input.length > 0) {
+                       if (input.length < MIN || input.length > MAX) {
+                               throw new Error(`Entropy must be ${MIN}-${MAX} bytes`)
+                       }
+                       if (input.length % MOD !== 0) {
+                               throw new RangeError(`Entropy must be a multiple of ${MOD} bytes`)
+                       }
+                       this.#bytes = input
+                       this.#bits = bytes.toBin(this.#bytes)
+                       this.#buffer = this.#bytes.buffer
+                       this.#hex = bytes.toHex(this.#bytes)
+                       return
+               }
 
-    this.#bytes = crypto.getRandomValues(new Uint8Array(MAX))
-    this.#hex = bytes.toHex(this.#bytes)
-    this.#bits = hex.toBin(this.#hex)
-    this.#buffer = this.#bytes.buffer
-  }
+               this.#bytes = crypto.getRandomValues(new Uint8Array(MAX))
+               this.#hex = bytes.toHex(this.#bytes)
+               this.#bits = hex.toBin(this.#hex)
+               this.#buffer = this.#bytes.buffer
+       }
 }
index 752ce1c16a5c4c348f19007623b68fc6f9119d42..cf8826343e37b14acb1c03dcfc4dbb16945ff65a 100644 (file)
@@ -9,60 +9,60 @@
 * other value will be changed automatically.
 */
 export class Rpc {
-  #u: URL
-  #n?: string
+       #u: URL
+       #n?: string
 
-  constructor (url: string | URL, apiKeyName?: string) {
-    this.#u = new URL(url)
-    this.#u.protocol = 'https:'
-    this.#n = apiKeyName
-  }
+       constructor (url: string | URL, apiKeyName?: string) {
+               this.#u = new URL(url)
+               this.#u.protocol = 'https:'
+               this.#n = apiKeyName
+       }
 
-  /**
-   *
-   * @param {string} action - Nano protocol RPC call to execute
-   * @param {object} [data] - JSON to send to the node as defined by the action
-   * @returns JSON-formatted RPC results from the node
-   */
-  async call (action: string, data?: { [key: string]: any }): Promise<any> {
-    this.#validate(action)
-    const headers: { [key: string]: string } = {}
-    headers['Content-Type'] = 'application/json'
-    if (this.#n && process.env.LIBNEMO_RPC_API_KEY) {
-      headers[this.#n] = process.env.LIBNEMO_RPC_API_KEY
-    }
+       /**
+        *
+        * @param {string} action - Nano protocol RPC call to execute
+        * @param {object} [data] - JSON to send to the node as defined by the action
+        * @returns JSON-formatted RPC results from the node
+        */
+       async call (action: string, data?: { [key: string]: any }): Promise<any> {
+               this.#validate(action)
+               const headers: { [key: string]: string } = {}
+               headers['Content-Type'] = 'application/json'
+               if (this.#n && process.env.LIBNEMO_RPC_API_KEY) {
+                       headers[this.#n] = process.env.LIBNEMO_RPC_API_KEY
+               }
 
-    data ??= {}
-    data.action = action.toLowerCase()
-    const body = JSON.stringify(data)
-      .replaceAll('/', '\\u002f')
-      .replaceAll('<', '\\u003c')
-      .replaceAll('>', '\\u003d')
-      .replaceAll('\\', '\\u005c')
+               data ??= {}
+               data.action = action.toLowerCase()
+               const body = JSON.stringify(data)
+                       .replaceAll('/', '\\u002f')
+                       .replaceAll('<', '\\u003c')
+                       .replaceAll('>', '\\u003d')
+                       .replaceAll('\\', '\\u005c')
 
-    const req = new Request(this.#u, {
-      method: 'POST',
-      headers,
-      body
-    })
-    try {
-      const res = await fetch(req)
-      return await res.json()
-    } catch (err) {
-      console.error(err)
-      return JSON.stringify(err)
-    }
-  }
+               const req = new Request(this.#u, {
+                       method: 'POST',
+                       headers,
+                       body
+               })
+               try {
+                       const res = await fetch(req)
+                       return await res.json()
+               } catch (err) {
+                       console.error(err)
+                       return JSON.stringify(err)
+               }
+       }
 
-  #validate (action: string): void {
-    if (!action) {
-      throw new ReferenceError('Action is required for RPCs')
-    }
-    if (typeof action !== 'string') {
-      throw new TypeError('RPC action must be a string')
-    }
-    if (!/^[A-Za-z]+(_[A-Za-z]+)*$/.test(action)) {
-      throw new TypeError('RPC action contains invalid characters')
-    }
-  }
+       #validate (action: string): void {
+               if (!action) {
+                       throw new ReferenceError('Action is required for RPCs')
+               }
+               if (typeof action !== 'string') {
+                       throw new TypeError('RPC action must be a string')
+               }
+               if (!/^[A-Za-z]+(_[A-Za-z]+)*$/.test(action)) {
+                       throw new TypeError('RPC action contains invalid characters')
+               }
+       }
 }
index c94e08b0d91edf26526eeead39244aa1746b43a3..27b3dffef32edaf2d8097f78d54540ad6905092a 100644 (file)
@@ -131,22 +131,22 @@ export const BIP32_TEST_VECTORS = Object.freeze({
        /**
        * These vectors test that invalid extended keys are recognized as invalid.
        */
-       INVALID_0: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6LBpB85b3D2yc8sfvZU521AAwdZafEz7mnzBBsz4wKY5fTtTQBm',  // (pubkey version / prvkey mismatch)
-       INVALID_1: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGTQQD3dC4H2D5GBj7vWvSQaaBv5cxi9gafk7NF3pnBju6dwKvH',  // (prvkey version / pubkey mismatch)
-       INVALID_2: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Txnt3siSujt9RCVYsx4qHZGc62TG4McvMGcAUjeuwZdduYEvFn',  // (invalid pubkey prefix 04)
-       INVALID_3: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGpWnsj83BHtEy5Zt8CcDr1UiRXuWCmTQLxEK9vbz5gPstX92JQ',  // (invalid prvkey prefix 04)
-       INVALID_4: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6N8ZMMXctdiCjxTNq964yKkwrkBJJwpzZS4HS2fxvyYUA4q2Xe4',  // (invalid pubkey prefix 01)
-       INVALID_5: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD9y5gkZ6Eq3Rjuahrv17fEQ3Qen6J',  // (invalid prvkey prefix 01)
-       INVALID_6: 'xprv9s2SPatNQ9Vc6GTbVMFPFo7jsaZySyzk7L8n2uqKXJen3KUmvQNTuLh3fhZMBoG3G4ZW1N2kZuHEPY53qmbZzCHshoQnNf4GvELZfqTUrcv',  // (zero depth with non - zero parent fingerprint)
-       INVALID_7: 'xpub661no6RGEX3uJkY4bNnPcw4URcQTrSibUZ4NqJEw5eBkv7ovTwgiT91XX27VbEXGENhYRCf7hyEbWrR3FewATdCEebj6znwMfQkhRYHRLpJ',  // (zero depth with non - zero parent fingerprint)
-       INVALID_8: 'xprv9s21ZrQH4r4TsiLvyLXqM9P7k1K3EYhA1kkD6xuquB5i39AU8KF42acDyL3qsDbU9NmZn6MsGSUYZEsuoePmjzsB3eFKSUEh3Gu1N3cqVUN',  // (zero depth with non - zero index)
-       INVALID_9: 'xpub661MyMwAuDcm6CRQ5N4qiHKrJ39Xe1R1NyfouMKTTWcguwVcfrZJaNvhpebzGerh7gucBvzEQWRugZDuDXjNDRmXzSZe4c7mnTK97pTvGS8',  // (zero depth with non - zero index)
-       INVALID_10: 'DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHGMQzT7ayAmfo4z3gY5KfbrZWZ6St24UVf2Qgo6oujFktLHdHY4', // (unknown extended key version)
-       INVALID_11: 'DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHPmHJiEDXkTiJTVV9rHEBUem2mwVbbNfvT2MTcAqj3nesx8uBf9', // (unknown extended key version)
-       INVALID_12: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzF93Y5wvzdUayhgkkFoicQZcP3y52uPPxFnfoLZB21Teqt1VvEHx', // (private key 0 not in 1..n - 1)
-       INVALID_13: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD5SDKr24z3aiUvKr9bJpdrcLg1y3G', // (private key n not in 1..n - 1)
-       INVALID_14: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Q5JXayek4PRsn35jii4veMimro1xefsM58PgBMrvdYre8QyULY', // (invalid pubkey 020000000000000000000000000000000000000000000000000000000000000007)
-       INVALID_15: 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHL'  // (invalid checksum)
+       INVALID_0: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6LBpB85b3D2yc8sfvZU521AAwdZafEz7mnzBBsz4wKY5fTtTQBm',   // (pubkey version / prvkey mismatch)
+       INVALID_1: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGTQQD3dC4H2D5GBj7vWvSQaaBv5cxi9gafk7NF3pnBju6dwKvH',   // (prvkey version / pubkey mismatch)
+       INVALID_2: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Txnt3siSujt9RCVYsx4qHZGc62TG4McvMGcAUjeuwZdduYEvFn',   // (invalid pubkey prefix 04)
+       INVALID_3: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGpWnsj83BHtEy5Zt8CcDr1UiRXuWCmTQLxEK9vbz5gPstX92JQ',   // (invalid prvkey prefix 04)
+       INVALID_4: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6N8ZMMXctdiCjxTNq964yKkwrkBJJwpzZS4HS2fxvyYUA4q2Xe4',   // (invalid pubkey prefix 01)
+       INVALID_5: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD9y5gkZ6Eq3Rjuahrv17fEQ3Qen6J',   // (invalid prvkey prefix 01)
+       INVALID_6: 'xprv9s2SPatNQ9Vc6GTbVMFPFo7jsaZySyzk7L8n2uqKXJen3KUmvQNTuLh3fhZMBoG3G4ZW1N2kZuHEPY53qmbZzCHshoQnNf4GvELZfqTUrcv',   // (zero depth with non - zero parent fingerprint)
+       INVALID_7: 'xpub661no6RGEX3uJkY4bNnPcw4URcQTrSibUZ4NqJEw5eBkv7ovTwgiT91XX27VbEXGENhYRCf7hyEbWrR3FewATdCEebj6znwMfQkhRYHRLpJ',   // (zero depth with non - zero parent fingerprint)
+       INVALID_8: 'xprv9s21ZrQH4r4TsiLvyLXqM9P7k1K3EYhA1kkD6xuquB5i39AU8KF42acDyL3qsDbU9NmZn6MsGSUYZEsuoePmjzsB3eFKSUEh3Gu1N3cqVUN',   // (zero depth with non - zero index)
+       INVALID_9: 'xpub661MyMwAuDcm6CRQ5N4qiHKrJ39Xe1R1NyfouMKTTWcguwVcfrZJaNvhpebzGerh7gucBvzEQWRugZDuDXjNDRmXzSZe4c7mnTK97pTvGS8',   // (zero depth with non - zero index)
+       INVALID_10: 'DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHGMQzT7ayAmfo4z3gY5KfbrZWZ6St24UVf2Qgo6oujFktLHdHY4',  // (unknown extended key version)
+       INVALID_11: 'DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHPmHJiEDXkTiJTVV9rHEBUem2mwVbbNfvT2MTcAqj3nesx8uBf9',  // (unknown extended key version)
+       INVALID_12: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzF93Y5wvzdUayhgkkFoicQZcP3y52uPPxFnfoLZB21Teqt1VvEHx',  // (private key 0 not in 1..n - 1)
+       INVALID_13: 'xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD5SDKr24z3aiUvKr9bJpdrcLg1y3G',  // (private key n not in 1..n - 1)
+       INVALID_14: 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Q5JXayek4PRsn35jii4veMimro1xefsM58PgBMrvdYre8QyULY',  // (invalid pubkey 020000000000000000000000000000000000000000000000000000000000000007)
+       INVALID_15: 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHL'   // (invalid checksum)
 })
 
 export const CUSTOM_TEST_VECTORS = Object.freeze({