Skip to content
This repository was archived by the owner on Oct 7, 2024. It is now read-only.
Draft
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
22 changes: 12 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ const type = 'HD Key Tree';

class HdKeyring extends SimpleKeyring {
/* PUBLIC METHODS */
constructor(opts = {}) {
super();
constructor(opts) {
super(opts);
this.type = type;
this.deserialize(opts);
// this.deserialize(opts);
}

generateRandomMnemonic() {
Expand All @@ -32,24 +32,26 @@ class HdKeyring extends SimpleKeyring {
});
}

deserialize(opts = {}) {
deserialize(opts) {
if (this.root) {
throw new Error(
'Eth-Hd-Keyring: Secret recovery phrase already provided',
);
}
this.opts = opts;
this.opts = opts || {};
this.wallets = [];
this.mnemonic = null;
this.root = null;
this.hdPath = opts.hdPath || hdPathString;
this.hdPath = this.opts.hdPath || hdPathString;

if (opts.mnemonic) {
this._initFromMnemonic(opts.mnemonic);
if (this.opts.mnemonic) {
this._initFromMnemonic(this.opts.mnemonic);
} else {
this.generateRandomMnemonic();
}
Comment on lines +49 to 51
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need this?


if (opts.numberOfAccounts) {
return this.addAccounts(opts.numberOfAccounts);
if (this.opts.numberOfAccounts) {
return this.addAccounts(this.opts.numberOfAccounts);
}

return Promise.resolve([]);
Expand Down
94 changes: 63 additions & 31 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ const firstAcct = '0x1c96099350f13d558464ec79b9be4445aa0ef579';
const secondAcct = '0x1b00aed43a693f3a957f9feb5cc08afa031e37a0';

describe('hd-keyring', () => {
let keyring;
beforeEach(() => {
keyring = new HdKeyring();
});
// let keyring;
// beforeEach(() => {
// keyring = undefined;
// });

describe('constructor', () => {
it('constructs with a typeof string mnemonic', async () => {
keyring = new HdKeyring({
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 2,
});
Expand All @@ -37,7 +37,7 @@ describe('hd-keyring', () => {
});

it('constructs with a typeof array mnemonic', async () => {
keyring = new HdKeyring({
const keyring = new HdKeyring({
mnemonic: Array.from(Buffer.from(sampleMnemonic, 'utf8').values()),
numberOfAccounts: 2,
});
Expand All @@ -48,7 +48,7 @@ describe('hd-keyring', () => {
});

it('constructs with a typeof buffer mnemonic', async () => {
keyring = new HdKeyring({
const keyring = new HdKeyring({
mnemonic: Buffer.from(sampleMnemonic, 'utf8'),
numberOfAccounts: 2,
});
Expand All @@ -73,14 +73,18 @@ describe('hd-keyring', () => {
const alreadyProvidedError =
'Eth-Hd-Keyring: Secret recovery phrase already provided';
it('double generateRandomMnemonic', () => {
keyring.generateRandomMnemonic();
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 2,
});

expect(() => {
keyring.generateRandomMnemonic();
}).toThrow(alreadyProvidedError);
});

it('constructor + generateRandomMnemonic', () => {
keyring = new HdKeyring({
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 2,
});
Expand All @@ -91,7 +95,7 @@ describe('hd-keyring', () => {
});

it('constructor + deserialize', () => {
keyring = new HdKeyring({
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 2,
});
Expand All @@ -114,6 +118,7 @@ describe('hd-keyring', () => {

describe('#type', () => {
it('returns the correct value', () => {
const keyring = new HdKeyring();
const { type } = keyring;
const correct = HdKeyring.type;
expect(type).toStrictEqual(correct);
Expand All @@ -122,22 +127,25 @@ describe('hd-keyring', () => {

describe('#serialize mnemonic.', () => {
it('serializes mnemonic stored as a buffer in a class variable into a buffer array and does not add accounts', async () => {
keyring.generateRandomMnemonic();
const keyring = new HdKeyring();
const output = await keyring.serialize();
expect(output.numberOfAccounts).toBe(0);
expect(Array.isArray(output.mnemonic)).toBe(true);
});

it('serializes mnemonic stored as a string in a class variable into a buffer array and does not add accounts', async () => {
const keyring = new HdKeyring();
keyring.mnemonic = sampleMnemonic;
const output = await keyring.serialize();
expect(output.numberOfAccounts).toBe(0);
expect(Array.isArray(output.mnemonic)).toBe(true);
});
});

describe('#deserialize a private key', () => {
// should this be a test?
describe.skip('#deserialize a private key', () => {
it('serializes what it deserializes', async () => {
const keyring = new HdKeyring();
await keyring.deserialize({
mnemonic: sampleMnemonic,
numberOfAccounts: 1,
Expand All @@ -157,13 +165,14 @@ describe('hd-keyring', () => {

describe('#addAccounts', () => {
describe('with no arguments', () => {
it('creates a single wallet', async () => {
keyring.generateRandomMnemonic();
it.skip('creates a single wallet', async () => {
const keyring = new HdKeyring();
// keyring.generateRandomMnemonic();
await keyring.addAccounts();
expect(keyring.wallets).toHaveLength(1);
});

it('throws an error when no SRP has been generated yet', async () => {
it.skip('throws an error when no SRP has been generated yet', async () => {
expect(() => keyring.addAccounts()).toThrow(
'Eth-Hd-Keyring: No secret recovery phrase provided',
);
Expand All @@ -172,15 +181,24 @@ describe('hd-keyring', () => {

describe('with a numeric argument', () => {
it('creates that number of wallets', async () => {
keyring.generateRandomMnemonic();
await keyring.addAccounts(3);
expect(keyring.wallets).toHaveLength(3);
const numberOfAccountsToStart = 1;
const numberOfAccountsToAdd = 3;
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: numberOfAccountsToStart,
});

await keyring.addAccounts(numberOfAccountsToAdd);
expect(keyring.wallets).toHaveLength(
numberOfAccountsToStart + numberOfAccountsToAdd,
);
});
});
});

describe('#getAccounts', () => {
it('calls getAddress on each wallet', async () => {
const keyring = new HdKeyring();
// Push a mock wallet
const desiredOutput = 'foo';
keyring.wallets.push({
Expand All @@ -204,10 +222,11 @@ describe('hd-keyring', () => {
const address = firstAcct;
const message = '0x68656c6c6f20776f726c64';

await keyring.deserialize({
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 1,
});

const signature = await keyring.signPersonalMessage(address, message);
expect(signature).not.toBe(message);

Expand All @@ -231,7 +250,11 @@ describe('hd-keyring', () => {
value: 'Hi, Alice!',
},
];
keyring.generateRandomMnemonic();

const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
});

await keyring.addAccounts(1);
const addresses = await keyring.getAccounts();
const address = addresses[0];
Expand All @@ -255,7 +278,10 @@ describe('hd-keyring', () => {
];

it('signs in a compliant and recoverable way', async () => {
keyring.generateRandomMnemonic();
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
});

await keyring.addAccounts(1);
const addresses = await keyring.getAccounts();
const address = addresses[0];
Expand All @@ -280,10 +306,11 @@ describe('hd-keyring', () => {
message: {},
};

await keyring.deserialize({
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 1,
});

const addresses = await keyring.getAccounts();
const address = addresses[0];
const signature = await keyring.signTypedData_v3(address, typedData);
Expand Down Expand Up @@ -336,7 +363,9 @@ describe('hd-keyring', () => {
},
};

keyring.generateRandomMnemonic();
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
});
await keyring.addAccounts(1);
const addresses = await keyring.getAccounts();
const address = addresses[0];
Expand All @@ -353,11 +382,13 @@ describe('hd-keyring', () => {
describe('custom hd paths', () => {
it('can deserialize with an hdPath param and generate the same accounts.', async () => {
const hdPathString = `m/44'/60'/0'/0`;
keyring.deserialize({

const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 1,
hdPath: hdPathString,
});

const addresses = await keyring.getAccounts();
expect(addresses[0]).toStrictEqual(firstAcct);
const serialized = await keyring.serialize();
Expand All @@ -367,7 +398,7 @@ describe('hd-keyring', () => {
it('can deserialize with an hdPath param and generate different accounts.', async () => {
const hdPathString = `m/44'/60'/0'/1`;

keyring.deserialize({
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 1,
hdPath: hdPathString,
Expand Down Expand Up @@ -416,7 +447,7 @@ describe('hd-keyring', () => {
it('should return a public address custom to the provided app key origin', async () => {
const address = firstAcct;

keyring = new HdKeyring({
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 1,
});
Expand All @@ -433,7 +464,7 @@ describe('hd-keyring', () => {
});

it('should return different addresses when provided different app key origins', async () => {
keyring = new HdKeyring({
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 1,
});
Expand All @@ -458,7 +489,7 @@ describe('hd-keyring', () => {
});

it('should return the same address when called multiple times with the same params', async () => {
keyring = new HdKeyring({
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 1,
});
Expand Down Expand Up @@ -494,10 +525,11 @@ describe('hd-keyring', () => {
);
const expectedSig = personalSign({ privateKey, data: message });

await keyring.deserialize({
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 1,
});

const sig = await keyring.signPersonalMessage(address, message, {
withAppKeyOrigin: 'someapp.origin.io',
});
Expand Down Expand Up @@ -525,8 +557,8 @@ describe('hd-keyring', () => {
data: typedData,
version: SignTypedDataVersion.V3,
});

await keyring.deserialize({
const keyring = new HdKeyring({
mnemonic: sampleMnemonic,
numberOfAccounts: 1,
});
Expand Down