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

Add method for setting the hdpath #107

Merged
merged 11 commits into from
Nov 17, 2021
36 changes: 36 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ const TrezorConnect = require('trezor-connect').default;
const { TransactionFactory } = require('@ethereumjs/tx');

const hdPathString = `m/44'/60'/0'/0`;
const SLIP0044TestnetPath = `m/44'/1'/0'/0`;

const ALLOWED_HD_PATHS = {
[hdPathString]: true,
[SLIP0044TestnetPath]: true,
};

const keyringType = 'Trezor Hardware';
const pathBase = 'm';
const MAX_INDEX = 1000;
Expand Down Expand Up @@ -338,6 +345,35 @@ class TrezorKeyring extends EventEmitter {
this.paths = {};
}

/**
* Set the HD path to be used by the keyring. Only known supported HD paths are allowed.
*
* If the given HD path is already the current HD path, nothing happens. Otherwise the new HD
* path is set, and the wallet state is completely reset.
*
* @throws {Error] Throws if the HD path is not supported.
*
* @param {string} hdPath - The HD path to set.
*/
setHdPath(hdPath) {
if (!ALLOWED_HD_PATHS[hdPath]) {
throw new Error(
`The setHdPath method does not support setting HD Path to ${hdPath}`,
);
}

// Reset HDKey if the path changes
if (this.hdPath !== hdPath) {
this.hdk = new HDKey();
this.accounts = [];
this.page = 0;
this.perPage = 5;
this.unlockedAccount = 0;
this.paths = {};
}
this.hdPath = hdPath;
}

/* PRIVATE METHODS */

_normalize(buf) {
Expand Down
57 changes: 57 additions & 0 deletions test/test-eth-trezor-keyring.js
Original file line number Diff line number Diff line change
Expand Up @@ -476,4 +476,61 @@ describe('TrezorKeyring', function () {
assert.equal(accounts.length, 0);
});
});

describe('setHdPath', function () {
const initialProperties = {
hdPath: `m/44'/60'/0'/0`,
accounts: ['Account 1'],
page: 2,
perPage: 10,
};
const accountToUnlock = 1;
const mockPaths = { '0x123': 1 };

beforeEach(function () {
keyring.deserialize(initialProperties);
keyring.paths = mockPaths;
keyring.setAccountToUnlock(accountToUnlock.toString(16));
});

it('should do nothing if passed an hdPath equal to the current hdPath', async function () {
keyring.setHdPath(initialProperties.hdPath);
assert.equal(keyring.hdPath, initialProperties.hdPath);
assert.deepEqual(keyring.accounts, initialProperties.accounts);
assert.equal(keyring.page, initialProperties.page);
assert.equal(keyring.perPage, initialProperties.perPage);
assert.equal(
keyring.hdk._publicKey.toString('hex'),
fakeHdKey._publicKey.toString('hex'),
);
assert.equal(keyring.unlockedAccount, accountToUnlock);
assert.deepEqual(keyring.paths, mockPaths);
});

it('should update the hdPath and reset account and page properties if passed a new hdPath', async function () {
const SLIP0044TestnetPath = `m/44'/1'/0'/0`;

keyring.setHdPath(SLIP0044TestnetPath);

assert.equal(keyring.hdPath, SLIP0044TestnetPath);
assert.deepEqual(keyring.accounts, []);
assert.equal(keyring.page, 0);
assert.equal(keyring.perPage, 5);
assert.equal(keyring.hdk._publicKey, null);
assert.equal(keyring.unlockedAccount, 0);
assert.deepEqual(keyring.paths, {});
});

it('should throw an error if passed an unsupported hdPath', async function () {
const unsupportedPath = 'unsupported hdPath';
try {
keyring.setHdPath(unsupportedPath);
} catch (error) {
assert.equal(
error.message,
`The setHdPath method does not support setting HD Path to ${unsupportedPath}`,
);
}
});
});
});