Skip to content

Commit b110b32

Browse files
committed
test: memoized keychain
1 parent 1577447 commit b110b32

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import stableStringify from 'json-stable-stringify'
2+
import { mnemonicToSeed } from 'bip39'
3+
import BJSON from 'buffer-json'
4+
5+
import KeyIdentifier from '@exodus/key-identifier'
6+
import memoizedKeychainDefinition from '../memoized-keychain'
7+
import { getSeedId } from '../crypto/seed-id'
8+
9+
const mockStorage = {
10+
get: jest.fn(),
11+
set: jest.fn(),
12+
}
13+
14+
const seed = mnemonicToSeed(
15+
'menu memory fury language physical wonder dog valid smart edge decrease worth'
16+
)
17+
18+
const seedId = getSeedId(seed)
19+
20+
const keyIdentifierEthereum0 = new KeyIdentifier({
21+
derivationAlgorithm: 'BIP32',
22+
derivationPath: "m/44'/60'/0'/0/0",
23+
assetName: 'ethereum',
24+
})
25+
26+
const storage = mockStorage
27+
28+
describe('memoizedKeychain', () => {
29+
let memoizedKeychain
30+
31+
beforeEach(() => {
32+
mockStorage.get.mockResolvedValue(null)
33+
memoizedKeychain = memoizedKeychainDefinition.factory({ storage })
34+
memoizedKeychain.addSeed(seed)
35+
jest.clearAllMocks()
36+
})
37+
38+
it('should construct correctly', () => {
39+
expect(() => memoizedKeychainDefinition.factory({ storage })).not.toThrow()
40+
})
41+
42+
it('should clone correctly', () => {
43+
expect(() => memoizedKeychainDefinition.factory({ storage }).clone()).not.toThrow()
44+
})
45+
46+
describe.each([
47+
{
48+
name: 'memoized',
49+
factory: () => {
50+
const keychain = memoizedKeychainDefinition.factory({ storage })
51+
keychain.addSeed(seed)
52+
return keychain
53+
},
54+
},
55+
{
56+
name: 'memoizedClone',
57+
factory: () => {
58+
const clone = memoizedKeychain.clone()
59+
clone.addSeed(seed)
60+
return clone
61+
},
62+
},
63+
])('memoization: $name', ({ factory }) => {
64+
const storageKey = stableStringify({
65+
seedId,
66+
keyId: {
67+
assetName: 'ethereum',
68+
derivationAlgorithm: 'BIP32',
69+
derivationPath: "m/44'/60'/0'/0/0",
70+
keyType: 'secp256k1',
71+
},
72+
})
73+
74+
const storageData = {
75+
[storageKey]: {
76+
xpub: 'xpub6H8P7xAy1nvvefMui3rD6yK3cdkBSAhukKRcxeqydPqdm8L8FAvxu33Hgoajcr8PW1oBPDm7sRdPSoUz55kcCF9LNd5RatNgExPrn8Pvd5P',
77+
publicKey: Buffer.from('AgyNoIyo7xR+pkMj5TnXkQE/8NtK6dMck+KUghia9w3l', 'base64'),
78+
},
79+
}
80+
81+
it('should retrieve publicKeys from storage at construction', async () => {
82+
mockStorage.get.mockResolvedValueOnce(BJSON.stringify(storageData))
83+
factory()
84+
expect(mockStorage.get).toHaveBeenCalledTimes(1)
85+
})
86+
87+
it('should write publicKeys to storage if not found', async () => {
88+
mockStorage.get.mockResolvedValueOnce(null)
89+
const keychain = factory()
90+
const exported = await keychain.exportKey({ seedId, keyId: keyIdentifierEthereum0 })
91+
expect(mockStorage.set).toHaveBeenCalledTimes(1)
92+
expect(mockStorage.set).toHaveBeenCalledWith('data1', BJSON.stringify(storageData))
93+
const exportedFromCache = await keychain.exportKey({ seedId, keyId: keyIdentifierEthereum0 })
94+
expect(mockStorage.set).toHaveBeenCalledTimes(1)
95+
expect(exported).toStrictEqual({ privateKey: null, xpriv: null, ...exportedFromCache })
96+
})
97+
98+
it('should still allow private keys', async () => {
99+
mockStorage.get.mockResolvedValueOnce(null)
100+
const keychain = factory()
101+
await expect(
102+
keychain.exportKey({ seedId, keyId: keyIdentifierEthereum0, exportPrivate: true })
103+
).resolves.not.toThrow()
104+
})
105+
})
106+
})

0 commit comments

Comments
 (0)