From 8db90538a17a0458fba6d2ed8a8b51bf9edf0fa4 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 18 Sep 2017 12:26:16 +0200 Subject: Fetch tokenTransferProxy address from exchange contract --- src/0x.ts | 14 ++- src/artifacts/TokenTransferProxy.json | 128 +-------------------- src/contract_wrappers/exchange_wrapper.ts | 5 + .../token_transfer_proxy_wrapper.ts | 9 +- src/contract_wrappers/token_wrapper.ts | 22 ++-- src/types.ts | 3 + test/artifacts_test.ts | 2 +- 7 files changed, 40 insertions(+), 143 deletions(-) diff --git a/src/0x.ts b/src/0x.ts index 5d5604780..8a69bec30 100644 --- a/src/0x.ts +++ b/src/0x.ts @@ -194,9 +194,15 @@ export class ZeroEx { gasPrice, }; this._web3Wrapper = new Web3Wrapper(provider, defaults); - this.token = new TokenWrapper(this._web3Wrapper); - this.proxy = new TokenTransferProxyWrapper(this._web3Wrapper); + this.token = new TokenWrapper( + this._web3Wrapper, + this._getTokenTransferProxyAddressAsync.bind(this), + ); this.exchange = new ExchangeWrapper(this._web3Wrapper, this.token); + this.proxy = new TokenTransferProxyWrapper( + this._web3Wrapper, + this._getTokenTransferProxyAddressAsync.bind(this), + ); this.tokenRegistry = new TokenRegistryWrapper(this._web3Wrapper); this.etherToken = new EtherTokenWrapper(this._web3Wrapper, this.token); } @@ -306,4 +312,8 @@ export class ZeroEx { }); return txReceiptPromise; } + private async _getTokenTransferProxyAddressAsync(): Promise { + const tokenTransferProxyAddress = await (this.exchange as any)._getTokenTransferProxyAddressAsync(); + return tokenTransferProxyAddress; + } } diff --git a/src/artifacts/TokenTransferProxy.json b/src/artifacts/TokenTransferProxy.json index e3f6f5e51..beeb16cfe 100644 --- a/src/artifacts/TokenTransferProxy.json +++ b/src/artifacts/TokenTransferProxy.json @@ -168,131 +168,7 @@ } ], "unlinked_binary": "0x60606040525b60008054600160a060020a03191633600160a060020a03161790555b5b6106e6806100316000396000f300606060405236156100725763ffffffff60e060020a60003504166315dacbea811461007457806342f1181e146100b3578063494503d4146100d157806370712939146101005780638da5cb5b1461011e578063b91816111461014a578063d39de6e91461017a578063f2fde38b146101e5575bfe5b341561007c57fe5b61009f600160a060020a0360043581169060243581169060443516606435610203565b604080519115158252519081900360200190f35b34156100bb57fe5b6100cf600160a060020a03600435166102ae565b005b34156100d957fe5b6100e4600435610390565b60408051600160a060020a039092168252519081900360200190f35b341561010857fe5b6100cf600160a060020a03600435166103c2565b005b341561012657fe5b6100e461055a565b60408051600160a060020a039092168252519081900360200190f35b341561015257fe5b61009f600160a060020a0360043516610569565b604080519115158252519081900360200190f35b341561018257fe5b61018a61057e565b60408051602080825283518183015283519192839290830191858101910280838382156101d2575b8051825260208311156101d257601f1990920191602091820191016101b2565b5050509050019250505060405180910390f35b34156101ed57fe5b6100cf600160a060020a03600435166105e7565b005b600160a060020a03331660009081526001602052604081205460ff16151561022b5760006000fd5b6040805160006020918201819052825160e060020a6323b872dd028152600160a060020a0388811660048301528781166024830152604482018790529351938916936323b872dd9360648084019491938390030190829087803b151561028d57fe5b6102c65a03f1151561029b57fe5b5050604051519150505b5b949350505050565b60005433600160a060020a039081169116146102ca5760006000fd5b600160a060020a038116600090815260016020526040902054819060ff16156102f35760006000fd5b600160a060020a0382166000908152600160208190526040909120805460ff191682179055600280549091810161032a8382610633565b916000526020600020900160005b81546101009190910a600160a060020a0381810219909216868316918202179092556040513390911692507f94bb87f4c15c4587ff559a7584006fa01ddf9299359be6b512b94527aa961aca90600090a35b5b505b50565b600280548290811061039e57fe5b906000526020600020900160005b915054906101000a9004600160a060020a031681565b6000805433600160a060020a039081169116146103df5760006000fd5b600160a060020a038216600090815260016020526040902054829060ff1615156104095760006000fd5b600160a060020a0383166000908152600160205260408120805460ff1916905591505b6002548210156105195782600160a060020a031660028381548110151561044f57fe5b906000526020600020900160005b9054906101000a9004600160a060020a0316600160a060020a0316141561050d5760028054600019810190811061049057fe5b906000526020600020900160005b9054906101000a9004600160a060020a03166002838154811015156104bf57fe5b906000526020600020900160005b6101000a815481600160a060020a030219169083600160a060020a0316021790555060016002818180549050039150816105079190610633565b50610519565b5b60019091019061042c565b604051600160a060020a0333811691908516907ff5b347a1e40749dd050f5f07fbdbeb7e3efa9756903044dd29401fd1d4bb4a1c90600090a35b5b505b5050565b600054600160a060020a031681565b60016020526000908152604090205460ff1681565b610586610687565b60028054806020026020016040519081016040528092919081815260200182805480156105dc57602002820191906000526020600020905b8154600160a060020a031681526001909101906020018083116105be575b505050505090505b90565b60005433600160a060020a039081169116146106035760006000fd5b600160a060020a0381161561038d5760008054600160a060020a031916600160a060020a0383161790555b5b5b50565b81548183558181151161055357600083815260209020610553918101908301610699565b5b505050565b81548183558181151161055357600083815260209020610553918101908301610699565b5b505050565b60408051602081019091526000815290565b6105e491905b808211156106b3576000815560010161069f565b5090565b905600a165627a7a72305820d2924957bb88a128789172e164d874fe5445218fc2dde2f5eb265839a1f341a20029", - "networks": { - "1": { - "links": {}, - "events": { - "0x94bb87f4c15c4587ff559a7584006fa01ddf9299359be6b512b94527aa961aca": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "target", - "type": "address" - }, - { - "indexed": true, - "name": "caller", - "type": "address" - } - ], - "name": "LogAuthorizedAddressAdded", - "type": "event" - }, - "0xf5b347a1e40749dd050f5f07fbdbeb7e3efa9756903044dd29401fd1d4bb4a1c": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "target", - "type": "address" - }, - { - "indexed": true, - "name": "caller", - "type": "address" - } - ], - "name": "LogAuthorizedAddressRemoved", - "type": "event" - } - }, - "updated_at": 1502478966000, - "address": "0x8da0d80f5007ef1e431dd2127178d224e32c2ef4" - }, - "42": { - "links": {}, - "events": { - "0x94bb87f4c15c4587ff559a7584006fa01ddf9299359be6b512b94527aa961aca": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "target", - "type": "address" - }, - { - "indexed": true, - "name": "caller", - "type": "address" - } - ], - "name": "LogAuthorizedAddressAdded", - "type": "event" - }, - "0xf5b347a1e40749dd050f5f07fbdbeb7e3efa9756903044dd29401fd1d4bb4a1c": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "target", - "type": "address" - }, - { - "indexed": true, - "name": "caller", - "type": "address" - } - ], - "name": "LogAuthorizedAddressRemoved", - "type": "event" - } - }, - "updated_at": 1502391794384, - "address": "0x087eed4bc1ee3de49befbd66c662b434b15d49d4" - }, - "50": { - "links": {}, - "events": { - "0x94bb87f4c15c4587ff559a7584006fa01ddf9299359be6b512b94527aa961aca": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "target", - "type": "address" - }, - { - "indexed": true, - "name": "caller", - "type": "address" - } - ], - "name": "LogAuthorizedAddressAdded", - "type": "event" - }, - "0xf5b347a1e40749dd050f5f07fbdbeb7e3efa9756903044dd29401fd1d4bb4a1c": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "target", - "type": "address" - }, - { - "indexed": true, - "name": "caller", - "type": "address" - } - ], - "name": "LogAuthorizedAddressRemoved", - "type": "event" - } - }, - "updated_at": 1503318938227, - "address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c" - } - }, + "networks": {}, "schema_version": "0.0.5", "updated_at": 1503318938227 -} \ No newline at end of file +} diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 73c4d935b..17e8095a4 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -748,4 +748,9 @@ export class ExchangeWrapper extends ContractWrapper { const ZRXtokenAddress = await exchangeInstance.ZRX_TOKEN_CONTRACT.callAsync(); return ZRXtokenAddress; } + private async _getTokenTransferProxyAddressAsync(): Promise { + const exchangeInstance = await this._getExchangeContractAsync(); + const tokenTransferProxyAddress = await exchangeInstance.TOKEN_TRANSFER_PROXY_CONTRACT.callAsync(); + return tokenTransferProxyAddress; + } } diff --git a/src/contract_wrappers/token_transfer_proxy_wrapper.ts b/src/contract_wrappers/token_transfer_proxy_wrapper.ts index 528d661d1..f81845af9 100644 --- a/src/contract_wrappers/token_transfer_proxy_wrapper.ts +++ b/src/contract_wrappers/token_transfer_proxy_wrapper.ts @@ -1,4 +1,5 @@ import * as _ from 'lodash'; +import {Web3Wrapper} from '../web3_wrapper'; import {ContractWrapper} from './contract_wrapper'; import {artifacts} from '../artifacts'; import {TokenTransferProxyContract} from '../types'; @@ -8,6 +9,11 @@ import {TokenTransferProxyContract} from '../types'; */ export class TokenTransferProxyWrapper extends ContractWrapper { private _tokenTransferProxyContractIfExists?: TokenTransferProxyContract; + private _tokenTransferProxyContractAddressFetcher: () => Promise; + constructor(web3Wrapper: Web3Wrapper, tokenTransferProxyContractAddressFetcher: () => Promise) { + super(web3Wrapper); + this._tokenTransferProxyContractAddressFetcher = tokenTransferProxyContractAddressFetcher; + } /** * Check if the Exchange contract address is authorized by the TokenTransferProxy contract. * @param exchangeContractAddress The hex encoded address of the Exchange contract to call. @@ -44,8 +50,9 @@ export class TokenTransferProxyWrapper extends ContractWrapper { if (!_.isUndefined(this._tokenTransferProxyContractIfExists)) { return this._tokenTransferProxyContractIfExists; } + const contractAddress = await this._tokenTransferProxyContractAddressFetcher(); const contractInstance = await this._instantiateContractIfExistsAsync( - artifacts.TokenTransferProxyArtifact, + artifacts.TokenTransferProxyArtifact, contractAddress, ); this._tokenTransferProxyContractIfExists = contractInstance as TokenTransferProxyContract; return this._tokenTransferProxyContractIfExists; diff --git a/src/contract_wrappers/token_wrapper.ts b/src/contract_wrappers/token_wrapper.ts index bdfdf0c74..59c4a4e7b 100644 --- a/src/contract_wrappers/token_wrapper.ts +++ b/src/contract_wrappers/token_wrapper.ts @@ -31,10 +31,12 @@ export class TokenWrapper extends ContractWrapper { public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; private _tokenContractsByAddress: {[address: string]: TokenContract}; private _tokenLogEventEmitters: ContractEventEmitter[]; - constructor(web3Wrapper: Web3Wrapper) { + private _tokenTransferProxyContractAddressFetcher: () => Promise; + constructor(web3Wrapper: Web3Wrapper, tokenTransferProxyContractAddressFetcher: () => Promise) { super(web3Wrapper); this._tokenContractsByAddress = {}; this._tokenLogEventEmitters = []; + this._tokenTransferProxyContractAddressFetcher = tokenTransferProxyContractAddressFetcher; } /** * Retrieves an owner's ERC20 token balance. @@ -133,7 +135,7 @@ export class TokenWrapper extends ContractWrapper { assert.isETHAddressHex('ownerAddress', ownerAddress); assert.isETHAddressHex('tokenAddress', tokenAddress); - const proxyAddress = await this._getProxyAddressAsync(); + const proxyAddress = await this._getTokentransferProxyAddressAsync(); const allowanceInBaseUnits = await this.getAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, methodOpts); return allowanceInBaseUnits; } @@ -152,7 +154,7 @@ export class TokenWrapper extends ContractWrapper { assert.isETHAddressHex('tokenAddress', tokenAddress); assert.isBigNumber('amountInBaseUnits', amountInBaseUnits); - const proxyAddress = await this._getProxyAddressAsync(); + const proxyAddress = await this._getTokentransferProxyAddressAsync(); const txHash = await this.setAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, amountInBaseUnits); return txHash; } @@ -299,15 +301,9 @@ export class TokenWrapper extends ContractWrapper { this._tokenContractsByAddress[tokenAddress] = tokenContract; return tokenContract; } - private async _getProxyAddressAsync() { - const networkIdIfExists = await this._web3Wrapper.getNetworkIdIfExistsAsync(); - const proxyNetworkConfigsIfExists = _.isUndefined(networkIdIfExists) ? - undefined : - artifacts.TokenTransferProxyArtifact.networks[networkIdIfExists]; - if (_.isUndefined(proxyNetworkConfigsIfExists)) { - throw new Error(ZeroExError.ContractNotDeployedOnNetwork); - } - const proxyAddress = proxyNetworkConfigsIfExists.address.toLowerCase(); - return proxyAddress; + private async _getTokentransferProxyAddressAsync(): Promise { + const tokenTransferProxyContractAddress = await this._tokenTransferProxyContractAddressFetcher(); + const lowerCaseTokenTransferProxyContractAddress = tokenTransferProxyContractAddress.toLowerCase(); + return lowerCaseTokenTransferProxyContractAddress; } } diff --git a/src/types.ts b/src/types.ts index eb83d7c2b..c7204a9fc 100644 --- a/src/types.ts +++ b/src/types.ts @@ -51,6 +51,9 @@ export interface ExchangeContract extends Web3.ContractInstance { ZRX_TOKEN_CONTRACT: { callAsync: () => Promise; }; + TOKEN_TRANSFER_PROXY_CONTRACT: { + callAsync: () => Promise; + }; getUnavailableTakerTokenAmount: { callAsync: (orderHash: string, defaultBlock?: Web3.BlockParam) => Promise; }; diff --git a/test/artifacts_test.ts b/test/artifacts_test.ts index 65d75f16e..59fd9e342 100644 --- a/test/artifacts_test.ts +++ b/test/artifacts_test.ts @@ -23,7 +23,7 @@ describe('Artifacts', () => { await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync(); }).timeout(TIMEOUT); it('proxy contract is deployed', async () => { - await (zeroEx.token as any)._getProxyAddressAsync(); + await (zeroEx.token as any)._getTokentransferProxyAddressAsync(); }).timeout(TIMEOUT); it('exchange contract is deployed', async () => { await zeroEx.exchange.getContractAddressAsync(); -- cgit v1.2.3 From 504e7a25a5ee138941ca35d4aad1b63444e47033 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 18 Sep 2017 15:55:26 +0200 Subject: Make contract addresses configurable --- src/0x.ts | 9 ++++++--- src/contract_wrappers/ether_token_wrapper.ts | 6 ++++-- src/contract_wrappers/exchange_wrapper.ts | 6 ++++-- src/contract_wrappers/token_registry_wrapper.ts | 6 ++++-- src/types.ts | 3 +++ 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/0x.ts b/src/0x.ts index 8a69bec30..37e25eb0f 100644 --- a/src/0x.ts +++ b/src/0x.ts @@ -198,13 +198,16 @@ export class ZeroEx { this._web3Wrapper, this._getTokenTransferProxyAddressAsync.bind(this), ); - this.exchange = new ExchangeWrapper(this._web3Wrapper, this.token); + const exchangeContractAddress = _.isUndefined(config) ? undefined : config.exchangeContractAddress; + this.exchange = new ExchangeWrapper(this._web3Wrapper, this.token, exchangeContractAddress); this.proxy = new TokenTransferProxyWrapper( this._web3Wrapper, this._getTokenTransferProxyAddressAsync.bind(this), ); - this.tokenRegistry = new TokenRegistryWrapper(this._web3Wrapper); - this.etherToken = new EtherTokenWrapper(this._web3Wrapper, this.token); + const tokenRegistryContractAddress = _.isUndefined(config) ? undefined : config.tokenRegistryContractAddress; + this.tokenRegistry = new TokenRegistryWrapper(this._web3Wrapper, tokenRegistryContractAddress); + const etherTokenContractAddress = _.isUndefined(config) ? undefined : config.etherTokenContractAddress; + this.etherToken = new EtherTokenWrapper(this._web3Wrapper, this.token, etherTokenContractAddress); } /** * Sets a new web3 provider for 0x.js. Updating the provider will stop all diff --git a/src/contract_wrappers/ether_token_wrapper.ts b/src/contract_wrappers/ether_token_wrapper.ts index b86309f90..efe3fe06c 100644 --- a/src/contract_wrappers/ether_token_wrapper.ts +++ b/src/contract_wrappers/ether_token_wrapper.ts @@ -13,9 +13,11 @@ import {artifacts} from '../artifacts'; export class EtherTokenWrapper extends ContractWrapper { private _etherTokenContractIfExists?: EtherTokenContract; private _tokenWrapper: TokenWrapper; - constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper) { + private _contractAddress?: string; + constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper, contractAddress?: string) { super(web3Wrapper); this._tokenWrapper = tokenWrapper; + this._contractAddress = contractAddress; } /** * Deposit ETH into the Wrapped ETH smart contract and issues the equivalent number of wrapped ETH tokens @@ -76,7 +78,7 @@ export class EtherTokenWrapper extends ContractWrapper { return this._etherTokenContractIfExists; } const contractInstance = await this._instantiateContractIfExistsAsync( - artifacts.EtherTokenArtifact, + artifacts.EtherTokenArtifact, this._contractAddress, ); this._etherTokenContractIfExists = contractInstance as EtherTokenContract; return this._etherTokenContractIfExists; diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 17e8095a4..2360f639d 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -56,6 +56,7 @@ export class ExchangeWrapper extends ContractWrapper { [ExchangeContractErrCodes.ERROR_FILL_TRUNCATION]: ExchangeContractErrs.OrderFillRoundingError, [ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.FillBalanceAllowanceError, }; + private _contractAddress?: string; private static _getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] { const orderAddresses: OrderAddresses = [ order.maker, @@ -74,11 +75,12 @@ export class ExchangeWrapper extends ContractWrapper { ]; return [orderAddresses, orderValues]; } - constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper) { + constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper, contractAddress?: string) { super(web3Wrapper); this._tokenWrapper = tokenWrapper; this._orderValidationUtils = new OrderValidationUtils(tokenWrapper, this); this._exchangeLogEventEmitters = []; + this._contractAddress = contractAddress; } /** * Returns the unavailable takerAmount of an order. Unavailable amount is defined as the total @@ -738,7 +740,7 @@ export class ExchangeWrapper extends ContractWrapper { return this._exchangeContractIfExists; } const contractInstance = await this._instantiateContractIfExistsAsync( - artifacts.ExchangeArtifact, + artifacts.ExchangeArtifact, this._contractAddress, ); this._exchangeContractIfExists = contractInstance as ExchangeContract; return this._exchangeContractIfExists; diff --git a/src/contract_wrappers/token_registry_wrapper.ts b/src/contract_wrappers/token_registry_wrapper.ts index 528a88e06..0807982b1 100644 --- a/src/contract_wrappers/token_registry_wrapper.ts +++ b/src/contract_wrappers/token_registry_wrapper.ts @@ -11,8 +11,10 @@ import {artifacts} from '../artifacts'; */ export class TokenRegistryWrapper extends ContractWrapper { private _tokenRegistryContractIfExists?: TokenRegistryContract; - constructor(web3Wrapper: Web3Wrapper) { + private _contractAddress?: string; + constructor(web3Wrapper: Web3Wrapper, contractAddress?: string) { super(web3Wrapper); + this._contractAddress = contractAddress; } /** * Retrieves all the tokens currently listed in the Token Registry smart contract @@ -102,7 +104,7 @@ export class TokenRegistryWrapper extends ContractWrapper { return this._tokenRegistryContractIfExists; } const contractInstance = await this._instantiateContractIfExistsAsync( - artifacts.TokenRegistryArtifact, + artifacts.TokenRegistryArtifact, this._contractAddress, ); this._tokenRegistryContractIfExists = contractInstance as TokenRegistryContract; return this._tokenRegistryContractIfExists; diff --git a/src/types.ts b/src/types.ts index c7204a9fc..9583d5bd4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -391,6 +391,9 @@ export interface JSONRPCPayload { export interface ZeroExConfig { gasPrice?: BigNumber.BigNumber; // Gas price to use with every transaction + exchangeContractAddress?: string; + tokenRegistryContractAddress?: string; + etherTokenContractAddress?: string; } export type TransactionReceipt = Web3.TransactionReceipt; -- cgit v1.2.3 From 40a0d345b5fc00d36928387cd558133358624f12 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 18 Sep 2017 16:54:24 +0200 Subject: Add tests for contracts address config --- src/contract_wrappers/token_registry_wrapper.ts | 10 +++++++++ test/0x.js_test.ts | 29 +++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/contract_wrappers/token_registry_wrapper.ts b/src/contract_wrappers/token_registry_wrapper.ts index 0807982b1..fb0ab78f6 100644 --- a/src/contract_wrappers/token_registry_wrapper.ts +++ b/src/contract_wrappers/token_registry_wrapper.ts @@ -84,6 +84,16 @@ export class TokenRegistryWrapper extends ContractWrapper { const token = this._createTokenFromMetadata(metadata); return token; } + /** + * Retrieves the Ethereum address of the TokenRegistry contract deployed on the network + * that the user-passed web3 provider is connected to. + * @returns The Ethereum address of the TokenRegistry contract being used. + */ + public async getContractAddressAsync(): Promise { + const tokenRegistryInstance = await this._getTokenRegistryContractAsync(); + const tokenRegistryAddress = tokenRegistryInstance.address; + return tokenRegistryAddress; + } private _createTokenFromMetadata(metadata: TokenMetadata): Token|undefined { if (metadata[0] === constants.NULL_ADDRESS) { return undefined; diff --git a/test/0x.js_test.ts b/test/0x.js_test.ts index 5461a7d3f..cc6b91e99 100644 --- a/test/0x.js_test.ts +++ b/test/0x.js_test.ts @@ -4,12 +4,11 @@ import {chaiSetup} from './utils/chai_setup'; import 'mocha'; import * as BigNumber from 'bignumber.js'; import * as Sinon from 'sinon'; -import {ZeroEx, Order} from '../src'; +import {ZeroEx, Order, ZeroExError, LogWithDecodedArgs} from '../src'; import {constants} from './utils/constants'; import {TokenUtils} from './utils/token_utils'; import {web3Factory} from './utils/web3_factory'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; -import {LogWithDecodedArgs} from '../src'; const blockchainLifecycle = new BlockchainLifecycle(); chaiSetup.configure(); @@ -231,4 +230,30 @@ describe('ZeroEx library', () => { expect(log.args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); }); }); + describe('#config', () => { + it('allows to specify exchange contract address', async () => { + const config = { + exchangeContractAddress: ZeroEx.NULL_ADDRESS, + }; + const zeroExWithWrongExchangeAddress = new ZeroEx(web3.currentProvider, config); + return expect(zeroExWithWrongExchangeAddress.exchange.getContractAddressAsync()) + .to.be.rejectedWith(ZeroExError.ContractDoesNotExist); + }); + it('allows to specify ether token contract address', async () => { + const config = { + etherTokenContractAddress: ZeroEx.NULL_ADDRESS, + }; + const zeroExWithWrongEtherTokenAddress = new ZeroEx(web3.currentProvider, config); + return expect(zeroExWithWrongEtherTokenAddress.etherToken.getContractAddressAsync()) + .to.be.rejectedWith(ZeroExError.ContractDoesNotExist); + }); + it('allows to specify token registry token contract address', async () => { + const config = { + tokenRegistryContractAddress: ZeroEx.NULL_ADDRESS, + }; + const zeroExWithWrongTokenRegistryAddress = new ZeroEx(web3.currentProvider, config); + return expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddressAsync()) + .to.be.rejectedWith(ZeroExError.ContractDoesNotExist); + }); + }); }); -- cgit v1.2.3 From 946978e454a93b9642a9ed261229ea749e71fd2f Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 18 Sep 2017 17:24:54 +0200 Subject: Add explanatory comment --- src/0x.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/0x.ts b/src/0x.ts index 37e25eb0f..70d0c7acf 100644 --- a/src/0x.ts +++ b/src/0x.ts @@ -315,6 +315,12 @@ export class ZeroEx { }); return txReceiptPromise; } + /* + * `TokenWrapper` needs a token transfer proxy address. `TokenTransferProxy` address is fetched from + * an `ExchnageWrapper`. `ExchangeWrapper` needs `TokenWrapper` to validate orders. Cycle. + * In order to break this - we create this function here and pass it as a parameter to the `TokenWrapper` + * and `ProxyWrapper`. + */ private async _getTokenTransferProxyAddressAsync(): Promise { const tokenTransferProxyAddress = await (this.exchange as any)._getTokenTransferProxyAddressAsync(); return tokenTransferProxyAddress; -- cgit v1.2.3 From e19d5b3c78d1f986bc7e0db70a8241b9f2995763 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 18 Sep 2017 17:26:30 +0200 Subject: Fix a typo --- src/contract_wrappers/token_wrapper.ts | 6 +++--- test/artifacts_test.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/contract_wrappers/token_wrapper.ts b/src/contract_wrappers/token_wrapper.ts index 59c4a4e7b..167815d73 100644 --- a/src/contract_wrappers/token_wrapper.ts +++ b/src/contract_wrappers/token_wrapper.ts @@ -135,7 +135,7 @@ export class TokenWrapper extends ContractWrapper { assert.isETHAddressHex('ownerAddress', ownerAddress); assert.isETHAddressHex('tokenAddress', tokenAddress); - const proxyAddress = await this._getTokentransferProxyAddressAsync(); + const proxyAddress = await this._getTokenTransferProxyAddressAsync(); const allowanceInBaseUnits = await this.getAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, methodOpts); return allowanceInBaseUnits; } @@ -154,7 +154,7 @@ export class TokenWrapper extends ContractWrapper { assert.isETHAddressHex('tokenAddress', tokenAddress); assert.isBigNumber('amountInBaseUnits', amountInBaseUnits); - const proxyAddress = await this._getTokentransferProxyAddressAsync(); + const proxyAddress = await this._getTokenTransferProxyAddressAsync(); const txHash = await this.setAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, amountInBaseUnits); return txHash; } @@ -301,7 +301,7 @@ export class TokenWrapper extends ContractWrapper { this._tokenContractsByAddress[tokenAddress] = tokenContract; return tokenContract; } - private async _getTokentransferProxyAddressAsync(): Promise { + private async _getTokenTransferProxyAddressAsync(): Promise { const tokenTransferProxyContractAddress = await this._tokenTransferProxyContractAddressFetcher(); const lowerCaseTokenTransferProxyContractAddress = tokenTransferProxyContractAddress.toLowerCase(); return lowerCaseTokenTransferProxyContractAddress; diff --git a/test/artifacts_test.ts b/test/artifacts_test.ts index 59fd9e342..bd34a6b91 100644 --- a/test/artifacts_test.ts +++ b/test/artifacts_test.ts @@ -23,7 +23,7 @@ describe('Artifacts', () => { await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync(); }).timeout(TIMEOUT); it('proxy contract is deployed', async () => { - await (zeroEx.token as any)._getTokentransferProxyAddressAsync(); + await (zeroEx.token as any)._getTokenTransferProxyAddressAsync(); }).timeout(TIMEOUT); it('exchange contract is deployed', async () => { await zeroEx.exchange.getContractAddressAsync(); -- cgit v1.2.3 From 4aeb6226d557ef924eb2182b383f5e77d7fc8199 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 19 Sep 2017 13:29:15 +0200 Subject: Add changes to the CHANGELOG --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bd1f5f34..c58d6566d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # CHANGELOG +v0.16.0 - _TBD, 2017_ +------------------------ + * Added the ability to specify custom contract addresses to be used with 0x.js (#165) + * ZeroExConfig.exchangeContractAddress + * ZeroExConfig.tokenRegistryContractAddress + * ZeroExConfig.etherTokenContractAddress + * Added `zeroEx.tokenRegistry.getContractAddressAsync` (#165) + v0.15.0 - _September 8, 2017_ ------------------------ * Added the ability to specify a historical `blockNumber` at which to query the blockchain's state when calling a token or exchange method (#161) -- cgit v1.2.3 From 903e2f4f8a1de54bae3863ecbfab1855a2edc55f Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 19 Sep 2017 14:13:06 +0200 Subject: Verify ZeroExConfig --- src/0x.ts | 4 ++++ src/schemas/zero_ex_config_schema.ts | 10 ++++++++++ 2 files changed, 14 insertions(+) create mode 100644 src/schemas/zero_ex_config_schema.ts diff --git a/src/0x.ts b/src/0x.ts index 70d0c7acf..ce2738a20 100644 --- a/src/0x.ts +++ b/src/0x.ts @@ -32,6 +32,7 @@ import { TransactionReceiptWithDecodedLogs, LogWithDecodedArgs, } from './types'; +import {zeroExConfigSchema} from './schemas/zero_ex_config_schema'; // Customize our BigNumber instances bigNumberConfigs.configure(); @@ -180,6 +181,9 @@ export class ZeroEx { */ constructor(provider: Web3Provider, config?: ZeroExConfig) { assert.isWeb3Provider('provider', provider); + if (!_.isUndefined(config)) { + assert.doesConformToSchema('config', config, zeroExConfigSchema); + } if (_.isUndefined((provider as any).sendAsync)) { // Web3@1.0 provider doesn't support synchronous http requests, // so it only has an async `send` method, instead of a `send` and `sendAsync` in web3@0.x.x` diff --git a/src/schemas/zero_ex_config_schema.ts b/src/schemas/zero_ex_config_schema.ts new file mode 100644 index 000000000..179e29c31 --- /dev/null +++ b/src/schemas/zero_ex_config_schema.ts @@ -0,0 +1,10 @@ +export const zeroExConfigSchema = { + id: '/ZeroExConfig', + properties: { + gasPrice: {$ref: '/Number'}, + exchangeContractAddress: {$ref: '/Address'}, + tokenRegistryContractAddress: {$ref: '/Address'}, + etherTokenContractAddress: {$ref: '/Address'}, + }, + type: 'object', +}; -- cgit v1.2.3 From 5e40f769969a67ab06e78b98a933413102529a41 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 19 Sep 2017 14:43:14 +0200 Subject: Postfix variable names with 'ifExists' --- src/0x.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/0x.ts b/src/0x.ts index ce2738a20..62ac7b212 100644 --- a/src/0x.ts +++ b/src/0x.ts @@ -202,16 +202,18 @@ export class ZeroEx { this._web3Wrapper, this._getTokenTransferProxyAddressAsync.bind(this), ); - const exchangeContractAddress = _.isUndefined(config) ? undefined : config.exchangeContractAddress; - this.exchange = new ExchangeWrapper(this._web3Wrapper, this.token, exchangeContractAddress); + const exchageContractAddressIfExists = _.isUndefined(config) ? undefined : config.exchangeContractAddress; + this.exchange = new ExchangeWrapper(this._web3Wrapper, this.token, exchageContractAddressIfExists); this.proxy = new TokenTransferProxyWrapper( this._web3Wrapper, this._getTokenTransferProxyAddressAsync.bind(this), ); - const tokenRegistryContractAddress = _.isUndefined(config) ? undefined : config.tokenRegistryContractAddress; - this.tokenRegistry = new TokenRegistryWrapper(this._web3Wrapper, tokenRegistryContractAddress); - const etherTokenContractAddress = _.isUndefined(config) ? undefined : config.etherTokenContractAddress; - this.etherToken = new EtherTokenWrapper(this._web3Wrapper, this.token, etherTokenContractAddress); + const tokenRegistryContractAddressIfExists = _.isUndefined(config) ? + undefined : + config.tokenRegistryContractAddress; + this.tokenRegistry = new TokenRegistryWrapper(this._web3Wrapper, tokenRegistryContractAddressIfExists); + const etherTokenContractAddressIfExists = _.isUndefined(config) ? undefined : config.etherTokenContractAddress; + this.etherToken = new EtherTokenWrapper(this._web3Wrapper, this.token, etherTokenContractAddressIfExists); } /** * Sets a new web3 provider for 0x.js. Updating the provider will stop all -- cgit v1.2.3 From e7af0eb20c108eae1c0e753d1079c2db3c13a583 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 19 Sep 2017 14:43:42 +0200 Subject: Prefix HACK comment with HACK --- src/0x.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/0x.ts b/src/0x.ts index 62ac7b212..d2899c401 100644 --- a/src/0x.ts +++ b/src/0x.ts @@ -322,7 +322,7 @@ export class ZeroEx { return txReceiptPromise; } /* - * `TokenWrapper` needs a token transfer proxy address. `TokenTransferProxy` address is fetched from + * HACK: `TokenWrapper` needs a token transfer proxy address. `TokenTransferProxy` address is fetched from * an `ExchnageWrapper`. `ExchangeWrapper` needs `TokenWrapper` to validate orders. Cycle. * In order to break this - we create this function here and pass it as a parameter to the `TokenWrapper` * and `ProxyWrapper`. -- cgit v1.2.3 From 66db021900cf4ac824635512052afb2bddb0299c Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 19 Sep 2017 14:53:12 +0200 Subject: Postfix variable names with 'ifExists' --- src/contract_wrappers/contract_wrapper.ts | 5 +++-- src/contract_wrappers/ether_token_wrapper.ts | 8 ++++---- src/contract_wrappers/exchange_wrapper.ts | 8 ++++---- src/contract_wrappers/token_registry_wrapper.ts | 8 ++++---- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/contract_wrappers/contract_wrapper.ts b/src/contract_wrappers/contract_wrapper.ts index 4e3fb5029..2a55b53d9 100644 --- a/src/contract_wrappers/contract_wrapper.ts +++ b/src/contract_wrappers/contract_wrapper.ts @@ -10,9 +10,10 @@ export class ContractWrapper { this._web3Wrapper = web3Wrapper; } protected async _instantiateContractIfExistsAsync(artifact: Artifact, - address?: string): Promise { + addressIfExists?: string, + ): Promise { const contractInstance = - await this._web3Wrapper.getContractInstanceFromArtifactAsync(artifact, address); + await this._web3Wrapper.getContractInstanceFromArtifactAsync(artifact, addressIfExists); return contractInstance; } } diff --git a/src/contract_wrappers/ether_token_wrapper.ts b/src/contract_wrappers/ether_token_wrapper.ts index efe3fe06c..f15e766f0 100644 --- a/src/contract_wrappers/ether_token_wrapper.ts +++ b/src/contract_wrappers/ether_token_wrapper.ts @@ -13,11 +13,11 @@ import {artifacts} from '../artifacts'; export class EtherTokenWrapper extends ContractWrapper { private _etherTokenContractIfExists?: EtherTokenContract; private _tokenWrapper: TokenWrapper; - private _contractAddress?: string; - constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper, contractAddress?: string) { + private _contractAddressIfExists?: string; + constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper, contractAddressIfExists?: string) { super(web3Wrapper); this._tokenWrapper = tokenWrapper; - this._contractAddress = contractAddress; + this._contractAddressIfExists = contractAddressIfExists; } /** * Deposit ETH into the Wrapped ETH smart contract and issues the equivalent number of wrapped ETH tokens @@ -78,7 +78,7 @@ export class EtherTokenWrapper extends ContractWrapper { return this._etherTokenContractIfExists; } const contractInstance = await this._instantiateContractIfExistsAsync( - artifacts.EtherTokenArtifact, this._contractAddress, + artifacts.EtherTokenArtifact, this._contractAddressIfExists, ); this._etherTokenContractIfExists = contractInstance as EtherTokenContract; return this._etherTokenContractIfExists; diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 2360f639d..11a448680 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -56,7 +56,7 @@ export class ExchangeWrapper extends ContractWrapper { [ExchangeContractErrCodes.ERROR_FILL_TRUNCATION]: ExchangeContractErrs.OrderFillRoundingError, [ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.FillBalanceAllowanceError, }; - private _contractAddress?: string; + private _contractAddressIfExists?: string; private static _getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] { const orderAddresses: OrderAddresses = [ order.maker, @@ -75,12 +75,12 @@ export class ExchangeWrapper extends ContractWrapper { ]; return [orderAddresses, orderValues]; } - constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper, contractAddress?: string) { + constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper, contractAddressIfExists?: string) { super(web3Wrapper); this._tokenWrapper = tokenWrapper; this._orderValidationUtils = new OrderValidationUtils(tokenWrapper, this); this._exchangeLogEventEmitters = []; - this._contractAddress = contractAddress; + this._contractAddressIfExists = contractAddressIfExists; } /** * Returns the unavailable takerAmount of an order. Unavailable amount is defined as the total @@ -740,7 +740,7 @@ export class ExchangeWrapper extends ContractWrapper { return this._exchangeContractIfExists; } const contractInstance = await this._instantiateContractIfExistsAsync( - artifacts.ExchangeArtifact, this._contractAddress, + artifacts.ExchangeArtifact, this._contractAddressIfExists, ); this._exchangeContractIfExists = contractInstance as ExchangeContract; return this._exchangeContractIfExists; diff --git a/src/contract_wrappers/token_registry_wrapper.ts b/src/contract_wrappers/token_registry_wrapper.ts index fb0ab78f6..2cc5a9aa0 100644 --- a/src/contract_wrappers/token_registry_wrapper.ts +++ b/src/contract_wrappers/token_registry_wrapper.ts @@ -11,10 +11,10 @@ import {artifacts} from '../artifacts'; */ export class TokenRegistryWrapper extends ContractWrapper { private _tokenRegistryContractIfExists?: TokenRegistryContract; - private _contractAddress?: string; - constructor(web3Wrapper: Web3Wrapper, contractAddress?: string) { + private _contractAddressIfExists?: string; + constructor(web3Wrapper: Web3Wrapper, contractAddressIfExists?: string) { super(web3Wrapper); - this._contractAddress = contractAddress; + this._contractAddressIfExists = contractAddressIfExists; } /** * Retrieves all the tokens currently listed in the Token Registry smart contract @@ -114,7 +114,7 @@ export class TokenRegistryWrapper extends ContractWrapper { return this._tokenRegistryContractIfExists; } const contractInstance = await this._instantiateContractIfExistsAsync( - artifacts.TokenRegistryArtifact, this._contractAddress, + artifacts.TokenRegistryArtifact, this._contractAddressIfExists, ); this._tokenRegistryContractIfExists = contractInstance as TokenRegistryContract; return this._tokenRegistryContractIfExists; -- cgit v1.2.3 From f1cb3a4f37f0382ebf3c0ec37a44587cbedf4cad Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 19 Sep 2017 14:53:58 +0200 Subject: Fix a comment --- src/0x.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/0x.ts b/src/0x.ts index d2899c401..e6fdf68e1 100644 --- a/src/0x.ts +++ b/src/0x.ts @@ -323,7 +323,7 @@ export class ZeroEx { } /* * HACK: `TokenWrapper` needs a token transfer proxy address. `TokenTransferProxy` address is fetched from - * an `ExchnageWrapper`. `ExchangeWrapper` needs `TokenWrapper` to validate orders. Cycle. + * an `ExchangeWrapper`. `ExchangeWrapper` needs `TokenWrapper` to validate orders, creating a dependency cycle. * In order to break this - we create this function here and pass it as a parameter to the `TokenWrapper` * and `ProxyWrapper`. */ -- cgit v1.2.3 From 0f942f95f0e8bed3db1bf0bc44b2b7f98c478d6b Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 19 Sep 2017 14:56:41 +0200 Subject: Move lower-casing logic --- src/contract_wrappers/exchange_wrapper.ts | 3 ++- src/contract_wrappers/token_wrapper.ts | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 11a448680..54d7f62d5 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -753,6 +753,7 @@ export class ExchangeWrapper extends ContractWrapper { private async _getTokenTransferProxyAddressAsync(): Promise { const exchangeInstance = await this._getExchangeContractAsync(); const tokenTransferProxyAddress = await exchangeInstance.TOKEN_TRANSFER_PROXY_CONTRACT.callAsync(); - return tokenTransferProxyAddress; + const tokenTransferProxyAddressLowerCase = tokenTransferProxyAddress.toLowerCase(); + return tokenTransferProxyAddressLowerCase; } } diff --git a/src/contract_wrappers/token_wrapper.ts b/src/contract_wrappers/token_wrapper.ts index 167815d73..f7f0a0ce3 100644 --- a/src/contract_wrappers/token_wrapper.ts +++ b/src/contract_wrappers/token_wrapper.ts @@ -303,7 +303,6 @@ export class TokenWrapper extends ContractWrapper { } private async _getTokenTransferProxyAddressAsync(): Promise { const tokenTransferProxyContractAddress = await this._tokenTransferProxyContractAddressFetcher(); - const lowerCaseTokenTransferProxyContractAddress = tokenTransferProxyContractAddress.toLowerCase(); - return lowerCaseTokenTransferProxyContractAddress; + return tokenTransferProxyContractAddress; } } -- cgit v1.2.3 From 96d853fc4baecd0c10727539a32b04dadef73026 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 19 Sep 2017 15:09:05 +0200 Subject: Add a comment for ZeroExConfig type --- src/types.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/types.ts b/src/types.ts index 9583d5bd4..b10d95adc 100644 --- a/src/types.ts +++ b/src/types.ts @@ -389,6 +389,12 @@ export interface JSONRPCPayload { method: string; } +/* + * gasPirce: Gas price to use with every transaction + * exchangeContractAddress: The address of an exchange contract to use + * tokenRegistryContractAddress: The address of a token registry contract to use + * etherTokenContractAddress: The address of an ether token contract to use + */ export interface ZeroExConfig { gasPrice?: BigNumber.BigNumber; // Gas price to use with every transaction exchangeContractAddress?: string; -- cgit v1.2.3 From 1efcc5ad6267f0a46588ccd79f31b1aa0026dcc6 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 20 Sep 2017 14:57:33 +0200 Subject: Fix the typo --- src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index b10d95adc..29fb40e73 100644 --- a/src/types.ts +++ b/src/types.ts @@ -390,7 +390,7 @@ export interface JSONRPCPayload { } /* - * gasPirce: Gas price to use with every transaction + * gasPrice: Gas price to use with every transaction * exchangeContractAddress: The address of an exchange contract to use * tokenRegistryContractAddress: The address of a token registry contract to use * etherTokenContractAddress: The address of an ether token contract to use -- cgit v1.2.3 From 91679caf936d3b3df369b2339c55468b222c9a16 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 20 Sep 2017 14:59:21 +0200 Subject: Update release date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c58d6566d..61031c089 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # CHANGELOG -v0.16.0 - _TBD, 2017_ +v0.16.0 - _September 20, 2017_ ------------------------ * Added the ability to specify custom contract addresses to be used with 0x.js (#165) * ZeroExConfig.exchangeContractAddress -- cgit v1.2.3