diff options
author | Leonid <logvinov.leon@gmail.com> | 2017-08-24 16:45:31 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-24 16:45:31 +0800 |
commit | 640825d18d197f6950f1eede0b43bb93be21a6ce (patch) | |
tree | da7ace561f495b033dc5f977a2bde7de6afdb827 | |
parent | e216f2ff6de9b2dd998c37c919b8786f7dff1101 (diff) | |
parent | 933242bd9d83ccbf92ce29aa2b4606336e64eed7 (diff) | |
download | dexon-sol-tools-640825d18d197f6950f1eede0b43bb93be21a6ce.tar dexon-sol-tools-640825d18d197f6950f1eede0b43bb93be21a6ce.tar.gz dexon-sol-tools-640825d18d197f6950f1eede0b43bb93be21a6ce.tar.bz2 dexon-sol-tools-640825d18d197f6950f1eede0b43bb93be21a6ce.tar.lz dexon-sol-tools-640825d18d197f6950f1eede0b43bb93be21a6ce.tar.xz dexon-sol-tools-640825d18d197f6950f1eede0b43bb93be21a6ce.tar.zst dexon-sol-tools-640825d18d197f6950f1eede0b43bb93be21a6ce.zip |
Merge pull request #132 from 0xProject/token-registry
Add public Token Registry getters
-rw-r--r-- | CHANGELOG.md | 7 | ||||
-rw-r--r-- | src/contract_wrappers/token_registry_wrapper.ts | 47 | ||||
-rw-r--r-- | src/types.ts | 12 | ||||
-rw-r--r-- | test/token_registry_wrapper_test.ts | 74 |
4 files changed, 135 insertions, 5 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index b5fef398c..d8f3b8e7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,17 @@ # CHANGELOG -v0.10.0 - _TBD_ +v0.10.0 - _Aug 24, 2017_ ------------------------ * Added `zeroEx.exchange.validateFillOrderThrowIfInvalidAsync` (#128) * Added `zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync` (#128) * Added `zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync` (#128) * Added `zeroEx.exchange.isRoundingErrorAsync` (#128) * Added `zeroEx.proxy.getContractAddressAsync` (#130) + * Added `zeroEx.tokenRegistry.getTokenAddressesAsync` (#132) + * Added `zeroEx.tokenRegistry.getTokenAddressBySymbolIfExistsAsync` (#132) + * Added `zeroEx.tokenRegistry.getTokenAddressByNameIfExistsAsync` (#132) + * Added `zeroEx.tokenRegistry.getTokenBySymbolIfExistsAsync` (#132) + * Added `zeroEx.tokenRegistry.getTokenByNameIfExistsAsync` (#132) * Added clear error message when checksummed address is passed to a public method (#124) * Fixes the description of `shouldThrowOnInsufficientBalanceOrAllowance` in docs (#127) diff --git a/src/contract_wrappers/token_registry_wrapper.ts b/src/contract_wrappers/token_registry_wrapper.ts index 58c191ea5..5fee1304e 100644 --- a/src/contract_wrappers/token_registry_wrapper.ts +++ b/src/contract_wrappers/token_registry_wrapper.ts @@ -21,7 +21,7 @@ export class TokenRegistryWrapper extends ContractWrapper { public async getTokensAsync(): Promise<Token[]> { const tokenRegistryContract = await this._getTokenRegistryContractAsync(); - const addresses = await tokenRegistryContract.getTokenAddresses.call(); + const addresses = await this.getTokenAddressesAsync(); const tokenPromises: Array<Promise<Token|undefined>> = _.map( addresses, (address: string) => (this.getTokenIfExistsAsync(address)), @@ -30,6 +30,15 @@ export class TokenRegistryWrapper extends ContractWrapper { return tokens as Token[]; } /** + * Retrieves all the addresses of the tokens currently listed in the Token Registry smart contract + * @return An array of token addresses. + */ + public async getTokenAddressesAsync(): Promise<string[]> { + const tokenRegistryContract = await this._getTokenRegistryContractAsync(); + const addresses = await tokenRegistryContract.getTokenAddresses.call(); + return addresses; + } + /** * Retrieves a token by address currently listed in the Token Registry smart contract * @return An object that conforms to the Token interface or undefined if token not found. */ @@ -38,6 +47,42 @@ export class TokenRegistryWrapper extends ContractWrapper { const tokenRegistryContract = await this._getTokenRegistryContractAsync(); const metadata = await tokenRegistryContract.getTokenMetaData.call(address); + const token = this._createTokenFromMetadata(metadata); + return token; + } + public async getTokenAddressBySymbolIfExistsAsync(symbol: string): Promise<string|undefined> { + assert.isString('symbol', symbol); + const tokenRegistryContract = await this._getTokenRegistryContractAsync(); + const addressIfExists = await tokenRegistryContract.getTokenAddressBySymbol.call(symbol); + if (addressIfExists === constants.NULL_ADDRESS) { + return undefined; + } + return addressIfExists; + } + public async getTokenAddressByNameIfExistsAsync(name: string): Promise<string|undefined> { + assert.isString('name', name); + const tokenRegistryContract = await this._getTokenRegistryContractAsync(); + const addressIfExists = await tokenRegistryContract.getTokenAddressByName.call(name); + if (addressIfExists === constants.NULL_ADDRESS) { + return undefined; + } + return addressIfExists; + } + public async getTokenBySymbolIfExistsAsync(symbol: string): Promise<Token|undefined> { + assert.isString('symbol', symbol); + const tokenRegistryContract = await this._getTokenRegistryContractAsync(); + const metadata = await tokenRegistryContract.getTokenBySymbol.call(symbol); + const token = this._createTokenFromMetadata(metadata); + return token; + } + public async getTokenByNameIfExistsAsync(name: string): Promise<Token|undefined> { + assert.isString('name', name); + const tokenRegistryContract = await this._getTokenRegistryContractAsync(); + const metadata = await tokenRegistryContract.getTokenByName.call(name); + const token = this._createTokenFromMetadata(metadata); + return token; + } + private _createTokenFromMetadata(metadata: TokenMetadata): Token|undefined { if (metadata[0] === constants.NULL_ADDRESS) { return undefined; } diff --git a/src/types.ts b/src/types.ts index 5ba85a7d5..71227647b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -145,6 +145,18 @@ export interface TokenRegistryContract extends ContractInstance { getTokenAddresses: { call: () => Promise<string[]>; }; + getTokenAddressBySymbol: { + call: (symbol: string) => Promise<string>; + }; + getTokenAddressByName: { + call: (name: string) => Promise<string>; + }; + getTokenBySymbol: { + call: (symbol: string) => Promise<TokenMetadata>; + }; + getTokenByName: { + call: (name: string) => Promise<TokenMetadata>; + }; } export interface EtherTokenContract extends ContractInstance { diff --git a/test/token_registry_wrapper_test.ts b/test/token_registry_wrapper_test.ts index 6b5640c6c..e1702cd45 100644 --- a/test/token_registry_wrapper_test.ts +++ b/test/token_registry_wrapper_test.ts @@ -3,10 +3,11 @@ import 'mocha'; import * as chai from 'chai'; import {chaiSetup} from './utils/chai_setup'; import {web3Factory} from './utils/web3_factory'; -import {ZeroEx} from '../src'; +import {ZeroEx, Token} from '../src'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; import {SchemaValidator} from '../src/utils/schema_validator'; import {tokenSchema} from '../src/schemas/token_schema'; +import {addressSchema} from '../src/schemas/basic_type_schemas'; chaiSetup.configure(); const expect = chai.expect; @@ -16,9 +17,25 @@ const TOKEN_REGISTRY_SIZE_AFTER_MIGRATION = 7; describe('TokenRegistryWrapper', () => { let zeroEx: ZeroEx; + let tokens: Token[]; + const tokenAddressBySymbol: {[symbol: string]: string} = {}; + const tokenAddressByName: {[symbol: string]: string} = {}; + const tokenBySymbol: {[symbol: string]: Token} = {}; + const tokenByName: {[symbol: string]: Token} = {}; + const registeredSymbol = 'ZRX'; + const registeredName = '0x Protocol Token'; + const unregisteredSymbol = 'MAL'; + const unregisteredName = 'Malicious Token'; before(async () => { const web3 = web3Factory.create(); zeroEx = new ZeroEx(web3.currentProvider); + tokens = await zeroEx.tokenRegistry.getTokensAsync(); + _.map(tokens, token => { + tokenAddressBySymbol[token.symbol] = token.address; + tokenAddressByName[token.name] = token.address; + tokenBySymbol[token.symbol] = token; + tokenByName[token.name] = token; + }); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -28,7 +45,6 @@ describe('TokenRegistryWrapper', () => { }); describe('#getTokensAsync', () => { it('should return all the tokens added to the tokenRegistry during the migration', async () => { - const tokens = await zeroEx.tokenRegistry.getTokensAsync(); expect(tokens).to.have.lengthOf(TOKEN_REGISTRY_SIZE_AFTER_MIGRATION); const schemaValidator = new SchemaValidator(); @@ -38,9 +54,61 @@ describe('TokenRegistryWrapper', () => { }); }); }); + describe('#getTokenAddressesAsync', () => { + it('should return all the token addresses added to the tokenRegistry during the migration', async () => { + const tokenAddresses = await zeroEx.tokenRegistry.getTokenAddressesAsync(); + expect(tokenAddresses).to.have.lengthOf(TOKEN_REGISTRY_SIZE_AFTER_MIGRATION); + + const schemaValidator = new SchemaValidator(); + _.each(tokenAddresses, tokenAddress => { + const validationResult = schemaValidator.validate(tokenAddress, addressSchema); + expect(validationResult.errors).to.have.lengthOf(0); + expect(tokenAddress).to.not.be.equal(ZeroEx.NULL_ADDRESS); + }); + }); + }); + describe('#getTokenAddressBySymbol', () => { + it('should return correct address for a token in the registry', async () => { + const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressBySymbolIfExistsAsync(registeredSymbol); + expect(tokenAddress).to.be.equal(tokenAddressBySymbol[registeredSymbol]); + }); + it('should return undefined for a token out of registry', async () => { + const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressBySymbolIfExistsAsync(unregisteredSymbol); + expect(tokenAddress).to.be.undefined(); + }); + }); + describe('#getTokenAddressByName', () => { + it('should return correct address for a token in the registry', async () => { + const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressByNameIfExistsAsync(registeredName); + expect(tokenAddress).to.be.equal(tokenAddressByName[registeredName]); + }); + it('should return undefined for a token out of registry', async () => { + const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressByNameIfExistsAsync(unregisteredName); + expect(tokenAddress).to.be.undefined(); + }); + }); + describe('#getTokenBySymbol', () => { + it('should return correct token for a token in the registry', async () => { + const token = await zeroEx.tokenRegistry.getTokenBySymbolIfExistsAsync(registeredSymbol); + expect(token).to.be.deep.equal(tokenBySymbol[registeredSymbol]); + }); + it('should return undefined for a token out of registry', async () => { + const token = await zeroEx.tokenRegistry.getTokenBySymbolIfExistsAsync(unregisteredSymbol); + expect(token).to.be.undefined(); + }); + }); + describe('#getTokenByName', () => { + it('should return correct token for a token in the registry', async () => { + const token = await zeroEx.tokenRegistry.getTokenByNameIfExistsAsync(registeredName); + expect(token).to.be.deep.equal(tokenByName[registeredName]); + }); + it('should return undefined for a token out of registry', async () => { + const token = await zeroEx.tokenRegistry.getTokenByNameIfExistsAsync(unregisteredName); + expect(token).to.be.undefined(); + }); + }); describe('#getTokenIfExistsAsync', () => { it('should return the token added to the tokenRegistry during the migration', async () => { - const tokens = await zeroEx.tokenRegistry.getTokensAsync(); const aToken = tokens[0]; const token = await zeroEx.tokenRegistry.getTokenIfExistsAsync(aToken.address); |