aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/0x.ts76
-rw-r--r--src/artifacts.ts13
-rw-r--r--src/artifacts/EtherToken.json2
-rw-r--r--src/contract.ts80
-rw-r--r--src/contract_wrappers/contract_wrapper.ts51
-rw-r--r--src/contract_wrappers/ether_token_wrapper.ts22
-rw-r--r--src/contract_wrappers/exchange_wrapper.ts127
-rw-r--r--src/contract_wrappers/token_registry_wrapper.ts22
-rw-r--r--src/contract_wrappers/token_transfer_proxy_wrapper.ts10
-rw-r--r--src/contract_wrappers/token_wrapper.ts67
-rw-r--r--src/globals.d.ts35
-rw-r--r--src/index.ts3
-rw-r--r--src/types.ts203
-rw-r--r--src/web3_wrapper.ts39
14 files changed, 469 insertions, 281 deletions
diff --git a/src/0x.ts b/src/0x.ts
index ba222f2c9..0af164b1e 100644
--- a/src/0x.ts
+++ b/src/0x.ts
@@ -1,9 +1,10 @@
import * as _ from 'lodash';
import * as BigNumber from 'bignumber.js';
+import * as Web3 from 'web3';
+import * as abiDecoder from 'abi-decoder';
import {SchemaValidator, schemas} from '0x-json-schemas';
import {bigNumberConfigs} from './bignumber_config';
import * as ethUtil from 'ethereumjs-util';
-import contract = require('truffle-contract');
import findVersions = require('find-versions');
import compareVersions = require('compare-versions');
import {Web3Wrapper} from './web3_wrapper';
@@ -11,12 +12,24 @@ import {constants} from './utils/constants';
import {utils} from './utils/utils';
import {signatureUtils} from './utils/signature_utils';
import {assert} from './utils/assert';
+import {artifacts} from './artifacts';
import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper';
import {TokenRegistryWrapper} from './contract_wrappers/token_registry_wrapper';
import {EtherTokenWrapper} from './contract_wrappers/ether_token_wrapper';
import {TokenWrapper} from './contract_wrappers/token_wrapper';
import {TokenTransferProxyWrapper} from './contract_wrappers/token_transfer_proxy_wrapper';
-import {ECSignature, ZeroExError, Order, SignedOrder, Web3Provider, ZeroExConfig} from './types';
+import {
+ ECSignature,
+ ZeroExError,
+ Order,
+ SignedOrder,
+ Web3Provider,
+ ZeroExConfig,
+ TransactionReceipt,
+ DecodedLogArgs,
+ TransactionReceiptWithDecodedLogs,
+ LogWithDecodedArgs,
+} from './types';
// Customize our BigNumber instances
bigNumberConfigs.configure();
@@ -170,13 +183,17 @@ export class ZeroEx {
// We re-assign the send method so that Web3@1.0 providers work with 0x.js
(provider as any).sendAsync = (provider as any).send;
}
- this._web3Wrapper = new Web3Wrapper(provider);
+ this._registerArtifactsWithinABIDecoder();
const gasPrice = _.isUndefined(config) ? undefined : config.gasPrice;
- this.token = new TokenWrapper(this._web3Wrapper, gasPrice);
- this.proxy = new TokenTransferProxyWrapper(this._web3Wrapper, gasPrice);
- this.exchange = new ExchangeWrapper(this._web3Wrapper, this.token, gasPrice);
- this.tokenRegistry = new TokenRegistryWrapper(this._web3Wrapper, gasPrice);
- this.etherToken = new EtherTokenWrapper(this._web3Wrapper, this.token, gasPrice);
+ const defaults = {
+ gasPrice,
+ };
+ this._web3Wrapper = new Web3Wrapper(provider, defaults);
+ this.token = new TokenWrapper(this._web3Wrapper);
+ this.proxy = new TokenTransferProxyWrapper(this._web3Wrapper);
+ this.exchange = new ExchangeWrapper(this._web3Wrapper, this.token);
+ this.tokenRegistry = new TokenRegistryWrapper(this._web3Wrapper);
+ this.etherToken = new EtherTokenWrapper(this._web3Wrapper, this.token);
}
/**
* Sets a new web3 provider for 0x.js. Updating the provider will stop all
@@ -249,4 +266,47 @@ export class ZeroEx {
throw new Error(ZeroExError.InvalidSignature);
}
+ /**
+ * Waits for a transaction to be mined and returns the transaction receipt.
+ * @param txHash Transaction hash
+ * @param pollingIntervalMs How often (in ms) should we check if the transaction is mined.
+ * @return Transaction receipt with decoded log args.
+ */
+ public async awaitTransactionMinedAsync(
+ txHash: string, pollingIntervalMs: number = 1000): Promise<TransactionReceiptWithDecodedLogs> {
+ const txReceiptPromise = new Promise(
+ (resolve: (receipt: TransactionReceiptWithDecodedLogs) => void, reject) => {
+ const intervalId = setInterval(async () => {
+ const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash);
+ if (!_.isNull(transactionReceipt)) {
+ clearInterval(intervalId);
+ const logsWithDecodedArgs = _.map(transactionReceipt.logs, (log: Web3.LogEntry) => {
+ const decodedLog = abiDecoder.decodeLogs([log])[0];
+ const decodedArgs = decodedLog.events;
+ const args: DecodedLogArgs = {};
+ _.forEach(decodedArgs, arg => {
+ args[arg.name] = arg.value;
+ });
+ const logWithDecodedArgs: LogWithDecodedArgs = {
+ ...log,
+ args,
+ event: decodedLog.name,
+ };
+ return logWithDecodedArgs;
+ });
+ const transactionReceiptWithDecodedLogArgs: TransactionReceiptWithDecodedLogs = {
+ ...transactionReceipt,
+ logs: logsWithDecodedArgs,
+ };
+ resolve(transactionReceiptWithDecodedLogArgs);
+ }
+ }, pollingIntervalMs);
+ });
+ return txReceiptPromise;
+ }
+ private _registerArtifactsWithinABIDecoder(): void {
+ for (const artifact of _.values(artifacts)) {
+ abiDecoder.addABI(artifact.abi);
+ }
+ }
}
diff --git a/src/artifacts.ts b/src/artifacts.ts
new file mode 100644
index 000000000..0c4627337
--- /dev/null
+++ b/src/artifacts.ts
@@ -0,0 +1,13 @@
+import * as TokenArtifact from './artifacts/Token.json';
+import * as ExchangeArtifact from './artifacts/Exchange.json';
+import * as EtherTokenArtifact from './artifacts/EtherToken.json';
+import * as TokenRegistryArtifact from './artifacts/TokenRegistry.json';
+import * as TokenTransferProxyArtifact from './artifacts/TokenTransferProxy.json';
+
+export const artifacts = {
+ TokenArtifact: TokenArtifact as any as Artifact,
+ ExchangeArtifact: ExchangeArtifact as any as Artifact,
+ EtherTokenArtifact: EtherTokenArtifact as any as Artifact,
+ TokenRegistryArtifact: TokenRegistryArtifact as any as Artifact,
+ TokenTransferProxyArtifact: TokenTransferProxyArtifact as any as Artifact,
+};
diff --git a/src/artifacts/EtherToken.json b/src/artifacts/EtherToken.json
index eca348530..54b5a032e 100644
--- a/src/artifacts/EtherToken.json
+++ b/src/artifacts/EtherToken.json
@@ -391,4 +391,4 @@
},
"schema_version": "0.0.5",
"updated_at": 1503318938233
-} \ No newline at end of file
+}
diff --git a/src/contract.ts b/src/contract.ts
new file mode 100644
index 000000000..1aacc65dc
--- /dev/null
+++ b/src/contract.ts
@@ -0,0 +1,80 @@
+import * as Web3 from 'web3';
+import * as _ from 'lodash';
+import promisify = require('es6-promisify');
+import {SchemaValidator, schemas} from '0x-json-schemas';
+import {AbiType} from './types';
+
+export class Contract implements Web3.ContractInstance {
+ public address: string;
+ public abi: Web3.ContractAbi;
+ private contract: Web3.ContractInstance;
+ private defaults: Partial<Web3.TxData>;
+ private validator: SchemaValidator;
+ // This class instance is going to be populated with functions and events depending on the ABI
+ // and we don't know their types in advance
+ [name: string]: any;
+ constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<Web3.TxData>) {
+ this.contract = web3ContractInstance;
+ this.address = web3ContractInstance.address;
+ this.abi = web3ContractInstance.abi;
+ this.defaults = defaults;
+ this.populateEvents();
+ this.populateFunctions();
+ this.validator = new SchemaValidator();
+ }
+ private populateFunctions(): void {
+ const functionsAbi = _.filter(this.abi, abiPart => abiPart.type === AbiType.Function);
+ _.forEach(functionsAbi, (functionAbi: Web3.MethodAbi) => {
+ if (functionAbi.constant) {
+ const cbStyleCallFunction = this.contract[functionAbi.name].call;
+ this[functionAbi.name] = {
+ callAsync: promisify(cbStyleCallFunction, this.contract),
+ };
+ } else {
+ const cbStyleFunction = this.contract[functionAbi.name];
+ const cbStyleEstimateGasFunction = this.contract[functionAbi.name].estimateGas;
+ this[functionAbi.name] = {
+ estimateGasAsync: promisify(cbStyleEstimateGasFunction, this.contract),
+ sendTransactionAsync: this.promisifyWithDefaultParams(cbStyleFunction),
+ };
+ }
+ });
+ }
+ private populateEvents(): void {
+ const eventsAbi = _.filter(this.abi, abiPart => abiPart.type === AbiType.Event);
+ _.forEach(eventsAbi, (eventAbi: Web3.EventAbi) => {
+ this[eventAbi.name] = this.contract[eventAbi.name];
+ });
+ }
+ private promisifyWithDefaultParams(fn: (...args: any[]) => void): (...args: any[]) => Promise<any> {
+ const promisifiedWithDefaultParams = (...args: any[]) => {
+ const promise = new Promise((resolve, reject) => {
+ const lastArg = args[args.length - 1];
+ let txData: Partial<Web3.TxData> = {};
+ if (this.isTxData(lastArg)) {
+ txData = args.pop();
+ }
+ txData = {
+ ...this.defaults,
+ ...txData,
+ };
+ const callback = (err: Error, data: any) => {
+ if (_.isNull(err)) {
+ resolve(data);
+ } else {
+ reject(err);
+ }
+ };
+ args.push(txData);
+ args.push(callback);
+ fn.apply(this.contract, args);
+ });
+ return promise;
+ };
+ return promisifiedWithDefaultParams;
+ }
+ private isTxData(lastArg: any): boolean {
+ const isValid = this.validator.isValid(lastArg, schemas.txDataSchema);
+ return isValid;
+ }
+}
diff --git a/src/contract_wrappers/contract_wrapper.ts b/src/contract_wrappers/contract_wrapper.ts
index 28df82cee..ca19342f3 100644
--- a/src/contract_wrappers/contract_wrapper.ts
+++ b/src/contract_wrappers/contract_wrapper.ts
@@ -1,53 +1,18 @@
import * as _ from 'lodash';
-import contract = require('truffle-contract');
+import * as Web3 from 'web3';
import {Web3Wrapper} from '../web3_wrapper';
-import {ZeroExError, Artifact, ContractInstance} from '../types';
+import {ZeroExError} from '../types';
import {utils} from '../utils/utils';
export class ContractWrapper {
protected _web3Wrapper: Web3Wrapper;
- private _gasPrice?: BigNumber.BigNumber;
- constructor(web3Wrapper: Web3Wrapper, gasPrice?: BigNumber.BigNumber) {
+ constructor(web3Wrapper: Web3Wrapper) {
this._web3Wrapper = web3Wrapper;
- this._gasPrice = gasPrice;
}
- protected async _instantiateContractIfExistsAsync(artifact: Artifact, address?: string): Promise<ContractInstance> {
- const c = await contract(artifact);
- c.defaults({
- gasPrice: this._gasPrice,
- });
- const providerObj = this._web3Wrapper.getCurrentProvider();
- c.setProvider(providerObj);
-
- const networkIdIfExists = await this._web3Wrapper.getNetworkIdIfExistsAsync();
- const artifactNetworkConfigs = _.isUndefined(networkIdIfExists) ?
- undefined :
- artifact.networks[networkIdIfExists];
- let contractAddress;
- if (!_.isUndefined(address)) {
- contractAddress = address;
- } else if (!_.isUndefined(artifactNetworkConfigs)) {
- contractAddress = artifactNetworkConfigs.address.toLowerCase();
- }
-
- if (!_.isUndefined(contractAddress)) {
- const doesContractExist = await this._web3Wrapper.doesContractExistAtAddressAsync(contractAddress);
- if (!doesContractExist) {
- throw new Error(ZeroExError.ContractDoesNotExist);
- }
- }
-
- try {
- const contractInstance = _.isUndefined(address) ? await c.deployed() : await c.at(address);
- return contractInstance;
- } catch (err) {
- const errMsg = `${err}`;
- if (_.includes(errMsg, 'not been deployed to detected network')) {
- throw new Error(ZeroExError.ContractDoesNotExist);
- } else {
- utils.consoleLog(`Notice: Error encountered: ${err} ${err.stack}`);
- throw new Error(ZeroExError.UnhandledError);
- }
- }
+ protected async _instantiateContractIfExistsAsync<A extends Web3.ContractInstance>(artifact: Artifact,
+ address?: string): Promise<A> {
+ const contractInstance =
+ await this._web3Wrapper.getContractInstanceFromArtifactAsync<A>(artifact, address);
+ return contractInstance;
}
}
diff --git a/src/contract_wrappers/ether_token_wrapper.ts b/src/contract_wrappers/ether_token_wrapper.ts
index 3c282510f..b86309f90 100644
--- a/src/contract_wrappers/ether_token_wrapper.ts
+++ b/src/contract_wrappers/ether_token_wrapper.ts
@@ -4,7 +4,7 @@ import {ContractWrapper} from './contract_wrapper';
import {TokenWrapper} from './token_wrapper';
import {EtherTokenContract, ZeroExError} from '../types';
import {assert} from '../utils/assert';
-import * as EtherTokenArtifacts from '../artifacts/EtherToken.json';
+import {artifacts} from '../artifacts';
/**
* This class includes all the functionality related to interacting with a wrapped Ether ERC20 token contract.
@@ -13,8 +13,8 @@ import * as EtherTokenArtifacts from '../artifacts/EtherToken.json';
export class EtherTokenWrapper extends ContractWrapper {
private _etherTokenContractIfExists?: EtherTokenContract;
private _tokenWrapper: TokenWrapper;
- constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper, gasPrice?: BigNumber.BigNumber) {
- super(web3Wrapper, gasPrice);
+ constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper) {
+ super(web3Wrapper);
this._tokenWrapper = tokenWrapper;
}
/**
@@ -23,8 +23,9 @@ export class EtherTokenWrapper extends ContractWrapper {
* for ETH.
* @param amountInWei Amount of ETH in Wei the caller wishes to deposit.
* @param depositor The hex encoded user Ethereum address that would like to make the deposit.
+ * @return Transaction hash.
*/
- public async depositAsync(amountInWei: BigNumber.BigNumber, depositor: string): Promise<void> {
+ public async depositAsync(amountInWei: BigNumber.BigNumber, depositor: string): Promise<string> {
assert.isBigNumber('amountInWei', amountInWei);
await assert.isSenderAddressAsync('depositor', depositor, this._web3Wrapper);
@@ -32,18 +33,20 @@ export class EtherTokenWrapper extends ContractWrapper {
assert.assert(ethBalanceInWei.gte(amountInWei), ZeroExError.InsufficientEthBalanceForDeposit);
const wethContract = await this._getEtherTokenContractAsync();
- await wethContract.deposit({
+ const txHash = await wethContract.deposit.sendTransactionAsync({
from: depositor,
value: amountInWei,
});
+ return txHash;
}
/**
* Withdraw ETH to the withdrawer's address from the wrapped ETH smart contract in exchange for the
* equivalent number of wrapped ETH tokens.
* @param amountInWei Amount of ETH in Wei the caller wishes to withdraw.
* @param withdrawer The hex encoded user Ethereum address that would like to make the withdrawl.
+ * @return Transaction hash.
*/
- public async withdrawAsync(amountInWei: BigNumber.BigNumber, withdrawer: string): Promise<void> {
+ public async withdrawAsync(amountInWei: BigNumber.BigNumber, withdrawer: string): Promise<string> {
assert.isBigNumber('amountInWei', amountInWei);
await assert.isSenderAddressAsync('withdrawer', withdrawer, this._web3Wrapper);
@@ -52,9 +55,10 @@ export class EtherTokenWrapper extends ContractWrapper {
assert.assert(WETHBalanceInBaseUnits.gte(amountInWei), ZeroExError.InsufficientWEthBalanceForWithdrawal);
const wethContract = await this._getEtherTokenContractAsync();
- await wethContract.withdraw(amountInWei, {
+ const txHash = await wethContract.withdraw.sendTransactionAsync(amountInWei, {
from: withdrawer,
});
+ return txHash;
}
/**
* Retrieves the Wrapped Ether token contract address
@@ -71,7 +75,9 @@ export class EtherTokenWrapper extends ContractWrapper {
if (!_.isUndefined(this._etherTokenContractIfExists)) {
return this._etherTokenContractIfExists;
}
- const contractInstance = await this._instantiateContractIfExistsAsync((EtherTokenArtifacts as any));
+ const contractInstance = await this._instantiateContractIfExistsAsync<EtherTokenContract>(
+ artifacts.EtherTokenArtifact,
+ );
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 d09df236b..115bd1110 100644
--- a/src/contract_wrappers/exchange_wrapper.ts
+++ b/src/contract_wrappers/exchange_wrapper.ts
@@ -21,7 +21,6 @@ import {
IndexedFilterValues,
CreateContractEvent,
ContractEventObj,
- ContractResponse,
OrderCancellationRequest,
OrderFillRequest,
LogErrorContractEventArgs,
@@ -36,21 +35,13 @@ import {ContractWrapper} from './contract_wrapper';
import {constants} from '../utils/constants';
import {TokenWrapper} from './token_wrapper';
import {decorators} from '../utils/decorators';
-import * as ExchangeArtifacts from '../artifacts/Exchange.json';
+import {artifacts} from '../artifacts';
/**
* This class includes all the functionality related to calling methods and subscribing to
* events of the 0x Exchange smart contract.
*/
export class ExchangeWrapper extends ContractWrapper {
- private _exchangeContractErrCodesToMsg = {
- [ExchangeContractErrCodes.ERROR_FILL_EXPIRED]: ExchangeContractErrs.OrderFillExpired,
- [ExchangeContractErrCodes.ERROR_CANCEL_EXPIRED]: ExchangeContractErrs.OrderFillExpired,
- [ExchangeContractErrCodes.ERROR_FILL_NO_VALUE]: ExchangeContractErrs.OrderRemainingFillAmountZero,
- [ExchangeContractErrCodes.ERROR_CANCEL_NO_VALUE]: ExchangeContractErrs.OrderRemainingFillAmountZero,
- [ExchangeContractErrCodes.ERROR_FILL_TRUNCATION]: ExchangeContractErrs.OrderFillRoundingError,
- [ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.FillBalanceAllowanceError,
- };
private _exchangeContractIfExists?: ExchangeContract;
private _exchangeLogEventEmitters: ContractEventEmitter[];
private _orderValidationUtils: OrderValidationUtils;
@@ -73,8 +64,8 @@ export class ExchangeWrapper extends ContractWrapper {
];
return [orderAddresses, orderValues];
}
- constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper, gasPrice?: BigNumber.BigNumber) {
- super(web3Wrapper, gasPrice);
+ constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper) {
+ super(web3Wrapper);
this._tokenWrapper = tokenWrapper;
this._orderValidationUtils = new OrderValidationUtils(tokenWrapper, this);
this._exchangeLogEventEmitters = [];
@@ -91,7 +82,7 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
const exchangeContract = await this._getExchangeContractAsync();
- let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.call(orderHash);
+ let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.callAsync(orderHash);
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
unavailableTakerTokenAmount = new BigNumber(unavailableTakerTokenAmount);
return unavailableTakerTokenAmount;
@@ -105,7 +96,7 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
const exchangeContract = await this._getExchangeContractAsync();
- let fillAmountInBaseUnits = await exchangeContract.filled.call(orderHash);
+ let fillAmountInBaseUnits = await exchangeContract.filled.callAsync(orderHash);
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
fillAmountInBaseUnits = new BigNumber(fillAmountInBaseUnits);
return fillAmountInBaseUnits;
@@ -120,7 +111,7 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
const exchangeContract = await this._getExchangeContractAsync();
- let cancelledAmountInBaseUnits = await exchangeContract.cancelled.call(orderHash);
+ let cancelledAmountInBaseUnits = await exchangeContract.cancelled.callAsync(orderHash);
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
cancelledAmountInBaseUnits = new BigNumber(cancelledAmountInBaseUnits);
return cancelledAmountInBaseUnits;
@@ -141,12 +132,12 @@ export class ExchangeWrapper extends ContractWrapper {
* @param takerAddress The user Ethereum address who would like to fill this order.
* Must be available via the supplied Web3.Provider
* passed to 0x.js.
- * @return The amount of the order that was filled (in taker token baseUnits).
+ * @return Transaction hash.
*/
@decorators.contractCallErrorHandler
public async fillOrderAsync(signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber.BigNumber,
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
- takerAddress: string): Promise<BigNumber.BigNumber> {
+ takerAddress: string): Promise<string> {
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
assert.isBigNumber('fillTakerTokenAmount', fillTakerTokenAmount);
assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
@@ -157,7 +148,7 @@ export class ExchangeWrapper extends ContractWrapper {
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder);
- const gas = await exchangeInstance.fillOrder.estimateGas(
+ const gas = await exchangeInstance.fillOrder.estimateGasAsync(
orderAddresses,
orderValues,
fillTakerTokenAmount,
@@ -169,7 +160,7 @@ export class ExchangeWrapper extends ContractWrapper {
from: takerAddress,
},
);
- const response: ContractResponse = await exchangeInstance.fillOrder(
+ const txHash: string = await exchangeInstance.fillOrder.sendTransactionAsync(
orderAddresses,
orderValues,
fillTakerTokenAmount,
@@ -182,10 +173,7 @@ export class ExchangeWrapper extends ContractWrapper {
gas,
},
);
- this._throwErrorLogsAsErrors(response.logs);
- const logFillArgs = response.logs[0].args as LogFillContractEventArgs;
- const filledTakerTokenAmount = new BigNumber(logFillArgs.filledTakerTokenAmount);
- return filledTakerTokenAmount;
+ return txHash;
}
/**
* Sequentially and atomically fills signedOrders up to the specified takerTokenFillAmount.
@@ -201,12 +189,12 @@ export class ExchangeWrapper extends ContractWrapper {
* @param takerAddress The user Ethereum address who would like to fill these
* orders. Must be available via the supplied Web3.Provider
* passed to 0x.js.
- * @return The amount of the orders that was filled (in taker token baseUnits).
+ * @return Transaction hash.
*/
@decorators.contractCallErrorHandler
public async fillOrdersUpToAsync(signedOrders: SignedOrder[], fillTakerTokenAmount: BigNumber.BigNumber,
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
- takerAddress: string): Promise<BigNumber.BigNumber> {
+ takerAddress: string): Promise<string> {
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
const takerTokenAddresses = _.map(signedOrders, signedOrder => signedOrder.takerTokenAddress);
assert.hasAtMostOneUniqueValue(takerTokenAddresses,
@@ -222,7 +210,7 @@ export class ExchangeWrapper extends ContractWrapper {
signedOrder, fillTakerTokenAmount, takerAddress);
}
if (_.isEmpty(signedOrders)) {
- return new BigNumber(0); // no-op
+ throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
}
const orderAddressesValuesAndSignatureArray = _.map(signedOrders, signedOrder => {
@@ -239,7 +227,7 @@ export class ExchangeWrapper extends ContractWrapper {
);
const exchangeInstance = await this._getExchangeContractAsync();
- const gas = await exchangeInstance.fillOrdersUpTo.estimateGas(
+ const gas = await exchangeInstance.fillOrdersUpTo.estimateGasAsync(
orderAddressesArray,
orderValuesArray,
fillTakerTokenAmount,
@@ -251,7 +239,7 @@ export class ExchangeWrapper extends ContractWrapper {
from: takerAddress,
},
);
- const response: ContractResponse = await exchangeInstance.fillOrdersUpTo(
+ const txHash = await exchangeInstance.fillOrdersUpTo.sendTransactionAsync(
orderAddressesArray,
orderValuesArray,
fillTakerTokenAmount,
@@ -264,13 +252,7 @@ export class ExchangeWrapper extends ContractWrapper {
gas,
},
);
- this._throwErrorLogsAsErrors(response.logs);
- let filledTakerTokenAmount = new BigNumber(0);
- _.each(response.logs, log => {
- filledTakerTokenAmount = filledTakerTokenAmount.plus(
- (log.args as LogFillContractEventArgs).filledTakerTokenAmount);
- });
- return filledTakerTokenAmount;
+ return txHash;
}
/**
* Batch version of fillOrderAsync.
@@ -288,11 +270,12 @@ export class ExchangeWrapper extends ContractWrapper {
* @param takerAddress The user Ethereum address who would like to fill
* these orders. Must be available via the supplied
* Web3.Provider passed to 0x.js.
+ * @return Transaction hash.
*/
@decorators.contractCallErrorHandler
public async batchFillOrdersAsync(orderFillRequests: OrderFillRequest[],
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
- takerAddress: string): Promise<void> {
+ takerAddress: string): Promise<string> {
assert.doesConformToSchema('orderFillRequests', orderFillRequests, schemas.orderFillRequestsSchema);
const exchangeContractAddresses = _.map(
orderFillRequests,
@@ -307,7 +290,7 @@ export class ExchangeWrapper extends ContractWrapper {
orderFillRequest.signedOrder, orderFillRequest.takerTokenFillAmount, takerAddress);
}
if (_.isEmpty(orderFillRequests)) {
- return; // no-op
+ throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
}
const orderAddressesValuesAmountsAndSignatureArray = _.map(orderFillRequests, orderFillRequest => {
@@ -325,7 +308,7 @@ export class ExchangeWrapper extends ContractWrapper {
);
const exchangeInstance = await this._getExchangeContractAsync();
- const gas = await exchangeInstance.batchFillOrders.estimateGas(
+ const gas = await exchangeInstance.batchFillOrders.estimateGasAsync(
orderAddressesArray,
orderValuesArray,
fillTakerTokenAmounts,
@@ -337,7 +320,7 @@ export class ExchangeWrapper extends ContractWrapper {
from: takerAddress,
},
);
- const response: ContractResponse = await exchangeInstance.batchFillOrders(
+ const txHash = await exchangeInstance.batchFillOrders.sendTransactionAsync(
orderAddressesArray,
orderValuesArray,
fillTakerTokenAmounts,
@@ -350,7 +333,7 @@ export class ExchangeWrapper extends ContractWrapper {
gas,
},
);
- this._throwErrorLogsAsErrors(response.logs);
+ return txHash;
}
/**
* Attempts to fill a specific amount of an order. If the entire amount specified cannot be filled,
@@ -360,10 +343,11 @@ export class ExchangeWrapper extends ContractWrapper {
* @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill.
* @param takerAddress The user Ethereum address who would like to fill this order.
* Must be available via the supplied Web3.Provider passed to 0x.js.
+ * @return Transaction hash.
*/
@decorators.contractCallErrorHandler
public async fillOrKillOrderAsync(signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber.BigNumber,
- takerAddress: string): Promise<void> {
+ takerAddress: string): Promise<string> {
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
assert.isBigNumber('fillTakerTokenAmount', fillTakerTokenAmount);
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
@@ -374,7 +358,7 @@ export class ExchangeWrapper extends ContractWrapper {
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder);
- const gas = await exchangeInstance.fillOrKillOrder.estimateGas(
+ const gas = await exchangeInstance.fillOrKillOrder.estimateGasAsync(
orderAddresses,
orderValues,
fillTakerTokenAmount,
@@ -385,7 +369,7 @@ export class ExchangeWrapper extends ContractWrapper {
from: takerAddress,
},
);
- const response: ContractResponse = await exchangeInstance.fillOrKillOrder(
+ const txHash = await exchangeInstance.fillOrKillOrder.sendTransactionAsync(
orderAddresses,
orderValues,
fillTakerTokenAmount,
@@ -397,7 +381,7 @@ export class ExchangeWrapper extends ContractWrapper {
gas,
},
);
- this._throwErrorLogsAsErrors(response.logs);
+ return txHash;
}
/**
* Batch version of fillOrKill. Allows a taker to specify a batch of orders that will either be atomically
@@ -405,10 +389,11 @@ export class ExchangeWrapper extends ContractWrapper {
* @param orderFillOrKillRequests An array of objects that conform to the OrderFillOrKillRequest interface.
* @param takerAddress The user Ethereum address who would like to fill there orders.
* Must be available via the supplied Web3.Provider passed to 0x.js.
+ * @return Transaction hash.
*/
@decorators.contractCallErrorHandler
public async batchFillOrKillAsync(orderFillOrKillRequests: OrderFillOrKillRequest[],
- takerAddress: string): Promise<void> {
+ takerAddress: string): Promise<string> {
assert.doesConformToSchema('orderFillOrKillRequests', orderFillOrKillRequests,
schemas.orderFillOrKillRequestsSchema);
const exchangeContractAddresses = _.map(
@@ -419,7 +404,7 @@ export class ExchangeWrapper extends ContractWrapper {
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress);
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
if (_.isEmpty(orderFillOrKillRequests)) {
- return; // no-op
+ throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
}
const exchangeInstance = await this._getExchangeContractAsync();
for (const request of orderFillOrKillRequests) {
@@ -441,7 +426,7 @@ export class ExchangeWrapper extends ContractWrapper {
const [orderAddresses, orderValues, fillTakerTokenAmounts, vParams, rParams, sParams] =
_.unzip<any>(orderAddressesValuesAndTakerTokenFillAmounts);
- const gas = await exchangeInstance.batchFillOrKillOrders.estimateGas(
+ const gas = await exchangeInstance.batchFillOrKillOrders.estimateGasAsync(
orderAddresses,
orderValues,
fillTakerTokenAmounts,
@@ -452,7 +437,7 @@ export class ExchangeWrapper extends ContractWrapper {
from: takerAddress,
},
);
- const response: ContractResponse = await exchangeInstance.batchFillOrKillOrders(
+ const txHash = await exchangeInstance.batchFillOrKillOrders.sendTransactionAsync(
orderAddresses,
orderValues,
fillTakerTokenAmounts,
@@ -464,18 +449,18 @@ export class ExchangeWrapper extends ContractWrapper {
gas,
},
);
- this._throwErrorLogsAsErrors(response.logs);
+ return txHash;
}
/**
* Cancel a given fill amount of an order. Cancellations are cumulative.
* @param order An object that conforms to the Order or SignedOrder interface.
* The order you would like to cancel.
* @param cancelTakerTokenAmount The amount (specified in taker tokens) that you would like to cancel.
- * @return The amount of the order that was cancelled (in taker token baseUnits).
+ * @return Transaction hash.
*/
@decorators.contractCallErrorHandler
public async cancelOrderAsync(
- order: Order|SignedOrder, cancelTakerTokenAmount: BigNumber.BigNumber): Promise<BigNumber.BigNumber> {
+ order: Order|SignedOrder, cancelTakerTokenAmount: BigNumber.BigNumber): Promise<string> {
assert.doesConformToSchema('order', order, schemas.orderSchema);
assert.isBigNumber('takerTokenCancelAmount', cancelTakerTokenAmount);
await assert.isSenderAddressAsync('order.maker', order.maker, this._web3Wrapper);
@@ -484,7 +469,7 @@ export class ExchangeWrapper extends ContractWrapper {
await this.validateCancelOrderThrowIfInvalidAsync(order, cancelTakerTokenAmount);
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order);
- const gas = await exchangeInstance.cancelOrder.estimateGas(
+ const gas = await exchangeInstance.cancelOrder.estimateGasAsync(
orderAddresses,
orderValues,
cancelTakerTokenAmount,
@@ -492,7 +477,7 @@ export class ExchangeWrapper extends ContractWrapper {
from: order.maker,
},
);
- const response: ContractResponse = await exchangeInstance.cancelOrder(
+ const txHash = await exchangeInstance.cancelOrder.sendTransactionAsync(
orderAddresses,
orderValues,
cancelTakerTokenAmount,
@@ -501,19 +486,17 @@ export class ExchangeWrapper extends ContractWrapper {
gas,
},
);
- this._throwErrorLogsAsErrors(response.logs);
- const logFillArgs = response.logs[0].args as LogCancelContractEventArgs;
- const cancelledTakerTokenAmount = new BigNumber(logFillArgs.cancelledTakerTokenAmount);
- return cancelledTakerTokenAmount;
+ return txHash;
}
/**
* Batch version of cancelOrderAsync. Atomically cancels multiple orders in a single transaction.
* All orders must be from the same maker.
* @param orderCancellationRequests An array of objects that conform to the OrderCancellationRequest
* interface.
+ * @return Transaction hash.
*/
@decorators.contractCallErrorHandler
- public async batchCancelOrdersAsync(orderCancellationRequests: OrderCancellationRequest[]): Promise<void> {
+ public async batchCancelOrdersAsync(orderCancellationRequests: OrderCancellationRequest[]): Promise<string> {
assert.doesConformToSchema('orderCancellationRequests', orderCancellationRequests,
schemas.orderCancellationRequestsSchema);
const exchangeContractAddresses = _.map(
@@ -532,7 +515,7 @@ export class ExchangeWrapper extends ContractWrapper {
);
}
if (_.isEmpty(orderCancellationRequests)) {
- return; // no-op
+ throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
}
const exchangeInstance = await this._getExchangeContractAsync();
const orderAddressesValuesAndTakerTokenCancelAmounts = _.map(orderCancellationRequests, cancellationRequest => {
@@ -544,7 +527,7 @@ export class ExchangeWrapper extends ContractWrapper {
// We use _.unzip<any> because _.unzip doesn't type check if values have different types :'(
const [orderAddresses, orderValues, cancelTakerTokenAmounts] =
_.unzip<any>(orderAddressesValuesAndTakerTokenCancelAmounts);
- const gas = await exchangeInstance.batchCancelOrders.estimateGas(
+ const gas = await exchangeInstance.batchCancelOrders.estimateGasAsync(
orderAddresses,
orderValues,
cancelTakerTokenAmounts,
@@ -552,7 +535,7 @@ export class ExchangeWrapper extends ContractWrapper {
from: maker,
},
);
- const response: ContractResponse = await exchangeInstance.batchCancelOrders(
+ const txHash = await exchangeInstance.batchCancelOrders.sendTransactionAsync(
orderAddresses,
orderValues,
cancelTakerTokenAmounts,
@@ -561,7 +544,7 @@ export class ExchangeWrapper extends ContractWrapper {
gas,
},
);
- this._throwErrorLogsAsErrors(response.logs);
+ return txHash;
}
/**
* Subscribe to an event type emitted by the Exchange smart contract
@@ -686,7 +669,7 @@ export class ExchangeWrapper extends ContractWrapper {
assert.isBigNumber('takerTokenAmount', takerTokenAmount);
assert.isBigNumber('makerTokenAmount', makerTokenAmount);
const exchangeInstance = await this._getExchangeContractAsync();
- const isRoundingError = await exchangeInstance.isRoundingError.call(
+ const isRoundingError = await exchangeInstance.isRoundingError.callAsync(
fillTakerTokenAmount, takerTokenAmount, makerTokenAmount,
);
return isRoundingError;
@@ -703,7 +686,7 @@ export class ExchangeWrapper extends ContractWrapper {
const exchangeInstance = await this._getExchangeContractAsync();
- const isValidSignature = await exchangeInstance.isValidSignature.call(
+ const isValidSignature = await exchangeInstance.isValidSignature.callAsync(
signerAddressHex,
dataHex,
ecSignature.v,
@@ -715,28 +698,22 @@ export class ExchangeWrapper extends ContractWrapper {
private async _getOrderHashHexUsingContractCallAsync(order: Order|SignedOrder): Promise<string> {
const exchangeInstance = await this._getExchangeContractAsync();
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order);
- const orderHashHex = await exchangeInstance.getOrderHash.call(orderAddresses, orderValues);
+ const orderHashHex = await exchangeInstance.getOrderHash.callAsync(orderAddresses, orderValues);
return orderHashHex;
}
- private _throwErrorLogsAsErrors(logs: ContractEvent[]): void {
- const errEvent = _.find(logs, {event: 'LogError'});
- if (!_.isUndefined(errEvent)) {
- const errCode = (errEvent.args as LogErrorContractEventArgs).errorId.toNumber();
- const errMessage = this._exchangeContractErrCodesToMsg[errCode];
- throw new Error(errMessage);
- }
- }
private async _getExchangeContractAsync(): Promise<ExchangeContract> {
if (!_.isUndefined(this._exchangeContractIfExists)) {
return this._exchangeContractIfExists;
}
- const contractInstance = await this._instantiateContractIfExistsAsync((ExchangeArtifacts as any));
+ const contractInstance = await this._instantiateContractIfExistsAsync<ExchangeContract>(
+ artifacts.ExchangeArtifact,
+ );
this._exchangeContractIfExists = contractInstance as ExchangeContract;
return this._exchangeContractIfExists;
}
private async _getZRXTokenAddressAsync(): Promise<string> {
const exchangeInstance = await this._getExchangeContractAsync();
- const ZRXtokenAddress = await exchangeInstance.ZRX_TOKEN_CONTRACT.call();
+ const ZRXtokenAddress = await exchangeInstance.ZRX_TOKEN_CONTRACT.callAsync();
return ZRXtokenAddress;
}
}
diff --git a/src/contract_wrappers/token_registry_wrapper.ts b/src/contract_wrappers/token_registry_wrapper.ts
index 822e69460..528a88e06 100644
--- a/src/contract_wrappers/token_registry_wrapper.ts
+++ b/src/contract_wrappers/token_registry_wrapper.ts
@@ -4,15 +4,15 @@ import {assert} from '../utils/assert';
import {Token, TokenRegistryContract, TokenMetadata} from '../types';
import {constants} from '../utils/constants';
import {ContractWrapper} from './contract_wrapper';
-import * as TokenRegistryArtifacts from '../artifacts/TokenRegistry.json';
+import {artifacts} from '../artifacts';
/**
* This class includes all the functionality related to interacting with the 0x Token Registry smart contract.
*/
export class TokenRegistryWrapper extends ContractWrapper {
private _tokenRegistryContractIfExists?: TokenRegistryContract;
- constructor(web3Wrapper: Web3Wrapper, gasPrice?: BigNumber.BigNumber) {
- super(web3Wrapper, gasPrice);
+ constructor(web3Wrapper: Web3Wrapper) {
+ super(web3Wrapper);
}
/**
* Retrieves all the tokens currently listed in the Token Registry smart contract
@@ -35,7 +35,7 @@ export class TokenRegistryWrapper extends ContractWrapper {
*/
public async getTokenAddressesAsync(): Promise<string[]> {
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
- const addresses = await tokenRegistryContract.getTokenAddresses.call();
+ const addresses = await tokenRegistryContract.getTokenAddresses.callAsync();
return addresses;
}
/**
@@ -46,14 +46,14 @@ export class TokenRegistryWrapper extends ContractWrapper {
assert.isETHAddressHex('address', address);
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
- const metadata = await tokenRegistryContract.getTokenMetaData.call(address);
+ const metadata = await tokenRegistryContract.getTokenMetaData.callAsync(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);
+ const addressIfExists = await tokenRegistryContract.getTokenAddressBySymbol.callAsync(symbol);
if (addressIfExists === constants.NULL_ADDRESS) {
return undefined;
}
@@ -62,7 +62,7 @@ export class TokenRegistryWrapper extends ContractWrapper {
public async getTokenAddressByNameIfExistsAsync(name: string): Promise<string|undefined> {
assert.isString('name', name);
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
- const addressIfExists = await tokenRegistryContract.getTokenAddressByName.call(name);
+ const addressIfExists = await tokenRegistryContract.getTokenAddressByName.callAsync(name);
if (addressIfExists === constants.NULL_ADDRESS) {
return undefined;
}
@@ -71,14 +71,14 @@ export class TokenRegistryWrapper extends ContractWrapper {
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 metadata = await tokenRegistryContract.getTokenBySymbol.callAsync(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 metadata = await tokenRegistryContract.getTokenByName.callAsync(name);
const token = this._createTokenFromMetadata(metadata);
return token;
}
@@ -101,7 +101,9 @@ export class TokenRegistryWrapper extends ContractWrapper {
if (!_.isUndefined(this._tokenRegistryContractIfExists)) {
return this._tokenRegistryContractIfExists;
}
- const contractInstance = await this._instantiateContractIfExistsAsync((TokenRegistryArtifacts as any));
+ const contractInstance = await this._instantiateContractIfExistsAsync<TokenRegistryContract>(
+ artifacts.TokenRegistryArtifact,
+ );
this._tokenRegistryContractIfExists = contractInstance as TokenRegistryContract;
return this._tokenRegistryContractIfExists;
}
diff --git a/src/contract_wrappers/token_transfer_proxy_wrapper.ts b/src/contract_wrappers/token_transfer_proxy_wrapper.ts
index da17d79ff..528d661d1 100644
--- a/src/contract_wrappers/token_transfer_proxy_wrapper.ts
+++ b/src/contract_wrappers/token_transfer_proxy_wrapper.ts
@@ -1,6 +1,6 @@
import * as _ from 'lodash';
import {ContractWrapper} from './contract_wrapper';
-import * as TokenTransferProxyArtifacts from '../artifacts/TokenTransferProxy.json';
+import {artifacts} from '../artifacts';
import {TokenTransferProxyContract} from '../types';
/**
@@ -15,7 +15,7 @@ export class TokenTransferProxyWrapper extends ContractWrapper {
*/
public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
const tokenTransferProxyContractInstance = await this._getTokenTransferProxyContractAsync();
- const isAuthorized = await tokenTransferProxyContractInstance.authorized.call(exchangeContractAddress);
+ const isAuthorized = await tokenTransferProxyContractInstance.authorized.callAsync(exchangeContractAddress);
return isAuthorized;
}
/**
@@ -24,7 +24,7 @@ export class TokenTransferProxyWrapper extends ContractWrapper {
*/
public async getAuthorizedAddressesAsync(): Promise<string[]> {
const tokenTransferProxyContractInstance = await this._getTokenTransferProxyContractAsync();
- const authorizedAddresses = await tokenTransferProxyContractInstance.getAuthorizedAddresses.call();
+ const authorizedAddresses = await tokenTransferProxyContractInstance.getAuthorizedAddresses.callAsync();
return authorizedAddresses;
}
/**
@@ -44,7 +44,9 @@ export class TokenTransferProxyWrapper extends ContractWrapper {
if (!_.isUndefined(this._tokenTransferProxyContractIfExists)) {
return this._tokenTransferProxyContractIfExists;
}
- const contractInstance = await this._instantiateContractIfExistsAsync((TokenTransferProxyArtifacts as any));
+ const contractInstance = await this._instantiateContractIfExistsAsync<TokenTransferProxyContract>(
+ artifacts.TokenTransferProxyArtifact,
+ );
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 f7070f1f4..f1f967286 100644
--- a/src/contract_wrappers/token_wrapper.ts
+++ b/src/contract_wrappers/token_wrapper.ts
@@ -7,8 +7,7 @@ import {utils} from '../utils/utils';
import {eventUtils} from '../utils/event_utils';
import {constants} from '../utils/constants';
import {ContractWrapper} from './contract_wrapper';
-import * as TokenArtifacts from '../artifacts/Token.json';
-import * as TokenTransferProxyArtifacts from '../artifacts/TokenTransferProxy.json';
+import {artifacts} from '../artifacts';
import {
TokenContract,
ZeroExError,
@@ -31,8 +30,8 @@ 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, gasPrice?: BigNumber.BigNumber) {
- super(web3Wrapper, gasPrice);
+ constructor(web3Wrapper: Web3Wrapper) {
+ super(web3Wrapper);
this._tokenContractsByAddress = {};
this._tokenLogEventEmitters = [];
}
@@ -47,7 +46,7 @@ export class TokenWrapper extends ContractWrapper {
assert.isETHAddressHex('tokenAddress', tokenAddress);
const tokenContract = await this._getTokenContractAsync(tokenAddress);
- let balance = await tokenContract.balanceOf.call(ownerAddress);
+ let balance = await tokenContract.balanceOf.callAsync(ownerAddress);
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
balance = new BigNumber(balance);
return balance;
@@ -60,9 +59,10 @@ export class TokenWrapper extends ContractWrapper {
* 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.BigNumber): Promise<void> {
+ amountInBaseUnits: BigNumber.BigNumber): Promise<string> {
await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper);
assert.isETHAddressHex('spenderAddress', spenderAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
@@ -74,10 +74,11 @@ export class TokenWrapper extends ContractWrapper {
// 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;
- await tokenContract.approve(spenderAddress, amountInBaseUnits, {
+ 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.
@@ -88,12 +89,14 @@ export class TokenWrapper extends ContractWrapper {
* @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<void> {
- await this.setAllowanceAsync(
+ 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.
@@ -102,12 +105,13 @@ export class TokenWrapper extends ContractWrapper {
* you would like to retrieve.
* @param spenderAddress The hex encoded user Ethereum address who can spend the allowance you are fetching.
*/
- public async getAllowanceAsync(tokenAddress: string, ownerAddress: string, spenderAddress: string) {
+ public async getAllowanceAsync(tokenAddress: string, ownerAddress: string,
+ spenderAddress: string): Promise<BigNumber.BigNumber> {
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
const tokenContract = await this._getTokenContractAsync(tokenAddress);
- let allowanceInBaseUnits = await tokenContract.allowance.call(ownerAddress, spenderAddress);
+ let allowanceInBaseUnits = await tokenContract.allowance.callAsync(ownerAddress, spenderAddress);
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
allowanceInBaseUnits = new BigNumber(allowanceInBaseUnits);
return allowanceInBaseUnits;
@@ -117,7 +121,7 @@ export class TokenWrapper extends ContractWrapper {
* @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.
*/
- public async getProxyAllowanceAsync(tokenAddress: string, ownerAddress: string) {
+ public async getProxyAllowanceAsync(tokenAddress: string, ownerAddress: string): Promise<BigNumber.BigNumber> {
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
@@ -132,15 +136,17 @@ export class TokenWrapper extends ContractWrapper {
* @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.BigNumber): Promise<void> {
+ amountInBaseUnits: BigNumber.BigNumber): Promise<string> {
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isBigNumber('amountInBaseUnits', amountInBaseUnits);
const proxyAddress = await this._getProxyAddressAsync();
- await this.setAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, amountInBaseUnits);
+ 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
@@ -150,9 +156,13 @@ export class TokenWrapper extends ContractWrapper {
* @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<void> {
- await this.setProxyAllowanceAsync(tokenAddress, ownerAddress, this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
+ 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`.
@@ -160,9 +170,10 @@ export class TokenWrapper extends ContractWrapper {
* @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.BigNumber): Promise<void> {
+ amountInBaseUnits: BigNumber.BigNumber): Promise<string> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper);
assert.isETHAddressHex('toAddress', toAddress);
@@ -175,9 +186,10 @@ export class TokenWrapper extends ContractWrapper {
throw new Error(ZeroExError.InsufficientBalanceForTransfer);
}
- await tokenContract.transfer(toAddress, amountInBaseUnits, {
+ const txHash = await tokenContract.transfer.sendTransactionAsync(toAddress, amountInBaseUnits, {
from: fromAddress,
});
+ return txHash;
}
/**
* Transfers `amountInBaseUnits` ERC20 tokens from `fromAddress` to `toAddress`.
@@ -190,10 +202,11 @@ export class TokenWrapper extends ContractWrapper {
* `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.BigNumber):
- Promise<void> {
+ Promise<string> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isETHAddressHex('fromAddress', fromAddress);
assert.isETHAddressHex('toAddress', toAddress);
@@ -212,9 +225,13 @@ export class TokenWrapper extends ContractWrapper {
throw new Error(ZeroExError.InsufficientBalanceForTransfer);
}
- await tokenContract.transferFrom(fromAddress, toAddress, amountInBaseUnits, {
- from: senderAddress,
- });
+ const txHash = await tokenContract.transferFrom.sendTransactionAsync(
+ fromAddress, toAddress, amountInBaseUnits,
+ {
+ from: senderAddress,
+ },
+ );
+ return txHash;
}
/**
* Subscribe to an event type emitted by the Token contract.
@@ -267,7 +284,9 @@ export class TokenWrapper extends ContractWrapper {
if (!_.isUndefined(tokenContract)) {
return tokenContract;
}
- const contractInstance = await this._instantiateContractIfExistsAsync((TokenArtifacts as any), tokenAddress);
+ const contractInstance = await this._instantiateContractIfExistsAsync<TokenContract>(
+ artifacts.TokenArtifact, tokenAddress,
+ );
tokenContract = contractInstance as TokenContract;
this._tokenContractsByAddress[tokenAddress] = tokenContract;
return tokenContract;
@@ -276,7 +295,7 @@ export class TokenWrapper extends ContractWrapper {
const networkIdIfExists = await this._web3Wrapper.getNetworkIdIfExistsAsync();
const proxyNetworkConfigsIfExists = _.isUndefined(networkIdIfExists) ?
undefined :
- (TokenTransferProxyArtifacts as any).networks[networkIdIfExists];
+ artifacts.TokenTransferProxyArtifact.networks[networkIdIfExists];
if (_.isUndefined(proxyNetworkConfigsIfExists)) {
throw new Error(ZeroExError.ContractNotDeployedOnNetwork);
}
diff --git a/src/globals.d.ts b/src/globals.d.ts
index 9230ab02d..39d0860eb 100644
--- a/src/globals.d.ts
+++ b/src/globals.d.ts
@@ -33,23 +33,11 @@ declare module '*.json' {
/* tslint:enable */
}
-// truffle-contract declarations
-declare interface ContractInstance {
- address: string;
-}
-declare interface ContractFactory {
- setProvider: (providerObj: any) => void;
- deployed: () => ContractInstance;
- // Both any's are Web3.CallData, but I was unable to import it in this file
- defaults: (config: any) => any;
- at: (address: string) => ContractInstance;
-}
declare interface Artifact {
- networks: {[networkId: number]: any};
-}
-declare function contract(artifacts: Artifact): ContractFactory;
-declare module 'truffle-contract' {
- export = contract;
+ abi: any;
+ networks: {[networkId: number]: {
+ address: string;
+ }};
}
// find-version declarations
@@ -81,3 +69,18 @@ declare class HDWalletProvider {
declare module 'truffle-hdwallet-provider' {
export = HDWalletProvider;
}
+
+// abi-decoder declarations
+interface DecodedLogArg {
+ name: string;
+ value: string|BigNumber.BigNumber;
+}
+interface DecodedLog {
+ name: string;
+ events: DecodedLogArg[];
+}
+declare module 'abi-decoder' {
+ import * as Web3 from 'web3';
+ const addABI: (abi: Web3.AbiDefinition) => void;
+ const decodeLogs: (logs: Web3.LogEntry[]) => DecodedLog[];
+}
diff --git a/src/index.ts b/src/index.ts
index 6d6e4484c..00d4730da 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -30,4 +30,7 @@ export {
ContractEventArgs,
Web3Provider,
ZeroExConfig,
+ TransactionReceiptWithDecodedLogs,
+ LogWithDecodedArgs,
+ DecodedLogArgs,
} from './types';
diff --git a/src/types.ts b/src/types.ts
index 2400a9a60..9d3f77127 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -14,6 +14,7 @@ export enum ZeroExError {
InsufficientWEthBalanceForWithdrawal = 'INSUFFICIENT_WETH_BALANCE_FOR_WITHDRAWAL',
InvalidJump = 'INVALID_JUMP',
OutOfGas = 'OUT_OF_GAS',
+ NoNetworkId = 'NO_NETWORK_ID',
}
/**
@@ -39,137 +40,154 @@ export interface ContractEventObj {
}
export type CreateContractEvent = (indexFilterValues: IndexedFilterValues,
subscriptionOpts: SubscriptionOpts) => ContractEventObj;
-export interface ExchangeContract extends ContractInstance {
+export interface ExchangeContract extends Web3.ContractInstance {
isValidSignature: {
- call: (signerAddressHex: string, dataHex: string, v: number, r: string, s: string,
- txOpts?: TxOpts) => Promise<boolean>;
+ callAsync: (signerAddressHex: string, dataHex: string, v: number, r: string, s: string,
+ txOpts?: TxOpts) => Promise<boolean>;
};
LogFill: CreateContractEvent;
LogCancel: CreateContractEvent;
LogError: CreateContractEvent;
ZRX_TOKEN_CONTRACT: {
- call: () => Promise<string>;
+ callAsync: () => Promise<string>;
};
getUnavailableTakerTokenAmount: {
- call: (orderHash: string) => Promise<BigNumber.BigNumber>;
+ callAsync: (orderHash: string) => Promise<BigNumber.BigNumber>;
};
isRoundingError: {
- call: (fillTakerAmount: BigNumber.BigNumber, takerTokenAmount: BigNumber.BigNumber,
- makerTokenAmount: BigNumber.BigNumber, txOpts?: TxOpts) => Promise<boolean>;
+ callAsync: (fillTakerAmount: BigNumber.BigNumber, takerTokenAmount: BigNumber.BigNumber,
+ makerTokenAmount: BigNumber.BigNumber, txOpts?: TxOpts) => Promise<boolean>;
};
fillOrder: {
- (orderAddresses: OrderAddresses, orderValues: OrderValues, fillTakerTokenAmount: BigNumber.BigNumber,
- shouldThrowOnInsufficientBalanceOrAllowance: boolean,
- v: number, r: string, s: string, txOpts?: TxOpts): Promise<ContractResponse>;
- estimateGas: (orderAddresses: OrderAddresses, orderValues: OrderValues,
- fillTakerTokenAmount: BigNumber.BigNumber,
- shouldThrowOnInsufficientBalanceOrAllowance: boolean,
- v: number, r: string, s: string, txOpts?: TxOpts) => Promise<number>;
+ sendTransactionAsync: (orderAddresses: OrderAddresses, orderValues: OrderValues,
+ fillTakerTokenAmount: BigNumber.BigNumber,
+ shouldThrowOnInsufficientBalanceOrAllowance: boolean,
+ v: number, r: string, s: string, txOpts?: TxOpts) => Promise<string>;
+ estimateGasAsync: (orderAddresses: OrderAddresses, orderValues: OrderValues,
+ fillTakerTokenAmount: BigNumber.BigNumber,
+ shouldThrowOnInsufficientBalanceOrAllowance: boolean,
+ v: number, r: string, s: string, txOpts?: TxOpts) => Promise<number>;
};
batchFillOrders: {
- (orderAddresses: OrderAddresses[], orderValues: OrderValues[], fillTakerTokenAmounts: BigNumber.BigNumber[],
- shouldThrowOnInsufficientBalanceOrAllowance: boolean,
- v: number[], r: string[], s: string[], txOpts?: TxOpts): Promise<ContractResponse>;
- estimateGas: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
- fillTakerTokenAmounts: BigNumber.BigNumber[],
- shouldThrowOnInsufficientBalanceOrAllowance: boolean,
- v: number[], r: string[], s: string[], txOpts?: TxOpts) => Promise<number>;
+ sendTransactionAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
+ fillTakerTokenAmounts: BigNumber.BigNumber[],
+ shouldThrowOnInsufficientBalanceOrAllowance: boolean,
+ v: number[], r: string[], s: string[], txOpts?: TxOpts) => Promise<string>;
+ estimateGasAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
+ fillTakerTokenAmounts: BigNumber.BigNumber[],
+ shouldThrowOnInsufficientBalanceOrAllowance: boolean,
+ v: number[], r: string[], s: string[], txOpts?: TxOpts) => Promise<number>;
};
fillOrdersUpTo: {
- (orderAddresses: OrderAddresses[], orderValues: OrderValues[], fillTakerTokenAmount: BigNumber.BigNumber,
- shouldThrowOnInsufficientBalanceOrAllowance: boolean,
- v: number[], r: string[], s: string[], txOpts?: TxOpts): Promise<ContractResponse>;
- estimateGas: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
- fillTakerTokenAmount: BigNumber.BigNumber,
- shouldThrowOnInsufficientBalanceOrAllowance: boolean,
- v: number[], r: string[], s: string[], txOpts?: TxOpts) => Promise<number>;
+ sendTransactionAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
+ fillTakerTokenAmount: BigNumber.BigNumber,
+ shouldThrowOnInsufficientBalanceOrAllowance: boolean,
+ v: number[], r: string[], s: string[], txOpts?: TxOpts) => Promise<string>;
+ estimateGasAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
+ fillTakerTokenAmount: BigNumber.BigNumber,
+ shouldThrowOnInsufficientBalanceOrAllowance: boolean,
+ v: number[], r: string[], s: string[], txOpts?: TxOpts) => Promise<number>;
};
cancelOrder: {
- (orderAddresses: OrderAddresses, orderValues: OrderValues, cancelTakerTokenAmount: BigNumber.BigNumber,
- txOpts?: TxOpts): Promise<ContractResponse>;
- estimateGas: (orderAddresses: OrderAddresses, orderValues: OrderValues,
- cancelTakerTokenAmount: BigNumber.BigNumber,
- txOpts?: TxOpts) => Promise<number>;
+ sendTransactionAsync: (orderAddresses: OrderAddresses, orderValues: OrderValues,
+ cancelTakerTokenAmount: BigNumber.BigNumber, txOpts?: TxOpts) => Promise<string>;
+ estimateGasAsync: (orderAddresses: OrderAddresses, orderValues: OrderValues,
+ cancelTakerTokenAmount: BigNumber.BigNumber,
+ txOpts?: TxOpts) => Promise<number>;
};
batchCancelOrders: {
- (orderAddresses: OrderAddresses[], orderValues: OrderValues[], cancelTakerTokenAmounts: BigNumber.BigNumber[],
- txOpts?: TxOpts): Promise<ContractResponse>;
- estimateGas: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
- cancelTakerTokenAmounts: BigNumber.BigNumber[],
- txOpts?: TxOpts) => Promise<number>;
+ sendTransactionAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
+ cancelTakerTokenAmounts: BigNumber.BigNumber[], txOpts?: TxOpts) => Promise<string>;
+ estimateGasAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
+ cancelTakerTokenAmounts: BigNumber.BigNumber[],
+ txOpts?: TxOpts) => Promise<number>;
};
fillOrKillOrder: {
- (orderAddresses: OrderAddresses, orderValues: OrderValues, fillTakerTokenAmount: BigNumber.BigNumber,
- v: number, r: string, s: string, txOpts?: TxOpts): Promise<ContractResponse>;
- estimateGas: (orderAddresses: OrderAddresses, orderValues: OrderValues,
- fillTakerTokenAmount: BigNumber.BigNumber,
- v: number, r: string, s: string, txOpts?: TxOpts) => Promise<number>;
+ sendTransactionAsync: (orderAddresses: OrderAddresses, orderValues: OrderValues,
+ fillTakerTokenAmount: BigNumber.BigNumber,
+ v: number, r: string, s: string, txOpts?: TxOpts) => Promise<string>;
+ estimateGasAsync: (orderAddresses: OrderAddresses, orderValues: OrderValues,
+ fillTakerTokenAmount: BigNumber.BigNumber,
+ v: number, r: string, s: string, txOpts?: TxOpts) => Promise<number>;
};
batchFillOrKillOrders: {
- (orderAddresses: OrderAddresses[], orderValues: OrderValues[], fillTakerTokenAmounts: BigNumber.BigNumber[],
- v: number[], r: string[], s: string[], txOpts: TxOpts): Promise<ContractResponse>;
- estimateGas: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
- fillTakerTokenAmounts: BigNumber.BigNumber[],
- v: number[], r: string[], s: string[], txOpts?: TxOpts) => Promise<number>;
+ sendTransactionAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
+ fillTakerTokenAmounts: BigNumber.BigNumber[],
+ v: number[], r: string[], s: string[], txOpts: TxOpts) => Promise<string>;
+ estimateGasAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
+ fillTakerTokenAmounts: BigNumber.BigNumber[],
+ v: number[], r: string[], s: string[], txOpts?: TxOpts) => Promise<number>;
};
filled: {
- call: (orderHash: string) => Promise<BigNumber.BigNumber>;
+ callAsync: (orderHash: string) => Promise<BigNumber.BigNumber>;
};
cancelled: {
- call: (orderHash: string) => Promise<BigNumber.BigNumber>;
+ callAsync: (orderHash: string) => Promise<BigNumber.BigNumber>;
};
getOrderHash: {
- call: (orderAddresses: OrderAddresses, orderValues: OrderValues) => Promise<string>;
+ callAsync: (orderAddresses: OrderAddresses, orderValues: OrderValues) => Promise<string>;
};
}
-export interface TokenContract extends ContractInstance {
+export interface TokenContract extends Web3.ContractInstance {
Transfer: CreateContractEvent;
Approval: CreateContractEvent;
balanceOf: {
- call: (address: string) => Promise<BigNumber.BigNumber>;
+ callAsync: (address: string) => Promise<BigNumber.BigNumber>;
};
allowance: {
- call: (ownerAddress: string, allowedAddress: string) => Promise<BigNumber.BigNumber>;
+ callAsync: (ownerAddress: string, allowedAddress: string) => Promise<BigNumber.BigNumber>;
+ };
+ transfer: {
+ sendTransactionAsync: (toAddress: string, amountInBaseUnits: BigNumber.BigNumber,
+ txOpts?: TxOpts) => Promise<string>;
+ };
+ transferFrom: {
+ sendTransactionAsync: (fromAddress: string, toAddress: string, amountInBaseUnits: BigNumber.BigNumber,
+ txOpts?: TxOpts) => Promise<string>;
+ };
+ approve: {
+ sendTransactionAsync: (proxyAddress: string, amountInBaseUnits: BigNumber.BigNumber,
+ txOpts?: TxOpts) => Promise<string>;
};
- transfer: (toAddress: string, amountInBaseUnits: BigNumber.BigNumber, txOpts?: TxOpts) => Promise<boolean>;
- transferFrom: (fromAddress: string, toAddress: string, amountInBaseUnits: BigNumber.BigNumber,
- txOpts?: TxOpts) => Promise<boolean>;
- approve: (proxyAddress: string, amountInBaseUnits: BigNumber.BigNumber, txOpts?: TxOpts) => Promise<void>;
}
-export interface TokenRegistryContract extends ContractInstance {
+export interface TokenRegistryContract extends Web3.ContractInstance {
getTokenMetaData: {
- call: (address: string) => Promise<TokenMetadata>;
+ callAsync: (address: string) => Promise<TokenMetadata>;
};
getTokenAddresses: {
- call: () => Promise<string[]>;
+ callAsync: () => Promise<string[]>;
};
getTokenAddressBySymbol: {
- call: (symbol: string) => Promise<string>;
+ callAsync: (symbol: string) => Promise<string>;
};
getTokenAddressByName: {
- call: (name: string) => Promise<string>;
+ callAsync: (name: string) => Promise<string>;
};
getTokenBySymbol: {
- call: (symbol: string) => Promise<TokenMetadata>;
+ callAsync: (symbol: string) => Promise<TokenMetadata>;
};
getTokenByName: {
- call: (name: string) => Promise<TokenMetadata>;
+ callAsync: (name: string) => Promise<TokenMetadata>;
};
}
-export interface EtherTokenContract extends ContractInstance {
- deposit: (txOpts: TxOpts) => Promise<void>;
- withdraw: (amount: BigNumber.BigNumber, txOpts: TxOpts) => Promise<void>;
+export interface EtherTokenContract extends Web3.ContractInstance {
+ deposit: {
+ sendTransactionAsync: (txOpts: TxOpts) => Promise<string>;
+ };
+ withdraw: {
+ sendTransactionAsync: (amount: BigNumber.BigNumber, txOpts: TxOpts) => Promise<string>;
+ };
}
-export interface TokenTransferProxyContract extends ContractInstance {
+export interface TokenTransferProxyContract extends Web3.ContractInstance {
getAuthorizedAddresses: {
- call: () => Promise<string[]>;
+ callAsync: () => Promise<string[]>;
};
authorized: {
- call: (address: string) => Promise<boolean>;
+ callAsync: (address: string) => Promise<boolean>;
};
}
@@ -209,10 +227,7 @@ export enum ExchangeContractErrs {
InsufficientRemainingFillAmount = 'INSUFFICIENT_REMAINING_FILL_AMOUNT',
MultipleTakerTokensInFillUpToDisallowed = 'MULTIPLE_TAKER_TOKENS_IN_FILL_UP_TO_DISALLOWED',
BatchOrdersMustHaveSameExchangeAddress = 'BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS',
-}
-
-export interface ContractResponse {
- logs: ContractEvent[];
+ BatchOrdersMustHaveAtLeastOneItem = 'BATCH_ORDERS_MUST_HAVE_AT_LEAST_ONE_ITEM',
}
export interface ContractEvent {
@@ -349,14 +364,6 @@ export interface OrderFillRequest {
export type AsyncMethod = (...args: any[]) => Promise<any>;
-export interface ContractInstance {
- address: string;
-}
-
-export interface Artifact {
- networks: {[networkId: number]: any};
-}
-
export interface ContractEventEmitter {
watch: (eventCallback: EventCallback) => void;
stopWatchingAsync: () => Promise<void>;
@@ -373,14 +380,6 @@ export interface ExchangeContractByAddress {
[address: string]: ExchangeContract;
}
-export interface ContractArtifact {
- networks: {
- [networkId: number]: {
- address: string;
- };
- };
-}
-
export interface JSONRPCPayload {
params: any[];
method: string;
@@ -389,3 +388,25 @@ export interface JSONRPCPayload {
export interface ZeroExConfig {
gasPrice?: BigNumber.BigNumber; // Gas price to use with every transaction
}
+
+export type TransactionReceipt = Web3.TransactionReceipt;
+
+export enum AbiType {
+ Function = 'function',
+ Constructor = 'constructor',
+ Event = 'event',
+ Fallback = 'fallback',
+}
+
+export interface DecodedLogArgs {
+ [argName: string]: ContractEventArg;
+}
+
+export interface LogWithDecodedArgs extends Web3.LogEntry {
+ args: DecodedLogArgs;
+ event: string;
+}
+
+export interface TransactionReceiptWithDecodedLogs extends Web3.TransactionReceipt {
+ logs: LogWithDecodedArgs[];
+}
diff --git a/src/web3_wrapper.ts b/src/web3_wrapper.ts
index 61bac45c9..7b9a28a7d 100644
--- a/src/web3_wrapper.ts
+++ b/src/web3_wrapper.ts
@@ -2,13 +2,17 @@ import * as _ from 'lodash';
import * as Web3 from 'web3';
import * as BigNumber from 'bignumber.js';
import promisify = require('es6-promisify');
+import {ZeroExError} from './types';
+import {Contract} from './contract';
export class Web3Wrapper {
private web3: Web3;
+ private defaults: Partial<Web3.TxData>;
private networkIdIfExists?: number;
- constructor(provider: Web3.Provider) {
+ constructor(provider: Web3.Provider, defaults: Partial<Web3.TxData>) {
this.web3 = new Web3();
this.web3.setProvider(provider);
+ this.defaults = defaults;
}
public setProvider(provider: Web3.Provider) {
delete this.networkIdIfExists;
@@ -25,6 +29,10 @@ export class Web3Wrapper {
const nodeVersion = await promisify(this.web3.version.getNode)();
return nodeVersion;
}
+ public async getTransactionReceiptAsync(txHash: string): Promise<Web3.TransactionReceipt> {
+ const transactionReceipt = await promisify(this.web3.eth.getTransactionReceipt)(txHash);
+ return transactionReceipt;
+ }
public getCurrentProvider(): Web3.Provider {
return this.web3.currentProvider;
}
@@ -41,6 +49,30 @@ export class Web3Wrapper {
return undefined;
}
}
+ public async getContractInstanceFromArtifactAsync<A extends Web3.ContractInstance>(artifact: Artifact,
+ address?: string): Promise<A> {
+ let contractAddress: string;
+ if (_.isUndefined(address)) {
+ const networkIdIfExists = await this.getNetworkIdIfExistsAsync();
+ if (_.isUndefined(networkIdIfExists)) {
+ throw new Error(ZeroExError.NoNetworkId);
+ }
+ if (_.isUndefined(artifact.networks[networkIdIfExists])) {
+ throw new Error(ZeroExError.ContractNotDeployedOnNetwork);
+ }
+ contractAddress = artifact.networks[networkIdIfExists].address.toLowerCase();
+ } else {
+ contractAddress = address;
+ }
+ const doesContractExist = await this.doesContractExistAtAddressAsync(contractAddress);
+ if (!doesContractExist) {
+ throw new Error(ZeroExError.ContractDoesNotExist);
+ }
+ const contractInstance = this.getContractInstance<A>(
+ artifact.abi, contractAddress,
+ );
+ return contractInstance;
+ }
public toWei(ethAmount: BigNumber.BigNumber): BigNumber.BigNumber {
const balanceWei = this.web3.toWei(ethAmount, 'ether');
return balanceWei;
@@ -68,6 +100,11 @@ export class Web3Wrapper {
const addresses: string[] = await promisify(this.web3.eth.getAccounts)();
return addresses;
}
+ private getContractInstance<A extends Web3.ContractInstance>(abi: Web3.ContractAbi, address: string): A {
+ const web3ContractInstance = this.web3.eth.contract(abi).at(address);
+ const contractInstance = new Contract(web3ContractInstance, this.defaults) as any as A;
+ return contractInstance;
+ }
private async getNetworkAsync(): Promise<number> {
const networkId = await promisify(this.web3.version.getNetwork)();
return networkId;