diff --git a/.eslintrc.js b/.eslintrc.js index 6bcadcd9..6cd934dd 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -11,6 +11,14 @@ module.exports = { allow: ['^UNSAFE_', 'coin_type', 'address_index'], }, ], + + 'no-restricted-globals': [ + 'error', + { + name: 'Buffer', + message: "Use 'Uint8Array' instead.", + }, + ], }, overrides: [ diff --git a/package.json b/package.json index 4c2cf5ba..55e84282 100755 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ ] }, "dependencies": { + "@metamask/utils": "^3.2.0", "@noble/ed25519": "^1.6.0", "@noble/hashes": "^1.0.0", "@noble/secp256k1": "^1.5.5", diff --git a/src/BIP44CoinTypeNode.test.ts b/src/BIP44CoinTypeNode.test.ts index 7ed89702..ca305bc0 100644 --- a/src/BIP44CoinTypeNode.test.ts +++ b/src/BIP44CoinTypeNode.test.ts @@ -1,3 +1,4 @@ +import { bytesToHex } from '@metamask/utils'; import fixtures from '../test/fixtures'; import { encodeExtendedKey, PRIVATE_KEY_VERSION } from './extended-keys'; import { @@ -82,26 +83,26 @@ describe('BIP44CoinTypeNode', () => { const inputs = [ { privateKey: '0xf00', - publicKey: Buffer.alloc(65, 1), - chainCode: Buffer.alloc(32, 1), + publicKey: new Uint8Array(65).fill(1), + chainCode: new Uint8Array(32).fill(1), ...options, }, { - privateKey: Buffer.allocUnsafe(64).fill(1).toString('hex'), - publicKey: Buffer.alloc(65, 1), - chainCode: Buffer.alloc(32, 1), + privateKey: bytesToHex(new Uint8Array(64).fill(1)), + publicKey: new Uint8Array(65).fill(1), + chainCode: new Uint8Array(32).fill(1), ...options, }, { - privateKey: Buffer.allocUnsafe(63).fill(1).toString('hex'), - publicKey: Buffer.alloc(65, 1), - chainCode: Buffer.alloc(32, 1), + privateKey: bytesToHex(new Uint8Array(63).fill(1)), + publicKey: new Uint8Array(65).fill(1), + chainCode: new Uint8Array(32).fill(1), ...options, }, { - privateKey: Buffer.alloc(64).toString('hex'), - publicKey: Buffer.alloc(65, 1), - chainCode: Buffer.alloc(32, 1), + privateKey: bytesToHex(new Uint8Array(64)), + publicKey: new Uint8Array(65).fill(1), + chainCode: new Uint8Array(32).fill(1), ...options, }, ]; @@ -116,13 +117,13 @@ describe('BIP44CoinTypeNode', () => { BIP44CoinTypeNode.fromJSON( { privateKey: 1, - publicKey: Buffer.alloc(65, 1), - chainCode: Buffer.alloc(32, 1), + publicKey: new Uint8Array(65).fill(1), + chainCode: new Uint8Array(32).fill(1), depth: 2, } as any, arbitraryCoinType, ), - ).rejects.toThrow('Invalid hex string: "1".'); + ).rejects.toThrow('Value must be a hexadecimal string.'); }); it('throws if coin type is invalid', async () => { @@ -430,7 +431,7 @@ describe('BIP44CoinTypeNode', () => { const extendedKey = encodeExtendedKey({ version: PRIVATE_KEY_VERSION, - privateKey: node.privateKeyBuffer as Buffer, + privateKey: node.privateKeyBuffer as Uint8Array, chainCode: node.chainCodeBuffer, depth: node.depth, parentFingerprint: node.parentFingerprint, diff --git a/src/BIP44CoinTypeNode.ts b/src/BIP44CoinTypeNode.ts index 463635e6..6d96d816 100644 --- a/src/BIP44CoinTypeNode.ts +++ b/src/BIP44CoinTypeNode.ts @@ -167,15 +167,15 @@ export class BIP44CoinTypeNode implements BIP44CoinTypeNodeInterface { return this.#node.depth; } - public get privateKeyBuffer(): Buffer | undefined { + public get privateKeyBuffer(): Uint8Array | undefined { return this.#node.privateKeyBuffer; } - public get publicKeyBuffer(): Buffer { + public get publicKeyBuffer(): Uint8Array { return this.#node.publicKeyBuffer; } - public get chainCodeBuffer(): Buffer { + public get chainCodeBuffer(): Uint8Array { return this.#node.chainCodeBuffer; } @@ -191,7 +191,7 @@ export class BIP44CoinTypeNode implements BIP44CoinTypeNodeInterface { return this.#node.compressedPublicKey; } - public get compressedPublicKeyBuffer(): Buffer { + public get compressedPublicKeyBuffer(): Uint8Array { return this.#node.compressedPublicKeyBuffer; } diff --git a/src/BIP44Node.test.ts b/src/BIP44Node.test.ts index 10d3d5fc..d68aada1 100644 --- a/src/BIP44Node.test.ts +++ b/src/BIP44Node.test.ts @@ -1,3 +1,4 @@ +import { bytesToHex } from '@metamask/utils'; import fixtures from '../test/fixtures'; import { createBip39KeyFromSeed, deriveChildKey } from './derivers/bip39'; import { hexStringToBuffer } from './utils'; @@ -131,7 +132,7 @@ describe('BIP44Node', () => { // getter ['depth', 'privateKey', 'publicKey', 'address'].forEach((property) => { - expect(() => (node[property] = Buffer.allocUnsafe(64).fill(1))).toThrow( + expect(() => (node[property] = new Uint8Array(64).fill(1))).toThrow( expect.objectContaining({ name: 'TypeError', message: expect.stringMatching( @@ -443,7 +444,7 @@ describe('BIP44Node', () => { }); expect(node.compressedPublicKey).toStrictEqual( - compressPublicKey(node.publicKeyBuffer).toString('hex'), + bytesToHex(compressPublicKey(node.publicKeyBuffer)), ); }); }); @@ -478,7 +479,7 @@ describe('BIP44Node', () => { const extendedKey = encodeExtendedKey({ version: PRIVATE_KEY_VERSION, - privateKey: node.privateKeyBuffer as Buffer, + privateKey: node.privateKeyBuffer as Uint8Array, chainCode: node.chainCodeBuffer, depth: node.depth, parentFingerprint: node.parentFingerprint, diff --git a/src/BIP44Node.ts b/src/BIP44Node.ts index 89d1fd49..9b99dcbf 100644 --- a/src/BIP44Node.ts +++ b/src/BIP44Node.ts @@ -23,9 +23,9 @@ type BIP44ExtendedKeyOptions = { readonly depth: number; readonly parentFingerprint: number; readonly index: number; - readonly chainCode: Buffer | string; - readonly privateKey?: Buffer | string; - readonly publicKey?: Buffer | string; + readonly chainCode: Uint8Array | string; + readonly privateKey?: Uint8Array | string; + readonly publicKey?: Uint8Array | string; }; type BIP44DerivationPathOptions = { @@ -221,15 +221,15 @@ export class BIP44Node implements BIP44NodeInterface { return this.#node.depth as BIP44Depth; } - public get privateKeyBuffer(): Buffer | undefined { + public get privateKeyBuffer(): Uint8Array | undefined { return this.#node.privateKeyBuffer; } - public get publicKeyBuffer(): Buffer { + public get publicKeyBuffer(): Uint8Array { return this.#node.publicKeyBuffer; } - public get chainCodeBuffer(): Buffer { + public get chainCodeBuffer(): Uint8Array { return this.#node.chainCodeBuffer; } @@ -245,7 +245,7 @@ export class BIP44Node implements BIP44NodeInterface { return this.#node.compressedPublicKey; } - public get compressedPublicKeyBuffer(): Buffer { + public get compressedPublicKeyBuffer(): Uint8Array { return this.#node.compressedPublicKeyBuffer; } diff --git a/src/SLIP10Node.test.ts b/src/SLIP10Node.test.ts index 375a90f3..7e226a44 100644 --- a/src/SLIP10Node.test.ts +++ b/src/SLIP10Node.test.ts @@ -1,3 +1,4 @@ +import { bytesToHex, hexToBytes } from '@metamask/utils'; import fixtures from '../test/fixtures'; import { ed25519, secp256k1 } from './curves'; import { SLIP10Node } from './SLIP10Node'; @@ -157,7 +158,7 @@ describe('SLIP10Node', () => { it('throws if no public or private key is specified', async () => { await expect( SLIP10Node.fromExtendedKey({ - chainCode: Buffer.alloc(32, 1), + chainCode: new Uint8Array(32).fill(1), depth: 0, parentFingerprint: 0, index: 0, @@ -188,8 +189,8 @@ describe('SLIP10Node', () => { depth: input as any, parentFingerprint: 0, index: 0, - publicKey: Buffer.alloc(65, 1), - chainCode: Buffer.alloc(32, 1), + publicKey: new Uint8Array(65).fill(1), + chainCode: new Uint8Array(32).fill(1), curve: 'secp256k1', }), ).rejects.toThrow( @@ -218,8 +219,8 @@ describe('SLIP10Node', () => { depth: 0, parentFingerprint: input as any, index: 0, - publicKey: Buffer.alloc(65, 1), - chainCode: Buffer.alloc(32, 1), + publicKey: new Uint8Array(65).fill(1), + chainCode: new Uint8Array(32).fill(1), curve: 'secp256k1', }), ).rejects.toThrow( @@ -232,15 +233,13 @@ describe('SLIP10Node', () => { await expect( SLIP10Node.fromExtendedKey({ privateKey: 'foo', - chainCode: Buffer.alloc(32, 1), + chainCode: new Uint8Array(32).fill(1), depth: 0, parentFingerprint: 0, index: 0, curve: 'secp256k1', }), - ).rejects.toThrow( - 'Invalid value: Must be a valid hex string of length: 64.', - ); + ).rejects.toThrow('Value must be a hexadecimal string.'); }); it('throws if the private key is not a Buffer or hexadecimal string', async () => { @@ -248,14 +247,14 @@ describe('SLIP10Node', () => { SLIP10Node.fromExtendedKey({ // @ts-expect-error Invalid private key type. privateKey: 123, - chainCode: Buffer.alloc(32, 1), + chainCode: new Uint8Array(32).fill(1), depth: 0, parentFingerprint: 0, index: 0, curve: 'secp256k1', }), ).rejects.toThrow( - 'Invalid value: Expected a Buffer or hexadecimal string.', + 'Invalid value: Expected an instance of Uint8Array or hexadecimal string.', ); }); }); @@ -338,7 +337,7 @@ describe('SLIP10Node', () => { 'publicKeyBuffer', 'chainCodeBuffer', ].forEach((property) => { - expect(() => (node[property] = Buffer.allocUnsafe(64).fill(1))).toThrow( + expect(() => (node[property] = new Uint8Array(64).fill(1))).toThrow( expect.objectContaining({ name: 'TypeError', message: expect.stringMatching( @@ -532,7 +531,7 @@ describe('SLIP10Node', () => { }); expect(node.compressedPublicKey).toStrictEqual( - compressPublicKey(node.publicKeyBuffer).toString('hex'), + bytesToHex(compressPublicKey(node.publicKeyBuffer)), ); }); }); @@ -563,7 +562,7 @@ describe('SLIP10Node', () => { 'returns the address for an secp256k1 node', async ({ index, address }) => { const { privateKey, chainCode } = await createBip39KeyFromSeed( - hexStringToBuffer(hexSeed), + hexToBytes(hexSeed), secp256k1, ); diff --git a/src/SLIP10Node.ts b/src/SLIP10Node.ts index 93305ccf..d424bf4f 100644 --- a/src/SLIP10Node.ts +++ b/src/SLIP10Node.ts @@ -1,3 +1,4 @@ +import { bytesToHex } from '@metamask/utils'; import { BUFFER_KEY_LENGTH, RootedSLIP10PathTuple, @@ -64,18 +65,18 @@ export type JsonSLIP10Node = { }; export type SLIP10NodeInterface = JsonSLIP10Node & { - chainCodeBuffer: Buffer; + chainCodeBuffer: Uint8Array; /** * The private key for this node, as a Node.js Buffer or browser-equivalent. * May be undefined if this node is a public key only node. */ - privateKeyBuffer?: Buffer; + privateKeyBuffer?: Uint8Array; /** * The public key for this node, as a Node.js Buffer or browser-equivalent. */ - publicKeyBuffer: Buffer; + publicKeyBuffer: Uint8Array; /** * @returns A JSON-compatible representation of this node's data fields. @@ -88,9 +89,9 @@ type SLIP10NodeConstructorOptions = { readonly masterFingerprint?: number; readonly parentFingerprint: number; readonly index: number; - readonly chainCode: Buffer; - readonly privateKey?: Buffer; - readonly publicKey: Buffer; + readonly chainCode: Uint8Array; + readonly privateKey?: Uint8Array; + readonly publicKey: Uint8Array; readonly curve: SupportedCurve; }; @@ -99,9 +100,9 @@ type SLIP10ExtendedKeyOptions = { readonly masterFingerprint?: number; readonly parentFingerprint: number; readonly index: number; - readonly chainCode: string | Buffer; - readonly privateKey?: string | Buffer; - readonly publicKey?: string | Buffer; + readonly chainCode: string | Uint8Array; + readonly privateKey?: string | Uint8Array; + readonly publicKey?: string | Uint8Array; readonly curve: SupportedCurve; }; @@ -130,6 +131,9 @@ export class SLIP10Node implements SLIP10NodeInterface { * validation fails. * * @param depth - The depth of the node. + * @param masterFingerprint - The fingerprint of the master node, i.e., the + * node at depth 0. May be undefined if this node was created from an extended + * key. * @param parentFingerprint - The fingerprint of the parent key, or 0 if * the node is a master node. * @param index - The index of the node, or 0 if the node is a master node. @@ -166,7 +170,7 @@ export class SLIP10Node implements SLIP10NodeInterface { index, chainCode: chainCodeBuffer, privateKey: privateKeyBuffer, - publicKey: await getCurveByName(curve).getPublicKey(privateKey), + publicKey: await getCurveByName(curve).getPublicKey(privateKeyBuffer), curve, }); } @@ -247,11 +251,11 @@ export class SLIP10Node implements SLIP10NodeInterface { public readonly index: number; - public readonly chainCodeBuffer: Buffer; + public readonly chainCodeBuffer: Uint8Array; - public readonly privateKeyBuffer?: Buffer; + public readonly privateKeyBuffer?: Uint8Array; - public readonly publicKeyBuffer: Buffer; + public readonly publicKeyBuffer: Uint8Array; constructor({ depth, @@ -276,23 +280,27 @@ export class SLIP10Node implements SLIP10NodeInterface { } public get chainCode() { - return this.chainCodeBuffer.toString('hex'); + return bytesToHex(this.chainCodeBuffer); } public get privateKey(): string | undefined { - return this.privateKeyBuffer?.toString('hex'); + if (this.privateKeyBuffer) { + return bytesToHex(this.privateKeyBuffer); + } + + return undefined; } public get publicKey(): string { - return this.publicKeyBuffer.toString('hex'); + return bytesToHex(this.publicKeyBuffer); } - public get compressedPublicKeyBuffer(): Buffer { + public get compressedPublicKeyBuffer(): Uint8Array { return getCurveByName(this.curve).compressPublicKey(this.publicKeyBuffer); } public get compressedPublicKey(): string { - return this.compressedPublicKeyBuffer.toString('hex'); + return bytesToHex(this.compressedPublicKeyBuffer); } public get address(): string { @@ -302,7 +310,7 @@ export class SLIP10Node implements SLIP10NodeInterface { ); } - return `0x${publicKeyToEthAddress(this.publicKeyBuffer).toString('hex')}`; + return bytesToHex(publicKeyToEthAddress(this.publicKeyBuffer)); } public get fingerprint(): number { diff --git a/src/curves/curve.ts b/src/curves/curve.ts index f06c4a1c..fbf2c32a 100644 --- a/src/curves/curve.ts +++ b/src/curves/curve.ts @@ -18,13 +18,13 @@ export type Curve = { n: bigint; }; getPublicKey: ( - privateKey: Uint8Array | string | bigint, + privateKey: Uint8Array, compressed?: boolean, - ) => Buffer | Promise; - isValidPrivateKey: (privateKey: Uint8Array | string | bigint) => boolean; - publicAdd: (publicKey: Buffer, tweak: Buffer) => Buffer; - compressPublicKey: (publicKey: Buffer) => Buffer; - decompressPublicKey: (publicKey: Buffer) => Buffer; + ) => Uint8Array | Promise; + isValidPrivateKey: (privateKey: Uint8Array) => boolean; + publicAdd: (publicKey: Uint8Array, tweak: Uint8Array) => Uint8Array; + compressPublicKey: (publicKey: Uint8Array) => Uint8Array; + decompressPublicKey: (publicKey: Uint8Array) => Uint8Array; }; /** diff --git a/src/curves/ed25519.test.ts b/src/curves/ed25519.test.ts index 9eb18642..10b03033 100644 --- a/src/curves/ed25519.test.ts +++ b/src/curves/ed25519.test.ts @@ -1,6 +1,5 @@ -import { bytesToHex } from '@noble/hashes/utils'; +import { hexToBytes, bytesToHex } from '@metamask/utils'; import fixtures from '../../test/fixtures'; -import { hexStringToBuffer } from '../utils'; import { compressPublicKey, curve, @@ -38,10 +37,13 @@ describe('ed25519', () => { 'returns the 0-padded public key for a private key', async ({ keys }) => { for (const { privateKey, publicKey } of keys) { - expect(bytesToHex(await getPublicKey(privateKey))).toBe(publicKey); - expect(bytesToHex(await getPublicKey(privateKey, true))).toBe( + expect(bytesToHex(await getPublicKey(hexToBytes(privateKey)))).toBe( publicKey, ); + + expect( + bytesToHex(await getPublicKey(hexToBytes(privateKey), true)), + ).toBe(publicKey); } }, ); @@ -49,7 +51,7 @@ describe('ed25519', () => { describe('publicAdd', () => { it('throws an error', () => { - expect(() => publicAdd(Buffer.alloc(1), Buffer.alloc(1))).toThrow( + expect(() => publicAdd(new Uint8Array([1]), new Uint8Array([1]))).toThrow( 'Ed25519 does not support public key derivation.', ); }); @@ -60,7 +62,7 @@ describe('ed25519', () => { it.each(slip10)('returns the same public key', async ({ keys }) => { for (const { publicKey } of keys) { - const publicKeyBuffer = hexStringToBuffer(publicKey); + const publicKeyBuffer = hexToBytes(publicKey); expect(compressPublicKey(publicKeyBuffer)).toStrictEqual( publicKeyBuffer, ); @@ -73,7 +75,7 @@ describe('ed25519', () => { it.each(slip10)('returns the same public key', async ({ keys }) => { for (const { publicKey } of keys) { - const publicKeyBuffer = hexStringToBuffer(publicKey); + const publicKeyBuffer = hexToBytes(publicKey); expect(decompressPublicKey(publicKeyBuffer)).toStrictEqual( publicKeyBuffer, ); diff --git a/src/curves/ed25519.ts b/src/curves/ed25519.ts index c28ffc26..786eaca6 100644 --- a/src/curves/ed25519.ts +++ b/src/curves/ed25519.ts @@ -1,4 +1,5 @@ import { getPublicKey as getEd25519PublicKey } from '@noble/ed25519'; +import { concatBytes, stringToBytes } from '@metamask/utils'; export { CURVE as curve } from '@noble/ed25519'; @@ -6,7 +7,7 @@ export const name = 'ed25519'; // Secret is defined in SLIP-10: // https://github.com/satoshilabs/slips/blob/133ea52a8e43d338b98be208907e144277e44c0e/slip-0010.md#master-key-generation -export const secret = Buffer.from('ed25519 seed', 'utf8'); +export const secret = stringToBytes('ed25519 seed'); // All private keys are valid for ed25519: // https://github.com/satoshilabs/slips/blob/133ea52a8e43d338b98be208907e144277e44c0e/slip-0010.md#master-key-generation @@ -18,23 +19,26 @@ export const deriveUnhardenedKeys = false; export const publicKeyLength = 33; export const getPublicKey = async ( - privateKey: Uint8Array | string | bigint, + privateKey: Uint8Array, _compressed?: boolean, -): Promise => { +): Promise => { const publicKey = await getEd25519PublicKey(privateKey); - return Buffer.concat([Buffer.alloc(1, 0), publicKey]); + return concatBytes([new Uint8Array([0]), publicKey]); }; -export const publicAdd = (_publicKey: Buffer, _tweak: Buffer): Buffer => { +export const publicAdd = ( + _publicKey: Uint8Array, + _tweak: Uint8Array, +): Uint8Array => { throw new Error('Ed25519 does not support public key derivation.'); }; -export const compressPublicKey = (publicKey: Buffer): Buffer => { +export const compressPublicKey = (publicKey: Uint8Array): Uint8Array => { // Ed25519 public keys don't have a compressed form. return publicKey; }; -export const decompressPublicKey = (publicKey: Buffer): Buffer => { +export const decompressPublicKey = (publicKey: Uint8Array): Uint8Array => { // Ed25519 public keys don't have a compressed form. return publicKey; }; diff --git a/src/curves/secp256k1.test.ts b/src/curves/secp256k1.test.ts index 5fbe8c5c..f886d904 100644 --- a/src/curves/secp256k1.test.ts +++ b/src/curves/secp256k1.test.ts @@ -1,4 +1,4 @@ -import { bytesToHex } from '@noble/hashes/utils'; +import { bytesToHex, hexToBytes } from '@metamask/utils'; import fixtures from '../../test/fixtures'; import { curve, getPublicKey, isValidPrivateKey } from './secp256k1'; @@ -15,10 +15,10 @@ describe('secp256k1', () => { describe('isValidPrivateKey', () => { it('checks if a private key is valid', () => { - expect(isValidPrivateKey('0x0')).toBe(false); - expect(isValidPrivateKey(fixtures.bip32[0].keys[0].privateKey)).toBe( - true, - ); + expect(isValidPrivateKey(hexToBytes('0x0'))).toBe(false); + expect( + isValidPrivateKey(hexToBytes(fixtures.bip32[0].keys[0].privateKey)), + ).toBe(true); }); }); @@ -29,7 +29,9 @@ describe('secp256k1', () => { 'returns the public key for a private key', async ({ keys }) => { for (const { privateKey, publicKey } of keys) { - expect(bytesToHex(await getPublicKey(privateKey))).toBe(publicKey); + expect(bytesToHex(await getPublicKey(hexToBytes(privateKey)))).toBe( + publicKey, + ); } }, ); diff --git a/src/curves/secp256k1.ts b/src/curves/secp256k1.ts index 6dbec568..35bbb3ff 100644 --- a/src/curves/secp256k1.ts +++ b/src/curves/secp256k1.ts @@ -1,29 +1,36 @@ import { - utils, getPublicKey as getSecp256k1PublicKey, Point, + utils, } from '@noble/secp256k1'; +import { stringToBytes } from '@metamask/utils'; export { CURVE as curve } from '@noble/secp256k1'; -export const { isValidPrivateKey } = utils; export const name = 'secp256k1'; // Secret is defined in BIP-32 and SLIP-10: // https://github.com/bitcoin/bips/blob/274fa400d630ba757bec0c03b35ebe2345197108/bip-0032.mediawiki#master-key-generation // https://github.com/satoshilabs/slips/blob/133ea52a8e43d338b98be208907e144277e44c0e/slip-0010.md#master-key-generation -export const secret = Buffer.from('Bitcoin seed', 'utf8'); +export const secret = stringToBytes('Bitcoin seed'); export const deriveUnhardenedKeys = true; export const publicKeyLength = 65; +export const isValidPrivateKey = (privateKey: Uint8Array) => { + return utils.isValidPrivateKey(privateKey); +}; + export const getPublicKey = ( - privateKey: Uint8Array | string | bigint, + privateKey: Uint8Array, compressed?: boolean, -): Buffer => Buffer.from(getSecp256k1PublicKey(privateKey, compressed)); +): Uint8Array => getSecp256k1PublicKey(privateKey, compressed); -export const publicAdd = (publicKey: Buffer, tweak: Buffer): Buffer => { +export const publicAdd = ( + publicKey: Uint8Array, + tweak: Uint8Array, +): Uint8Array => { const point = Point.fromHex(publicKey); // The returned child key Ki is point(parse256(IL)) + Kpar. @@ -33,17 +40,17 @@ export const publicAdd = (publicKey: Buffer, tweak: Buffer): Buffer => { newPoint.assertValidity(); - return Buffer.from(newPoint.toRawBytes(false)); + return newPoint.toRawBytes(false); }; -export const compressPublicKey = (publicKey: Uint8Array): Buffer => { +export const compressPublicKey = (publicKey: Uint8Array): Uint8Array => { const point = Point.fromHex(publicKey); - return Buffer.from(point.toRawBytes(true)); + return point.toRawBytes(true); }; -export const decompressPublicKey = (publicKey: Uint8Array): Buffer => { +export const decompressPublicKey = (publicKey: Uint8Array): Uint8Array => { // This calculates a point on the elliptic curve from a compressed public key. We can then use // this to get the uncompressed version of the public key. const point = Point.fromHex(publicKey); - return Buffer.from(point.toRawBytes(false)); + return point.toRawBytes(false); }; diff --git a/src/derivation.test.ts b/src/derivation.test.ts index caa5e452..908f180c 100755 --- a/src/derivation.test.ts +++ b/src/derivation.test.ts @@ -1,3 +1,4 @@ +import { bytesToHex } from '@metamask/utils'; import fixtures from '../test/fixtures'; import { HDPathTuple } from './constants'; import { deriveKeyFromPath } from './derivation'; @@ -48,10 +49,8 @@ describe('derivation', () => { // validate addresses keys.forEach(({ privateKeyBuffer }, index) => { - const address = privateKeyToEthAddress(privateKeyBuffer as Buffer); - expect(`0x${address.toString('hex')}`).toStrictEqual( - expectedAddresses[index], - ); + const address = privateKeyToEthAddress(privateKeyBuffer as Uint8Array); + expect(bytesToHex(address)).toStrictEqual(expectedAddresses[index]); }); }); @@ -75,10 +74,8 @@ describe('derivation', () => { // validate addresses keys.forEach(({ privateKeyBuffer }, index) => { - const address = privateKeyToEthAddress(privateKeyBuffer as Buffer); - expect(`0x${address.toString('hex')}`).toStrictEqual( - expectedAddresses[index], - ); + const address = privateKeyToEthAddress(privateKeyBuffer as Uint8Array); + expect(bytesToHex(address)).toStrictEqual(expectedAddresses[index]); }); }); @@ -288,15 +285,15 @@ describe('derivation', () => { describe('privateKeyToEthAddress', () => { it('throws for invalid inputs', () => { [ - Buffer.allocUnsafe(31).fill(1), - Buffer.alloc(32, 0), + new Uint8Array(31).fill(1), + new Uint8Array(32).fill(0), 'foo', {}, null, undefined, ].forEach((invalidInput) => { expect(() => privateKeyToEthAddress(invalidInput as any)).toThrow( - 'Invalid key: The key must be a 32-byte, non-zero Buffer.', + 'Invalid key: The key must be a 32-byte, non-zero Uint8Array.', ); }); }); diff --git a/src/derivers/bip32.test.ts b/src/derivers/bip32.test.ts index 44a27ba7..f21097d0 100644 --- a/src/derivers/bip32.test.ts +++ b/src/derivers/bip32.test.ts @@ -1,4 +1,5 @@ import { CURVE } from '@noble/secp256k1'; +import { bytesToHex } from '@metamask/utils'; import { hexStringToBuffer } from '../utils'; import fixtures from '../../test/fixtures'; import { secp256k1 } from '../curves'; @@ -59,20 +60,18 @@ describe('privateKeyToEthAddress', () => { const { privateKey, address } = fixtures['ethereumjs-wallet']; expect( - `0x${privateKeyToEthAddress(hexStringToBuffer(privateKey)).toString( - 'hex', - )}`, + bytesToHex(privateKeyToEthAddress(hexStringToBuffer(privateKey))), ).toBe(address); }); it('throws for invalid private keys', () => { // @ts-expect-error Invalid public key type. expect(() => privateKeyToEthAddress('foo')).toThrow( - 'Invalid key: The key must be a 32-byte, non-zero Buffer.', + 'Invalid key: The key must be a 32-byte, non-zero Uint8Array.', ); - expect(() => privateKeyToEthAddress(Buffer.alloc(31).fill(1))).toThrow( - 'Invalid key: The key must be a 32-byte, non-zero Buffer.', + expect(() => privateKeyToEthAddress(new Uint8Array(31).fill(1))).toThrow( + 'Invalid key: The key must be a 32-byte, non-zero Uint8Array.', ); }); }); @@ -82,20 +81,18 @@ describe('publicKeyToEthAddress', () => { const { publicKey, address } = fixtures['ethereumjs-wallet']; expect( - `0x${publicKeyToEthAddress(hexStringToBuffer(publicKey)).toString( - 'hex', - )}`, + bytesToHex(publicKeyToEthAddress(hexStringToBuffer(publicKey))), ).toBe(address); }); it('throws for invalid public keys', () => { // @ts-expect-error Invalid public key type. expect(() => publicKeyToEthAddress('foo')).toThrow( - 'Invalid key: The key must be a 65-byte, non-zero Buffer.', + 'Invalid key: The key must be a 65-byte, non-zero Uint8Array.', ); - expect(() => publicKeyToEthAddress(Buffer.alloc(64).fill(1))).toThrow( - 'Invalid key: The key must be a 65-byte, non-zero Buffer.', + expect(() => publicKeyToEthAddress(new Uint8Array(64).fill(1))).toThrow( + 'Invalid key: The key must be a 65-byte, non-zero Uint8Array.', ); }); }); diff --git a/src/derivers/bip32.ts b/src/derivers/bip32.ts index bd33e3b1..d1c72c85 100755 --- a/src/derivers/bip32.ts +++ b/src/derivers/bip32.ts @@ -1,8 +1,14 @@ import { keccak_256 as keccak256 } from '@noble/hashes/sha3'; import { hmac } from '@noble/hashes/hmac'; import { sha512 } from '@noble/hashes/sha512'; +import { + assert, + bytesToBigInt, + concatBytes, + hexToBytes, +} from '@metamask/utils'; import { BIP_32_HARDENED_OFFSET, BUFFER_KEY_LENGTH } from '../constants'; -import { bytesToNumber, hexStringToBuffer, isValidBufferKey } from '../utils'; +import { isValidBufferKey } from '../utils'; import { Curve, mod, secp256k1 } from '../curves'; import { SLIP10Node } from '../SLIP10Node'; import { DeriveChildKeyArgs, DerivedKeys } from '.'; @@ -18,10 +24,11 @@ import { DeriveChildKeyArgs, DerivedKeys } from '.'; * address. * @returns The Ethereum address corresponding to the given key. */ -export function privateKeyToEthAddress(key: Buffer) { - if (!Buffer.isBuffer(key) || !isValidBufferKey(key, BUFFER_KEY_LENGTH)) { - throw new Error('Invalid key: The key must be a 32-byte, non-zero Buffer.'); - } +export function privateKeyToEthAddress(key: Uint8Array) { + assert( + key instanceof Uint8Array && isValidBufferKey(key, BUFFER_KEY_LENGTH), + 'Invalid key: The key must be a 32-byte, non-zero Uint8Array.', + ); const publicKey = secp256k1.getPublicKey(key, false); return publicKeyToEthAddress(publicKey); @@ -38,15 +45,14 @@ export function privateKeyToEthAddress(key: Buffer) { * address. * @returns The Ethereum address corresponding to the given key. */ -export function publicKeyToEthAddress(key: Buffer) { - if ( - !Buffer.isBuffer(key) || - !isValidBufferKey(key, secp256k1.publicKeyLength) - ) { - throw new Error('Invalid key: The key must be a 65-byte, non-zero Buffer.'); - } - - return Buffer.from(keccak256(key.slice(1)).slice(-20)); +export function publicKeyToEthAddress(key: Uint8Array) { + assert( + key instanceof Uint8Array && + isValidBufferKey(key, secp256k1.publicKeyLength), + 'Invalid key: The key must be a 65-byte, non-zero Uint8Array.', + ); + + return keccak256(key.slice(1)).slice(-20); } /** @@ -123,7 +129,6 @@ export async function deriveChildKey({ const publicExtension = await derivePublicExtension({ parentPublicKey: node.compressedPublicKeyBuffer, childIndex, - curve, }); const { publicKey, chainCode } = generatePublicKey({ @@ -145,7 +150,7 @@ export async function deriveChildKey({ } type DeriveSecretExtensionArgs = { - privateKey: Buffer; + privateKey: Uint8Array; childIndex: number; isHardened: boolean; curve: Curve; @@ -166,33 +171,32 @@ async function deriveSecretExtension({ }: DeriveSecretExtensionArgs) { if (isHardened) { // Hardened child - const indexBuffer = Buffer.allocUnsafe(4); - indexBuffer.writeUInt32BE(childIndex + BIP_32_HARDENED_OFFSET, 0); - const pk = privateKey; - const zb = Buffer.alloc(1, 0); - return Buffer.concat([zb, pk, indexBuffer]); + const indexBytes = new Uint8Array(4); + const view = new DataView(indexBytes.buffer); + + view.setUint32(0, childIndex + BIP_32_HARDENED_OFFSET, false); + return concatBytes([new Uint8Array([0]), privateKey, indexBytes]); } // Normal child - const indexBuffer = Buffer.allocUnsafe(4); - indexBuffer.writeUInt32BE(childIndex, 0); const parentPublicKey = await curve.getPublicKey(privateKey, true); - return Buffer.concat([parentPublicKey, indexBuffer]); + return derivePublicExtension({ parentPublicKey, childIndex }); } type DerivePublicExtensionArgs = { - parentPublicKey: Buffer; + parentPublicKey: Uint8Array; childIndex: number; - curve: Curve; }; async function derivePublicExtension({ parentPublicKey, childIndex, }: DerivePublicExtensionArgs) { - const indexBuffer = Buffer.alloc(4); - indexBuffer.writeUInt32BE(childIndex, 0); - return Buffer.concat([parentPublicKey, indexBuffer]); + const indexBytes = new Uint8Array(4); + const view = new DataView(indexBytes.buffer); + + view.setUint32(0, childIndex, false); + return concatBytes([parentPublicKey, indexBytes]); } /** @@ -208,28 +212,30 @@ export function privateAdd( privateKeyBuffer: Uint8Array, tweakBuffer: Uint8Array, curve: Curve, -): Buffer { - const privateKey = bytesToNumber(privateKeyBuffer); - const tweak = bytesToNumber(tweakBuffer); +): Uint8Array { + const privateKey = bytesToBigInt(privateKeyBuffer); + const tweak = bytesToBigInt(tweakBuffer); if (tweak >= curve.curve.n) { throw new Error('Invalid tweak: Tweak is larger than the curve order.'); } const added = mod(privateKey + tweak, curve.curve.n); - if (!curve.isValidPrivateKey(added)) { + const bytes = hexToBytes(added.toString(16).padStart(64, '0')); + + if (!curve.isValidPrivateKey(bytes)) { throw new Error( 'Invalid private key or tweak: The resulting private key is invalid.', ); } - return hexStringToBuffer(added.toString(16).padStart(64, '0')); + return bytes; } type GenerateKeyArgs = { - privateKey: Buffer; - chainCode: Buffer; - secretExtension: Buffer; + privateKey: Uint8Array; + chainCode: Uint8Array; + secretExtension: Uint8Array; curve: Curve; }; @@ -244,10 +250,10 @@ async function generateKey({ chainCode, secretExtension, curve, -}: GenerateKeyArgs): Promise { +}: GenerateKeyArgs): Promise { const entropy = hmac(sha512, chainCode, secretExtension); - const keyMaterial = Buffer.from(entropy.slice(0, 32)); - const childChainCode = Buffer.from(entropy.slice(32)); + const keyMaterial = entropy.slice(0, 32); + const childChainCode = entropy.slice(32); // If curve is ed25519: The returned child key ki is parse256(IL). // https://github.com/satoshilabs/slips/blob/133ea52a8e43d338b98be208907e144277e44c0e/slip-0010.md#private-parent-key--private-child-key @@ -263,9 +269,9 @@ async function generateKey({ } type GeneratePublicKeyArgs = { - publicKey: Buffer; - chainCode: Buffer; - publicExtension: Buffer; + publicKey: Uint8Array; + chainCode: Uint8Array; + publicExtension: Uint8Array; curve: Curve; }; @@ -280,10 +286,10 @@ function generatePublicKey({ const childChainCode = entropy.slice(32); // This function may fail if the resulting key is invalid. - const childPublicKey = curve.publicAdd(publicKey, Buffer.from(keyMaterial)); + const childPublicKey = curve.publicAdd(publicKey, keyMaterial); return { - publicKey: Buffer.from(childPublicKey), - chainCode: Buffer.from(childChainCode), + publicKey: childPublicKey, + chainCode: childChainCode, }; } diff --git a/src/derivers/bip39.ts b/src/derivers/bip39.ts index 46785f0c..f907983b 100755 --- a/src/derivers/bip39.ts +++ b/src/derivers/bip39.ts @@ -1,4 +1,4 @@ -import { mnemonicToSeedSync } from '@scure/bip39'; +import { mnemonicToSeed } from '@scure/bip39'; import { hmac } from '@noble/hashes/hmac'; import { sha512 } from '@noble/hashes/sha512'; import { BIP39Node } from '../constants'; @@ -23,7 +23,7 @@ export async function deriveChildKey({ path, curve, }: DeriveChildKeyArgs): Promise { - return createBip39KeyFromSeed(Buffer.from(mnemonicToSeedSync(path)), curve); + return createBip39KeyFromSeed(await mnemonicToSeed(path), curve); } /** @@ -32,10 +32,10 @@ export async function deriveChildKey({ * @returns An object containing the corresponding BIP-39 master key and chain code. */ export async function createBip39KeyFromSeed( - seed: Buffer, + seed: Uint8Array, curve: Curve = secp256k1, ): Promise { - const key = Buffer.from(hmac(sha512, curve.secret, seed)); + const key = hmac(sha512, curve.secret, seed); const privateKey = key.slice(0, 32); const chainCode = key.slice(32); diff --git a/src/derivers/index.ts b/src/derivers/index.ts index 681746cc..aafb5fe8 100644 --- a/src/derivers/index.ts +++ b/src/derivers/index.ts @@ -7,9 +7,9 @@ export type DerivedKeys = { /** * The derived private key, can be undefined if public key derivation was used. */ - privateKey?: Buffer; - publicKey: Buffer; - chainCode: Buffer; + privateKey?: Uint8Array; + publicKey: Uint8Array; + chainCode: Uint8Array; }; export type DeriveChildKeyArgs = { diff --git a/src/extended-keys.test.ts b/src/extended-keys.test.ts index c6489bbd..ac12b273 100644 --- a/src/extended-keys.test.ts +++ b/src/extended-keys.test.ts @@ -1,3 +1,4 @@ +import { hexToBytes } from '@metamask/utils'; import { decodeExtendedKey, encodeExtendedKey, @@ -16,10 +17,10 @@ describe('decodeExtendedKey', () => { depth: 0, parentFingerprint: 0, index: 0, - chainCode: hexStringToBuffer( + chainCode: hexToBytes( '873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508', ), - publicKey: hexStringToBuffer( + publicKey: hexToBytes( '0439a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c23cbe7ded0e7ce6a594896b8f62888fdbc5c8821305e2ea42bf01e37300116281', ), version: PUBLIC_KEY_VERSION, diff --git a/src/extended-keys.ts b/src/extended-keys.ts index 6510c205..8a554486 100644 --- a/src/extended-keys.ts +++ b/src/extended-keys.ts @@ -23,17 +23,17 @@ type ExtendedKeyLike = { depth: number; parentFingerprint: number; index: number; - chainCode: Buffer; + chainCode: Uint8Array; }; type ExtendedPublicKey = ExtendedKeyLike & { version: typeof PUBLIC_KEY_VERSION; - publicKey: Buffer; + publicKey: Uint8Array; }; type ExtendedPrivateKey = ExtendedKeyLike & { version: typeof PRIVATE_KEY_VERSION; - privateKey: Buffer; + privateKey: Uint8Array; }; export type ExtendedKey = ExtendedPublicKey | ExtendedPrivateKey; @@ -55,12 +55,18 @@ export const decodeExtendedKey = (extendedKey: string): ExtendedKey => { ); } - const version = buffer.readUInt32BE(0); - const depth = buffer.readUInt8(4); + const view = new DataView( + buffer.buffer, + buffer.byteOffset, + buffer.byteLength, + ); + + const version = view.getUint32(0, false); + const depth = view.getUint8(4); validateBIP44Depth(depth); - const parentFingerprint = buffer.readUInt32BE(5); - const index = buffer.readUInt32BE(9); + const parentFingerprint = view.getUint32(5, false); + const index = view.getUint32(9, false); const chainCode = buffer.slice(13, 45); if (!isValidBufferKey(chainCode, 32)) { @@ -76,8 +82,10 @@ export const decodeExtendedKey = (extendedKey: string): ExtendedKey => { ); } + const keyView = new DataView(key.buffer, key.byteOffset, key.byteLength); + if (version === PUBLIC_KEY_VERSION) { - if (key.readUInt8(0) !== 0x02 && key.readUInt8(0) !== 0x03) { + if (keyView.getUint8(0) !== 0x02 && keyView.getUint8(0) !== 0x03) { throw new Error( `Invalid extended key: Public key must start with 0x02 or 0x03.`, ); @@ -94,7 +102,7 @@ export const decodeExtendedKey = (extendedKey: string): ExtendedKey => { } if (version === PRIVATE_KEY_VERSION) { - if (key.readUInt8(0) !== 0x00) { + if (keyView.getUint8(0) !== 0x00) { throw new Error( `Invalid extended key: Private key must start with 0x00.`, ); @@ -122,26 +130,28 @@ export const decodeExtendedKey = (extendedKey: string): ExtendedKey => { */ export const encodeExtendedKey = (extendedKey: ExtendedKey): string => { const { version, depth, parentFingerprint, index, chainCode } = extendedKey; - const buffer = Buffer.alloc(78); - buffer.writeUInt32BE(version, 0); - buffer.writeUInt8(depth, 4); - buffer.writeUInt32BE(parentFingerprint, 5); - buffer.writeUInt32BE(index, 9); + const bytes = new Uint8Array(78); + const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + + view.setUint32(0, version, false); + view.setUint8(4, depth); + view.setUint32(5, parentFingerprint, false); + view.setUint32(9, index, false); - chainCode.copy(buffer, 13); + bytes.set(chainCode, 13); if (extendedKey.version === PUBLIC_KEY_VERSION) { const { publicKey } = extendedKey; const compressedPublicKey = compressPublicKey(publicKey); - compressedPublicKey.copy(buffer, 45); + bytes.set(compressedPublicKey, 45); } if (extendedKey.version === PRIVATE_KEY_VERSION) { const { privateKey } = extendedKey; - privateKey.copy(buffer, 46); + bytes.set(privateKey, 46); } - return encodeBase58check(buffer); + return encodeBase58check(bytes); }; diff --git a/src/index.test.ts b/src/index.test.ts index 3baf1c89..235c43f7 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1,7 +1,6 @@ import { MAX_BIP_44_DEPTH, MIN_BIP_44_DEPTH, - PackageBuffer, SLIP10Node, secp256k1, ed25519, @@ -12,7 +11,6 @@ describe('index', () => { it('has expected exports', () => { expect(MAX_BIP_44_DEPTH).toStrictEqual(5); expect(MIN_BIP_44_DEPTH).toStrictEqual(0); - expect(PackageBuffer).toStrictEqual(Buffer); expect(SLIP10Node).toBeDefined(); expect(secp256k1).toBeDefined(); diff --git a/src/index.ts b/src/index.ts index 9a5b4761..365d1f9e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,9 +18,3 @@ export { BIP32Node, BIP39Node, } from './constants'; - -/** - * The {@link Buffer} accessible to `@metamask/key-tree`, re-exported in case - * of module resolution issues. - */ -export { Buffer as PackageBuffer } from 'buffer'; diff --git a/src/utils.test.ts b/src/utils.test.ts index fb99e8bd..63a02d83 100644 --- a/src/utils.test.ts +++ b/src/utils.test.ts @@ -1,3 +1,4 @@ +import { hexToBytes, stringToBytes } from '@metamask/utils'; import { getBIP32NodeToken, getBIP44ChangePathString, @@ -13,9 +14,6 @@ import { validateBIP32Index, isValidBIP32Index, isHardened, - stripHexPrefix, - isValidHexString, - bytesToNumber, encodeBase58check, decodeBase58check, } from './utils'; @@ -208,66 +206,39 @@ describe('isHardened', () => { }); }); -describe('stripHexPrefix', () => { - it('strips the hex prefix from a string', () => { - expect(stripHexPrefix('0x123')).toBe('123'); - expect(stripHexPrefix('0x')).toBe(''); - }); - - it('does not change a string without a prefix', () => { - expect(stripHexPrefix('123')).toBe('123'); - expect(stripHexPrefix('')).toBe(''); - }); -}); - -describe('isValidHexString', () => { - it('returns true if the string is a valid hex string', () => { - expect(isValidHexString('0x123')).toBe(true); - expect(isValidHexString('0x0')).toBe(true); - }); - - it('returns false if the string is not a valid hex string', () => { - expect(isValidHexString('')).toBe(false); - expect(isValidHexString('0x')).toBe(false); - expect(isValidHexString('0x0g')).toBe(false); - }); -}); - describe('hexStringToBuffer', () => { it('returns the same buffer if a buffer is passed', () => { - const buffer = Buffer.from('123', 'hex'); + const buffer = hexToBytes('123'); expect(hexStringToBuffer(buffer)).toBe(buffer); }); it('returns a buffer from a hex string', () => { - expect(hexStringToBuffer('1234')).toStrictEqual(Buffer.from('1234', 'hex')); - expect(hexStringToBuffer('0x1234')).toStrictEqual( - Buffer.from('1234', 'hex'), - ); + expect(hexStringToBuffer('1234')).toStrictEqual(hexToBytes('1234')); + expect(hexStringToBuffer('0x1234')).toStrictEqual(hexToBytes('1234')); }); it('throws if the string is not a valid hex string', () => { - expect(() => hexStringToBuffer('')).toThrow('Invalid hex string: "".'); - expect(() => hexStringToBuffer('0x')).toThrow('Invalid hex string: "0x".'); + expect(() => hexStringToBuffer('')).toThrow( + 'Value must be a hexadecimal string.', + ); + expect(() => hexStringToBuffer('0x0g')).toThrow( - 'Invalid hex string: "0x0g".', + 'Value must be a hexadecimal string.', ); }); }); describe('nullableHexStringToBuffer', () => { it('returns the same buffer if a buffer is passed', () => { - const buffer = Buffer.from('123', 'hex'); + const buffer = hexToBytes('123'); expect(nullableHexStringToBuffer(buffer)).toBe(buffer); }); it('returns a buffer for a hexadecimal string', () => { - expect(nullableHexStringToBuffer('1234')).toStrictEqual( - Buffer.from('1234', 'hex'), - ); + expect(nullableHexStringToBuffer('1234')).toStrictEqual(hexToBytes('1234')); expect(nullableHexStringToBuffer('0x1234')).toStrictEqual( - Buffer.from('1234', 'hex'), + hexToBytes('1234'), ); }); @@ -277,28 +248,24 @@ describe('nullableHexStringToBuffer', () => { it('throws if the string is not a valid hex string', () => { expect(() => nullableHexStringToBuffer('')).toThrow( - 'Invalid hex string: "".', - ); - - expect(() => nullableHexStringToBuffer('0x')).toThrow( - 'Invalid hex string: "0x".', + 'Value must be a hexadecimal string.', ); expect(() => nullableHexStringToBuffer('0x0g')).toThrow( - 'Invalid hex string: "0x0g".', + 'Value must be a hexadecimal string.', ); }); }); describe('isValidBufferKey', () => { it('checks the buffer length', () => { - expect(isValidBufferKey(Buffer.alloc(32).fill(1), 32)).toBe(true); - expect(isValidBufferKey(Buffer.alloc(31).fill(1), 32)).toBe(false); + expect(isValidBufferKey(new Uint8Array(32).fill(1), 32)).toBe(true); + expect(isValidBufferKey(new Uint8Array(31).fill(1), 32)).toBe(false); }); it('checks if the buffer has at least one non-zero byte', () => { - expect(isValidBufferKey(Buffer.alloc(32).fill(1), 32)).toBe(true); - expect(isValidBufferKey(Buffer.alloc(32).fill(0), 32)).toBe(false); + expect(isValidBufferKey(new Uint8Array(32).fill(1), 32)).toBe(true); + expect(isValidBufferKey(new Uint8Array(32).fill(0), 32)).toBe(false); }); }); @@ -317,13 +284,6 @@ describe('isValidInteger', () => { ); }); -describe('bytesToNumber', () => { - it('returns a bigint from a buffer', () => { - expect(bytesToNumber(Buffer.from('123', 'hex'))).toBe(BigInt(BigInt(18))); - expect(bytesToNumber(Buffer.from('456', 'hex'))).toBe(BigInt(BigInt(69))); - }); -}); - describe('getBuffer', () => { it('returns a buffer for a hexadecimal string', () => { expect(getBuffer('0x1234', 2)).toStrictEqual(hexStringToBuffer('1234')); @@ -348,14 +308,14 @@ describe('getBuffer', () => { describe('encodeBase58Check', () => { it('encodes a buffer with Base58check', () => { - expect(encodeBase58check(Buffer.from('foo bar'))).toBe('SQHFQMRT97ajZaP'); + expect(encodeBase58check(stringToBytes('foo bar'))).toBe('SQHFQMRT97ajZaP'); }); }); describe('decodeBase58Check', () => { it('decodes a Base58check encoded string', () => { expect(decodeBase58check('SQHFQMRT97ajZaP')).toStrictEqual( - Buffer.from('foo bar'), + stringToBytes('foo bar'), ); }); @@ -376,11 +336,11 @@ describe('getFingerprint', () => { }); it('throws if the public key is not a valid buffer', async () => { - expect(() => getFingerprint(Buffer.alloc(33).fill(0))).toThrow( + expect(() => getFingerprint(new Uint8Array(33).fill(0))).toThrow( 'Invalid public key: The key must be a 33-byte, non-zero Buffer.', ); - expect(() => getFingerprint(Buffer.alloc(65).fill(1))).toThrow( + expect(() => getFingerprint(new Uint8Array(65).fill(1))).toThrow( 'Invalid public key: The key must be a 33-byte, non-zero Buffer.', ); }); diff --git a/src/utils.ts b/src/utils.ts index cba9bf70..84d57d24 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,7 +1,7 @@ -import { bytesToHex } from '@noble/hashes/utils'; import { base58check as scureBase58check } from '@scure/base'; import { sha256 } from '@noble/hashes/sha256'; import { ripemd160 } from '@noble/hashes/ripemd160'; +import { hexToBytes } from '@metamask/utils'; import { BIP32Node, BIP44PurposeNodeToken, @@ -172,49 +172,25 @@ export function isHardened(bip32Token: string): boolean { return bip32Token.endsWith(`'`); } -/** - * @param hexString - The hexadecimal string to strip. - * @returns The hexadecimal string, without a `0x`-prefix, if any. - */ -export function stripHexPrefix(hexString: string): string { - return hexString.replace(/^0x/iu, ''); -} - -/** - * Tests whether the specified string is a valid hexadecimal string. The string - * may or may not be `0x`-prefixed, and the test is case-insensitive. - * - * @param hexString - The string to test. - * @returns Whether the specified string is a valid hexadecimal string. The - * string may or may not be `0x`-prefixed. - */ -export function isValidHexString(hexString: string): boolean { - return /^(?:0x)?[a-f0-9]+$/iu.test(hexString); -} - /** * @param hexString - The hexadecimal string to convert. - * @returns The {@link Buffer} corresponding to the hexadecimal string. + * @returns The `Uint8Array` corresponding to the hexadecimal string. */ -export function hexStringToBuffer(hexString: string | Buffer): Buffer { - if (Buffer.isBuffer(hexString)) { +export function hexStringToBuffer(hexString: string | Uint8Array): Uint8Array { + if (hexString instanceof Uint8Array) { return hexString; } - if (typeof hexString !== 'string' || !isValidHexString(hexString)) { - throw new Error(`Invalid hex string: "${hexString}".`); - } - - return Buffer.from(stripHexPrefix(hexString), 'hex'); + return hexToBytes(hexString); } /** * @param hexString - The hexadecimal string to convert. - * @returns The {@link Buffer} corresponding to the hexadecimal string. + * @returns The `Uint8Array` corresponding to the hexadecimal string. */ export function nullableHexStringToBuffer( - hexString?: string | Buffer, -): Buffer | undefined { + hexString?: string | Uint8Array, +): Uint8Array | undefined { if (hexString !== undefined) { return hexStringToBuffer(hexString); } @@ -223,15 +199,15 @@ export function nullableHexStringToBuffer( } /** - * Tests whether the specified {@link Buffer} is a valid BIP-32 key. + * Tests whether the specified `Uint8Array` is a valid BIP-32 key. * A valid buffer key is 64 bytes long and has at least one non-zero byte. * - * @param buffer - The {@link Buffer} to test. + * @param buffer - The `Uint8Array` to test. * @param expectedLength - The expected length of the buffer. * @returns Whether the buffer represents a valid BIP-32 key. */ export function isValidBufferKey( - buffer: Buffer, + buffer: Uint8Array, expectedLength: number, ): boolean { if (buffer.length !== expectedLength) { @@ -257,60 +233,46 @@ export function isValidInteger(value: unknown): value is number { } /** - * Get a BigInt from a byte array. - * - * @param bytes - The byte array to get the BigInt for. - * @returns The byte array as BigInt. - */ -export function bytesToNumber(bytes: Uint8Array): bigint { - return BigInt(`0x${bytesToHex(bytes)}`); -} - -/** - * Get a Buffer from a hexadecimal string or Buffer. Validates that the - * length of the Buffer matches the specified length, and that the buffer + * Get a `Uint8Array` from a hexadecimal string or `Uint8Array`. Validates that the + * length of the buffer matches the specified length, and that the buffer * is not empty. * - * @param value - The value to convert to a Buffer. - * @param length - The length to validate the Buffer against. + * @param value - The value to convert to a `Uint8Array`. + * @param length - The length to validate the `Uint8Array` against. */ -export function getBuffer(value: unknown, length: number): Buffer { - if (value instanceof Buffer) { +export function getBuffer(value: unknown, length: number): Uint8Array { + if (value instanceof Uint8Array) { validateBuffer(value, length); return value; } if (typeof value === 'string') { - if (!isValidHexString(value)) { - throw new Error( - `Invalid value: Must be a valid hex string of length: ${length * 2}.`, - ); - } - - const buffer = hexStringToBuffer(value); + const buffer = hexToBytes(value); validateBuffer(buffer, length); return buffer; } - throw new Error(`Invalid value: Expected a Buffer or hexadecimal string.`); + throw new Error( + `Invalid value: Expected an instance of Uint8Array or hexadecimal string.`, + ); } function validateBuffer( - buffer: Buffer, + buffer: Uint8Array, length: number, -): asserts buffer is Buffer { +): asserts buffer is Uint8Array { if (!isValidBufferKey(buffer, length)) { throw new Error(`Invalid value: Must be a non-zero ${length}-byte buffer.`); } } -export const decodeBase58check = (value: string): Buffer => { +export const decodeBase58check = (value: string): Uint8Array => { const base58Check = scureBase58check(sha256); try { - return Buffer.from(base58Check.decode(value)); + return base58Check.decode(value); } catch { throw new Error( `Invalid value: Value is not base58-encoded, or the checksum is invalid.`, @@ -318,7 +280,7 @@ export const decodeBase58check = (value: string): Buffer => { } }; -export const encodeBase58check = (value: Buffer): string => { +export const encodeBase58check = (value: Uint8Array): string => { const base58Check = scureBase58check(sha256); return base58Check.encode(value); @@ -329,12 +291,16 @@ export const encodeBase58check = (value: Buffer): string => { * * @param publicKey - The compressed public key to get the fingerprint for. */ -export const getFingerprint = (publicKey: Buffer): number => { +export const getFingerprint = (publicKey: Uint8Array): number => { if (!isValidBufferKey(publicKey, 33)) { throw new Error( `Invalid public key: The key must be a 33-byte, non-zero Buffer.`, ); } - return Buffer.from(ripemd160(sha256(publicKey))).readUInt32BE(0); + const bytes = ripemd160(sha256(publicKey)); + const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + + // The equivalent of `Buffer.readUInt32BE(0)`. + return view.getUint32(0, false); }; diff --git a/test/fixtures.ts b/test/fixtures.ts index a4f604b0..04d7a615 100644 --- a/test/fixtures.ts +++ b/test/fixtures.ts @@ -31,11 +31,11 @@ export default { // The state of the default branch as of 2021-10-19 'ethereumjs-wallet': { hexSeed: - '747f302d9c916698912d5f70be53a6cf53bc495803a5523d3a7c3afa2afba94ec3803f838b3e1929ab5481f9da35441372283690fdcf27372c38f40ba134fe03', + '0x747f302d9c916698912d5f70be53a6cf53bc495803a5523d3a7c3afa2afba94ec3803f838b3e1929ab5481f9da35441372283690fdcf27372c38f40ba134fe03', privateKey: - 'f29d6ddd6b0cd1fd59ed99900edd5a53e905b87dfe06824751010feb5228d960', + '0xf29d6ddd6b0cd1fd59ed99900edd5a53e905b87dfe06824751010feb5228d960', publicKey: - '04f7e989b55ebf3f9acfd32303e83069a9e4220bfc128f962325e6aa87e0f11f902a188c3f22f975c064a20c12b5523c53735f42467f2b83546869180abc42751e', + '0x04f7e989b55ebf3f9acfd32303e83069a9e4220bfc128f962325e6aa87e0f11f902a188c3f22f975c064a20c12b5523c53735f42467f2b83546869180abc42751e', address: '0xb9f89177a4ce589e6d18c33a9748bcc8063836df', // The path used is modified from the ethereumjs-wallet original, which // isn't BIP-44 compatible. Since we're testing against their @@ -52,49 +52,49 @@ export default { index: 0, address: '0xc5ba325f997531b5f0f50868913f0ce2fc0386bd', publicKey: - '0438e5105bf4d908b40743bd3fc0e8e4ac281872086bf3323dfb4459a8b147aaa74b2b6624479ce069d60ff41336ce7eb0613f66ee91ba72a7581144134d814624', + '0x0438e5105bf4d908b40743bd3fc0e8e4ac281872086bf3323dfb4459a8b147aaa74b2b6624479ce069d60ff41336ce7eb0613f66ee91ba72a7581144134d814624', }, { index: 1, address: '0x326aa42f2b600f624d800e109b1e146906bc8175', publicKey: - '04fcdae40d78db4aaa196c8f421f9d9243934f4abc69de95dd27522e275de7276b486b6219ad930775127a5645a226a716a52accc456cd93ea82f56ee98994cf6e', + '0x04fcdae40d78db4aaa196c8f421f9d9243934f4abc69de95dd27522e275de7276b486b6219ad930775127a5645a226a716a52accc456cd93ea82f56ee98994cf6e', }, { index: 5, address: '0x6d0cc8671c91559d5f2d43de9c33eee0497db7cd', publicKey: - '04226d57014fd0e9eea04a6de8e2071b111b42a102e416f21529698acfec7b78a0ba774dd957dfb6c71f3c597b7cb3ee9c08eeb48f7bf34a8dc24319d743339346', + '0x04226d57014fd0e9eea04a6de8e2071b111b42a102e416f21529698acfec7b78a0ba774dd957dfb6c71f3c597b7cb3ee9c08eeb48f7bf34a8dc24319d743339346', }, { index: 50, address: '0x7bf971adda7f4487ac8f3dbd7450463ff3624f94', publicKey: - '04c7fa0b4154bcb1e2d854c035ba591c3b87ccfbf3fafd0ed30585a1f843e79efcea470920b3fba70524b8a9854ddcfa05192de7d54154e28a8156b5d83a3a7883', + '0x04c7fa0b4154bcb1e2d854c035ba591c3b87ccfbf3fafd0ed30585a1f843e79efcea470920b3fba70524b8a9854ddcfa05192de7d54154e28a8156b5d83a3a7883', }, { index: 500, address: '0x564d7507d39a881d04bffc0120ebd331e7c41758', publicKey: - '0461091945ed21fa036f0e97b4135fc01fb936910989519ba9a8c1c0867f3b34fbe6941f8529d1771532d79fdb2060cecaa12f12323086aec6eeb2ba9a9d9af3e9', + '0x0461091945ed21fa036f0e97b4135fc01fb936910989519ba9a8c1c0867f3b34fbe6941f8529d1771532d79fdb2060cecaa12f12323086aec6eeb2ba9a9d9af3e9', }, { index: 5000, address: '0x7496ff062c1fe3e750dff9cbbe317558161ba6db', publicKey: - '04cceed14fef73e6c61e648761df3489e6cd87dfbcfa20241fd001675654ecb3d8a0d3b50410a9444de6d38af04f28add1ae12280889b5816dfc66a597cea539ec', + '0x04cceed14fef73e6c61e648761df3489e6cd87dfbcfa20241fd001675654ecb3d8a0d3b50410a9444de6d38af04f28add1ae12280889b5816dfc66a597cea539ec', }, { index: 4_999_999, address: '0xddf1f1a72a668d5014ec57a24019291fd2a00197', publicKey: - '04b1eed5ab048a7de8939c1a9536d04076982454d7883ec665e4e7da4d457f99842df19468193267e93ec3e4faa5be9602072a6aad69de0f1687a5f1ea57a93a4c', + '0x04b1eed5ab048a7de8939c1a9536d04076982454d7883ec665e4e7da4d457f99842df19468193267e93ec3e4faa5be9602072a6aad69de0f1687a5f1ea57a93a4c', }, { index: 5_000_000, address: '0x24dd12b9df5375f3b7fc5a539d4ac1bd2c16e9a0', publicKey: - '04e2ddbc99b6e0f8fc4e62242e375a49a8d856d6865607db474d444d4b729e28e3c80172acc9473b8ba6eaa7c893864589df35ca10d42ca9937cd6c77768871374', + '0x04e2ddbc99b6e0f8fc4e62242e375a49a8d856d6865607db474d444d4b729e28e3c80172acc9473b8ba6eaa7c893864589df35ca10d42ca9937cd6c77768871374', }, ], }, @@ -105,7 +105,7 @@ export default { bip32: [ // ===Test vector 1=== { - hexSeed: '000102030405060708090a0b0c0d0e0f', + hexSeed: '0x000102030405060708090a0b0c0d0e0f', keys: [ { path: { @@ -120,9 +120,9 @@ export default { extPrivKey: 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi', privateKey: - 'e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35', + '0xe8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35', publicKey: - '0439a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c23cbe7ded0e7ce6a594896b8f62888fdbc5c8821305e2ea42bf01e37300116281', + '0x0439a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c23cbe7ded0e7ce6a594896b8f62888fdbc5c8821305e2ea42bf01e37300116281', }, { path: { @@ -137,9 +137,9 @@ export default { extPrivKey: 'xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7', privateKey: - 'edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea', + '0xedb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea', publicKey: - '045a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc567f717885be239daadce76b568958305183ad616ff74ed4dc219a74c26d35f839', + '0x045a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc567f717885be239daadce76b568958305183ad616ff74ed4dc219a74c26d35f839', }, { path: { @@ -154,9 +154,9 @@ export default { extPrivKey: 'xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs', privateKey: - '3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368', + '0x3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368', publicKey: - '04501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c008794c1df8131b9ad1e1359965b3f3ee2feef0866be693729772be14be881ab', + '0x04501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c008794c1df8131b9ad1e1359965b3f3ee2feef0866be693729772be14be881ab', }, { path: { @@ -171,9 +171,9 @@ export default { extPrivKey: 'xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM', privateKey: - 'cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca', + '0xcbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca', publicKey: - '0457bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc24310ef3676384179e713be3115e93f34ac9a3933f6367aeb3081527ea74027b7', + '0x0457bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc24310ef3676384179e713be3115e93f34ac9a3933f6367aeb3081527ea74027b7', }, { path: { @@ -188,9 +188,9 @@ export default { extPrivKey: 'xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334', privateKey: - '0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4', + '0x0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4', publicKey: - '04e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d292728ad8d58a140050c1016e21f285636a580f4d2711b7fac3957a594ddf416a0', + '0x04e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d292728ad8d58a140050c1016e21f285636a580f4d2711b7fac3957a594ddf416a0', }, { path: { @@ -211,9 +211,9 @@ export default { extPrivKey: 'xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76', privateKey: - '471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8', + '0x471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8', publicKey: - '042a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011cf31cb47de7ccf6196d3a580d055837de7aa374e28c6c8a263e7b4512ceee362', + '0x042a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011cf31cb47de7ccf6196d3a580d055837de7aa374e28c6c8a263e7b4512ceee362', }, ], }, @@ -221,7 +221,7 @@ export default { // ===Test vector 2=== { hexSeed: - 'fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542', + '0xfffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542', keys: [ { path: { @@ -236,9 +236,9 @@ export default { extPrivKey: 'xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U', privateKey: - '4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e', + '0x4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e', publicKey: - '04cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a77bd3305d363c26f82c1e41c667e4b3561c06c60a2104d2b548e6dd059056aa51', + '0x04cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a77bd3305d363c26f82c1e41c667e4b3561c06c60a2104d2b548e6dd059056aa51', }, { path: { @@ -253,9 +253,9 @@ export default { extPrivKey: 'xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt', privateKey: - 'abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e', + '0xabe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e', publicKey: - '04fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea67a50538b6f7d8b5f7a1cc657efd267cde8cc1d8c0451d1340a0fb3642777544', + '0x04fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea67a50538b6f7d8b5f7a1cc657efd267cde8cc1d8c0451d1340a0fb3642777544', }, { path: { @@ -270,9 +270,9 @@ export default { extPrivKey: 'xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9', privateKey: - '877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93', + '0x877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93', publicKey: - '04c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b6c8bf5e8fbfc053205b45776963d148187d0aebf9c08bf2b253dc1cf5860fc19', + '0x04c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b6c8bf5e8fbfc053205b45776963d148187d0aebf9c08bf2b253dc1cf5860fc19', }, { path: { @@ -287,9 +287,9 @@ export default { extPrivKey: 'xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef', privateKey: - '704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7', + '0x704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7', publicKey: - '04a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9105b3150817d235e80ea17914dc9d6f542b1c5f4b16d8d98fe3c94fc0a67de89', + '0x04a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9105b3150817d235e80ea17914dc9d6f542b1c5f4b16d8d98fe3c94fc0a67de89', }, { path: { @@ -309,9 +309,9 @@ export default { extPrivKey: 'xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc', privateKey: - 'f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d', + '0xf1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d', publicKey: - '04d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ecb53a1b24eda1117d6864f1dbaf2f92345a1cb52c70036e2a424b37c3d829b0', + '0x04d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ecb53a1b24eda1117d6864f1dbaf2f92345a1cb52c70036e2a424b37c3d829b0', }, { path: { @@ -333,9 +333,9 @@ export default { extPrivKey: 'xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j', privateKey: - 'bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23', + '0xbb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23', publicKey: - '044d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c4597bb130cb16893607c6e7418c46be47b8f4a3ddbe5e6e71051393b1d673abe', + '0x044d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c4597bb130cb16893607c6e7418c46be47b8f4a3ddbe5e6e71051393b1d673abe', }, ], }, @@ -344,7 +344,7 @@ export default { // These vectors test for the retention of leading zeros. For more information, see: https://github.com/bitpay/bitcore-lib/issues/47 and https://github.com/iancoleman/bip39/issues/58 { hexSeed: - '4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be', + '0x4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be', keys: [ { path: { @@ -359,9 +359,9 @@ export default { extPrivKey: 'xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6', privateKey: - '00ddb80b067e0d4993197fe10f2657a844a384589847602d56f0c629c81aae32', + '0x00ddb80b067e0d4993197fe10f2657a844a384589847602d56f0c629c81aae32', publicKey: - '04683af1ba5743bdfc798cf814efeeab2735ec52d95eced528e692b8e34c4e5669d2f2686ced96d375a75298f07ed30751e2a3f45e2d184b268d02c8d5dd6fbdb5', + '0x04683af1ba5743bdfc798cf814efeeab2735ec52d95eced528e692b8e34c4e5669d2f2686ced96d375a75298f07ed30751e2a3f45e2d184b268d02c8d5dd6fbdb5', }, { path: { @@ -376,9 +376,9 @@ export default { extPrivKey: 'xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L', privateKey: - '491f7a2eebc7b57028e0d3faa0acda02e75c33b03c48fb288c41e2ea44e1daef', + '0x491f7a2eebc7b57028e0d3faa0acda02e75c33b03c48fb288c41e2ea44e1daef', publicKey: - '046557fdda1d5d43d79611f784780471f086d58e8126b8c40acb82272a7712e7f259a34ffdc4c82e5cb68a96ccc6cb53e8765527148d1a85b52dfb8953d8d001fc', + '0x046557fdda1d5d43d79611f784780471f086d58e8126b8c40acb82272a7712e7f259a34ffdc4c82e5cb68a96ccc6cb53e8765527148d1a85b52dfb8953d8d001fc', }, ], }, @@ -387,7 +387,7 @@ export default { // These vectors test for the retention of leading zeros. For more information, see: https://github.com/btcsuite/btcutil/issues/172 btcsuite/btcutil#172 { hexSeed: - '3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678', + '0x3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678', keys: [ { path: { @@ -402,9 +402,9 @@ export default { extPrivKey: 'xprv9s21ZrQH143K48vGoLGRPxgo2JNkJ3J3fqkirQC2zVdk5Dgd5w14S7fRDyHH4dWNHUgkvsvNDCkvAwcSHNAQwhwgNMgZhLtQC63zxwhQmRv', privateKey: - '12c0d59c7aa3a10973dbd3f478b65f2516627e3fe61e00c345be9a477ad2e215', + '0x12c0d59c7aa3a10973dbd3f478b65f2516627e3fe61e00c345be9a477ad2e215', publicKey: - '046f6fedc9240f61daa9c7144b682a430a3a1366576f840bf2d070101fcbc9a02d64f0ba4512324da4cb12cd1b7b09a3410ad2e88fa9c51067528b4a21edd1c820', + '0x046f6fedc9240f61daa9c7144b682a430a3a1366576f840bf2d070101fcbc9a02d64f0ba4512324da4cb12cd1b7b09a3410ad2e88fa9c51067528b4a21edd1c820', }, { path: { @@ -419,9 +419,9 @@ export default { extPrivKey: 'xprv9vB7xEWwNp9kh1wQRfCCQMnZUEG21LpbR9NPCNN1dwhiZkjjeGRnaALmPXCX7SgjFTiCTT6bXes17boXtjq3xLpcDjzEuGLQBM5ohqkao9G', privateKey: - '00d948e9261e41362a688b916f297121ba6bfb2274a3575ac0e456551dfd7f7e', + '0x00d948e9261e41362a688b916f297121ba6bfb2274a3575ac0e456551dfd7f7e', publicKey: - '049382d2b6003446792d2917f7ac4b3edf079a1a94dd4eb010dc25109dda680a9d2ea33616de0b194f4c2a246ecefaff985c15671b7600d9d06ba4d658a280a1a7', + '0x049382d2b6003446792d2917f7ac4b3edf079a1a94dd4eb010dc25109dda680a9d2ea33616de0b194f4c2a246ecefaff985c15671b7600d9d06ba4d658a280a1a7', }, { path: { @@ -436,9 +436,9 @@ export default { extPrivKey: 'xprv9xJocDuwtYCMNAo3Zw76WENQeAS6WGXQ55RCy7tDJ8oALr4FWkuVoHJeHVAcAqiZLE7Je3vZJHxspZdFHfnBEjHqU5hG1Jaj32dVoS6XLT1', privateKey: - '3a2086edd7d9df86c3487a5905a1712a9aa664bce8cc268141e07549eaa8661d', + '0x3a2086edd7d9df86c3487a5905a1712a9aa664bce8cc268141e07549eaa8661d', publicKey: - '042edaf9e591ee27f3c69c36221e3c54c38088ef34e93fbb9bb2d4d9b92364cbbd9fa61aa41b9e4a7ced425e125d074537314b7adfe59c2f98049ca763dbc0e613', + '0x042edaf9e591ee27f3c69c36221e3c54c38088ef34e93fbb9bb2d4d9b92364cbbd9fa61aa41b9e4a7ced425e125d074537314b7adfe59c2f98049ca763dbc0e613', }, ], }, @@ -452,51 +452,51 @@ export default { privateAdd: [ { privateKey: - '0000000000000000000000000000000000000000000000000000000000000001', + '0x0000000000000000000000000000000000000000000000000000000000000001', tweak: - '0000000000000000000000000000000000000000000000000000000000000001', + '0x0000000000000000000000000000000000000000000000000000000000000001', result: - '0000000000000000000000000000000000000000000000000000000000000002', + '0x0000000000000000000000000000000000000000000000000000000000000002', }, { privateKey: - '8b147e947559e2a1598f6f0c334512a318a17e2f7992110448f33e42b365c2b6', + '0x8b147e947559e2a1598f6f0c334512a318a17e2f7992110448f33e42b365c2b6', tweak: - 'e6a9bdd2ccbccdf4c65472338459df8888cc77fbf4ffcd0b9c35e36a68b24ae9', + '0xe6a9bdd2ccbccdf4c65472338459df8888cc77fbf4ffcd0b9c35e36a68b24ae9', result: - '71be3c674216b0961fe3e13fb79ef22ce6bf1944bf493dd42556c3204be1cc5e', + '0x71be3c674216b0961fe3e13fb79ef22ce6bf1944bf493dd42556c3204be1cc5e', }, { privateKey: - '28ae78e8c4674af70102b7ed86156e2563e5d53011f3cbd86c302d7a927b4a2d', + '0x28ae78e8c4674af70102b7ed86156e2563e5d53011f3cbd86c302d7a927b4a2d', tweak: - '116f2e9181d755d41ffe6b01f0bf2ddf45ca3300acb8dea7a8b436ebdc166207', + '0x116f2e9181d755d41ffe6b01f0bf2ddf45ca3300acb8dea7a8b436ebdc166207', result: - '3a1da77a463ea0cb210122ef76d49c04a9b00830beacaa8014e464666e91ac34', + '0x3a1da77a463ea0cb210122ef76d49c04a9b00830beacaa8014e464666e91ac34', }, { privateKey: - 'a03f6d00fde0ae947746099de9d8038558879fb074a7bf8912366f377e227d8b', + '0xa03f6d00fde0ae947746099de9d8038558879fb074a7bf8912366f377e227d8b', tweak: - 'e09c82be0eb3d7e8c1f22387b412b324805e17ffbc42beddfb4e498723a26ac8', + '0xe09c82be0eb3d7e8c1f22387b412b324805e17ffbc42beddfb4e498723a26ac8', result: - '80dbefbf0c94867d39382d259deab6ab1e36dac981a1de2b4db25a31d18ea712', + '0x80dbefbf0c94867d39382d259deab6ab1e36dac981a1de2b4db25a31d18ea712', }, { privateKey: - '81f0934c5b1e2ba3d3f929eb8b5a5b0afbb3e1ac73020644327d19464e14453f', + '0x81f0934c5b1e2ba3d3f929eb8b5a5b0afbb3e1ac73020644327d19464e14453f', tweak: - '7bce175ad49a5824ac09d0ef1ce66099a2a55bcdf89438283f69d86e60144af1', + '0x7bce175ad49a5824ac09d0ef1ce66099a2a55bcdf89438283f69d86e60144af1', result: - 'fdbeaaa72fb883c88002fadaa840bba49e593d7a6b963e6c71e6f1b4ae289030', + '0xfdbeaaa72fb883c88002fadaa840bba49e593d7a6b963e6c71e6f1b4ae289030', }, { privateKey: - 'fca181aa616897c330c1847dc0e10400016ebef97f43ecf593cd5ef7c4f105b7', + '0xfca181aa616897c330c1847dc0e10400016ebef97f43ecf593cd5ef7c4f105b7', tweak: - '33b0309878b3100d4b7652361e0efe72a482a7a5009d3ce7f5fd069db81540a0', + '0x33b0309878b3100d4b7652361e0efe72a482a7a5009d3ce7f5fd069db81540a0', result: - '3051b242da1ba7d07c37d6b3def00273eb4289b7d09889a1c9f80708acd00516', + '0x3051b242da1ba7d07c37d6b3def00273eb4289b7d09889a1c9f80708acd00516', }, ], }, @@ -506,7 +506,7 @@ export default { // The state of the default branch as of 2022-03-17 slip10: [ { - hexSeed: '000102030405060708090a0b0c0d0e0f', + hexSeed: '0x000102030405060708090a0b0c0d0e0f', keys: [ { path: { @@ -517,9 +517,9 @@ export default { theirs: 'm', }, privateKey: - '2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7', + '0x2b4be7f19ee27bbf30c667b642d5f4aa69fd169872f8fc3059c08ebae2eb19e7', publicKey: - '00a4b2856bfec510abab89753fac1ac0e1112364e7d250545963f135f2a33188ed', + '0x00a4b2856bfec510abab89753fac1ac0e1112364e7d250545963f135f2a33188ed', }, { path: { @@ -530,9 +530,9 @@ export default { theirs: `m/0'`, }, privateKey: - '68e0fe46dfb67e368c75379acec591dad19df3cde26e63b93a8e704f1dade7a3', + '0x68e0fe46dfb67e368c75379acec591dad19df3cde26e63b93a8e704f1dade7a3', publicKey: - '008c8a13df77a28f3445213a0f432fde644acaa215fc72dcdf300d5efaa85d350c', + '0x008c8a13df77a28f3445213a0f432fde644acaa215fc72dcdf300d5efaa85d350c', }, { path: { @@ -543,9 +543,9 @@ export default { theirs: `m/0'/1'`, }, privateKey: - 'b1d0bad404bf35da785a64ca1ac54b2617211d2777696fbffaf208f746ae84f2', + '0xb1d0bad404bf35da785a64ca1ac54b2617211d2777696fbffaf208f746ae84f2', publicKey: - '001932a5270f335bed617d5b935c80aedb1a35bd9fc1e31acafd5372c30f5c1187', + '0x001932a5270f335bed617d5b935c80aedb1a35bd9fc1e31acafd5372c30f5c1187', }, { path: { @@ -556,9 +556,9 @@ export default { theirs: `m/0'/1'/2'`, }, privateKey: - '92a5b23c0b8a99e37d07df3fb9966917f5d06e02ddbd909c7e184371463e9fc9', + '0x92a5b23c0b8a99e37d07df3fb9966917f5d06e02ddbd909c7e184371463e9fc9', publicKey: - '00ae98736566d30ed0e9d2f4486a64bc95740d89c7db33f52121f8ea8f76ff0fc1', + '0x00ae98736566d30ed0e9d2f4486a64bc95740d89c7db33f52121f8ea8f76ff0fc1', }, { path: { @@ -569,9 +569,9 @@ export default { theirs: `m/0'/1'/2'/2'`, }, privateKey: - '30d1dc7e5fc04c31219ab25a27ae00b50f6fd66622f6e9c913253d6511d1e662', + '0x30d1dc7e5fc04c31219ab25a27ae00b50f6fd66622f6e9c913253d6511d1e662', publicKey: - '008abae2d66361c879b900d204ad2cc4984fa2aa344dd7ddc46007329ac76c429c', + '0x008abae2d66361c879b900d204ad2cc4984fa2aa344dd7ddc46007329ac76c429c', }, { path: { @@ -588,15 +588,15 @@ export default { theirs: `m/0'/1'/2'/2'/1000000000'`, }, privateKey: - '8f94d394a8e8fd6b1bc2f3f49f5c47e385281d5c17e65324b0f62483e37e8793', + '0x8f94d394a8e8fd6b1bc2f3f49f5c47e385281d5c17e65324b0f62483e37e8793', publicKey: - '003c24da049451555d51a7014a37337aa4e12d41e485abccfa46b47dfb2af54b7a', + '0x003c24da049451555d51a7014a37337aa4e12d41e485abccfa46b47dfb2af54b7a', }, ], }, { hexSeed: - 'fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542', + '0xfffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542', keys: [ { path: { @@ -607,9 +607,9 @@ export default { theirs: 'm', }, privateKey: - '171cb88b1b3c1db25add599712e36245d75bc65a1a5c9e18d76f9f2b1eab4012', + '0x171cb88b1b3c1db25add599712e36245d75bc65a1a5c9e18d76f9f2b1eab4012', publicKey: - '008fe9693f8fa62a4305a140b9764c5ee01e455963744fe18204b4fb948249308a', + '0x008fe9693f8fa62a4305a140b9764c5ee01e455963744fe18204b4fb948249308a', }, { path: { @@ -620,9 +620,9 @@ export default { theirs: `m/0'`, }, privateKey: - '1559eb2bbec5790b0c65d8693e4d0875b1747f4970ae8b650486ed7470845635', + '0x1559eb2bbec5790b0c65d8693e4d0875b1747f4970ae8b650486ed7470845635', publicKey: - '0086fab68dcb57aa196c77c5f264f215a112c22a912c10d123b0d03c3c28ef1037', + '0x0086fab68dcb57aa196c77c5f264f215a112c22a912c10d123b0d03c3c28ef1037', }, { path: { @@ -633,9 +633,9 @@ export default { theirs: `m/0'/2147483647'`, }, privateKey: - 'ea4f5bfe8694d8bb74b7b59404632fd5968b774ed545e810de9c32a4fb4192f4', + '0xea4f5bfe8694d8bb74b7b59404632fd5968b774ed545e810de9c32a4fb4192f4', publicKey: - '005ba3b9ac6e90e83effcd25ac4e58a1365a9e35a3d3ae5eb07b9e4d90bcf7506d', + '0x005ba3b9ac6e90e83effcd25ac4e58a1365a9e35a3d3ae5eb07b9e4d90bcf7506d', }, { path: { @@ -646,9 +646,9 @@ export default { theirs: `m/0'/2147483647'/1'`, }, privateKey: - '3757c7577170179c7868353ada796c839135b3d30554bbb74a4b1e4a5a58505c', + '0x3757c7577170179c7868353ada796c839135b3d30554bbb74a4b1e4a5a58505c', publicKey: - '002e66aa57069c86cc18249aecf5cb5a9cebbfd6fadeab056254763874a9352b45', + '0x002e66aa57069c86cc18249aecf5cb5a9cebbfd6fadeab056254763874a9352b45', }, { path: { @@ -664,9 +664,9 @@ export default { theirs: `m/0'/2147483647'/1'/2147483646'`, }, privateKey: - '5837736c89570de861ebc173b1086da4f505d4adb387c6a1b1342d5e4ac9ec72', + '0x5837736c89570de861ebc173b1086da4f505d4adb387c6a1b1342d5e4ac9ec72', publicKey: - '00e33c0f7d81d843c572275f287498e8d408654fdf0d1e065b84e2e6f157aab09b', + '0x00e33c0f7d81d843c572275f287498e8d408654fdf0d1e065b84e2e6f157aab09b', }, { path: { @@ -683,9 +683,9 @@ export default { theirs: `m/0'/2147483647'/1'/2147483646'/2'`, }, privateKey: - '551d333177df541ad876a60ea71f00447931c0a9da16f227c11ea080d7391b8d', + '0x551d333177df541ad876a60ea71f00447931c0a9da16f227c11ea080d7391b8d', publicKey: - '0047150c75db263559a70d5778bf36abbab30fb061ad69f69ece61a72b0cfa4fc0', + '0x0047150c75db263559a70d5778bf36abbab30fb061ad69f69ece61a72b0cfa4fc0', }, ], }, @@ -696,9 +696,9 @@ export default { // Fixtures generated by running the tests and logging the results. 'ed25519-hd-key': { hexSeed: - 'fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542', + '0xfffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542', privateKey: - 'd3de0cf6f12d2c916530a9871c16d0429f3f0152e22e260527a4769fddc1bba8', + '0xd3de0cf6f12d2c916530a9871c16d0429f3f0152e22e260527a4769fddc1bba8', // The path used is modified from the ed25519-hd-key original, which // isn't BIP-44 compatible. Since we're testing against their // implementation, not any reference values, this is fine. @@ -713,58 +713,58 @@ export default { { index: 0, privateKey: - '5ff1d76d708c8db54ded88f0f00fd60105d609beb029f50b1051117ca36a61e1', + '0x5ff1d76d708c8db54ded88f0f00fd60105d609beb029f50b1051117ca36a61e1', publicKey: - '001fd3196b4db863989445c760c9e65de4ce5cebdada0e4ead00e9be44a99ea7f3', + '0x001fd3196b4db863989445c760c9e65de4ce5cebdada0e4ead00e9be44a99ea7f3', }, { index: 1, privateKey: - '1ae261442406e5f4e87efac331bce3a25016957133ada46d82579c11e6108fc3', + '0x1ae261442406e5f4e87efac331bce3a25016957133ada46d82579c11e6108fc3', publicKey: - '009ae7a413c01359fe1d525ca446ebc974c97e535061564da577c6ef55c09d057e', + '0x009ae7a413c01359fe1d525ca446ebc974c97e535061564da577c6ef55c09d057e', }, { index: 5, privateKey: - '344d6bc78531985dd4220faa61bfb81653043e171f64d01c36de5a0ef39f9ede', + '0x344d6bc78531985dd4220faa61bfb81653043e171f64d01c36de5a0ef39f9ede', publicKey: - '000ab89e1f22d9162e0e3f02736d5c704c95faba6ce2dce72d121852172da4b1e4', + '0x000ab89e1f22d9162e0e3f02736d5c704c95faba6ce2dce72d121852172da4b1e4', }, { index: 50, privateKey: - '3468ee8024444e88781b2a5c92973ec965f43f8715414bac3e1b7f46589f41d5', + '0x3468ee8024444e88781b2a5c92973ec965f43f8715414bac3e1b7f46589f41d5', publicKey: - '00fd4f06acb57dba0c1cffc12e9241d4f9c5afebce724b1b84124e99dbeeb63ae9', + '0x00fd4f06acb57dba0c1cffc12e9241d4f9c5afebce724b1b84124e99dbeeb63ae9', }, { index: 500, privateKey: - '557676494a3b1309487dd990e12ccb22a0c3195ba696afdc96a48b65171f804d', + '0x557676494a3b1309487dd990e12ccb22a0c3195ba696afdc96a48b65171f804d', publicKey: - '00ee6fb077beb5bd25db75bed73fa3e0e6fa1a1a4a3b912c84722afdfe2c0cabfe', + '0x00ee6fb077beb5bd25db75bed73fa3e0e6fa1a1a4a3b912c84722afdfe2c0cabfe', }, { index: 5000, privateKey: - '5f0df48ccabf174f49a74ec14b518933b7b939f45ace2a4858d0038dfa5ed8dc', + '0x5f0df48ccabf174f49a74ec14b518933b7b939f45ace2a4858d0038dfa5ed8dc', publicKey: - '00ec36e172507304eebaeb451aaf329f1d6da7b77501a33e2cfa6700bd5bf0815f', + '0x00ec36e172507304eebaeb451aaf329f1d6da7b77501a33e2cfa6700bd5bf0815f', }, { index: 4_999_999, privateKey: - '5e65e057d8324c547ba3fe5eec1ae627c503ea6001dca3f2c077bb9d673d0fbf', + '0x5e65e057d8324c547ba3fe5eec1ae627c503ea6001dca3f2c077bb9d673d0fbf', publicKey: - '009dc2f2dc4434dd8fd7c9728ca7d55c3f15f679da8fd6522d6b514f20d8f27c21', + '0x009dc2f2dc4434dd8fd7c9728ca7d55c3f15f679da8fd6522d6b514f20d8f27c21', }, { index: 5_000_000, privateKey: - '759d3e66b20d6f057d1e0873e26430cdce67d0dfc160ecfe36acefe58ec1cb48', + '0x759d3e66b20d6f057d1e0873e26430cdce67d0dfc160ecfe36acefe58ec1cb48', publicKey: - '005cb94d2247fc84176fe7a43a7ce530b1064642acaf3fb61987c22f8638acf2d8', + '0x005cb94d2247fc84176fe7a43a7ce530b1064642acaf3fb61987c22f8638acf2d8', }, ], }, diff --git a/yarn.lock b/yarn.lock index 7fd11bb9..6abe0d05 100644 --- a/yarn.lock +++ b/yarn.lock @@ -828,6 +828,7 @@ __metadata: "@metamask/eslint-config-jest": ^8.0.0 "@metamask/eslint-config-nodejs": ^8.0.0 "@metamask/eslint-config-typescript": ^8.0.0 + "@metamask/utils": ^3.2.0 "@noble/ed25519": ^1.6.0 "@noble/hashes": ^1.0.0 "@noble/secp256k1": ^1.5.5 @@ -854,6 +855,18 @@ __metadata: languageName: unknown linkType: soft +"@metamask/utils@npm:^3.2.0": + version: 3.2.0 + resolution: "@metamask/utils@npm:3.2.0" + dependencies: + "@types/debug": ^4.1.7 + debug: ^4.3.4 + fast-deep-equal: ^3.1.3 + superstruct: ^0.16.5 + checksum: 99adcbd273c69075628913259f8c3fb843291898eba813f4f5fe0bfc060ae5955e2c69e70e15b04156793f8d84edd077d1fac3f8c3927e067d0f311eef9d4469 + languageName: node + linkType: hard + "@noble/ed25519@npm:^1.6.0": version: 1.7.0 resolution: "@noble/ed25519@npm:1.7.0" @@ -1040,6 +1053,15 @@ __metadata: languageName: node linkType: hard +"@types/debug@npm:^4.1.7": + version: 4.1.7 + resolution: "@types/debug@npm:4.1.7" + dependencies: + "@types/ms": "*" + checksum: 0a7b89d8ed72526858f0b61c6fd81f477853e8c4415bb97f48b1b5545248d2ae389931680b94b393b993a7cfe893537a200647d93defe6d87159b96812305adc + languageName: node + linkType: hard + "@types/glob@npm:^7.1.1": version: 7.2.0 resolution: "@types/glob@npm:7.2.0" @@ -1115,6 +1137,13 @@ __metadata: languageName: node linkType: hard +"@types/ms@npm:*": + version: 0.7.31 + resolution: "@types/ms@npm:0.7.31" + checksum: daadd354aedde024cce6f5aa873fefe7b71b22cd0e28632a69e8b677aeb48ae8caa1c60e5919bb781df040d116b01cb4316335167a3fc0ef6a63fa3614c0f6da + languageName: node + linkType: hard + "@types/node@npm:*": version: 18.7.15 resolution: "@types/node@npm:18.7.15" @@ -6057,6 +6086,13 @@ __metadata: languageName: node linkType: hard +"superstruct@npm:^0.16.5": + version: 0.16.5 + resolution: "superstruct@npm:0.16.5" + checksum: 9f843c38695b584a605ae9b028629de18a85bd0dca0e9449b4ab98bb7b9ac3d82599870acbab9fbd2ee454c6b187af7e61562e252dfadabd974191ab4ab2e3ce + languageName: node + linkType: hard + "supports-color@npm:^5.3.0": version: 5.5.0 resolution: "supports-color@npm:5.5.0"