Merge pull request #413 from 0xProject/feature/ethers-contracts
abi-gen V2 abi and ethers-contracts
This commit is contained in:
commit
7aa070f9ea
@ -1,5 +1,4 @@
|
|||||||
lib
|
lib
|
||||||
generated
|
|
||||||
.nyc_output
|
.nyc_output
|
||||||
/packages/contracts/src/artifacts
|
/packages/contracts/src/artifacts
|
||||||
package.json
|
package.json
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
* Validate and lowercase all addresses in public methods (#373)
|
* Validate and lowercase all addresses in public methods (#373)
|
||||||
* Improve validation to force passing contract addresses on private networks (#385)
|
* 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)
|
* Rename all public `_unsubscribeAll` methods to `unsubscribeAll` (#415)
|
||||||
|
|
||||||
## v0.32.2 - _February 9, 2018_
|
## 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;",
|
"build": "run-p build:umd:prod build:commonjs; exit 0;",
|
||||||
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_DIR",
|
"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",
|
"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'",
|
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
|
||||||
"test:circleci": "run-s test:coverage report_test_coverage",
|
"test:circleci": "run-s test:coverage report_test_coverage",
|
||||||
"test": "run-s clean test:commonjs",
|
"test": "run-s clean test:commonjs",
|
||||||
@ -77,6 +77,7 @@
|
|||||||
"types-bn": "^0.0.1",
|
"types-bn": "^0.0.1",
|
||||||
"typescript": "2.7.1",
|
"typescript": "2.7.1",
|
||||||
"web3-provider-engine": "^13.0.1",
|
"web3-provider-engine": "^13.0.1",
|
||||||
|
"ethers-typescript-typings": "^0.0.1",
|
||||||
"web3-typescript-typings": "^0.9.11",
|
"web3-typescript-typings": "^0.9.11",
|
||||||
"webpack": "^3.1.0"
|
"webpack": "^3.1.0"
|
||||||
},
|
},
|
||||||
@ -88,6 +89,7 @@
|
|||||||
"@0xproject/web3-wrapper": "^0.1.14",
|
"@0xproject/web3-wrapper": "^0.1.14",
|
||||||
"bintrees": "^1.0.2",
|
"bintrees": "^1.0.2",
|
||||||
"bn.js": "^4.11.8",
|
"bn.js": "^4.11.8",
|
||||||
|
"ethers-contracts": "^2.2.1",
|
||||||
"ethereumjs-abi": "^0.6.4",
|
"ethereumjs-abi": "^0.6.4",
|
||||||
"ethereumjs-blockstream": "^2.0.6",
|
"ethereumjs-blockstream": "^2.0.6",
|
||||||
"ethereumjs-util": "^5.1.1",
|
"ethereumjs-util": "^5.1.1",
|
||||||
|
@ -108,10 +108,10 @@ export class ContractWrapper {
|
|||||||
const logWithDecodedArgs = this._abiDecoder.tryToDecodeLogOrNoop(log);
|
const logWithDecodedArgs = this._abiDecoder.tryToDecodeLogOrNoop(log);
|
||||||
return logWithDecodedArgs;
|
return logWithDecodedArgs;
|
||||||
}
|
}
|
||||||
protected async _instantiateContractIfExistsAsync(
|
protected async _getContractAbiAndAddressFromArtifactsAsync(
|
||||||
artifact: Artifact,
|
artifact: Artifact,
|
||||||
addressIfExists?: string,
|
addressIfExists?: string,
|
||||||
): Promise<Web3.ContractInstance> {
|
): Promise<[Web3.ContractAbi, string]> {
|
||||||
let contractAddress: string;
|
let contractAddress: string;
|
||||||
if (_.isUndefined(addressIfExists)) {
|
if (_.isUndefined(addressIfExists)) {
|
||||||
if (_.isUndefined(artifact.networks[this._networkId])) {
|
if (_.isUndefined(artifact.networks[this._networkId])) {
|
||||||
@ -125,8 +125,8 @@ export class ContractWrapper {
|
|||||||
if (!doesContractExist) {
|
if (!doesContractExist) {
|
||||||
throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contract_name]);
|
throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contract_name]);
|
||||||
}
|
}
|
||||||
const contractInstance = this._web3Wrapper.getContractInstance(artifact.abi, contractAddress);
|
const abiAndAddress: [Web3.ContractAbi, string] = [artifact.abi, contractAddress];
|
||||||
return contractInstance;
|
return abiAndAddress;
|
||||||
}
|
}
|
||||||
protected _getContractAddress(artifact: Artifact, addressIfExists?: string): string {
|
protected _getContractAddress(artifact: Artifact, addressIfExists?: string): string {
|
||||||
if (_.isUndefined(addressIfExists)) {
|
if (_.isUndefined(addressIfExists)) {
|
||||||
|
@ -187,11 +187,11 @@ export class EtherTokenWrapper extends ContractWrapper {
|
|||||||
if (!_.isUndefined(etherTokenContract)) {
|
if (!_.isUndefined(etherTokenContract)) {
|
||||||
return etherTokenContract;
|
return etherTokenContract;
|
||||||
}
|
}
|
||||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||||
artifacts.EtherTokenArtifact,
|
artifacts.EtherTokenArtifact,
|
||||||
etherTokenAddress,
|
etherTokenAddress,
|
||||||
);
|
);
|
||||||
const contractInstance = new EtherTokenContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
|
const contractInstance = new EtherTokenContract(this._web3Wrapper, abi, address);
|
||||||
etherTokenContract = contractInstance;
|
etherTokenContract = contractInstance;
|
||||||
this._etherTokenContractsByAddress[etherTokenAddress] = etherTokenContract;
|
this._etherTokenContractsByAddress[etherTokenAddress] = etherTokenContract;
|
||||||
return etherTokenContract;
|
return etherTokenContract;
|
||||||
|
@ -108,8 +108,10 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
|
|
||||||
const exchangeContract = await this._getExchangeContractAsync();
|
const exchangeContract = await this._getExchangeContractAsync();
|
||||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
||||||
|
const txData = {};
|
||||||
let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.callAsync(
|
let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.callAsync(
|
||||||
orderHash,
|
orderHash,
|
||||||
|
txData,
|
||||||
defaultBlock,
|
defaultBlock,
|
||||||
);
|
);
|
||||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
// 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 exchangeContract = await this._getExchangeContractAsync();
|
||||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
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
|
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||||
fillAmountInBaseUnits = new BigNumber(fillAmountInBaseUnits);
|
fillAmountInBaseUnits = new BigNumber(fillAmountInBaseUnits);
|
||||||
return fillAmountInBaseUnits;
|
return fillAmountInBaseUnits;
|
||||||
@ -144,7 +147,8 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
|
|
||||||
const exchangeContract = await this._getExchangeContractAsync();
|
const exchangeContract = await this._getExchangeContractAsync();
|
||||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
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
|
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||||
cancelledAmountInBaseUnits = new BigNumber(cancelledAmountInBaseUnits);
|
cancelledAmountInBaseUnits = new BigNumber(cancelledAmountInBaseUnits);
|
||||||
return cancelledAmountInBaseUnits;
|
return cancelledAmountInBaseUnits;
|
||||||
@ -858,7 +862,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
});
|
});
|
||||||
if (!_.isUndefined(errLog)) {
|
if (!_.isUndefined(errLog)) {
|
||||||
const logArgs = (errLog as LogWithDecodedArgs<LogErrorContractEventArgs>).args;
|
const logArgs = (errLog as LogWithDecodedArgs<LogErrorContractEventArgs>).args;
|
||||||
const errCode = logArgs.errorId.toNumber();
|
const errCode = logArgs.errorId;
|
||||||
const errMessage = this._exchangeContractErrCodesToMsg[errCode];
|
const errMessage = this._exchangeContractErrCodesToMsg[errCode];
|
||||||
throw new Error(errMessage);
|
throw new Error(errMessage);
|
||||||
}
|
}
|
||||||
@ -906,11 +910,11 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
if (!_.isUndefined(this._exchangeContractIfExists)) {
|
if (!_.isUndefined(this._exchangeContractIfExists)) {
|
||||||
return this._exchangeContractIfExists;
|
return this._exchangeContractIfExists;
|
||||||
}
|
}
|
||||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||||
artifacts.ExchangeArtifact,
|
artifacts.ExchangeArtifact,
|
||||||
this._contractAddressIfExists,
|
this._contractAddressIfExists,
|
||||||
);
|
);
|
||||||
const contractInstance = new ExchangeContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
|
const contractInstance = new ExchangeContract(this._web3Wrapper, abi, address);
|
||||||
this._exchangeContractIfExists = contractInstance;
|
this._exchangeContractIfExists = contractInstance;
|
||||||
return this._exchangeContractIfExists;
|
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],
|
address: metadata[0],
|
||||||
name: metadata[1],
|
name: metadata[1],
|
||||||
symbol: metadata[2],
|
symbol: metadata[2],
|
||||||
decimals: metadata[3].toNumber(),
|
decimals: metadata[3],
|
||||||
};
|
};
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
@ -50,7 +50,8 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
|||||||
public async getTokenAddressesAsync(): Promise<string[]> {
|
public async getTokenAddressesAsync(): Promise<string[]> {
|
||||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||||
const addresses = await tokenRegistryContract.getTokenAddresses.callAsync();
|
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
|
* 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)) {
|
if (!_.isUndefined(this._tokenRegistryContractIfExists)) {
|
||||||
return this._tokenRegistryContractIfExists;
|
return this._tokenRegistryContractIfExists;
|
||||||
}
|
}
|
||||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||||
artifacts.TokenRegistryArtifact,
|
artifacts.TokenRegistryArtifact,
|
||||||
this._contractAddressIfExists,
|
this._contractAddressIfExists,
|
||||||
);
|
);
|
||||||
const contractInstance = new TokenRegistryContract(
|
const contractInstance = new TokenRegistryContract(this._web3Wrapper, abi, address);
|
||||||
web3ContractInstance,
|
|
||||||
this._web3Wrapper.getContractDefaults(),
|
|
||||||
);
|
|
||||||
this._tokenRegistryContractIfExists = contractInstance;
|
this._tokenRegistryContractIfExists = contractInstance;
|
||||||
return this._tokenRegistryContractIfExists;
|
return this._tokenRegistryContractIfExists;
|
||||||
}
|
}
|
||||||
|
@ -59,14 +59,11 @@ export class TokenTransferProxyWrapper extends ContractWrapper {
|
|||||||
if (!_.isUndefined(this._tokenTransferProxyContractIfExists)) {
|
if (!_.isUndefined(this._tokenTransferProxyContractIfExists)) {
|
||||||
return this._tokenTransferProxyContractIfExists;
|
return this._tokenTransferProxyContractIfExists;
|
||||||
}
|
}
|
||||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||||
artifacts.TokenTransferProxyArtifact,
|
artifacts.TokenTransferProxyArtifact,
|
||||||
this._contractAddressIfExists,
|
this._contractAddressIfExists,
|
||||||
);
|
);
|
||||||
const contractInstance = new TokenTransferProxyContract(
|
const contractInstance = new TokenTransferProxyContract(this._web3Wrapper, abi, address);
|
||||||
web3ContractInstance,
|
|
||||||
this._web3Wrapper.getContractDefaults(),
|
|
||||||
);
|
|
||||||
this._tokenTransferProxyContractIfExists = contractInstance;
|
this._tokenTransferProxyContractIfExists = contractInstance;
|
||||||
return this._tokenTransferProxyContractIfExists;
|
return this._tokenTransferProxyContractIfExists;
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,8 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
|
|
||||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
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
|
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||||
balance = new BigNumber(balance);
|
balance = new BigNumber(balance);
|
||||||
return balance;
|
return balance;
|
||||||
@ -146,9 +147,11 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
|
|
||||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
||||||
|
const txData = {};
|
||||||
let allowanceInBaseUnits = await tokenContract.allowance.callAsync(
|
let allowanceInBaseUnits = await tokenContract.allowance.callAsync(
|
||||||
normalizedOwnerAddress,
|
normalizedOwnerAddress,
|
||||||
normalizedSpenderAddress,
|
normalizedSpenderAddress,
|
||||||
|
txData,
|
||||||
defaultBlock,
|
defaultBlock,
|
||||||
);
|
);
|
||||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||||
@ -419,11 +422,11 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
if (!_.isUndefined(tokenContract)) {
|
if (!_.isUndefined(tokenContract)) {
|
||||||
return tokenContract;
|
return tokenContract;
|
||||||
}
|
}
|
||||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||||
artifacts.TokenArtifact,
|
artifacts.TokenArtifact,
|
||||||
normalizedTokenAddress,
|
normalizedTokenAddress,
|
||||||
);
|
);
|
||||||
const contractInstance = new TokenContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
|
const contractInstance = new TokenContract(this._web3Wrapper, abi, address);
|
||||||
tokenContract = contractInstance;
|
tokenContract = contractInstance;
|
||||||
this._tokenContractsByAddress[normalizedTokenAddress] = tokenContract;
|
this._tokenContractsByAddress[normalizedTokenAddress] = tokenContract;
|
||||||
return tokenContract;
|
return tokenContract;
|
||||||
|
@ -127,7 +127,7 @@ export interface SignedOrder extends Order {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// [address, name, symbol, decimals, ipfsHash, swarmHash]
|
// [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 {
|
export interface Token {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -35,12 +35,8 @@ export class FillScenarios {
|
|||||||
const web3Wrapper = (this._zeroEx as any)._web3Wrapper as Web3Wrapper;
|
const web3Wrapper = (this._zeroEx as any)._web3Wrapper as Web3Wrapper;
|
||||||
for (const token of this._tokens) {
|
for (const token of this._tokens) {
|
||||||
if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') {
|
if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') {
|
||||||
const contractInstance = web3Wrapper.getContractInstance(
|
|
||||||
artifacts.DummyTokenArtifact.abi,
|
|
||||||
token.address,
|
|
||||||
);
|
|
||||||
const defaults = {};
|
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 tokenSupply = ZeroEx.toBaseUnitAmount(INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS, token.decimals);
|
||||||
const txHash = await dummyToken.setBalance.sendTransactionAsync(this._coinbase, tokenSupply, {
|
const txHash = await dummyToken.setBalance.sendTransactionAsync(this._coinbase, tokenSupply, {
|
||||||
from: this._coinbase,
|
from: this._coinbase,
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
"./test/**/*",
|
"./test/**/*",
|
||||||
"../../node_modules/types-bn/index.d.ts",
|
"../../node_modules/types-bn/index.d.ts",
|
||||||
"../../node_modules/types-ethereumjs-util/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/web3-typescript-typings/index.d.ts",
|
||||||
"../../node_modules/chai-typescript-typings/index.d.ts",
|
"../../node_modules/chai-typescript-typings/index.d.ts",
|
||||||
"../../node_modules/chai-as-promised-typescript-typings/index.d.ts"
|
"../../node_modules/chai-as-promised-typescript-typings/index.d.ts"
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
# CHANGELOG
|
# 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_
|
## v0.2.1 - _February 9, 2018_
|
||||||
|
|
||||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
* 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 toSnakeCase = require('to-snake-case');
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
import { ContextData, ParamKind } from './types';
|
import { ContextData, ContractsBackend, ParamKind } from './types';
|
||||||
import { utils } from './utils';
|
import { utils } from './utils';
|
||||||
|
|
||||||
const ABI_TYPE_CONSTRUCTOR = 'constructor';
|
const ABI_TYPE_CONSTRUCTOR = 'constructor';
|
||||||
const ABI_TYPE_METHOD = 'function';
|
const ABI_TYPE_METHOD = 'function';
|
||||||
const ABI_TYPE_EVENT = 'event';
|
const ABI_TYPE_EVENT = 'event';
|
||||||
const DEFAULT_NETWORK_ID = 50;
|
const DEFAULT_NETWORK_ID = 50;
|
||||||
|
const DEFAULT_BACKEND = 'web3';
|
||||||
|
|
||||||
const args = yargs
|
const args = yargs
|
||||||
.option('abis', {
|
.option('abis', {
|
||||||
@ -43,6 +44,12 @@ const args = yargs
|
|||||||
demandOption: true,
|
demandOption: true,
|
||||||
normalize: 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', {
|
.option('network-id', {
|
||||||
describe: 'ID of the network where contract ABIs are nested in artifacts',
|
describe: 'ID of the network where contract ABIs are nested in artifacts',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
@ -73,8 +80,8 @@ function writeOutputFile(name: string, renderedTsCode: string): void {
|
|||||||
utils.log(`Created: ${chalk.bold(filePath)}`);
|
utils.log(`Created: ${chalk.bold(filePath)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input));
|
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input, args.backend));
|
||||||
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output));
|
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output, args.backend));
|
||||||
|
|
||||||
if (args.partials) {
|
if (args.partials) {
|
||||||
registerPartials(args.partials);
|
registerPartials(args.partials);
|
||||||
@ -129,6 +136,7 @@ for (const abiFileName of abiFileNames) {
|
|||||||
const methodData = {
|
const methodData = {
|
||||||
...methodAbi,
|
...methodAbi,
|
||||||
singleReturnValue: methodAbi.outputs.length === 1,
|
singleReturnValue: methodAbi.outputs.length === 1,
|
||||||
|
hasReturnValue: methodAbi.outputs.length !== 0,
|
||||||
};
|
};
|
||||||
return methodData;
|
return methodData;
|
||||||
});
|
});
|
||||||
|
@ -12,8 +12,14 @@ export enum AbiType {
|
|||||||
Fallback = 'fallback',
|
Fallback = 'fallback',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ContractsBackend {
|
||||||
|
Web3 = 'web3',
|
||||||
|
Ethers = 'ethers',
|
||||||
|
}
|
||||||
|
|
||||||
export interface Method extends Web3.MethodAbi {
|
export interface Method extends Web3.MethodAbi {
|
||||||
singleReturnValue: boolean;
|
singleReturnValue: boolean;
|
||||||
|
hasReturnValue: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ContextData {
|
export interface ContextData {
|
||||||
|
@ -3,15 +3,21 @@ import * as _ from 'lodash';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
import { AbiType, ParamKind } from './types';
|
import { AbiType, ContractsBackend, ParamKind } from './types';
|
||||||
|
|
||||||
export const utils = {
|
export const utils = {
|
||||||
solTypeToTsType(paramKind: ParamKind, solType: string): string {
|
solTypeToTsType(
|
||||||
|
paramKind: ParamKind,
|
||||||
|
backend: ContractsBackend,
|
||||||
|
solType: string,
|
||||||
|
components?: Web3.DataItem[],
|
||||||
|
): string {
|
||||||
const trailingArrayRegex = /\[\d*\]$/;
|
const trailingArrayRegex = /\[\d*\]$/;
|
||||||
if (solType.match(trailingArrayRegex)) {
|
if (solType.match(trailingArrayRegex)) {
|
||||||
const arrayItemSolType = solType.replace(trailingArrayRegex, '');
|
const arrayItemSolType = solType.replace(trailingArrayRegex, '');
|
||||||
const arrayItemTsType = utils.solTypeToTsType(paramKind, arrayItemSolType);
|
const arrayItemTsType = utils.solTypeToTsType(paramKind, backend, arrayItemSolType, components);
|
||||||
const arrayTsType = utils.isUnionType(arrayItemTsType)
|
const arrayTsType =
|
||||||
|
utils.isUnionType(arrayItemTsType) || utils.isObjectType(arrayItemTsType)
|
||||||
? `Array<${arrayItemTsType}>`
|
? `Array<${arrayItemTsType}>`
|
||||||
: `${arrayItemTsType}[]`;
|
: `${arrayItemTsType}[]`;
|
||||||
return arrayTsType;
|
return arrayTsType;
|
||||||
@ -24,25 +30,49 @@ export const utils = {
|
|||||||
{ regex: '^bytes\\d*$', tsType: 'string' },
|
{ regex: '^bytes\\d*$', tsType: 'string' },
|
||||||
];
|
];
|
||||||
if (paramKind === ParamKind.Input) {
|
if (paramKind === ParamKind.Input) {
|
||||||
// web3 allows to pass those an non-bignumbers and that's nice
|
// web3 and ethers allow to pass those as numbers instead of bignumbers
|
||||||
// but it always returns stuff as BigNumbers
|
|
||||||
solTypeRegexToTsType.unshift({
|
solTypeRegexToTsType.unshift({
|
||||||
regex: '^u?int(8|16|32)?$',
|
regex: '^u?int(8|16|32)?$',
|
||||||
tsType: 'number|BigNumber',
|
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) {
|
for (const regexAndTxType of solTypeRegexToTsType) {
|
||||||
const { regex, tsType } = regexAndTxType;
|
const { regex, tsType } = regexAndTxType;
|
||||||
if (solType.match(regex)) {
|
if (solType.match(regex)) {
|
||||||
return tsType;
|
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}`);
|
throw new Error(`Unknown Solidity type found: ${solType}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isUnionType(tsType: string): boolean {
|
isUnionType(tsType: string): boolean {
|
||||||
return tsType === 'number|BigNumber';
|
return tsType === 'number|BigNumber';
|
||||||
},
|
},
|
||||||
|
isObjectType(tsType: string): boolean {
|
||||||
|
return /^{.*}$/.test(tsType);
|
||||||
|
},
|
||||||
log(...args: any[]): void {
|
log(...args: any[]): void {
|
||||||
console.log(...args); // tslint:disable-line:no-console
|
console.log(...args); // tslint:disable-line:no-console
|
||||||
},
|
},
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
/**
|
/**
|
||||||
* This file is auto-generated using abi-gen. Don't edit directly.
|
* 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:no-consecutive-blank-lines
|
||||||
// tslint:disable-next-line:no-unused-variable
|
// tslint:disable-next-line:no-unused-variable
|
||||||
import { TxData, TxDataPayable } from '@0xproject/types';
|
import { TxData, TxDataPayable } from '@0xproject/types';
|
||||||
import { BigNumber, classUtils, promisify } from '@0xproject/utils';
|
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 * as Web3 from 'web3';
|
||||||
|
|
||||||
import {BaseContract} from './base_contract';
|
|
||||||
|
|
||||||
{{#if events}}
|
{{#if events}}
|
||||||
export type {{contractName}}ContractEventArgs =
|
export type {{contractName}}ContractEventArgs =
|
||||||
{{#each events}}
|
{{#each events}}
|
||||||
@ -28,6 +29,7 @@ export enum {{contractName}}Events {
|
|||||||
{{/each}}
|
{{/each}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
// tslint:disable:no-parameter-reassignment
|
||||||
export class {{contractName}}Contract extends BaseContract {
|
export class {{contractName}}Contract extends BaseContract {
|
||||||
{{#each methods}}
|
{{#each methods}}
|
||||||
{{#this.constant}}
|
{{#this.constant}}
|
||||||
@ -37,8 +39,8 @@ export class {{contractName}}Contract extends BaseContract {
|
|||||||
{{> tx contractName=../contractName}}
|
{{> tx contractName=../contractName}}
|
||||||
{{/this.constant}}
|
{{/this.constant}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<TxData>) {
|
constructor(web3Wrapper: Web3Wrapper, abi: Web3.ContractAbi, address: string) {
|
||||||
super(web3ContractInstance, defaults);
|
super(web3Wrapper, abi, address);
|
||||||
classUtils.bindAll(this, ['_web3ContractInstance', '_defaults']);
|
classUtils.bindAll(this, ['_ethersInterface', 'address', 'abi', '_web3Wrapper']);
|
||||||
}
|
}
|
||||||
} // tslint:disable:max-file-line-count
|
} // 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 {
|
export interface {{name}}ContractEventArgs {
|
||||||
{{#each inputs}}
|
{{#each inputs}}
|
||||||
{{name}}: {{#returnType type}}{{/returnType}};
|
{{name}}: {{#returnType type components}}{{/returnType}};
|
||||||
{{/each}}
|
{{/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}}
|
{{/this.payable}}
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const self = this as {{contractName}}Contract;
|
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(
|
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
||||||
txData,
|
{
|
||||||
|
...txData,
|
||||||
|
data: encodedData,
|
||||||
|
},
|
||||||
self.{{this.name}}.estimateGasAsync.bind(
|
self.{{this.name}}.estimateGasAsync.bind(
|
||||||
self,
|
self,
|
||||||
{{> params inputs=inputs}}
|
{{> params inputs=inputs}}
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const txHash = await promisify<string>(
|
const txHash = await this._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||||
self._web3ContractInstance.{{this.name}}, self._web3ContractInstance,
|
|
||||||
)(
|
|
||||||
{{> params inputs=inputs}}
|
|
||||||
txDataWithDefaults,
|
|
||||||
);
|
|
||||||
return txHash;
|
return txHash;
|
||||||
},
|
},
|
||||||
async estimateGasAsync(
|
async estimateGasAsync(
|
||||||
@ -29,15 +32,16 @@ public {{this.name}} = {
|
|||||||
txData: TxData = {},
|
txData: TxData = {},
|
||||||
): Promise<number> {
|
): Promise<number> {
|
||||||
const self = this as {{contractName}}Contract;
|
const self = this as {{contractName}}Contract;
|
||||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
const encodedData = this._ethersInterface.functions.{{this.name}}(
|
||||||
txData,
|
|
||||||
);
|
|
||||||
const gas = await promisify<number>(
|
|
||||||
self._web3ContractInstance.{{this.name}}.estimateGas, self._web3ContractInstance,
|
|
||||||
)(
|
|
||||||
{{> params inputs=inputs}}
|
{{> params inputs=inputs}}
|
||||||
txDataWithDefaults,
|
).data
|
||||||
|
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
||||||
|
{
|
||||||
|
...txData,
|
||||||
|
data: encodedData,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
const gas = await this._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
||||||
return gas;
|
return gas;
|
||||||
},
|
},
|
||||||
getABIEncodedTransactionData(
|
getABIEncodedTransactionData(
|
||||||
@ -45,7 +49,10 @@ public {{this.name}} = {
|
|||||||
txData: TxData = {},
|
txData: TxData = {},
|
||||||
): string {
|
): string {
|
||||||
const self = this as {{contractName}}Contract;
|
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;
|
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: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",
|
"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",
|
"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",
|
"migrate": "node ../deployer/lib/src/cli.js migrate",
|
||||||
"lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'",
|
"lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'",
|
||||||
"test:circleci": "yarn test"
|
"test:circleci": "yarn test"
|
||||||
@ -58,6 +58,7 @@
|
|||||||
"types-bn": "^0.0.1",
|
"types-bn": "^0.0.1",
|
||||||
"types-ethereumjs-util": "0xProject/types-ethereumjs-util",
|
"types-ethereumjs-util": "0xProject/types-ethereumjs-util",
|
||||||
"typescript": "2.7.1",
|
"typescript": "2.7.1",
|
||||||
|
"ethers-typescript-typings": "^0.0.1",
|
||||||
"web3-typescript-typings": "^0.9.11",
|
"web3-typescript-typings": "^0.9.11",
|
||||||
"yargs": "^10.0.3"
|
"yargs": "^10.0.3"
|
||||||
},
|
},
|
||||||
@ -72,6 +73,7 @@
|
|||||||
"bn.js": "^4.11.8",
|
"bn.js": "^4.11.8",
|
||||||
"ethereumjs-abi": "^0.6.4",
|
"ethereumjs-abi": "^0.6.4",
|
||||||
"ethereumjs-util": "^5.1.1",
|
"ethereumjs-util": "^5.1.1",
|
||||||
|
"ethers-contracts": "^2.2.1",
|
||||||
"isomorphic-fetch": "^2.2.1",
|
"isomorphic-fetch": "^2.2.1",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"request": "^2.81.0",
|
"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 {
|
import { LogWithDecodedArgs, SignedOrder, TransactionReceiptWithDecodedLogs, ZeroEx } from '0x.js';
|
||||||
LogCancelContractEventArgs,
|
|
||||||
LogErrorContractEventArgs,
|
|
||||||
LogFillContractEventArgs,
|
|
||||||
LogWithDecodedArgs,
|
|
||||||
SignedOrder,
|
|
||||||
TransactionReceiptWithDecodedLogs,
|
|
||||||
ZeroEx,
|
|
||||||
} from '0x.js';
|
|
||||||
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
|
||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
@ -15,7 +7,12 @@ import ethUtil = require('ethereumjs-util');
|
|||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
|
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 { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
|
||||||
import { Balances } from '../../util/balances';
|
import { Balances } from '../../util/balances';
|
||||||
import { constants } from '../../util/constants';
|
import { constants } from '../../util/constants';
|
||||||
@ -63,16 +60,20 @@ describe('Exchange', () => {
|
|||||||
deployer.deployAsync(ContractName.DummyToken),
|
deployer.deployAsync(ContractName.DummyToken),
|
||||||
deployer.deployAsync(ContractName.DummyToken),
|
deployer.deployAsync(ContractName.DummyToken),
|
||||||
]);
|
]);
|
||||||
rep = new DummyTokenContract(repInstance);
|
rep = new DummyTokenContract(web3Wrapper, repInstance.abi, repInstance.address);
|
||||||
dgd = new DummyTokenContract(dgdInstance);
|
dgd = new DummyTokenContract(web3Wrapper, dgdInstance.abi, dgdInstance.address);
|
||||||
zrx = new DummyTokenContract(zrxInstance);
|
zrx = new DummyTokenContract(web3Wrapper, zrxInstance.abi, zrxInstance.address);
|
||||||
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
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, [
|
const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [
|
||||||
zrx.address,
|
zrx.address,
|
||||||
tokenTransferProxy.address,
|
tokenTransferProxy.address,
|
||||||
]);
|
]);
|
||||||
exchange = new ExchangeContract(exchangeInstance);
|
exchange = new ExchangeContract(web3Wrapper, exchangeInstance.abi, exchangeInstance.address);
|
||||||
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] });
|
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] });
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, {
|
zeroEx = new ZeroEx(web3.currentProvider, {
|
||||||
exchangeContractAddress: exchange.address,
|
exchangeContractAddress: exchange.address,
|
||||||
@ -650,7 +651,7 @@ describe('Exchange', () => {
|
|||||||
|
|
||||||
it('should not change balances if makerTokenAddress is ZRX, makerTokenAmount + makerFee > maker allowance, \
|
it('should not change balances if makerTokenAddress is ZRX, makerTokenAmount + makerFee > maker allowance, \
|
||||||
and shouldThrowOnInsufficientBalanceOrAllowance = false', async () => {
|
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({
|
signedOrder = await orderFactory.newSignedOrderAsync({
|
||||||
makerTokenAddress: zrx.address,
|
makerTokenAddress: zrx.address,
|
||||||
makerTokenAmount: new BigNumber(makerZRXAllowance),
|
makerTokenAmount: new BigNumber(makerZRXAllowance),
|
||||||
@ -676,7 +677,7 @@ describe('Exchange', () => {
|
|||||||
|
|
||||||
it('should not change balances if takerTokenAddress is ZRX, takerTokenAmount + takerFee > taker allowance, \
|
it('should not change balances if takerTokenAddress is ZRX, takerTokenAmount + takerFee > taker allowance, \
|
||||||
and shouldThrowOnInsufficientBalanceOrAllowance = false', async () => {
|
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({
|
signedOrder = await orderFactory.newSignedOrderAsync({
|
||||||
takerTokenAddress: zrx.address,
|
takerTokenAddress: zrx.address,
|
||||||
takerTokenAmount: new BigNumber(takerZRXAllowance),
|
takerTokenAmount: new BigNumber(takerZRXAllowance),
|
||||||
@ -723,7 +724,7 @@ describe('Exchange', () => {
|
|||||||
const res = await exWrapper.fillOrderAsync(signedOrder, taker);
|
const res = await exWrapper.fillOrderAsync(signedOrder, taker);
|
||||||
expect(res.logs).to.have.length(1);
|
expect(res.logs).to.have.length(1);
|
||||||
const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>;
|
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);
|
expect(errCode).to.be.equal(ExchangeContractErrs.ERROR_ORDER_EXPIRED);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -734,7 +735,7 @@ describe('Exchange', () => {
|
|||||||
const res = await exWrapper.fillOrderAsync(signedOrder, taker);
|
const res = await exWrapper.fillOrderAsync(signedOrder, taker);
|
||||||
expect(res.logs).to.have.length(1);
|
expect(res.logs).to.have.length(1);
|
||||||
const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>;
|
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);
|
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);
|
const res = await exWrapper.cancelOrderAsync(signedOrder, maker);
|
||||||
expect(res.logs).to.have.length(1);
|
expect(res.logs).to.have.length(1);
|
||||||
const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>;
|
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);
|
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);
|
const res = await exWrapper.cancelOrderAsync(signedOrder, maker);
|
||||||
expect(res.logs).to.have.length(1);
|
expect(res.logs).to.have.length(1);
|
||||||
const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>;
|
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);
|
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 * as chai from 'chai';
|
||||||
import ethUtil = require('ethereumjs-util');
|
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 { constants } from '../../util/constants';
|
||||||
import { ExchangeWrapper } from '../../util/exchange_wrapper';
|
import { ExchangeWrapper } from '../../util/exchange_wrapper';
|
||||||
import { OrderFactory } from '../../util/order_factory';
|
import { OrderFactory } from '../../util/order_factory';
|
||||||
@ -42,7 +47,7 @@ describe('Exchange', () => {
|
|||||||
zrx.address,
|
zrx.address,
|
||||||
tokenTransferProxy.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] });
|
await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] });
|
||||||
const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID });
|
const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID });
|
||||||
exchangeWrapper = new ExchangeWrapper(exchange, zeroEx);
|
exchangeWrapper = new ExchangeWrapper(exchange, zeroEx);
|
||||||
@ -50,8 +55,8 @@ describe('Exchange', () => {
|
|||||||
exchangeContractAddress: exchange.address,
|
exchangeContractAddress: exchange.address,
|
||||||
maker,
|
maker,
|
||||||
feeRecipient,
|
feeRecipient,
|
||||||
makerToken: rep.address,
|
makerTokenAddress: rep.address,
|
||||||
takerToken: dgd.address,
|
takerTokenAddress: dgd.address,
|
||||||
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
|
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
|
||||||
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
|
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
|
||||||
makerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
|
makerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
|
||||||
|
@ -7,7 +7,12 @@ import * as _ from 'lodash';
|
|||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
|
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 { TokenRegistryContract } from '../../src/contract_wrappers/generated/token_registry';
|
||||||
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
|
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
|
||||||
import { Balances } from '../../util/balances';
|
import { Balances } from '../../util/balances';
|
||||||
@ -55,18 +60,26 @@ describe('Exchange', () => {
|
|||||||
deployer.deployAsync(ContractName.DummyToken),
|
deployer.deployAsync(ContractName.DummyToken),
|
||||||
deployer.deployAsync(ContractName.DummyToken),
|
deployer.deployAsync(ContractName.DummyToken),
|
||||||
]);
|
]);
|
||||||
rep = new DummyTokenContract(repInstance);
|
rep = new DummyTokenContract(web3Wrapper, repInstance.abi, repInstance.address);
|
||||||
dgd = new DummyTokenContract(dgdInstance);
|
dgd = new DummyTokenContract(web3Wrapper, dgdInstance.abi, dgdInstance.address);
|
||||||
zrx = new DummyTokenContract(zrxInstance);
|
zrx = new DummyTokenContract(web3Wrapper, zrxInstance.abi, zrxInstance.address);
|
||||||
const tokenRegistryInstance = await deployer.deployAsync(ContractName.TokenRegistry);
|
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);
|
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, [
|
const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [
|
||||||
zrx.address,
|
zrx.address,
|
||||||
tokenTransferProxy.address,
|
tokenTransferProxy.address,
|
||||||
]);
|
]);
|
||||||
exchange = new ExchangeContract(exchangeInstance);
|
exchange = new ExchangeContract(web3Wrapper, exchangeInstance.abi, exchangeInstance.address);
|
||||||
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] });
|
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] });
|
||||||
const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID });
|
const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID });
|
||||||
exWrapper = new ExchangeWrapper(exchange, zeroEx);
|
exWrapper = new ExchangeWrapper(exchange, zeroEx);
|
||||||
|
@ -59,10 +59,14 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
SIGNATURES_REQUIRED,
|
SIGNATURES_REQUIRED,
|
||||||
0,
|
0,
|
||||||
]);
|
]);
|
||||||
multiSig = new MultiSigWalletWithTimeLockContract(multiSigInstance);
|
multiSig = new MultiSigWalletWithTimeLockContract(
|
||||||
|
web3Wrapper,
|
||||||
|
multiSigInstance.abi,
|
||||||
|
multiSigInstance.address,
|
||||||
|
);
|
||||||
multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract);
|
multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract);
|
||||||
|
|
||||||
const secondsTimeLocked = await multiSig.secondsTimeLocked();
|
const secondsTimeLocked = await multiSig.secondsTimeLocked.callAsync();
|
||||||
initialSecondsTimeLocked = secondsTimeLocked.toNumber();
|
initialSecondsTimeLocked = secondsTimeLocked.toNumber();
|
||||||
});
|
});
|
||||||
it('should throw when not called by wallet', async () => {
|
it('should throw when not called by wallet', async () => {
|
||||||
@ -113,7 +117,7 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
const blockNum = await web3Wrapper.getBlockNumberAsync();
|
const blockNum = await web3Wrapper.getBlockNumberAsync();
|
||||||
const blockInfo = await web3Wrapper.getBlockAsync(blockNum);
|
const blockInfo = await web3Wrapper.getBlockAsync(blockNum);
|
||||||
const timestamp = new BigNumber(blockInfo.timestamp);
|
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);
|
expect(timestamp).to.be.bignumber.equal(confirmationTimeBigNum);
|
||||||
});
|
});
|
||||||
@ -141,7 +145,7 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
const res = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
expect(res.logs).to.have.length(2);
|
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);
|
expect(secondsTimeLocked).to.be.bignumber.equal(SECONDS_TIME_LOCKED);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -152,10 +156,14 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
SIGNATURES_REQUIRED,
|
SIGNATURES_REQUIRED,
|
||||||
SECONDS_TIME_LOCKED,
|
SECONDS_TIME_LOCKED,
|
||||||
]);
|
]);
|
||||||
multiSig = new MultiSigWalletWithTimeLockContract(multiSigInstance);
|
multiSig = new MultiSigWalletWithTimeLockContract(
|
||||||
|
web3Wrapper,
|
||||||
|
multiSigInstance.abi,
|
||||||
|
multiSigInstance.address,
|
||||||
|
);
|
||||||
multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract);
|
multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract);
|
||||||
|
|
||||||
const secondsTimeLocked = await multiSig.secondsTimeLocked();
|
const secondsTimeLocked = await multiSig.secondsTimeLocked.callAsync();
|
||||||
initialSecondsTimeLocked = secondsTimeLocked.toNumber();
|
initialSecondsTimeLocked = secondsTimeLocked.toNumber();
|
||||||
const destination = multiSig.address;
|
const destination = multiSig.address;
|
||||||
const from = owners[0];
|
const from = owners[0];
|
||||||
@ -187,7 +195,7 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
await rpc.increaseTimeAsync(SECONDS_TIME_LOCKED.toNumber());
|
await rpc.increaseTimeAsync(SECONDS_TIME_LOCKED.toNumber());
|
||||||
await multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] });
|
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);
|
expect(secondsTimeLocked).to.be.bignumber.equal(newSecondsTimeLocked);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -49,7 +49,11 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
[authorizedAddress, unauthorizedAddress] = accounts;
|
[authorizedAddress, unauthorizedAddress] = accounts;
|
||||||
const initialOwner = accounts[0];
|
const initialOwner = accounts[0];
|
||||||
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
||||||
tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
|
tokenTransferProxy = new TokenTransferProxyContract(
|
||||||
|
web3Wrapper,
|
||||||
|
tokenTransferProxyInstance.abi,
|
||||||
|
tokenTransferProxyInstance.address,
|
||||||
|
);
|
||||||
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(authorizedAddress, {
|
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(authorizedAddress, {
|
||||||
from: initialOwner,
|
from: initialOwner,
|
||||||
});
|
});
|
||||||
@ -57,7 +61,11 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
ContractName.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,
|
ContractName.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,
|
||||||
[owners, requiredApprovals, SECONDS_TIME_LOCKED, tokenTransferProxy.address],
|
[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, {
|
await tokenTransferProxy.transferOwnership.sendTransactionAsync(multiSig.address, {
|
||||||
from: initialOwner,
|
from: initialOwner,
|
||||||
});
|
});
|
||||||
@ -74,12 +82,14 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
describe('isFunctionRemoveAuthorizedAddress', () => {
|
describe('isFunctionRemoveAuthorizedAddress', () => {
|
||||||
it('should throw if data is not for removeAuthorizedAddress', async () => {
|
it('should throw if data is not for removeAuthorizedAddress', async () => {
|
||||||
const data = MultiSigWrapper.encodeFnArgs('addAuthorizedAddress', PROXY_ABI, [owners[0]]);
|
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 () => {
|
it('should return true if data is for removeAuthorizedAddress', async () => {
|
||||||
const data = MultiSigWrapper.encodeFnArgs('removeAuthorizedAddress', PROXY_ABI, [owners[0]]);
|
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();
|
expect(isFunctionRemoveAuthorizedAddress).to.be.true();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -114,7 +124,7 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
||||||
const txId = log.args.transactionId;
|
const txId = log.args.transactionId;
|
||||||
await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
|
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();
|
expect(isConfirmed).to.be.true();
|
||||||
|
|
||||||
return expect(
|
return expect(
|
||||||
@ -133,7 +143,7 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
||||||
const txId = log.args.transactionId;
|
const txId = log.args.transactionId;
|
||||||
await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
|
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();
|
expect(isConfirmed).to.be.true();
|
||||||
|
|
||||||
return expect(
|
return expect(
|
||||||
@ -152,10 +162,10 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
||||||
const txId = log.args.transactionId;
|
const txId = log.args.transactionId;
|
||||||
await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
|
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();
|
expect(isConfirmed).to.be.true();
|
||||||
await multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] });
|
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();
|
expect(isAuthorized).to.be.false();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -170,10 +180,10 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
|
|||||||
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
|
||||||
const txId = log.args.transactionId;
|
const txId = log.args.transactionId;
|
||||||
await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
|
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();
|
expect(isConfirmed).to.be.true();
|
||||||
await multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] });
|
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];
|
const isExecuted = tx[3];
|
||||||
expect(isExecuted).to.be.true();
|
expect(isExecuted).to.be.true();
|
||||||
return expect(
|
return expect(
|
||||||
|
@ -31,7 +31,7 @@ describe('TokenRegistry', () => {
|
|||||||
owner = accounts[0];
|
owner = accounts[0];
|
||||||
notOwner = accounts[1];
|
notOwner = accounts[1];
|
||||||
const tokenRegInstance = await deployer.deployAsync(ContractName.TokenRegistry);
|
const tokenRegInstance = await deployer.deployAsync(ContractName.TokenRegistry);
|
||||||
tokenReg = new TokenRegistryContract(tokenRegInstance);
|
tokenReg = new TokenRegistryContract(web3Wrapper, tokenRegInstance.abi, tokenRegInstance.address);
|
||||||
tokenRegWrapper = new TokenRegWrapper(tokenReg);
|
tokenRegWrapper = new TokenRegWrapper(tokenReg);
|
||||||
});
|
});
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
@ -25,7 +25,11 @@ describe('TokenTransferProxy', () => {
|
|||||||
owner = address = accounts[0];
|
owner = address = accounts[0];
|
||||||
notOwner = accounts[1];
|
notOwner = accounts[1];
|
||||||
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
||||||
tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
|
tokenTransferProxy = new TokenTransferProxyContract(
|
||||||
|
web3Wrapper,
|
||||||
|
tokenTransferProxyInstance.abi,
|
||||||
|
tokenTransferProxyInstance.address,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await blockchainLifecycle.startAsync();
|
await blockchainLifecycle.startAsync();
|
||||||
@ -41,7 +45,7 @@ describe('TokenTransferProxy', () => {
|
|||||||
});
|
});
|
||||||
it('should allow owner to add an authorized address', async () => {
|
it('should allow owner to add an authorized address', async () => {
|
||||||
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, { from: owner });
|
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();
|
expect(isAuthorized).to.be.true();
|
||||||
});
|
});
|
||||||
it('should throw if owner attempts to authorize a duplicate address', async () => {
|
it('should throw if owner attempts to authorize a duplicate address', async () => {
|
||||||
@ -67,7 +71,7 @@ describe('TokenTransferProxy', () => {
|
|||||||
await tokenTransferProxy.removeAuthorizedAddress.sendTransactionAsync(address, {
|
await tokenTransferProxy.removeAuthorizedAddress.sendTransactionAsync(address, {
|
||||||
from: owner,
|
from: owner,
|
||||||
});
|
});
|
||||||
const isAuthorized = await tokenTransferProxy.authorized(address);
|
const isAuthorized = await tokenTransferProxy.authorized.callAsync(address);
|
||||||
expect(isAuthorized).to.be.false();
|
expect(isAuthorized).to.be.false();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -82,19 +86,19 @@ describe('TokenTransferProxy', () => {
|
|||||||
|
|
||||||
describe('getAuthorizedAddresses', () => {
|
describe('getAuthorizedAddresses', () => {
|
||||||
it('should return all authorized addresses', async () => {
|
it('should return all authorized addresses', async () => {
|
||||||
const initial = await tokenTransferProxy.getAuthorizedAddresses();
|
const initial = await tokenTransferProxy.getAuthorizedAddresses.callAsync();
|
||||||
expect(initial).to.have.length(0);
|
expect(initial).to.have.length(0);
|
||||||
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, {
|
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, {
|
||||||
from: owner,
|
from: owner,
|
||||||
});
|
});
|
||||||
const afterAdd = await tokenTransferProxy.getAuthorizedAddresses();
|
const afterAdd = await tokenTransferProxy.getAuthorizedAddresses.callAsync();
|
||||||
expect(afterAdd).to.have.length(1);
|
expect(afterAdd).to.have.length(1);
|
||||||
expect(afterAdd).to.include(address);
|
expect(afterAdd).to.include(address);
|
||||||
|
|
||||||
await tokenTransferProxy.removeAuthorizedAddress.sendTransactionAsync(address, {
|
await tokenTransferProxy.removeAuthorizedAddress.sendTransactionAsync(address, {
|
||||||
from: owner,
|
from: owner,
|
||||||
});
|
});
|
||||||
const afterRemove = await tokenTransferProxy.getAuthorizedAddresses();
|
const afterRemove = await tokenTransferProxy.getAuthorizedAddresses.callAsync();
|
||||||
expect(afterRemove).to.have.length(0);
|
expect(afterRemove).to.have.length(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -33,9 +33,13 @@ describe('TokenTransferProxy', () => {
|
|||||||
accounts = await web3Wrapper.getAvailableAddressesAsync();
|
accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||||
owner = notAuthorized = accounts[0];
|
owner = notAuthorized = accounts[0];
|
||||||
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
|
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);
|
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]]);
|
dmyBalances = new Balances([rep], [accounts[0], accounts[1]]);
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
@ -35,7 +35,7 @@ describe('UnlimitedAllowanceToken', () => {
|
|||||||
owner = accounts[0];
|
owner = accounts[0];
|
||||||
spender = accounts[1];
|
spender = accounts[1];
|
||||||
const tokenInstance = await deployer.deployAsync(ContractName.DummyToken);
|
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 });
|
await token.mint.sendTransactionAsync(MAX_MINT_VALUE, { from: owner });
|
||||||
tokenAddress = token.address;
|
tokenAddress = token.address;
|
||||||
});
|
});
|
||||||
|
@ -36,7 +36,7 @@ describe('ZRXToken', () => {
|
|||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
});
|
});
|
||||||
const zrxInstance = await deployer.deployAsync(ContractName.ZRXToken);
|
const zrxInstance = await deployer.deployAsync(ContractName.ZRXToken);
|
||||||
zrx = new ZRXTokenContract(zrxInstance);
|
zrx = new ZRXTokenContract(web3Wrapper, zrxInstance.abi, zrxInstance.address);
|
||||||
zrxAddress = zrx.address;
|
zrxAddress = zrx.address;
|
||||||
MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
|
MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
|
||||||
});
|
});
|
||||||
@ -48,25 +48,25 @@ describe('ZRXToken', () => {
|
|||||||
});
|
});
|
||||||
describe('constants', () => {
|
describe('constants', () => {
|
||||||
it('should have 18 decimals', async () => {
|
it('should have 18 decimals', async () => {
|
||||||
const decimals = new BigNumber(await zrx.decimals());
|
const decimals = new BigNumber(await zrx.decimals.callAsync());
|
||||||
const expectedDecimals = 18;
|
const expectedDecimals = 18;
|
||||||
expect(decimals).to.be.bignumber.equal(expectedDecimals);
|
expect(decimals).to.be.bignumber.equal(expectedDecimals);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have a total supply of 1 billion tokens', async () => {
|
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;
|
const expectedTotalSupply = 1000000000;
|
||||||
expect(ZeroEx.toUnitAmount(totalSupply, 18)).to.be.bignumber.equal(expectedTotalSupply);
|
expect(ZeroEx.toUnitAmount(totalSupply, 18)).to.be.bignumber.equal(expectedTotalSupply);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be named 0x Protocol Token', async () => {
|
it('should be named 0x Protocol Token', async () => {
|
||||||
const name = await zrx.name();
|
const name = await zrx.name.callAsync();
|
||||||
const expectedName = '0x Protocol Token';
|
const expectedName = '0x Protocol Token';
|
||||||
expect(name).to.be.equal(expectedName);
|
expect(name).to.be.equal(expectedName);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have the symbol ZRX', async () => {
|
it('should have the symbol ZRX', async () => {
|
||||||
const symbol = await zrx.symbol();
|
const symbol = await zrx.symbol.callAsync();
|
||||||
const expectedSymbol = 'ZRX';
|
const expectedSymbol = 'ZRX';
|
||||||
expect(symbol).to.be.equal(expectedSymbol);
|
expect(symbol).to.be.equal(expectedSymbol);
|
||||||
});
|
});
|
||||||
@ -75,7 +75,7 @@ describe('ZRXToken', () => {
|
|||||||
describe('constructor', () => {
|
describe('constructor', () => {
|
||||||
it('should initialize owner balance to totalSupply', async () => {
|
it('should initialize owner balance to totalSupply', async () => {
|
||||||
const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
|
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);
|
expect(totalSupply).to.be.bignumber.equal(ownerBalance);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"../../node_modules/types-ethereumjs-util/index.d.ts",
|
"../../node_modules/types-ethereumjs-util/index.d.ts",
|
||||||
"../../node_modules/chai-typescript-typings/index.d.ts",
|
"../../node_modules/chai-typescript-typings/index.d.ts",
|
||||||
"../../node_modules/web3-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/chai-as-promised-typescript-typings/index.d.ts",
|
||||||
"../../node_modules/types-ethereumjs-util/index.d.ts",
|
"../../node_modules/types-ethereumjs-util/index.d.ts",
|
||||||
"../../node_modules/types-bn/index.d.ts",
|
"../../node_modules/types-bn/index.d.ts",
|
||||||
|
@ -17,7 +17,7 @@ export class Balances {
|
|||||||
const balancesByOwner: BalancesByOwner = {};
|
const balancesByOwner: BalancesByOwner = {};
|
||||||
for (const tokenContractInstance of this._tokenContractInstances) {
|
for (const tokenContractInstance of this._tokenContractInstances) {
|
||||||
for (const ownerAddress of this._ownerAddresses) {
|
for (const ownerAddress of this._ownerAddresses) {
|
||||||
let balance = await tokenContractInstance.balanceOf(ownerAddress);
|
let balance = await tokenContractInstance.balanceOf.callAsync(ownerAddress);
|
||||||
balance = new BigNumber(balance);
|
balance = new BigNumber(balance);
|
||||||
if (_.isUndefined(balancesByOwner[ownerAddress])) {
|
if (_.isUndefined(balancesByOwner[ownerAddress])) {
|
||||||
balancesByOwner[ownerAddress] = {};
|
balancesByOwner[ownerAddress] = {};
|
||||||
|
@ -186,11 +186,11 @@ export class ExchangeWrapper {
|
|||||||
public async getOrderHashAsync(signedOrder: SignedOrder): Promise<string> {
|
public async getOrderHashAsync(signedOrder: SignedOrder): Promise<string> {
|
||||||
const shouldThrowOnInsufficientBalanceOrAllowance = false;
|
const shouldThrowOnInsufficientBalanceOrAllowance = false;
|
||||||
const params = signedOrderUtils.getOrderAddressesAndValues(signedOrder);
|
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;
|
return orderHash;
|
||||||
}
|
}
|
||||||
public async isValidSignatureAsync(signedOrder: SignedOrder): Promise<boolean> {
|
public async isValidSignatureAsync(signedOrder: SignedOrder): Promise<boolean> {
|
||||||
const isValidSignature = await this._exchange.isValidSignature(
|
const isValidSignature = await this._exchange.isValidSignature.callAsync(
|
||||||
signedOrder.maker,
|
signedOrder.maker,
|
||||||
ZeroEx.getOrderHashHex(signedOrder),
|
ZeroEx.getOrderHashHex(signedOrder),
|
||||||
signedOrder.ecSignature.v,
|
signedOrder.ecSignature.v,
|
||||||
@ -204,7 +204,7 @@ export class ExchangeWrapper {
|
|||||||
denominator: BigNumber,
|
denominator: BigNumber,
|
||||||
target: BigNumber,
|
target: BigNumber,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const isRoundingError = await this._exchange.isRoundingError(numerator, denominator, target);
|
const isRoundingError = await this._exchange.isRoundingError.callAsync(numerator, denominator, target);
|
||||||
return isRoundingError;
|
return isRoundingError;
|
||||||
}
|
}
|
||||||
public async getPartialAmountAsync(
|
public async getPartialAmountAsync(
|
||||||
@ -212,7 +212,9 @@ export class ExchangeWrapper {
|
|||||||
denominator: BigNumber,
|
denominator: BigNumber,
|
||||||
target: BigNumber,
|
target: BigNumber,
|
||||||
): Promise<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;
|
return partialAmount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,36 +22,36 @@ export class TokenRegWrapper {
|
|||||||
return tx;
|
return tx;
|
||||||
}
|
}
|
||||||
public async getTokenMetaDataAsync(tokenAddress: string) {
|
public async getTokenMetaDataAsync(tokenAddress: string) {
|
||||||
const data = await this._tokenReg.getTokenMetaData(tokenAddress);
|
const data = await this._tokenReg.getTokenMetaData.callAsync(tokenAddress);
|
||||||
const token: Token = {
|
const token: Token = {
|
||||||
address: data[0],
|
address: data[0],
|
||||||
name: data[1],
|
name: data[1],
|
||||||
symbol: data[2],
|
symbol: data[2],
|
||||||
decimals: data[3].toNumber(),
|
decimals: data[3],
|
||||||
ipfsHash: data[4],
|
ipfsHash: data[4],
|
||||||
swarmHash: data[5],
|
swarmHash: data[5],
|
||||||
};
|
};
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
public async getTokenByNameAsync(tokenName: string) {
|
public async getTokenByNameAsync(tokenName: string) {
|
||||||
const data = await this._tokenReg.getTokenByName(tokenName);
|
const data = await this._tokenReg.getTokenByName.callAsync(tokenName);
|
||||||
const token: Token = {
|
const token: Token = {
|
||||||
address: data[0],
|
address: data[0],
|
||||||
name: data[1],
|
name: data[1],
|
||||||
symbol: data[2],
|
symbol: data[2],
|
||||||
decimals: data[3].toNumber(),
|
decimals: data[3],
|
||||||
ipfsHash: data[4],
|
ipfsHash: data[4],
|
||||||
swarmHash: data[5],
|
swarmHash: data[5],
|
||||||
};
|
};
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
public async getTokenBySymbolAsync(tokenSymbol: string) {
|
public async getTokenBySymbolAsync(tokenSymbol: string) {
|
||||||
const data = await this._tokenReg.getTokenBySymbol(tokenSymbol);
|
const data = await this._tokenReg.getTokenBySymbol.callAsync(tokenSymbol);
|
||||||
const token: Token = {
|
const token: Token = {
|
||||||
address: data[0],
|
address: data[0],
|
||||||
name: data[1],
|
name: data[1],
|
||||||
symbol: data[2],
|
symbol: data[2],
|
||||||
decimals: data[3].toNumber(),
|
decimals: data[3],
|
||||||
ipfsHash: data[4],
|
ipfsHash: data[4],
|
||||||
swarmHash: data[5],
|
swarmHash: data[5],
|
||||||
};
|
};
|
||||||
|
@ -41,8 +41,8 @@ export interface DefaultOrderParams {
|
|||||||
exchangeContractAddress: string;
|
exchangeContractAddress: string;
|
||||||
maker: string;
|
maker: string;
|
||||||
feeRecipient: string;
|
feeRecipient: string;
|
||||||
makerToken: string;
|
makerTokenAddress: string;
|
||||||
takerToken: string;
|
takerTokenAddress: string;
|
||||||
makerTokenAmount: BigNumber;
|
makerTokenAmount: BigNumber;
|
||||||
takerTokenAmount: BigNumber;
|
takerTokenAmount: BigNumber;
|
||||||
makerFee: BigNumber;
|
makerFee: BigNumber;
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
"tslint": "5.8.0",
|
"tslint": "5.8.0",
|
||||||
"types-bn": "^0.0.1",
|
"types-bn": "^0.0.1",
|
||||||
"typescript": "2.7.1",
|
"typescript": "2.7.1",
|
||||||
|
"ethers-typescript-typings": "^0.0.1",
|
||||||
"web3-typescript-typings": "^0.9.11"
|
"web3-typescript-typings": "^0.9.11"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -10,8 +10,8 @@ import { constants } from './utils/constants';
|
|||||||
import { CliOptions, CompilerOptions, DeployerOptions } from './utils/types';
|
import { CliOptions, CompilerOptions, DeployerOptions } from './utils/types';
|
||||||
|
|
||||||
const DEFAULT_OPTIMIZER_ENABLED = false;
|
const DEFAULT_OPTIMIZER_ENABLED = false;
|
||||||
const DEFAULT_CONTRACTS_DIR = path.resolve('src');
|
const DEFAULT_CONTRACTS_DIR = path.resolve('src/contracts');
|
||||||
const DEFAULT_ARTIFACTS_DIR = path.resolve('artifacts');
|
const DEFAULT_ARTIFACTS_DIR = path.resolve('src/artifacts');
|
||||||
const DEFAULT_NETWORK_ID = 50;
|
const DEFAULT_NETWORK_ID = 50;
|
||||||
const DEFAULT_JSONRPC_PORT = 8545;
|
const DEFAULT_JSONRPC_PORT = 8545;
|
||||||
const DEFAULT_GAS_PRICE = (10 ** 9 * 2).toString();
|
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> {
|
function getContractsSetFromList(contracts: string): Set<string> {
|
||||||
const specifiedContracts = new Set();
|
const specifiedContracts = new Set();
|
||||||
|
if (contracts === '*') {
|
||||||
|
return new Set(['*']);
|
||||||
|
}
|
||||||
const contractsArray = contracts.split(',');
|
const contractsArray = contracts.split(',');
|
||||||
_.forEach(contractsArray, contractName => {
|
_.forEach(contractsArray, contractName => {
|
||||||
const fileName = `${contractName}${constants.SOLIDITY_FILE_EXTENSION}`;
|
const fileName = `${contractName}${constants.SOLIDITY_FILE_EXTENSION}`;
|
||||||
|
@ -174,7 +174,7 @@ export class Deployer {
|
|||||||
const block = await this.web3Wrapper.getBlockAsync('latest');
|
const block = await this.web3Wrapper.getBlockAsync('latest');
|
||||||
let gas: number;
|
let gas: number;
|
||||||
try {
|
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);
|
gas = Math.min(gasEstimate + EXTRA_GAS, block.gasLimit);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
gas = block.gasLimit;
|
gas = block.gasLimit;
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"../../node_modules/types-bn/index.d.ts",
|
"../../node_modules/types-bn/index.d.ts",
|
||||||
"../../node_modules/types-ethereumjs-util/index.d.ts",
|
"../../node_modules/types-ethereumjs-util/index.d.ts",
|
||||||
"../../node_modules/chai-typescript-typings/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/web3-typescript-typings/index.d.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
"./test/**/*",
|
"./test/**/*",
|
||||||
"../../node_modules/types-bn/index.d.ts",
|
"../../node_modules/types-bn/index.d.ts",
|
||||||
"../../node_modules/chai-typescript-typings/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/web3-typescript-typings/index.d.ts",
|
||||||
"../../node_modules/types-ethereumjs-util/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
|
# 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_
|
## v0.2.1 - _February 9, 2018_
|
||||||
|
|
||||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
* 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';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
export interface TxData {
|
export interface TxData {
|
||||||
|
data?: string;
|
||||||
from?: string;
|
from?: string;
|
||||||
gas?: number;
|
gas?: number;
|
||||||
gasPrice?: BigNumber;
|
gasPrice?: BigNumber;
|
||||||
@ -38,7 +39,7 @@ export enum AbiType {
|
|||||||
Fallback = 'fallback',
|
Fallback = 'fallback',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ContractEventArg = string | BigNumber;
|
export type ContractEventArg = string | BigNumber | number;
|
||||||
|
|
||||||
export interface DecodedLogArgs {
|
export interface DecodedLogArgs {
|
||||||
[argName: string]: ContractEventArg;
|
[argName: string]: ContractEventArg;
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
## v0.4.0 - _TBD, 2018_
|
||||||
|
|
||||||
|
* Use `ethers-contracts` as a backend to decode event args (#413)
|
||||||
|
|
||||||
## v0.3.2 - _February 9, 2018_
|
## v0.3.2 - _February 9, 2018_
|
||||||
|
|
||||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||||
|
@ -26,11 +26,13 @@
|
|||||||
"shx": "^0.2.2",
|
"shx": "^0.2.2",
|
||||||
"tslint": "5.8.0",
|
"tslint": "5.8.0",
|
||||||
"typescript": "2.7.1",
|
"typescript": "2.7.1",
|
||||||
|
"ethers-typescript-typings": "^0.0.1",
|
||||||
"web3-typescript-typings": "^0.9.11"
|
"web3-typescript-typings": "^0.9.11"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0xproject/types": "^0.2.3",
|
"@0xproject/types": "^0.2.3",
|
||||||
"bignumber.js": "~4.1.0",
|
"bignumber.js": "~4.1.0",
|
||||||
|
"ethers-contracts": "^2.2.1",
|
||||||
"js-sha3": "^0.7.0",
|
"js-sha3": "^0.7.0",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"web3": "^0.20.0"
|
"web3": "^0.20.0"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { AbiType, DecodedLogArgs, LogWithDecodedArgs, RawLog, SolidityTypes } from '@0xproject/types';
|
import { AbiType, DecodedLogArgs, LogWithDecodedArgs, RawLog, SolidityTypes } from '@0xproject/types';
|
||||||
|
import * as ethersContracts from 'ethers-contracts';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
import * as SolidityCoder from 'web3/lib/solidity/coder';
|
|
||||||
|
|
||||||
import { BigNumber } from './configured_bignumber';
|
import { BigNumber } from './configured_bignumber';
|
||||||
|
|
||||||
@ -27,31 +27,29 @@ export class AbiDecoder {
|
|||||||
if (_.isUndefined(event)) {
|
if (_.isUndefined(event)) {
|
||||||
return log;
|
return log;
|
||||||
}
|
}
|
||||||
|
const ethersInterface = new ethersContracts.Interface([event]);
|
||||||
const logData = log.data;
|
const logData = log.data;
|
||||||
const decodedParams: DecodedLogArgs = {};
|
const decodedParams: DecodedLogArgs = {};
|
||||||
let dataIndex = 0;
|
|
||||||
let topicsIndex = 1;
|
let topicsIndex = 1;
|
||||||
|
|
||||||
const nonIndexedInputs = _.filter(event.inputs, input => !input.indexed);
|
const nonIndexedInputs = _.filter(event.inputs, input => !input.indexed);
|
||||||
const dataTypes = _.map(nonIndexedInputs, input => input.type);
|
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;
|
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
|
// 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)) {
|
if (_.isUndefined(value)) {
|
||||||
failedToDecode = true;
|
failedToDecode = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (param.type === SolidityTypes.Address) {
|
if (param.type === SolidityTypes.Address) {
|
||||||
value = AbiDecoder._padZeros(new BigNumber(value).toString(16));
|
value = AbiDecoder._padZeros(new BigNumber(value).toString(16));
|
||||||
} else if (
|
} else if (param.type === SolidityTypes.Uint256 || param.type === SolidityTypes.Uint) {
|
||||||
param.type === SolidityTypes.Uint256 ||
|
|
||||||
param.type === SolidityTypes.Uint8 ||
|
|
||||||
param.type === SolidityTypes.Uint
|
|
||||||
) {
|
|
||||||
value = new BigNumber(value);
|
value = new BigNumber(value);
|
||||||
|
} else if (param.type === SolidityTypes.Uint8) {
|
||||||
|
value = new BigNumber(value).toNumber();
|
||||||
}
|
}
|
||||||
decodedParams[param.name] = value;
|
decodedParams[param.name] = value;
|
||||||
});
|
});
|
||||||
@ -67,11 +65,14 @@ export class AbiDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private _addABI(abiArray: Web3.AbiDefinition[]): void {
|
private _addABI(abiArray: Web3.AbiDefinition[]): void {
|
||||||
|
if (_.isUndefined(abiArray)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const ethersInterface = new ethersContracts.Interface(abiArray);
|
||||||
_.map(abiArray, (abi: Web3.AbiDefinition) => {
|
_.map(abiArray, (abi: Web3.AbiDefinition) => {
|
||||||
if (abi.type === AbiType.Event) {
|
if (abi.type === AbiType.Event) {
|
||||||
const signature = `${abi.name}(${_.map(abi.inputs, input => input.type).join(',')})`;
|
const topic = ethersInterface.events[abi.name].topic;
|
||||||
const signatureHash = new Web3().sha3(signature);
|
this._methodIds[topic] = abi;
|
||||||
this._methodIds[signatureHash] = abi;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this._savedABIs = this._savedABIs.concat(abiArray);
|
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": {
|
"compilerOptions": {
|
||||||
"outDir": "lib"
|
"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
|
# CHANGELOG
|
||||||
|
|
||||||
## v0.2.XX - _TBD_ 2018
|
## v0.2.0 _TBD, 2018_
|
||||||
|
|
||||||
* Ensure all returned user addresses are lowercase (#373)
|
* 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)
|
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||||
|
@ -26,11 +26,13 @@
|
|||||||
"shx": "^0.2.2",
|
"shx": "^0.2.2",
|
||||||
"tslint": "5.8.0",
|
"tslint": "5.8.0",
|
||||||
"typescript": "2.7.1",
|
"typescript": "2.7.1",
|
||||||
|
"ethers-typescript-typings": "^0.0.1",
|
||||||
"web3-typescript-typings": "^0.9.11"
|
"web3-typescript-typings": "^0.9.11"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0xproject/types": "^0.2.3",
|
"@0xproject/types": "^0.2.3",
|
||||||
"@0xproject/utils": "^0.3.4",
|
"@0xproject/utils": "^0.3.4",
|
||||||
|
"ethers-contracts": "^2.2.1",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"web3": "^0.20.0"
|
"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';
|
export { Web3Wrapper } from './web3_wrapper';
|
||||||
import { BigNumber, promisify } from '@0xproject/utils';
|
export { BaseContract } from './base_contract';
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
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": {
|
"compilerOptions": {
|
||||||
"outDir": "lib"
|
"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"
|
utf8 "^2.1.1"
|
||||||
uuid "^2.0.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:
|
ethjs-abi@0.1.8:
|
||||||
version "0.1.8"
|
version "0.1.8"
|
||||||
resolved "https://registry.yarnpkg.com/ethjs-abi/-/ethjs-abi-0.1.8.tgz#cd288583ed628cdfadaf8adefa3ba1dbcbca6c18"
|
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"
|
version "0.5.5"
|
||||||
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.5.tgz#baf0c0e8c54ad5903447df96ade7a4a1bca79a4a"
|
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:
|
js-sha3@^0.3.1:
|
||||||
version "0.3.1"
|
version "0.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243"
|
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243"
|
||||||
@ -9811,7 +9830,7 @@ xml-js@^1.3.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
sax "^1.2.4"
|
sax "^1.2.4"
|
||||||
|
|
||||||
xmlhttprequest@*:
|
xmlhttprequest@*, xmlhttprequest@1.8.0:
|
||||||
version "1.8.0"
|
version "1.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
|
resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user