From 2c3b718a4fa063277163e72f1be962dab3dfd21a Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Tue, 30 May 2017 14:48:41 +0200 Subject: rename erc20Wrapper to tokenWrapper to be more generic in case we end up supporting another spec --- src/0x.js.ts | 17 ++++++++--- src/contract_wrappers/erc20_wrapper.ts | 28 ----------------- src/contract_wrappers/token_wrapper.ts | 42 ++++++++++++++++++++++++++ test/erc20_wrapper_test.ts | 55 ---------------------------------- test/token_wrapper_test.ts | 55 ++++++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 87 deletions(-) delete mode 100644 src/contract_wrappers/erc20_wrapper.ts create mode 100644 src/contract_wrappers/token_wrapper.ts delete mode 100644 test/erc20_wrapper_test.ts create mode 100644 test/token_wrapper_test.ts diff --git a/src/0x.js.ts b/src/0x.js.ts index 7932559fb..96b290439 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -13,16 +13,16 @@ import compareVersions = require('compare-versions'); import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; import {TokenRegistryWrapper} from './contract_wrappers/token_registry_wrapper'; import {ecSignatureSchema} from './schemas/ec_signature_schema'; -import {ERC20Wrapper} from './contract_wrappers/erc20_wrapper'; +import {TokenWrapper} from './contract_wrappers/token_wrapper'; import {SolidityTypes, ECSignature, ZeroExError} from './types'; const MAX_DIGITS_IN_UNSIGNED_256_INT = 78; export class ZeroEx { - public web3Wrapper: Web3Wrapper; public exchange: ExchangeWrapper; public tokenRegistry: TokenRegistryWrapper; - public erc20: ERC20Wrapper; + public erc20: TokenWrapper; + private web3Wrapper: Web3Wrapper; /** * Computes the orderHash given the order parameters and returns it as a hex encoded string. */ @@ -137,7 +137,16 @@ export class ZeroEx { this.web3Wrapper = new Web3Wrapper(web3); this.exchange = new ExchangeWrapper(this.web3Wrapper); this.tokenRegistry = new TokenRegistryWrapper(this.web3Wrapper); - this.erc20 = new ERC20Wrapper(this.web3Wrapper); + this.erc20 = new TokenWrapper(this.web3Wrapper); + } + /** + * Sets a new provider for the web3 instance used by 0x.js + */ + public setProvider(provider: Web3.Provider) { + this.web3Wrapper.setProvider(provider); + this.exchange.invalidateContractInstance(); + this.tokenRegistry.invalidateContractInstance(); + this.erc20.invalidateContractInstances(); } /** * Signs an orderHash and returns it's elliptic curve signature diff --git a/src/contract_wrappers/erc20_wrapper.ts b/src/contract_wrappers/erc20_wrapper.ts deleted file mode 100644 index 60b1887db..000000000 --- a/src/contract_wrappers/erc20_wrapper.ts +++ /dev/null @@ -1,28 +0,0 @@ -import * as _ from 'lodash'; -import * as BigNumber from 'bignumber.js'; -import {Web3Wrapper} from '../web3_wrapper'; -import {assert} from '../utils/assert'; -import {ContractWrapper} from './contract_wrapper'; -import * as TokenArtifacts from '../artifacts/Token.json'; -import {ERC20Contract} from '../types'; - -export class ERC20Wrapper extends ContractWrapper { - constructor(web3Wrapper: Web3Wrapper) { - super(web3Wrapper); - } - /** - * Returns an owner's ERC20 token balance - */ - public async getBalanceAsync(tokenAddress: string, ownerAddress: string): Promise { - assert.isETHAddressHex('ownerAddress', ownerAddress); - assert.isETHAddressHex('tokenAddress', tokenAddress); - - const contractInstance = await this.instantiateContractIfExistsAsync((TokenArtifacts as any), tokenAddress); - const tokenContract = contractInstance as ERC20Contract; - let balance = await tokenContract.balanceOf.call(ownerAddress); - // The BigNumber instance returned by Web3 is of a much older version then our own, we therefore - // should always re-instantiate the returned BigNumber after retrieval. - balance = _.isUndefined(balance) ? new BigNumber(0) : new BigNumber(balance); - return balance; - } -} diff --git a/src/contract_wrappers/token_wrapper.ts b/src/contract_wrappers/token_wrapper.ts new file mode 100644 index 000000000..bd815554a --- /dev/null +++ b/src/contract_wrappers/token_wrapper.ts @@ -0,0 +1,42 @@ +import * as _ from 'lodash'; +import * as BigNumber from 'bignumber.js'; +import {Web3Wrapper} from '../web3_wrapper'; +import {assert} from '../utils/assert'; +import {ContractWrapper} from './contract_wrapper'; +import * as TokenArtifacts from '../artifacts/Token.json'; +import {ERC20Contract} from '../types'; + +export class TokenWrapper extends ContractWrapper { + private tokenContractsByAddress: {[address: string]: ERC20Contract}; + constructor(web3Wrapper: Web3Wrapper) { + super(web3Wrapper); + this.tokenContractsByAddress = {}; + } + public invalidateContractInstances() { + this.tokenContractsByAddress = {}; + } + /** + * Returns an owner's ERC20 token balance + */ + public async getBalanceAsync(tokenAddress: string, ownerAddress: string): Promise { + assert.isETHAddressHex('ownerAddress', ownerAddress); + assert.isETHAddressHex('tokenAddress', tokenAddress); + + const tokenContract = await this.getTokenContractAsync(tokenAddress); + let balance = await tokenContract.balanceOf.call(ownerAddress); + // The BigNumber instance returned by Web3 is of a much older version then our own, we therefore + // should always re-instantiate the returned BigNumber after retrieval. + balance = _.isUndefined(balance) ? new BigNumber(0) : new BigNumber(balance); + return balance; + } + private async getTokenContractAsync(tokenAddress: string): Promise { + let tokenContract = this.tokenContractsByAddress[tokenAddress]; + if (!_.isUndefined(tokenContract)) { + return tokenContract; + } + const contractInstance = await this.instantiateContractIfExistsAsync((TokenArtifacts as any), tokenAddress); + tokenContract = contractInstance as ERC20Contract; + this.tokenContractsByAddress[tokenAddress] = tokenContract; + return tokenContract; + } +} diff --git a/test/erc20_wrapper_test.ts b/test/erc20_wrapper_test.ts deleted file mode 100644 index c28c057a7..000000000 --- a/test/erc20_wrapper_test.ts +++ /dev/null @@ -1,55 +0,0 @@ -import 'mocha'; -import * as chai from 'chai'; -import chaiAsPromised = require('chai-as-promised'); -import * as Web3 from 'web3'; -import * as BigNumber from 'bignumber.js'; -import promisify = require('es6-promisify'); -import {web3Factory} from './utils/web3_factory'; -import {ZeroEx} from '../src/0x.js'; -import {ZeroExError, Token} from '../src/types'; -import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; - -const expect = chai.expect; -chai.use(chaiAsPromised); -const blockchainLifecycle = new BlockchainLifecycle(); - -describe('ERC20Wrapper', () => { - let web3: Web3; - let zeroEx: ZeroEx; - let userAddresses: string[]; - let tokens: Token[]; - before(async () => { - web3 = web3Factory.create(); - zeroEx = new ZeroEx(web3); - userAddresses = await promisify(web3.eth.getAccounts)(); - tokens = await zeroEx.tokenRegistry.getTokensAsync(); - }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - describe('#getBalanceAsync', () => { - it('should return the balance for an existing ERC20 token', async () => { - const aToken = tokens[0]; - const aOwnerAddress = userAddresses[0]; - const balance = await zeroEx.erc20.getBalanceAsync(aToken.address, aOwnerAddress); - const expectedBalance = new BigNumber('100000000000000000000000000'); - expect(balance).to.be.bignumber.equal(expectedBalance); - }); - it ('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { - const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; - const aOwnerAddress = userAddresses[0]; - expect(zeroEx.erc20.getBalanceAsync(nonExistentTokenAddress, aOwnerAddress)) - .to.be.rejectedWith(ZeroExError.CONTRACT_DOES_NOT_EXIST); - }); - it ('should return a balance of 0 for a non-existent owner address', async () => { - const aToken = tokens[0]; - const aNonExistentOwner = '0x198C6Ad858F213Fb31b6FE809E25040E6B964593'; - const balance = await zeroEx.erc20.getBalanceAsync(aToken.address, aNonExistentOwner); - const expectedBalance = new BigNumber('0'); - expect(balance).to.be.bignumber.equal(expectedBalance); - }); - }); -}); diff --git a/test/token_wrapper_test.ts b/test/token_wrapper_test.ts new file mode 100644 index 000000000..22fb6e052 --- /dev/null +++ b/test/token_wrapper_test.ts @@ -0,0 +1,55 @@ +import 'mocha'; +import * as chai from 'chai'; +import chaiAsPromised = require('chai-as-promised'); +import * as Web3 from 'web3'; +import * as BigNumber from 'bignumber.js'; +import promisify = require('es6-promisify'); +import {web3Factory} from './utils/web3_factory'; +import {ZeroEx} from '../src/0x.js'; +import {ZeroExError, Token} from '../src/types'; +import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; + +const expect = chai.expect; +chai.use(chaiAsPromised); +const blockchainLifecycle = new BlockchainLifecycle(); + +describe('TokenWrapper', () => { + let web3: Web3; + let zeroEx: ZeroEx; + let userAddresses: string[]; + let tokens: Token[]; + before(async () => { + web3 = web3Factory.create(); + zeroEx = new ZeroEx(web3); + userAddresses = await promisify(web3.eth.getAccounts)(); + tokens = await zeroEx.tokenRegistry.getTokensAsync(); + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + describe('#getBalanceAsync', () => { + it('should return the balance for an existing ERC20 token', async () => { + const aToken = tokens[0]; + const aOwnerAddress = userAddresses[0]; + const balance = await zeroEx.erc20.getBalanceAsync(aToken.address, aOwnerAddress); + const expectedBalance = new BigNumber('100000000000000000000000000'); + expect(balance).to.be.bignumber.equal(expectedBalance); + }); + it ('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { + const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; + const aOwnerAddress = userAddresses[0]; + expect(zeroEx.erc20.getBalanceAsync(nonExistentTokenAddress, aOwnerAddress)) + .to.be.rejectedWith(ZeroExError.CONTRACT_DOES_NOT_EXIST); + }); + it ('should return a balance of 0 for a non-existent owner address', async () => { + const aToken = tokens[0]; + const aNonExistentOwner = '0x198C6Ad858F213Fb31b6FE809E25040E6B964593'; + const balance = await zeroEx.erc20.getBalanceAsync(aToken.address, aNonExistentOwner); + const expectedBalance = new BigNumber('0'); + expect(balance).to.be.bignumber.equal(expectedBalance); + }); + }); +}); -- cgit v1.2.3