From 260ab2d4134e24a3a2f3fab845fa72c1e1766a3e Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Wed, 11 Apr 2018 14:04:27 +1000 Subject: Update changelog and add derivationBasePath --- packages/subproviders/CHANGELOG.json | 3 ++- packages/subproviders/src/subproviders/ledger.ts | 26 +++++++++++----------- .../src/subproviders/mnemonic_wallet.ts | 19 ++++++++-------- packages/subproviders/src/types.ts | 3 ++- packages/subproviders/src/utils/wallet_utils.ts | 11 ++++----- 5 files changed, 33 insertions(+), 29 deletions(-) (limited to 'packages/subproviders') diff --git a/packages/subproviders/CHANGELOG.json b/packages/subproviders/CHANGELOG.json index ccf807695..554fbd0cf 100644 --- a/packages/subproviders/CHANGELOG.json +++ b/packages/subproviders/CHANGELOG.json @@ -7,7 +7,8 @@ "pr": 506 }, { - "note": "Add mnemonic wallet subprovider, deprecating our truffle-hdwallet-provider fork", + "note": + "Add mnemonic wallet subprovider, deprecating our truffle-hdwallet-provider fork. Support multiple addresses in ledger and mnemonic wallets", "pr": 507 } ] diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts index 6c685c84d..975893f8a 100644 --- a/packages/subproviders/src/subproviders/ledger.ts +++ b/packages/subproviders/src/subproviders/ledger.ts @@ -24,7 +24,6 @@ import { BaseWalletSubprovider } from './base_wallet_subprovider'; const DEFAULT_DERIVATION_PATH = `44'/60'/0'`; const ASK_FOR_ON_DEVICE_CONFIRMATION = false; const SHOULD_GET_CHAIN_CODE = true; -const IS_CHILD_KEY = true; /** * Subprovider for interfacing with a user's [Ledger Nano S](https://www.ledgerwallet.com/products/ledger-nano-s). @@ -35,7 +34,7 @@ export class LedgerSubprovider extends BaseWalletSubprovider { private _nonceLock = new Lock(); private _connectionLock = new Lock(); private _networkId: number; - private _derivationPath: string; + private _derivationBasePath: string; private _ledgerEthereumClientFactoryAsync: LedgerEthereumClientFactoryAsync; private _ledgerClientIfExists?: LedgerEthereumClient; private _shouldAlwaysAskForConfirmation: boolean; @@ -50,7 +49,7 @@ export class LedgerSubprovider extends BaseWalletSubprovider { super(); this._networkId = config.networkId; this._ledgerEthereumClientFactoryAsync = config.ledgerEthereumClientFactoryAsync; - this._derivationPath = config.derivationPath || DEFAULT_DERIVATION_PATH; + this._derivationBasePath = config.derivationPath || DEFAULT_DERIVATION_PATH; this._shouldAlwaysAskForConfirmation = !_.isUndefined(config.accountFetchingConfigs) && !_.isUndefined(config.accountFetchingConfigs.shouldAskForOnDeviceConfirmation) @@ -67,14 +66,14 @@ export class LedgerSubprovider extends BaseWalletSubprovider { * @returns derivation path */ public getPath(): string { - return this._derivationPath; + return this._derivationBasePath; } /** * Set a desired derivation path when computing the available user addresses * @param derivationPath The desired derivation path (e.g `44'/60'/0'`) */ public setPath(derivationPath: string) { - this._derivationPath = derivationPath; + this._derivationBasePath = derivationPath; } /** * Retrieve a users Ledger accounts. The accounts are derived from the derivationPath, @@ -88,8 +87,8 @@ export class LedgerSubprovider extends BaseWalletSubprovider { public async getAccountsAsync( numberOfAccounts: number = walletUtils.DEFAULT_NUM_ADDRESSES_TO_FETCH, ): Promise { - const initialHDerivedKey = await this._initialDerivedKeyAsync(); - const derivedKeys = walletUtils.calculateDerivedHDKeys(initialHDerivedKey, numberOfAccounts); + const initialDerivedKey = await this._initialDerivedKeyAsync(); + const derivedKeys = walletUtils.calculateDerivedHDKeys(initialDerivedKey, numberOfAccounts); const accounts = _.map(derivedKeys, 'address'); return accounts; } @@ -117,8 +116,8 @@ export class LedgerSubprovider extends BaseWalletSubprovider { const txHex = tx.serialize().toString('hex'); try { - const derivationPath = `${derivedKey.derivationPath}/${derivedKey.derivationIndex}`; - const result = await ledgerClient.signTransaction(derivationPath, txHex); + const fullDerivationPath = derivedKey.derivationPath; + const result = await ledgerClient.signTransaction(fullDerivationPath, txHex); // Store signature in transaction tx.r = Buffer.from(result.r, 'hex'); tx.s = Buffer.from(result.s, 'hex'); @@ -161,8 +160,8 @@ export class LedgerSubprovider extends BaseWalletSubprovider { const ledgerClient = await this._createLedgerClientAsync(); try { - const derivationPath = `${derivedKey.derivationPath}/${derivedKey.derivationIndex}`; - const result = await ledgerClient.signPersonalMessage(derivationPath, ethUtil.stripHexPrefix(data)); + const fullDerivationPath = derivedKey.derivationPath; + const result = await ledgerClient.signPersonalMessage(fullDerivationPath, ethUtil.stripHexPrefix(data)); const v = result.v - 27; let vHex = v.toString(16); if (vHex.length < 2) { @@ -203,7 +202,7 @@ export class LedgerSubprovider extends BaseWalletSubprovider { let ledgerResponse; try { ledgerResponse = await ledgerClient.getAddress( - this._derivationPath, + this._derivationBasePath, this._shouldAlwaysAskForConfirmation, SHOULD_GET_CHAIN_CODE, ); @@ -217,7 +216,8 @@ export class LedgerSubprovider extends BaseWalletSubprovider { hdKey, address: ledgerResponse.address, isChildKey: true, - derivationPath: this._derivationPath, + derivationBasePath: this._derivationBasePath, + derivationPath: `${this._derivationBasePath}/${0}`, derivationIndex: 0, }; } diff --git a/packages/subproviders/src/subproviders/mnemonic_wallet.ts b/packages/subproviders/src/subproviders/mnemonic_wallet.ts index 40f584250..972f7e65e 100644 --- a/packages/subproviders/src/subproviders/mnemonic_wallet.ts +++ b/packages/subproviders/src/subproviders/mnemonic_wallet.ts @@ -19,31 +19,32 @@ const DEFAULT_DERIVATION_PATH = `44'/60'/0'/0`; */ export class MnemonicWalletSubprovider extends BaseWalletSubprovider { private _addressSearchLimit: number; - private _derivationPath: string; + private _derivationBasePath: string; private _derivedKey: DerivedHDKey; /** * Instantiates a MnemonicWalletSubprovider. Defaults to derivationPath set to `44'/60'/0'/0`. * This is the default in TestRPC/Ganache, this can be overridden if desired. * @param mnemonic The mnemonic seed - * @param derivationPath The derivation path, defaults to `44'/60'/0'/0` + * @param derivationBasePath The derivation path, defaults to `44'/60'/0'/0` * @param addressSearchLimit The limit on address search attempts before raising `WalletSubproviderErrors.AddressNotFound` * @return MnemonicWalletSubprovider instance */ constructor( mnemonic: string, - derivationPath: string = DEFAULT_DERIVATION_PATH, + derivationBasePath: string = DEFAULT_DERIVATION_PATH, addressSearchLimit: number = walletUtils.DEFAULT_ADDRESS_SEARCH_LIMIT, ) { assert.isString('mnemonic', mnemonic); - assert.isString('derivationPath', derivationPath); + assert.isString('derivationPath', derivationBasePath); assert.isNumber('addressSearchLimit', addressSearchLimit); super(); const seed = bip39.mnemonicToSeed(mnemonic); const hdKey = HDNode.fromMasterSeed(seed); - this._derivationPath = derivationPath; + this._derivationBasePath = derivationBasePath; this._derivedKey = { address: walletUtils.addressOfHDKey(hdKey), - derivationPath: this._derivationPath, + derivationBasePath: this._derivationBasePath, + derivationPath: `${this._derivationBasePath}/${0}`, derivationIndex: 0, hdKey, isChildKey: false, @@ -55,17 +56,17 @@ export class MnemonicWalletSubprovider extends BaseWalletSubprovider { * @returns derivation path */ public getPath(): string { - return this._derivationPath; + return this._derivationBasePath; } /** * Set a desired derivation path when computing the available user addresses * @param derivationPath The desired derivation path (e.g `44'/60'/0'`) */ public setPath(derivationPath: string) { - this._derivationPath = derivationPath; + this._derivationBasePath = derivationPath; this._derivedKey = { ...this._derivedKey, - derivationPath: this._derivationPath, + derivationBasePath: this._derivationBasePath, }; } /** diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts index 140c7c2df..c76be1bf8 100644 --- a/packages/subproviders/src/types.ts +++ b/packages/subproviders/src/types.ts @@ -114,8 +114,9 @@ export enum NonceSubproviderErrors { } export interface DerivedHDKey { address: string; - derivationPath: string; derivationIndex: number; + derivationBasePath: string; + derivationPath: string; hdKey: HDNode; isChildKey: boolean; } diff --git a/packages/subproviders/src/utils/wallet_utils.ts b/packages/subproviders/src/utils/wallet_utils.ts index bd1851d9a..2d9d14e44 100644 --- a/packages/subproviders/src/utils/wallet_utils.ts +++ b/packages/subproviders/src/utils/wallet_utils.ts @@ -20,18 +20,19 @@ class DerivedHDKeyIterator implements IterableIterator { } public next(): IteratorResult { - const derivationPath = this._initialDerivedKey.derivationPath; + const derivationBasePath = this._initialDerivedKey.derivationBasePath; const derivationIndex = this._index; // If the DerivedHDKey is a child then we walk relative, if not we walk the full derivation path - const path = this._initialDerivedKey.isChildKey - ? `m/${derivationIndex}` - : `m/${derivationPath}/${derivationIndex}`; + const fullDerivationPath = `m/${derivationBasePath}/${derivationIndex}`; + const relativeDerivationPath = `m/${derivationIndex}`; + const path = this._initialDerivedKey.isChildKey ? relativeDerivationPath : fullDerivationPath; const hdKey = this._initialDerivedKey.hdKey.derive(path); const address = walletUtils.addressOfHDKey(hdKey); const derivedKey: DerivedHDKey = { address, hdKey, - derivationPath, + derivationPath: fullDerivationPath, + derivationBasePath: this._initialDerivedKey.derivationBasePath, derivationIndex, isChildKey: this._initialDerivedKey.isChildKey, }; -- cgit v1.2.3