Merge pull request #413 from 0xProject/feature/ethers-contracts
abi-gen V2 abi and ethers-contracts
This commit is contained in:
		@@ -1,5 +1,4 @@
 | 
			
		||||
lib
 | 
			
		||||
generated
 | 
			
		||||
.nyc_output
 | 
			
		||||
/packages/contracts/src/artifacts
 | 
			
		||||
package.json
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
 | 
			
		||||
    * Validate and lowercase all addresses in public methods (#373)
 | 
			
		||||
    * Improve validation to force passing contract addresses on private networks (#385)
 | 
			
		||||
    * Change `LogErrorContractEventArgs.errorId` type from `BigNumber` to `number` (#413)
 | 
			
		||||
    * Rename all public `_unsubscribeAll` methods to `unsubscribeAll` (#415)
 | 
			
		||||
 | 
			
		||||
## v0.32.2 - _February 9, 2018_
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
public {{this.name}} = {
 | 
			
		||||
    async callAsync(
 | 
			
		||||
    {{> typed_params inputs=inputs}}
 | 
			
		||||
        defaultBlock?: Web3.BlockParam,
 | 
			
		||||
    ): Promise<{{> return_type outputs=outputs}}> {
 | 
			
		||||
        const self = this as {{contractName}}Contract;
 | 
			
		||||
        const result = await promisify<{{> return_type outputs=outputs}}>(
 | 
			
		||||
            self._web3ContractInstance.{{this.name}}.call,
 | 
			
		||||
            self._web3ContractInstance,
 | 
			
		||||
        )(
 | 
			
		||||
            {{> params inputs=inputs}}
 | 
			
		||||
        );
 | 
			
		||||
        return result;
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
@@ -1,6 +0,0 @@
 | 
			
		||||
{{#singleReturnValue}}
 | 
			
		||||
{{#returnType outputs.0.type}}{{/returnType}}
 | 
			
		||||
{{/singleReturnValue}}
 | 
			
		||||
{{^singleReturnValue}}
 | 
			
		||||
[{{#each outputs}}{{#returnType type}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}]
 | 
			
		||||
{{/singleReturnValue}}
 | 
			
		||||
@@ -1,3 +0,0 @@
 | 
			
		||||
{{#each inputs}}
 | 
			
		||||
    {{name}}: {{#parameterType type}}{{/parameterType}},
 | 
			
		||||
{{/each}}
 | 
			
		||||
@@ -17,7 +17,7 @@
 | 
			
		||||
        "build": "run-p build:umd:prod build:commonjs; exit 0;",
 | 
			
		||||
        "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_DIR",
 | 
			
		||||
        "upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json",
 | 
			
		||||
        "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template contract_templates/contract.handlebars --partials 'contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated",
 | 
			
		||||
        "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'",
 | 
			
		||||
        "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
 | 
			
		||||
        "test:circleci": "run-s test:coverage report_test_coverage",
 | 
			
		||||
        "test": "run-s clean test:commonjs",
 | 
			
		||||
@@ -77,6 +77,7 @@
 | 
			
		||||
        "types-bn": "^0.0.1",
 | 
			
		||||
        "typescript": "2.7.1",
 | 
			
		||||
        "web3-provider-engine": "^13.0.1",
 | 
			
		||||
        "ethers-typescript-typings": "^0.0.1",
 | 
			
		||||
        "web3-typescript-typings": "^0.9.11",
 | 
			
		||||
        "webpack": "^3.1.0"
 | 
			
		||||
    },
 | 
			
		||||
@@ -88,6 +89,7 @@
 | 
			
		||||
        "@0xproject/web3-wrapper": "^0.1.14",
 | 
			
		||||
        "bintrees": "^1.0.2",
 | 
			
		||||
        "bn.js": "^4.11.8",
 | 
			
		||||
        "ethers-contracts": "^2.2.1",
 | 
			
		||||
        "ethereumjs-abi": "^0.6.4",
 | 
			
		||||
        "ethereumjs-blockstream": "^2.0.6",
 | 
			
		||||
        "ethereumjs-util": "^5.1.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -108,10 +108,10 @@ export class ContractWrapper {
 | 
			
		||||
        const logWithDecodedArgs = this._abiDecoder.tryToDecodeLogOrNoop(log);
 | 
			
		||||
        return logWithDecodedArgs;
 | 
			
		||||
    }
 | 
			
		||||
    protected async _instantiateContractIfExistsAsync(
 | 
			
		||||
    protected async _getContractAbiAndAddressFromArtifactsAsync(
 | 
			
		||||
        artifact: Artifact,
 | 
			
		||||
        addressIfExists?: string,
 | 
			
		||||
    ): Promise<Web3.ContractInstance> {
 | 
			
		||||
    ): Promise<[Web3.ContractAbi, string]> {
 | 
			
		||||
        let contractAddress: string;
 | 
			
		||||
        if (_.isUndefined(addressIfExists)) {
 | 
			
		||||
            if (_.isUndefined(artifact.networks[this._networkId])) {
 | 
			
		||||
@@ -125,8 +125,8 @@ export class ContractWrapper {
 | 
			
		||||
        if (!doesContractExist) {
 | 
			
		||||
            throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contract_name]);
 | 
			
		||||
        }
 | 
			
		||||
        const contractInstance = this._web3Wrapper.getContractInstance(artifact.abi, contractAddress);
 | 
			
		||||
        return contractInstance;
 | 
			
		||||
        const abiAndAddress: [Web3.ContractAbi, string] = [artifact.abi, contractAddress];
 | 
			
		||||
        return abiAndAddress;
 | 
			
		||||
    }
 | 
			
		||||
    protected _getContractAddress(artifact: Artifact, addressIfExists?: string): string {
 | 
			
		||||
        if (_.isUndefined(addressIfExists)) {
 | 
			
		||||
 
 | 
			
		||||
@@ -187,11 +187,11 @@ export class EtherTokenWrapper extends ContractWrapper {
 | 
			
		||||
        if (!_.isUndefined(etherTokenContract)) {
 | 
			
		||||
            return etherTokenContract;
 | 
			
		||||
        }
 | 
			
		||||
        const web3ContractInstance = await this._instantiateContractIfExistsAsync(
 | 
			
		||||
        const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
 | 
			
		||||
            artifacts.EtherTokenArtifact,
 | 
			
		||||
            etherTokenAddress,
 | 
			
		||||
        );
 | 
			
		||||
        const contractInstance = new EtherTokenContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
 | 
			
		||||
        const contractInstance = new EtherTokenContract(this._web3Wrapper, abi, address);
 | 
			
		||||
        etherTokenContract = contractInstance;
 | 
			
		||||
        this._etherTokenContractsByAddress[etherTokenAddress] = etherTokenContract;
 | 
			
		||||
        return etherTokenContract;
 | 
			
		||||
 
 | 
			
		||||
@@ -108,8 +108,10 @@ export class ExchangeWrapper extends ContractWrapper {
 | 
			
		||||
 | 
			
		||||
        const exchangeContract = await this._getExchangeContractAsync();
 | 
			
		||||
        const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
 | 
			
		||||
        const txData = {};
 | 
			
		||||
        let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.callAsync(
 | 
			
		||||
            orderHash,
 | 
			
		||||
            txData,
 | 
			
		||||
            defaultBlock,
 | 
			
		||||
        );
 | 
			
		||||
        // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
 | 
			
		||||
@@ -127,7 +129,8 @@ export class ExchangeWrapper extends ContractWrapper {
 | 
			
		||||
 | 
			
		||||
        const exchangeContract = await this._getExchangeContractAsync();
 | 
			
		||||
        const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
 | 
			
		||||
        let fillAmountInBaseUnits = await exchangeContract.filled.callAsync(orderHash, defaultBlock);
 | 
			
		||||
        const txData = {};
 | 
			
		||||
        let fillAmountInBaseUnits = await exchangeContract.filled.callAsync(orderHash, txData, defaultBlock);
 | 
			
		||||
        // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
 | 
			
		||||
        fillAmountInBaseUnits = new BigNumber(fillAmountInBaseUnits);
 | 
			
		||||
        return fillAmountInBaseUnits;
 | 
			
		||||
@@ -144,7 +147,8 @@ export class ExchangeWrapper extends ContractWrapper {
 | 
			
		||||
 | 
			
		||||
        const exchangeContract = await this._getExchangeContractAsync();
 | 
			
		||||
        const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
 | 
			
		||||
        let cancelledAmountInBaseUnits = await exchangeContract.cancelled.callAsync(orderHash, defaultBlock);
 | 
			
		||||
        const txData = {};
 | 
			
		||||
        let cancelledAmountInBaseUnits = await exchangeContract.cancelled.callAsync(orderHash, txData, defaultBlock);
 | 
			
		||||
        // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
 | 
			
		||||
        cancelledAmountInBaseUnits = new BigNumber(cancelledAmountInBaseUnits);
 | 
			
		||||
        return cancelledAmountInBaseUnits;
 | 
			
		||||
@@ -858,7 +862,7 @@ export class ExchangeWrapper extends ContractWrapper {
 | 
			
		||||
        });
 | 
			
		||||
        if (!_.isUndefined(errLog)) {
 | 
			
		||||
            const logArgs = (errLog as LogWithDecodedArgs<LogErrorContractEventArgs>).args;
 | 
			
		||||
            const errCode = logArgs.errorId.toNumber();
 | 
			
		||||
            const errCode = logArgs.errorId;
 | 
			
		||||
            const errMessage = this._exchangeContractErrCodesToMsg[errCode];
 | 
			
		||||
            throw new Error(errMessage);
 | 
			
		||||
        }
 | 
			
		||||
@@ -906,11 +910,11 @@ export class ExchangeWrapper extends ContractWrapper {
 | 
			
		||||
        if (!_.isUndefined(this._exchangeContractIfExists)) {
 | 
			
		||||
            return this._exchangeContractIfExists;
 | 
			
		||||
        }
 | 
			
		||||
        const web3ContractInstance = await this._instantiateContractIfExistsAsync(
 | 
			
		||||
        const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
 | 
			
		||||
            artifacts.ExchangeArtifact,
 | 
			
		||||
            this._contractAddressIfExists,
 | 
			
		||||
        );
 | 
			
		||||
        const contractInstance = new ExchangeContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
 | 
			
		||||
        const contractInstance = new ExchangeContract(this._web3Wrapper, abi, address);
 | 
			
		||||
        this._exchangeContractIfExists = contractInstance;
 | 
			
		||||
        return this._exchangeContractIfExists;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1 @@
 | 
			
		||||
dummy_token.ts
 | 
			
		||||
ether_token.ts
 | 
			
		||||
exchange.ts
 | 
			
		||||
token_registry.ts
 | 
			
		||||
token_transfer_proxy.ts
 | 
			
		||||
token.ts
 | 
			
		||||
*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,33 +0,0 @@
 | 
			
		||||
import {TxData, TxDataPayable} from '@0xproject/types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
import * as Web3 from 'web3';
 | 
			
		||||
 | 
			
		||||
export class BaseContract {
 | 
			
		||||
    protected _web3ContractInstance: Web3.ContractInstance;
 | 
			
		||||
    protected _defaults: Partial<TxData>;
 | 
			
		||||
    protected async _applyDefaultsToTxDataAsync<T extends TxData|TxDataPayable>(
 | 
			
		||||
        txData: T,
 | 
			
		||||
        estimateGasAsync?: (txData: T) => Promise<number>,
 | 
			
		||||
    ): Promise<TxData> {
 | 
			
		||||
        // Gas amount sourced with the following priorities:
 | 
			
		||||
        // 1. Optional param passed in to public method call
 | 
			
		||||
        // 2. Global config passed in at library instantiation
 | 
			
		||||
        // 3. Gas estimate calculation + safety margin
 | 
			
		||||
        const removeUndefinedProperties = _.pickBy;
 | 
			
		||||
        const txDataWithDefaults = {
 | 
			
		||||
            ...removeUndefinedProperties(this._defaults),
 | 
			
		||||
            ...removeUndefinedProperties(txData as any),
 | 
			
		||||
            // HACK: TS can't prove that T is spreadable.
 | 
			
		||||
            // Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
 | 
			
		||||
        };
 | 
			
		||||
        if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
 | 
			
		||||
            const estimatedGas = await estimateGasAsync(txData);
 | 
			
		||||
            txDataWithDefaults.gas = estimatedGas;
 | 
			
		||||
        }
 | 
			
		||||
        return txDataWithDefaults;
 | 
			
		||||
    }
 | 
			
		||||
    constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<TxData>) {
 | 
			
		||||
        this._web3ContractInstance = web3ContractInstance;
 | 
			
		||||
        this._defaults = defaults;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -23,7 +23,7 @@ export class TokenRegistryWrapper extends ContractWrapper {
 | 
			
		||||
            address: metadata[0],
 | 
			
		||||
            name: metadata[1],
 | 
			
		||||
            symbol: metadata[2],
 | 
			
		||||
            decimals: metadata[3].toNumber(),
 | 
			
		||||
            decimals: metadata[3],
 | 
			
		||||
        };
 | 
			
		||||
        return token;
 | 
			
		||||
    }
 | 
			
		||||
@@ -50,7 +50,8 @@ export class TokenRegistryWrapper extends ContractWrapper {
 | 
			
		||||
    public async getTokenAddressesAsync(): Promise<string[]> {
 | 
			
		||||
        const tokenRegistryContract = await this._getTokenRegistryContractAsync();
 | 
			
		||||
        const addresses = await tokenRegistryContract.getTokenAddresses.callAsync();
 | 
			
		||||
        return addresses;
 | 
			
		||||
        const lowerCaseAddresses = _.map(addresses, address => address.toLowerCase());
 | 
			
		||||
        return lowerCaseAddresses;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Retrieves a token by address currently listed in the Token Registry smart contract
 | 
			
		||||
@@ -116,14 +117,11 @@ export class TokenRegistryWrapper extends ContractWrapper {
 | 
			
		||||
        if (!_.isUndefined(this._tokenRegistryContractIfExists)) {
 | 
			
		||||
            return this._tokenRegistryContractIfExists;
 | 
			
		||||
        }
 | 
			
		||||
        const web3ContractInstance = await this._instantiateContractIfExistsAsync(
 | 
			
		||||
        const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
 | 
			
		||||
            artifacts.TokenRegistryArtifact,
 | 
			
		||||
            this._contractAddressIfExists,
 | 
			
		||||
        );
 | 
			
		||||
        const contractInstance = new TokenRegistryContract(
 | 
			
		||||
            web3ContractInstance,
 | 
			
		||||
            this._web3Wrapper.getContractDefaults(),
 | 
			
		||||
        );
 | 
			
		||||
        const contractInstance = new TokenRegistryContract(this._web3Wrapper, abi, address);
 | 
			
		||||
        this._tokenRegistryContractIfExists = contractInstance;
 | 
			
		||||
        return this._tokenRegistryContractIfExists;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -59,14 +59,11 @@ export class TokenTransferProxyWrapper extends ContractWrapper {
 | 
			
		||||
        if (!_.isUndefined(this._tokenTransferProxyContractIfExists)) {
 | 
			
		||||
            return this._tokenTransferProxyContractIfExists;
 | 
			
		||||
        }
 | 
			
		||||
        const web3ContractInstance = await this._instantiateContractIfExistsAsync(
 | 
			
		||||
        const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
 | 
			
		||||
            artifacts.TokenTransferProxyArtifact,
 | 
			
		||||
            this._contractAddressIfExists,
 | 
			
		||||
        );
 | 
			
		||||
        const contractInstance = new TokenTransferProxyContract(
 | 
			
		||||
            web3ContractInstance,
 | 
			
		||||
            this._web3Wrapper.getContractDefaults(),
 | 
			
		||||
        );
 | 
			
		||||
        const contractInstance = new TokenTransferProxyContract(this._web3Wrapper, abi, address);
 | 
			
		||||
        this._tokenTransferProxyContractIfExists = contractInstance;
 | 
			
		||||
        return this._tokenTransferProxyContractIfExists;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,8 @@ export class TokenWrapper extends ContractWrapper {
 | 
			
		||||
 | 
			
		||||
        const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
 | 
			
		||||
        const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
 | 
			
		||||
        let balance = await tokenContract.balanceOf.callAsync(normalizedOwnerAddress, defaultBlock);
 | 
			
		||||
        const txData = {};
 | 
			
		||||
        let balance = await tokenContract.balanceOf.callAsync(normalizedOwnerAddress, txData, defaultBlock);
 | 
			
		||||
        // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
 | 
			
		||||
        balance = new BigNumber(balance);
 | 
			
		||||
        return balance;
 | 
			
		||||
@@ -146,9 +147,11 @@ export class TokenWrapper extends ContractWrapper {
 | 
			
		||||
 | 
			
		||||
        const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
 | 
			
		||||
        const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
 | 
			
		||||
        const txData = {};
 | 
			
		||||
        let allowanceInBaseUnits = await tokenContract.allowance.callAsync(
 | 
			
		||||
            normalizedOwnerAddress,
 | 
			
		||||
            normalizedSpenderAddress,
 | 
			
		||||
            txData,
 | 
			
		||||
            defaultBlock,
 | 
			
		||||
        );
 | 
			
		||||
        // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
 | 
			
		||||
@@ -419,11 +422,11 @@ export class TokenWrapper extends ContractWrapper {
 | 
			
		||||
        if (!_.isUndefined(tokenContract)) {
 | 
			
		||||
            return tokenContract;
 | 
			
		||||
        }
 | 
			
		||||
        const web3ContractInstance = await this._instantiateContractIfExistsAsync(
 | 
			
		||||
        const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
 | 
			
		||||
            artifacts.TokenArtifact,
 | 
			
		||||
            normalizedTokenAddress,
 | 
			
		||||
        );
 | 
			
		||||
        const contractInstance = new TokenContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
 | 
			
		||||
        const contractInstance = new TokenContract(this._web3Wrapper, abi, address);
 | 
			
		||||
        tokenContract = contractInstance;
 | 
			
		||||
        this._tokenContractsByAddress[normalizedTokenAddress] = tokenContract;
 | 
			
		||||
        return tokenContract;
 | 
			
		||||
 
 | 
			
		||||
@@ -127,7 +127,7 @@ export interface SignedOrder extends Order {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//                          [address, name, symbol, decimals, ipfsHash, swarmHash]
 | 
			
		||||
export type TokenMetadata = [string, string, string, BigNumber, string, string];
 | 
			
		||||
export type TokenMetadata = [string, string, string, number, string, string];
 | 
			
		||||
 | 
			
		||||
export interface Token {
 | 
			
		||||
    name: string;
 | 
			
		||||
 
 | 
			
		||||
@@ -35,12 +35,8 @@ export class FillScenarios {
 | 
			
		||||
        const web3Wrapper = (this._zeroEx as any)._web3Wrapper as Web3Wrapper;
 | 
			
		||||
        for (const token of this._tokens) {
 | 
			
		||||
            if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') {
 | 
			
		||||
                const contractInstance = web3Wrapper.getContractInstance(
 | 
			
		||||
                    artifacts.DummyTokenArtifact.abi,
 | 
			
		||||
                    token.address,
 | 
			
		||||
                );
 | 
			
		||||
                const defaults = {};
 | 
			
		||||
                const dummyToken = new DummyTokenContract(contractInstance, defaults);
 | 
			
		||||
                const dummyToken = new DummyTokenContract(web3Wrapper, artifacts.DummyTokenArtifact.abi, token.address);
 | 
			
		||||
                const tokenSupply = ZeroEx.toBaseUnitAmount(INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS, token.decimals);
 | 
			
		||||
                const txHash = await dummyToken.setBalance.sendTransactionAsync(this._coinbase, tokenSupply, {
 | 
			
		||||
                    from: this._coinbase,
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@
 | 
			
		||||
        "./test/**/*",
 | 
			
		||||
        "../../node_modules/types-bn/index.d.ts",
 | 
			
		||||
        "../../node_modules/types-ethereumjs-util/index.d.ts",
 | 
			
		||||
        "../../node_modules/ethers-typescript-typings/index.d.ts",
 | 
			
		||||
        "../../node_modules/web3-typescript-typings/index.d.ts",
 | 
			
		||||
        "../../node_modules/chai-typescript-typings/index.d.ts",
 | 
			
		||||
        "../../node_modules/chai-as-promised-typescript-typings/index.d.ts"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,11 @@
 | 
			
		||||
# CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v0.2.3 - _TBD, 2018_
 | 
			
		||||
 | 
			
		||||
    * Add a `backend` parameter that allows you to specify the Ethereum library you use in your templates (`web3` or `ethers`). Ethers auto-converts small ints to numbers whereas Web3 doesn't. Defaults to `web3` (#413)
 | 
			
		||||
    * Add support for [tuple types](https://solidity.readthedocs.io/en/develop/abi-spec.html#handling-tuple-types) (#413)
 | 
			
		||||
    * Add `hasReturnValue` to context data (#413)
 | 
			
		||||
 | 
			
		||||
## v0.2.1 - _February 9, 2018_
 | 
			
		||||
 | 
			
		||||
    * Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
 | 
			
		||||
 
 | 
			
		||||
@@ -11,13 +11,14 @@ import * as yargs from 'yargs';
 | 
			
		||||
import toSnakeCase = require('to-snake-case');
 | 
			
		||||
import * as Web3 from 'web3';
 | 
			
		||||
 | 
			
		||||
import { ContextData, ParamKind } from './types';
 | 
			
		||||
import { ContextData, ContractsBackend, ParamKind } from './types';
 | 
			
		||||
import { utils } from './utils';
 | 
			
		||||
 | 
			
		||||
const ABI_TYPE_CONSTRUCTOR = 'constructor';
 | 
			
		||||
const ABI_TYPE_METHOD = 'function';
 | 
			
		||||
const ABI_TYPE_EVENT = 'event';
 | 
			
		||||
const DEFAULT_NETWORK_ID = 50;
 | 
			
		||||
const DEFAULT_BACKEND = 'web3';
 | 
			
		||||
 | 
			
		||||
const args = yargs
 | 
			
		||||
    .option('abis', {
 | 
			
		||||
@@ -43,6 +44,12 @@ const args = yargs
 | 
			
		||||
        demandOption: true,
 | 
			
		||||
        normalize: true,
 | 
			
		||||
    })
 | 
			
		||||
    .option('backend', {
 | 
			
		||||
        describe: `The backing Ethereum library your app uses. Either 'web3' or 'ethers'. Ethers auto-converts small ints to numbers whereas Web3 doesn't.`,
 | 
			
		||||
        type: 'string',
 | 
			
		||||
        choices: [ContractsBackend.Web3, ContractsBackend.Ethers],
 | 
			
		||||
        default: DEFAULT_BACKEND,
 | 
			
		||||
    })
 | 
			
		||||
    .option('network-id', {
 | 
			
		||||
        describe: 'ID of the network where contract ABIs are nested in artifacts',
 | 
			
		||||
        type: 'number',
 | 
			
		||||
@@ -73,8 +80,8 @@ function writeOutputFile(name: string, renderedTsCode: string): void {
 | 
			
		||||
    utils.log(`Created: ${chalk.bold(filePath)}`);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input));
 | 
			
		||||
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output));
 | 
			
		||||
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input, args.backend));
 | 
			
		||||
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output, args.backend));
 | 
			
		||||
 | 
			
		||||
if (args.partials) {
 | 
			
		||||
    registerPartials(args.partials);
 | 
			
		||||
@@ -129,6 +136,7 @@ for (const abiFileName of abiFileNames) {
 | 
			
		||||
        const methodData = {
 | 
			
		||||
            ...methodAbi,
 | 
			
		||||
            singleReturnValue: methodAbi.outputs.length === 1,
 | 
			
		||||
            hasReturnValue: methodAbi.outputs.length !== 0,
 | 
			
		||||
        };
 | 
			
		||||
        return methodData;
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -12,8 +12,14 @@ export enum AbiType {
 | 
			
		||||
    Fallback = 'fallback',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export enum ContractsBackend {
 | 
			
		||||
    Web3 = 'web3',
 | 
			
		||||
    Ethers = 'ethers',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Method extends Web3.MethodAbi {
 | 
			
		||||
    singleReturnValue: boolean;
 | 
			
		||||
    hasReturnValue: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ContextData {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,15 +3,21 @@ import * as _ from 'lodash';
 | 
			
		||||
import * as path from 'path';
 | 
			
		||||
import * as Web3 from 'web3';
 | 
			
		||||
 | 
			
		||||
import { AbiType, ParamKind } from './types';
 | 
			
		||||
import { AbiType, ContractsBackend, ParamKind } from './types';
 | 
			
		||||
 | 
			
		||||
export const utils = {
 | 
			
		||||
    solTypeToTsType(paramKind: ParamKind, solType: string): string {
 | 
			
		||||
    solTypeToTsType(
 | 
			
		||||
        paramKind: ParamKind,
 | 
			
		||||
        backend: ContractsBackend,
 | 
			
		||||
        solType: string,
 | 
			
		||||
        components?: Web3.DataItem[],
 | 
			
		||||
    ): string {
 | 
			
		||||
        const trailingArrayRegex = /\[\d*\]$/;
 | 
			
		||||
        if (solType.match(trailingArrayRegex)) {
 | 
			
		||||
            const arrayItemSolType = solType.replace(trailingArrayRegex, '');
 | 
			
		||||
            const arrayItemTsType = utils.solTypeToTsType(paramKind, arrayItemSolType);
 | 
			
		||||
            const arrayTsType = utils.isUnionType(arrayItemTsType)
 | 
			
		||||
            const arrayItemTsType = utils.solTypeToTsType(paramKind, backend, arrayItemSolType, components);
 | 
			
		||||
            const arrayTsType =
 | 
			
		||||
                utils.isUnionType(arrayItemTsType) || utils.isObjectType(arrayItemTsType)
 | 
			
		||||
                    ? `Array<${arrayItemTsType}>`
 | 
			
		||||
                    : `${arrayItemTsType}[]`;
 | 
			
		||||
            return arrayTsType;
 | 
			
		||||
@@ -24,25 +30,49 @@ export const utils = {
 | 
			
		||||
                { regex: '^bytes\\d*$', tsType: 'string' },
 | 
			
		||||
            ];
 | 
			
		||||
            if (paramKind === ParamKind.Input) {
 | 
			
		||||
                // web3 allows to pass those an non-bignumbers and that's nice
 | 
			
		||||
                // but it always returns stuff as BigNumbers
 | 
			
		||||
                // web3 and ethers allow to pass those as numbers instead of bignumbers
 | 
			
		||||
                solTypeRegexToTsType.unshift({
 | 
			
		||||
                    regex: '^u?int(8|16|32)?$',
 | 
			
		||||
                    tsType: 'number|BigNumber',
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            if (backend === ContractsBackend.Ethers && paramKind === ParamKind.Output) {
 | 
			
		||||
                // ethers-contracts automatically converts small BigNumbers to numbers
 | 
			
		||||
                solTypeRegexToTsType.unshift({
 | 
			
		||||
                    regex: '^u?int(8|16|32|48)?$',
 | 
			
		||||
                    tsType: 'number',
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            for (const regexAndTxType of solTypeRegexToTsType) {
 | 
			
		||||
                const { regex, tsType } = regexAndTxType;
 | 
			
		||||
                if (solType.match(regex)) {
 | 
			
		||||
                    return tsType;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            const TUPLE_TYPE_REGEX = '^tuple$';
 | 
			
		||||
            if (solType.match(TUPLE_TYPE_REGEX)) {
 | 
			
		||||
                const componentsType = _.map(components, component => {
 | 
			
		||||
                    const componentValueType = utils.solTypeToTsType(
 | 
			
		||||
                        paramKind,
 | 
			
		||||
                        backend,
 | 
			
		||||
                        component.type,
 | 
			
		||||
                        component.components,
 | 
			
		||||
                    );
 | 
			
		||||
                    const componentType = `${component.name}: ${componentValueType}`;
 | 
			
		||||
                    return componentType;
 | 
			
		||||
                });
 | 
			
		||||
                const tsType = `{${componentsType}}`;
 | 
			
		||||
                return tsType;
 | 
			
		||||
            }
 | 
			
		||||
            throw new Error(`Unknown Solidity type found: ${solType}`);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    isUnionType(tsType: string): boolean {
 | 
			
		||||
        return tsType === 'number|BigNumber';
 | 
			
		||||
    },
 | 
			
		||||
    isObjectType(tsType: string): boolean {
 | 
			
		||||
        return /^{.*}$/.test(tsType);
 | 
			
		||||
    },
 | 
			
		||||
    log(...args: any[]): void {
 | 
			
		||||
        console.log(...args); // tslint:disable-line:no-console
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,16 @@
 | 
			
		||||
/**
 | 
			
		||||
 * This file is auto-generated using abi-gen. Don't edit directly.
 | 
			
		||||
 * Templates can be found at https://github.com/0xProject/0x.js/tree/development/packages/0x.js/contract_templates.
 | 
			
		||||
 * Templates can be found at https://github.com/0xProject/0x.js/tree/development/packages/contract_templates.
 | 
			
		||||
 */
 | 
			
		||||
// tslint:disable:no-consecutive-blank-lines
 | 
			
		||||
// tslint:disable-next-line:no-unused-variable
 | 
			
		||||
import { TxData, TxDataPayable } from '@0xproject/types';
 | 
			
		||||
import { BigNumber, classUtils, promisify } from '@0xproject/utils';
 | 
			
		||||
import { BaseContract, Web3Wrapper } from '@0xproject/web3-wrapper';
 | 
			
		||||
import * as ethersContracts from 'ethers-contracts';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
import * as Web3 from 'web3';
 | 
			
		||||
 | 
			
		||||
import {BaseContract} from './base_contract';
 | 
			
		||||
 | 
			
		||||
{{#if events}}
 | 
			
		||||
export type {{contractName}}ContractEventArgs =
 | 
			
		||||
{{#each events}}
 | 
			
		||||
@@ -28,6 +29,7 @@ export enum {{contractName}}Events {
 | 
			
		||||
{{/each}}
 | 
			
		||||
{{/if}}
 | 
			
		||||
 | 
			
		||||
// tslint:disable:no-parameter-reassignment
 | 
			
		||||
export class {{contractName}}Contract extends BaseContract {
 | 
			
		||||
{{#each methods}}
 | 
			
		||||
    {{#this.constant}}
 | 
			
		||||
@@ -37,8 +39,8 @@ export class {{contractName}}Contract extends BaseContract {
 | 
			
		||||
    {{> tx contractName=../contractName}}
 | 
			
		||||
    {{/this.constant}}
 | 
			
		||||
{{/each}}
 | 
			
		||||
    constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<TxData>) {
 | 
			
		||||
        super(web3ContractInstance, defaults);
 | 
			
		||||
        classUtils.bindAll(this, ['_web3ContractInstance', '_defaults']);
 | 
			
		||||
    constructor(web3Wrapper: Web3Wrapper, abi: Web3.ContractAbi, address: string) {
 | 
			
		||||
        super(web3Wrapper, abi, address);
 | 
			
		||||
        classUtils.bindAll(this, ['_ethersInterface', 'address', 'abi', '_web3Wrapper']);
 | 
			
		||||
    }
 | 
			
		||||
} // tslint:disable:max-file-line-count
 | 
			
		||||
							
								
								
									
										3
									
								
								packages/contract_templates/partials/call.handlebars
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								packages/contract_templates/partials/call.handlebars
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
public {{this.name}} = {
 | 
			
		||||
    {{> callAsync}}
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										30
									
								
								packages/contract_templates/partials/callAsync.handlebars
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								packages/contract_templates/partials/callAsync.handlebars
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
{{#hasReturnValue}}
 | 
			
		||||
async callAsync(
 | 
			
		||||
{{> typed_params inputs=inputs}}
 | 
			
		||||
{{#this.payable}}
 | 
			
		||||
    txData: TxDataPayable = {},
 | 
			
		||||
{{/this.payable}}
 | 
			
		||||
{{^this.payable}}
 | 
			
		||||
    txData: TxData = {},
 | 
			
		||||
{{/this.payable}}
 | 
			
		||||
    defaultBlock?: Web3.BlockParam,
 | 
			
		||||
): Promise<{{> return_type outputs=outputs}}> {
 | 
			
		||||
    const self = this as {{contractName}}Contract;
 | 
			
		||||
    const inputAbi = _.find(this.abi, {name: '{{this.name}}'}).inputs;
 | 
			
		||||
    [{{> params inputs=inputs}}] = BaseContract._transformABIData(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(this));
 | 
			
		||||
    const encodedData = self._ethersInterface.functions.{{this.name}}(
 | 
			
		||||
        {{> params inputs=inputs}}
 | 
			
		||||
    ).data;
 | 
			
		||||
    const callData = await self._applyDefaultsToTxDataAsync(
 | 
			
		||||
        {
 | 
			
		||||
            data: encodedData,
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
    const rawCallResult = await self._web3Wrapper.callAsync(callData, defaultBlock);
 | 
			
		||||
    const outputAbi = _.find(this.abi, {name: '{{this.name}}'}).outputs as Web3.DataItem[];
 | 
			
		||||
    const outputParamsTypes = _.map(outputAbi, 'type');
 | 
			
		||||
    let resultArray = ethersContracts.Interface.decodeParams(outputParamsTypes, rawCallResult) as any;
 | 
			
		||||
    resultArray = BaseContract._transformABIData(outputAbi, resultArray, BaseContract._lowercaseAddress.bind(this));
 | 
			
		||||
    return resultArray{{#singleReturnValue}}[0]{{/singleReturnValue}};
 | 
			
		||||
},
 | 
			
		||||
{{/hasReturnValue}}
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
export interface {{name}}ContractEventArgs {
 | 
			
		||||
    {{#each inputs}}
 | 
			
		||||
    {{name}}: {{#returnType type}}{{/returnType}};
 | 
			
		||||
    {{name}}: {{#returnType type components}}{{/returnType}};
 | 
			
		||||
    {{/each}}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								packages/contract_templates/partials/return_type.handlebars
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								packages/contract_templates/partials/return_type.handlebars
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
{{#if outputs.length}}
 | 
			
		||||
{{#singleReturnValue}}
 | 
			
		||||
{{#returnType outputs.0.type components}}{{/returnType}}
 | 
			
		||||
{{/singleReturnValue}}
 | 
			
		||||
{{^singleReturnValue}}
 | 
			
		||||
[{{#each outputs}}{{#returnType type components}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}]
 | 
			
		||||
{{/singleReturnValue}}
 | 
			
		||||
{{else}}
 | 
			
		||||
void
 | 
			
		||||
{{/if}}
 | 
			
		||||
@@ -9,19 +9,22 @@ public {{this.name}} = {
 | 
			
		||||
    {{/this.payable}}
 | 
			
		||||
    ): Promise<string> {
 | 
			
		||||
        const self = this as {{contractName}}Contract;
 | 
			
		||||
        const inputAbi = _.find(this.abi, {name: '{{this.name}}'}).inputs;
 | 
			
		||||
        [{{> params inputs=inputs}}] = BaseContract._transformABIData(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(this));
 | 
			
		||||
        const encodedData = this._ethersInterface.functions.{{this.name}}(
 | 
			
		||||
            {{> params inputs=inputs}}
 | 
			
		||||
        ).data
 | 
			
		||||
        const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
 | 
			
		||||
            txData,
 | 
			
		||||
            {
 | 
			
		||||
                ...txData,
 | 
			
		||||
                data: encodedData,
 | 
			
		||||
            },
 | 
			
		||||
            self.{{this.name}}.estimateGasAsync.bind(
 | 
			
		||||
                self,
 | 
			
		||||
                {{> params inputs=inputs}}
 | 
			
		||||
            ),
 | 
			
		||||
        );
 | 
			
		||||
        const txHash = await promisify<string>(
 | 
			
		||||
            self._web3ContractInstance.{{this.name}}, self._web3ContractInstance,
 | 
			
		||||
        )(
 | 
			
		||||
            {{> params inputs=inputs}}
 | 
			
		||||
            txDataWithDefaults,
 | 
			
		||||
        );
 | 
			
		||||
        const txHash = await this._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
 | 
			
		||||
        return txHash;
 | 
			
		||||
    },
 | 
			
		||||
    async estimateGasAsync(
 | 
			
		||||
@@ -29,15 +32,16 @@ public {{this.name}} = {
 | 
			
		||||
        txData: TxData = {},
 | 
			
		||||
    ): Promise<number> {
 | 
			
		||||
        const self = this as {{contractName}}Contract;
 | 
			
		||||
        const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
 | 
			
		||||
            txData,
 | 
			
		||||
        );
 | 
			
		||||
        const gas = await promisify<number>(
 | 
			
		||||
            self._web3ContractInstance.{{this.name}}.estimateGas, self._web3ContractInstance,
 | 
			
		||||
        )(
 | 
			
		||||
        const encodedData = this._ethersInterface.functions.{{this.name}}(
 | 
			
		||||
            {{> params inputs=inputs}}
 | 
			
		||||
            txDataWithDefaults,
 | 
			
		||||
        ).data
 | 
			
		||||
        const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
 | 
			
		||||
            {
 | 
			
		||||
                ...txData,
 | 
			
		||||
                data: encodedData,
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
        const gas = await this._web3Wrapper.estimateGasAsync(txDataWithDefaults);
 | 
			
		||||
        return gas;
 | 
			
		||||
    },
 | 
			
		||||
    getABIEncodedTransactionData(
 | 
			
		||||
@@ -45,7 +49,10 @@ public {{this.name}} = {
 | 
			
		||||
        txData: TxData = {},
 | 
			
		||||
    ): string {
 | 
			
		||||
        const self = this as {{contractName}}Contract;
 | 
			
		||||
        const abiEncodedTransactionData = self._web3ContractInstance.{{this.name}}.getData();
 | 
			
		||||
        const abiEncodedTransactionData = this._ethersInterface.functions.{{this.name}}(
 | 
			
		||||
            {{> params inputs=inputs}}
 | 
			
		||||
        ).data
 | 
			
		||||
        return abiEncodedTransactionData;
 | 
			
		||||
    },
 | 
			
		||||
    {{> callAsync}}
 | 
			
		||||
};
 | 
			
		||||
@@ -0,0 +1,3 @@
 | 
			
		||||
{{#each inputs}}
 | 
			
		||||
    {{name}}: {{#parameterType type components}}{{/parameterType}},
 | 
			
		||||
{{/each}}
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * This file is auto-generated using abi-gen. Don't edit directly.
 | 
			
		||||
 * Templates can be found at https://github.com/0xProject/0x.js/tree/development/packages/abi-gen-templates.
 | 
			
		||||
 */
 | 
			
		||||
// tslint:disable:async-suffix member-ordering no-consecutive-blank-lines
 | 
			
		||||
// tslint:disable-next-line:no-unused-variable
 | 
			
		||||
import { TxData, TxDataPayable } from '@0xproject/types';
 | 
			
		||||
import { BigNumber, classUtils, promisify } from '@0xproject/utils';
 | 
			
		||||
import * as Web3 from 'web3';
 | 
			
		||||
 | 
			
		||||
import {BaseContract} from './base_contract';
 | 
			
		||||
 | 
			
		||||
export class {{contractName}}Contract extends BaseContract {
 | 
			
		||||
{{#each methods}}
 | 
			
		||||
    {{#this.constant}}
 | 
			
		||||
    {{> call contractName=../contractName}}
 | 
			
		||||
    {{/this.constant}}
 | 
			
		||||
    {{^this.constant}}
 | 
			
		||||
    {{> tx contractName=../contractName}}
 | 
			
		||||
    {{/this.constant}}
 | 
			
		||||
{{/each}}
 | 
			
		||||
    constructor(web3ContractInstance: Web3.ContractInstance, defaults?: Partial<TxData>) {
 | 
			
		||||
        super(web3ContractInstance, defaults);
 | 
			
		||||
        classUtils.bindAll(this, ['_web3ContractInstance', '_defaults']);
 | 
			
		||||
    }
 | 
			
		||||
} // tslint:disable:max-file-line-count
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
public async {{this.name}}(
 | 
			
		||||
{{> typed_params inputs=inputs}}
 | 
			
		||||
    defaultBlock?: Web3.BlockParam,
 | 
			
		||||
): Promise<{{> return_type outputs=outputs}}> {
 | 
			
		||||
    const self = this as {{contractName}}Contract;
 | 
			
		||||
    const result = await self._web3ContractInstance.{{this.name}}.call(
 | 
			
		||||
        {{> params inputs=inputs}}
 | 
			
		||||
    );
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,3 +0,0 @@
 | 
			
		||||
{{#each inputs}}
 | 
			
		||||
{{name}},
 | 
			
		||||
{{/each}}
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
{{#if outputs.length}}
 | 
			
		||||
{{#singleReturnValue}}
 | 
			
		||||
{{#returnType outputs.0.type}}{{/returnType}}
 | 
			
		||||
{{/singleReturnValue}}
 | 
			
		||||
{{^singleReturnValue}}
 | 
			
		||||
[{{#each outputs}}{{#returnType type}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}]
 | 
			
		||||
{{/singleReturnValue}}
 | 
			
		||||
{{else}}
 | 
			
		||||
void
 | 
			
		||||
{{/if}}
 | 
			
		||||
@@ -1,36 +0,0 @@
 | 
			
		||||
public {{this.name}} = {
 | 
			
		||||
    async sendTransactionAsync(
 | 
			
		||||
    {{> typed_params inputs=inputs}}
 | 
			
		||||
    {{#this.payable}}
 | 
			
		||||
        txData: TxDataPayable = {},
 | 
			
		||||
    {{/this.payable}}
 | 
			
		||||
    {{^this.payable}}
 | 
			
		||||
        txData: TxData = {},
 | 
			
		||||
    {{/this.payable}}
 | 
			
		||||
    ): Promise<string> {
 | 
			
		||||
        const self = this as {{contractName}}Contract;
 | 
			
		||||
        const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(txData);
 | 
			
		||||
        const txHash = await self._web3ContractInstance.{{this.name}}(
 | 
			
		||||
            {{> params inputs=inputs}}
 | 
			
		||||
            txDataWithDefaults,
 | 
			
		||||
        );
 | 
			
		||||
        return txHash;
 | 
			
		||||
    },
 | 
			
		||||
    async callAsync(
 | 
			
		||||
    {{> typed_params inputs=inputs}}
 | 
			
		||||
    {{#this.payable}}
 | 
			
		||||
        txData: TxDataPayable = {},
 | 
			
		||||
    {{/this.payable}}
 | 
			
		||||
    {{^this.payable}}
 | 
			
		||||
        txData: TxData = {},
 | 
			
		||||
    {{/this.payable}}
 | 
			
		||||
    ): Promise<{{> return_type outputs=outputs}}> {
 | 
			
		||||
        const self = this as {{contractName}}Contract;
 | 
			
		||||
        const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(txData);
 | 
			
		||||
        const returnValue = await self._web3ContractInstance.{{this.name}}.call(
 | 
			
		||||
            {{> params inputs=inputs}}
 | 
			
		||||
            txDataWithDefaults,
 | 
			
		||||
        );
 | 
			
		||||
        return returnValue;
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
@@ -1,3 +0,0 @@
 | 
			
		||||
{{#each inputs}}
 | 
			
		||||
    {{name}}: {{#parameterType type}}{{/parameterType}},
 | 
			
		||||
{{/each}}
 | 
			
		||||
@@ -17,7 +17,7 @@
 | 
			
		||||
        "compile:comment": "Yarn workspaces do not link binaries correctly so we need to reference them directly https://github.com/yarnpkg/yarn/issues/3846",
 | 
			
		||||
        "compile": "node ../deployer/lib/src/cli.js compile --contracts ${npm_package_config_contracts} --contracts-dir src/contracts --artifacts-dir src/artifacts",
 | 
			
		||||
        "clean": "shx rm -rf ./lib",
 | 
			
		||||
        "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/artifacts/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken).json' --template contract_templates/contract.handlebars --partials 'contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated",
 | 
			
		||||
        "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/artifacts/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'",
 | 
			
		||||
        "migrate": "node ../deployer/lib/src/cli.js migrate",
 | 
			
		||||
        "lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'",
 | 
			
		||||
        "test:circleci": "yarn test"
 | 
			
		||||
@@ -58,6 +58,7 @@
 | 
			
		||||
        "types-bn": "^0.0.1",
 | 
			
		||||
        "types-ethereumjs-util": "0xProject/types-ethereumjs-util",
 | 
			
		||||
        "typescript": "2.7.1",
 | 
			
		||||
        "ethers-typescript-typings": "^0.0.1",
 | 
			
		||||
        "web3-typescript-typings": "^0.9.11",
 | 
			
		||||
        "yargs": "^10.0.3"
 | 
			
		||||
    },
 | 
			
		||||
@@ -72,6 +73,7 @@
 | 
			
		||||
        "bn.js": "^4.11.8",
 | 
			
		||||
        "ethereumjs-abi": "^0.6.4",
 | 
			
		||||
        "ethereumjs-util": "^5.1.1",
 | 
			
		||||
        "ethers-contracts": "^2.2.1",
 | 
			
		||||
        "isomorphic-fetch": "^2.2.1",
 | 
			
		||||
        "lodash": "^4.17.4",
 | 
			
		||||
        "request": "^2.81.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1 @@
 | 
			
		||||
dummy_token.ts
 | 
			
		||||
exchange.ts
 | 
			
		||||
multi_sig_wallet_with_time_lock_except_remove_authorized_address.ts
 | 
			
		||||
multi_sig_wallet_with_time_lock.ts
 | 
			
		||||
multi_sig_wallet.ts
 | 
			
		||||
token_registry.ts
 | 
			
		||||
token_transfer_proxy.ts
 | 
			
		||||
zrx_token.ts
 | 
			
		||||
*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,35 +0,0 @@
 | 
			
		||||
import {TxData, TxDataPayable} from '@0xproject/types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
import * as Web3 from 'web3';
 | 
			
		||||
 | 
			
		||||
export class BaseContract {
 | 
			
		||||
    public address: string;
 | 
			
		||||
    protected _web3ContractInstance: Web3.ContractInstance;
 | 
			
		||||
    protected _defaults: Partial<TxData>;
 | 
			
		||||
    protected async _applyDefaultsToTxDataAsync<T extends TxData|TxDataPayable>(
 | 
			
		||||
        txData: T,
 | 
			
		||||
        estimateGasAsync?: (txData: T) => Promise<number>,
 | 
			
		||||
    ): Promise<TxData> {
 | 
			
		||||
        // Gas amount sourced with the following priorities:
 | 
			
		||||
        // 1. Optional param passed in to public method call
 | 
			
		||||
        // 2. Global config passed in at library instantiation
 | 
			
		||||
        // 3. Gas estimate calculation + safety margin
 | 
			
		||||
        const removeUndefinedProperties = _.pickBy;
 | 
			
		||||
        const txDataWithDefaults = {
 | 
			
		||||
            ...removeUndefinedProperties(this._defaults),
 | 
			
		||||
            ...removeUndefinedProperties(txData as any),
 | 
			
		||||
            // HACK: TS can't prove that T is spreadable.
 | 
			
		||||
            // Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
 | 
			
		||||
        };
 | 
			
		||||
        if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
 | 
			
		||||
            const estimatedGas = await estimateGasAsync(txData);
 | 
			
		||||
            txDataWithDefaults.gas = estimatedGas;
 | 
			
		||||
        }
 | 
			
		||||
        return txDataWithDefaults;
 | 
			
		||||
    }
 | 
			
		||||
    constructor(web3ContractInstance: Web3.ContractInstance, defaults?: Partial<TxData>) {
 | 
			
		||||
        this.address = web3ContractInstance.address;
 | 
			
		||||
        this._web3ContractInstance = web3ContractInstance;
 | 
			
		||||
        this._defaults = defaults || {};
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,12 +1,4 @@
 | 
			
		||||
import {
 | 
			
		||||
    LogCancelContractEventArgs,
 | 
			
		||||
    LogErrorContractEventArgs,
 | 
			
		||||
    LogFillContractEventArgs,
 | 
			
		||||
    LogWithDecodedArgs,
 | 
			
		||||
    SignedOrder,
 | 
			
		||||
    TransactionReceiptWithDecodedLogs,
 | 
			
		||||
    ZeroEx,
 | 
			
		||||
} from '0x.js';
 | 
			
		||||
import { LogWithDecodedArgs, SignedOrder, TransactionReceiptWithDecodedLogs, ZeroEx } from '0x.js';
 | 
			
		||||
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
 | 
			
		||||
import { BigNumber } from '@0xproject/utils';
 | 
			
		||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
 | 
			
		||||
@@ -15,7 +7,12 @@ import ethUtil = require('ethereumjs-util');
 | 
			
		||||
import * as Web3 from 'web3';
 | 
			
		||||
 | 
			
		||||
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
 | 
			
		||||
import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
 | 
			
		||||
import {
 | 
			
		||||
    ExchangeContract,
 | 
			
		||||
    LogCancelContractEventArgs,
 | 
			
		||||
    LogErrorContractEventArgs,
 | 
			
		||||
    LogFillContractEventArgs,
 | 
			
		||||
} from '../../src/contract_wrappers/generated/exchange';
 | 
			
		||||
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
 | 
			
		||||
import { Balances } from '../../util/balances';
 | 
			
		||||
import { constants } from '../../util/constants';
 | 
			
		||||
@@ -63,16 +60,20 @@ describe('Exchange', () => {
 | 
			
		||||
            deployer.deployAsync(ContractName.DummyToken),
 | 
			
		||||
            deployer.deployAsync(ContractName.DummyToken),
 | 
			
		||||
        ]);
 | 
			
		||||
        rep = new DummyTokenContract(repInstance);
 | 
			
		||||
        dgd = new DummyTokenContract(dgdInstance);
 | 
			
		||||
        zrx = new DummyTokenContract(zrxInstance);
 | 
			
		||||
        rep = new DummyTokenContract(web3Wrapper, repInstance.abi, repInstance.address);
 | 
			
		||||
        dgd = new DummyTokenContract(web3Wrapper, dgdInstance.abi, dgdInstance.address);
 | 
			
		||||
        zrx = new DummyTokenContract(web3Wrapper, zrxInstance.abi, zrxInstance.address);
 | 
			
		||||
        const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
 | 
			
		||||
        tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
 | 
			
		||||
        tokenTransferProxy = new TokenTransferProxyContract(
 | 
			
		||||
            web3Wrapper,
 | 
			
		||||
            tokenTransferProxyInstance.abi,
 | 
			
		||||
            tokenTransferProxyInstance.address,
 | 
			
		||||
        );
 | 
			
		||||
        const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [
 | 
			
		||||
            zrx.address,
 | 
			
		||||
            tokenTransferProxy.address,
 | 
			
		||||
        ]);
 | 
			
		||||
        exchange = new ExchangeContract(exchangeInstance);
 | 
			
		||||
        exchange = new ExchangeContract(web3Wrapper, exchangeInstance.abi, exchangeInstance.address);
 | 
			
		||||
        await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] });
 | 
			
		||||
        zeroEx = new ZeroEx(web3.currentProvider, {
 | 
			
		||||
            exchangeContractAddress: exchange.address,
 | 
			
		||||
@@ -650,7 +651,7 @@ describe('Exchange', () => {
 | 
			
		||||
 | 
			
		||||
        it('should not change balances if makerTokenAddress is ZRX, makerTokenAmount + makerFee > maker allowance, \
 | 
			
		||||
                and shouldThrowOnInsufficientBalanceOrAllowance = false', async () => {
 | 
			
		||||
            const makerZRXAllowance = await zrx.allowance(maker, tokenTransferProxy.address);
 | 
			
		||||
            const makerZRXAllowance = await zrx.allowance.callAsync(maker, tokenTransferProxy.address);
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync({
 | 
			
		||||
                makerTokenAddress: zrx.address,
 | 
			
		||||
                makerTokenAmount: new BigNumber(makerZRXAllowance),
 | 
			
		||||
@@ -676,7 +677,7 @@ describe('Exchange', () => {
 | 
			
		||||
 | 
			
		||||
        it('should not change balances if takerTokenAddress is ZRX, takerTokenAmount + takerFee > taker allowance, \
 | 
			
		||||
                and shouldThrowOnInsufficientBalanceOrAllowance = false', async () => {
 | 
			
		||||
            const takerZRXAllowance = await zrx.allowance(taker, tokenTransferProxy.address);
 | 
			
		||||
            const takerZRXAllowance = await zrx.allowance.callAsync(taker, tokenTransferProxy.address);
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync({
 | 
			
		||||
                takerTokenAddress: zrx.address,
 | 
			
		||||
                takerTokenAmount: new BigNumber(takerZRXAllowance),
 | 
			
		||||
@@ -723,7 +724,7 @@ describe('Exchange', () => {
 | 
			
		||||
            const res = await exWrapper.fillOrderAsync(signedOrder, taker);
 | 
			
		||||
            expect(res.logs).to.have.length(1);
 | 
			
		||||
            const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>;
 | 
			
		||||
            const errCode = log.args.errorId.toNumber();
 | 
			
		||||
            const errCode = log.args.errorId;
 | 
			
		||||
            expect(errCode).to.be.equal(ExchangeContractErrs.ERROR_ORDER_EXPIRED);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -734,7 +735,7 @@ describe('Exchange', () => {
 | 
			
		||||
            const res = await exWrapper.fillOrderAsync(signedOrder, taker);
 | 
			
		||||
            expect(res.logs).to.have.length(1);
 | 
			
		||||
            const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>;
 | 
			
		||||
            const errCode = log.args.errorId.toNumber();
 | 
			
		||||
            const errCode = log.args.errorId;
 | 
			
		||||
            expect(errCode).to.be.equal(ExchangeContractErrs.ERROR_ORDER_FULLY_FILLED_OR_CANCELLED);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
@@ -862,7 +863,7 @@ describe('Exchange', () => {
 | 
			
		||||
            const res = await exWrapper.cancelOrderAsync(signedOrder, maker);
 | 
			
		||||
            expect(res.logs).to.have.length(1);
 | 
			
		||||
            const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>;
 | 
			
		||||
            const errCode = log.args.errorId.toNumber();
 | 
			
		||||
            const errCode = log.args.errorId;
 | 
			
		||||
            expect(errCode).to.be.equal(ExchangeContractErrs.ERROR_ORDER_FULLY_FILLED_OR_CANCELLED);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -874,7 +875,7 @@ describe('Exchange', () => {
 | 
			
		||||
            const res = await exWrapper.cancelOrderAsync(signedOrder, maker);
 | 
			
		||||
            expect(res.logs).to.have.length(1);
 | 
			
		||||
            const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>;
 | 
			
		||||
            const errCode = log.args.errorId.toNumber();
 | 
			
		||||
            const errCode = log.args.errorId;
 | 
			
		||||
            expect(errCode).to.be.equal(ExchangeContractErrs.ERROR_ORDER_EXPIRED);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,12 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import ethUtil = require('ethereumjs-util');
 | 
			
		||||
 | 
			
		||||
import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
 | 
			
		||||
import {
 | 
			
		||||
    ExchangeContract,
 | 
			
		||||
    LogCancelContractEventArgs,
 | 
			
		||||
    LogErrorContractEventArgs,
 | 
			
		||||
    LogFillContractEventArgs,
 | 
			
		||||
} from '../../src/contract_wrappers/generated/exchange';
 | 
			
		||||
import { constants } from '../../util/constants';
 | 
			
		||||
import { ExchangeWrapper } from '../../util/exchange_wrapper';
 | 
			
		||||
import { OrderFactory } from '../../util/order_factory';
 | 
			
		||||
@@ -42,7 +47,7 @@ describe('Exchange', () => {
 | 
			
		||||
            zrx.address,
 | 
			
		||||
            tokenTransferProxy.address,
 | 
			
		||||
        ]);
 | 
			
		||||
        const exchange = new ExchangeContract(exchangeInstance);
 | 
			
		||||
        const exchange = new ExchangeContract(web3Wrapper, exchangeInstance.abi, exchangeInstance.address);
 | 
			
		||||
        await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] });
 | 
			
		||||
        const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID });
 | 
			
		||||
        exchangeWrapper = new ExchangeWrapper(exchange, zeroEx);
 | 
			
		||||
@@ -50,8 +55,8 @@ describe('Exchange', () => {
 | 
			
		||||
            exchangeContractAddress: exchange.address,
 | 
			
		||||
            maker,
 | 
			
		||||
            feeRecipient,
 | 
			
		||||
            makerToken: rep.address,
 | 
			
		||||
            takerToken: dgd.address,
 | 
			
		||||
            makerTokenAddress: rep.address,
 | 
			
		||||
            takerTokenAddress: dgd.address,
 | 
			
		||||
            makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
 | 
			
		||||
            takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
 | 
			
		||||
            makerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,12 @@ import * as _ from 'lodash';
 | 
			
		||||
import * as Web3 from 'web3';
 | 
			
		||||
 | 
			
		||||
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
 | 
			
		||||
import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
 | 
			
		||||
import {
 | 
			
		||||
    ExchangeContract,
 | 
			
		||||
    LogCancelContractEventArgs,
 | 
			
		||||
    LogErrorContractEventArgs,
 | 
			
		||||
    LogFillContractEventArgs,
 | 
			
		||||
} from '../../src/contract_wrappers/generated/exchange';
 | 
			
		||||
import { TokenRegistryContract } from '../../src/contract_wrappers/generated/token_registry';
 | 
			
		||||
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
 | 
			
		||||
import { Balances } from '../../util/balances';
 | 
			
		||||
@@ -55,18 +60,26 @@ describe('Exchange', () => {
 | 
			
		||||
            deployer.deployAsync(ContractName.DummyToken),
 | 
			
		||||
            deployer.deployAsync(ContractName.DummyToken),
 | 
			
		||||
        ]);
 | 
			
		||||
        rep = new DummyTokenContract(repInstance);
 | 
			
		||||
        dgd = new DummyTokenContract(dgdInstance);
 | 
			
		||||
        zrx = new DummyTokenContract(zrxInstance);
 | 
			
		||||
        rep = new DummyTokenContract(web3Wrapper, repInstance.abi, repInstance.address);
 | 
			
		||||
        dgd = new DummyTokenContract(web3Wrapper, dgdInstance.abi, dgdInstance.address);
 | 
			
		||||
        zrx = new DummyTokenContract(web3Wrapper, zrxInstance.abi, zrxInstance.address);
 | 
			
		||||
        const tokenRegistryInstance = await deployer.deployAsync(ContractName.TokenRegistry);
 | 
			
		||||
        tokenRegistry = new TokenRegistryContract(tokenRegistryInstance);
 | 
			
		||||
        tokenRegistry = new TokenRegistryContract(
 | 
			
		||||
            web3Wrapper,
 | 
			
		||||
            tokenRegistryInstance.abi,
 | 
			
		||||
            tokenRegistryInstance.address,
 | 
			
		||||
        );
 | 
			
		||||
        const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
 | 
			
		||||
        tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
 | 
			
		||||
        tokenTransferProxy = new TokenTransferProxyContract(
 | 
			
		||||
            web3Wrapper,
 | 
			
		||||
            tokenTransferProxyInstance.abi,
 | 
			
		||||
            tokenTransferProxyInstance.address,
 | 
			
		||||
        );
 | 
			
		||||
        const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [
 | 
			
		||||
            zrx.address,
 | 
			
		||||
            tokenTransferProxy.address,
 | 
			
		||||
        ]);
 | 
			
		||||
        exchange = new ExchangeContract(exchangeInstance);
 | 
			
		||||
        exchange = new ExchangeContract(web3Wrapper, exchangeInstance.abi, exchangeInstance.address);
 | 
			
		||||
        await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] });
 | 
			
		||||
        const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID });
 | 
			
		||||
        exWrapper = new ExchangeWrapper(exchange, zeroEx);
 | 
			
		||||
 
 | 
			
		||||
@@ -59,10 +59,14 @@ describe('MultiSigWalletWithTimeLock', () => {
 | 
			
		||||
                    SIGNATURES_REQUIRED,
 | 
			
		||||
                    0,
 | 
			
		||||
                ]);
 | 
			
		||||
                multiSig = new MultiSigWalletWithTimeLockContract(multiSigInstance);
 | 
			
		||||
                multiSig = new MultiSigWalletWithTimeLockContract(
 | 
			
		||||
                    web3Wrapper,
 | 
			
		||||
                    multiSigInstance.abi,
 | 
			
		||||
                    multiSigInstance.address,
 | 
			
		||||
                );
 | 
			
		||||
                multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract);
 | 
			
		||||
 | 
			
		||||
                const secondsTimeLocked = await multiSig.secondsTimeLocked();
 | 
			
		||||
                const secondsTimeLocked = await multiSig.secondsTimeLocked.callAsync();
 | 
			
		||||
                initialSecondsTimeLocked = secondsTimeLocked.toNumber();
 | 
			
		||||
            });
 | 
			
		||||
            it('should throw when not called by wallet', async () => {
 | 
			
		||||
@@ -113,7 +117,7 @@ describe('MultiSigWalletWithTimeLock', () => {
 | 
			
		||||
                const blockNum = await web3Wrapper.getBlockNumberAsync();
 | 
			
		||||
                const blockInfo = await web3Wrapper.getBlockAsync(blockNum);
 | 
			
		||||
                const timestamp = new BigNumber(blockInfo.timestamp);
 | 
			
		||||
                const confirmationTimeBigNum = new BigNumber(await multiSig.confirmationTimes(txId));
 | 
			
		||||
                const confirmationTimeBigNum = new BigNumber(await multiSig.confirmationTimes.callAsync(txId));
 | 
			
		||||
 | 
			
		||||
                expect(timestamp).to.be.bignumber.equal(confirmationTimeBigNum);
 | 
			
		||||
            });
 | 
			
		||||
@@ -141,7 +145,7 @@ describe('MultiSigWalletWithTimeLock', () => {
 | 
			
		||||
                const res = await zeroEx.awaitTransactionMinedAsync(txHash);
 | 
			
		||||
                expect(res.logs).to.have.length(2);
 | 
			
		||||
 | 
			
		||||
                const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked());
 | 
			
		||||
                const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.callAsync());
 | 
			
		||||
                expect(secondsTimeLocked).to.be.bignumber.equal(SECONDS_TIME_LOCKED);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
@@ -152,10 +156,14 @@ describe('MultiSigWalletWithTimeLock', () => {
 | 
			
		||||
                    SIGNATURES_REQUIRED,
 | 
			
		||||
                    SECONDS_TIME_LOCKED,
 | 
			
		||||
                ]);
 | 
			
		||||
                multiSig = new MultiSigWalletWithTimeLockContract(multiSigInstance);
 | 
			
		||||
                multiSig = new MultiSigWalletWithTimeLockContract(
 | 
			
		||||
                    web3Wrapper,
 | 
			
		||||
                    multiSigInstance.abi,
 | 
			
		||||
                    multiSigInstance.address,
 | 
			
		||||
                );
 | 
			
		||||
                multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract);
 | 
			
		||||
 | 
			
		||||
                const secondsTimeLocked = await multiSig.secondsTimeLocked();
 | 
			
		||||
                const secondsTimeLocked = await multiSig.secondsTimeLocked.callAsync();
 | 
			
		||||
                initialSecondsTimeLocked = secondsTimeLocked.toNumber();
 | 
			
		||||
                const destination = multiSig.address;
 | 
			
		||||
                const from = owners[0];
 | 
			
		||||
@@ -187,7 +195,7 @@ describe('MultiSigWalletWithTimeLock', () => {
 | 
			
		||||
                await rpc.increaseTimeAsync(SECONDS_TIME_LOCKED.toNumber());
 | 
			
		||||
                await multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] });
 | 
			
		||||
 | 
			
		||||
                const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked());
 | 
			
		||||
                const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.callAsync());
 | 
			
		||||
                expect(secondsTimeLocked).to.be.bignumber.equal(newSecondsTimeLocked);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,11 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
 | 
			
		||||
        [authorizedAddress, unauthorizedAddress] = accounts;
 | 
			
		||||
        const initialOwner = accounts[0];
 | 
			
		||||
        const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
 | 
			
		||||
        tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
 | 
			
		||||
        tokenTransferProxy = new TokenTransferProxyContract(
 | 
			
		||||
            web3Wrapper,
 | 
			
		||||
            tokenTransferProxyInstance.abi,
 | 
			
		||||
            tokenTransferProxyInstance.address,
 | 
			
		||||
        );
 | 
			
		||||
        await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(authorizedAddress, {
 | 
			
		||||
            from: initialOwner,
 | 
			
		||||
        });
 | 
			
		||||
@@ -57,7 +61,11 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
 | 
			
		||||
            ContractName.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,
 | 
			
		||||
            [owners, requiredApprovals, SECONDS_TIME_LOCKED, tokenTransferProxy.address],
 | 
			
		||||
        );
 | 
			
		||||
        multiSig = new MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract(multiSigInstance);
 | 
			
		||||
        multiSig = new MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract(
 | 
			
		||||
            web3Wrapper,
 | 
			
		||||
            multiSigInstance.abi,
 | 
			
		||||
            multiSigInstance.address,
 | 
			
		||||
        );
 | 
			
		||||
        await tokenTransferProxy.transferOwnership.sendTransactionAsync(multiSig.address, {
 | 
			
		||||
            from: initialOwner,
 | 
			
		||||
        });
 | 
			
		||||
@@ -74,12 +82,14 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
 | 
			
		||||
    describe('isFunctionRemoveAuthorizedAddress', () => {
 | 
			
		||||
        it('should throw if data is not for removeAuthorizedAddress', async () => {
 | 
			
		||||
            const data = MultiSigWrapper.encodeFnArgs('addAuthorizedAddress', PROXY_ABI, [owners[0]]);
 | 
			
		||||
            return expect(multiSig.isFunctionRemoveAuthorizedAddress(data)).to.be.rejectedWith(constants.REVERT);
 | 
			
		||||
            return expect(multiSig.isFunctionRemoveAuthorizedAddress.callAsync(data)).to.be.rejectedWith(
 | 
			
		||||
                constants.REVERT,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return true if data is for removeAuthorizedAddress', async () => {
 | 
			
		||||
            const data = MultiSigWrapper.encodeFnArgs('removeAuthorizedAddress', PROXY_ABI, [owners[0]]);
 | 
			
		||||
            const isFunctionRemoveAuthorizedAddress = await multiSig.isFunctionRemoveAuthorizedAddress(data);
 | 
			
		||||
            const isFunctionRemoveAuthorizedAddress = await multiSig.isFunctionRemoveAuthorizedAddress.callAsync(data);
 | 
			
		||||
            expect(isFunctionRemoveAuthorizedAddress).to.be.true();
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
@@ -114,7 +124,7 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
 | 
			
		||||
            const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
 | 
			
		||||
            const txId = log.args.transactionId;
 | 
			
		||||
            await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
 | 
			
		||||
            const isConfirmed = await multiSig.isConfirmed(txId);
 | 
			
		||||
            const isConfirmed = await multiSig.isConfirmed.callAsync(txId);
 | 
			
		||||
            expect(isConfirmed).to.be.true();
 | 
			
		||||
 | 
			
		||||
            return expect(
 | 
			
		||||
@@ -133,7 +143,7 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
 | 
			
		||||
            const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
 | 
			
		||||
            const txId = log.args.transactionId;
 | 
			
		||||
            await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
 | 
			
		||||
            const isConfirmed = await multiSig.isConfirmed(txId);
 | 
			
		||||
            const isConfirmed = await multiSig.isConfirmed.callAsync(txId);
 | 
			
		||||
            expect(isConfirmed).to.be.true();
 | 
			
		||||
 | 
			
		||||
            return expect(
 | 
			
		||||
@@ -152,10 +162,10 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
 | 
			
		||||
            const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
 | 
			
		||||
            const txId = log.args.transactionId;
 | 
			
		||||
            await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
 | 
			
		||||
            const isConfirmed = await multiSig.isConfirmed(txId);
 | 
			
		||||
            const isConfirmed = await multiSig.isConfirmed.callAsync(txId);
 | 
			
		||||
            expect(isConfirmed).to.be.true();
 | 
			
		||||
            await multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] });
 | 
			
		||||
            const isAuthorized = await tokenTransferProxy.authorized(authorizedAddress);
 | 
			
		||||
            const isAuthorized = await tokenTransferProxy.authorized.callAsync(authorizedAddress);
 | 
			
		||||
            expect(isAuthorized).to.be.false();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -170,10 +180,10 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
 | 
			
		||||
            const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
 | 
			
		||||
            const txId = log.args.transactionId;
 | 
			
		||||
            await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
 | 
			
		||||
            const isConfirmed = await multiSig.isConfirmed(txId);
 | 
			
		||||
            const isConfirmed = await multiSig.isConfirmed.callAsync(txId);
 | 
			
		||||
            expect(isConfirmed).to.be.true();
 | 
			
		||||
            await multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] });
 | 
			
		||||
            const tx = await multiSig.transactions(txId);
 | 
			
		||||
            const tx = await multiSig.transactions.callAsync(txId);
 | 
			
		||||
            const isExecuted = tx[3];
 | 
			
		||||
            expect(isExecuted).to.be.true();
 | 
			
		||||
            return expect(
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ describe('TokenRegistry', () => {
 | 
			
		||||
        owner = accounts[0];
 | 
			
		||||
        notOwner = accounts[1];
 | 
			
		||||
        const tokenRegInstance = await deployer.deployAsync(ContractName.TokenRegistry);
 | 
			
		||||
        tokenReg = new TokenRegistryContract(tokenRegInstance);
 | 
			
		||||
        tokenReg = new TokenRegistryContract(web3Wrapper, tokenRegInstance.abi, tokenRegInstance.address);
 | 
			
		||||
        tokenRegWrapper = new TokenRegWrapper(tokenReg);
 | 
			
		||||
    });
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,11 @@ describe('TokenTransferProxy', () => {
 | 
			
		||||
        owner = address = accounts[0];
 | 
			
		||||
        notOwner = accounts[1];
 | 
			
		||||
        const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
 | 
			
		||||
        tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
 | 
			
		||||
        tokenTransferProxy = new TokenTransferProxyContract(
 | 
			
		||||
            web3Wrapper,
 | 
			
		||||
            tokenTransferProxyInstance.abi,
 | 
			
		||||
            tokenTransferProxyInstance.address,
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
@@ -41,7 +45,7 @@ describe('TokenTransferProxy', () => {
 | 
			
		||||
        });
 | 
			
		||||
        it('should allow owner to add an authorized address', async () => {
 | 
			
		||||
            await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, { from: owner });
 | 
			
		||||
            const isAuthorized = await tokenTransferProxy.authorized(address);
 | 
			
		||||
            const isAuthorized = await tokenTransferProxy.authorized.callAsync(address);
 | 
			
		||||
            expect(isAuthorized).to.be.true();
 | 
			
		||||
        });
 | 
			
		||||
        it('should throw if owner attempts to authorize a duplicate address', async () => {
 | 
			
		||||
@@ -67,7 +71,7 @@ describe('TokenTransferProxy', () => {
 | 
			
		||||
            await tokenTransferProxy.removeAuthorizedAddress.sendTransactionAsync(address, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            const isAuthorized = await tokenTransferProxy.authorized(address);
 | 
			
		||||
            const isAuthorized = await tokenTransferProxy.authorized.callAsync(address);
 | 
			
		||||
            expect(isAuthorized).to.be.false();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -82,19 +86,19 @@ describe('TokenTransferProxy', () => {
 | 
			
		||||
 | 
			
		||||
    describe('getAuthorizedAddresses', () => {
 | 
			
		||||
        it('should return all authorized addresses', async () => {
 | 
			
		||||
            const initial = await tokenTransferProxy.getAuthorizedAddresses();
 | 
			
		||||
            const initial = await tokenTransferProxy.getAuthorizedAddresses.callAsync();
 | 
			
		||||
            expect(initial).to.have.length(0);
 | 
			
		||||
            await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            const afterAdd = await tokenTransferProxy.getAuthorizedAddresses();
 | 
			
		||||
            const afterAdd = await tokenTransferProxy.getAuthorizedAddresses.callAsync();
 | 
			
		||||
            expect(afterAdd).to.have.length(1);
 | 
			
		||||
            expect(afterAdd).to.include(address);
 | 
			
		||||
 | 
			
		||||
            await tokenTransferProxy.removeAuthorizedAddress.sendTransactionAsync(address, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            const afterRemove = await tokenTransferProxy.getAuthorizedAddresses();
 | 
			
		||||
            const afterRemove = await tokenTransferProxy.getAuthorizedAddresses.callAsync();
 | 
			
		||||
            expect(afterRemove).to.have.length(0);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -33,9 +33,13 @@ describe('TokenTransferProxy', () => {
 | 
			
		||||
        accounts = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
        owner = notAuthorized = accounts[0];
 | 
			
		||||
        const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
 | 
			
		||||
        tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
 | 
			
		||||
        tokenTransferProxy = new TokenTransferProxyContract(
 | 
			
		||||
            web3Wrapper,
 | 
			
		||||
            tokenTransferProxyInstance.abi,
 | 
			
		||||
            tokenTransferProxyInstance.address,
 | 
			
		||||
        );
 | 
			
		||||
        const repInstance = await deployer.deployAsync(ContractName.DummyToken);
 | 
			
		||||
        rep = new DummyTokenContract(repInstance);
 | 
			
		||||
        rep = new DummyTokenContract(web3Wrapper, repInstance.abi, repInstance.address);
 | 
			
		||||
 | 
			
		||||
        dmyBalances = new Balances([rep], [accounts[0], accounts[1]]);
 | 
			
		||||
        await Promise.all([
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ describe('UnlimitedAllowanceToken', () => {
 | 
			
		||||
        owner = accounts[0];
 | 
			
		||||
        spender = accounts[1];
 | 
			
		||||
        const tokenInstance = await deployer.deployAsync(ContractName.DummyToken);
 | 
			
		||||
        token = new DummyTokenContract(tokenInstance);
 | 
			
		||||
        token = new DummyTokenContract(web3Wrapper, tokenInstance.abi, tokenInstance.address);
 | 
			
		||||
        await token.mint.sendTransactionAsync(MAX_MINT_VALUE, { from: owner });
 | 
			
		||||
        tokenAddress = token.address;
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,7 @@ describe('ZRXToken', () => {
 | 
			
		||||
            networkId: constants.TESTRPC_NETWORK_ID,
 | 
			
		||||
        });
 | 
			
		||||
        const zrxInstance = await deployer.deployAsync(ContractName.ZRXToken);
 | 
			
		||||
        zrx = new ZRXTokenContract(zrxInstance);
 | 
			
		||||
        zrx = new ZRXTokenContract(web3Wrapper, zrxInstance.abi, zrxInstance.address);
 | 
			
		||||
        zrxAddress = zrx.address;
 | 
			
		||||
        MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
 | 
			
		||||
    });
 | 
			
		||||
@@ -48,25 +48,25 @@ describe('ZRXToken', () => {
 | 
			
		||||
    });
 | 
			
		||||
    describe('constants', () => {
 | 
			
		||||
        it('should have 18 decimals', async () => {
 | 
			
		||||
            const decimals = new BigNumber(await zrx.decimals());
 | 
			
		||||
            const decimals = new BigNumber(await zrx.decimals.callAsync());
 | 
			
		||||
            const expectedDecimals = 18;
 | 
			
		||||
            expect(decimals).to.be.bignumber.equal(expectedDecimals);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should have a total supply of 1 billion tokens', async () => {
 | 
			
		||||
            const totalSupply = new BigNumber(await zrx.totalSupply());
 | 
			
		||||
            const totalSupply = new BigNumber(await zrx.totalSupply.callAsync());
 | 
			
		||||
            const expectedTotalSupply = 1000000000;
 | 
			
		||||
            expect(ZeroEx.toUnitAmount(totalSupply, 18)).to.be.bignumber.equal(expectedTotalSupply);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should be named 0x Protocol Token', async () => {
 | 
			
		||||
            const name = await zrx.name();
 | 
			
		||||
            const name = await zrx.name.callAsync();
 | 
			
		||||
            const expectedName = '0x Protocol Token';
 | 
			
		||||
            expect(name).to.be.equal(expectedName);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should have the symbol ZRX', async () => {
 | 
			
		||||
            const symbol = await zrx.symbol();
 | 
			
		||||
            const symbol = await zrx.symbol.callAsync();
 | 
			
		||||
            const expectedSymbol = 'ZRX';
 | 
			
		||||
            expect(symbol).to.be.equal(expectedSymbol);
 | 
			
		||||
        });
 | 
			
		||||
@@ -75,7 +75,7 @@ describe('ZRXToken', () => {
 | 
			
		||||
    describe('constructor', () => {
 | 
			
		||||
        it('should initialize owner balance to totalSupply', async () => {
 | 
			
		||||
            const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
 | 
			
		||||
            const totalSupply = new BigNumber(await zrx.totalSupply());
 | 
			
		||||
            const totalSupply = new BigNumber(await zrx.totalSupply.callAsync());
 | 
			
		||||
            expect(totalSupply).to.be.bignumber.equal(ownerBalance);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@
 | 
			
		||||
        "../../node_modules/types-ethereumjs-util/index.d.ts",
 | 
			
		||||
        "../../node_modules/chai-typescript-typings/index.d.ts",
 | 
			
		||||
        "../../node_modules/web3-typescript-typings/index.d.ts",
 | 
			
		||||
        "../../node_modules/ethers-typescript-typings/index.d.ts",
 | 
			
		||||
        "../../node_modules/chai-as-promised-typescript-typings/index.d.ts",
 | 
			
		||||
        "../../node_modules/types-ethereumjs-util/index.d.ts",
 | 
			
		||||
        "../../node_modules/types-bn/index.d.ts",
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ export class Balances {
 | 
			
		||||
        const balancesByOwner: BalancesByOwner = {};
 | 
			
		||||
        for (const tokenContractInstance of this._tokenContractInstances) {
 | 
			
		||||
            for (const ownerAddress of this._ownerAddresses) {
 | 
			
		||||
                let balance = await tokenContractInstance.balanceOf(ownerAddress);
 | 
			
		||||
                let balance = await tokenContractInstance.balanceOf.callAsync(ownerAddress);
 | 
			
		||||
                balance = new BigNumber(balance);
 | 
			
		||||
                if (_.isUndefined(balancesByOwner[ownerAddress])) {
 | 
			
		||||
                    balancesByOwner[ownerAddress] = {};
 | 
			
		||||
 
 | 
			
		||||
@@ -186,11 +186,11 @@ export class ExchangeWrapper {
 | 
			
		||||
    public async getOrderHashAsync(signedOrder: SignedOrder): Promise<string> {
 | 
			
		||||
        const shouldThrowOnInsufficientBalanceOrAllowance = false;
 | 
			
		||||
        const params = signedOrderUtils.getOrderAddressesAndValues(signedOrder);
 | 
			
		||||
        const orderHash = await this._exchange.getOrderHash(params.orderAddresses, params.orderValues);
 | 
			
		||||
        const orderHash = await this._exchange.getOrderHash.callAsync(params.orderAddresses, params.orderValues);
 | 
			
		||||
        return orderHash;
 | 
			
		||||
    }
 | 
			
		||||
    public async isValidSignatureAsync(signedOrder: SignedOrder): Promise<boolean> {
 | 
			
		||||
        const isValidSignature = await this._exchange.isValidSignature(
 | 
			
		||||
        const isValidSignature = await this._exchange.isValidSignature.callAsync(
 | 
			
		||||
            signedOrder.maker,
 | 
			
		||||
            ZeroEx.getOrderHashHex(signedOrder),
 | 
			
		||||
            signedOrder.ecSignature.v,
 | 
			
		||||
@@ -204,7 +204,7 @@ export class ExchangeWrapper {
 | 
			
		||||
        denominator: BigNumber,
 | 
			
		||||
        target: BigNumber,
 | 
			
		||||
    ): Promise<boolean> {
 | 
			
		||||
        const isRoundingError = await this._exchange.isRoundingError(numerator, denominator, target);
 | 
			
		||||
        const isRoundingError = await this._exchange.isRoundingError.callAsync(numerator, denominator, target);
 | 
			
		||||
        return isRoundingError;
 | 
			
		||||
    }
 | 
			
		||||
    public async getPartialAmountAsync(
 | 
			
		||||
@@ -212,7 +212,9 @@ export class ExchangeWrapper {
 | 
			
		||||
        denominator: BigNumber,
 | 
			
		||||
        target: BigNumber,
 | 
			
		||||
    ): Promise<BigNumber> {
 | 
			
		||||
        const partialAmount = new BigNumber(await this._exchange.getPartialAmount(numerator, denominator, target));
 | 
			
		||||
        const partialAmount = new BigNumber(
 | 
			
		||||
            await this._exchange.getPartialAmount.callAsync(numerator, denominator, target),
 | 
			
		||||
        );
 | 
			
		||||
        return partialAmount;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,36 +22,36 @@ export class TokenRegWrapper {
 | 
			
		||||
        return tx;
 | 
			
		||||
    }
 | 
			
		||||
    public async getTokenMetaDataAsync(tokenAddress: string) {
 | 
			
		||||
        const data = await this._tokenReg.getTokenMetaData(tokenAddress);
 | 
			
		||||
        const data = await this._tokenReg.getTokenMetaData.callAsync(tokenAddress);
 | 
			
		||||
        const token: Token = {
 | 
			
		||||
            address: data[0],
 | 
			
		||||
            name: data[1],
 | 
			
		||||
            symbol: data[2],
 | 
			
		||||
            decimals: data[3].toNumber(),
 | 
			
		||||
            decimals: data[3],
 | 
			
		||||
            ipfsHash: data[4],
 | 
			
		||||
            swarmHash: data[5],
 | 
			
		||||
        };
 | 
			
		||||
        return token;
 | 
			
		||||
    }
 | 
			
		||||
    public async getTokenByNameAsync(tokenName: string) {
 | 
			
		||||
        const data = await this._tokenReg.getTokenByName(tokenName);
 | 
			
		||||
        const data = await this._tokenReg.getTokenByName.callAsync(tokenName);
 | 
			
		||||
        const token: Token = {
 | 
			
		||||
            address: data[0],
 | 
			
		||||
            name: data[1],
 | 
			
		||||
            symbol: data[2],
 | 
			
		||||
            decimals: data[3].toNumber(),
 | 
			
		||||
            decimals: data[3],
 | 
			
		||||
            ipfsHash: data[4],
 | 
			
		||||
            swarmHash: data[5],
 | 
			
		||||
        };
 | 
			
		||||
        return token;
 | 
			
		||||
    }
 | 
			
		||||
    public async getTokenBySymbolAsync(tokenSymbol: string) {
 | 
			
		||||
        const data = await this._tokenReg.getTokenBySymbol(tokenSymbol);
 | 
			
		||||
        const data = await this._tokenReg.getTokenBySymbol.callAsync(tokenSymbol);
 | 
			
		||||
        const token: Token = {
 | 
			
		||||
            address: data[0],
 | 
			
		||||
            name: data[1],
 | 
			
		||||
            symbol: data[2],
 | 
			
		||||
            decimals: data[3].toNumber(),
 | 
			
		||||
            decimals: data[3],
 | 
			
		||||
            ipfsHash: data[4],
 | 
			
		||||
            swarmHash: data[5],
 | 
			
		||||
        };
 | 
			
		||||
 
 | 
			
		||||
@@ -41,8 +41,8 @@ export interface DefaultOrderParams {
 | 
			
		||||
    exchangeContractAddress: string;
 | 
			
		||||
    maker: string;
 | 
			
		||||
    feeRecipient: string;
 | 
			
		||||
    makerToken: string;
 | 
			
		||||
    takerToken: string;
 | 
			
		||||
    makerTokenAddress: string;
 | 
			
		||||
    takerTokenAddress: string;
 | 
			
		||||
    makerTokenAmount: BigNumber;
 | 
			
		||||
    takerTokenAmount: BigNumber;
 | 
			
		||||
    makerFee: BigNumber;
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,7 @@
 | 
			
		||||
        "tslint": "5.8.0",
 | 
			
		||||
        "types-bn": "^0.0.1",
 | 
			
		||||
        "typescript": "2.7.1",
 | 
			
		||||
        "ethers-typescript-typings": "^0.0.1",
 | 
			
		||||
        "web3-typescript-typings": "^0.9.11"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
 
 | 
			
		||||
@@ -10,8 +10,8 @@ import { constants } from './utils/constants';
 | 
			
		||||
import { CliOptions, CompilerOptions, DeployerOptions } from './utils/types';
 | 
			
		||||
 | 
			
		||||
const DEFAULT_OPTIMIZER_ENABLED = false;
 | 
			
		||||
const DEFAULT_CONTRACTS_DIR = path.resolve('src');
 | 
			
		||||
const DEFAULT_ARTIFACTS_DIR = path.resolve('artifacts');
 | 
			
		||||
const DEFAULT_CONTRACTS_DIR = path.resolve('src/contracts');
 | 
			
		||||
const DEFAULT_ARTIFACTS_DIR = path.resolve('src/artifacts');
 | 
			
		||||
const DEFAULT_NETWORK_ID = 50;
 | 
			
		||||
const DEFAULT_JSONRPC_PORT = 8545;
 | 
			
		||||
const DEFAULT_GAS_PRICE = (10 ** 9 * 2).toString();
 | 
			
		||||
@@ -100,6 +100,9 @@ async function onDeployCommand(argv: CliOptions): Promise<void> {
 | 
			
		||||
 */
 | 
			
		||||
function getContractsSetFromList(contracts: string): Set<string> {
 | 
			
		||||
    const specifiedContracts = new Set();
 | 
			
		||||
    if (contracts === '*') {
 | 
			
		||||
        return new Set(['*']);
 | 
			
		||||
    }
 | 
			
		||||
    const contractsArray = contracts.split(',');
 | 
			
		||||
    _.forEach(contractsArray, contractName => {
 | 
			
		||||
        const fileName = `${contractName}${constants.SOLIDITY_FILE_EXTENSION}`;
 | 
			
		||||
 
 | 
			
		||||
@@ -174,7 +174,7 @@ export class Deployer {
 | 
			
		||||
        const block = await this.web3Wrapper.getBlockAsync('latest');
 | 
			
		||||
        let gas: number;
 | 
			
		||||
        try {
 | 
			
		||||
            const gasEstimate: number = await this.web3Wrapper.estimateGasAsync(data);
 | 
			
		||||
            const gasEstimate: number = await this.web3Wrapper.estimateGasAsync({ data });
 | 
			
		||||
            gas = Math.min(gasEstimate + EXTRA_GAS, block.gasLimit);
 | 
			
		||||
        } catch (err) {
 | 
			
		||||
            gas = block.gasLimit;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@
 | 
			
		||||
        "../../node_modules/types-bn/index.d.ts",
 | 
			
		||||
        "../../node_modules/types-ethereumjs-util/index.d.ts",
 | 
			
		||||
        "../../node_modules/chai-typescript-typings/index.d.ts",
 | 
			
		||||
        "../../node_modules/ethers-typescript-typings/index.d.ts",
 | 
			
		||||
        "../../node_modules/web3-typescript-typings/index.d.ts"
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@
 | 
			
		||||
        "./test/**/*",
 | 
			
		||||
        "../../node_modules/types-bn/index.d.ts",
 | 
			
		||||
        "../../node_modules/chai-typescript-typings/index.d.ts",
 | 
			
		||||
        "../../node_modules/ethers-typescript-typings/index.d.ts",
 | 
			
		||||
        "../../node_modules/web3-typescript-typings/index.d.ts",
 | 
			
		||||
        "../../node_modules/types-ethereumjs-util/index.d.ts"
 | 
			
		||||
    ]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								packages/ethers-typescript-typings/.npmignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								packages/ethers-typescript-typings/.npmignore
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
.*
 | 
			
		||||
yarn-error.log
 | 
			
		||||
/scripts/
 | 
			
		||||
							
								
								
									
										5
									
								
								packages/ethers-typescript-typings/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								packages/ethers-typescript-typings/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
# CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v0.0.1 - _TBD, 2018_
 | 
			
		||||
 | 
			
		||||
    * Initial types (#413)
 | 
			
		||||
							
								
								
									
										49
									
								
								packages/ethers-typescript-typings/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								packages/ethers-typescript-typings/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
## ethers-typescript-typings
 | 
			
		||||
 | 
			
		||||
There currently isn't an official [Ethers][ethers]
 | 
			
		||||
type definition included in the [DefinitelyTyped][definitelytyped] project.
 | 
			
		||||
Until that happens, we will continue to improve our own type definition.
 | 
			
		||||
If it get's close to comprehensive, we'll add it to [DefinitelyTyped][definitelytyped].
 | 
			
		||||
 | 
			
		||||
[ethers]: https://github.com/ethers-io/ethers.js
 | 
			
		||||
[definitelytyped]: https://github.com/DefinitelyTyped/DefinitelyTyped
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
yarn add -D ethers-typescript-typings
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
Add the following line within an `include` section of your `tsconfig.json`
 | 
			
		||||
 | 
			
		||||
```json
 | 
			
		||||
"./node_modules/ethers-typescript-typings/index.d.ts"
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Contributing
 | 
			
		||||
 | 
			
		||||
We strongly encourage that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
 | 
			
		||||
 | 
			
		||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
 | 
			
		||||
 | 
			
		||||
### Install Dependencies
 | 
			
		||||
 | 
			
		||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
yarn config set workspaces-experimental true
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Then install dependencies
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
yarn install
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Lint
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
yarn lint
 | 
			
		||||
```
 | 
			
		||||
							
								
								
									
										28
									
								
								packages/ethers-typescript-typings/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								packages/ethers-typescript-typings/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
declare module 'ethers-contracts' {
 | 
			
		||||
    export interface TransactionDescription {
 | 
			
		||||
        name: string;
 | 
			
		||||
        signature: string;
 | 
			
		||||
        sighash: string;
 | 
			
		||||
        data: string;
 | 
			
		||||
    }
 | 
			
		||||
    export interface CallDescription extends TransactionDescription {
 | 
			
		||||
        parse: (...args: any[]) => any;
 | 
			
		||||
    }
 | 
			
		||||
    export interface FunctionDescription {
 | 
			
		||||
        (...params: any[]): TransactionDescription | CallDescription;
 | 
			
		||||
        inputs: { names: string[]; types: string[] };
 | 
			
		||||
        outputs: { names: string[]; types: string[] };
 | 
			
		||||
    }
 | 
			
		||||
    export interface EventDescription {
 | 
			
		||||
        parse: (...args: any[]) => any;
 | 
			
		||||
        inputs: { names: string[]; types: string[] };
 | 
			
		||||
        signature: string;
 | 
			
		||||
        topic: string;
 | 
			
		||||
    }
 | 
			
		||||
    export class Interface {
 | 
			
		||||
        public functions: { [functionName: string]: FunctionDescription };
 | 
			
		||||
        public events: { [eventName: string]: EventDescription };
 | 
			
		||||
        public static decodeParams(types: string[], data: string): any[];
 | 
			
		||||
        constructor(abi: any);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								packages/ethers-typescript-typings/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								packages/ethers-typescript-typings/package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "ethers-typescript-typings",
 | 
			
		||||
    "version": "0.0.1",
 | 
			
		||||
    "description": "Typescript type definitions for ethers.js",
 | 
			
		||||
    "main": "index.d.ts",
 | 
			
		||||
    "types": "index.d.ts",
 | 
			
		||||
    "scripts": {
 | 
			
		||||
        "lint": "tslint index.d.ts"
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
        "type": "git",
 | 
			
		||||
        "url": "git+https://github.com/0xProject/0x.js.git"
 | 
			
		||||
    },
 | 
			
		||||
    "author": "Fabio Berger",
 | 
			
		||||
    "contributors": [
 | 
			
		||||
        "Leonid Logvinov <logvinov.leon@gmail.com>"
 | 
			
		||||
    ],
 | 
			
		||||
    "license": "Apache-2.0",
 | 
			
		||||
    "bugs": {
 | 
			
		||||
        "url": "https://github.com/0xProject/0x.js/issues"
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x.js/packages/ethers-typescript-typings#readme",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "tslint": "5.8.0",
 | 
			
		||||
        "tslint-config-0xproject": "^0.0.2",
 | 
			
		||||
        "typescript": "2.7.1"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,5 @@
 | 
			
		||||
const postpublish_utils = require('../../../scripts/postpublish_utils');
 | 
			
		||||
const packageJSON = require('../package.json');
 | 
			
		||||
 | 
			
		||||
const subPackageName = packageJSON.name;
 | 
			
		||||
postpublish_utils.standardPostPublishAsync(subPackageName);
 | 
			
		||||
							
								
								
									
										3
									
								
								packages/ethers-typescript-typings/tslint.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								packages/ethers-typescript-typings/tslint.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
{
 | 
			
		||||
    "extends": ["tslint-config-0xproject"]
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,10 @@
 | 
			
		||||
# CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v0.2.4 - _TBD, 2018_
 | 
			
		||||
 | 
			
		||||
    * Add `data` to `TxData` (#413)
 | 
			
		||||
    * Add `number` as an option to `ContractEventArg` (#413)
 | 
			
		||||
 | 
			
		||||
## v0.2.1 - _February 9, 2018_
 | 
			
		||||
 | 
			
		||||
    * Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ import { BigNumber } from 'bignumber.js';
 | 
			
		||||
import * as Web3 from 'web3';
 | 
			
		||||
 | 
			
		||||
export interface TxData {
 | 
			
		||||
    data?: string;
 | 
			
		||||
    from?: string;
 | 
			
		||||
    gas?: number;
 | 
			
		||||
    gasPrice?: BigNumber;
 | 
			
		||||
@@ -38,7 +39,7 @@ export enum AbiType {
 | 
			
		||||
    Fallback = 'fallback',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type ContractEventArg = string | BigNumber;
 | 
			
		||||
export type ContractEventArg = string | BigNumber | number;
 | 
			
		||||
 | 
			
		||||
export interface DecodedLogArgs {
 | 
			
		||||
    [argName: string]: ContractEventArg;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,9 @@
 | 
			
		||||
# CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v0.4.0 - _TBD, 2018_
 | 
			
		||||
 | 
			
		||||
    * Use `ethers-contracts` as a backend to decode event args (#413)
 | 
			
		||||
 | 
			
		||||
## v0.3.2 - _February 9, 2018_
 | 
			
		||||
 | 
			
		||||
    * Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
 | 
			
		||||
 
 | 
			
		||||
@@ -26,11 +26,13 @@
 | 
			
		||||
        "shx": "^0.2.2",
 | 
			
		||||
        "tslint": "5.8.0",
 | 
			
		||||
        "typescript": "2.7.1",
 | 
			
		||||
        "ethers-typescript-typings": "^0.0.1",
 | 
			
		||||
        "web3-typescript-typings": "^0.9.11"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0xproject/types": "^0.2.3",
 | 
			
		||||
        "bignumber.js": "~4.1.0",
 | 
			
		||||
        "ethers-contracts": "^2.2.1",
 | 
			
		||||
        "js-sha3": "^0.7.0",
 | 
			
		||||
        "lodash": "^4.17.4",
 | 
			
		||||
        "web3": "^0.20.0"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
import { AbiType, DecodedLogArgs, LogWithDecodedArgs, RawLog, SolidityTypes } from '@0xproject/types';
 | 
			
		||||
import * as ethersContracts from 'ethers-contracts';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
import * as Web3 from 'web3';
 | 
			
		||||
import * as SolidityCoder from 'web3/lib/solidity/coder';
 | 
			
		||||
 | 
			
		||||
import { BigNumber } from './configured_bignumber';
 | 
			
		||||
 | 
			
		||||
@@ -27,31 +27,29 @@ export class AbiDecoder {
 | 
			
		||||
        if (_.isUndefined(event)) {
 | 
			
		||||
            return log;
 | 
			
		||||
        }
 | 
			
		||||
        const ethersInterface = new ethersContracts.Interface([event]);
 | 
			
		||||
        const logData = log.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('0x'.length));
 | 
			
		||||
        const decodedData = ethersInterface.events[event.name].parse(log.data);
 | 
			
		||||
 | 
			
		||||
        let failedToDecode = false;
 | 
			
		||||
        _.forEach(event.inputs, (param: Web3.EventParameter) => {
 | 
			
		||||
        _.forEach(event.inputs, (param: Web3.EventParameter, i: number) => {
 | 
			
		||||
            // Indexed parameters are stored in topics. Non-indexed ones in decodedData
 | 
			
		||||
            let value: BigNumber | string = param.indexed ? log.topics[topicsIndex++] : decodedData[dataIndex++];
 | 
			
		||||
            let value: BigNumber | string | number = param.indexed ? log.topics[topicsIndex++] : decodedData[i];
 | 
			
		||||
            if (_.isUndefined(value)) {
 | 
			
		||||
                failedToDecode = true;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (param.type === SolidityTypes.Address) {
 | 
			
		||||
                value = AbiDecoder._padZeros(new BigNumber(value).toString(16));
 | 
			
		||||
            } else if (
 | 
			
		||||
                param.type === SolidityTypes.Uint256 ||
 | 
			
		||||
                param.type === SolidityTypes.Uint8 ||
 | 
			
		||||
                param.type === SolidityTypes.Uint
 | 
			
		||||
            ) {
 | 
			
		||||
            } else if (param.type === SolidityTypes.Uint256 || param.type === SolidityTypes.Uint) {
 | 
			
		||||
                value = new BigNumber(value);
 | 
			
		||||
            } else if (param.type === SolidityTypes.Uint8) {
 | 
			
		||||
                value = new BigNumber(value).toNumber();
 | 
			
		||||
            }
 | 
			
		||||
            decodedParams[param.name] = value;
 | 
			
		||||
        });
 | 
			
		||||
@@ -67,11 +65,14 @@ export class AbiDecoder {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    private _addABI(abiArray: Web3.AbiDefinition[]): void {
 | 
			
		||||
        if (_.isUndefined(abiArray)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        const ethersInterface = new ethersContracts.Interface(abiArray);
 | 
			
		||||
        _.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;
 | 
			
		||||
                const topic = ethersInterface.events[abi.name].topic;
 | 
			
		||||
                this._methodIds[topic] = abi;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        this._savedABIs = this._savedABIs.concat(abiArray);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								packages/utils/src/globals.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								packages/utils/src/globals.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +0,0 @@
 | 
			
		||||
declare module 'web3/lib/solidity/coder' {
 | 
			
		||||
    const decodeParams: (types: string[], data: string) => any[];
 | 
			
		||||
}
 | 
			
		||||
@@ -3,5 +3,9 @@
 | 
			
		||||
    "compilerOptions": {
 | 
			
		||||
        "outDir": "lib"
 | 
			
		||||
    },
 | 
			
		||||
    "include": ["./src/**/*", "../../node_modules/web3-typescript-typings/index.d.ts"]
 | 
			
		||||
    "include": [
 | 
			
		||||
        "./src/**/*",
 | 
			
		||||
        "../../node_modules/web3-typescript-typings/index.d.ts",
 | 
			
		||||
        "../../node_modules/ethers-typescript-typings/index.d.ts"
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,12 @@
 | 
			
		||||
# CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v0.2.XX - _TBD_ 2018
 | 
			
		||||
## v0.2.0 _TBD, 2018_
 | 
			
		||||
 | 
			
		||||
    * Ensure all returned user addresses are lowercase (#373)
 | 
			
		||||
    * Add `web3Wrapper.callAsync` (#413)
 | 
			
		||||
    * Make `web3Wrapper.estimateGas` accept whole `txData` instead of `data` (#413)
 | 
			
		||||
    * Remove `web3Wrapper.getContractInstance` (#413)
 | 
			
		||||
 | 
			
		||||
## v0.1.12 - _February 9, 2018_
 | 
			
		||||
## v0.1.12 _February 9, 2018_
 | 
			
		||||
 | 
			
		||||
    * Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
 | 
			
		||||
 
 | 
			
		||||
@@ -26,11 +26,13 @@
 | 
			
		||||
        "shx": "^0.2.2",
 | 
			
		||||
        "tslint": "5.8.0",
 | 
			
		||||
        "typescript": "2.7.1",
 | 
			
		||||
        "ethers-typescript-typings": "^0.0.1",
 | 
			
		||||
        "web3-typescript-typings": "^0.9.11"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0xproject/types": "^0.2.3",
 | 
			
		||||
        "@0xproject/utils": "^0.3.4",
 | 
			
		||||
        "ethers-contracts": "^2.2.1",
 | 
			
		||||
        "lodash": "^4.17.4",
 | 
			
		||||
        "web3": "^0.20.0"
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										69
									
								
								packages/web3-wrapper/src/base_contract.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								packages/web3-wrapper/src/base_contract.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
import { TxData, TxDataPayable } from '@0xproject/types';
 | 
			
		||||
import * as ethersContracts from 'ethers-contracts';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
import * as Web3 from 'web3';
 | 
			
		||||
 | 
			
		||||
import { Web3Wrapper } from './web3_wrapper';
 | 
			
		||||
 | 
			
		||||
export class BaseContract {
 | 
			
		||||
    protected _ethersInterface: ethersContracts.Interface;
 | 
			
		||||
    protected _web3Wrapper: Web3Wrapper;
 | 
			
		||||
    public abi: Web3.ContractAbi;
 | 
			
		||||
    public address: string;
 | 
			
		||||
    protected static _transformABIData(
 | 
			
		||||
        abis: Web3.DataItem[],
 | 
			
		||||
        values: any[],
 | 
			
		||||
        transformation: (type: string, value: any) => any,
 | 
			
		||||
    ): any {
 | 
			
		||||
        return _.map(values, (value: any, i: number) =>
 | 
			
		||||
            BaseContract._transformTypedData(abis[i].type, value, transformation),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    protected static _lowercaseAddress(type: string, value: string): string {
 | 
			
		||||
        return type === 'address' ? value.toLowerCase() : value;
 | 
			
		||||
    }
 | 
			
		||||
    protected static _bigNumberToString(type: string, value: string): string {
 | 
			
		||||
        return _.isObject(value) && (value as any).isBigNumber ? value.toString() : value;
 | 
			
		||||
    }
 | 
			
		||||
    private static _transformTypedData(
 | 
			
		||||
        type: string,
 | 
			
		||||
        values: any,
 | 
			
		||||
        transformation: (type: string, value: any) => any,
 | 
			
		||||
    ): any {
 | 
			
		||||
        const trailingArrayRegex = /\[\d*\]$/;
 | 
			
		||||
        if (type.match(trailingArrayRegex)) {
 | 
			
		||||
            const arrayItemType = type.replace(trailingArrayRegex, '');
 | 
			
		||||
            return _.map(values, value => this._transformTypedData(arrayItemType, value, transformation));
 | 
			
		||||
        } else {
 | 
			
		||||
            return transformation(type, values);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    protected async _applyDefaultsToTxDataAsync<T extends Partial<TxData | TxDataPayable>>(
 | 
			
		||||
        txData: T,
 | 
			
		||||
        estimateGasAsync?: (txData: T) => Promise<number>,
 | 
			
		||||
    ): Promise<TxData> {
 | 
			
		||||
        // Gas amount sourced with the following priorities:
 | 
			
		||||
        // 1. Optional param passed in to public method call
 | 
			
		||||
        // 2. Global config passed in at library instantiation
 | 
			
		||||
        // 3. Gas estimate calculation + safety margin
 | 
			
		||||
        const removeUndefinedProperties = _.pickBy;
 | 
			
		||||
        const txDataWithDefaults = {
 | 
			
		||||
            to: this.address,
 | 
			
		||||
            ...removeUndefinedProperties(this._web3Wrapper.getContractDefaults()),
 | 
			
		||||
            ...removeUndefinedProperties(txData as any),
 | 
			
		||||
            // HACK: TS can't prove that T is spreadable.
 | 
			
		||||
            // Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
 | 
			
		||||
        };
 | 
			
		||||
        if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
 | 
			
		||||
            const estimatedGas = await estimateGasAsync(txData);
 | 
			
		||||
            txDataWithDefaults.gas = estimatedGas;
 | 
			
		||||
        }
 | 
			
		||||
        return txDataWithDefaults;
 | 
			
		||||
    }
 | 
			
		||||
    constructor(web3Wrapper: Web3Wrapper, abi: Web3.ContractAbi, address: string) {
 | 
			
		||||
        this._web3Wrapper = web3Wrapper;
 | 
			
		||||
        this.abi = abi;
 | 
			
		||||
        this.address = address;
 | 
			
		||||
        this._ethersInterface = new ethersContracts.Interface(abi);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,179 +1,2 @@
 | 
			
		||||
import { TransactionReceipt, TxData } from '@0xproject/types';
 | 
			
		||||
import { BigNumber, promisify } from '@0xproject/utils';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
import * as Web3 from 'web3';
 | 
			
		||||
 | 
			
		||||
interface RawLogEntry {
 | 
			
		||||
    logIndex: string | null;
 | 
			
		||||
    transactionIndex: string | null;
 | 
			
		||||
    transactionHash: string;
 | 
			
		||||
    blockHash: string | null;
 | 
			
		||||
    blockNumber: string | null;
 | 
			
		||||
    address: string;
 | 
			
		||||
    data: string;
 | 
			
		||||
    topics: string[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class Web3Wrapper {
 | 
			
		||||
    private _web3: Web3;
 | 
			
		||||
    private _defaults: Partial<TxData>;
 | 
			
		||||
    private _jsonRpcRequestId: number;
 | 
			
		||||
    constructor(provider: Web3.Provider, defaults?: Partial<TxData>) {
 | 
			
		||||
        if (_.isUndefined((provider as any).sendAsync)) {
 | 
			
		||||
            // Web3@1.0 provider doesn't support synchronous http requests,
 | 
			
		||||
            // so it only has an async `send` method, instead of a `send` and `sendAsync` in web3@0.x.x`
 | 
			
		||||
            // 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._web3 = new Web3();
 | 
			
		||||
        this._web3.setProvider(provider);
 | 
			
		||||
        this._defaults = defaults || {};
 | 
			
		||||
        this._jsonRpcRequestId = 0;
 | 
			
		||||
    }
 | 
			
		||||
    public getContractDefaults(): Partial<TxData> {
 | 
			
		||||
        return this._defaults;
 | 
			
		||||
    }
 | 
			
		||||
    public setProvider(provider: Web3.Provider) {
 | 
			
		||||
        this._web3.setProvider(provider);
 | 
			
		||||
    }
 | 
			
		||||
    public isAddress(address: string): boolean {
 | 
			
		||||
        return this._web3.isAddress(address);
 | 
			
		||||
    }
 | 
			
		||||
    public async isSenderAddressAvailableAsync(senderAddress: string): Promise<boolean> {
 | 
			
		||||
        const addresses = await this.getAvailableAddressesAsync();
 | 
			
		||||
        const normalizedAddress = senderAddress.toLowerCase();
 | 
			
		||||
        return _.includes(addresses, normalizedAddress);
 | 
			
		||||
    }
 | 
			
		||||
    public async getNodeVersionAsync(): Promise<string> {
 | 
			
		||||
        const nodeVersion = await promisify<string>(this._web3.version.getNode)();
 | 
			
		||||
        return nodeVersion;
 | 
			
		||||
    }
 | 
			
		||||
    public async getNetworkIdAsync(): Promise<number> {
 | 
			
		||||
        const networkIdStr = await promisify<string>(this._web3.version.getNetwork)();
 | 
			
		||||
        const networkId = _.parseInt(networkIdStr);
 | 
			
		||||
        return networkId;
 | 
			
		||||
    }
 | 
			
		||||
    public async getTransactionReceiptAsync(txHash: string): Promise<TransactionReceipt> {
 | 
			
		||||
        const transactionReceipt = await promisify<TransactionReceipt>(this._web3.eth.getTransactionReceipt)(txHash);
 | 
			
		||||
        if (!_.isNull(transactionReceipt)) {
 | 
			
		||||
            transactionReceipt.status = this._normalizeTxReceiptStatus(transactionReceipt.status);
 | 
			
		||||
        }
 | 
			
		||||
        return transactionReceipt;
 | 
			
		||||
    }
 | 
			
		||||
    public getCurrentProvider(): Web3.Provider {
 | 
			
		||||
        return this._web3.currentProvider;
 | 
			
		||||
    }
 | 
			
		||||
    public toWei(ethAmount: BigNumber): BigNumber {
 | 
			
		||||
        const balanceWei = this._web3.toWei(ethAmount, 'ether');
 | 
			
		||||
        return balanceWei;
 | 
			
		||||
    }
 | 
			
		||||
    public async getBalanceInWeiAsync(owner: string): Promise<BigNumber> {
 | 
			
		||||
        let balanceInWei = await promisify<BigNumber>(this._web3.eth.getBalance)(owner);
 | 
			
		||||
        // Rewrap in a new BigNumber
 | 
			
		||||
        balanceInWei = new BigNumber(balanceInWei);
 | 
			
		||||
        return balanceInWei;
 | 
			
		||||
    }
 | 
			
		||||
    public async doesContractExistAtAddressAsync(address: string): Promise<boolean> {
 | 
			
		||||
        const code = await promisify<string>(this._web3.eth.getCode)(address);
 | 
			
		||||
        // Regex matches 0x0, 0x00, 0x in order to accommodate poorly implemented clients
 | 
			
		||||
        const codeIsEmpty = /^0x0{0,40}$/i.test(code);
 | 
			
		||||
        return !codeIsEmpty;
 | 
			
		||||
    }
 | 
			
		||||
    public async signTransactionAsync(address: string, message: string): Promise<string> {
 | 
			
		||||
        const signData = await promisify<string>(this._web3.eth.sign)(address, message);
 | 
			
		||||
        return signData;
 | 
			
		||||
    }
 | 
			
		||||
    public async getBlockNumberAsync(): Promise<number> {
 | 
			
		||||
        const blockNumber = await promisify<number>(this._web3.eth.getBlockNumber)();
 | 
			
		||||
        return blockNumber;
 | 
			
		||||
    }
 | 
			
		||||
    public async getBlockAsync(blockParam: string | Web3.BlockParam): Promise<Web3.BlockWithoutTransactionData> {
 | 
			
		||||
        const block = await promisify<Web3.BlockWithoutTransactionData>(this._web3.eth.getBlock)(blockParam);
 | 
			
		||||
        return block;
 | 
			
		||||
    }
 | 
			
		||||
    public async getBlockTimestampAsync(blockParam: string | Web3.BlockParam): Promise<number> {
 | 
			
		||||
        const { timestamp } = await this.getBlockAsync(blockParam);
 | 
			
		||||
        return timestamp;
 | 
			
		||||
    }
 | 
			
		||||
    public async getAvailableAddressesAsync(): Promise<string[]> {
 | 
			
		||||
        const addresses = await promisify<string[]>(this._web3.eth.getAccounts)();
 | 
			
		||||
        const normalizedAddresses = _.map(addresses, address => address.toLowerCase());
 | 
			
		||||
        return normalizedAddresses;
 | 
			
		||||
    }
 | 
			
		||||
    public async getLogsAsync(filter: Web3.FilterObject): Promise<Web3.LogEntry[]> {
 | 
			
		||||
        let fromBlock = filter.fromBlock;
 | 
			
		||||
        if (_.isNumber(fromBlock)) {
 | 
			
		||||
            fromBlock = this._web3.toHex(fromBlock);
 | 
			
		||||
        }
 | 
			
		||||
        let toBlock = filter.toBlock;
 | 
			
		||||
        if (_.isNumber(toBlock)) {
 | 
			
		||||
            toBlock = this._web3.toHex(toBlock);
 | 
			
		||||
        }
 | 
			
		||||
        const serializedFilter = {
 | 
			
		||||
            ...filter,
 | 
			
		||||
            fromBlock,
 | 
			
		||||
            toBlock,
 | 
			
		||||
        };
 | 
			
		||||
        const payload = {
 | 
			
		||||
            jsonrpc: '2.0',
 | 
			
		||||
            id: this._jsonRpcRequestId++,
 | 
			
		||||
            method: 'eth_getLogs',
 | 
			
		||||
            params: [serializedFilter],
 | 
			
		||||
        };
 | 
			
		||||
        const rawLogs = await this._sendRawPayloadAsync<RawLogEntry[]>(payload);
 | 
			
		||||
        const formattedLogs = _.map(rawLogs, this._formatLog.bind(this));
 | 
			
		||||
        return formattedLogs;
 | 
			
		||||
    }
 | 
			
		||||
    public getContractFromAbi(abi: Web3.ContractAbi): Web3.Contract<any> {
 | 
			
		||||
        const web3Contract = this._web3.eth.contract(abi);
 | 
			
		||||
        return web3Contract;
 | 
			
		||||
    }
 | 
			
		||||
    public getContractInstance(abi: Web3.ContractAbi, address: string): Web3.ContractInstance {
 | 
			
		||||
        const web3ContractInstance = this.getContractFromAbi(abi).at(address);
 | 
			
		||||
        return web3ContractInstance;
 | 
			
		||||
    }
 | 
			
		||||
    public async estimateGasAsync(data: string): Promise<number> {
 | 
			
		||||
        const gas = await promisify<number>(this._web3.eth.estimateGas)({ data });
 | 
			
		||||
        return gas;
 | 
			
		||||
    }
 | 
			
		||||
    public async sendTransactionAsync(txData: Web3.TxData): Promise<string> {
 | 
			
		||||
        const txHash = await promisify<string>(this._web3.eth.sendTransaction)(txData);
 | 
			
		||||
        return txHash;
 | 
			
		||||
    }
 | 
			
		||||
    private async _sendRawPayloadAsync<A>(payload: Web3.JSONRPCRequestPayload): Promise<A> {
 | 
			
		||||
        const sendAsync = this._web3.currentProvider.sendAsync.bind(this._web3.currentProvider);
 | 
			
		||||
        const response = await promisify<Web3.JSONRPCResponsePayload>(sendAsync)(payload);
 | 
			
		||||
        const result = response.result;
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
    private _normalizeTxReceiptStatus(status: undefined | null | string | 0 | 1): null | 0 | 1 {
 | 
			
		||||
        // Transaction status might have four values
 | 
			
		||||
        // undefined - Testrpc and other old clients
 | 
			
		||||
        // null - New clients on old transactions
 | 
			
		||||
        // number - Parity
 | 
			
		||||
        // hex - Geth
 | 
			
		||||
        if (_.isString(status)) {
 | 
			
		||||
            return this._web3.toDecimal(status) as 0 | 1;
 | 
			
		||||
        } else if (_.isUndefined(status)) {
 | 
			
		||||
            return null;
 | 
			
		||||
        } else {
 | 
			
		||||
            return status;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    private _formatLog(rawLog: RawLogEntry): Web3.LogEntry {
 | 
			
		||||
        const formattedLog = {
 | 
			
		||||
            ...rawLog,
 | 
			
		||||
            logIndex: this._hexToDecimal(rawLog.logIndex),
 | 
			
		||||
            blockNumber: this._hexToDecimal(rawLog.blockNumber),
 | 
			
		||||
            transactionIndex: this._hexToDecimal(rawLog.transactionIndex),
 | 
			
		||||
        };
 | 
			
		||||
        return formattedLog;
 | 
			
		||||
    }
 | 
			
		||||
    private _hexToDecimal(hex: string | null): number | null {
 | 
			
		||||
        if (_.isNull(hex)) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        const decimal = this._web3.toDecimal(hex);
 | 
			
		||||
        return decimal;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
export { Web3Wrapper } from './web3_wrapper';
 | 
			
		||||
export { BaseContract } from './base_contract';
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										179
									
								
								packages/web3-wrapper/src/web3_wrapper.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								packages/web3-wrapper/src/web3_wrapper.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,179 @@
 | 
			
		||||
import { TransactionReceipt, TxData } from '@0xproject/types';
 | 
			
		||||
import { BigNumber, promisify } from '@0xproject/utils';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
import * as Web3 from 'web3';
 | 
			
		||||
 | 
			
		||||
interface RawLogEntry {
 | 
			
		||||
    logIndex: string | null;
 | 
			
		||||
    transactionIndex: string | null;
 | 
			
		||||
    transactionHash: string;
 | 
			
		||||
    blockHash: string | null;
 | 
			
		||||
    blockNumber: string | null;
 | 
			
		||||
    address: string;
 | 
			
		||||
    data: string;
 | 
			
		||||
    topics: string[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class Web3Wrapper {
 | 
			
		||||
    private _web3: Web3;
 | 
			
		||||
    private _defaults: Partial<TxData>;
 | 
			
		||||
    private _jsonRpcRequestId: number;
 | 
			
		||||
    constructor(provider: Web3.Provider, defaults?: Partial<TxData>) {
 | 
			
		||||
        if (_.isUndefined((provider as any).sendAsync)) {
 | 
			
		||||
            // Web3@1.0 provider doesn't support synchronous http requests,
 | 
			
		||||
            // so it only has an async `send` method, instead of a `send` and `sendAsync` in web3@0.x.x`
 | 
			
		||||
            // 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._web3 = new Web3();
 | 
			
		||||
        this._web3.setProvider(provider);
 | 
			
		||||
        this._defaults = defaults || {};
 | 
			
		||||
        this._jsonRpcRequestId = 0;
 | 
			
		||||
    }
 | 
			
		||||
    public getContractDefaults(): Partial<TxData> {
 | 
			
		||||
        return this._defaults;
 | 
			
		||||
    }
 | 
			
		||||
    public setProvider(provider: Web3.Provider) {
 | 
			
		||||
        this._web3.setProvider(provider);
 | 
			
		||||
    }
 | 
			
		||||
    public isAddress(address: string): boolean {
 | 
			
		||||
        return this._web3.isAddress(address);
 | 
			
		||||
    }
 | 
			
		||||
    public async isSenderAddressAvailableAsync(senderAddress: string): Promise<boolean> {
 | 
			
		||||
        const addresses = await this.getAvailableAddressesAsync();
 | 
			
		||||
        const normalizedAddress = senderAddress.toLowerCase();
 | 
			
		||||
        return _.includes(addresses, normalizedAddress);
 | 
			
		||||
    }
 | 
			
		||||
    public async getNodeVersionAsync(): Promise<string> {
 | 
			
		||||
        const nodeVersion = await promisify<string>(this._web3.version.getNode)();
 | 
			
		||||
        return nodeVersion;
 | 
			
		||||
    }
 | 
			
		||||
    public async getNetworkIdAsync(): Promise<number> {
 | 
			
		||||
        const networkIdStr = await promisify<string>(this._web3.version.getNetwork)();
 | 
			
		||||
        const networkId = _.parseInt(networkIdStr);
 | 
			
		||||
        return networkId;
 | 
			
		||||
    }
 | 
			
		||||
    public async getTransactionReceiptAsync(txHash: string): Promise<TransactionReceipt> {
 | 
			
		||||
        const transactionReceipt = await promisify<TransactionReceipt>(this._web3.eth.getTransactionReceipt)(txHash);
 | 
			
		||||
        if (!_.isNull(transactionReceipt)) {
 | 
			
		||||
            transactionReceipt.status = this._normalizeTxReceiptStatus(transactionReceipt.status);
 | 
			
		||||
        }
 | 
			
		||||
        return transactionReceipt;
 | 
			
		||||
    }
 | 
			
		||||
    public getCurrentProvider(): Web3.Provider {
 | 
			
		||||
        return this._web3.currentProvider;
 | 
			
		||||
    }
 | 
			
		||||
    public toWei(ethAmount: BigNumber): BigNumber {
 | 
			
		||||
        const balanceWei = this._web3.toWei(ethAmount, 'ether');
 | 
			
		||||
        return balanceWei;
 | 
			
		||||
    }
 | 
			
		||||
    public async getBalanceInWeiAsync(owner: string): Promise<BigNumber> {
 | 
			
		||||
        let balanceInWei = await promisify<BigNumber>(this._web3.eth.getBalance)(owner);
 | 
			
		||||
        // Rewrap in a new BigNumber
 | 
			
		||||
        balanceInWei = new BigNumber(balanceInWei);
 | 
			
		||||
        return balanceInWei;
 | 
			
		||||
    }
 | 
			
		||||
    public async doesContractExistAtAddressAsync(address: string): Promise<boolean> {
 | 
			
		||||
        const code = await promisify<string>(this._web3.eth.getCode)(address);
 | 
			
		||||
        // Regex matches 0x0, 0x00, 0x in order to accommodate poorly implemented clients
 | 
			
		||||
        const codeIsEmpty = /^0x0{0,40}$/i.test(code);
 | 
			
		||||
        return !codeIsEmpty;
 | 
			
		||||
    }
 | 
			
		||||
    public async signTransactionAsync(address: string, message: string): Promise<string> {
 | 
			
		||||
        const signData = await promisify<string>(this._web3.eth.sign)(address, message);
 | 
			
		||||
        return signData;
 | 
			
		||||
    }
 | 
			
		||||
    public async getBlockNumberAsync(): Promise<number> {
 | 
			
		||||
        const blockNumber = await promisify<number>(this._web3.eth.getBlockNumber)();
 | 
			
		||||
        return blockNumber;
 | 
			
		||||
    }
 | 
			
		||||
    public async getBlockAsync(blockParam: string | Web3.BlockParam): Promise<Web3.BlockWithoutTransactionData> {
 | 
			
		||||
        const block = await promisify<Web3.BlockWithoutTransactionData>(this._web3.eth.getBlock)(blockParam);
 | 
			
		||||
        return block;
 | 
			
		||||
    }
 | 
			
		||||
    public async getBlockTimestampAsync(blockParam: string | Web3.BlockParam): Promise<number> {
 | 
			
		||||
        const { timestamp } = await this.getBlockAsync(blockParam);
 | 
			
		||||
        return timestamp;
 | 
			
		||||
    }
 | 
			
		||||
    public async getAvailableAddressesAsync(): Promise<string[]> {
 | 
			
		||||
        const addresses = await promisify<string[]>(this._web3.eth.getAccounts)();
 | 
			
		||||
        const normalizedAddresses = _.map(addresses, address => address.toLowerCase());
 | 
			
		||||
        return normalizedAddresses;
 | 
			
		||||
    }
 | 
			
		||||
    public async getLogsAsync(filter: Web3.FilterObject): Promise<Web3.LogEntry[]> {
 | 
			
		||||
        let fromBlock = filter.fromBlock;
 | 
			
		||||
        if (_.isNumber(fromBlock)) {
 | 
			
		||||
            fromBlock = this._web3.toHex(fromBlock);
 | 
			
		||||
        }
 | 
			
		||||
        let toBlock = filter.toBlock;
 | 
			
		||||
        if (_.isNumber(toBlock)) {
 | 
			
		||||
            toBlock = this._web3.toHex(toBlock);
 | 
			
		||||
        }
 | 
			
		||||
        const serializedFilter = {
 | 
			
		||||
            ...filter,
 | 
			
		||||
            fromBlock,
 | 
			
		||||
            toBlock,
 | 
			
		||||
        };
 | 
			
		||||
        const payload = {
 | 
			
		||||
            jsonrpc: '2.0',
 | 
			
		||||
            id: this._jsonRpcRequestId++,
 | 
			
		||||
            method: 'eth_getLogs',
 | 
			
		||||
            params: [serializedFilter],
 | 
			
		||||
        };
 | 
			
		||||
        const rawLogs = await this._sendRawPayloadAsync<RawLogEntry[]>(payload);
 | 
			
		||||
        const formattedLogs = _.map(rawLogs, this._formatLog.bind(this));
 | 
			
		||||
        return formattedLogs;
 | 
			
		||||
    }
 | 
			
		||||
    public getContractFromAbi(abi: Web3.ContractAbi): Web3.Contract<any> {
 | 
			
		||||
        const web3Contract = this._web3.eth.contract(abi);
 | 
			
		||||
        return web3Contract;
 | 
			
		||||
    }
 | 
			
		||||
    public async estimateGasAsync(txData: Partial<Web3.TxData>): Promise<number> {
 | 
			
		||||
        const gas = await promisify<number>(this._web3.eth.estimateGas)(txData);
 | 
			
		||||
        return gas;
 | 
			
		||||
    }
 | 
			
		||||
    public async callAsync(callData: Web3.CallData, defaultBlock?: Web3.BlockParam): Promise<string> {
 | 
			
		||||
        const rawCalllResult = await promisify<string>(this._web3.eth.call)(callData, defaultBlock);
 | 
			
		||||
        return rawCalllResult;
 | 
			
		||||
    }
 | 
			
		||||
    public async sendTransactionAsync(txData: Web3.TxData): Promise<string> {
 | 
			
		||||
        const txHash = await promisify<string>(this._web3.eth.sendTransaction)(txData);
 | 
			
		||||
        return txHash;
 | 
			
		||||
    }
 | 
			
		||||
    private async _sendRawPayloadAsync<A>(payload: Web3.JSONRPCRequestPayload): Promise<A> {
 | 
			
		||||
        const sendAsync = this._web3.currentProvider.sendAsync.bind(this._web3.currentProvider);
 | 
			
		||||
        const response = await promisify<Web3.JSONRPCResponsePayload>(sendAsync)(payload);
 | 
			
		||||
        const result = response.result;
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
    private _normalizeTxReceiptStatus(status: undefined | null | string | 0 | 1): null | 0 | 1 {
 | 
			
		||||
        // Transaction status might have four values
 | 
			
		||||
        // undefined - Testrpc and other old clients
 | 
			
		||||
        // null - New clients on old transactions
 | 
			
		||||
        // number - Parity
 | 
			
		||||
        // hex - Geth
 | 
			
		||||
        if (_.isString(status)) {
 | 
			
		||||
            return this._web3.toDecimal(status) as 0 | 1;
 | 
			
		||||
        } else if (_.isUndefined(status)) {
 | 
			
		||||
            return null;
 | 
			
		||||
        } else {
 | 
			
		||||
            return status;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    private _formatLog(rawLog: RawLogEntry): Web3.LogEntry {
 | 
			
		||||
        const formattedLog = {
 | 
			
		||||
            ...rawLog,
 | 
			
		||||
            logIndex: this._hexToDecimal(rawLog.logIndex),
 | 
			
		||||
            blockNumber: this._hexToDecimal(rawLog.blockNumber),
 | 
			
		||||
            transactionIndex: this._hexToDecimal(rawLog.transactionIndex),
 | 
			
		||||
        };
 | 
			
		||||
        return formattedLog;
 | 
			
		||||
    }
 | 
			
		||||
    private _hexToDecimal(hex: string | null): number | null {
 | 
			
		||||
        if (_.isNull(hex)) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        const decimal = this._web3.toDecimal(hex);
 | 
			
		||||
        return decimal;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,5 +3,9 @@
 | 
			
		||||
    "compilerOptions": {
 | 
			
		||||
        "outDir": "lib"
 | 
			
		||||
    },
 | 
			
		||||
    "include": ["./src/**/*", "../../node_modules/web3-typescript-typings/index.d.ts"]
 | 
			
		||||
    "include": [
 | 
			
		||||
        "./src/**/*",
 | 
			
		||||
        "../../node_modules/ethers-typescript-typings/index.d.ts",
 | 
			
		||||
        "../../node_modules/web3-typescript-typings/index.d.ts"
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								yarn.lock
									
									
									
									
									
								
							@@ -3227,6 +3227,21 @@ ethereumjs-wallet@^0.6.0:
 | 
			
		||||
    utf8 "^2.1.1"
 | 
			
		||||
    uuid "^2.0.1"
 | 
			
		||||
 | 
			
		||||
ethers-contracts@^2.2.1:
 | 
			
		||||
  version "2.2.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/ethers-contracts/-/ethers-contracts-2.2.1.tgz#e2bf5dd5e157313ba454b50c646c8472fcd0a8b3"
 | 
			
		||||
  dependencies:
 | 
			
		||||
    ethers-utils "^2.1.0"
 | 
			
		||||
 | 
			
		||||
ethers-utils@^2.1.0:
 | 
			
		||||
  version "2.1.11"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/ethers-utils/-/ethers-utils-2.1.11.tgz#b27535ca3226118be300211c39c896b1e5e21641"
 | 
			
		||||
  dependencies:
 | 
			
		||||
    bn.js "^4.4.0"
 | 
			
		||||
    hash.js "^1.0.0"
 | 
			
		||||
    js-sha3 "0.5.7"
 | 
			
		||||
    xmlhttprequest "1.8.0"
 | 
			
		||||
 | 
			
		||||
ethjs-abi@0.1.8:
 | 
			
		||||
  version "0.1.8"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/ethjs-abi/-/ethjs-abi-0.1.8.tgz#cd288583ed628cdfadaf8adefa3ba1dbcbca6c18"
 | 
			
		||||
@@ -4970,6 +4985,10 @@ js-sha3@0.5.5:
 | 
			
		||||
  version "0.5.5"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.5.tgz#baf0c0e8c54ad5903447df96ade7a4a1bca79a4a"
 | 
			
		||||
 | 
			
		||||
js-sha3@0.5.7:
 | 
			
		||||
  version "0.5.7"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7"
 | 
			
		||||
 | 
			
		||||
js-sha3@^0.3.1:
 | 
			
		||||
  version "0.3.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243"
 | 
			
		||||
@@ -9811,7 +9830,7 @@ xml-js@^1.3.2:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    sax "^1.2.4"
 | 
			
		||||
 | 
			
		||||
xmlhttprequest@*:
 | 
			
		||||
xmlhttprequest@*, xmlhttprequest@1.8.0:
 | 
			
		||||
  version "1.8.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user