aboutsummaryrefslogtreecommitdiffstats
path: root/src/contract_wrappers/token_wrapper.ts
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2017-11-13 11:17:18 +0800
committerFabio Berger <me@fabioberger.com>2017-11-13 11:17:18 +0800
commitc4ee2d73865a1444c079b9e2836b7630a0adf03e (patch)
treeb9c7794e7022fb189675d914f5fe58dcabd67dec /src/contract_wrappers/token_wrapper.ts
parenta74ec0effa818a86233fe64cb0dad2c61bbb4bb6 (diff)
downloaddexon-sol-tools-c4ee2d73865a1444c079b9e2836b7630a0adf03e.tar
dexon-sol-tools-c4ee2d73865a1444c079b9e2836b7630a0adf03e.tar.gz
dexon-sol-tools-c4ee2d73865a1444c079b9e2836b7630a0adf03e.tar.bz2
dexon-sol-tools-c4ee2d73865a1444c079b9e2836b7630a0adf03e.tar.lz
dexon-sol-tools-c4ee2d73865a1444c079b9e2836b7630a0adf03e.tar.xz
dexon-sol-tools-c4ee2d73865a1444c079b9e2836b7630a0adf03e.tar.zst
dexon-sol-tools-c4ee2d73865a1444c079b9e2836b7630a0adf03e.zip
Switch over to Lerna + Yarn Workspaces setup for a mono-repo approach
Diffstat (limited to 'src/contract_wrappers/token_wrapper.ts')
-rw-r--r--src/contract_wrappers/token_wrapper.ts313
1 files changed, 0 insertions, 313 deletions
diff --git a/src/contract_wrappers/token_wrapper.ts b/src/contract_wrappers/token_wrapper.ts
deleted file mode 100644
index 614ac19d4..000000000
--- a/src/contract_wrappers/token_wrapper.ts
+++ /dev/null
@@ -1,313 +0,0 @@
-import * as _ from 'lodash';
-import BigNumber from 'bignumber.js';
-import {schemas} from '0x-json-schemas';
-import {Web3Wrapper} from '../web3_wrapper';
-import {assert} from '../utils/assert';
-import {constants} from '../utils/constants';
-import {ContractWrapper} from './contract_wrapper';
-import {AbiDecoder} from '../utils/abi_decoder';
-import {artifacts} from '../artifacts';
-import {
- TokenContract,
- ZeroExError,
- TokenEvents,
- IndexedFilterValues,
- SubscriptionOpts,
- MethodOpts,
- LogWithDecodedArgs,
- EventCallback,
- TokenContractEventArgs,
-} from '../types';
-
-const ALLOWANCE_TO_ZERO_GAS_AMOUNT = 47275;
-
-/**
- * This class includes all the functionality related to interacting with ERC20 token contracts.
- * All ERC20 method calls are supported, along with some convenience methods for getting/setting allowances
- * to the 0x Proxy smart contract.
- */
-export class TokenWrapper extends ContractWrapper {
- public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
- private _tokenContractsByAddress: {[address: string]: TokenContract};
- private _tokenTransferProxyContractAddressFetcher: () => Promise<string>;
- constructor(web3Wrapper: Web3Wrapper, abiDecoder: AbiDecoder,
- tokenTransferProxyContractAddressFetcher: () => Promise<string>) {
- super(web3Wrapper, abiDecoder);
- this._tokenContractsByAddress = {};
- this._tokenTransferProxyContractAddressFetcher = tokenTransferProxyContractAddressFetcher;
- }
- /**
- * Retrieves an owner's ERC20 token balance.
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param ownerAddress The hex encoded user Ethereum address whose balance you would like to check.
- * @param methodOpts Optional arguments this method accepts.
- * @return The owner's ERC20 token balance in base units.
- */
- public async getBalanceAsync(tokenAddress: string, ownerAddress: string,
- methodOpts?: MethodOpts): Promise<BigNumber> {
- assert.isETHAddressHex('ownerAddress', ownerAddress);
- assert.isETHAddressHex('tokenAddress', tokenAddress);
-
- const tokenContract = await this._getTokenContractAsync(tokenAddress);
- const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
- let balance = await tokenContract.balanceOf.callAsync(ownerAddress, defaultBlock);
- // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
- balance = new BigNumber(balance);
- return balance;
- }
- /**
- * Sets the spender's allowance to a specified number of baseUnits on behalf of the owner address.
- * Equivalent to the ERC20 spec method `approve`.
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param ownerAddress The hex encoded user Ethereum address who would like to set an allowance
- * for spenderAddress.
- * @param spenderAddress The hex encoded user Ethereum address who will be able to spend the set allowance.
- * @param amountInBaseUnits The allowance amount you would like to set.
- * @return Transaction hash.
- */
- public async setAllowanceAsync(tokenAddress: string, ownerAddress: string, spenderAddress: string,
- amountInBaseUnits: BigNumber): Promise<string> {
- await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper);
- assert.isETHAddressHex('spenderAddress', spenderAddress);
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
-
- const tokenContract = await this._getTokenContractAsync(tokenAddress);
- // Hack: for some reason default estimated gas amount causes `base fee exceeds gas limit` exception
- // on testrpc. Probably related to https://github.com/ethereumjs/testrpc/issues/294
- // TODO: Debug issue in testrpc and submit a PR, then remove this hack
- const networkIdIfExists = await this._web3Wrapper.getNetworkIdIfExistsAsync();
- const gas = networkIdIfExists === constants.TESTRPC_NETWORK_ID ? ALLOWANCE_TO_ZERO_GAS_AMOUNT : undefined;
- const txHash = await tokenContract.approve.sendTransactionAsync(spenderAddress, amountInBaseUnits, {
- from: ownerAddress,
- gas,
- });
- return txHash;
- }
- /**
- * Sets the spender's allowance to an unlimited number of baseUnits on behalf of the owner address.
- * Equivalent to the ERC20 spec method `approve`.
- * Setting an unlimited allowance will lower the gas cost for filling orders involving tokens that forego updating
- * allowances set to the max amount (e.g ZRX, WETH)
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param ownerAddress The hex encoded user Ethereum address who would like to set an allowance
- * for spenderAddress.
- * @param spenderAddress The hex encoded user Ethereum address who will be able to spend the set allowance.
- * @return Transaction hash.
- */
- public async setUnlimitedAllowanceAsync(tokenAddress: string, ownerAddress: string,
- spenderAddress: string): Promise<string> {
- const txHash = await this.setAllowanceAsync(
- tokenAddress, ownerAddress, spenderAddress, this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
- );
- return txHash;
- }
- /**
- * Retrieves the owners allowance in baseUnits set to the spender's address.
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param ownerAddress The hex encoded user Ethereum address whose allowance to spenderAddress
- * you would like to retrieve.
- * @param spenderAddress The hex encoded user Ethereum address who can spend the allowance you are fetching.
- * @param methodOpts Optional arguments this method accepts.
- */
- public async getAllowanceAsync(tokenAddress: string, ownerAddress: string,
- spenderAddress: string, methodOpts?: MethodOpts): Promise<BigNumber> {
- assert.isETHAddressHex('ownerAddress', ownerAddress);
- assert.isETHAddressHex('tokenAddress', tokenAddress);
-
- const tokenContract = await this._getTokenContractAsync(tokenAddress);
- const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
- let allowanceInBaseUnits = await tokenContract.allowance.callAsync(ownerAddress, spenderAddress, defaultBlock);
- // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
- allowanceInBaseUnits = new BigNumber(allowanceInBaseUnits);
- return allowanceInBaseUnits;
- }
- /**
- * Retrieves the owner's allowance in baseUnits set to the 0x proxy contract.
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param ownerAddress The hex encoded user Ethereum address whose proxy contract allowance we are retrieving.
- * @param methodOpts Optional arguments this method accepts.
- */
- public async getProxyAllowanceAsync(tokenAddress: string, ownerAddress: string,
- methodOpts?: MethodOpts): Promise<BigNumber> {
- assert.isETHAddressHex('ownerAddress', ownerAddress);
- assert.isETHAddressHex('tokenAddress', tokenAddress);
-
- const proxyAddress = await this._getTokenTransferProxyAddressAsync();
- const allowanceInBaseUnits = await this.getAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, methodOpts);
- return allowanceInBaseUnits;
- }
- /**
- * Sets the 0x proxy contract's allowance to a specified number of a tokens' baseUnits on behalf
- * of an owner address.
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param ownerAddress The hex encoded user Ethereum address who is setting an allowance
- * for the Proxy contract.
- * @param amountInBaseUnits The allowance amount specified in baseUnits.
- * @return Transaction hash.
- */
- public async setProxyAllowanceAsync(tokenAddress: string, ownerAddress: string,
- amountInBaseUnits: BigNumber): Promise<string> {
- assert.isETHAddressHex('ownerAddress', ownerAddress);
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
-
- const proxyAddress = await this._getTokenTransferProxyAddressAsync();
- const txHash = await this.setAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, amountInBaseUnits);
- return txHash;
- }
- /**
- * Sets the 0x proxy contract's allowance to a unlimited number of a tokens' baseUnits on behalf
- * of an owner address.
- * Setting an unlimited allowance will lower the gas cost for filling orders involving tokens that forego updating
- * allowances set to the max amount (e.g ZRX, WETH)
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param ownerAddress The hex encoded user Ethereum address who is setting an allowance
- * for the Proxy contract.
- * @return Transaction hash.
- */
- public async setUnlimitedProxyAllowanceAsync(tokenAddress: string, ownerAddress: string): Promise<string> {
- const txHash = await this.setProxyAllowanceAsync(
- tokenAddress, ownerAddress, this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
- );
- return txHash;
- }
- /**
- * Transfers `amountInBaseUnits` ERC20 tokens from `fromAddress` to `toAddress`.
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param fromAddress The hex encoded user Ethereum address that will send the funds.
- * @param toAddress The hex encoded user Ethereum address that will receive the funds.
- * @param amountInBaseUnits The amount (specified in baseUnits) of the token to transfer.
- * @return Transaction hash.
- */
- public async transferAsync(tokenAddress: string, fromAddress: string, toAddress: string,
- amountInBaseUnits: BigNumber): Promise<string> {
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper);
- assert.isETHAddressHex('toAddress', toAddress);
- assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
-
- const tokenContract = await this._getTokenContractAsync(tokenAddress);
-
- const fromAddressBalance = await this.getBalanceAsync(tokenAddress, fromAddress);
- if (fromAddressBalance.lessThan(amountInBaseUnits)) {
- throw new Error(ZeroExError.InsufficientBalanceForTransfer);
- }
-
- const txHash = await tokenContract.transfer.sendTransactionAsync(toAddress, amountInBaseUnits, {
- from: fromAddress,
- });
- return txHash;
- }
- /**
- * Transfers `amountInBaseUnits` ERC20 tokens from `fromAddress` to `toAddress`.
- * Requires the fromAddress to have sufficient funds and to have approved an allowance of
- * `amountInBaseUnits` to `senderAddress`.
- * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed.
- * @param fromAddress The hex encoded user Ethereum address whose funds are being sent.
- * @param toAddress The hex encoded user Ethereum address that will receive the funds.
- * @param senderAddress The hex encoded user Ethereum address whose initiates the fund transfer. The
- * `fromAddress` must have set an allowance to the `senderAddress`
- * before this call.
- * @param amountInBaseUnits The amount (specified in baseUnits) of the token to transfer.
- * @return Transaction hash.
- */
- public async transferFromAsync(tokenAddress: string, fromAddress: string, toAddress: string,
- senderAddress: string, amountInBaseUnits: BigNumber):
- Promise<string> {
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- assert.isETHAddressHex('fromAddress', fromAddress);
- assert.isETHAddressHex('toAddress', toAddress);
- await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper);
- assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
-
- const tokenContract = await this._getTokenContractAsync(tokenAddress);
-
- const fromAddressAllowance = await this.getAllowanceAsync(tokenAddress, fromAddress, senderAddress);
- if (fromAddressAllowance.lessThan(amountInBaseUnits)) {
- throw new Error(ZeroExError.InsufficientAllowanceForTransfer);
- }
-
- const fromAddressBalance = await this.getBalanceAsync(tokenAddress, fromAddress);
- if (fromAddressBalance.lessThan(amountInBaseUnits)) {
- throw new Error(ZeroExError.InsufficientBalanceForTransfer);
- }
-
- const txHash = await tokenContract.transferFrom.sendTransactionAsync(
- fromAddress, toAddress, amountInBaseUnits,
- {
- from: senderAddress,
- },
- );
- return txHash;
- }
- /**
- * Subscribe to an event type emitted by the Token contract.
- * @param tokenAddress The hex encoded address where the ERC20 token is deployed.
- * @param eventName The token contract event you would like to subscribe to.
- * @param indexFilterValues An object where the keys are indexed args returned by the event and
- * the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
- * @param callback Callback that gets called when a log is added/removed
- * @return Subscription token used later to unsubscribe
- */
- public subscribe<ArgsType extends TokenContractEventArgs>(
- tokenAddress: string, eventName: TokenEvents, indexFilterValues: IndexedFilterValues,
- callback: EventCallback<ArgsType>): string {
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
- assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
- assert.isFunction('callback', callback);
- const subscriptionToken = this._subscribe<ArgsType>(
- tokenAddress, eventName, indexFilterValues, artifacts.TokenArtifact.abi, callback,
- );
- return subscriptionToken;
- }
- /**
- * Cancel a subscription
- * @param subscriptionToken Subscription token returned by `subscribe()`
- */
- public unsubscribe(subscriptionToken: string): void {
- this._unsubscribe(subscriptionToken);
- }
- /**
- * Gets historical logs without creating a subscription
- * @param tokenAddress An address of the token that emmited the logs.
- * @param eventName The token contract event you would like to subscribe to.
- * @param subscriptionOpts Subscriptions options that let you configure the subscription.
- * @param indexFilterValues An object where the keys are indexed args returned by the event and
- * the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
- * @return Array of logs that match the parameters
- */
- public async getLogsAsync<ArgsType extends TokenContractEventArgs>(
- tokenAddress: string, eventName: TokenEvents, subscriptionOpts: SubscriptionOpts,
- indexFilterValues: IndexedFilterValues): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
- assert.isETHAddressHex('tokenAddress', tokenAddress);
- assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
- assert.doesConformToSchema('subscriptionOpts', subscriptionOpts, schemas.subscriptionOptsSchema);
- assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
- const logs = await this._getLogsAsync<ArgsType>(
- tokenAddress, eventName, subscriptionOpts, indexFilterValues, artifacts.TokenArtifact.abi,
- );
- return logs;
- }
- private _invalidateContractInstancesAsync(): void {
- this.unsubscribeAll();
- this._tokenContractsByAddress = {};
- }
- private async _getTokenContractAsync(tokenAddress: string): Promise<TokenContract> {
- let tokenContract = this._tokenContractsByAddress[tokenAddress];
- if (!_.isUndefined(tokenContract)) {
- return tokenContract;
- }
- const contractInstance = await this._instantiateContractIfExistsAsync<TokenContract>(
- artifacts.TokenArtifact, tokenAddress,
- );
- tokenContract = contractInstance as TokenContract;
- this._tokenContractsByAddress[tokenAddress] = tokenContract;
- return tokenContract;
- }
- private async _getTokenTransferProxyAddressAsync(): Promise<string> {
- const tokenTransferProxyContractAddress = await this._tokenTransferProxyContractAddressFetcher();
- return tokenTransferProxyContractAddress;
- }
-}