Compare commits
69 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c567249819 | ||
|
d2dc4d18be | ||
|
67ed341f24 | ||
|
0b6e874a0d | ||
|
88791f732f | ||
|
b1feb5ac29 | ||
|
873aa26f63 | ||
|
a57b22a6bc | ||
|
7c61b09dce | ||
|
b38aff8808 | ||
|
912d15cb73 | ||
|
9dc13360c9 | ||
|
cb44b77d0b | ||
|
1baf065317 | ||
|
88c96c7052 | ||
|
9680cc1270 | ||
|
68d051d4a7 | ||
|
f1ed572819 | ||
|
9ae56485a9 | ||
|
a7ba16ef4a | ||
|
35f3396295 | ||
|
10817aa337 | ||
|
542aae6cd9 | ||
|
92eb68bf2c | ||
|
aa7d10e510 | ||
|
7377df8a4d | ||
|
70a7f02d0f | ||
|
5fb4b54153 | ||
|
c64154e33a | ||
|
07da617c05 | ||
|
35c133caed | ||
|
18a52a1ea7 | ||
|
501f054d51 | ||
|
f0a5ad2d20 | ||
|
258b4fac31 | ||
|
8ebc724379 | ||
|
df904f80e3 | ||
|
e6e12e946e | ||
|
2fd5f2781b | ||
|
2f97ddb727 | ||
|
a7b2131db7 | ||
|
f057267955 | ||
|
b0547819fd | ||
|
dff63f9b89 | ||
|
ee00769be1 | ||
|
ec22097efb | ||
|
bc5fd316df | ||
|
92b101fac8 | ||
|
78c46d7cc9 | ||
|
9f12ef61b0 | ||
|
e05dfab1fc | ||
|
b5c6c91962 | ||
|
f6a945dfe4 | ||
|
a12df1c73a | ||
|
876032a8a7 | ||
|
96d2a55eff | ||
|
5d57a2f0e9 | ||
|
2b547f94a4 | ||
|
c9e490bdae | ||
|
6325a03818 | ||
|
2577d8f662 | ||
|
1ad395cf86 | ||
|
1c2d4cbb1a | ||
|
9818eb2835 | ||
|
59fed02a8b | ||
|
0275ac9dad | ||
|
62452db5d8 | ||
|
792646888a | ||
|
66066b9722 |
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,6 +1,20 @@
|
||||
# CHANGELOG
|
||||
|
||||
v0.12.0 - _September 2, 2017_
|
||||
v0.13.1 - _September 6, 2017_
|
||||
------------------------
|
||||
* Added `zeroEx.exchange.throwLogErrorsAsErrors` method to public interface (#157)
|
||||
* Fixed an issue with overlapping async intervals in `zeroEx.awaitTransactionMinedAsync` (#157)
|
||||
* Fixed an issue with log decoder returning `BigNumber`s as `strings` (#157)
|
||||
|
||||
v0.13.0 - _September 6, 2017_
|
||||
------------------------
|
||||
* Made all the functions submitting transactions to the network to immediately return transaction hash (#151)
|
||||
* Added `zeroEx.awaitTransactionMinedAsync` (#151)
|
||||
* Added `TransactionReceiptWithDecodedLogs`, `LogWithDecodedArgs`, `DecodedLogArgs` to public types (#151)
|
||||
* Added signature validation to `validateFillOrderThrowIfInvalidAsync` (#152)
|
||||
|
||||
v0.12.1 - _September 2, 2017_
|
||||
------------------------
|
||||
* Added the support for web3@1.x.x provider (#142)
|
||||
* Added the optional `zeroExConfig` parameter to the constructor of `ZeroEx` (#139)
|
||||
* Added the ability to specify `gasPrice` when instantiating `ZeroEx` (#139)
|
||||
|
10
package.json
10
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "0x.js",
|
||||
"version": "0.12.0",
|
||||
"version": "0.13.0",
|
||||
"description": "A javascript library for interacting with the 0x protocol",
|
||||
"keywords": [
|
||||
"0x.js",
|
||||
@@ -36,7 +36,7 @@
|
||||
"pretest:umd": "run-s clean build:umd:dev build:commonjs",
|
||||
"substitute_umd_bundle": "npm run remove_src_files_not_used_by_tests; shx mv _bundles/* lib/src",
|
||||
"remove_src_files_not_used_by_tests": "find ./lib/src \\( -path ./lib/src/utils -o -path ./lib/src/subproviders -o -path ./lib/src/schemas -o -path \"./lib/src/types.*\" \\) -prune -o -type f -print | xargs rm",
|
||||
"run_mocha": "mocha lib/test/**/*_test.js --timeout 4000 --bail"
|
||||
"run_mocha": "mocha lib/test/**/*_test.js --timeout 5000 --bail"
|
||||
},
|
||||
"config": {
|
||||
"artifacts": "TokenTransferProxy Exchange TokenRegistry Token EtherToken",
|
||||
@@ -85,13 +85,12 @@
|
||||
"types-bn": "^0.0.1",
|
||||
"types-ethereumjs-util": "^0.0.5",
|
||||
"typescript": "^2.4.1",
|
||||
"web3_beta": "ethereum/web3.js#1.0",
|
||||
"web3-provider-engine": "^13.0.1",
|
||||
"web3-typescript-typings": "^0.3.2",
|
||||
"web3-typescript-typings": "^0.6.0",
|
||||
"webpack": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"0x-json-schemas": "^0.3.0",
|
||||
"0x-json-schemas": "^0.5.1",
|
||||
"bignumber.js": "^4.0.2",
|
||||
"compare-versions": "^3.0.1",
|
||||
"es6-promisify": "^5.0.0",
|
||||
@@ -100,7 +99,6 @@
|
||||
"find-versions": "^2.0.0",
|
||||
"lodash": "^4.17.4",
|
||||
"publish-release": "^1.3.3",
|
||||
"truffle-contract": "^2.0.1",
|
||||
"web3": "^0.20.0"
|
||||
}
|
||||
}
|
||||
|
73
src/0x.ts
73
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,26 @@ import {constants} from './utils/constants';
|
||||
import {utils} from './utils/utils';
|
||||
import {signatureUtils} from './utils/signature_utils';
|
||||
import {assert} from './utils/assert';
|
||||
import {AbiDecoder} from './utils/abi_decoder';
|
||||
import {intervalUtils} from './utils/interval_utils';
|
||||
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();
|
||||
@@ -57,6 +72,7 @@ export class ZeroEx {
|
||||
*/
|
||||
public proxy: TokenTransferProxyWrapper;
|
||||
private _web3Wrapper: Web3Wrapper;
|
||||
private _abiDecoder: AbiDecoder;
|
||||
/**
|
||||
* Verifies that the elliptic curve signature `signature` was generated
|
||||
* by signing `data` with the private key corresponding to the `signerAddress` address.
|
||||
@@ -170,13 +186,19 @@ 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);
|
||||
const artifactJSONs = _.values(artifacts);
|
||||
const abiArrays = _.map(artifactJSONs, artifact => artifact.abi);
|
||||
this._abiDecoder = new AbiDecoder(abiArrays);
|
||||
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 +271,39 @@ 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 = intervalUtils.setAsyncExcludingInterval(async () => {
|
||||
const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash);
|
||||
if (!_.isNull(transactionReceipt)) {
|
||||
intervalUtils.clearAsyncExcludingInterval(intervalId);
|
||||
const logsWithDecodedArgs = _.map(transactionReceipt.logs, (log: Web3.LogEntry) => {
|
||||
const decodedLog = this._abiDecoder.decodeLog(log);
|
||||
if (_.isUndefined(decodedLog)) {
|
||||
return log;
|
||||
}
|
||||
const logWithDecodedArgs: LogWithDecodedArgs = {
|
||||
...log,
|
||||
...decodedLog,
|
||||
};
|
||||
return logWithDecodedArgs;
|
||||
});
|
||||
const transactionReceiptWithDecodedLogArgs: TransactionReceiptWithDecodedLogs = {
|
||||
...transactionReceipt,
|
||||
logs: logsWithDecodedArgs,
|
||||
};
|
||||
resolve(transactionReceiptWithDecodedLogArgs);
|
||||
}
|
||||
}, pollingIntervalMs);
|
||||
});
|
||||
return txReceiptPromise;
|
||||
}
|
||||
}
|
||||
|
13
src/artifacts.ts
Normal file
13
src/artifacts.ts
Normal file
@@ -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,
|
||||
};
|
@@ -391,4 +391,4 @@
|
||||
},
|
||||
"schema_version": "0.0.5",
|
||||
"updated_at": 1503318938233
|
||||
}
|
||||
}
|
||||
|
80
src/contract.ts
Normal file
80
src/contract.ts
Normal file
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -21,12 +21,12 @@ import {
|
||||
IndexedFilterValues,
|
||||
CreateContractEvent,
|
||||
ContractEventObj,
|
||||
ContractResponse,
|
||||
OrderCancellationRequest,
|
||||
OrderFillRequest,
|
||||
LogErrorContractEventArgs,
|
||||
LogFillContractEventArgs,
|
||||
LogCancelContractEventArgs,
|
||||
LogWithDecodedArgs,
|
||||
} from '../types';
|
||||
import {assert} from '../utils/assert';
|
||||
import {utils} from '../utils/utils';
|
||||
@@ -36,13 +36,17 @@ 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 _exchangeContractIfExists?: ExchangeContract;
|
||||
private _exchangeLogEventEmitters: ContractEventEmitter[];
|
||||
private _orderValidationUtils: OrderValidationUtils;
|
||||
private _tokenWrapper: TokenWrapper;
|
||||
private _exchangeContractErrCodesToMsg = {
|
||||
[ExchangeContractErrCodes.ERROR_FILL_EXPIRED]: ExchangeContractErrs.OrderFillExpired,
|
||||
[ExchangeContractErrCodes.ERROR_CANCEL_EXPIRED]: ExchangeContractErrs.OrderFillExpired,
|
||||
@@ -51,10 +55,6 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
[ExchangeContractErrCodes.ERROR_FILL_TRUNCATION]: ExchangeContractErrs.OrderFillRoundingError,
|
||||
[ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.FillBalanceAllowanceError,
|
||||
};
|
||||
private _exchangeContractIfExists?: ExchangeContract;
|
||||
private _exchangeLogEventEmitters: ContractEventEmitter[];
|
||||
private _orderValidationUtils: OrderValidationUtils;
|
||||
private _tokenWrapper: TokenWrapper;
|
||||
private static _getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] {
|
||||
const orderAddresses: OrderAddresses = [
|
||||
order.maker,
|
||||
@@ -73,8 +73,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 +91,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 +105,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 +120,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 +141,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 +157,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 +169,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 +182,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 +198,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 +219,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 +236,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 +248,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 +261,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 +279,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 +299,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 +317,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 +329,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 +342,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 +352,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 +367,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 +378,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 +390,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 +398,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 +413,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 +435,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 +446,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 +458,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 +478,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 +486,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 +495,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 +524,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 +536,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 +544,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 +553,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,11 +678,24 @@ 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;
|
||||
}
|
||||
/**
|
||||
* Checks if logs contain LogError, which is emmited by Exchange contract on transaction failure.
|
||||
* @param logsWithDecodedArgs Transaction logs as returned by `zeroEx.awaitTransactionMinedAsync`
|
||||
*/
|
||||
public throwLogErrorsAsErrors(logsWithDecodedArgs: LogWithDecodedArgs[]): void {
|
||||
const errLog = _.find(logsWithDecodedArgs, {event: ExchangeEvents.LogError});
|
||||
if (!_.isUndefined(errLog)) {
|
||||
const logArgs: LogErrorContractEventArgs = errLog.args as any;
|
||||
const errCode = logArgs.errorId.toNumber();
|
||||
const errMessage = this._exchangeContractErrCodesToMsg[errCode];
|
||||
throw new Error(errMessage);
|
||||
}
|
||||
}
|
||||
private async _invalidateContractInstancesAsync(): Promise<void> {
|
||||
await this.stopWatchingAllEventsAsync();
|
||||
delete this._exchangeContractIfExists;
|
||||
@@ -703,7 +708,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 +720,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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
50
src/globals.d.ts
vendored
50
src/globals.d.ts
vendored
@@ -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
|
||||
@@ -75,9 +63,33 @@ declare module 'ethereumjs-abi' {
|
||||
}
|
||||
|
||||
// truffle-hdwallet-provider declarations
|
||||
declare class HDWalletProvider {
|
||||
constructor(mnemonic: string, rpcUrl: string);
|
||||
}
|
||||
declare module 'truffle-hdwallet-provider' {
|
||||
import * as Web3 from 'web3';
|
||||
class HDWalletProvider implements Web3.Provider {
|
||||
constructor(mnemonic: string, rpcUrl: string);
|
||||
public sendAsync(
|
||||
payload: Web3.JSONRPCRequestPayload,
|
||||
callback: (err: Error, result: Web3.JSONRPCResponsePayload) => void,
|
||||
): void;
|
||||
}
|
||||
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[];
|
||||
}
|
||||
|
||||
declare module 'web3/lib/solidity/coder' {
|
||||
const decodeParams: (types: string[], data: string) => any[];
|
||||
}
|
||||
|
@@ -30,4 +30,7 @@ export {
|
||||
ContractEventArgs,
|
||||
Web3Provider,
|
||||
ZeroExConfig,
|
||||
TransactionReceiptWithDecodedLogs,
|
||||
LogWithDecodedArgs,
|
||||
DecodedLogArgs,
|
||||
} from './types';
|
||||
|
205
src/types.ts
205
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,27 @@ 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 DecodedArgs {
|
||||
args: DecodedLogArgs;
|
||||
event: string;
|
||||
}
|
||||
|
||||
export interface LogWithDecodedArgs extends Web3.LogEntry, DecodedArgs {}
|
||||
|
||||
export interface TransactionReceiptWithDecodedLogs extends Web3.TransactionReceipt {
|
||||
logs: Array<LogWithDecodedArgs|Web3.LogEntry>;
|
||||
}
|
||||
|
67
src/utils/abi_decoder.ts
Normal file
67
src/utils/abi_decoder.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import * as Web3 from 'web3';
|
||||
import * as _ from 'lodash';
|
||||
import * as BigNumber from 'bignumber.js';
|
||||
import {AbiType, DecodedLogArgs, DecodedArgs} from '../types';
|
||||
import * as SolidityCoder from 'web3/lib/solidity/coder';
|
||||
|
||||
export class AbiDecoder {
|
||||
private savedABIs: Web3.AbiDefinition[] = [];
|
||||
private methodIds: {[signatureHash: string]: Web3.EventAbi} = {};
|
||||
constructor(abiArrays: Web3.AbiDefinition[][]) {
|
||||
_.map(abiArrays, this.addABI.bind(this));
|
||||
}
|
||||
public decodeLog(logItem: Web3.LogEntry): DecodedArgs|undefined {
|
||||
const methodId = logItem.topics[0];
|
||||
const event = this.methodIds[methodId];
|
||||
if (!_.isUndefined(event)) {
|
||||
const logData = logItem.data;
|
||||
const decodedParams: DecodedLogArgs = {};
|
||||
let dataIndex = 0;
|
||||
let topicsIndex = 1;
|
||||
|
||||
const nonIndexedInputs = _.filter(event.inputs, input => !input.indexed);
|
||||
const dataTypes = _.map(nonIndexedInputs, input => input.type);
|
||||
const decodedData = SolidityCoder.decodeParams(dataTypes, logData.slice(2));
|
||||
_.map(event.inputs, (param: Web3.EventParameter) => {
|
||||
let value;
|
||||
if (param.indexed) {
|
||||
value = logItem.topics[topicsIndex];
|
||||
topicsIndex++;
|
||||
} else {
|
||||
value = decodedData[dataIndex];
|
||||
dataIndex++;
|
||||
}
|
||||
if (param.type === 'address') {
|
||||
value = this.padZeros(new BigNumber(value).toString(16));
|
||||
} else if (param.type === 'uint256' || param.type === 'uint8' || param.type === 'int' ) {
|
||||
value = new BigNumber(value);
|
||||
}
|
||||
decodedParams[param.name] = value;
|
||||
});
|
||||
|
||||
return {
|
||||
event: event.name,
|
||||
args: decodedParams,
|
||||
};
|
||||
}
|
||||
}
|
||||
private addABI(abiArray: Web3.AbiDefinition[]): void {
|
||||
_.map(abiArray, (abi: Web3.AbiDefinition) => {
|
||||
if (abi.type === AbiType.Event) {
|
||||
const signature = `${abi.name}(${_.map(abi.inputs, input => input.type).join(',')})`;
|
||||
const signatureHash = new Web3().sha3(signature);
|
||||
this.methodIds[signatureHash] = abi;
|
||||
}
|
||||
});
|
||||
this.savedABIs = this.savedABIs.concat(abiArray);
|
||||
}
|
||||
private padZeros(address: string) {
|
||||
let formatted = address;
|
||||
if (_.startsWith(formatted, '0x')) {
|
||||
formatted = formatted.slice(2);
|
||||
}
|
||||
|
||||
formatted = _.padStart(formatted, 40, '0');
|
||||
return `0x${formatted}`;
|
||||
}
|
||||
}
|
20
src/utils/interval_utils.ts
Normal file
20
src/utils/interval_utils.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import * as _ from 'lodash';
|
||||
|
||||
export const intervalUtils = {
|
||||
setAsyncExcludingInterval(fn: () => Promise<void>, intervalMs: number) {
|
||||
let locked = false;
|
||||
const intervalId = setInterval(async () => {
|
||||
if (locked) {
|
||||
return;
|
||||
} else {
|
||||
locked = true;
|
||||
await fn();
|
||||
locked = false;
|
||||
}
|
||||
});
|
||||
return intervalId;
|
||||
},
|
||||
clearAsyncExcludingInterval(intervalId: number): void {
|
||||
clearInterval(intervalId);
|
||||
},
|
||||
};
|
@@ -1,4 +1,5 @@
|
||||
import {ExchangeContractErrs, SignedOrder, Order} from '../types';
|
||||
import {ExchangeContractErrs, SignedOrder, Order, ZeroExError} from '../types';
|
||||
import {ZeroEx} from '../0x';
|
||||
import {TokenWrapper} from '../contract_wrappers/token_wrapper';
|
||||
import {ExchangeWrapper} from '../contract_wrappers/exchange_wrapper';
|
||||
import {utils} from '../utils/utils';
|
||||
@@ -19,6 +20,9 @@ export class OrderValidationUtils {
|
||||
throw new Error(ExchangeContractErrs.OrderFillAmountZero);
|
||||
}
|
||||
const orderHash = utils.getOrderHashHex(signedOrder);
|
||||
if (!ZeroEx.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker)) {
|
||||
throw new Error(ZeroExError.InvalidSignature);
|
||||
}
|
||||
const unavailableTakerTokenAmount = await this.exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
|
||||
if (signedOrder.makerTokenAmount.eq(unavailableTakerTokenAmount)) {
|
||||
throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
||||
|
@@ -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;
|
||||
|
@@ -6,8 +6,12 @@ import * as BigNumber from 'bignumber.js';
|
||||
import * as Sinon from 'sinon';
|
||||
import {ZeroEx, Order} from '../src';
|
||||
import {constants} from './utils/constants';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
|
||||
import {LogWithDecodedArgs} from '../src';
|
||||
|
||||
const blockchainLifecycle = new BlockchainLifecycle();
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
@@ -204,4 +208,27 @@ describe('ZeroEx library', () => {
|
||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||
});
|
||||
});
|
||||
describe('#awaitTransactionMinedAsync', () => {
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
it('returns transaction receipt with decoded logs', async () => {
|
||||
const availableAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||
const coinbase = availableAddresses[0];
|
||||
const tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
const tokenUtils = new TokenUtils(tokens);
|
||||
const zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
|
||||
const proxyAddress = await zeroEx.proxy.getContractAddressAsync();
|
||||
const txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(zrxTokenAddress, coinbase);
|
||||
const txReceiptWithDecodedLogs = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs;
|
||||
expect(log.event).to.be.equal('Approval');
|
||||
expect(log.args._owner).to.be.equal(coinbase);
|
||||
expect(log.args._spender).to.be.equal(proxyAddress);
|
||||
expect(log.args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -52,7 +52,8 @@ describe('EtherTokenWrapper', () => {
|
||||
expect(preETHBalance).to.be.bignumber.gt(0);
|
||||
expect(preWETHBalance).to.be.bignumber.equal(0);
|
||||
|
||||
await zeroEx.etherToken.depositAsync(depositWeiAmount, addressWithETH);
|
||||
const txHash = await zeroEx.etherToken.depositAsync(depositWeiAmount, addressWithETH);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
|
||||
const postETHBalanceInWei = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
const postWETHBalanceInBaseUnits = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
|
||||
@@ -86,7 +87,8 @@ describe('EtherTokenWrapper', () => {
|
||||
expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
|
||||
expect(preWETHBalance).to.be.bignumber.equal(depositWeiAmount);
|
||||
|
||||
await zeroEx.etherToken.withdrawAsync(depositWeiAmount, addressWithETH);
|
||||
const txHash = await zeroEx.etherToken.withdrawAsync(depositWeiAmount, addressWithETH);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
|
||||
const postETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
const postWETHBalanceInBaseUnits = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
|
||||
|
@@ -169,8 +169,9 @@ describe('ExchangeWrapper', () => {
|
||||
.to.be.bignumber.equal(0);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount);
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
const txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, fillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(fillTakerAmount));
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
|
||||
@@ -185,8 +186,9 @@ describe('ExchangeWrapper', () => {
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
const partialFillAmount = new BigNumber(3);
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
const txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(partialFillAmount));
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
|
||||
@@ -196,34 +198,6 @@ describe('ExchangeWrapper', () => {
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(partialFillAmount));
|
||||
});
|
||||
it('should return filled amount', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
const partialFillAmount = new BigNumber(3);
|
||||
const filledAmount = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
expect(filledAmount).to.be.bignumber.equal(partialFillAmount);
|
||||
});
|
||||
it('should return the partially filled amount \
|
||||
if the fill amount specified is greater then the amount available', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
const partialFillAmount = new BigNumber(3);
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
const missingBalance = new BigNumber(1);
|
||||
const totalBalance = partialFillAmount.plus(missingBalance);
|
||||
await zeroEx.token.transferAsync(takerTokenAddress, coinbase, takerAddress, missingBalance);
|
||||
await zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, totalBalance);
|
||||
await zeroEx.token.transferAsync(makerTokenAddress, coinbase, makerAddress, missingBalance);
|
||||
await zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, totalBalance);
|
||||
const remainingFillAmount = fillableAmount.minus(partialFillAmount);
|
||||
const filledAmount = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
expect(filledAmount).to.be.bignumber.equal(remainingFillAmount);
|
||||
});
|
||||
it('should fill the valid orders with fees', async () => {
|
||||
const makerFee = new BigNumber(1);
|
||||
const takerFee = new BigNumber(2);
|
||||
@@ -231,8 +205,9 @@ describe('ExchangeWrapper', () => {
|
||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee,
|
||||
makerAddress, takerAddress, fillableAmount, feeRecipient,
|
||||
);
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
const txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, fillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
expect(await zeroEx.token.getBalanceAsync(zrxTokenAddress, feeRecipient))
|
||||
.to.be.bignumber.equal(makerFee.plus(takerFee));
|
||||
});
|
||||
@@ -265,13 +240,15 @@ describe('ExchangeWrapper', () => {
|
||||
];
|
||||
});
|
||||
describe('successful batch fills', () => {
|
||||
it('should no-op for an empty batch', async () => {
|
||||
await zeroEx.exchange.batchFillOrdersAsync(
|
||||
[], shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
it('should throw if a batch is empty', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrdersAsync(
|
||||
[], shouldThrowOnInsufficientBalanceOrAllowance, takerAddress),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
|
||||
});
|
||||
it('should successfully fill multiple orders', async () => {
|
||||
await zeroEx.exchange.batchFillOrdersAsync(
|
||||
const txHash = await zeroEx.exchange.batchFillOrdersAsync(
|
||||
orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
|
||||
const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
|
||||
expect(filledAmount).to.be.bignumber.equal(fillTakerAmount);
|
||||
@@ -298,26 +275,22 @@ describe('ExchangeWrapper', () => {
|
||||
signedOrders = [signedOrder, anotherSignedOrder];
|
||||
});
|
||||
describe('successful batch fills', () => {
|
||||
it('should no-op for an empty batch', async () => {
|
||||
await zeroEx.exchange.fillOrdersUpToAsync(
|
||||
[], fillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
it('should throw if a batch is empty', async () => {
|
||||
return expect(zeroEx.exchange.fillOrdersUpToAsync(
|
||||
[], fillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
|
||||
});
|
||||
it('should successfully fill up to specified amount', async () => {
|
||||
await zeroEx.exchange.fillOrdersUpToAsync(
|
||||
const txHash = await zeroEx.exchange.fillOrdersUpToAsync(
|
||||
signedOrders, fillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
|
||||
const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
|
||||
expect(filledAmount).to.be.bignumber.equal(fillableAmount);
|
||||
const remainingFillAmount = fillableAmount.minus(1);
|
||||
expect(anotherFilledAmount).to.be.bignumber.equal(remainingFillAmount);
|
||||
});
|
||||
it('should return filled amount', async () => {
|
||||
const filledTakerTokenAmount = await zeroEx.exchange.fillOrdersUpToAsync(
|
||||
signedOrders, fillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
);
|
||||
expect(filledTakerTokenAmount).to.be.bignumber.equal(fillUpToAmount);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -344,14 +317,11 @@ describe('ExchangeWrapper', () => {
|
||||
describe('#cancelOrderAsync', () => {
|
||||
describe('successful cancels', () => {
|
||||
it('should cancel an order', async () => {
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount);
|
||||
const txHash = await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHashHex);
|
||||
expect(cancelledAmount).to.be.bignumber.equal(cancelAmount);
|
||||
});
|
||||
it('should return cancelled amount', async () => {
|
||||
const cancelledAmount = await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount);
|
||||
expect(cancelledAmount).to.be.bignumber.equal(cancelAmount);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#batchCancelOrdersAsync', () => {
|
||||
|
@@ -4,7 +4,7 @@ import * as BigNumber from 'bignumber.js';
|
||||
import promisify = require('es6-promisify');
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import {ZeroEx, SignedOrder, Token, ExchangeContractErrs} from '../src';
|
||||
import {ZeroEx, SignedOrder, Token, ExchangeContractErrs, ZeroExError} from '../src';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
|
||||
import {FillScenarios} from './utils/fill_scenarios';
|
||||
@@ -64,6 +64,16 @@ describe('OrderValidation', () => {
|
||||
signedOrder, zeroFillAmount, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should throw when the signature is invalid', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
// 27 <--> 28
|
||||
signedOrder.ecSignature.v = 27 + (28 - signedOrder.ecSignature.v);
|
||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder, fillableAmount, takerAddress,
|
||||
)).to.be.rejectedWith(ZeroExError.InvalidSignature);
|
||||
});
|
||||
it('should throw when the order is fully filled or cancelled', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
|
@@ -58,7 +58,8 @@ describe('TokenWrapper', () => {
|
||||
const toAddress = addressWithoutFunds;
|
||||
const preBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
|
||||
expect(preBalance).to.be.bignumber.equal(0);
|
||||
await zeroEx.token.transferAsync(token.address, fromAddress, toAddress, transferAmount);
|
||||
const txHash = await zeroEx.token.transferAsync(token.address, fromAddress, toAddress, transferAmount);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const postBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
|
||||
return expect(postBalance).to.be.bignumber.equal(transferAmount);
|
||||
});
|
||||
@@ -356,7 +357,7 @@ describe('TokenWrapper', () => {
|
||||
// we do need both. A hack is to make the top-level a sync fn w/ a done callback and then
|
||||
// wrap the rest of the test in an async block
|
||||
// Source: https://github.com/mochajs/mocha/issues/2407
|
||||
it('Should receive the Transfer event when an order is filled', (done: DoneCallback) => {
|
||||
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const zeroExEvent = await zeroEx.token.subscribeAsync(
|
||||
tokenAddress, TokenEvents.Transfer, subscriptionOpts, indexFilterValues);
|
||||
@@ -372,7 +373,7 @@ describe('TokenWrapper', () => {
|
||||
await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Approval event when an order is cancelled', (done: DoneCallback) => {
|
||||
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const zeroExEvent = await zeroEx.token.subscribeAsync(
|
||||
tokenAddress, TokenEvents.Approval, subscriptionOpts, indexFilterValues);
|
||||
|
@@ -6,7 +6,6 @@
|
||||
import ProviderEngine = require('web3-provider-engine');
|
||||
import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
|
||||
import * as Web3 from 'web3';
|
||||
import * as Web3_beta from 'web3_beta';
|
||||
import {constants} from './constants';
|
||||
import {EmptyWalletSubProvider} from '../../src/subproviders/empty_wallet_subprovider';
|
||||
|
||||
@@ -29,9 +28,4 @@ export const web3Factory = {
|
||||
provider.start();
|
||||
return provider;
|
||||
},
|
||||
getProviderBeta(): Web3.Provider {
|
||||
const rpcUrl = `http://${constants.RPC_HOST}:${constants.RPC_PORT}`;
|
||||
const providerBeta = new Web3_beta.providers.HttpProvider(rpcUrl);
|
||||
return providerBeta;
|
||||
},
|
||||
};
|
||||
|
@@ -1,16 +0,0 @@
|
||||
import * as chai from 'chai';
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import 'mocha';
|
||||
import {ZeroEx, Order, SubscriptionOpts, TokenEvents, ContractEvent} from '../src';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('ZeroEx with beta web3', () => {
|
||||
const web3_beta_provider = web3Factory.getProviderBeta();
|
||||
const zeroEx = new ZeroEx(web3_beta_provider);
|
||||
it('is able to make a call using a beta provider', async () => {
|
||||
await zeroEx.tokenRegistry.getTokenAddressesAsync();
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user