init trezor subprovider w/ trezor connect client api

This commit is contained in:
MarcZenn
2018-12-12 14:42:36 -08:00
parent 1c65fa212d
commit d52dc69279
4 changed files with 23 additions and 121 deletions

View File

@@ -67,8 +67,6 @@
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"dirty-chai": "^2.0.1",
"jsdom": "13.0.0",
"jsdom-global": "3.0.2",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
"npm-run-all": "^4.1.2",

View File

@@ -1,15 +1,7 @@
/**
* NOTE:: trezor-connect module currently runs in browser only https://github.com/trezor/connect/issues/248
* which breaks mocha/chai unit tests. Importing jsdom-global here injects DOM API into testing environment.
* https://github.com/rstacruz/jsdom-global
*/
import 'jsdom-global/register';
import { assert } from '@0x/assert';
import { addressUtils } from '@0x/utils';
import EthereumTx = require('ethereumjs-tx');
import * as _ from 'lodash';
import TrezorConnect from 'trezor-connect';
import {
PartialTxParams,
@@ -18,6 +10,7 @@ import {
TrezorResponseErrorPayload,
TrezorSignMssgResponsePayload,
TrezorSignTxResponsePayload,
TrezorSubproviderConfig,
WalletSubproviderErrors,
} from '../types';
@@ -28,17 +21,18 @@ const PRIVATE_KEY_PATH = `m/44'/60'/0'`;
export class TrezorSubprovider extends BaseWalletSubprovider {
private readonly _publicKeyPath: string;
private _cachedAccounts: string[];
// NOTE:: trezor-connect module currently runs in browser only https://github.com/trezor/connect/issues/248
private _runningInBrowser: boolean;
private readonly _trezorConnectClientApi: any;
/**
* Instantiates a TrezorSubprovider. Defaults to private key path set to `44'/60'/0'`.
* Must be initialized with trezor-connect API module https://github.com/trezor/connect.
* @param TrezorSubprovider config object containing trezor-connect API
* @return TrezorSubprovider instance
*/
constructor() {
constructor(config: TrezorSubproviderConfig) {
super();
this._publicKeyPath = PRIVATE_KEY_PATH;
this._cachedAccounts = [];
this._runningInBrowser = typeof window === 'undefined' ? false : true;
this._trezorConnectClientApi = config.trezorConnectClientApi;
}
/**
* Retrieve a users Trezor account. The accounts are private key path derived, This method
@@ -47,14 +41,11 @@ export class TrezorSubprovider extends BaseWalletSubprovider {
* @return An array of accounts
*/
public async getAccountsAsync(): Promise<string[]> {
if (!this._runningInBrowser) {
throw new Error(WalletSubproviderErrors.MustRunInBrowser);
}
if (this._cachedAccounts.length) {
return this._cachedAccounts;
}
const accounts: string[] = [];
const response: TrezorConnectResponse = TrezorConnect.ethereumGetAddress({ path: this._publicKeyPath, showOnTrezor: true });
const response: TrezorConnectResponse = await this._trezorConnectClientApi.ethereumGetAddress({ path: this._publicKeyPath, showOnTrezor: true });
if (response.success) {
const payload: TrezorGetAddressResponsePayload = response.payload;
@@ -79,9 +70,6 @@ export class TrezorSubprovider extends BaseWalletSubprovider {
if (_.isUndefined(txData.from) || !addressUtils.isAddress(txData.from)) {
throw new Error(WalletSubproviderErrors.FromAddressMissingOrInvalid);
}
if (!this._runningInBrowser) {
throw new Error(WalletSubproviderErrors.MustRunInBrowser);
}
txData.value = txData.value ? txData.value : '0x0';
txData.data = txData.data ? txData.data : '0x';
txData.gas = txData.gas ? txData.gas : '0x0';
@@ -89,7 +77,7 @@ export class TrezorSubprovider extends BaseWalletSubprovider {
const accountIndex = this._cachedAccounts.indexOf(txData.from);
const response: TrezorConnectResponse = TrezorConnect.ethereumSignTransaction({
const response: TrezorConnectResponse = await this._trezorConnectClientApi.ethereumSignTransaction({
path: this._publicKeyPath + `${accountIndex}`,
transaction: {
to: txData.to,
@@ -139,13 +127,10 @@ export class TrezorSubprovider extends BaseWalletSubprovider {
if (_.isUndefined(data)) {
throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage);
}
if (!this._runningInBrowser) {
throw new Error(WalletSubproviderErrors.MustRunInBrowser);
}
assert.isHexString('data', data);
assert.isETHAddressHex('address', address);
const accountIndex = this._cachedAccounts.indexOf(address);
const response: TrezorConnectResponse = TrezorConnect.ethereumSignMessage({ path: this._publicKeyPath + `${accountIndex}`, message: data, hex: false });
const response: TrezorConnectResponse = await this._trezorConnectClientApi.ethereumSignMessage({ path: this._publicKeyPath + `${accountIndex}`, message: data, hex: false });
if (response.success) {
const payload: TrezorSignMssgResponsePayload = response.payload;

View File

@@ -2,6 +2,8 @@ import { ECSignature } from '@0x/types';
import { JSONRPCRequestPayload } from 'ethereum-types';
import HDNode = require('hdkey');
import TrezorConnect from 'trezor-connect';
export interface LedgerCommunicationClient {
close: () => Promise<void>;
}
@@ -111,7 +113,6 @@ export enum WalletSubproviderErrors {
SenderInvalidOrNotSupplied = 'SENDER_INVALID_OR_NOT_SUPPLIED',
FromAddressMissingOrInvalid = 'FROM_ADDRESS_MISSING_OR_INVALID',
MethodNotSupported = 'METHOD_NOT_SUPPORTED',
MustRunInBrowser = 'METHOD_CAN_ONLY_RUN_IN_BROWSER',
}
export enum LedgerSubproviderErrors {
TooOldLedgerFirmware = 'TOO_OLD_LEDGER_FIRMWARE',
@@ -138,6 +139,10 @@ export interface JSONRPCRequestPayloadWithMethod extends JSONRPCRequestPayload {
method: string;
}
export interface TrezorSubproviderConfig {
trezorConnectClientApi: typeof TrezorConnect;
}
export interface TrezorGetAddressResponsePayload {
address: string;
path: {

102
yarn.lock
View File

@@ -1963,7 +1963,7 @@ acorn-dynamic-import@^3.0.0:
dependencies:
acorn "^5.0.0"
acorn-globals@^4.1.0, acorn-globals@^4.3.0:
acorn-globals@^4.1.0:
version "4.3.0"
resolved "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz#e3b6f8da3c1552a95ae627571f7dd6923bb54103"
dependencies:
@@ -4864,11 +4864,11 @@ csso@~2.3.1:
clap "^1.0.9"
source-map "^0.5.3"
cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0", cssom@^0.3.4:
cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
version "0.3.4"
resolved "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz#8cd52e8a3acfd68d3aed38ee0a640177d2f9d797"
cssstyle@^1.0.0, cssstyle@^1.1.1:
cssstyle@^1.0.0:
version "1.1.1"
resolved "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz#18b038a9c44d65f7a8e428a653b9f6fe42faf5fb"
dependencies:
@@ -4926,14 +4926,6 @@ data-urls@^1.0.0:
whatwg-mimetype "^2.1.0"
whatwg-url "^7.0.0"
data-urls@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe"
dependencies:
abab "^2.0.0"
whatwg-mimetype "^2.2.0"
whatwg-url "^7.0.0"
date-fns@^1.27.2:
version "1.29.0"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6"
@@ -5759,7 +5751,7 @@ escodegen@1.8.x:
optionalDependencies:
source-map "~0.2.0"
escodegen@^1.11.0, escodegen@^1.9.1:
escodegen@^1.9.1:
version "1.11.0"
resolved "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589"
dependencies:
@@ -9160,41 +9152,6 @@ jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
jsdom-global@3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/jsdom-global/-/jsdom-global-3.0.2.tgz#6bd299c13b0c4626b2da2c0393cd4385d606acb9"
jsdom@13.0.0:
version "13.0.0"
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-13.0.0.tgz#f1df2411b714a4e08d1bdc343c0a0889c688210f"
dependencies:
abab "^2.0.0"
acorn "^6.0.2"
acorn-globals "^4.3.0"
array-equal "^1.0.0"
cssom "^0.3.4"
cssstyle "^1.1.1"
data-urls "^1.0.1"
domexception "^1.0.1"
escodegen "^1.11.0"
html-encoding-sniffer "^1.0.2"
nwsapi "^2.0.9"
parse5 "5.1.0"
pn "^1.1.0"
request "^2.88.0"
request-promise-native "^1.0.5"
saxes "^3.1.3"
symbol-tree "^3.2.2"
tough-cookie "^2.4.3"
w3c-hr-time "^1.0.1"
w3c-xmlserializer "^1.0.0"
webidl-conversions "^4.0.2"
whatwg-encoding "^1.0.5"
whatwg-mimetype "^2.2.0"
whatwg-url "^7.0.0"
ws "^6.1.0"
xml-name-validator "^3.0.0"
jsdom@^11.5.1:
version "11.12.0"
resolved "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8"
@@ -11233,7 +11190,7 @@ numeral@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/numeral/-/numeral-2.0.6.tgz#4ad080936d443c2561aed9f2197efffe25f4e506"
nwsapi@^2.0.7, nwsapi@^2.0.9:
nwsapi@^2.0.7:
version "2.0.9"
resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.9.tgz#77ac0cdfdcad52b6a1151a84e73254edc33ed016"
@@ -11793,10 +11750,6 @@ parse5@4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
parse5@5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2"
parse5@^3.0.1, parse5@^3.0.3:
version "3.0.3"
resolved "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c"
@@ -12542,7 +12495,7 @@ pseudomap@^1.0.1, pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
psl@^1.1.24, psl@^1.1.28:
psl@^1.1.24:
version "1.1.29"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67"
@@ -12666,10 +12619,6 @@ punycode@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d"
punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
q@^1.1.2, q@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
@@ -13573,7 +13522,7 @@ request@2.81.0, "request@>=2.9.0 <2.82.0":
tunnel-agent "^0.6.0"
uuid "^3.0.0"
request@^2.47.0, request@^2.87.0, request@^2.88.0:
request@^2.47.0, request@^2.87.0:
version "2.88.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
dependencies:
@@ -13970,12 +13919,6 @@ sax@>=0.6.0, sax@^1.2.4, sax@~1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
saxes@^3.1.3:
version "3.1.4"
resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.4.tgz#4ad5c53eb085ac0570ea1071a07aaf22ad29cebd"
dependencies:
xmlchars "^1.3.1"
schedule@^0.5.0:
version "0.5.0"
resolved "https://registry.npmjs.org/schedule/-/schedule-0.5.0.tgz#c128fffa0b402488b08b55ae74bb9df55cc29cc8"
@@ -15570,13 +15513,6 @@ tough-cookie@>=2.3.3, tough-cookie@^2.3.4, tough-cookie@~2.4.3:
psl "^1.1.24"
punycode "^1.4.1"
tough-cookie@^2.4.3:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
dependencies:
psl "^1.1.28"
punycode "^2.1.1"
tough-cookie@~2.3.0, tough-cookie@~2.3.3:
version "2.3.4"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655"
@@ -16431,14 +16367,6 @@ w3c-hr-time@^1.0.1:
dependencies:
browser-process-hrtime "^0.1.2"
w3c-xmlserializer@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-1.0.1.tgz#054cdcd359dc5d1f3ec9be4e272c756af4b21d39"
dependencies:
domexception "^1.0.1"
webidl-conversions "^4.0.2"
xml-name-validator "^3.0.0"
walkdir@0.0.11:
version "0.0.11"
resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.0.11.tgz#a16d025eb931bd03b52f308caed0f40fcebe9532"
@@ -16912,7 +16840,7 @@ websocket@^1.0.24, websocket@^1.0.25:
typedarray-to-buffer "^3.1.2"
yaeti "^0.0.6"
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5:
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
version "1.0.5"
resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
dependencies:
@@ -16930,10 +16858,6 @@ whatwg-mimetype@^2.1.0:
version "2.2.0"
resolved "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.2.0.tgz#a3d58ef10b76009b042d03e25591ece89b88d171"
whatwg-mimetype@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
whatwg-url@^6.4.1:
version "6.5.0"
resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8"
@@ -17103,12 +17027,6 @@ ws@^5.2.0:
dependencies:
async-limiter "~1.0.0"
ws@^6.1.0:
version "6.1.2"
resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.2.tgz#3cc7462e98792f0ac679424148903ded3b9c3ad8"
dependencies:
async-limiter "~1.0.0"
wsrun@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/wsrun/-/wsrun-2.2.0.tgz#fe05ca2c466e9281059d255b2773e7964dbcb3a7"
@@ -17198,10 +17116,6 @@ xmlbuilder@~9.0.1:
version "9.0.7"
resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
xmlchars@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-1.3.1.tgz#1dda035f833dbb4f86a0c28eaa6ca769214793cf"
xmlhttprequest@*, xmlhttprequest@1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"