Skip to content
This repository has been archived by the owner on Oct 7, 2024. It is now read-only.

Bump eth-hd-keyring to latest version #132

Merged
merged 3 commits into from
Apr 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ const encryptor = require('browser-passworder');
const { normalize: normalizeAddress } = require('eth-sig-util');

const SimpleKeyring = require('eth-simple-keyring');
const HdKeyring = require('eth-hd-keyring');
const HdKeyring = require('@metamask/eth-hd-keyring');

const keyringTypes = [SimpleKeyring, HdKeyring];

const KEYRINGS_TYPE_MAP = {
HD_KEYRING: 'HD Key Tree',
SIMPLE_KEYRING: 'Simple Key Pair',
};
/**
* Strip the hex prefix from an address, if present
* @param {string} address - The address that might be hex prefixed.
Expand Down Expand Up @@ -107,7 +111,7 @@ class KeyringController extends EventEmitter {

return this.persistAllKeyrings(password)
.then(() => {
return this.addNewKeyring('HD Key Tree', {
return this.addNewKeyring(KEYRINGS_TYPE_MAP.HD_KEYRING, {
mnemonic: seed,
numberOfAccounts: 1,
});
Expand Down Expand Up @@ -194,9 +198,14 @@ class KeyringController extends EventEmitter {
* @param {Object} opts - The constructor options for the keyring.
* @returns {Promise<Keyring>} The new keyring.
*/
addNewKeyring(type, opts) {
addNewKeyring(type, opts = {}) {
const Keyring = this.getKeyringClassForType(type);
const keyring = new Keyring(opts);
if (!opts.mnemonic && type === KEYRINGS_TYPE_MAP.HD_KEYRING) {
keyring.generateRandomMnemonic();
keyring.addAccounts();
}

return keyring
.getAccounts()
.then((accounts) => {
Expand Down Expand Up @@ -250,7 +259,7 @@ class KeyringController extends EventEmitter {
checkForDuplicate(type, newAccountArray) {
return this.getAccounts().then((accounts) => {
switch (type) {
case 'Simple Key Pair': {
case KEYRINGS_TYPE_MAP.SIMPLE_KEYRING: {
const isIncluded = Boolean(
accounts.find(
(key) =>
Expand Down Expand Up @@ -503,7 +512,7 @@ class KeyringController extends EventEmitter {
createFirstKeyTree(password) {
this.password = password;
this.clearKeyrings();
return this.addNewKeyring('HD Key Tree', { numberOfAccounts: 1 })
return this.addNewKeyring(KEYRINGS_TYPE_MAP.HD_KEYRING)
.then((keyring) => {
return keyring.getAccounts();
})
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
"lint:fix": "yarn lint:eslint --fix && yarn lint:misc --write"
},
"dependencies": {
"@metamask/eth-hd-keyring": "^4.0.2",
"bip39": "^3.0.4",
"browser-passworder": "^2.0.3",
"eth-hd-keyring": "^3.6.0",
"eth-sig-util": "^3.0.1",
"eth-simple-keyring": "^4.2.0",
"obs-store": "^4.0.3"
Expand Down
107 changes: 99 additions & 8 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,20 @@ const Wallet = require('ethereumjs-wallet').default;
const KeyringController = require('..');
const mockEncryptor = require('./lib/mock-encryptor');

const mockAddress = '0xeF35cA8EbB9669A35c31b5F6f249A9941a812AC1'.toLowerCase();

const password = 'password123';
const walletOneSeedWords =
'puzzle seed penalty soldier say clay field arctic metal hen cage runway';
const walletOneAddresses = ['0xef35ca8ebb9669a35c31b5f6f249a9941a812ac1'];

const walletTwoSeedWords =
'urge letter protect palace city barely security section midnight wealth south deer';

const walletTwoAddresses = [
'0xbbafcf3d00fb625b65bb1497c94bf42c1f4b3e78',
'0x49dd2653f38f75d40fdbd51e83b9c9724c87f7eb',
];
describe('KeyringController', function () {
let keyringController;
const password = 'password123';
const seedWords =
'puzzle seed penalty soldier say clay field arctic metal hen cage runway';
const addresses = [mockAddress];

beforeEach(async function () {
keyringController = new KeyringController({
Expand Down Expand Up @@ -103,6 +109,41 @@ describe('KeyringController', function () {
});
});

describe('createNewVaultAndRestore', function () {
it('clears old keyrings and creates a one', async function () {
const initialAccounts = await keyringController.getAccounts();
expect(initialAccounts).toHaveLength(1);
await keyringController.addNewKeyring('HD Key Tree');

const allAccounts = await keyringController.getAccounts();
expect(allAccounts).toHaveLength(2);

await keyringController.createNewVaultAndRestore(
password,
walletOneSeedWords,
);

const allAccountsAfter = await keyringController.getAccounts();
expect(allAccountsAfter).toHaveLength(1);
expect(allAccountsAfter[0]).toBe(walletOneAddresses[0]);
});

it('throws error if argument password is not a string', async function () {
await expect(() =>
keyringController.createNewVaultAndRestore(12, walletTwoSeedWords),
).rejects.toThrow('Password must be text.');
});

it('throws error if mnemonic passed is invalid', async function () {
await expect(() =>
keyringController.createNewVaultAndRestore(
password,
'test test test palace city barely security section midnight wealth south deer',
),
).rejects.toThrow('Seed phrase is invalid.');
});
});

describe('addNewKeyring', function () {
it('should add simple key pair', async function () {
const privateKey =
Expand All @@ -123,14 +164,39 @@ describe('KeyringController', function () {
);
expect(allAccounts).toStrictEqual(expectedAllAccounts);
});

it('should add HD Key Tree without mnemonic passed as an argument', async function () {
const previousAllAccounts = await keyringController.getAccounts();
expect(previousAllAccounts).toHaveLength(1);
const keyring = await keyringController.addNewKeyring('HD Key Tree');
const keyringAccounts = await keyring.getAccounts();
expect(keyringAccounts).toHaveLength(1);
const allAccounts = await keyringController.getAccounts();
expect(allAccounts).toHaveLength(2);
});

it('should add HD Key Tree with mnemonic passed as an argument', async function () {
const previousAllAccounts = await keyringController.getAccounts();
expect(previousAllAccounts).toHaveLength(1);
const keyring = await keyringController.addNewKeyring('HD Key Tree', {
numberOfAccounts: 2,
mnemonic: walletTwoSeedWords,
});
const keyringAccounts = await keyring.getAccounts();
expect(keyringAccounts).toHaveLength(2);
expect(keyringAccounts[0]).toStrictEqual(walletTwoAddresses[0]);
expect(keyringAccounts[1]).toStrictEqual(walletTwoAddresses[1]);
const allAccounts = await keyringController.getAccounts();
expect(allAccounts).toHaveLength(3);
});
});

describe('restoreKeyring', function () {
it(`should pass a keyring's serialized data back to the correct type.`, async function () {
const mockSerialized = {
type: 'HD Key Tree',
data: {
mnemonic: seedWords,
mnemonic: walletOneSeedWords,
numberOfAccounts: 1,
},
};
Expand All @@ -139,7 +205,7 @@ describe('KeyringController', function () {
expect(keyring.wallets).toHaveLength(1);

const accounts = await keyring.getAccounts();
expect(accounts[0]).toBe(addresses[0]);
expect(accounts[0]).toBe(walletOneAddresses[0]);
});
});

Expand Down Expand Up @@ -228,6 +294,31 @@ describe('KeyringController', function () {
});
});

describe('verifyPassword', function () {
it('throws an error if no encrypted vault is in controller state', async function () {
keyringController = new KeyringController({
encryptor: mockEncryptor,
});
await expect(() =>
keyringController.verifyPassword('test'),
).rejects.toThrow('Cannot unlock without a previous vault.');
});
});

describe('addNewAccount', function () {
it('adds a new account to the keyring it receives as an argument', async function () {
const [HDKeyring] = await keyringController.getKeyringsByType(
'HD Key Tree',
);
const initialAccounts = await HDKeyring.getAccounts();
expect(initialAccounts).toHaveLength(1);

await keyringController.addNewAccount(HDKeyring);
const accountsAfterAdd = await HDKeyring.getAccounts();
expect(accountsAfterAdd).toHaveLength(2);
});
});

describe('getAppKeyAddress', function () {
it('returns the expected app key address', async function () {
const address = '0x01560cd3bac62cc6d7e6380600d9317363400896';
Expand Down
87 changes: 41 additions & 46 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,16 @@
semver "^7.3.5"
yargs "^17.0.1"

"@metamask/bip39@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@metamask/bip39/-/bip39-4.0.0.tgz#1cb867a8454e3d45d065107b4e070d58bdb64aac"
integrity sha512-xH2g8mFe9p2WePnKeQJH4U8MB6pWPyvwpsz4stb0YdnMOR7cKA6Jm/KOSFiPKr1i9+AzNDImt/XxhwF5ej4jXQ==
dependencies:
"@types/node" "11.11.6"
create-hash "^1.1.0"
pbkdf2 "^3.0.9"
randombytes "^2.0.1"

"@metamask/eslint-config-jest@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/@metamask/eslint-config-jest/-/eslint-config-jest-7.0.0.tgz#81612aaf5307c3d65bb43366000233cd0b6e9db4"
Expand All @@ -552,6 +562,28 @@
resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-7.0.1.tgz#eeb87baa902965ca7931c26911d7027373706f34"
integrity sha512-dMZ+iyZrHdZK0D1uStTx8UN6Q6IK9YGbqPUwxgTj63M0mZOsuqs8qpGf+9Dn7uqS+8Oe9jNqejKxozjTiJvsEw==

"@metamask/eth-hd-keyring@^4.0.2":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@metamask/eth-hd-keyring/-/eth-hd-keyring-4.0.2.tgz#0a81556a556b361755c8d6fb5aced1ce5be0331c"
integrity sha512-v47VOTCCmZUZ6uxM5tQNoasQjLdrZADmgph2fhk4m7zKVUxDvYFU7FJT3Rm55fk8mg+dKSbEObDriqbdWeBbcA==
dependencies:
"@metamask/bip39" "^4.0.0"
"@metamask/eth-sig-util" "^4.0.0"
eth-simple-keyring "^4.2.0"
ethereumjs-util "^7.0.9"
ethereumjs-wallet "^1.0.1"

"@metamask/eth-sig-util@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.0.tgz#11553ba06de0d1352332c1bde28c8edd00e0dcf6"
integrity sha512-LczOjjxY4A7XYloxzyxJIHONELmUxVZncpOLoClpEcTiebiVdM46KRPYXGuULro9oNNR2xdVx3yoKiQjdfWmoA==
dependencies:
ethereumjs-abi "^0.6.8"
ethereumjs-util "^6.2.1"
ethjs-util "^0.1.6"
tweetnacl "^1.0.3"
tweetnacl-util "^0.15.1"

"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
Expand Down Expand Up @@ -1140,17 +1172,6 @@ bindings@^1.2.1, bindings@^1.5.0:
dependencies:
file-uri-to-path "1.0.0"

bip39@^2.2.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.6.0.tgz#9e3a720b42ec8b3fbe4038f1e445317b6a99321c"
integrity sha512-RrnQRG2EgEoqO24ea+Q/fftuPUZLmrEM3qNhhGsA3PbaXaCW791LTzPuVyx/VprXQcTbPJ3K3UeTna8ZnVl2sg==
dependencies:
create-hash "^1.1.0"
pbkdf2 "^3.0.9"
randombytes "^2.0.1"
safe-buffer "^5.0.1"
unorm "^1.3.3"

bip39@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.0.4.tgz#5b11fed966840b5e1b8539f0f54ab6392969b2a0"
Expand Down Expand Up @@ -1942,17 +1963,6 @@ esutils@^2.0.2:
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==

eth-hd-keyring@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/eth-hd-keyring/-/eth-hd-keyring-3.6.0.tgz#6835d30aa411b8d3ef098e82f6427b5325082abb"
integrity sha512-n2CwE9VNXsxLrXQa6suv0Umt4NT6+HtoahKgWx3YviXx4rQFwVT5nDwZfjhwrT31ESuoXYNIeJgz5hKLD96QeQ==
dependencies:
bip39 "^2.2.0"
eth-sig-util "^3.0.1"
eth-simple-keyring "^4.2.0"
ethereumjs-util "^7.0.9"
ethereumjs-wallet "^1.0.1"

eth-sig-util@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.1.tgz#8753297c83a3f58346bd13547b59c4b2cd110c96"
Expand Down Expand Up @@ -2015,18 +2025,18 @@ ethereumjs-util@^5.1.1:
safe-buffer "^5.1.1"
secp256k1 "^3.0.1"

ethereumjs-util@^6.0.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz#23ec79b2488a7d041242f01e25f24e5ad0357960"
integrity sha512-vb0XN9J2QGdZGIEKG2vXM+kUdEivUfU6Wmi5y0cg+LRhDYKnXIZ/Lz7XjFbHRR9VIKq2lVGLzGBkA++y2nOdOQ==
ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69"
integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==
dependencies:
"@types/bn.js" "^4.11.3"
bn.js "^4.11.0"
create-hash "^1.1.2"
elliptic "^6.5.2"
ethereum-cryptography "^0.1.3"
ethjs-util "0.1.6"
keccak "^2.0.0"
rlp "^2.2.3"
secp256k1 "^3.0.1"

ethereumjs-util@^7.0.2:
version "7.0.10"
Expand Down Expand Up @@ -2066,7 +2076,7 @@ ethereumjs-wallet@^1.0.1:
utf8 "^3.0.0"
uuid "^3.3.2"

ethjs-util@0.1.6, ethjs-util@^0.1.3:
ethjs-util@0.1.6, ethjs-util@^0.1.3, ethjs-util@^0.1.6:
version "0.1.6"
resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536"
integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==
Expand Down Expand Up @@ -3359,16 +3369,6 @@ keccak@^1.0.2:
nan "^2.2.1"
safe-buffer "^5.1.0"

keccak@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/keccak/-/keccak-2.1.0.tgz#734ea53f2edcfd0f42cdb8d5f4c358fef052752b"
integrity sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q==
dependencies:
bindings "^1.5.0"
inherits "^2.0.4"
nan "^2.14.0"
safe-buffer "^5.2.0"

keccak@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.1.tgz#ae30a0e94dbe43414f741375cff6d64c8bea0bff"
Expand Down Expand Up @@ -4191,7 +4191,7 @@ run-parallel@^1.1.9:
dependencies:
queue-microtask "^1.2.2"

safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0:
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2:
version "5.2.0"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
Expand Down Expand Up @@ -4699,7 +4699,7 @@ tunnel-agent@^0.6.0:
dependencies:
safe-buffer "^5.0.1"

tweetnacl-util@^0.15.0:
tweetnacl-util@^0.15.0, tweetnacl-util@^0.15.1:
version "0.15.1"
resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b"
integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==
Expand Down Expand Up @@ -4765,11 +4765,6 @@ universalify@^0.1.2:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==

unorm@^1.3.3:
version "1.6.0"
resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af"
integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==

uri-js@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
Expand Down