From 5be9cc94e4e12fda8da2e8944f4fdb9d439449bc Mon Sep 17 00:00:00 2001 From: Will O'Beirne Date: Wed, 23 May 2018 16:52:15 -0400 Subject: [PATCH] Convert ledger over to updated libs --- common/libs/wallet/deterministic/ledger.ts | 48 +++++++++++----------- common/selectors/wallet.ts | 8 ++-- common/typescript/ledgerco.d.ts | 45 -------------------- package.json | 2 +- 4 files changed, 28 insertions(+), 75 deletions(-) delete mode 100644 common/typescript/ledgerco.d.ts diff --git a/common/libs/wallet/deterministic/ledger.ts b/common/libs/wallet/deterministic/ledger.ts index dd21e9d3..9432679e 100644 --- a/common/libs/wallet/deterministic/ledger.ts +++ b/common/libs/wallet/deterministic/ledger.ts @@ -1,4 +1,5 @@ -import ledger from 'ledgerco'; +import TransportU2F from '@ledgerhq/hw-transport-u2f'; +import LedgerEth from '@ledgerhq/hw-app-eth'; import EthTx, { TxObj } from 'ethereumjs-tx'; import { addHexPrefix, toBuffer } from 'ethereumjs-util'; import { HardwareWallet, ChainCodeResponse } from './hardware'; @@ -17,11 +18,11 @@ export class LedgerWallet extends HardwareWallet implements IFullWallet { } return makeApp() - .then(app => app.getAddress_async(dpath, false, true)) + .then(app => app.getAddress(dpath, false, true)) .then(res => { return { publicKey: res.publicKey, - chainCode: res.chainCode + chainCode: res.chainCode as string }; }) .catch((err: any) => { @@ -29,15 +30,10 @@ export class LedgerWallet extends HardwareWallet implements IFullWallet { }); } - private ethApp: ledger.eth; - constructor(address: string, dPath: string, index: number) { super(address, dPath, index); - makeApp().then(app => (this.ethApp = app)); } - // modeled after - // https://github.com/kvhnuke/etherwallet/blob/3f7ff809e5d02d7ea47db559adaca1c930025e24/app/scripts/uiFuncs.js#L58 public async signRawTransaction(t: EthTx): Promise { const txFields = getTransactionFields(t); @@ -55,10 +51,8 @@ export class LedgerWallet extends HardwareWallet implements IFullWallet { t.s = toBuffer(0); try { - const result = await this.ethApp.signTransaction_async( - this.getPath(), - t.serialize().toString('hex') - ); + const ethApp = await makeApp(); + const result = await ethApp.signTransaction(this.getPath(), t.serialize().toString('hex')); const txToSerialize: TxObj = { ...txFields, @@ -73,8 +67,6 @@ export class LedgerWallet extends HardwareWallet implements IFullWallet { } } - // modeled after - // https://github.com/kvhnuke/etherwallet/blob/3f7ff809e5d02d7ea47db559adaca1c930025e24/app/scripts/controllers/signMsgCtrl.js#L53 public async signMessage(msg: string): Promise { if (!msg) { throw Error('No message to sign'); @@ -89,17 +81,18 @@ export class LedgerWallet extends HardwareWallet implements IFullWallet { return res.signedMessage; } - const msgHex = Buffer.from(msg).toString('hex'); try { - const signed = await this.ethApp.signPersonalMessage_async(this.getPath(), msgHex); + const msgHex = Buffer.from(msg).toString('hex'); + const ethApp = await makeApp(); + const signed = await ethApp.signPersonalMessage(this.getPath(), msgHex); const combined = addHexPrefix(signed.r + signed.s + signed.v.toString(16)); return combined; - } catch (error) { - throw (this.ethApp as any).getError(error); + } catch (err) { + throw new Error(ledgerErrToMessage(err)); } } - public displayAddress() { + public async displayAddress() { const path = this.dPath + '/' + this.index; if (process.env.BUILD_ELECTRON) { @@ -111,10 +104,14 @@ export class LedgerWallet extends HardwareWallet implements IFullWallet { .catch(() => false); } - return this.ethApp - .getAddress_async(path, true, false) - .then(() => true) - .catch(() => false); + try { + const ethApp = await makeApp(); + await ethApp.getAddress(path, true, false); + return true; + } catch (err) { + console.error('Failed to display Ledger address:', err); + return false; + } } public getWalletType(): string { @@ -122,8 +119,9 @@ export class LedgerWallet extends HardwareWallet implements IFullWallet { } } -function makeApp(): Promise { - return ledger.comm_u2f.create_async().then((comm: any) => new ledger.eth(comm)); +async function makeApp() { + const transport = await TransportU2F.create(); + return new LedgerEth(transport); } function ledgerErrToMessage(err: any) { diff --git a/common/selectors/wallet.ts b/common/selectors/wallet.ts index cc0382e2..d9908d12 100644 --- a/common/selectors/wallet.ts +++ b/common/selectors/wallet.ts @@ -187,11 +187,11 @@ export function getDisabledWallets(state: AppState): DisabledWallets { } // Some wallets are disabled on certain platforms - if (process.env.BUILD_DOWNLOADABLE) { - // addReason([SecureWalletName.LEDGER_NANO_S], 'This wallet is only supported at MyCrypto.com'); - } if (process.env.BUILD_ELECTRON) { - addReason([SecureWalletName.WEB3], 'This wallet is not supported in the MyCrypto app'); + addReason( + [SecureWalletName.WEB3, SecureWalletName.TREZOR], + 'This wallet is not supported in the MyCrypto app' + ); } // Dedupe and sort for consistency diff --git a/common/typescript/ledgerco.d.ts b/common/typescript/ledgerco.d.ts deleted file mode 100644 index 41d026ea..00000000 --- a/common/typescript/ledgerco.d.ts +++ /dev/null @@ -1,45 +0,0 @@ -declare module 'ledgerco' { - // TODO: fill the library typings out - export const comm_u2f: any; - export class eth { - constructor(transport: any); - getAddress_async( - path: string, - boolDisplay?: boolean, - boolChaincode?: boolean - ): Promise<{ - publicKey: string; - address: string; - chainCode: string; - }>; - - signTransaction_async( - path: string, - rawTxHex: string - ): Promise<{ - s: string; - v: string; - r: string; - }>; - - getAppConfiguration_async(): Promise<{ - arbitraryDataEnabled: number; - version: string; - }>; - - signPersonalMessage_async( - path: string, - messageHex: string - ): Promise<{ - v: number; - s: string; - r: string; - }>; - - signPersonalMessage_async( - path: string, - messageHex: string, - cb: (signed: any, error: any) => any - ): void; - } -} diff --git a/package.json b/package.json index f7c2e7f9..d53f032c 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "dependencies": { "@ledgerhq/hw-app-eth": "4.7.3", "@ledgerhq/hw-transport-node-hid": "4.7.6", + "@ledgerhq/hw-transport-u2f": "4.12.0", "@parity/qr-signer": "0.2.1", "babel-polyfill": "6.26.0", "bip39": "2.5.0", @@ -29,7 +30,6 @@ "hdkey": "0.8.0", "idna-uts46": "1.1.0", "jsonschema": "1.2.4", - "ledgerco": "1.2.1", "lodash": "4.17.5", "moment": "2.22.1", "moment-timezone": "0.5.14",