aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2017-12-08 01:42:50 +0800
committerFabio Berger <me@fabioberger.com>2017-12-08 01:42:50 +0800
commit215e33fa6c1ca3c27712f5253daeaebf590f8983 (patch)
treecfee907308158726196d4edfebd7a9bc7064e76b
parent3d12b84f1d1ecf8eb6fa145f4bf124f0b7b484c1 (diff)
parentbe17b75ad3e043df6f4ff05ead0627cb9a45d93b (diff)
downloaddexon-0x-contracts-215e33fa6c1ca3c27712f5253daeaebf590f8983.tar.gz
dexon-0x-contracts-215e33fa6c1ca3c27712f5253daeaebf590f8983.tar.zst
dexon-0x-contracts-215e33fa6c1ca3c27712f5253daeaebf590f8983.zip
Merge branch 'feature/addSubproviders' into feature/portal-ledger-support
* feature/addSubproviders: remove unneeded reset Use rejectedWith Add missing calls to configure remove unneeded type assertions remove unused type Simplify interface to signPersonalMessageAsync Fix unit test Fix ethereumjs-tx declaration and import Use assert.isHexString Add type defs for ledgerco and ethereumjs-tx Make test only run unit tests since cannot run integration tests on CI Improve README Fix version and remove the UMD build Fix tslint error
-rw-r--r--packages/subproviders/README.md2
-rw-r--r--packages/subproviders/package.json17
-rw-r--r--packages/subproviders/src/globals.d.ts48
-rw-r--r--packages/subproviders/src/subproviders/ledger.ts37
-rw-r--r--packages/subproviders/src/types.ts7
-rw-r--r--packages/subproviders/test/integration/ledger_subprovider_test.ts3
-rw-r--r--packages/subproviders/test/unit/ledger_subprovider_test.ts39
-rw-r--r--packages/subproviders/webpack.config.js56
-rw-r--r--packages/website/package.json2
-rw-r--r--packages/website/ts/components/ui/lifecycle_raised_button.tsx2
-rw-r--r--packages/website/ts/globals.d.ts2
11 files changed, 68 insertions, 147 deletions
diff --git a/packages/subproviders/README.md b/packages/subproviders/README.md
index 72f18a962..5fa31611a 100644
--- a/packages/subproviders/README.md
+++ b/packages/subproviders/README.md
@@ -29,7 +29,7 @@ In order to run the integration tests, make sure you have a Ledger Nano S availa
- Plug it into your computer
- Unlock the device
-- Open the Ethereum app
+- Open the on-device Ethereum app
- Make sure "browser support" is disabled
Then run:
diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json
index 74d1ba8c9..11d116278 100644
--- a/packages/subproviders/package.json
+++ b/packages/subproviders/package.json
@@ -1,25 +1,20 @@
{
"name": "@0xproject/subproviders",
- "version": "0.0.0",
+ "version": "0.0.1",
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"license": "Apache-2.0",
"scripts": {
"prebuild": "npm run clean",
- "build": "run-p build:umd:dev build:commonjs; exit 0;",
"clean": "shx rm -rf lib",
- "build:umd:dev": "webpack",
- "build:umd:prod": "NODE_ENV=production webpack",
- "build:commonjs": "tsc",
+ "build": "tsc",
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
- "pretest:umd": "run-s clean build:umd:dev build:commonjs",
- "substitute_umd_bundle": "shx mv _bundles/* lib/src",
- "run_mocha_all": "mocha lib/test/**/*_test.js --timeout 10000 --bail --exit",
"run_mocha_unit": "mocha lib/test/unit/**/*_test.js --timeout 10000 --bail --exit",
"run_mocha_integration": "mocha lib/test/integration/**/*_test.js --timeout 10000 --bail --exit",
- "test": "run-s clean build:commonjs run_mocha_all",
- "test:unit": "run-s clean build:commonjs run_mocha_unit",
- "test:integration": "run-s clean build:commonjs run_mocha_integration"
+ "test": "npm run test:unit",
+ "test:all": "run-s test:unit test:integration",
+ "test:unit": "run-s clean build run_mocha_unit",
+ "test:integration": "run-s clean build run_mocha_integration"
},
"dependencies": {
"@0xproject/assert": "^0.0.6",
diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts
index 362587e08..520ca9232 100644
--- a/packages/subproviders/src/globals.d.ts
+++ b/packages/subproviders/src/globals.d.ts
@@ -1,27 +1,56 @@
/// <reference types='chai-typescript-typings' />
/// <reference types='chai-as-promised-typescript-typings' />
declare module 'dirty-chai';
-declare module 'ledgerco';
-declare module 'ethereumjs-tx';
declare module 'es6-promisify';
// tslint:disable:max-classes-per-file
// tslint:disable:class-name
// tslint:disable:completed-docs
+// Ethereumjs-tx declarations
+declare module 'ethereumjs-tx' {
+ class EthereumTx {
+ public raw: Buffer[];
+ public r: Buffer;
+ public s: Buffer;
+ public v: Buffer;
+ public serialize(): Buffer;
+ constructor(txParams: any);
+ }
+ export = EthereumTx;
+}
+
// Ledgerco declarations
+interface ECSignatureString {
+ v: string;
+ r: string;
+ s: string;
+}
+interface ECSignature {
+ v: number;
+ r: string;
+ s: string;
+}
declare module 'ledgerco' {
interface comm {
- close_async: Promise<void>;
- create_async: Promise<void>;
+ close_async(): Promise<void>;
}
export class comm_node implements comm {
- public create_async: Promise<void>;
- public close_async: Promise<void>;
+ public static create_async(timeoutMilliseconds?: number): Promise<comm_node>;
+ public close_async(): Promise<void>;
}
export class comm_u2f implements comm {
- public create_async: Promise<void>;
- public close_async: Promise<void>;
+ public static create_async(): Promise<comm_u2f>;
+ public close_async(): Promise<void>;
+ }
+ export class eth {
+ public comm: comm;
+ constructor(comm: comm);
+ public getAddress_async(path: string, display?: boolean, chaincode?: boolean):
+ Promise<{publicKey: string; address: 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>;
}
}
@@ -66,6 +95,3 @@ declare module 'web3-provider-engine' {
}
export = Web3ProviderEngine;
}
-// tslint:enable:max-classes-per-file
-// tslint:enable:class-name
-// tslint:enable:completed-docs
diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts
index ccc94d76f..83c5b6867 100644
--- a/packages/subproviders/src/subproviders/ledger.ts
+++ b/packages/subproviders/src/subproviders/ledger.ts
@@ -1,6 +1,7 @@
+import {assert} from '@0xproject/assert';
import promisify = require('es6-promisify');
import {isAddress} from 'ethereum-address';
-import * as EthereumTx from 'ethereumjs-tx';
+import EthereumTx = require('ethereumjs-tx');
import ethUtil = require('ethereumjs-util');
import * as ledger from 'ledgerco';
import * as _ from 'lodash';
@@ -14,7 +15,6 @@ import {
LedgerSubproviderErrors,
PartialTxParams,
ResponseWithTxParams,
- SignPersonalMessageParams,
} from '../types';
import {Subprovider} from './subprovider';
@@ -46,17 +46,6 @@ export class LedgerSubprovider extends Subprovider {
const isValid = nonPrefixed.match(HEX_REGEX);
return isValid;
}
- private static validatePersonalMessage(msgParams: PartialTxParams) {
- if (_.isUndefined(msgParams.from) || !isAddress(msgParams.from)) {
- throw new Error(LedgerSubproviderErrors.FromAddressMissingOrInvalid);
- }
- if (_.isUndefined(msgParams.data)) {
- throw new Error(LedgerSubproviderErrors.DataMissingForSignPersonalMessage);
- }
- if (!LedgerSubprovider.isValidHex(msgParams.data)) {
- throw new Error(LedgerSubproviderErrors.DataNotValidHexForSignPersonalMessage);
- }
- }
private static validateSender(sender: string) {
if (_.isUndefined(sender) || !isAddress(sender)) {
throw new Error(LedgerSubproviderErrors.SenderInvalidOrNotSupplied);
@@ -132,17 +121,13 @@ export class LedgerSubprovider extends Subprovider {
return;
case 'personal_sign':
- // non-standard "extraParams" to be appended to our "msgParams" obj
- // good place for metadata
- const extraParams = payload.params[2] || {};
- const msgParams = _.assign({}, extraParams, {
- from: payload.params[1],
- data: payload.params[0],
- });
-
+ const data = payload.params[0];
try {
- LedgerSubprovider.validatePersonalMessage(msgParams);
- const ecSignatureHex = await this.signPersonalMessageAsync(msgParams);
+ if (_.isUndefined(data)) {
+ throw new Error(LedgerSubproviderErrors.DataMissingForSignPersonalMessage);
+ }
+ assert.isHexString('data', data);
+ const ecSignatureHex = await this.signPersonalMessageAsync(data);
end(null, ecSignatureHex);
} catch (err) {
end(err);
@@ -208,12 +193,12 @@ export class LedgerSubprovider extends Subprovider {
throw err;
}
}
- public async signPersonalMessageAsync(msgParams: SignPersonalMessageParams): Promise<string> {
+ public async signPersonalMessageAsync(data: string): Promise<string> {
this._ledgerClientIfExists = await this.createLedgerClientAsync();
try {
const derivationPath = this.getDerivationPath();
const result = await this._ledgerClientIfExists.signPersonalMessage_async(
- derivationPath, ethUtil.stripHexPrefix(msgParams.data));
+ derivationPath, ethUtil.stripHexPrefix(data));
const v = result.v - 27;
let vHex = v.toString(16);
if (vHex.length < 2) {
@@ -251,7 +236,7 @@ export class LedgerSubprovider extends Subprovider {
this._ledgerClientIfExists = undefined;
this._connectionLock.signal();
}
- private async sendTransactionAsync(txParams: PartialTxParams): Promise<any> {
+ private async sendTransactionAsync(txParams: PartialTxParams): Promise<Web3.JSONRPCResponsePayload> {
await this._nonceLock.wait();
try {
// fill in the extras
diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts
index 4564c5229..38dc1e67e 100644
--- a/packages/subproviders/src/types.ts
+++ b/packages/subproviders/src/types.ts
@@ -2,8 +2,6 @@ import * as _ from 'lodash';
import * as Web3 from 'web3';
export interface LedgerCommunicationClient {
- exchange: (apduHex: string, statusList: number[]) => Promise<any[]>;
- setScrambleKey: (key: string) => void;
close_async: () => Promise<void>;
}
@@ -74,10 +72,6 @@ export interface LedgerWalletSubprovider {
setPathIndex: (pathIndex: number) => void;
}
-export interface SignPersonalMessageParams {
- data: string;
-}
-
export interface PartialTxParams {
nonce: string;
gasPrice?: string;
@@ -109,7 +103,6 @@ export enum LedgerSubproviderErrors {
TooOldLedgerFirmware = 'TOO_OLD_LEDGER_FIRMWARE',
FromAddressMissingOrInvalid = 'FROM_ADDRESS_MISSING_OR_INVALID',
DataMissingForSignPersonalMessage = 'DATA_MISSING_FOR_SIGN_PERSONAL_MESSAGE',
- DataNotValidHexForSignPersonalMessage = 'DATA_NOT_VALID_HEX_FOR_SIGN_PERSONAL_MESSAGE',
SenderInvalidOrNotSupplied = 'SENDER_INVALID_OR_NOT_SUPPLIED',
MultipleOpenConnectionsDisallowed = 'MULTIPLE_OPEN_CONNECTIONS_DISALLOWED',
}
diff --git a/packages/subproviders/test/integration/ledger_subprovider_test.ts b/packages/subproviders/test/integration/ledger_subprovider_test.ts
index ab1ee3264..75f6d47fe 100644
--- a/packages/subproviders/test/integration/ledger_subprovider_test.ts
+++ b/packages/subproviders/test/integration/ledger_subprovider_test.ts
@@ -20,6 +20,7 @@ import {
import {chaiSetup} from '../chai_setup';
import {reportCallbackErrors} from '../utils/report_callback_errors';
+chaiSetup.configure();
const expect = chai.expect;
const TEST_RPC_ACCOUNT_0 = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
@@ -41,7 +42,7 @@ describe('LedgerSubprovider', () => {
});
it('signs a personal message', async () => {
const data = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
- const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync({data});
+ const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(data);
expect(ecSignatureHex.length).to.be.equal(132);
expect(ecSignatureHex.substr(0, 2)).to.be.equal('0x');
});
diff --git a/packages/subproviders/test/unit/ledger_subprovider_test.ts b/packages/subproviders/test/unit/ledger_subprovider_test.ts
index f895e7b74..bc9671948 100644
--- a/packages/subproviders/test/unit/ledger_subprovider_test.ts
+++ b/packages/subproviders/test/unit/ledger_subprovider_test.ts
@@ -19,6 +19,7 @@ import {
import {chaiSetup} from '../chai_setup';
import {reportCallbackErrors} from '../utils/report_callback_errors';
+chaiSetup.configure();
const expect = chai.expect;
const FAKE_ADDRESS = '0x9901c66f2d4b95f7074b553da78084d708beca70';
@@ -35,7 +36,7 @@ describe('LedgerSubprovider', () => {
};
},
signPersonalMessage_async: async () => {
- const ecSignature: ECSignature = {
+ const ecSignature = {
v: 28,
r: 'a6cc284bff14b42bdf5e9286730c152be91719d478605ec46b3bebcd0ae49148',
s: '0652a1a7b742ceb0213d1e744316e285f41f878d8af0b8e632cbca4c279132d0',
@@ -43,7 +44,7 @@ describe('LedgerSubprovider', () => {
return ecSignature;
},
signTransaction_async: async (derivationPath: string, txHex: string) => {
- const ecSignature: ECSignatureString = {
+ const ecSignature = {
v: '77',
r: '88a95ef1378487bc82be558e82c8478baf840c545d5b887536bb1da63673a98b',
s: '019f4a4b9a107d1e6752bf7f701e275f28c13791d6e76af895b07373462cefaa',
@@ -71,8 +72,7 @@ describe('LedgerSubprovider', () => {
});
it('signs a personal message', async () => {
const data = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
- const msgParams = {data};
- const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(msgParams);
+ const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(data);
// tslint:disable-next-line:max-line-length
expect(ecSignatureHex).to.be.equal('0xa6cc284bff14b42bdf5e9286730c152be91719d478605ec46b3bebcd0ae491480652a1a7b742ceb0213d1e744316e285f41f878d8af0b8e632cbca4c279132d001');
});
@@ -80,16 +80,10 @@ describe('LedgerSubprovider', () => {
describe('failure cases', () => {
it('cannot open multiple simultaneous connections to the Ledger device', async () => {
const data = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
- const msgParams = {data};
- try {
- const result = await Promise.all([
- ledgerSubprovider.getAccountsAsync(),
- ledgerSubprovider.signPersonalMessageAsync(msgParams),
- ]);
- throw new Error('Multiple simultaneous calls succeeded when they should have failed');
- } catch (err) {
- expect(err.message).to.be.equal(LedgerSubproviderErrors.MultipleOpenConnectionsDisallowed);
- }
+ return expect(Promise.all([
+ ledgerSubprovider.getAccountsAsync(),
+ ledgerSubprovider.signPersonalMessageAsync(data),
+ ])).to.be.rejectedWith(LedgerSubproviderErrors.MultipleOpenConnectionsDisallowed);
});
});
});
@@ -157,21 +151,6 @@ describe('LedgerSubprovider', () => {
});
});
describe('failure cases', () => {
- it('should throw if `from` param missing when calling personal_sign', (done: DoneCallback) => {
- const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
- const payload = {
- jsonrpc: '2.0',
- method: 'personal_sign',
- params: [messageHex], // Missing from param
- id: 1,
- };
- const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => {
- expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal(LedgerSubproviderErrors.FromAddressMissingOrInvalid);
- done();
- });
- provider.sendAsync(payload, callback);
- });
it('should throw if `data` param not hex when calling personal_sign', (done: DoneCallback) => {
const nonHexMessage = 'hello world';
const payload = {
@@ -182,7 +161,7 @@ describe('LedgerSubprovider', () => {
};
const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => {
expect(err).to.not.be.a('null');
- expect(err.message).to.be.equal(LedgerSubproviderErrors.DataNotValidHexForSignPersonalMessage);
+ expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world');
done();
});
provider.sendAsync(payload, callback);
diff --git a/packages/subproviders/webpack.config.js b/packages/subproviders/webpack.config.js
deleted file mode 100644
index a73489704..000000000
--- a/packages/subproviders/webpack.config.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * This is to generate the umd bundle only
- */
-const _ = require('lodash');
-const webpack = require('webpack');
-const path = require('path');
-const production = process.env.NODE_ENV === 'production';
-
-let entry = {
- 'index': './src/index.ts',
-};
-if (production) {
- entry = _.assign({}, entry, {'index.min': './src/index.ts'});
-}
-
-module.exports = {
- entry,
- output: {
- path: path.resolve(__dirname, '_bundles'),
- filename: '[name].js',
- libraryTarget: 'umd',
- library: '0x Subproviders',
- umdNamedDefine: true,
- },
- resolve: {
- extensions: ['.ts', '.js', '.json'],
- },
- devtool: 'source-map',
- plugins: [
- new webpack.optimize.UglifyJsPlugin({
- minimize: true,
- sourceMap: true,
- include: /\.min\.js$/,
- }),
- ],
- module: {
- rules: [
- {
- test: /\.ts$/,
- use: [
- {
- loader: 'awesome-typescript-loader',
- query: {
- declaration: false,
- },
- },
- ],
- exclude: /node_modules/,
- },
- {
- test: /\.json$/,
- loader: 'json-loader',
- },
- ],
- },
-};
diff --git a/packages/website/package.json b/packages/website/package.json
index fc7d65d05..ac6e61a88 100644
--- a/packages/website/package.json
+++ b/packages/website/package.json
@@ -18,7 +18,7 @@
"author": "Fabio Berger",
"license": "Apache-2.0",
"dependencies": {
- "@0xproject/subproviders": "0.0.0",
+ "@0xproject/subproviders": "0.0.1",
"0x.js": "0xproject/0x.js/packages/0x.js#0x.js@0.27.1",
"accounting": "^0.4.1",
"basscss": "^8.0.3",
diff --git a/packages/website/ts/components/ui/lifecycle_raised_button.tsx b/packages/website/ts/components/ui/lifecycle_raised_button.tsx
index 338a3bf76..cba94ca8c 100644
--- a/packages/website/ts/components/ui/lifecycle_raised_button.tsx
+++ b/packages/website/ts/components/ui/lifecycle_raised_button.tsx
@@ -20,7 +20,7 @@ interface LifeCycleRaisedButtonProps {
labelReady: React.ReactNode|string;
labelLoading: React.ReactNode|string;
labelComplete: React.ReactNode|string;
- onClickAsyncFn: () => boolean;
+ onClickAsyncFn: () => Promise<boolean>;
backgroundColor?: string;
labelColor?: string;
}
diff --git a/packages/website/ts/globals.d.ts b/packages/website/ts/globals.d.ts
index 46897b429..38a4b971e 100644
--- a/packages/website/ts/globals.d.ts
+++ b/packages/website/ts/globals.d.ts
@@ -163,5 +163,3 @@ declare interface Artifact {
};
};
}
-
-// tslint:enable:max-classes-per-file