aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
authorLeonid Logvinov <logvinov.leon@gmail.com>2018-04-10 20:06:43 +0800
committerLeonid Logvinov <logvinov.leon@gmail.com>2018-04-12 18:50:52 +0800
commit4dd9f29769bea90a4b687be26b086164aaff685a (patch)
tree60bb5ce2b589114d01ddce38753e31bf78664ef3 /packages
parentf2f9bd2e7ac1372073644a4e30a5d99e8c57fbb1 (diff)
downloaddexon-sol-tools-4dd9f29769bea90a4b687be26b086164aaff685a.tar
dexon-sol-tools-4dd9f29769bea90a4b687be26b086164aaff685a.tar.gz
dexon-sol-tools-4dd9f29769bea90a4b687be26b086164aaff685a.tar.bz2
dexon-sol-tools-4dd9f29769bea90a4b687be26b086164aaff685a.tar.lz
dexon-sol-tools-4dd9f29769bea90a4b687be26b086164aaff685a.tar.xz
dexon-sol-tools-4dd9f29769bea90a4b687be26b086164aaff685a.tar.zst
dexon-sol-tools-4dd9f29769bea90a4b687be26b086164aaff685a.zip
Add ony abi-gen changes from Greg's PR
Diffstat (limited to 'packages')
-rw-r--r--packages/abi-gen/src/index.ts14
-rw-r--r--packages/abi-gen/src/types.ts9
-rw-r--r--packages/abi-gen/src/utils.ts4
-rw-r--r--packages/base-contract/src/index.ts48
-rw-r--r--packages/contract_templates/contract.handlebars2
-rw-r--r--packages/contract_templates/partials/callAsync.handlebars4
-rw-r--r--packages/contract_templates/partials/tx.handlebars22
-rw-r--r--packages/deployer/package.json1
-rw-r--r--packages/deployer/src/utils/contract.ts4
-rw-r--r--packages/deployer/src/utils/encoder.ts4
-rw-r--r--packages/metacoin/artifacts/Metacoin.json95
-rw-r--r--packages/metacoin/contracts/Metacoin.sol15
-rw-r--r--packages/metacoin/test/metacoin_test.ts56
-rw-r--r--packages/utils/src/abi_utils.ts71
-rw-r--r--packages/utils/src/index.ts1
15 files changed, 297 insertions, 53 deletions
diff --git a/packages/abi-gen/src/index.ts b/packages/abi-gen/src/index.ts
index 942bb12db..ecef33b16 100644
--- a/packages/abi-gen/src/index.ts
+++ b/packages/abi-gen/src/index.ts
@@ -1,7 +1,7 @@
#!/usr/bin/env node
import { AbiDefinition, ConstructorAbi, EventAbi, MethodAbi } from '@0xproject/types';
-import { logUtils } from '@0xproject/utils';
+import { abiUtils, logUtils } from '@0xproject/utils';
import chalk from 'chalk';
import * as fs from 'fs';
import { sync as globSync } from 'glob';
@@ -12,7 +12,7 @@ import * as yargs from 'yargs';
import toSnakeCase = require('to-snake-case');
-import { ContextData, ContractsBackend, ParamKind } from './types';
+import { ContextData, ContractsBackend, Method, ParamKind } from './types';
import { utils } from './utils';
const ABI_TYPE_CONSTRUCTOR = 'constructor';
@@ -83,7 +83,6 @@ function writeOutputFile(name: string, renderedTsCode: string): void {
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input, args.backend));
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output, args.backend));
-
if (args.partials) {
registerPartials(args.partials);
}
@@ -126,11 +125,12 @@ for (const abiFileName of abiFileNames) {
}
const methodAbis = ABI.filter((abi: AbiDefinition) => abi.type === ABI_TYPE_METHOD) as MethodAbi[];
- const methodsData = _.map(methodAbis, methodAbi => {
- _.map(methodAbi.inputs, (input, i: number) => {
+ const sanitizedMethodAbis = abiUtils.renameOverloadedMethods(methodAbis) as MethodAbi[];
+ const methodsData = _.map(methodAbis, (methodAbi, methodAbiIndex: number) => {
+ _.forEach(methodAbi.inputs, (input, inputIndex: number) => {
if (_.isEmpty(input.name)) {
// Auto-generated getters don't have parameter names
- input.name = `index_${i}`;
+ input.name = `index_${inputIndex}`;
}
});
// This will make templates simpler
@@ -138,6 +138,8 @@ for (const abiFileName of abiFileNames) {
...methodAbi,
singleReturnValue: methodAbi.outputs.length === 1,
hasReturnValue: methodAbi.outputs.length !== 0,
+ tsName: sanitizedMethodAbis[methodAbiIndex].name,
+ functionSignature: abiUtils.getFunctionSignature(methodAbi),
};
return methodData;
});
diff --git a/packages/abi-gen/src/types.ts b/packages/abi-gen/src/types.ts
index df5b1feaf..648281774 100644
--- a/packages/abi-gen/src/types.ts
+++ b/packages/abi-gen/src/types.ts
@@ -5,13 +5,6 @@ export enum ParamKind {
Output = 'output',
}
-export enum AbiType {
- Function = 'function',
- Constructor = 'constructor',
- Event = 'event',
- Fallback = 'fallback',
-}
-
export enum ContractsBackend {
Web3 = 'web3',
Ethers = 'ethers',
@@ -20,6 +13,8 @@ export enum ContractsBackend {
export interface Method extends MethodAbi {
singleReturnValue: boolean;
hasReturnValue: boolean;
+ tsName: string;
+ functionSignature: string;
}
export interface ContextData {
diff --git a/packages/abi-gen/src/utils.ts b/packages/abi-gen/src/utils.ts
index 755fbc71a..20b734959 100644
--- a/packages/abi-gen/src/utils.ts
+++ b/packages/abi-gen/src/utils.ts
@@ -1,9 +1,9 @@
-import { ConstructorAbi, DataItem } from '@0xproject/types';
+import { AbiType, ConstructorAbi, DataItem } from '@0xproject/types';
import * as fs from 'fs';
import * as _ from 'lodash';
import * as path from 'path';
-import { AbiType, ContractsBackend, ParamKind } from './types';
+import { ContractsBackend, ParamKind } from './types';
export const utils = {
solTypeToTsType(paramKind: ParamKind, backend: ContractsBackend, solType: string, components?: DataItem[]): string {
diff --git a/packages/base-contract/src/index.ts b/packages/base-contract/src/index.ts
index bba686f8b..bfa99fac1 100644
--- a/packages/base-contract/src/index.ts
+++ b/packages/base-contract/src/index.ts
@@ -1,13 +1,26 @@
-import { ContractAbi, DataItem, Provider, TxData, TxDataPayable } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
+import {
+ AbiDefinition,
+ AbiType,
+ ContractAbi,
+ DataItem,
+ MethodAbi,
+ Provider,
+ TxData,
+ TxDataPayable,
+} from '@0xproject/types';
+import { abiUtils, BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as ethersContracts from 'ethers-contracts';
import * as _ from 'lodash';
import { formatABIDataItem } from './utils';
+export interface EthersInterfaceByFunctionSignature {
+ [key: string]: ethersContracts.Interface;
+}
+
export class BaseContract {
- protected _ethersInterface: ethersContracts.Interface;
+ protected _ethersInterfacesByFunctionSignature: EthersInterfaceByFunctionSignature;
protected _web3Wrapper: Web3Wrapper;
public abi: ContractAbi;
public address: string;
@@ -49,10 +62,37 @@ export class BaseContract {
}
return txDataWithDefaults;
}
+ protected _lookupEthersInterface(functionSignature: string): ethersContracts.Interface {
+ const ethersInterface = this._ethersInterfacesByFunctionSignature[functionSignature];
+ if (_.isUndefined(ethersInterface)) {
+ throw new Error(`Failed to lookup method with function signature '${functionSignature}'`);
+ }
+ return ethersInterface;
+ }
+ protected _lookupAbi(functionSignature: string): MethodAbi {
+ const methodAbi = _.find(this.abi, (abiDefinition: AbiDefinition) => {
+ if (abiDefinition.type !== AbiType.Function) {
+ return false;
+ }
+ const abiFunctionSignature = abiUtils.getFunctionSignature(abiDefinition);
+ if (abiFunctionSignature === functionSignature) {
+ return true;
+ }
+ return false;
+ }) as MethodAbi;
+ return methodAbi;
+ }
constructor(abi: ContractAbi, address: string, provider: Provider, defaults?: Partial<TxData>) {
this._web3Wrapper = new Web3Wrapper(provider, defaults);
this.abi = abi;
this.address = address;
- this._ethersInterface = new ethersContracts.Interface(abi);
+ const methodAbis = this.abi.filter(
+ (abiDefinition: AbiDefinition) => abiDefinition.type === AbiType.Function,
+ ) as MethodAbi[];
+ this._ethersInterfacesByFunctionSignature = {};
+ _.each(methodAbis, methodAbi => {
+ const functionSignature = abiUtils.getFunctionSignature(methodAbi);
+ this._ethersInterfacesByFunctionSignature[functionSignature] = new ethersContracts.Interface([methodAbi]);
+ });
}
}
diff --git a/packages/contract_templates/contract.handlebars b/packages/contract_templates/contract.handlebars
index 3e3f87f10..472452d74 100644
--- a/packages/contract_templates/contract.handlebars
+++ b/packages/contract_templates/contract.handlebars
@@ -41,6 +41,6 @@ export class {{contractName}}Contract extends BaseContract {
{{/each}}
constructor(abi: ContractAbi, address: string, provider: Provider, defaults?: Partial<TxData>) {
super(abi, address, provider, defaults);
- classUtils.bindAll(this, ['_ethersInterface', 'address', 'abi', '_web3Wrapper']);
+ classUtils.bindAll(this, ['_ethersInterfacesByFunctionSignature', 'address', 'abi', '_web3Wrapper']);
}
} // tslint:disable:max-file-line-count
diff --git a/packages/contract_templates/partials/callAsync.handlebars b/packages/contract_templates/partials/callAsync.handlebars
index 8de69203e..a6f4abdf2 100644
--- a/packages/contract_templates/partials/callAsync.handlebars
+++ b/packages/contract_templates/partials/callAsync.handlebars
@@ -5,9 +5,9 @@ async callAsync(
defaultBlock?: BlockParam,
): Promise<{{> return_type outputs=outputs}}> {
const self = this as any as {{contractName}}Contract;
- const inputAbi = (_.find(self.abi, {name: '{{this.name}}'}) as MethodAbi).inputs;
+ const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs;
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self));
- const encodedData = self._ethersInterface.functions.{{this.name}}(
+ const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}(
{{> params inputs=inputs}}
).data;
const callDataWithDefaults = await self._applyDefaultsToTxDataAsync(
diff --git a/packages/contract_templates/partials/tx.handlebars b/packages/contract_templates/partials/tx.handlebars
index 41ba6d3f7..22fe0c597 100644
--- a/packages/contract_templates/partials/tx.handlebars
+++ b/packages/contract_templates/partials/tx.handlebars
@@ -1,4 +1,4 @@
-public {{this.name}} = {
+public {{this.tsName}} = {
async sendTransactionAsync(
{{> typed_params inputs=inputs}}
{{#this.payable}}
@@ -9,17 +9,17 @@ public {{this.name}} = {
{{/this.payable}}
): Promise<string> {
const self = this as any as {{contractName}}Contract;
- const inputAbi = (_.find(self.abi, {name: '{{this.name}}'}) as MethodAbi).inputs;
+ const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs;
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self));
- const encodedData = self._ethersInterface.functions.{{this.name}}(
+ const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}(
{{> params inputs=inputs}}
- ).data
+ ).data;
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
{
...txData,
data: encodedData,
},
- self.{{this.name}}.estimateGasAsync.bind(
+ self.{{this.tsName}}.estimateGasAsync.bind(
self,
{{> params inputs=inputs}}
),
@@ -32,11 +32,11 @@ public {{this.name}} = {
txData: Partial<TxData> = {},
): Promise<number> {
const self = this as any as {{contractName}}Contract;
- const inputAbi = (_.find(self.abi, {name: '{{this.name}}'}) as MethodAbi).inputs;
+ const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs;
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(this));
- const encodedData = self._ethersInterface.functions.{{this.name}}(
+ const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}(
{{> params inputs=inputs}}
- ).data
+ ).data;
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
{
...txData,
@@ -50,11 +50,11 @@ public {{this.name}} = {
{{> typed_params inputs=inputs}}
): string {
const self = this as any as {{contractName}}Contract;
- const inputAbi = (_.find(self.abi, {name: '{{this.name}}'}) as MethodAbi).inputs;
+ const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs;
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self));
- const abiEncodedTransactionData = self._ethersInterface.functions.{{this.name}}(
+ const abiEncodedTransactionData = self._lookupEthersInterface('{{this.name}}').functions.{{this.name}}(
{{> params inputs=inputs}}
- ).data
+ ).data;
return abiEncodedTransactionData;
},
{{> callAsync}}
diff --git a/packages/deployer/package.json b/packages/deployer/package.json
index ef5c1cd16..6afaa13b3 100644
--- a/packages/deployer/package.json
+++ b/packages/deployer/package.json
@@ -53,6 +53,7 @@
"@types/require-from-string": "^1.2.0",
"@types/semver": "^5.5.0",
"chai": "^4.0.1",
+ "chai-as-promised": "^7.1.0",
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"mocha": "^4.0.1",
diff --git a/packages/deployer/src/utils/contract.ts b/packages/deployer/src/utils/contract.ts
index 9b7baac11..e8dd5218a 100644
--- a/packages/deployer/src/utils/contract.ts
+++ b/packages/deployer/src/utils/contract.ts
@@ -1,11 +1,9 @@
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
-import { ContractAbi, EventAbi, FunctionAbi, MethodAbi, TxData } from '@0xproject/types';
+import { AbiType, ContractAbi, EventAbi, FunctionAbi, MethodAbi, TxData } from '@0xproject/types';
import { promisify } from '@0xproject/utils';
import * as _ from 'lodash';
import * as Web3 from 'web3';
-import { AbiType } from './types';
-
export class Contract implements Web3.ContractInstance {
public address: string;
public abi: ContractAbi;
diff --git a/packages/deployer/src/utils/encoder.ts b/packages/deployer/src/utils/encoder.ts
index 4f62662e1..806efbbca 100644
--- a/packages/deployer/src/utils/encoder.ts
+++ b/packages/deployer/src/utils/encoder.ts
@@ -1,9 +1,7 @@
-import { AbiDefinition, ContractAbi, DataItem } from '@0xproject/types';
+import { AbiDefinition, AbiType, ContractAbi, DataItem } from '@0xproject/types';
import * as _ from 'lodash';
import * as web3Abi from 'web3-eth-abi';
-import { AbiType } from './types';
-
export const encoder = {
encodeConstructorArgsFromAbi(args: any[], abi: ContractAbi): string {
const constructorTypes: string[] = [];
diff --git a/packages/metacoin/artifacts/Metacoin.json b/packages/metacoin/artifacts/Metacoin.json
index 46c3ee71c..3531a1683 100644
--- a/packages/metacoin/artifacts/Metacoin.json
+++ b/packages/metacoin/artifacts/Metacoin.json
@@ -3,11 +3,50 @@
"networks": {
"50": {
"solc_version": "0.4.21",
- "keccak256": "0x2c3aa2e9dbef58abf57cecc148464d0852a83d7f30bbd2066f2a13b8bd3b1dd0",
- "source_tree_hash": "0x2c3aa2e9dbef58abf57cecc148464d0852a83d7f30bbd2066f2a13b8bd3b1dd0",
+ "keccak256": "0x85fb29ea6c21adcf07f754b2ad06482dd6fcd62d31935e36041b4d064c6a038e",
+ "source_tree_hash": "0x85fb29ea6c21adcf07f754b2ad06482dd6fcd62d31935e36041b4d064c6a038e",
"optimizer_enabled": false,
"abi": [
{
+ "constant": false,
+ "inputs": [
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferData",
+ "type": "tuple"
+ },
+ {
+ "name": "callback",
+ "type": "uint32"
+ }
+ ],
+ "name": "nestedTransferData",
+ "type": "tuple"
+ }
+ ],
+ "name": "transfer",
+ "outputs": [
+ {
+ "name": "",
+ "type": "int256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [
{
@@ -56,6 +95,39 @@
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "components": [
+ {
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferData",
+ "type": "tuple"
+ },
+ {
+ "name": "callback",
+ "type": "uint32"
+ }
+ ],
+ "name": "transfer",
+ "outputs": [
+ {
+ "name": "",
+ "type": "int256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"inputs": [],
"payable": false,
"stateMutability": "nonpayable",
@@ -84,15 +156,14 @@
"type": "event"
}
],
- "bytecode":
- "0x6060604052341561000f57600080fd5b6127106000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610406806100636000396000f30060606040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806327e235e3146100515780632bd14bb914610087575b600080fd5b341561005c57600080fd5b610071600461006c9036906102b9565b6100bd565b60405161007e9190610344565b60405180910390f35b341561009257600080fd5b6100a760046100a29036906102e2565b6100d5565b6040516100b49190610329565b60405180910390f35b60006020528060005260406000206000915090505481565b600081602001516000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101561012a5760009050610240565b81602001516000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160200151600080846000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84602001516040516102339190610344565b60405180910390a3600190505b919050565b600061025182356103a2565b905092915050565b60006040828403121561026b57600080fd5b610275604061035f565b9050600061028584828501610245565b6000830152506020610299848285016102a5565b60208301525092915050565b60006102b182356103c2565b905092915050565b6000602082840312156102cb57600080fd5b60006102d984828501610245565b91505092915050565b6000604082840312156102f457600080fd5b600061030284828501610259565b91505092915050565b6103148161038c565b82525050565b61032381610398565b82525050565b600060208201905061033e600083018461030b565b92915050565b6000602082019050610359600083018461031a565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561038257600080fd5b8060405250919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008190509190505600a265627a7a72305820d15828219194e8ddaa624e10f9c8823c05268d79753b4c60ef401fb4fe5f09dc6c6578706572696d656e74616cf50037",
- "runtime_bytecode":
- "0x60606040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806327e235e3146100515780632bd14bb914610087575b600080fd5b341561005c57600080fd5b610071600461006c9036906102b9565b6100bd565b60405161007e9190610344565b60405180910390f35b341561009257600080fd5b6100a760046100a29036906102e2565b6100d5565b6040516100b49190610329565b60405180910390f35b60006020528060005260406000206000915090505481565b600081602001516000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101561012a5760009050610240565b81602001516000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160200151600080846000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84602001516040516102339190610344565b60405180910390a3600190505b919050565b600061025182356103a2565b905092915050565b60006040828403121561026b57600080fd5b610275604061035f565b9050600061028584828501610245565b6000830152506020610299848285016102a5565b60208301525092915050565b60006102b182356103c2565b905092915050565b6000602082840312156102cb57600080fd5b60006102d984828501610245565b91505092915050565b6000604082840312156102f457600080fd5b600061030284828501610259565b91505092915050565b6103148161038c565b82525050565b61032381610398565b82525050565b600060208201905061033e600083018461030b565b92915050565b6000602082019050610359600083018461031a565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561038257600080fd5b8060405250919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008190509190505600a265627a7a72305820d15828219194e8ddaa624e10f9c8823c05268d79753b4c60ef401fb4fe5f09dc6c6578706572696d656e74616cf50037",
- "updated_at": 1522318279735,
- "source_map": "60:662:0:-;;;290:72;;;;;;;;350:5;327:8;:20;336:10;327:20;;;;;;;;;;;;;;;:28;;;;60:662;;;;;;",
- "source_map_runtime":
- "60:662:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;368:352;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84:41;;;;;;;;;;;;;;;;;:::o;368:352::-;429:12;480;:19;;;457:8;:20;466:10;457:20;;;;;;;;;;;;;;;;:42;453:60;;;508:5;501:12;;;;453:60;547:12;:19;;;523:8;:20;532:10;523:20;;;;;;;;;;;;;;;;:43;;;;;;;;;;;605:12;:19;;;576:8;:25;585:12;:15;;;576:25;;;;;;;;;;;;;;;;:48;;;;;;;;;;;655:12;:15;;;634:58;;643:10;634:58;;;672:12;:19;;;634:58;;;;;;;;;;;;;;;709:4;702:11;;368:352;;;;:::o;5:118:-1:-;;72:46;110:6;97:20;72:46;;;63:55;;57:66;;;;;165:469;;282:4;270:9;265:3;261:19;257:30;254:2;;;300:1;297;290:12;254:2;318:20;333:4;318:20;;;309:29;;386:1;417:49;462:3;453:6;442:9;438:22;417:49;;;411:3;404:5;400:15;393:74;348:130;530:2;563:49;608:3;599:6;588:9;584:22;563:49;;;556:4;549:5;545:16;538:75;488:136;248:386;;;;;641:118;;708:46;746:6;733:20;708:46;;;699:55;;693:66;;;;;766:241;;870:2;858:9;849:7;845:23;841:32;838:2;;;886:1;883;876:12;838:2;921:1;938:53;983:7;974:6;963:9;959:22;938:53;;;928:63;;900:97;832:175;;;;;1014:297;;1146:2;1134:9;1125:7;1121:23;1117:32;1114:2;;;1162:1;1159;1152:12;1114:2;1197:1;1214:81;1287:7;1278:6;1267:9;1263:22;1214:81;;;1204:91;;1176:125;1108:203;;;;;1318:101;1385:28;1407:5;1385:28;;;1380:3;1373:41;1367:52;;;1426:110;1499:31;1524:5;1499:31;;;1494:3;1487:44;1481:55;;;1543:181;;1645:2;1634:9;1630:18;1622:26;;1659:55;1711:1;1700:9;1696:17;1687:6;1659:55;;;1616:108;;;;;1731:193;;1839:2;1828:9;1824:18;1816:26;;1853:61;1911:1;1900:9;1896:17;1887:6;1853:61;;;1810:114;;;;;1931:256;;1993:2;1987:9;1977:19;;2031:4;2023:6;2019:17;2130:6;2118:10;2115:22;2094:18;2082:10;2079:34;2076:62;2073:2;;;2151:1;2148;2141:12;2073:2;2171:10;2167:2;2160:22;1971:216;;;;;2194:92;;2274:5;2267:13;2260:21;2249:32;;2243:43;;;;2293:79;;2362:5;2351:16;;2345:27;;;;2379:128;;2459:42;2452:5;2448:54;2437:65;;2431:76;;;;2514:79;;2583:5;2572:16;;2566:27;;;",
- "sources": ["Metacoin.sol"]
+ "bytecode": "0x6060604052341561000f57600080fd5b6127106000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610613806100636000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063135cfdb11461006757806327e235e31461009d5780632bd14bb9146100d35780632f8086ba14610109575b600080fd5b341561007257600080fd5b6100876004610082903690610446565b61013f565b604051610094919061051c565b60405180910390f35b34156100a857600080fd5b6100bd60046100b890369061041d565b61015a565b6040516100ca9190610537565b60405180910390f35b34156100de57600080fd5b6100f360046100ee90369061046f565b610172565b6040516101009190610501565b60405180910390f35b341561011457600080fd5b6101296004610124903690610498565b6102e2565b604051610136919061051c565b60405180910390f35b6000610153826000015183602001516102e2565b9050919050565b60006020528060005260406000206000915090505481565b600081602001516000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156101c757600090506102dd565b81602001516000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160200151600080846000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84602001516040516102d09190610537565b60405180910390a3600190505b919050565b60006102ed83610172565b508163ffffffff16905092915050565b6000610309823561059f565b905092915050565b60006060828403121561032357600080fd5b61032d6040610552565b9050600061033d8482850161035d565b600083015250604061035184828501610409565b60208301525092915050565b60006040828403121561036f57600080fd5b6103796040610552565b90506000610389848285016102fd565b600083015250602061039d848285016103f5565b60208301525092915050565b6000604082840312156103bb57600080fd5b6103c56040610552565b905060006103d5848285016102fd565b60008301525060206103e9848285016103f5565b60208301525092915050565b600061040182356105bf565b905092915050565b600061041582356105c9565b905092915050565b60006020828403121561042f57600080fd5b600061043d848285016102fd565b91505092915050565b60006060828403121561045857600080fd5b600061046684828501610311565b91505092915050565b60006040828403121561048157600080fd5b600061048f848285016103a9565b91505092915050565b600080606083850312156104ab57600080fd5b60006104b9858286016103a9565b92505060406104ca85828601610409565b9150509250929050565b6104dd8161057f565b82525050565b6104ec8161058b565b82525050565b6104fb81610595565b82525050565b600060208201905061051660008301846104d4565b92915050565b600060208201905061053160008301846104e3565b92915050565b600060208201905061054c60008301846104f2565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561057557600080fd5b8060405250919050565b60008115159050919050565b6000819050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600063ffffffff821690509190505600a265627a7a723058207dad40553c9997face2fbb94ecdaa66f3336759e728fd02bc7b545c9a05076766c6578706572696d656e74616cf50037",
+ "runtime_bytecode": "0x606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063135cfdb11461006757806327e235e31461009d5780632bd14bb9146100d35780632f8086ba14610109575b600080fd5b341561007257600080fd5b6100876004610082903690610446565b61013f565b604051610094919061051c565b60405180910390f35b34156100a857600080fd5b6100bd60046100b890369061041d565b61015a565b6040516100ca9190610537565b60405180910390f35b34156100de57600080fd5b6100f360046100ee90369061046f565b610172565b6040516101009190610501565b60405180910390f35b341561011457600080fd5b6101296004610124903690610498565b6102e2565b604051610136919061051c565b60405180910390f35b6000610153826000015183602001516102e2565b9050919050565b60006020528060005260406000206000915090505481565b600081602001516000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156101c757600090506102dd565b81602001516000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160200151600080846000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84602001516040516102d09190610537565b60405180910390a3600190505b919050565b60006102ed83610172565b508163ffffffff16905092915050565b6000610309823561059f565b905092915050565b60006060828403121561032357600080fd5b61032d6040610552565b9050600061033d8482850161035d565b600083015250604061035184828501610409565b60208301525092915050565b60006040828403121561036f57600080fd5b6103796040610552565b90506000610389848285016102fd565b600083015250602061039d848285016103f5565b60208301525092915050565b6000604082840312156103bb57600080fd5b6103c56040610552565b905060006103d5848285016102fd565b60008301525060206103e9848285016103f5565b60208301525092915050565b600061040182356105bf565b905092915050565b600061041582356105c9565b905092915050565b60006020828403121561042f57600080fd5b600061043d848285016102fd565b91505092915050565b60006060828403121561045857600080fd5b600061046684828501610311565b91505092915050565b60006040828403121561048157600080fd5b600061048f848285016103a9565b91505092915050565b600080606083850312156104ab57600080fd5b60006104b9858286016103a9565b92505060406104ca85828601610409565b9150509250929050565b6104dd8161057f565b82525050565b6104ec8161058b565b82525050565b6104fb81610595565b82525050565b600060208201905061051660008301846104d4565b92915050565b600060208201905061053160008301846104e3565b92915050565b600060208201905061054c60008301846104f2565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561057557600080fd5b8060405250919050565b60008115159050919050565b6000819050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600063ffffffff821690509190505600a265627a7a723058207dad40553c9997face2fbb94ecdaa66f3336759e728fd02bc7b545c9a05076766c6578706572696d656e74616cf50037",
+ "updated_at": 1523361870927,
+ "source_map": "60:1093:0:-;;;389:72;;;;;;;;449:5;426:8;:20;435:10;426:20;;;;;;;;;;;;;;;:28;;;;60:1093;;;;;;",
+ "source_map_runtime": "60:1093:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;978:172;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;467:352;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;825:147;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;978:172;1051:3;1073:70;1082:18;:31;;;1115:18;:27;;;1073:8;:70::i;:::-;1066:77;;978:172;;;:::o;84:41::-;;;;;;;;;;;;;;;;;:::o;467:352::-;528:12;579;:19;;;556:8;:20;565:10;556:20;;;;;;;;;;;;;;;;:42;552:60;;;607:5;600:12;;;;552:60;646:12;:19;;;622:8;:20;631:10;622:20;;;;;;;;;;;;;;;;:43;;;;;;;;;;;704:12;:19;;;675:8;:25;684:12;:15;;;675:25;;;;;;;;;;;;;;;;:48;;;;;;;;;;;754:12;:15;;;733:58;;742:10;733:58;;;771:12;:19;;;733:58;;;;;;;;;;;;;;;808:4;801:11;;467:352;;;;:::o;825:147::-;903:3;918:22;927:12;918:8;:22::i;:::-;;957:8;950:15;;;;825:147;;;;:::o;5:118:-1:-;;72:46;110:6;97:20;72:46;;;63:55;;57:66;;;;;171:510;;294:4;282:9;277:3;273:19;269:30;266:2;;;312:1;309;302:12;266:2;330:20;345:4;330:20;;;321:29;;408:1;439:73;508:3;499:6;488:9;484:22;439:73;;;433:3;426:5;422:15;415:98;360:164;578:2;611:48;655:3;646:6;635:9;631:22;611:48;;;604:4;597:5;593:16;586:74;534:137;260:421;;;;;723:465;;836:4;824:9;819:3;815:19;811:30;808:2;;;854:1;851;844:12;808:2;872:20;887:4;872:20;;;863:29;;940:1;971:49;1016:3;1007:6;996:9;992:22;971:49;;;965:3;958:5;954:15;947:74;902:130;1084:2;1117:49;1162:3;1153:6;1142:9;1138:22;1117:49;;;1110:4;1103:5;1099:16;1092:75;1042:136;802:386;;;;;1230:469;;1347:4;1335:9;1330:3;1326:19;1322:30;1319:2;;;1365:1;1362;1355:12;1319:2;1383:20;1398:4;1383:20;;;1374:29;;1451:1;1482:49;1527:3;1518:6;1507:9;1503:22;1482:49;;;1476:3;1469:5;1465:15;1458:74;1413:130;1595:2;1628:49;1673:3;1664:6;1653:9;1649:22;1628:49;;;1621:4;1614:5;1610:16;1603:75;1553:136;1313:386;;;;;1706:118;;1773:46;1811:6;1798:20;1773:46;;;1764:55;;1758:66;;;;;1831:116;;1897:45;1934:6;1921:20;1897:45;;;1888:54;;1882:65;;;;;1954:241;;2058:2;2046:9;2037:7;2033:23;2029:32;2026:2;;;2074:1;2071;2064:12;2026:2;2109:1;2126:53;2171:7;2162:6;2151:9;2147:22;2126:53;;;2116:63;;2088:97;2020:175;;;;;2202:309;;2340:2;2328:9;2319:7;2315:23;2311:32;2308:2;;;2356:1;2353;2346:12;2308:2;2391:1;2408:87;2487:7;2478:6;2467:9;2463:22;2408:87;;;2398:97;;2370:131;2302:209;;;;;2518:297;;2650:2;2638:9;2629:7;2625:23;2621:32;2618:2;;;2666:1;2663;2656:12;2618:2;2701:1;2718:81;2791:7;2782:6;2771:9;2767:22;2718:81;;;2708:91;;2680:125;2612:203;;;;;2822:420;;;2970:2;2958:9;2949:7;2945:23;2941:32;2938:2;;;2986:1;2983;2976:12;2938:2;3021:1;3038:81;3111:7;3102:6;3091:9;3087:22;3038:81;;;3028:91;;3000:125;3156:2;3174:52;3218:7;3209:6;3198:9;3194:22;3174:52;;;3164:62;;3135:97;2932:310;;;;;;3249:101;3316:28;3338:5;3316:28;;;3311:3;3304:41;3298:52;;;3357:107;3428:30;3452:5;3428:30;;;3423:3;3416:43;3410:54;;;3471:110;3544:31;3569:5;3544:31;;;3539:3;3532:44;3526:55;;;3588:181;;3690:2;3679:9;3675:18;3667:26;;3704:55;3756:1;3745:9;3741:17;3732:6;3704:55;;;3661:108;;;;;3776:189;;3882:2;3871:9;3867:18;3859:26;;3896:59;3952:1;3941:9;3937:17;3928:6;3896:59;;;3853:112;;;;;3972:193;;4080:2;4069:9;4065:18;4057:26;;4094:61;4152:1;4141:9;4137:17;4128:6;4094:61;;;4051:114;;;;;4172:256;;4234:2;4228:9;4218:19;;4272:4;4264:6;4260:17;4371:6;4359:10;4356:22;4335:18;4323:10;4320:34;4317:62;4314:2;;;4392:1;4389;4382:12;4314:2;4412:10;4408:2;4401:22;4212:216;;;;;4435:92;;4515:5;4508:13;4501:21;4490:32;;4484:43;;;;4534:78;;4602:5;4591:16;;4585:27;;;;4619:79;;4688:5;4677:16;;4671:27;;;;4705:128;;4785:42;4778:5;4774:54;4763:65;;4757:76;;;;4840:79;;4909:5;4898:16;;4892:27;;;;4926:95;;5005:10;4998:5;4994:22;4983:33;;4977:44;;;",
+ "sources": [
+ "Metacoin.sol"
+ ]
}
}
-}
+} \ No newline at end of file
diff --git a/packages/metacoin/contracts/Metacoin.sol b/packages/metacoin/contracts/Metacoin.sol
index 6b6814b21..ac212b32e 100644
--- a/packages/metacoin/contracts/Metacoin.sol
+++ b/packages/metacoin/contracts/Metacoin.sol
@@ -11,6 +11,11 @@ contract Metacoin {
uint256 amount;
}
+ struct NestedTransferData {
+ TransferData transferData;
+ uint32 callback;
+ }
+
function Metacoin() public {
balances[msg.sender] = 10000;
}
@@ -22,4 +27,14 @@ contract Metacoin {
Transfer(msg.sender, transferData.to, transferData.amount);
return true;
}
+
+ function transfer(TransferData transferData, uint32 callback) public returns (int) {
+ transfer(transferData);
+ return callback;
+ }
+
+ function transfer(NestedTransferData nestedTransferData) public returns (int) {
+ return transfer(nestedTransferData.transferData, nestedTransferData.callback);
+ }
+
}
diff --git a/packages/metacoin/test/metacoin_test.ts b/packages/metacoin/test/metacoin_test.ts
index 73537d342..51830d1ef 100644
--- a/packages/metacoin/test/metacoin_test.ts
+++ b/packages/metacoin/test/metacoin_test.ts
@@ -36,12 +36,12 @@ describe('Metacoin', () => {
});
});
describe('#transfer', () => {
- it(`should successfully transfer tokens`, async () => {
+ it(`should successfully transfer tokens (via transfer1)`, async () => {
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
const amount = INITIAL_BALANCE.div(2);
const oldBalance = await metacoin.balances.callAsync(ZERO_ADDRESS);
expect(oldBalance).to.be.bignumber.equal(0);
- const txHash = await metacoin.transfer.sendTransactionAsync(
+ const txHash = await metacoin.transfer1.sendTransactionAsync(
{
to: ZERO_ADDRESS,
amount,
@@ -58,5 +58,57 @@ describe('Metacoin', () => {
const newBalance = await metacoin.balances.callAsync(ZERO_ADDRESS);
expect(newBalance).to.be.bignumber.equal(amount);
});
+
+ it(`should successfully transfer tokens (via transfer2)`, async () => {
+ const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
+ const amount = INITIAL_BALANCE.div(2);
+ const oldBalance = await metacoin.balances.callAsync(ZERO_ADDRESS);
+ expect(oldBalance).to.be.bignumber.equal(0);
+ const callback = 59;
+ const txHash = await metacoin.transfer2.sendTransactionAsync(
+ {
+ to: ZERO_ADDRESS,
+ amount,
+ },
+ callback,
+ { from: devConstants.TESTRPC_FIRST_ADDRESS },
+ );
+ const txReceipt = await web3Wrapper.awaitTransactionMinedAsync(txHash);
+ const transferLogs = txReceipt.logs[0] as LogWithDecodedArgs<TransferContractEventArgs>;
+ expect(transferLogs.args).to.be.deep.equal({
+ _to: ZERO_ADDRESS,
+ _from: devConstants.TESTRPC_FIRST_ADDRESS,
+ _value: amount,
+ });
+ const newBalance = await metacoin.balances.callAsync(ZERO_ADDRESS);
+ expect(newBalance).to.be.bignumber.equal(amount);
+ });
+
+ it(`should successfully transfer tokens (via transfer3)`, async () => {
+ const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
+ const amount = INITIAL_BALANCE.div(2);
+ const oldBalance = await metacoin.balances.callAsync(ZERO_ADDRESS);
+ expect(oldBalance).to.be.bignumber.equal(0);
+ const callback = 59;
+ const txHash = await metacoin.transfer3.sendTransactionAsync(
+ {
+ transferData: {
+ to: ZERO_ADDRESS,
+ amount,
+ },
+ callback,
+ },
+ { from: devConstants.TESTRPC_FIRST_ADDRESS },
+ );
+ const txReceipt = await web3Wrapper.awaitTransactionMinedAsync(txHash);
+ const transferLogs = txReceipt.logs[0] as LogWithDecodedArgs<TransferContractEventArgs>;
+ expect(transferLogs.args).to.be.deep.equal({
+ _to: ZERO_ADDRESS,
+ _from: devConstants.TESTRPC_FIRST_ADDRESS,
+ _value: amount,
+ });
+ const newBalance = await metacoin.balances.callAsync(ZERO_ADDRESS);
+ expect(newBalance).to.be.bignumber.equal(amount);
+ });
});
});
diff --git a/packages/utils/src/abi_utils.ts b/packages/utils/src/abi_utils.ts
new file mode 100644
index 000000000..c4533d42e
--- /dev/null
+++ b/packages/utils/src/abi_utils.ts
@@ -0,0 +1,71 @@
+import { AbiDefinition, AbiType, ConstructorAbi, ContractAbi, DataItem, MethodAbi } from '@0xproject/types';
+import * as _ from 'lodash';
+
+export const abiUtils = {
+ parseFunctionParam(param: DataItem): string {
+ if (param.type === 'tuple') {
+ // Parse out tuple types into {type_1, type_2, ..., type_N}
+ const tupleComponents = param.components;
+ const paramString = _.map(tupleComponents, component => this.parseFunctionParam(component));
+ const tupleParamString = `{${paramString}}`;
+ return tupleParamString;
+ }
+ return param.type;
+ },
+ getFunctionSignature(methodAbi: MethodAbi): string {
+ const functionName = methodAbi.name;
+ const parameterTypeList = _.map(methodAbi.inputs, (param: DataItem) => this.parseFunctionParam(param));
+ const functionSignature = `${functionName}(${parameterTypeList})`;
+ return functionSignature;
+ },
+ /**
+ * Solidity supports function overloading whereas TypeScript does not.
+ * See: https://solidity.readthedocs.io/en/v0.4.21/contracts.html?highlight=overload#function-overloading
+ * In order to support overloaded functions, we suffix overloaded function names with an index.
+ * This index should be deterministic, regardless of function ordering within the smart contract. To do so,
+ * we assign indexes based on the alphabetical order of function signatures.
+ *
+ * E.g
+ * ['f(uint)', 'f(uint,byte32)']
+ * Should always be renamed to:
+ * ['f1(uint)', 'f2(uint,byte32)']
+ * Regardless of the order in which these these overloaded functions are declared within the contract ABI.
+ */
+ renameOverloadedMethods(inputContractAbi: ContractAbi): ContractAbi {
+ const contractAbi = _.cloneDeep(inputContractAbi);
+ const methodAbis = contractAbi.filter((abi: AbiDefinition) => abi.type === AbiType.Function) as MethodAbi[];
+ // Sort method Abis into alphabetical order, by function signature
+ const methodAbisOrdered = _.sortBy(methodAbis, [
+ (methodAbi: MethodAbi) => {
+ const functionSignature = this.getFunctionSignature(methodAbi);
+ return functionSignature;
+ },
+ ]);
+ // Group method Abis by name (overloaded methods will be grouped together, in alphabetical order)
+ const methodAbisByName: { [key: string]: MethodAbi[] } = {};
+ _.each(methodAbisOrdered, methodAbi => {
+ (methodAbisByName[methodAbi.name] || (methodAbisByName[methodAbi.name] = [])).push(methodAbi);
+ });
+ // Rename overloaded methods to overloadedMethodName1, overloadedMethodName2, ...
+ _.each(methodAbisByName, methodAbisWithSameName => {
+ _.each(methodAbisWithSameName, (methodAbi, i: number) => {
+ if (methodAbisWithSameName.length > 1) {
+ const overloadedMethodId = i + 1;
+ const sanitizedMethodName = `${methodAbi.name}${overloadedMethodId}`;
+ const indexOfExistingAbiWithSanitizedMethodNameIfExists = _.findIndex(
+ methodAbis,
+ currentMethodAbi => currentMethodAbi.name === sanitizedMethodName,
+ );
+ if (indexOfExistingAbiWithSanitizedMethodNameIfExists >= 0) {
+ const methodName = methodAbi.name;
+ throw new Error(
+ `Failed to rename overloaded method '${methodName}' to '${sanitizedMethodName}'. A method with this name already exists.`,
+ );
+ }
+ methodAbi.name = sanitizedMethodName;
+ }
+ });
+ });
+ return contractAbi;
+ },
+};
diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts
index 6a9c052f8..709ec93b2 100644
--- a/packages/utils/src/index.ts
+++ b/packages/utils/src/index.ts
@@ -5,4 +5,5 @@ export { intervalUtils } from './interval_utils';
export { BigNumber } from './configured_bignumber';
export { AbiDecoder } from './abi_decoder';
export { logUtils } from './log_utils';
+export { abiUtils } from './abi_utils';
export { NULL_BYTES } from './constants';