From 8521775389b2e7ddefec20f1d06331e4bc3d0540 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Mon, 5 Mar 2018 21:05:30 -0500 Subject: Update ledgerco packages --- packages/subproviders/package.json | 4 ++- packages/subproviders/src/globals.d.ts | 22 ++++++++++++ packages/subproviders/src/index.ts | 30 ++++++++-------- packages/subproviders/src/subproviders/ledger.ts | 8 ++--- packages/subproviders/src/types.ts | 44 +++++++++++++++++------- 5 files changed, 76 insertions(+), 32 deletions(-) diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index ec0642bce..7c02b5745 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -21,12 +21,14 @@ "@0xproject/assert": "^0.1.0", "@0xproject/types": "^0.3.0", "@0xproject/utils": "^0.4.0", + "@ledgerhq/hw-app-eth": "^4.3.0", + "@ledgerhq/hw-transport": "^4.3.0", + "@ledgerhq/hw-transport-u2f": "^4.3.0", "bn.js": "^4.11.8", "es6-promisify": "^5.0.0", "ethereumjs-tx": "^1.3.3", "ethereumjs-util": "^5.1.1", "hdkey": "^0.7.1", - "ledgerco": "0xProject/ledger-node-js-api", "lodash": "^4.17.4", "semaphore-async-await": "^1.5.1", "web3": "^0.20.0", diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts index 6f344dcd3..0c8b3fed3 100644 --- a/packages/subproviders/src/globals.d.ts +++ b/packages/subproviders/src/globals.d.ts @@ -32,6 +32,28 @@ interface ECSignature { r: string; s: string; } + +interface LedgerTransport { + close(): Promise +} + +declare module '@ledgerhq/hw-app-eth' { + export class Eth { + constructor(transport: LedgerTransport); + public getAddress(path: string, boolDisplay?: boolean, boolChaincode?: boolean): Promise<{ publicKey: string; address: string; chainCode: string }>; + public signTransaction(path: string, rawTxHex: string): Promise; + public getAppConfiguration(): Promise<{ arbitraryDataEnabled: number; version: string; }>; + public signPersonalMessage(path: string, messageHex: string): Promise; + transport: LedgerTransport; + } +} +declare module '@ledgerhq/hw-transport-u2f' { + export class TransportU2F implements LedgerTransport { + public static create(): Promise; + public close(): Promise; + } +} + declare module 'ledgerco' { interface comm { close_async(): Promise; diff --git a/packages/subproviders/src/index.ts b/packages/subproviders/src/index.ts index 4da405ec0..566743fd0 100644 --- a/packages/subproviders/src/index.ts +++ b/packages/subproviders/src/index.ts @@ -1,8 +1,10 @@ import { - comm_node as LedgerNodeCommunication, - comm_u2f as LedgerBrowserCommunication, - eth as LedgerEthereumClientFn, -} from 'ledgerco'; + Eth as LedgerEthereumClientFn, +} from '@ledgerhq/hw-app-eth'; + +import { + TransportU2F as LedgerBrowserCommunication, +} from '@ledgerhq/hw-transport-u2f'; import { LedgerEthereumClient } from './types'; @@ -19,17 +21,17 @@ export { ECSignature, LedgerWalletSubprovider, LedgerCommunicationClient, NonceS * @return LedgerEthereumClient A browser client */ export async function ledgerEthereumBrowserClientFactoryAsync(): Promise { - const ledgerConnection = await LedgerBrowserCommunication.create_async(); + const ledgerConnection = await LedgerBrowserCommunication.create(); const ledgerEthClient = new LedgerEthereumClientFn(ledgerConnection); return ledgerEthClient; } -/** - * A factory for creating a LedgerEthereumClient usable in a Node.js context. - * @return LedgerEthereumClient A Node.js client - */ -export async function ledgerEthereumNodeJsClientFactoryAsync(): Promise { - const ledgerConnection = await LedgerNodeCommunication.create_async(); - const ledgerEthClient = new LedgerEthereumClientFn(ledgerConnection); - return ledgerEthClient; -} +// /** +// * A factory for creating a LedgerEthereumClient usable in a Node.js context. +// * @return LedgerEthereumClient A Node.js client +// */ +// export async function ledgerEthereumNodeJsClientFactoryAsync(): Promise { +// const ledgerConnection = await LedgerNodeCommunication.create_async(); +// const ledgerEthClient = new LedgerEthereumClientFn(ledgerConnection); +// return ledgerEthClient; +// } diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts index 85cdf0efc..0a84caae3 100644 --- a/packages/subproviders/src/subproviders/ledger.ts +++ b/packages/subproviders/src/subproviders/ledger.ts @@ -134,7 +134,7 @@ export class LedgerSubprovider extends Subprovider { let ledgerResponse; try { - ledgerResponse = await this._ledgerClientIfExists.getAddress_async( + ledgerResponse = await this._ledgerClientIfExists.getAddress( this._derivationPath, this._shouldAlwaysAskForConfirmation, SHOULD_GET_CHAIN_CODE, @@ -173,7 +173,7 @@ export class LedgerSubprovider extends Subprovider { const txHex = tx.serialize().toString('hex'); try { const derivationPath = this._getDerivationPath(); - const result = await this._ledgerClientIfExists.signTransaction_async(derivationPath, txHex); + const result = await this._ledgerClientIfExists.signTransaction(derivationPath, txHex); // Store signature in transaction tx.r = Buffer.from(result.r, 'hex'); tx.s = Buffer.from(result.s, 'hex'); @@ -199,7 +199,7 @@ export class LedgerSubprovider extends Subprovider { this._ledgerClientIfExists = await this._createLedgerClientAsync(); try { const derivationPath = this._getDerivationPath(); - const result = await this._ledgerClientIfExists.signPersonalMessage_async( + const result = await this._ledgerClientIfExists.signPersonalMessage( derivationPath, ethUtil.stripHexPrefix(data), ); @@ -236,7 +236,7 @@ export class LedgerSubprovider extends Subprovider { this._connectionLock.signal(); return; } - await this._ledgerClientIfExists.comm.close_async(); + await this._ledgerClientIfExists.transport.close(); this._ledgerClientIfExists = undefined; this._connectionLock.signal(); } diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts index 65b7f6c8f..785547a22 100644 --- a/packages/subproviders/src/types.ts +++ b/packages/subproviders/src/types.ts @@ -1,7 +1,25 @@ import * as _ from 'lodash'; +declare class LedgerTransport { + // tslint:disable-next-line:async-suffix + public static create(): Promise; + // tslint:disable-next-line:async-suffix + public static close(): Promise; +} + export interface LedgerCommunicationClient { - close_async: () => Promise; + close: () => Promise; +} + +export interface LedgerEthereumClient { + getAddress: ( + derivationPath: string, + askForDeviceConfirmation?: boolean, + shouldGetChainCode?: boolean, + ) => Promise<{ publicKey: string; address: string; chainCode: string }>; + signTransaction: (derivationPath: string, rawTxHex: string) => Promise; + signPersonalMessage: (derivationPath: string, messageHex: string) => Promise; + transport: LedgerCommunicationClient; } /* @@ -9,18 +27,18 @@ export interface LedgerCommunicationClient { * It uses an internal LedgerCommunicationClient to relay these requests. Currently * 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: true, - ) => Promise; - signPersonalMessage_async: (derivationPath: string, messageHex: string) => Promise; - signTransaction_async: (derivationPath: string, txHex: string) => Promise; - comm: LedgerCommunicationClient; -} +// 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: true, +// ) => Promise; +// signPersonalMessage_async: (derivationPath: string, messageHex: string) => Promise; +// signTransaction_async: (derivationPath: string, txHex: string) => Promise; +// comm: LedgerCommunicationClient; +// } export interface ECSignatureString { v: string; -- cgit v1.2.3 From 71e7e9c9c3ed89c1c25f46085c0968a62099cb5a Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Mon, 5 Mar 2018 21:07:07 -0500 Subject: Remove old ledger --- packages/subproviders/src/globals.d.ts | 29 ----------------------------- packages/subproviders/src/index.ts | 10 ---------- 2 files changed, 39 deletions(-) diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts index 0c8b3fed3..1a9b2ad61 100644 --- a/packages/subproviders/src/globals.d.ts +++ b/packages/subproviders/src/globals.d.ts @@ -54,35 +54,6 @@ declare module '@ledgerhq/hw-transport-u2f' { } } -declare module 'ledgerco' { - interface comm { - close_async(): Promise; - } - export class comm_node implements comm { - public static create_async(timeoutMilliseconds?: number): Promise; - public close_async(): Promise; - } - export class comm_u2f implements comm { - public static create_async(): Promise; - public close_async(): Promise; - } - export class eth { - public comm: comm; - constructor(comm: comm); - public getAddress_async( - path: string, - display?: boolean, - chaincode?: boolean, - ): Promise<{ publicKey: string; address: string; chainCode: string }>; - public signTransaction_async(path: string, rawTxHex: string): Promise; - public getAppConfiguration_async(): Promise<{ - arbitraryDataEnabled: number; - version: string; - }>; - public signPersonalMessage_async(path: string, messageHex: string): Promise; - } -} - // Semaphore-async-await declarations declare module 'semaphore-async-await' { class Semaphore { diff --git a/packages/subproviders/src/index.ts b/packages/subproviders/src/index.ts index 566743fd0..d296c7be6 100644 --- a/packages/subproviders/src/index.ts +++ b/packages/subproviders/src/index.ts @@ -25,13 +25,3 @@ export async function ledgerEthereumBrowserClientFactoryAsync(): Promise { -// const ledgerConnection = await LedgerNodeCommunication.create_async(); -// const ledgerEthClient = new LedgerEthereumClientFn(ledgerConnection); -// return ledgerEthClient; -// } -- cgit v1.2.3 From 7bfc499ec8e50778dd33183646dd19ef66496052 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Mon, 5 Mar 2018 22:14:00 -0500 Subject: Nuke tests for now --- packages/subproviders/package.json | 1 - packages/subproviders/src/globals.d.ts | 17 +- packages/subproviders/src/index.ts | 13 +- packages/subproviders/src/types.ts | 32 +- .../test/integration/ledger_subprovider_test.ts | 366 ++++++++++----------- .../test/unit/ledger_subprovider_test.ts | 10 +- 6 files changed, 209 insertions(+), 230 deletions(-) diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index 7c02b5745..9e18f95e1 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -22,7 +22,6 @@ "@0xproject/types": "^0.3.0", "@0xproject/utils": "^0.4.0", "@ledgerhq/hw-app-eth": "^4.3.0", - "@ledgerhq/hw-transport": "^4.3.0", "@ledgerhq/hw-transport-u2f": "^4.3.0", "bn.js": "^4.11.8", "es6-promisify": "^5.0.0", diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts index 1a9b2ad61..238d9be78 100644 --- a/packages/subproviders/src/globals.d.ts +++ b/packages/subproviders/src/globals.d.ts @@ -34,22 +34,27 @@ interface ECSignature { } interface LedgerTransport { - close(): Promise + close(): Promise; } declare module '@ledgerhq/hw-app-eth' { - export class Eth { + class Eth { constructor(transport: LedgerTransport); - public getAddress(path: string, boolDisplay?: boolean, boolChaincode?: boolean): Promise<{ publicKey: string; address: string; chainCode: string }>; + public getAddress( + path: string, + boolDisplay?: boolean, + boolChaincode?: boolean, + ): Promise<{ publicKey: string; address: string; chainCode: string }>; public signTransaction(path: string, rawTxHex: string): Promise; - public getAppConfiguration(): Promise<{ arbitraryDataEnabled: number; version: string; }>; + public getAppConfiguration(): Promise<{ arbitraryDataEnabled: number; version: string }>; public signPersonalMessage(path: string, messageHex: string): Promise; transport: LedgerTransport; } + export default Eth; } declare module '@ledgerhq/hw-transport-u2f' { - export class TransportU2F implements LedgerTransport { - public static create(): Promise; + export default class TransportU2F { + public static create(): Promise; public close(): Promise; } } diff --git a/packages/subproviders/src/index.ts b/packages/subproviders/src/index.ts index d296c7be6..e22b6f5f3 100644 --- a/packages/subproviders/src/index.ts +++ b/packages/subproviders/src/index.ts @@ -1,10 +1,5 @@ -import { - Eth as LedgerEthereumClientFn, -} from '@ledgerhq/hw-app-eth'; - -import { - TransportU2F as LedgerBrowserCommunication, -} from '@ledgerhq/hw-transport-u2f'; +import Eth from '@ledgerhq/hw-app-eth'; +import TransportU2F from '@ledgerhq/hw-transport-u2f'; import { LedgerEthereumClient } from './types'; @@ -21,7 +16,7 @@ export { ECSignature, LedgerWalletSubprovider, LedgerCommunicationClient, NonceS * @return LedgerEthereumClient A browser client */ export async function ledgerEthereumBrowserClientFactoryAsync(): Promise { - const ledgerConnection = await LedgerBrowserCommunication.create(); - const ledgerEthClient = new LedgerEthereumClientFn(ledgerConnection); + const ledgerConnection = await TransportU2F.create(); + const ledgerEthClient = new Eth(ledgerConnection); return ledgerEthClient; } diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts index 785547a22..11a178f69 100644 --- a/packages/subproviders/src/types.ts +++ b/packages/subproviders/src/types.ts @@ -1,45 +1,25 @@ import * as _ from 'lodash'; -declare class LedgerTransport { - // tslint:disable-next-line:async-suffix - public static create(): Promise; - // tslint:disable-next-line:async-suffix - public static close(): Promise; -} - export interface LedgerCommunicationClient { close: () => Promise; } +/* + * The LedgerEthereumClient sends Ethereum-specific requests to the Ledger Nano S + * It uses an internal LedgerCommunicationClient to relay these requests. Currently + * NodeJs and Browser communication are supported. + */ export interface LedgerEthereumClient { getAddress: ( derivationPath: string, askForDeviceConfirmation?: boolean, shouldGetChainCode?: boolean, - ) => Promise<{ publicKey: string; address: string; chainCode: string }>; + ) => Promise; signTransaction: (derivationPath: string, rawTxHex: string) => Promise; signPersonalMessage: (derivationPath: string, messageHex: string) => Promise; transport: LedgerCommunicationClient; } -/* - * The LedgerEthereumClient sends Ethereum-specific requests to the Ledger Nano S - * It uses an internal LedgerCommunicationClient to relay these requests. Currently - * 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: true, -// ) => Promise; -// signPersonalMessage_async: (derivationPath: string, messageHex: string) => Promise; -// signTransaction_async: (derivationPath: string, txHex: string) => Promise; -// comm: LedgerCommunicationClient; -// } - export interface ECSignatureString { v: string; r: string; diff --git a/packages/subproviders/test/integration/ledger_subprovider_test.ts b/packages/subproviders/test/integration/ledger_subprovider_test.ts index b052a76d2..979215bbe 100644 --- a/packages/subproviders/test/integration/ledger_subprovider_test.ts +++ b/packages/subproviders/test/integration/ledger_subprovider_test.ts @@ -1,190 +1,190 @@ -import * as chai from 'chai'; -import promisify = require('es6-promisify'); -import * as ethUtils from 'ethereumjs-util'; -import * as _ from 'lodash'; -import Web3 = require('web3'); -import Web3ProviderEngine = require('web3-provider-engine'); -import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); +// import * as chai from 'chai'; +// import promisify = require('es6-promisify'); +// import * as ethUtils from 'ethereumjs-util'; +// import * as _ from 'lodash'; +// import Web3 = require('web3'); +// import Web3ProviderEngine = require('web3-provider-engine'); +// import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); -import { ledgerEthereumNodeJsClientFactoryAsync, LedgerSubprovider } from '../../src'; -import { DoneCallback } from '../../src/types'; -import { chaiSetup } from '../chai_setup'; -import { reportCallbackErrors } from '../utils/report_callback_errors'; +// import { ledgerEthereumNodeJsClientFactoryAsync, LedgerSubprovider } from '../../src'; +// import { DoneCallback } from '../../src/types'; +// import { chaiSetup } from '../chai_setup'; +// import { reportCallbackErrors } from '../utils/report_callback_errors'; -chaiSetup.configure(); -const expect = chai.expect; +// chaiSetup.configure(); +// const expect = chai.expect; -const TEST_RPC_ACCOUNT_0 = '0x5409ed021d9299bf6814279a6a1411a7e866a631'; +// const TEST_RPC_ACCOUNT_0 = '0x5409ed021d9299bf6814279a6a1411a7e866a631'; -describe('LedgerSubprovider', () => { - let ledgerSubprovider: LedgerSubprovider; - const networkId: number = 42; - before(async () => { - ledgerSubprovider = new LedgerSubprovider({ - networkId, - ledgerEthereumClientFactoryAsync: ledgerEthereumNodeJsClientFactoryAsync, - }); - }); - describe('direct method calls', () => { - it('returns default number of accounts', async () => { - const accounts = await ledgerSubprovider.getAccountsAsync(); - expect(accounts[0]).to.not.be.an('undefined'); - expect(accounts.length).to.be.equal(10); - }); - it('returns requested number of accounts', async () => { - const numberOfAccounts = 20; - const accounts = await ledgerSubprovider.getAccountsAsync(numberOfAccounts); - expect(accounts[0]).to.not.be.an('undefined'); - expect(accounts.length).to.be.equal(numberOfAccounts); - }); - it('signs a personal message', async () => { - const data = ethUtils.bufferToHex(ethUtils.toBuffer('hello world')); - const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(data); - expect(ecSignatureHex.length).to.be.equal(132); - expect(ecSignatureHex.substr(0, 2)).to.be.equal('0x'); - }); - it('signs a transaction', async () => { - const tx = { - nonce: '0x00', - gas: '0x2710', - to: '0x0000000000000000000000000000000000000000', - value: '0x00', - chainId: 3, - }; - const txHex = await ledgerSubprovider.signTransactionAsync(tx); - expect(txHex).to.be.equal( - '0xf85f8080822710940000000000000000000000000000000000000000808077a088a95ef1378487bc82be558e82c8478baf840c545d5b887536bb1da63673a98ba0019f4a4b9a107d1e6752bf7f701e275f28c13791d6e76af895b07373462cefaa', - ); - }); - }); - describe('calls through a provider', () => { - let defaultProvider: Web3ProviderEngine; - let ledgerProvider: Web3ProviderEngine; - before(() => { - ledgerProvider = new Web3ProviderEngine(); - ledgerProvider.addProvider(ledgerSubprovider); - const httpProvider = new RpcSubprovider({ - rpcUrl: 'http://localhost:8545', - }); - ledgerProvider.addProvider(httpProvider); - ledgerProvider.start(); +// describe('LedgerSubprovider', () => { +// let ledgerSubprovider: LedgerSubprovider; +// const networkId: number = 42; +// before(async () => { +// ledgerSubprovider = new LedgerSubprovider({ +// networkId, +// ledgerEthereumClientFactoryAsync: ledgerEthereumNodeJsClientFactoryAsync, +// }); +// }); +// describe('direct method calls', () => { +// it('returns default number of accounts', async () => { +// const accounts = await ledgerSubprovider.getAccountsAsync(); +// expect(accounts[0]).to.not.be.an('undefined'); +// expect(accounts.length).to.be.equal(10); +// }); +// it('returns requested number of accounts', async () => { +// const numberOfAccounts = 20; +// const accounts = await ledgerSubprovider.getAccountsAsync(numberOfAccounts); +// expect(accounts[0]).to.not.be.an('undefined'); +// expect(accounts.length).to.be.equal(numberOfAccounts); +// }); +// it('signs a personal message', async () => { +// const data = ethUtils.bufferToHex(ethUtils.toBuffer('hello world')); +// const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(data); +// expect(ecSignatureHex.length).to.be.equal(132); +// expect(ecSignatureHex.substr(0, 2)).to.be.equal('0x'); +// }); +// it('signs a transaction', async () => { +// const tx = { +// nonce: '0x00', +// gas: '0x2710', +// to: '0x0000000000000000000000000000000000000000', +// value: '0x00', +// chainId: 3, +// }; +// const txHex = await ledgerSubprovider.signTransactionAsync(tx); +// expect(txHex).to.be.equal( +// '0xf85f8080822710940000000000000000000000000000000000000000808077a088a95ef1378487bc82be558e82c8478baf840c545d5b887536bb1da63673a98ba0019f4a4b9a107d1e6752bf7f701e275f28c13791d6e76af895b07373462cefaa', +// ); +// }); +// }); +// describe('calls through a provider', () => { +// let defaultProvider: Web3ProviderEngine; +// let ledgerProvider: Web3ProviderEngine; +// before(() => { +// ledgerProvider = new Web3ProviderEngine(); +// ledgerProvider.addProvider(ledgerSubprovider); +// const httpProvider = new RpcSubprovider({ +// rpcUrl: 'http://localhost:8545', +// }); +// ledgerProvider.addProvider(httpProvider); +// ledgerProvider.start(); - defaultProvider = new Web3ProviderEngine(); - defaultProvider.addProvider(httpProvider); - defaultProvider.start(); - }); - it('returns a list of accounts', (done: DoneCallback) => { - const payload = { - jsonrpc: '2.0', - method: 'eth_accounts', - params: [], - id: 1, - }; - const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { - expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(10); - done(); - }); - ledgerProvider.sendAsync(payload, callback); - }); - it('signs a personal message with eth_sign', (done: DoneCallback) => { - (async () => { - const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world')); - const accounts = await ledgerSubprovider.getAccountsAsync(); - const signer = accounts[0]; - const payload = { - jsonrpc: '2.0', - method: 'eth_sign', - params: [signer, messageHex], - id: 1, - }; - const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { - expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(132); - expect(response.result.substr(0, 2)).to.be.equal('0x'); - done(); - }); - ledgerProvider.sendAsync(payload, callback); - })().catch(done); - }); - it('signs a personal message with personal_sign', (done: DoneCallback) => { - (async () => { - const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world')); - const accounts = await ledgerSubprovider.getAccountsAsync(); - const signer = accounts[0]; - const payload = { - jsonrpc: '2.0', - method: 'personal_sign', - params: [messageHex, signer], - id: 1, - }; - const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { - expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(132); - expect(response.result.substr(0, 2)).to.be.equal('0x'); - done(); - }); - ledgerProvider.sendAsync(payload, callback); - })().catch(done); - }); - it('signs a transaction', (done: DoneCallback) => { - const tx = { - to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66', - value: '0x00', - }; - const payload = { - jsonrpc: '2.0', - method: 'eth_signTransaction', - params: [tx], - id: 1, - }; - const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { - expect(err).to.be.a('null'); - expect(response.result.raw.length).to.be.equal(206); - expect(response.result.raw.substr(0, 2)).to.be.equal('0x'); - done(); - }); - ledgerProvider.sendAsync(payload, callback); - }); - it('signs and sends a transaction', (done: DoneCallback) => { - (async () => { - const accounts = await ledgerSubprovider.getAccountsAsync(); +// defaultProvider = new Web3ProviderEngine(); +// defaultProvider.addProvider(httpProvider); +// defaultProvider.start(); +// }); +// it('returns a list of accounts', (done: DoneCallback) => { +// const payload = { +// jsonrpc: '2.0', +// method: 'eth_accounts', +// params: [], +// id: 1, +// }; +// const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { +// expect(err).to.be.a('null'); +// expect(response.result.length).to.be.equal(10); +// done(); +// }); +// ledgerProvider.sendAsync(payload, callback); +// }); +// it('signs a personal message with eth_sign', (done: DoneCallback) => { +// (async () => { +// const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world')); +// const accounts = await ledgerSubprovider.getAccountsAsync(); +// const signer = accounts[0]; +// const payload = { +// jsonrpc: '2.0', +// method: 'eth_sign', +// params: [signer, messageHex], +// id: 1, +// }; +// const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { +// expect(err).to.be.a('null'); +// expect(response.result.length).to.be.equal(132); +// expect(response.result.substr(0, 2)).to.be.equal('0x'); +// done(); +// }); +// ledgerProvider.sendAsync(payload, callback); +// })().catch(done); +// }); +// it('signs a personal message with personal_sign', (done: DoneCallback) => { +// (async () => { +// const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world')); +// const accounts = await ledgerSubprovider.getAccountsAsync(); +// const signer = accounts[0]; +// const payload = { +// jsonrpc: '2.0', +// method: 'personal_sign', +// params: [messageHex, signer], +// id: 1, +// }; +// const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { +// expect(err).to.be.a('null'); +// expect(response.result.length).to.be.equal(132); +// expect(response.result.substr(0, 2)).to.be.equal('0x'); +// done(); +// }); +// ledgerProvider.sendAsync(payload, callback); +// })().catch(done); +// }); +// it('signs a transaction', (done: DoneCallback) => { +// const tx = { +// to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66', +// value: '0x00', +// }; +// const payload = { +// jsonrpc: '2.0', +// method: 'eth_signTransaction', +// params: [tx], +// id: 1, +// }; +// const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { +// expect(err).to.be.a('null'); +// expect(response.result.raw.length).to.be.equal(206); +// expect(response.result.raw.substr(0, 2)).to.be.equal('0x'); +// done(); +// }); +// ledgerProvider.sendAsync(payload, callback); +// }); +// it('signs and sends a transaction', (done: DoneCallback) => { +// (async () => { +// const accounts = await ledgerSubprovider.getAccountsAsync(); - // Give first account on Ledger sufficient ETH to complete tx send - let tx = { - to: accounts[0], - from: TEST_RPC_ACCOUNT_0, - value: '0x8ac7230489e80000', // 10 ETH - }; - let payload = { - jsonrpc: '2.0', - method: 'eth_sendTransaction', - params: [tx], - id: 1, - }; - await promisify(defaultProvider.sendAsync, defaultProvider)(payload); +// // Give first account on Ledger sufficient ETH to complete tx send +// let tx = { +// to: accounts[0], +// from: TEST_RPC_ACCOUNT_0, +// value: '0x8ac7230489e80000', // 10 ETH +// }; +// let payload = { +// jsonrpc: '2.0', +// method: 'eth_sendTransaction', +// params: [tx], +// id: 1, +// }; +// await promisify(defaultProvider.sendAsync, defaultProvider)(payload); - // Send transaction from Ledger - tx = { - to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66', - from: accounts[0], - value: '0xde0b6b3a7640000', - }; - payload = { - jsonrpc: '2.0', - method: 'eth_sendTransaction', - params: [tx], - id: 1, - }; - const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { - expect(err).to.be.a('null'); - const result = response.result; - expect(result.length).to.be.equal(66); - expect(result.substr(0, 2)).to.be.equal('0x'); - done(); - }); - ledgerProvider.sendAsync(payload, callback); - })().catch(done); - }); - }); -}); +// // Send transaction from Ledger +// tx = { +// to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66', +// from: accounts[0], +// value: '0xde0b6b3a7640000', +// }; +// payload = { +// jsonrpc: '2.0', +// method: 'eth_sendTransaction', +// params: [tx], +// id: 1, +// }; +// const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { +// expect(err).to.be.a('null'); +// const result = response.result; +// expect(result.length).to.be.equal(66); +// expect(result.substr(0, 2)).to.be.equal('0x'); +// done(); +// }); +// ledgerProvider.sendAsync(payload, callback); +// })().catch(done); +// }); +// }); +// }); diff --git a/packages/subproviders/test/unit/ledger_subprovider_test.ts b/packages/subproviders/test/unit/ledger_subprovider_test.ts index 0d301bce9..4c0803a29 100644 --- a/packages/subproviders/test/unit/ledger_subprovider_test.ts +++ b/packages/subproviders/test/unit/ledger_subprovider_test.ts @@ -21,7 +21,7 @@ describe('LedgerSubprovider', () => { const ledgerEthereumClientFactoryAsync = async () => { // tslint:disable:no-object-literal-type-assertion const ledgerEthClient = { - getAddress_async: async () => { + getAddress: async () => { const publicKey = '04f428290f4c5ed6a198f71b8205f488141dbb3f0840c923bbfa798ecbee6370986c03b5575d94d506772fb48a6a44e345e4ebd4f028a6f609c44b655d6d3e71a1'; const chainCode = 'ac055a5537c0c7e9e02d14a197cad6b857836da2a12043b46912a37d959b5ae8'; @@ -32,7 +32,7 @@ describe('LedgerSubprovider', () => { chainCode, }; }, - signPersonalMessage_async: async () => { + signPersonalMessage: async () => { const ecSignature = { v: 28, r: 'a6cc284bff14b42bdf5e9286730c152be91719d478605ec46b3bebcd0ae49148', @@ -40,7 +40,7 @@ describe('LedgerSubprovider', () => { }; return ecSignature; }, - signTransaction_async: async (derivationPath: string, txHex: string) => { + signTransaction: async (derivationPath: string, txHex: string) => { const ecSignature = { v: '77', r: '88a95ef1378487bc82be558e82c8478baf840c545d5b887536bb1da63673a98b', @@ -48,8 +48,8 @@ describe('LedgerSubprovider', () => { }; return ecSignature; }, - comm: { - close_async: _.noop, + transport: { + close: _.noop, } as LedgerCommunicationClient, }; // tslint:enable:no-object-literal-type-assertion -- cgit v1.2.3 From f3026e33fd439bbd550e1814b5f067c36290638b Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Tue, 6 Mar 2018 08:57:54 -0500 Subject: Force shouldGetChainCode to true in types --- packages/subproviders/src/types.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts index 11a178f69..f49ac6107 100644 --- a/packages/subproviders/src/types.ts +++ b/packages/subproviders/src/types.ts @@ -10,10 +10,12 @@ 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: ( derivationPath: string, - askForDeviceConfirmation?: boolean, - shouldGetChainCode?: boolean, + askForDeviceConfirmation: boolean, + shouldGetChainCode: true, ) => Promise; signTransaction: (derivationPath: string, rawTxHex: string) => Promise; signPersonalMessage: (derivationPath: string, messageHex: string) => Promise; -- cgit v1.2.3 From d7373a5c0455ef81a5a1852123136e4724f13e36 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Tue, 6 Mar 2018 20:25:21 -0500 Subject: Add ledger-node package as optional dependency --- packages/subproviders/CHANGELOG.md | 4 + packages/subproviders/package.json | 3 + packages/subproviders/src/globals.d.ts | 10 +- .../test/integration/ledger_subprovider_test.ts | 375 +++++++++++---------- 4 files changed, 208 insertions(+), 184 deletions(-) diff --git a/packages/subproviders/CHANGELOG.md b/packages/subproviders/CHANGELOG.md index 7e1e006e3..b7247748e 100644 --- a/packages/subproviders/CHANGELOG.md +++ b/packages/subproviders/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## v0.7.0 - _March 6, 2018_ + + * Updated legerco packages. Removed node-hid packages as a dependency. (#437) + ## v0.6.0 - _March 4, 2018_ * Move web3 types from being a devDep to a dep since one cannot use this package without it (#429) diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index 9e18f95e1..a3e865d24 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -54,5 +54,8 @@ "types-ethereumjs-util": "0xProject/types-ethereumjs-util", "typescript": "2.7.1", "webpack": "^3.1.0" + }, + "optionalDependencies": { + "@ledgerhq/hw-transport-node-hid": "^4.3.0" } } diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts index 238d9be78..e258ef947 100644 --- a/packages/subproviders/src/globals.d.ts +++ b/packages/subproviders/src/globals.d.ts @@ -39,6 +39,7 @@ interface LedgerTransport { declare module '@ledgerhq/hw-app-eth' { class Eth { + public transport: LedgerTransport; constructor(transport: LedgerTransport); public getAddress( path: string, @@ -48,10 +49,10 @@ declare module '@ledgerhq/hw-app-eth' { public signTransaction(path: string, rawTxHex: string): Promise; public getAppConfiguration(): Promise<{ arbitraryDataEnabled: number; version: string }>; public signPersonalMessage(path: string, messageHex: string): Promise; - transport: LedgerTransport; } export default Eth; } + declare module '@ledgerhq/hw-transport-u2f' { export default class TransportU2F { public static create(): Promise; @@ -59,6 +60,13 @@ declare module '@ledgerhq/hw-transport-u2f' { } } +declare module '@ledgerhq/hw-transport-node-hid' { + export default class TransportNodeHid { + public static create(): Promise; + public close(): Promise; + } +} + // Semaphore-async-await declarations declare module 'semaphore-async-await' { class Semaphore { diff --git a/packages/subproviders/test/integration/ledger_subprovider_test.ts b/packages/subproviders/test/integration/ledger_subprovider_test.ts index 979215bbe..86faebbd3 100644 --- a/packages/subproviders/test/integration/ledger_subprovider_test.ts +++ b/packages/subproviders/test/integration/ledger_subprovider_test.ts @@ -1,190 +1,199 @@ -// import * as chai from 'chai'; -// import promisify = require('es6-promisify'); -// import * as ethUtils from 'ethereumjs-util'; -// import * as _ from 'lodash'; -// import Web3 = require('web3'); -// import Web3ProviderEngine = require('web3-provider-engine'); -// import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); +import Eth from '@ledgerhq/hw-app-eth'; +// tslint:disable-next-line:no-implicit-dependencies +import TransportNodeHid from '@ledgerhq/hw-transport-node-hid'; +import * as chai from 'chai'; +import promisify = require('es6-promisify'); +import * as ethUtils from 'ethereumjs-util'; +import * as _ from 'lodash'; +import Web3 = require('web3'); +import Web3ProviderEngine = require('web3-provider-engine'); +import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); -// import { ledgerEthereumNodeJsClientFactoryAsync, LedgerSubprovider } from '../../src'; -// import { DoneCallback } from '../../src/types'; -// import { chaiSetup } from '../chai_setup'; -// import { reportCallbackErrors } from '../utils/report_callback_errors'; +import { LedgerSubprovider } from '../../src'; +import { DoneCallback, LedgerEthereumClient } from '../../src/types'; +import { chaiSetup } from '../chai_setup'; +import { reportCallbackErrors } from '../utils/report_callback_errors'; -// chaiSetup.configure(); -// const expect = chai.expect; +chaiSetup.configure(); +const expect = chai.expect; -// const TEST_RPC_ACCOUNT_0 = '0x5409ed021d9299bf6814279a6a1411a7e866a631'; +async function ledgerEthereumNodeJsClientFactoryAsync(): Promise { + const ledgerConnection = await TransportNodeHid.create(); + const ledgerEthClient = new Eth(ledgerConnection); + return ledgerEthClient; +} -// describe('LedgerSubprovider', () => { -// let ledgerSubprovider: LedgerSubprovider; -// const networkId: number = 42; -// before(async () => { -// ledgerSubprovider = new LedgerSubprovider({ -// networkId, -// ledgerEthereumClientFactoryAsync: ledgerEthereumNodeJsClientFactoryAsync, -// }); -// }); -// describe('direct method calls', () => { -// it('returns default number of accounts', async () => { -// const accounts = await ledgerSubprovider.getAccountsAsync(); -// expect(accounts[0]).to.not.be.an('undefined'); -// expect(accounts.length).to.be.equal(10); -// }); -// it('returns requested number of accounts', async () => { -// const numberOfAccounts = 20; -// const accounts = await ledgerSubprovider.getAccountsAsync(numberOfAccounts); -// expect(accounts[0]).to.not.be.an('undefined'); -// expect(accounts.length).to.be.equal(numberOfAccounts); -// }); -// it('signs a personal message', async () => { -// const data = ethUtils.bufferToHex(ethUtils.toBuffer('hello world')); -// const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(data); -// expect(ecSignatureHex.length).to.be.equal(132); -// expect(ecSignatureHex.substr(0, 2)).to.be.equal('0x'); -// }); -// it('signs a transaction', async () => { -// const tx = { -// nonce: '0x00', -// gas: '0x2710', -// to: '0x0000000000000000000000000000000000000000', -// value: '0x00', -// chainId: 3, -// }; -// const txHex = await ledgerSubprovider.signTransactionAsync(tx); -// expect(txHex).to.be.equal( -// '0xf85f8080822710940000000000000000000000000000000000000000808077a088a95ef1378487bc82be558e82c8478baf840c545d5b887536bb1da63673a98ba0019f4a4b9a107d1e6752bf7f701e275f28c13791d6e76af895b07373462cefaa', -// ); -// }); -// }); -// describe('calls through a provider', () => { -// let defaultProvider: Web3ProviderEngine; -// let ledgerProvider: Web3ProviderEngine; -// before(() => { -// ledgerProvider = new Web3ProviderEngine(); -// ledgerProvider.addProvider(ledgerSubprovider); -// const httpProvider = new RpcSubprovider({ -// rpcUrl: 'http://localhost:8545', -// }); -// ledgerProvider.addProvider(httpProvider); -// ledgerProvider.start(); +const TEST_RPC_ACCOUNT_0 = '0x5409ed021d9299bf6814279a6a1411a7e866a631'; -// defaultProvider = new Web3ProviderEngine(); -// defaultProvider.addProvider(httpProvider); -// defaultProvider.start(); -// }); -// it('returns a list of accounts', (done: DoneCallback) => { -// const payload = { -// jsonrpc: '2.0', -// method: 'eth_accounts', -// params: [], -// id: 1, -// }; -// const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { -// expect(err).to.be.a('null'); -// expect(response.result.length).to.be.equal(10); -// done(); -// }); -// ledgerProvider.sendAsync(payload, callback); -// }); -// it('signs a personal message with eth_sign', (done: DoneCallback) => { -// (async () => { -// const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world')); -// const accounts = await ledgerSubprovider.getAccountsAsync(); -// const signer = accounts[0]; -// const payload = { -// jsonrpc: '2.0', -// method: 'eth_sign', -// params: [signer, messageHex], -// id: 1, -// }; -// const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { -// expect(err).to.be.a('null'); -// expect(response.result.length).to.be.equal(132); -// expect(response.result.substr(0, 2)).to.be.equal('0x'); -// done(); -// }); -// ledgerProvider.sendAsync(payload, callback); -// })().catch(done); -// }); -// it('signs a personal message with personal_sign', (done: DoneCallback) => { -// (async () => { -// const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world')); -// const accounts = await ledgerSubprovider.getAccountsAsync(); -// const signer = accounts[0]; -// const payload = { -// jsonrpc: '2.0', -// method: 'personal_sign', -// params: [messageHex, signer], -// id: 1, -// }; -// const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { -// expect(err).to.be.a('null'); -// expect(response.result.length).to.be.equal(132); -// expect(response.result.substr(0, 2)).to.be.equal('0x'); -// done(); -// }); -// ledgerProvider.sendAsync(payload, callback); -// })().catch(done); -// }); -// it('signs a transaction', (done: DoneCallback) => { -// const tx = { -// to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66', -// value: '0x00', -// }; -// const payload = { -// jsonrpc: '2.0', -// method: 'eth_signTransaction', -// params: [tx], -// id: 1, -// }; -// const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { -// expect(err).to.be.a('null'); -// expect(response.result.raw.length).to.be.equal(206); -// expect(response.result.raw.substr(0, 2)).to.be.equal('0x'); -// done(); -// }); -// ledgerProvider.sendAsync(payload, callback); -// }); -// it('signs and sends a transaction', (done: DoneCallback) => { -// (async () => { -// const accounts = await ledgerSubprovider.getAccountsAsync(); +describe('LedgerSubprovider', () => { + let ledgerSubprovider: LedgerSubprovider; + const networkId: number = 42; + before(async () => { + ledgerSubprovider = new LedgerSubprovider({ + networkId, + ledgerEthereumClientFactoryAsync: ledgerEthereumNodeJsClientFactoryAsync, + }); + }); + describe('direct method calls', () => { + it('returns default number of accounts', async () => { + const accounts = await ledgerSubprovider.getAccountsAsync(); + expect(accounts[0]).to.not.be.an('undefined'); + expect(accounts.length).to.be.equal(10); + }); + it('returns requested number of accounts', async () => { + const numberOfAccounts = 20; + const accounts = await ledgerSubprovider.getAccountsAsync(numberOfAccounts); + expect(accounts[0]).to.not.be.an('undefined'); + expect(accounts.length).to.be.equal(numberOfAccounts); + }); + it('signs a personal message', async () => { + const data = ethUtils.bufferToHex(ethUtils.toBuffer('hello world')); + const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(data); + expect(ecSignatureHex.length).to.be.equal(132); + expect(ecSignatureHex.substr(0, 2)).to.be.equal('0x'); + }); + it('signs a transaction', async () => { + const tx = { + nonce: '0x00', + gas: '0x2710', + to: '0x0000000000000000000000000000000000000000', + value: '0x00', + chainId: 3, + }; + const txHex = await ledgerSubprovider.signTransactionAsync(tx); + expect(txHex).to.be.equal( + '0xf85f8080822710940000000000000000000000000000000000000000808077a088a95ef1378487bc82be558e82c8478baf840c545d5b887536bb1da63673a98ba0019f4a4b9a107d1e6752bf7f701e275f28c13791d6e76af895b07373462cefaa', + ); + }); + }); + describe('calls through a provider', () => { + let defaultProvider: Web3ProviderEngine; + let ledgerProvider: Web3ProviderEngine; + before(() => { + ledgerProvider = new Web3ProviderEngine(); + ledgerProvider.addProvider(ledgerSubprovider); + const httpProvider = new RpcSubprovider({ + rpcUrl: 'http://localhost:8545', + }); + ledgerProvider.addProvider(httpProvider); + ledgerProvider.start(); -// // Give first account on Ledger sufficient ETH to complete tx send -// let tx = { -// to: accounts[0], -// from: TEST_RPC_ACCOUNT_0, -// value: '0x8ac7230489e80000', // 10 ETH -// }; -// let payload = { -// jsonrpc: '2.0', -// method: 'eth_sendTransaction', -// params: [tx], -// id: 1, -// }; -// await promisify(defaultProvider.sendAsync, defaultProvider)(payload); + defaultProvider = new Web3ProviderEngine(); + defaultProvider.addProvider(httpProvider); + defaultProvider.start(); + }); + it('returns a list of accounts', (done: DoneCallback) => { + const payload = { + jsonrpc: '2.0', + method: 'eth_accounts', + params: [], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { + expect(err).to.be.a('null'); + expect(response.result.length).to.be.equal(10); + done(); + }); + ledgerProvider.sendAsync(payload, callback); + }); + it('signs a personal message with eth_sign', (done: DoneCallback) => { + (async () => { + const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world')); + const accounts = await ledgerSubprovider.getAccountsAsync(); + const signer = accounts[0]; + const payload = { + jsonrpc: '2.0', + method: 'eth_sign', + params: [signer, messageHex], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { + expect(err).to.be.a('null'); + expect(response.result.length).to.be.equal(132); + expect(response.result.substr(0, 2)).to.be.equal('0x'); + done(); + }); + ledgerProvider.sendAsync(payload, callback); + })().catch(done); + }); + it('signs a personal message with personal_sign', (done: DoneCallback) => { + (async () => { + const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world')); + const accounts = await ledgerSubprovider.getAccountsAsync(); + const signer = accounts[0]; + const payload = { + jsonrpc: '2.0', + method: 'personal_sign', + params: [messageHex, signer], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { + expect(err).to.be.a('null'); + expect(response.result.length).to.be.equal(132); + expect(response.result.substr(0, 2)).to.be.equal('0x'); + done(); + }); + ledgerProvider.sendAsync(payload, callback); + })().catch(done); + }); + it('signs a transaction', (done: DoneCallback) => { + const tx = { + to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66', + value: '0x00', + }; + const payload = { + jsonrpc: '2.0', + method: 'eth_signTransaction', + params: [tx], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { + expect(err).to.be.a('null'); + expect(response.result.raw.length).to.be.equal(206); + expect(response.result.raw.substr(0, 2)).to.be.equal('0x'); + done(); + }); + ledgerProvider.sendAsync(payload, callback); + }); + it('signs and sends a transaction', (done: DoneCallback) => { + (async () => { + const accounts = await ledgerSubprovider.getAccountsAsync(); -// // Send transaction from Ledger -// tx = { -// to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66', -// from: accounts[0], -// value: '0xde0b6b3a7640000', -// }; -// payload = { -// jsonrpc: '2.0', -// method: 'eth_sendTransaction', -// params: [tx], -// id: 1, -// }; -// const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { -// expect(err).to.be.a('null'); -// const result = response.result; -// expect(result.length).to.be.equal(66); -// expect(result.substr(0, 2)).to.be.equal('0x'); -// done(); -// }); -// ledgerProvider.sendAsync(payload, callback); -// })().catch(done); -// }); -// }); -// }); + // Give first account on Ledger sufficient ETH to complete tx send + let tx = { + to: accounts[0], + from: TEST_RPC_ACCOUNT_0, + value: '0x8ac7230489e80000', // 10 ETH + }; + let payload = { + jsonrpc: '2.0', + method: 'eth_sendTransaction', + params: [tx], + id: 1, + }; + await promisify(defaultProvider.sendAsync, defaultProvider)(payload); + + // Send transaction from Ledger + tx = { + to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66', + from: accounts[0], + value: '0xde0b6b3a7640000', + }; + payload = { + jsonrpc: '2.0', + method: 'eth_sendTransaction', + params: [tx], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => { + expect(err).to.be.a('null'); + const result = response.result; + expect(result.length).to.be.equal(66); + expect(result.substr(0, 2)).to.be.equal('0x'); + done(); + }); + ledgerProvider.sendAsync(payload, callback); + })().catch(done); + }); + }); +}); -- cgit v1.2.3 From a941f0ffb6c4c011160e04522613318a3da9c5b5 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Tue, 6 Mar 2018 20:49:05 -0500 Subject: README --- packages/subproviders/README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/subproviders/README.md b/packages/subproviders/README.md index 67a6a92d2..52ad3388e 100644 --- a/packages/subproviders/README.md +++ b/packages/subproviders/README.md @@ -42,6 +42,26 @@ const accounts = await ledgerSubprovider.getAccountsAsync(); A subprovider that enables your dApp to send signing requests to a user's Ledger Nano S hardware wallet. These can be requests to sign transactions or messages. +##### Ledger Nano S + Node-hid (usb) + +By default, node-hid transport support is an optional dependency. This is due to the requirement of native usb developer packages on the host system. If these aren't installed the entire `npm install` fails. We also no longer export node-hid transport client factories. To re-create this see our integration tests or follow the example below: + +```typescript +import Eth from '@ledgerhq/hw-app-eth'; +import TransportNodeHid from '@ledgerhq/hw-transport-node-hid'; +async function ledgerEthereumNodeJsClientFactoryAsync(): Promise { + const ledgerConnection = await TransportNodeHid.create(); + const ledgerEthClient = new Eth(ledgerConnection); + return ledgerEthClient; +} + +// Create a LedgerSubprovider with the node-hid transport +ledgerSubprovider = new LedgerSubprovider({ + networkId, + ledgerEthereumClientFactoryAsync: ledgerEthereumNodeJsClientFactoryAsync, +}); +``` + #### Redundant RPC subprovider A subprovider which attempts to send an RPC call to a list of RPC endpoints sequentially, until one of them returns a successful response. -- cgit v1.2.3 From 5b9c5d27906dc2a3b4462599a1a67e43a4210ebd Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Wed, 7 Mar 2018 11:59:09 -0500 Subject: Use our dev seed derivation path. Ensuring our signer address is 0x5409ed021d9299bf6814279a6a1411a7e866a631 --- packages/subproviders/test/integration/ledger_subprovider_test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/subproviders/test/integration/ledger_subprovider_test.ts b/packages/subproviders/test/integration/ledger_subprovider_test.ts index 86faebbd3..a9f538038 100644 --- a/packages/subproviders/test/integration/ledger_subprovider_test.ts +++ b/packages/subproviders/test/integration/ledger_subprovider_test.ts @@ -23,6 +23,7 @@ async function ledgerEthereumNodeJsClientFactoryAsync(): Promise { @@ -32,6 +33,7 @@ describe('LedgerSubprovider', () => { ledgerSubprovider = new LedgerSubprovider({ networkId, ledgerEthereumClientFactoryAsync: ledgerEthereumNodeJsClientFactoryAsync, + derivationPath: DEFAULT_DERIVATION_PATH, }); }); describe('direct method calls', () => { @@ -62,7 +64,7 @@ describe('LedgerSubprovider', () => { }; const txHex = await ledgerSubprovider.signTransactionAsync(tx); expect(txHex).to.be.equal( - '0xf85f8080822710940000000000000000000000000000000000000000808077a088a95ef1378487bc82be558e82c8478baf840c545d5b887536bb1da63673a98ba0019f4a4b9a107d1e6752bf7f701e275f28c13791d6e76af895b07373462cefaa', + '0xf85f8080822710940000000000000000000000000000000000000000808078a0712854c73c69445cc1b22a7c3d7312ff9a97fe4ffba35fd636e8236b211b6e7ca0647cee031615e52d916c7c707025bc64ad525d8f1b9876c3435a863b42743178', ); }); }); -- cgit v1.2.3 From e2e6ae937d2d38210442f493c24d492e3b477907 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Wed, 7 Mar 2018 12:30:27 -0500 Subject: README on derivation path --- packages/subproviders/README.md | 8 ++++++++ packages/subproviders/test/integration/ledger_subprovider_test.ts | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/packages/subproviders/README.md b/packages/subproviders/README.md index 52ad3388e..f3e3bd0ae 100644 --- a/packages/subproviders/README.md +++ b/packages/subproviders/README.md @@ -42,6 +42,8 @@ const accounts = await ledgerSubprovider.getAccountsAsync(); A subprovider that enables your dApp to send signing requests to a user's Ledger Nano S hardware wallet. These can be requests to sign transactions or messages. +Ledger Nano (and this library) by default uses a derivation path of `44'/60'/0'`. This is different to TestRPC which by default uses `m/44'/60'/0'/0`. This is a configuration option in the Ledger Subprovider package. + ##### Ledger Nano S + Node-hid (usb) By default, node-hid transport support is an optional dependency. This is due to the requirement of native usb developer packages on the host system. If these aren't installed the entire `npm install` fails. We also no longer export node-hid transport client factories. To re-create this see our integration tests or follow the example below: @@ -62,6 +64,12 @@ ledgerSubprovider = new LedgerSubprovider({ }); ``` +##### Testing Subprovider + Ledger integration + +To run our integration tests you need a ledger configured with our development mnemonic seed. +This is available in the top level package.json under `mnemonic`. +Configure your ledger and run the integration tests. We assume a derivation path of `m/44'/60'/0'/0` and this is configured in the tests. To this setup and derivation path, your first account should be `0x5409ed021d9299bf6814279a6a1411a7e866a631`, exactly like TestRPC. + #### Redundant RPC subprovider A subprovider which attempts to send an RPC call to a list of RPC endpoints sequentially, until one of them returns a successful response. diff --git a/packages/subproviders/test/integration/ledger_subprovider_test.ts b/packages/subproviders/test/integration/ledger_subprovider_test.ts index a9f538038..8ed69edaf 100644 --- a/packages/subproviders/test/integration/ledger_subprovider_test.ts +++ b/packages/subproviders/test/integration/ledger_subprovider_test.ts @@ -42,6 +42,10 @@ describe('LedgerSubprovider', () => { expect(accounts[0]).to.not.be.an('undefined'); expect(accounts.length).to.be.equal(10); }); + it('returns the expected account', async () => { + const accounts = await ledgerSubprovider.getAccountsAsync(); + expect(accounts[0]).to.be.equal(TEST_RPC_ACCOUNT_0); + }); it('returns requested number of accounts', async () => { const numberOfAccounts = 20; const accounts = await ledgerSubprovider.getAccountsAsync(numberOfAccounts); @@ -61,6 +65,7 @@ describe('LedgerSubprovider', () => { to: '0x0000000000000000000000000000000000000000', value: '0x00', chainId: 3, + from: TEST_RPC_ACCOUNT_0, }; const txHex = await ledgerSubprovider.signTransactionAsync(tx); expect(txHex).to.be.equal( -- cgit v1.2.3 From 1a6c2e2baca33ce377b86f30abe0c16619a3577c Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Wed, 7 Mar 2018 15:20:06 -0500 Subject: Feedback --- packages/subproviders/CHANGELOG.md | 4 ++-- packages/subproviders/README.md | 4 ++-- packages/subproviders/src/globals.d.ts | 4 ++-- packages/subproviders/test/integration/ledger_subprovider_test.ts | 7 ++++--- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/subproviders/CHANGELOG.md b/packages/subproviders/CHANGELOG.md index b7247748e..8e7321d4a 100644 --- a/packages/subproviders/CHANGELOG.md +++ b/packages/subproviders/CHANGELOG.md @@ -1,8 +1,8 @@ # CHANGELOG -## v0.7.0 - _March 6, 2018_ +## v0.7.0 - _TBD_ - * Updated legerco packages. Removed node-hid packages as a dependency. (#437) + * Updated legerco packages. Removed node-hid package as a dependency and make it an optional dependency. It is still used in integration tests but is causing problems for users on Linux distros. (#437) ## v0.6.0 - _March 4, 2018_ diff --git a/packages/subproviders/README.md b/packages/subproviders/README.md index f3e3bd0ae..53fbb2348 100644 --- a/packages/subproviders/README.md +++ b/packages/subproviders/README.md @@ -67,8 +67,8 @@ ledgerSubprovider = new LedgerSubprovider({ ##### Testing Subprovider + Ledger integration To run our integration tests you need a ledger configured with our development mnemonic seed. -This is available in the top level package.json under `mnemonic`. -Configure your ledger and run the integration tests. We assume a derivation path of `m/44'/60'/0'/0` and this is configured in the tests. To this setup and derivation path, your first account should be `0x5409ed021d9299bf6814279a6a1411a7e866a631`, exactly like TestRPC. +Our development mnemonic is `concert load couple harbor equip island argue ramp clarify fence smart topic`. +Configure your ledger and run the integration tests. We assume a derivation path of `m/44'/60'/0'/0` and this is configured in the tests. With this setup and derivation path, your first account should be `0x5409ed021d9299bf6814279a6a1411a7e866a631`, exactly like TestRPC. #### Redundant RPC subprovider diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts index e258ef947..d59ee9e67 100644 --- a/packages/subproviders/src/globals.d.ts +++ b/packages/subproviders/src/globals.d.ts @@ -54,14 +54,14 @@ declare module '@ledgerhq/hw-app-eth' { } declare module '@ledgerhq/hw-transport-u2f' { - export default class TransportU2F { + export default class TransportU2F implements LedgerTransport { public static create(): Promise; public close(): Promise; } } declare module '@ledgerhq/hw-transport-node-hid' { - export default class TransportNodeHid { + export default class TransportNodeHid implements LedgerTransport { public static create(): Promise; public close(): Promise; } diff --git a/packages/subproviders/test/integration/ledger_subprovider_test.ts b/packages/subproviders/test/integration/ledger_subprovider_test.ts index 8ed69edaf..a94cfbe3a 100644 --- a/packages/subproviders/test/integration/ledger_subprovider_test.ts +++ b/packages/subproviders/test/integration/ledger_subprovider_test.ts @@ -1,4 +1,5 @@ import Eth from '@ledgerhq/hw-app-eth'; +// HACK: This depdency is optional and tslint skips optional depdencies // tslint:disable-next-line:no-implicit-dependencies import TransportNodeHid from '@ledgerhq/hw-transport-node-hid'; import * as chai from 'chai'; @@ -23,7 +24,7 @@ async function ledgerEthereumNodeJsClientFactoryAsync(): Promise { @@ -33,7 +34,7 @@ describe('LedgerSubprovider', () => { ledgerSubprovider = new LedgerSubprovider({ networkId, ledgerEthereumClientFactoryAsync: ledgerEthereumNodeJsClientFactoryAsync, - derivationPath: DEFAULT_DERIVATION_PATH, + derivationPath: TESTRPC_DERIVATION_PATH, }); }); describe('direct method calls', () => { @@ -42,7 +43,7 @@ describe('LedgerSubprovider', () => { expect(accounts[0]).to.not.be.an('undefined'); expect(accounts.length).to.be.equal(10); }); - it('returns the expected account', async () => { + it('returns the expected first account from a ledger set up with the test mnemonic', async () => { const accounts = await ledgerSubprovider.getAccountsAsync(); expect(accounts[0]).to.be.equal(TEST_RPC_ACCOUNT_0); }); -- cgit v1.2.3 From bd8b8abfea725dbf0826af407ca1f409a88701bf Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Wed, 7 Mar 2018 21:44:11 +0100 Subject: Improve README --- packages/subproviders/README.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/subproviders/README.md b/packages/subproviders/README.md index 53fbb2348..4614342b2 100644 --- a/packages/subproviders/README.md +++ b/packages/subproviders/README.md @@ -64,12 +64,6 @@ ledgerSubprovider = new LedgerSubprovider({ }); ``` -##### Testing Subprovider + Ledger integration - -To run our integration tests you need a ledger configured with our development mnemonic seed. -Our development mnemonic is `concert load couple harbor equip island argue ramp clarify fence smart topic`. -Configure your ledger and run the integration tests. We assume a derivation path of `m/44'/60'/0'/0` and this is configured in the tests. With this setup and derivation path, your first account should be `0x5409ed021d9299bf6814279a6a1411a7e866a631`, exactly like TestRPC. - #### Redundant RPC subprovider A subprovider which attempts to send an RPC call to a list of RPC endpoints sequentially, until one of them returns a successful response. @@ -132,10 +126,12 @@ yarn run test:unit In order to run the integration tests, make sure you have a Ledger Nano S available. +* Setup your Ledger with the development mnemonic seed: `concert load couple harbor equip island argue ramp clarify fence smart topic` * Plug it into your computer * Unlock the device * Open the on-device Ethereum app -* Make sure "browser support" is disabled +* Make sure "browser support" and "contract data" are disabled +* Start [TestRPC](https://github.com/trufflesuite/ganache-cli) locally at port `8545` Then run: @@ -143,6 +139,8 @@ Then run: yarn test:integration ``` +**Note:** We assume a derivation path of `m/44'/60'/0'/0` which is already configured in the tests. With this setup and derivation path, your first account should be `0x5409ed021d9299bf6814279a6a1411a7e866a631`, exactly like TestRPC. + #### All tests ```bash -- cgit v1.2.3 From c3eaa694dd81dd9f36a965c52b9bf5104a7a8fa7 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Wed, 7 Mar 2018 21:58:18 +0100 Subject: Update yarn.lock --- yarn.lock | 256 ++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 158 insertions(+), 98 deletions(-) diff --git a/yarn.lock b/yarn.lock index a1e35e3f1..5869f1be8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,32 @@ # yarn lockfile v1 +"@ledgerhq/hw-app-eth@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-4.3.0.tgz#5f365a3560cd78e8cd711737ec56249390cbf5e5" + dependencies: + "@ledgerhq/hw-transport" "^4.3.0" + +"@ledgerhq/hw-transport-node-hid@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.3.0.tgz#6438133a2021ecf8db03b0ae4827b9ec454c5577" + dependencies: + "@ledgerhq/hw-transport" "^4.3.0" + node-hid "^0.7.2" + +"@ledgerhq/hw-transport-u2f@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-u2f/-/hw-transport-u2f-4.3.0.tgz#af54309671b0dc1c169a99fa23398e6b23d26ca1" + dependencies: + "@ledgerhq/hw-transport" "^4.3.0" + u2f-api "^0.2.7" + +"@ledgerhq/hw-transport@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-4.3.0.tgz#24e1ff819d8aad00a58ae10ed3ee5d60aad54d7c" + dependencies: + events "^1.1.1" + "@types/accounting@^0.4.1": version "0.4.1" resolved "https://registry.yarnpkg.com/@types/accounting/-/accounting-0.4.1.tgz#865d9f5694fd7c438fba34eb4bc82eec6f34cdd5" @@ -619,12 +645,6 @@ async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" -async@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4" - dependencies: - lodash "^4.14.0" - async@^0.9.0: version "0.9.2" resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" @@ -1321,7 +1341,7 @@ binary-extensions@^1.0.0: version "1.11.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" -bindings@^1.2.1: +bindings@^1.2.1, bindings@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" @@ -1345,6 +1365,12 @@ bip66@^1.1.3: dependencies: safe-buffer "^5.0.1" +bl@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" + dependencies: + readable-stream "^2.0.5" + bl@~0.9.4: version "0.9.5" resolved "https://registry.yarnpkg.com/bl/-/bl-0.9.5.tgz#c06b797af085ea00bc527afc8efcf11de2232054" @@ -1562,10 +1588,6 @@ buffer-indexof@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" -buffer-shims@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" - buffer-to-arraybuffer@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.2.tgz#d0d80564dc31866a1976515487b3ab620db7c849" @@ -2592,7 +2614,7 @@ debug-log@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" -debug@2.2.0, debug@~2.2.0: +debug@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" dependencies: @@ -2624,6 +2646,12 @@ decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + dependencies: + mimic-response "^1.0.0" + dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" @@ -2743,7 +2771,7 @@ detect-indent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" -detect-libc@^1.0.2: +detect-libc@^1.0.2, detect-libc@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" @@ -3300,7 +3328,7 @@ eventemitter3@1.x.x: version "1.2.0" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" -events@^1.0.0: +events@^1.0.0, events@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -3369,6 +3397,10 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" +expand-template@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.1.0.tgz#e09efba977bf98f9ee0ed25abd0c692e02aec3fc" + expand-tilde@^2.0.0, expand-tilde@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" @@ -3799,7 +3831,7 @@ fsevents@^1.0.0: nan "^2.3.0" node-pre-gyp "^0.6.39" -fstream-ignore@^1.0.5, fstream-ignore@~1.0.5: +fstream-ignore@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" dependencies: @@ -3807,7 +3839,7 @@ fstream-ignore@^1.0.5, fstream-ignore@~1.0.5: inherits "2" minimatch "^3.0.0" -fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2, fstream@~1.0.10: +fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: version "1.0.11" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" dependencies: @@ -3927,6 +3959,10 @@ gitconfiglocal@^1.0.0: dependencies: ini "^1.3.2" +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + github-url-to-object@^1.4.2: version "1.6.0" resolved "https://registry.yarnpkg.com/github-url-to-object/-/github-url-to-object-1.6.0.tgz#891ef7fbbfaba8fed71510acdb1b4e9346a970dc" @@ -5247,14 +5283,6 @@ lcov-parse@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" -ledgerco@0xProject/ledger-node-js-api: - version "1.1.3" - resolved "https://codeload.github.com/0xProject/ledger-node-js-api/tar.gz/24aed21b8b362f2afc86faa578f38955ae2319ba" - dependencies: - async "2.1.4" - node-hid "0.5.4" - q "1.4.1" - lerna@^2.5.1: version "2.6.0" resolved "https://registry.yarnpkg.com/lerna/-/lerna-2.6.0.tgz#865377717ca9e0daa5a2fbb00e364968d533650a" @@ -5900,6 +5928,10 @@ mimic-fn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" +mimic-response@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e" + min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" @@ -6057,10 +6089,14 @@ mute-stream@0.0.7, mute-stream@~0.0.4: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -nan@^2.0.5, nan@^2.0.8, nan@^2.2.1, nan@^2.3.0, nan@^2.3.3, nan@^2.4.0: +nan@^2.0.5, nan@^2.0.8, nan@^2.2.1, nan@^2.3.0, nan@^2.3.3: version "2.8.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" +nan@^2.6.2: + version "2.9.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.9.2.tgz#f564d75f5f8f36a6d9456cca7a6c4fe488ab7866" + nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" @@ -6099,6 +6135,12 @@ nise@^1.2.0: path-to-regexp "^1.7.0" text-encoding "^0.6.4" +node-abi@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.3.0.tgz#f3d554d6ac72a9ee16f0f4dc9548db7c08de4986" + dependencies: + semver "^5.4.1" + node-fetch@^1.0.1, node-fetch@^1.3.3, node-fetch@~1.7.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" @@ -6110,12 +6152,13 @@ node-forge@0.6.33: version "0.6.33" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.6.33.tgz#463811879f573d45155ad6a9f43dc296e8e85ebc" -node-hid@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-0.5.4.tgz#a7246dfc08d52774147fa264354d5da6eab40253" +node-hid@^0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-0.7.2.tgz#15025cdea2e9756aca2de7266529996d40e52c56" dependencies: - nan "^2.4.0" - node-pre-gyp "0.6.31" + bindings "^1.3.0" + nan "^2.6.2" + prebuild-install "^2.2.2" node-libs-browser@^2.0.0: version "2.1.0" @@ -6145,20 +6188,6 @@ node-libs-browser@^2.0.0: util "^0.10.3" vm-browserify "0.0.4" -node-pre-gyp@0.6.31: - version "0.6.31" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.31.tgz#d8a00ddaa301a940615dbcc8caad4024d58f6017" - dependencies: - mkdirp "~0.5.1" - nopt "~3.0.6" - npmlog "^4.0.0" - rc "~1.1.6" - request "^2.75.0" - rimraf "~2.5.4" - semver "~5.3.0" - tar "~2.2.1" - tar-pack "~3.3.0" - node-pre-gyp@^0.6.39: version "0.6.39" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" @@ -6196,6 +6225,10 @@ noms@0.0.0: inherits "^2.0.1" readable-stream "~1.0.31" +noop-logger@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" + nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -6209,12 +6242,6 @@ nopt@~1.0.10: dependencies: abbrev "1" -nopt@~3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - dependencies: - abbrev "1" - normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" @@ -6263,7 +6290,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npmlog@^4.0.0, npmlog@^4.0.2, npmlog@^4.1.2: +npmlog@^4.0.1, npmlog@^4.0.2, npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" dependencies: @@ -6410,7 +6437,7 @@ once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4, once@^1.4.0: dependencies: wrappy "1" -once@~1.3.0, once@~1.3.3: +once@~1.3.0: version "1.3.3" resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" dependencies: @@ -7026,6 +7053,26 @@ postcss@^6.0.1: source-map "^0.6.1" supports-color "^5.1.0" +prebuild-install@^2.2.2: + version "2.5.1" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-2.5.1.tgz#0f234140a73760813657c413cdccdda58296b1da" + dependencies: + detect-libc "^1.0.3" + expand-template "^1.0.2" + github-from-package "0.0.0" + minimist "^1.2.0" + mkdirp "^0.5.1" + node-abi "^2.2.0" + noop-logger "^0.1.1" + npmlog "^4.0.1" + os-homedir "^1.0.1" + pump "^2.0.1" + rc "^1.1.6" + simple-get "^2.7.0" + tar-fs "^1.13.0" + tunnel-agent "^0.6.0" + which-pm-runs "^1.0.0" + prepend-http@^1.0.0, prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" @@ -7057,6 +7104,10 @@ process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" @@ -7174,6 +7225,13 @@ pump@^2.0.0: end-of-stream "^1.1.0" once "^1.3.1" +pump@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + pumpify@^1.3.3: version "1.3.6" resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.3.6.tgz#00d40e5ded0a3bf1e0788b1c0cf426a42882ab64" @@ -7190,10 +7248,6 @@ punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" -q@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" - q@^1.1.2, q@^1.4.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -7293,15 +7347,6 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -rc@~1.1.6: - version "1.1.7" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.7.tgz#c5ea564bb07aff9fd3a5b32e906c1d3a65940fea" - dependencies: - deep-extend "~0.4.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - react-addons-create-fragment@^15.4.0: version "15.6.2" resolved "https://registry.yarnpkg.com/react-addons-create-fragment/-/react-addons-create-fragment-15.6.2.tgz#a394de7c2c7becd6b5475ba1b97ac472ce7c74f8" @@ -7607,16 +7652,16 @@ readable-stream@^1.0.33, readable-stream@~1.1.9: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@~2.1.4: - version "2.1.5" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.1.5.tgz#66fa8b720e1438b364681f2ad1a63c618448c9d0" +readable-stream@^2.0.5: + version "2.3.5" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.5.tgz#b4f85003a938cbb6ecbce2a124fb1012bd1a838d" dependencies: - buffer-shims "^1.0.0" core-util-is "~1.0.0" - inherits "~2.0.1" + inherits "~2.0.3" isarray "~1.0.0" - process-nextick-args "~1.0.6" - string_decoder "~0.10.x" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.0.3" util-deprecate "~1.0.1" readdirp@^2.0.0: @@ -7838,7 +7883,7 @@ request@2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" -request@^2.54.0, request@^2.67.0, request@^2.75.0, request@^2.79.0, request@^2.81.0: +request@^2.54.0, request@^2.67.0, request@^2.79.0, request@^2.81.0: version "2.83.0" resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" dependencies: @@ -7951,12 +7996,6 @@ rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2. dependencies: glob "^7.0.5" -rimraf@~2.5.1, rimraf@~2.5.4: - version "2.5.4" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04" - dependencies: - glob "^7.0.5" - ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7" @@ -8111,10 +8150,6 @@ semver@^4.1.0: version "4.3.6" resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" -semver@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - send@0.16.1: version "0.16.1" resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" @@ -8288,6 +8323,10 @@ simple-assign@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/simple-assign/-/simple-assign-0.1.0.tgz#17fd3066a5f3d7738f50321bb0f14ca281cc4baa" +simple-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + simple-get@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-1.4.3.tgz#e9755eda407e96da40c5e5158c9ea37b33becbeb" @@ -8296,6 +8335,14 @@ simple-get@^1.4.3: unzip-response "^1.0.0" xtend "^4.0.0" +simple-get@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.7.0.tgz#ad37f926d08129237ff08c4f2edfd6f10e0380b5" + dependencies: + decompress-response "^3.3.0" + once "^1.3.1" + simple-concat "^1.0.0" + single-line-log@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/single-line-log/-/single-line-log-0.4.1.tgz#87a55649f749d783ec0dcd804e8140d9873c7cee" @@ -8848,6 +8895,15 @@ tape@^4.4.0, tape@^4.6.3: string.prototype.trim "~1.1.2" through "~2.3.8" +tar-fs@^1.13.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.0.tgz#e877a25acbcc51d8c790da1c57c9cf439817b896" + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.1" + pump "^1.0.0" + tar-stream "^1.1.2" + tar-pack@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" @@ -8861,20 +8917,16 @@ tar-pack@^3.4.0: tar "^2.2.1" uid-number "^0.0.6" -tar-pack@~3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.3.0.tgz#30931816418f55afc4d21775afdd6720cee45dae" - dependencies: - debug "~2.2.0" - fstream "~1.0.10" - fstream-ignore "~1.0.5" - once "~1.3.3" - readable-stream "~2.1.4" - rimraf "~2.5.1" - tar "~2.2.1" - uid-number "~0.0.6" - -tar@^2.2.1, tar@~2.2.1: +tar-stream@^1.1.2: + version "1.5.5" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.5.tgz#5cad84779f45c83b1f2508d96b09d88c7218af55" + dependencies: + bl "^1.0.0" + end-of-stream "^1.0.0" + readable-stream "^2.0.0" + xtend "^4.0.0" + +tar@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" dependencies: @@ -9287,6 +9339,10 @@ typescript@2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.1.tgz#bb3682c2c791ac90e7c6210b26478a8da085c359" +u2f-api@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/u2f-api/-/u2f-api-0.2.7.tgz#17bf196b242f6bf72353d9858e6a7566cc192720" + ua-parser-js@^0.7.9: version "0.7.17" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" @@ -9312,7 +9368,7 @@ uglifyjs-webpack-plugin@^0.4.6: uglify-js "^2.8.29" webpack-sources "^1.0.1" -uid-number@^0.0.6, uid-number@~0.0.6: +uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" @@ -9892,6 +9948,10 @@ which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" +which-pm-runs@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" + which@^1.2.14, which@^1.2.9, which@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" -- cgit v1.2.3