From 054c00e3232b03fe6298b1d6fd203ea5a55b1607 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Sun, 17 Dec 2017 01:07:28 -0600 Subject: Add entry to CHANGELOG --- packages/0x.js/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'packages') diff --git a/packages/0x.js/CHANGELOG.md b/packages/0x.js/CHANGELOG.md index 963b3d56c..0ef433fe9 100644 --- a/packages/0x.js/CHANGELOG.md +++ b/packages/0x.js/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +v0.28.0 - _TBD_ +------------------------ +* Add `etherTokenAddress` arg to `depositAsync` and `withdrawAsync` methods on `EtherToken` wrapper. (#267) + v0.27.1 - _November 28, 2017_ ------------------------ * Export `TransactionOpts` type -- cgit From b640e2cc4990e83511e1f796a06cdc890ceec396 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Sun, 17 Dec 2017 12:40:04 -0600 Subject: Update website calls to deposit/withdraw --- packages/website/ts/blockchain.ts | 8 ++++---- packages/website/ts/components/eth_weth_conversion_button.tsx | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 6877a301a..a42b19cff 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -388,18 +388,18 @@ export class Blockchain { const balance = await this.web3Wrapper.getBalanceInEthAsync(owner); return balance; } - public async convertEthToWrappedEthTokensAsync(amount: BigNumber): Promise { + public async convertEthToWrappedEthTokensAsync(etherTokenAddress: string, amount: BigNumber): Promise { utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.'); utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES); - const txHash = await this.zeroEx.etherToken.depositAsync(amount, this.userAddress); + const txHash = await this.zeroEx.etherToken.depositAsync(etherTokenAddress, amount, this.userAddress); await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash); } - public async convertWrappedEthTokensToEthAsync(amount: BigNumber): Promise { + public async convertWrappedEthTokensToEthAsync(etherTokenAddress: string, amount: BigNumber): Promise { utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.'); utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES); - const txHash = await this.zeroEx.etherToken.withdrawAsync(amount, this.userAddress); + const txHash = await this.zeroEx.etherToken.withdrawAsync(etherTokenAddress, amount, this.userAddress); await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash); } public async doesContractExistAtAddressAsync(address: string) { diff --git a/packages/website/ts/components/eth_weth_conversion_button.tsx b/packages/website/ts/components/eth_weth_conversion_button.tsx index b017de27b..c8a279de9 100644 --- a/packages/website/ts/components/eth_weth_conversion_button.tsx +++ b/packages/website/ts/components/eth_weth_conversion_button.tsx @@ -88,12 +88,12 @@ export class EthWethConversionButton extends let balance = tokenState.balance; try { if (direction === Side.deposit) { - await this.props.blockchain.convertEthToWrappedEthTokensAsync(value); + await this.props.blockchain.convertEthToWrappedEthTokensAsync(token.address, value); const ethAmount = ZeroEx.toUnitAmount(value, constants.ETH_DECIMAL_PLACES); this.props.dispatcher.showFlashMessage(`Successfully wrapped ${ethAmount.toString()} ETH to WETH`); balance = balance.plus(value); } else { - await this.props.blockchain.convertWrappedEthTokensToEthAsync(value); + await this.props.blockchain.convertWrappedEthTokensToEthAsync(token.address, value); const tokenAmount = ZeroEx.toUnitAmount(value, token.decimals); this.props.dispatcher.showFlashMessage(`Successfully unwrapped ${tokenAmount.toString()} WETH to ETH`); balance = balance.minus(value); -- cgit From edbe6915e07a516f5fad2a38eb8ffe96a7b28318 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Sun, 17 Dec 2017 13:22:54 -0600 Subject: Fixed https://github.com/0xProject/wiki/issues/19 by disabling re-rendering of markdownCodeBlock renderer if props haven't updated --- .../ts/pages/shared/markdown_code_block.tsx | 29 ++++++++++++++-------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/pages/shared/markdown_code_block.tsx b/packages/website/ts/pages/shared/markdown_code_block.tsx index 621e5b606..aded15f0c 100644 --- a/packages/website/ts/pages/shared/markdown_code_block.tsx +++ b/packages/website/ts/pages/shared/markdown_code_block.tsx @@ -7,14 +7,23 @@ interface MarkdownCodeBlockProps { language: string; } -export function MarkdownCodeBlock(props: MarkdownCodeBlockProps) { - return ( - - - {props.literal} - - - ); +interface MarkdownCodeBlockState {} + +export class MarkdownCodeBlock extends React.Component { + // Re-rendering a codeblock causes any use selection to become de-selected. This is annoying when trying + // to copy-paste code examples. We therefore noop re-renders on this component if it's props haven't changed. + public shouldComponentUpdate(nextProps: MarkdownCodeBlockProps, nextState: MarkdownCodeBlockState) { + return nextProps.literal !== this.props.literal || nextProps.language !== this.props.language; + } + public render() { + return ( + + + {this.props.literal} + + + ); + } } -- cgit From 4dc6694651a5fba5b4e280f9eb3d5da528057cc2 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Sun, 17 Dec 2017 23:30:14 -0500 Subject: Move web3 import after subprovider imports in test web3_factory --- packages/0x.js/test/0x.js_test.ts | 6 +++--- packages/0x.js/test/utils/web3_factory.ts | 8 +++++++- packages/kovan-faucets/src/ts/handler.ts | 2 +- packages/kovan-faucets/src/ts/request_queue.ts | 2 +- packages/kovan-faucets/src/ts/zrx_request_queue.ts | 2 +- 5 files changed, 13 insertions(+), 7 deletions(-) (limited to 'packages') diff --git a/packages/0x.js/test/0x.js_test.ts b/packages/0x.js/test/0x.js_test.ts index e1ceb12c8..56585fea0 100644 --- a/packages/0x.js/test/0x.js_test.ts +++ b/packages/0x.js/test/0x.js_test.ts @@ -82,9 +82,9 @@ describe('ZeroEx library', () => { it('should return true if the signature does pertain to the dataHex & address', async () => { const isValidSignatureLocal = ZeroEx.isValidSignature(dataHex, signature, address); expect(isValidSignatureLocal).to.be.true(); - const isValidSignatureOnContract = await (zeroEx.exchange as any) - ._isValidSignatureUsingContractCallAsync(dataHex, signature, address); - return expect(isValidSignatureOnContract).to.be.true(); + return expect( + (zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, signature, address), + ).to.become(true); }); }); describe('#generateSalt', () => { diff --git a/packages/0x.js/test/utils/web3_factory.ts b/packages/0x.js/test/utils/web3_factory.ts index 6f72cec58..7e65a4381 100644 --- a/packages/0x.js/test/utils/web3_factory.ts +++ b/packages/0x.js/test/utils/web3_factory.ts @@ -3,7 +3,6 @@ // we are not running in a browser env. // Filed issue: https://github.com/ethereum/web3.js/issues/844 (global as any).XMLHttpRequest = undefined; -import * as Web3 from 'web3'; import ProviderEngine = require('web3-provider-engine'); import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); @@ -12,6 +11,13 @@ import {FakeGasEstimateSubprovider} from './subproviders/fake_gas_estimate_subpr import {constants} from './constants'; +// HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang +// because they are using the wrong XHR package. +// importing web3 after subproviders fixes this issue +// Filed issue: https://github.com/ethereum/web3.js/issues/844 +// tslint:disable-next-line:ordered-imports +import * as Web3 from 'web3'; + export const web3Factory = { create(hasAddresses: boolean = true): Web3 { const provider = this.getRpcProvider(hasAddresses); diff --git a/packages/kovan-faucets/src/ts/handler.ts b/packages/kovan-faucets/src/ts/handler.ts index 1c6866a1c..d31d1478d 100644 --- a/packages/kovan-faucets/src/ts/handler.ts +++ b/packages/kovan-faucets/src/ts/handler.ts @@ -13,7 +13,7 @@ import {ZRXRequestQueue} from './zrx_request_queue'; // HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang // because they are using the wrong XHR package. -// Issue: https://github.com/trufflesuite/truffle-contract/issues/14 +// Filed issue: https://github.com/ethereum/web3.js/issues/844 // tslint:disable-next-line:ordered-imports import * as Web3 from 'web3'; diff --git a/packages/kovan-faucets/src/ts/request_queue.ts b/packages/kovan-faucets/src/ts/request_queue.ts index 0b5e66ae9..1ad7e68be 100644 --- a/packages/kovan-faucets/src/ts/request_queue.ts +++ b/packages/kovan-faucets/src/ts/request_queue.ts @@ -3,7 +3,7 @@ import * as timers from 'timers'; // HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang // because they are using the wrong XHR package. -// Issue: https://github.com/trufflesuite/truffle-contract/issues/14 +// Filed issue: https://github.com/ethereum/web3.js/issues/844 // tslint:disable-next-line:ordered-imports import * as Web3 from 'web3'; diff --git a/packages/kovan-faucets/src/ts/zrx_request_queue.ts b/packages/kovan-faucets/src/ts/zrx_request_queue.ts index 3b505690f..717adc3c4 100644 --- a/packages/kovan-faucets/src/ts/zrx_request_queue.ts +++ b/packages/kovan-faucets/src/ts/zrx_request_queue.ts @@ -9,7 +9,7 @@ import {utils} from './utils'; // HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang // because they are using the wrong XHR package. -// Issue: https://github.com/trufflesuite/truffle-contract/issues/14 +// Filed issue: https://github.com/ethereum/web3.js/issues/844 // tslint:disable-next-line:ordered-imports import * as Web3 from 'web3'; -- cgit From 6d447fd8a509118dca4f52c4939782e67f4f1076 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 18 Dec 2017 12:30:14 +0100 Subject: Add hdnode dependency --- packages/subproviders/package.json | 1 + packages/subproviders/src/globals.d.ts | 11 +++++++++++ 2 files changed, 12 insertions(+) (limited to 'packages') diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index 8a222457d..56fc9bf8b 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -23,6 +23,7 @@ "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", diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts index adef23806..ce7b46155 100644 --- a/packages/subproviders/src/globals.d.ts +++ b/packages/subproviders/src/globals.d.ts @@ -91,3 +91,14 @@ declare module 'web3-provider-engine' { } export = Web3ProviderEngine; } + +// hdkey declarations +declare module 'hdkey' { + class HDNode { + public publicKey: Buffer; + public chainCode: Buffer; + public constructor(); + public derive(path: string): HDNode; + } + export = HDNode; +} -- cgit From 064405126d7e198c6c3363416abf3b1bc16acc6a Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 18 Dec 2017 12:30:34 +0100 Subject: Implement the address derivations --- packages/subproviders/src/globals.d.ts | 2 +- packages/subproviders/src/subproviders/ledger.ts | 33 +++++++++++++--------- packages/subproviders/src/types.ts | 4 ++- .../test/unit/ledger_subprovider_test.ts | 10 +++++-- 4 files changed, 32 insertions(+), 17 deletions(-) (limited to 'packages') diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts index ce7b46155..3800c970f 100644 --- a/packages/subproviders/src/globals.d.ts +++ b/packages/subproviders/src/globals.d.ts @@ -48,7 +48,7 @@ declare module 'ledgerco' { public comm: comm; constructor(comm: comm); public getAddress_async(path: string, display?: boolean, chaincode?: boolean): - Promise<{publicKey: string; address: string}>; + Promise<{publicKey: string; address: string; chainCode: string}>; public signTransaction_async(path: string, rawTxHex: string): Promise; public getAppConfiguration_async(): Promise<{ arbitraryDataEnabled: number; version: string }>; public signPersonalMessage_async(path: string, messageHex: string): Promise; diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts index 9ffc105a4..9b2f1d129 100644 --- a/packages/subproviders/src/subproviders/ledger.ts +++ b/packages/subproviders/src/subproviders/ledger.ts @@ -2,6 +2,7 @@ import {assert} from '@0xproject/assert'; import {addressUtils} from '@0xproject/utils'; import EthereumTx = require('ethereumjs-tx'); import ethUtil = require('ethereumjs-util'); +import HDNode = require('hdkey'); import * as _ from 'lodash'; import Semaphore from 'semaphore-async-await'; import Web3 = require('web3'); @@ -20,7 +21,7 @@ import {Subprovider} from './subprovider'; const DEFAULT_DERIVATION_PATH = `44'/60'/0'`; const NUM_ADDRESSES_TO_FETCH = 10; const ASK_FOR_ON_DEVICE_CONFIRMATION = false; -const SHOULD_GET_CHAIN_CODE = false; +const SHOULD_GET_CHAIN_CODE = true; export class LedgerSubprovider extends Subprovider { private _nonceLock: Semaphore; @@ -127,21 +128,27 @@ export class LedgerSubprovider extends Subprovider { public async getAccountsAsync(): Promise { this._ledgerClientIfExists = await this.createLedgerClientAsync(); - // TODO: replace with generating addresses without hitting Ledger + let ledgerResponse; + try { + ledgerResponse = await this._ledgerClientIfExists.getAddress_async( + `${this._derivationPath}`, this._shouldAlwaysAskForConfirmation, SHOULD_GET_CHAIN_CODE, + ); + } finally { + await this.destoryLedgerClientAsync(); + } + + const hdKey = new HDNode(); + hdKey.publicKey = new Buffer(ledgerResponse.publicKey, 'hex'); + hdKey.chainCode = new Buffer(ledgerResponse.chainCode, 'hex'); + const accounts = []; for (let i = 0; i < NUM_ADDRESSES_TO_FETCH; i++) { - try { - const derivationPath = `${this._derivationPath}/${i + this._derivationPathIndex}`; - const result = await this._ledgerClientIfExists.getAddress_async( - derivationPath, this._shouldAlwaysAskForConfirmation, SHOULD_GET_CHAIN_CODE, - ); - accounts.push(result.address.toLowerCase()); - } catch (err) { - await this.destoryLedgerClientAsync(); - throw err; - } + const derivedHDNode = hdKey.derive(`m/${i + this._derivationPathIndex}`); + const derivedPublicKey = derivedHDNode.publicKey; + const ethereumAddressUnprefixed = ethUtil.publicToAddress(derivedPublicKey, true).toString('hex'); + const ethereumAddressPrefixed = ethUtil.addHexPrefix(ethereumAddressUnprefixed); + accounts.push(ethereumAddressPrefixed.toLowerCase()); } - await this.destoryLedgerClientAsync(); return accounts; } public async signTransactionAsync(txParams: PartialTxParams): Promise { diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts index 1e7d3eab0..02855dd4c 100644 --- a/packages/subproviders/src/types.ts +++ b/packages/subproviders/src/types.ts @@ -11,7 +11,7 @@ export interface LedgerCommunicationClient { */ export interface LedgerEthereumClient { getAddress_async: (derivationPath: string, askForDeviceConfirmation: boolean, - shouldGetChainCode: boolean) => Promise; + shouldGetChainCode: true) => Promise; signPersonalMessage_async: (derivationPath: string, messageHex: string) => Promise; signTransaction_async: (derivationPath: string, txHex: string) => Promise; comm: LedgerCommunicationClient; @@ -63,6 +63,8 @@ export interface SignatureData { export interface LedgerGetAddressResult { address: string; + publicKey: string; + chainCode: string; } export interface LedgerWalletSubprovider { diff --git a/packages/subproviders/test/unit/ledger_subprovider_test.ts b/packages/subproviders/test/unit/ledger_subprovider_test.ts index bd4d93325..237090051 100644 --- a/packages/subproviders/test/unit/ledger_subprovider_test.ts +++ b/packages/subproviders/test/unit/ledger_subprovider_test.ts @@ -18,7 +18,7 @@ import {reportCallbackErrors} from '../utils/report_callback_errors'; chaiSetup.configure(); const expect = chai.expect; -const FAKE_ADDRESS = '0x9901c66f2d4b95f7074b553da78084d708beca70'; +const FAKE_ADDRESS = '0xb088a3bc93f71b4de97b9de773e9647645983688'; describe('LedgerSubprovider', () => { const networkId: number = 42; @@ -28,8 +28,14 @@ describe('LedgerSubprovider', () => { // tslint:disable:no-object-literal-type-assertion const ledgerEthClient = { getAddress_async: async () => { + // tslint:disable-next-line:max-line-length + const publicKey = '04f428290f4c5ed6a198f71b8205f488141dbb3f0840c923bbfa798ecbee6370986c03b5575d94d506772fb48a6a44e345e4ebd4f028a6f609c44b655d6d3e71a1'; + const chainCode = 'ac055a5537c0c7e9e02d14a197cad6b857836da2a12043b46912a37d959b5ae8'; + const address = '0xBa388BA5e5EEF2c6cE42d831c2B3A28D3c99bdB1'; return { - address: FAKE_ADDRESS, + publicKey, + address, + chainCode, }; }, signPersonalMessage_async: async () => { -- cgit From 950406f1f9ad79a60ced5f6680c33fbc4237de3b Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 18 Dec 2017 14:47:39 +0100 Subject: Remove redundant template string --- packages/subproviders/src/subproviders/ledger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages') diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts index 9b2f1d129..793effaeb 100644 --- a/packages/subproviders/src/subproviders/ledger.ts +++ b/packages/subproviders/src/subproviders/ledger.ts @@ -131,7 +131,7 @@ export class LedgerSubprovider extends Subprovider { let ledgerResponse; try { ledgerResponse = await this._ledgerClientIfExists.getAddress_async( - `${this._derivationPath}`, this._shouldAlwaysAskForConfirmation, SHOULD_GET_CHAIN_CODE, + this._derivationPath, this._shouldAlwaysAskForConfirmation, SHOULD_GET_CHAIN_CODE, ); } finally { await this.destoryLedgerClientAsync(); -- cgit From 90d1c3e2c98944728ac9d38f22c050a490318deb Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 18 Dec 2017 14:49:13 +0100 Subject: Introduce a variable for true --- packages/subproviders/src/subproviders/ledger.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'packages') diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts index 793effaeb..f9922fdda 100644 --- a/packages/subproviders/src/subproviders/ledger.ts +++ b/packages/subproviders/src/subproviders/ledger.ts @@ -145,7 +145,10 @@ export class LedgerSubprovider extends Subprovider { for (let i = 0; i < NUM_ADDRESSES_TO_FETCH; i++) { const derivedHDNode = hdKey.derive(`m/${i + this._derivationPathIndex}`); const derivedPublicKey = derivedHDNode.publicKey; - const ethereumAddressUnprefixed = ethUtil.publicToAddress(derivedPublicKey, true).toString('hex'); + const shouldSanitizePublicKey = true; + const ethereumAddressUnprefixed = ethUtil.publicToAddress( + derivedPublicKey, shouldSanitizePublicKey, + ).toString('hex'); const ethereumAddressPrefixed = ethUtil.addHexPrefix(ethereumAddressUnprefixed); accounts.push(ethereumAddressPrefixed.toLowerCase()); } -- cgit From a3a2df098b3a67ec2da036ae469cb54709f0fd71 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 18 Dec 2017 15:56:31 +0100 Subject: Add a comment --- packages/subproviders/src/types.ts | 2 ++ 1 file changed, 2 insertions(+) (limited to 'packages') diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts index 02855dd4c..c5ccf1fda 100644 --- a/packages/subproviders/src/types.ts +++ b/packages/subproviders/src/types.ts @@ -10,6 +10,8 @@ export interface LedgerCommunicationClient { * NodeJs and Browser communication are supported. */ export interface LedgerEthereumClient { + // shouldGetChainCode is defined as `true` instead of `boolean` because other types rely on the assumption + // that we get back the chain code and we don't have dependent types to express it properly getAddress_async: (derivationPath: string, askForDeviceConfirmation: boolean, shouldGetChainCode: true) => Promise; signPersonalMessage_async: (derivationPath: string, messageHex: string) => Promise; -- cgit From a57dda2c2a47671b0766c7c28d24560e3000ca66 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 18 Dec 2017 15:57:40 +0100 Subject: Update CHANGELOG --- packages/subproviders/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'packages') diff --git a/packages/subproviders/CHANGELOG.md b/packages/subproviders/CHANGELOG.md index b4cce6be0..358fcfa15 100644 --- a/packages/subproviders/CHANGELOG.md +++ b/packages/subproviders/CHANGELOG.md @@ -1,4 +1,5 @@ # CHANGELOG -vx.x.x +v0.x.x - _TBD, 2017_ ------------------------ + * Improve the performance of address fetching (#271) -- cgit From 7710989dee4b198bd817dca5277fffd77da7ddc4 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Mon, 18 Dec 2017 22:04:12 +0100 Subject: Add additional public changes introduced to changelog --- packages/0x.js/CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'packages') diff --git a/packages/0x.js/CHANGELOG.md b/packages/0x.js/CHANGELOG.md index 0ef433fe9..9874b0ca8 100644 --- a/packages/0x.js/CHANGELOG.md +++ b/packages/0x.js/CHANGELOG.md @@ -2,7 +2,9 @@ v0.28.0 - _TBD_ ------------------------ -* Add `etherTokenAddress` arg to `depositAsync` and `withdrawAsync` methods on `EtherToken` wrapper. (#267) +* Add `etherTokenAddress` arg to `depositAsync` and `withdrawAsync` methods on `zeroEx.etherToken` (#267) +* Removed accidentally included `unsubscribeAll` method from `zeroEx.proxy`, `zeroEx.etherToken` and `zeroEx.tokenRegistry` (#267) +* Removed `etherTokenContractAddress` from `ZeroEx` constructor arg `ZeroExConfig` (#267) v0.27.1 - _November 28, 2017_ ------------------------ -- cgit