aboutsummaryrefslogtreecommitdiffstats
path: root/packages/subproviders/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/subproviders/src')
-rw-r--r--packages/subproviders/src/globals.d.ts13
-rw-r--r--packages/subproviders/src/subproviders/ledger.ts36
-rw-r--r--packages/subproviders/src/types.ts6
3 files changed, 40 insertions, 15 deletions
diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts
index adef23806..3800c970f 100644
--- a/packages/subproviders/src/globals.d.ts
+++ b/packages/subproviders/src/globals.d.ts
@@ -48,7 +48,7 @@ declare module 'ledgerco' {
public comm: comm;
constructor(comm: comm);
public getAddress_async(path: string, display?: boolean, chaincode?: boolean):
- Promise<{publicKey: string; address: string}>;
+ Promise<{publicKey: string; address: string; chainCode: string}>;
public signTransaction_async(path: string, rawTxHex: string): Promise<ECSignatureString>;
public getAppConfiguration_async(): Promise<{ arbitraryDataEnabled: number; version: string }>;
public signPersonalMessage_async(path: string, messageHex: string): Promise<ECSignature>;
@@ -91,3 +91,14 @@ declare module 'web3-provider-engine' {
}
export = Web3ProviderEngine;
}
+
+// hdkey declarations
+declare module 'hdkey' {
+ class HDNode {
+ public publicKey: Buffer;
+ public chainCode: Buffer;
+ public constructor();
+ public derive(path: string): HDNode;
+ }
+ export = HDNode;
+}
diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts
index 9ffc105a4..f9922fdda 100644
--- a/packages/subproviders/src/subproviders/ledger.ts
+++ b/packages/subproviders/src/subproviders/ledger.ts
@@ -2,6 +2,7 @@ import {assert} from '@0xproject/assert';
import {addressUtils} from '@0xproject/utils';
import EthereumTx = require('ethereumjs-tx');
import ethUtil = require('ethereumjs-util');
+import HDNode = require('hdkey');
import * as _ from 'lodash';
import Semaphore from 'semaphore-async-await';
import Web3 = require('web3');
@@ -20,7 +21,7 @@ import {Subprovider} from './subprovider';
const DEFAULT_DERIVATION_PATH = `44'/60'/0'`;
const NUM_ADDRESSES_TO_FETCH = 10;
const ASK_FOR_ON_DEVICE_CONFIRMATION = false;
-const SHOULD_GET_CHAIN_CODE = false;
+const SHOULD_GET_CHAIN_CODE = true;
export class LedgerSubprovider extends Subprovider {
private _nonceLock: Semaphore;
@@ -127,21 +128,30 @@ export class LedgerSubprovider extends Subprovider {
public async getAccountsAsync(): Promise<string[]> {
this._ledgerClientIfExists = await this.createLedgerClientAsync();
- // TODO: replace with generating addresses without hitting Ledger
+ let ledgerResponse;
+ try {
+ ledgerResponse = await this._ledgerClientIfExists.getAddress_async(
+ this._derivationPath, this._shouldAlwaysAskForConfirmation, SHOULD_GET_CHAIN_CODE,
+ );
+ } finally {
+ await this.destoryLedgerClientAsync();
+ }
+
+ const hdKey = new HDNode();
+ hdKey.publicKey = new Buffer(ledgerResponse.publicKey, 'hex');
+ hdKey.chainCode = new Buffer(ledgerResponse.chainCode, 'hex');
+
const accounts = [];
for (let i = 0; i < NUM_ADDRESSES_TO_FETCH; i++) {
- try {
- const derivationPath = `${this._derivationPath}/${i + this._derivationPathIndex}`;
- const result = await this._ledgerClientIfExists.getAddress_async(
- derivationPath, this._shouldAlwaysAskForConfirmation, SHOULD_GET_CHAIN_CODE,
- );
- accounts.push(result.address.toLowerCase());
- } catch (err) {
- await this.destoryLedgerClientAsync();
- throw err;
- }
+ const derivedHDNode = hdKey.derive(`m/${i + this._derivationPathIndex}`);
+ const derivedPublicKey = derivedHDNode.publicKey;
+ const shouldSanitizePublicKey = true;
+ const ethereumAddressUnprefixed = ethUtil.publicToAddress(
+ derivedPublicKey, shouldSanitizePublicKey,
+ ).toString('hex');
+ const ethereumAddressPrefixed = ethUtil.addHexPrefix(ethereumAddressUnprefixed);
+ accounts.push(ethereumAddressPrefixed.toLowerCase());
}
- await this.destoryLedgerClientAsync();
return accounts;
}
public async signTransactionAsync(txParams: PartialTxParams): Promise<string> {
diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts
index 1e7d3eab0..c5ccf1fda 100644
--- a/packages/subproviders/src/types.ts
+++ b/packages/subproviders/src/types.ts
@@ -10,8 +10,10 @@ export interface LedgerCommunicationClient {
* NodeJs and Browser communication are supported.
*/
export interface LedgerEthereumClient {
+ // shouldGetChainCode is defined as `true` instead of `boolean` because other types rely on the assumption
+ // that we get back the chain code and we don't have dependent types to express it properly
getAddress_async: (derivationPath: string, askForDeviceConfirmation: boolean,
- shouldGetChainCode: boolean) => Promise<LedgerGetAddressResult>;
+ shouldGetChainCode: true) => Promise<LedgerGetAddressResult>;
signPersonalMessage_async: (derivationPath: string, messageHex: string) => Promise<ECSignature>;
signTransaction_async: (derivationPath: string, txHex: string) => Promise<ECSignatureString>;
comm: LedgerCommunicationClient;
@@ -63,6 +65,8 @@ export interface SignatureData {
export interface LedgerGetAddressResult {
address: string;
+ publicKey: string;
+ chainCode: string;
}
export interface LedgerWalletSubprovider {