@@ -3,7 +3,10 @@ import { SnapCaveatType } from '@metamask/snaps-utils';
33import {
44 MOCK_SNAP_ID ,
55 TEST_SECRET_RECOVERY_PHRASE_BYTES ,
6+ TEST_SECRET_RECOVERY_PHRASE_SEED_BYTES ,
67} from '@metamask/snaps-utils/test-utils' ;
8+ import { hmac } from '@noble/hashes/hmac' ;
9+ import { sha512 } from '@noble/hashes/sha512' ;
710
811import {
912 getBip32EntropyBuilder ,
@@ -13,6 +16,7 @@ import {
1316describe ( 'specificationBuilder' , ( ) => {
1417 const methodHooks = {
1518 getMnemonic : jest . fn ( ) ,
19+ getMnemonicSeed : jest . fn ( ) ,
1620 getUnlockPromise : jest . fn ( ) ,
1721 getClientCryptography : jest . fn ( ) ,
1822 } ;
@@ -66,12 +70,16 @@ describe('getBip32EntropyImplementation', () => {
6670 const getMnemonic = jest
6771 . fn ( )
6872 . mockResolvedValue ( TEST_SECRET_RECOVERY_PHRASE_BYTES ) ;
73+ const getMnemonicSeed = jest
74+ . fn ( )
75+ . mockResolvedValue ( TEST_SECRET_RECOVERY_PHRASE_SEED_BYTES ) ;
6976 const getClientCryptography = jest . fn ( ) . mockReturnValue ( { } ) ;
7077
7178 expect (
7279 await getBip32EntropyImplementation ( {
7380 getUnlockPromise,
7481 getMnemonic,
82+ getMnemonicSeed,
7583 getClientCryptography,
7684 // @ts -expect-error Missing other required properties.
7785 } ) ( {
@@ -97,12 +105,16 @@ describe('getBip32EntropyImplementation', () => {
97105 const getMnemonic = jest
98106 . fn ( )
99107 . mockResolvedValue ( TEST_SECRET_RECOVERY_PHRASE_BYTES ) ;
108+ const getMnemonicSeed = jest
109+ . fn ( )
110+ . mockResolvedValue ( TEST_SECRET_RECOVERY_PHRASE_SEED_BYTES ) ;
100111 const getClientCryptography = jest . fn ( ) . mockReturnValue ( { } ) ;
101112
102113 expect (
103114 await getBip32EntropyImplementation ( {
104115 getUnlockPromise,
105116 getMnemonic,
117+ getMnemonicSeed,
106118 getClientCryptography,
107119 // @ts -expect-error Missing other required properties.
108120 } ) ( {
@@ -131,13 +143,17 @@ describe('getBip32EntropyImplementation', () => {
131143 const getMnemonic = jest
132144 . fn ( )
133145 . mockResolvedValue ( TEST_SECRET_RECOVERY_PHRASE_BYTES ) ;
146+ const getMnemonicSeed = jest
147+ . fn ( )
148+ . mockResolvedValue ( TEST_SECRET_RECOVERY_PHRASE_SEED_BYTES ) ;
134149
135150 const getClientCryptography = jest . fn ( ) . mockReturnValue ( { } ) ;
136151
137152 expect (
138153 await getBip32EntropyImplementation ( {
139154 getUnlockPromise,
140155 getMnemonic,
156+ getMnemonicSeed,
141157 getClientCryptography,
142158 // @ts -expect-error Missing other required properties.
143159 } ) ( {
@@ -166,13 +182,17 @@ describe('getBip32EntropyImplementation', () => {
166182 const getMnemonic = jest
167183 . fn ( )
168184 . mockResolvedValue ( TEST_SECRET_RECOVERY_PHRASE_BYTES ) ;
185+ const getMnemonicSeed = jest
186+ . fn ( )
187+ . mockResolvedValue ( TEST_SECRET_RECOVERY_PHRASE_SEED_BYTES ) ;
169188
170189 const getClientCryptography = jest . fn ( ) . mockReturnValue ( { } ) ;
171190
172191 expect (
173192 await getBip32EntropyImplementation ( {
174193 getUnlockPromise,
175194 getMnemonic,
195+ getMnemonicSeed,
176196 getClientCryptography,
177197 // @ts -expect-error Missing other required properties.
178198 } ) ( {
@@ -200,6 +220,53 @@ describe('getBip32EntropyImplementation', () => {
200220 const getMnemonic = jest
201221 . fn ( )
202222 . mockImplementation ( ( ) => TEST_SECRET_RECOVERY_PHRASE_BYTES ) ;
223+ const getMnemonicSeed = jest
224+ . fn ( )
225+ . mockResolvedValue ( TEST_SECRET_RECOVERY_PHRASE_SEED_BYTES ) ;
226+
227+ const getUnlockPromise = jest . fn ( ) ;
228+ const getClientCryptography = jest . fn ( ) . mockReturnValue ( { } ) ;
229+
230+ expect (
231+ await getBip32EntropyImplementation ( {
232+ getUnlockPromise,
233+ getMnemonic,
234+ getMnemonicSeed,
235+ getClientCryptography,
236+ } ) ( {
237+ method : 'snap_getBip32Entropy' ,
238+ context : { origin : MOCK_SNAP_ID } ,
239+ params : {
240+ path : [ 'm' , "44'" , "1'" ] ,
241+ curve : 'ed25519Bip32' ,
242+ source : 'source-id' ,
243+ } ,
244+ } ) ,
245+ ) . toMatchInlineSnapshot ( `
246+ {
247+ "chainCode": "0x25ebfafe30b0178f7b95b9a8580c386800344f4820697cc5e8cac4afb6d91d01",
248+ "curve": "ed25519Bip32",
249+ "depth": 2,
250+ "index": 2147483649,
251+ "masterFingerprint": 1587894111,
252+ "network": "mainnet",
253+ "parentFingerprint": 1429088440,
254+ "privateKey": "0x98a1e11f532dc7c8130246d6bce0bea5412cb333862f7de2cf94cbaedfbc734e7c6bcc37dd7270a54709ff022dbae6b9fa416a25ac760ccfeff157a469eab0a3",
255+ "publicKey": "0x5af28295d600e796ed0b4e51ec8a0f3d5b1f8a647d3ba7a56d7eb0941561d537",
256+ }
257+ ` ) ;
258+
259+ expect ( getMnemonic ) . toHaveBeenCalledWith ( 'source-id' ) ;
260+ expect ( getMnemonicSeed ) . not . toHaveBeenCalled ( ) ;
261+ } ) ;
262+
263+ it ( 'calls `getMnemonicSeed` with a different entropy source' , async ( ) => {
264+ const getMnemonic = jest
265+ . fn ( )
266+ . mockImplementation ( ( ) => TEST_SECRET_RECOVERY_PHRASE_BYTES ) ;
267+ const getMnemonicSeed = jest
268+ . fn ( )
269+ . mockResolvedValue ( TEST_SECRET_RECOVERY_PHRASE_SEED_BYTES ) ;
203270
204271 const getUnlockPromise = jest . fn ( ) ;
205272 const getClientCryptography = jest . fn ( ) . mockReturnValue ( { } ) ;
@@ -208,6 +275,7 @@ describe('getBip32EntropyImplementation', () => {
208275 await getBip32EntropyImplementation ( {
209276 getUnlockPromise,
210277 getMnemonic,
278+ getMnemonicSeed,
211279 getClientCryptography,
212280 } ) ( {
213281 method : 'snap_getBip32Entropy' ,
@@ -232,44 +300,53 @@ describe('getBip32EntropyImplementation', () => {
232300 }
233301 ` ) ;
234302
235- expect ( getMnemonic ) . toHaveBeenCalledWith ( 'source-id' ) ;
303+ expect ( getMnemonicSeed ) . toHaveBeenCalledWith ( 'source-id' ) ;
304+ expect ( getMnemonic ) . not . toHaveBeenCalled ( ) ;
236305 } ) ;
237306
238307 it ( 'uses custom client cryptography functions' , async ( ) => {
239308 const getUnlockPromise = jest . fn ( ) . mockResolvedValue ( undefined ) ;
240309 const getMnemonic = jest
241310 . fn ( )
242311 . mockResolvedValue ( TEST_SECRET_RECOVERY_PHRASE_BYTES ) ;
312+ const getMnemonicSeed = jest
313+ . fn ( )
314+ . mockResolvedValue ( TEST_SECRET_RECOVERY_PHRASE_SEED_BYTES ) ;
243315
244- const pbkdf2Sha512 = jest . fn ( ) . mockResolvedValue ( new Uint8Array ( 64 ) ) ;
316+ const hmacSha512 = jest
317+ . fn ( )
318+ . mockImplementation ( ( key : Uint8Array , data : Uint8Array ) =>
319+ hmac ( sha512 , key , data ) ,
320+ ) ;
245321 const getClientCryptography = jest . fn ( ) . mockReturnValue ( {
246- pbkdf2Sha512 ,
322+ hmacSha512 ,
247323 } ) ;
248324
249325 expect (
250326 await getBip32EntropyImplementation ( {
251327 getUnlockPromise,
252328 getMnemonic,
329+ getMnemonicSeed,
253330 getClientCryptography,
254331 // @ts -expect-error Missing other required properties.
255332 } ) ( {
256333 params : { path : [ 'm' , "44'" , "1'" ] , curve : 'secp256k1' } ,
257334 } ) ,
258335 ) . toMatchInlineSnapshot ( `
259336 {
260- "chainCode": "0x8472428420c7fd8ef7280545bb6d2bde1d7c6b490556ccd59895f242716388d1 ",
337+ "chainCode": "0x50ccfa58a885b48b5eed09486b3948e8454f34856fb81da5d7b8519d7997abd1 ",
261338 "curve": "secp256k1",
262339 "depth": 2,
263340 "index": 2147483649,
264- "masterFingerprint": 3276136937 ,
341+ "masterFingerprint": 1404659567 ,
265342 "network": "mainnet",
266- "parentFingerprint": 1981505209 ,
267- "privateKey": "0x71d945aba22cd337ff26a107073ae2606dee5dbf7ecfe5c25870b8eaf62b9f1b ",
268- "publicKey": "0x0491c4b234ca9b394f40d90f09092e04fd3bca2aa68c57e1311b25acfd972c5a6fc7ffd19e7812127473aa2bd827917b6ec7b57bec73cf022fc1f1fa0593f48770 ",
343+ "parentFingerprint": 1829122711 ,
344+ "privateKey": "0xc73cedb996e7294f032766853a8b7ba11ab4ce9755fc052f2f7b9000044c99af ",
345+ "publicKey": "0x048e129862c1de5ca86468add43b001d32fd34b8113de716ecd63fa355b7f1165f0e76f5dc6095100f9fdaa76ddf28aa3f21406ac5fda7c71ffbedb45634fe2ceb ",
269346 }
270347 ` ) ;
271348
272- expect ( pbkdf2Sha512 ) . toHaveBeenCalledTimes ( 1 ) ;
349+ expect ( hmacSha512 ) . toHaveBeenCalledTimes ( 3 ) ;
273350 } ) ;
274351 } ) ;
275352} ) ;
0 commit comments