aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Hysen <hysz@users.noreply.github.com>2019-02-08 07:18:37 +0800
committerGitHub <noreply@github.com>2019-02-08 07:18:37 +0800
commit1170cf18964f67cec41d380a4fff66735dca04a5 (patch)
treec1bb8d38131ae5117754a7b2f7301f18fb40bef3
parent3939d516e67bd36a95beac1bca049842bff554e3 (diff)
parentb9ee9d2bd5b6aac11ccea5a71291e8885bbe6f7a (diff)
downloaddexon-0x-contracts-1170cf18964f67cec41d380a4fff66735dca04a5.tar
dexon-0x-contracts-1170cf18964f67cec41d380a4fff66735dca04a5.tar.gz
dexon-0x-contracts-1170cf18964f67cec41d380a4fff66735dca04a5.tar.bz2
dexon-0x-contracts-1170cf18964f67cec41d380a4fff66735dca04a5.tar.lz
dexon-0x-contracts-1170cf18964f67cec41d380a4fff66735dca04a5.tar.xz
dexon-0x-contracts-1170cf18964f67cec41d380a4fff66735dca04a5.tar.zst
dexon-0x-contracts-1170cf18964f67cec41d380a4fff66735dca04a5.zip
Merge pull request #1592 from 0xProject/feature/abiEncoder/simplifiedSigParsing
Simplified signature parsing + signature tests
-rw-r--r--packages/utils/CHANGELOG.json9
-rw-r--r--packages/utils/src/abi_encoder/evm_data_type_factory.ts87
-rw-r--r--packages/utils/src/abi_encoder/evm_data_types/method.ts5
-rw-r--r--packages/utils/src/abi_encoder/index.ts1
-rw-r--r--packages/utils/src/abi_encoder/utils/signature_parser.ts151
-rw-r--r--packages/utils/test/abi_encoder/evm_data_types_test.ts2
-rw-r--r--packages/utils/test/abi_encoder/signature_test.ts393
-rw-r--r--packages/utils/test/abi_encoder/signature_tests.ts0
8 files changed, 549 insertions, 99 deletions
diff --git a/packages/utils/CHANGELOG.json b/packages/utils/CHANGELOG.json
index 007591d18..9ce2a4c52 100644
--- a/packages/utils/CHANGELOG.json
+++ b/packages/utils/CHANGELOG.json
@@ -1,5 +1,14 @@
[
{
+ "version": "4.0.4",
+ "changes": [
+ {
+ "note": "Cleaner signature parsing",
+ "pr": 1592
+ }
+ ]
+ },
+ {
"version": "4.0.3",
"changes": [
{
diff --git a/packages/utils/src/abi_encoder/evm_data_type_factory.ts b/packages/utils/src/abi_encoder/evm_data_type_factory.ts
index 268649148..8e477f856 100644
--- a/packages/utils/src/abi_encoder/evm_data_type_factory.ts
+++ b/packages/utils/src/abi_encoder/evm_data_type_factory.ts
@@ -2,7 +2,7 @@
import { DataItem, MethodAbi } from 'ethereum-types';
import * as _ from 'lodash';
-import { generateDataItemsFromSignature } from './utils/signature_parser';
+import { generateDataItemFromSignature } from './utils/signature_parser';
import { DataType } from './abstract_data_types/data_type';
import { DataTypeFactory } from './abstract_data_types/interfaces';
@@ -134,32 +134,87 @@ export class EvmDataTypeFactory implements DataTypeFactory {
/**
* Convenience function for creating a DataType from different inputs.
- * @param input A single or set of DataItem or a DataType signature.
- * A signature in the form of '<type>' is interpreted as a `DataItem`
- * For example, 'string' is interpreted as {type: 'string'}
- * A signature in the form '(<type1>, <type2>, ..., <typen>)' is interpreted as `DataItem[]`
- * For eaxmple, '(string, uint256)' is interpreted as [{type: 'string'}, {type: 'uint256'}]
+ * @param input A single or set of DataItem or a signature for an EVM data type.
* @return DataType corresponding to input.
*/
export function create(input: DataItem | DataItem[] | string): DataType {
- // Handle different types of input
- const isSignature = typeof input === 'string';
- const isTupleSignature = isSignature && (input as string).startsWith('(');
- const shouldParseAsTuple = isTupleSignature || _.isArray(input);
- // Create input `dataItem`
+ const dataItem = consolidateDataItemsIntoSingle(input);
+ const dataType = EvmDataTypeFactory.getInstance().create(dataItem);
+ return dataType;
+}
+
+/**
+ * Convenience function to aggregate a single input or a set of inputs into a single DataItem.
+ * An array of data items is grouped into a single tuple.
+ * @param input A single data item; a set of data items; a signature.
+ * @return A single data item corresponding to input.
+ */
+function consolidateDataItemsIntoSingle(input: DataItem | DataItem[] | string): DataItem {
let dataItem: DataItem;
- if (shouldParseAsTuple) {
- const dataItems = isSignature ? generateDataItemsFromSignature(input as string) : (input as DataItem[]);
+ if (_.isArray(input)) {
+ const dataItems = input as DataItem[];
dataItem = {
name: '',
type: 'tuple',
components: dataItems,
};
} else {
- dataItem = isSignature ? generateDataItemsFromSignature(input as string)[0] : (input as DataItem);
+ dataItem = _.isString(input) ? generateDataItemFromSignature(input) : (input as DataItem);
}
- // Create data type
- const dataType = EvmDataTypeFactory.getInstance().create(dataItem);
+ return dataItem;
+}
+
+/**
+ * Convenience function for creating a Method encoder from different inputs.
+ * @param methodName name of method.
+ * @param input A single data item; a set of data items; a signature; or an array of signatures (optional).
+ * @param output A single data item; a set of data items; a signature; or an array of signatures (optional).
+ * @return Method corresponding to input.
+ */
+export function createMethod(
+ methodName: string,
+ input?: DataItem | DataItem[] | string | string[],
+ output?: DataItem | DataItem[] | string | string[],
+): Method {
+ const methodInput = _.isUndefined(input) ? [] : consolidateDataItemsIntoArray(input);
+ const methodOutput = _.isUndefined(output) ? [] : consolidateDataItemsIntoArray(output);
+ const methodAbi: MethodAbi = {
+ name: methodName,
+ inputs: methodInput,
+ outputs: methodOutput,
+ type: 'function',
+ // default fields not used by ABI
+ constant: false,
+ payable: false,
+ stateMutability: 'nonpayable',
+ };
+ const dataType = new Method(methodAbi);
return dataType;
}
+
+/**
+ * Convenience function that aggregates a single input or a set of inputs into an array of DataItems.
+ * @param input A single data item; a set of data items; a signature; or an array of signatures.
+ * @return Array of data items corresponding to input.
+ */
+function consolidateDataItemsIntoArray(input: DataItem | DataItem[] | string | string[]): DataItem[] {
+ let dataItems: DataItem[];
+ if (_.isArray(input) && _.isEmpty(input)) {
+ dataItems = [];
+ } else if (_.isArray(input) && _.isString(input[0])) {
+ dataItems = [];
+ _.each(input as string[], (signature: string) => {
+ const dataItem = generateDataItemFromSignature(signature);
+ dataItems.push(dataItem);
+ });
+ } else if (_.isArray(input)) {
+ dataItems = input as DataItem[];
+ } else if (typeof input === 'string') {
+ const dataItem = generateDataItemFromSignature(input);
+ dataItems = [dataItem];
+ } else {
+ dataItems = [input as DataItem];
+ }
+ return dataItems;
+}
/* tslint:enable no-construct */
diff --git a/packages/utils/src/abi_encoder/evm_data_types/method.ts b/packages/utils/src/abi_encoder/evm_data_types/method.ts
index c852a0fdf..93746fa00 100644
--- a/packages/utils/src/abi_encoder/evm_data_types/method.ts
+++ b/packages/utils/src/abi_encoder/evm_data_types/method.ts
@@ -65,6 +65,11 @@ export class MethodDataType extends AbstractSetDataType {
return this._methodSelector;
}
+ public getReturnValueDataItem(): DataItem {
+ const returnValueDataItem = this._returnDataType.getDataItem();
+ return returnValueDataItem;
+ }
+
private _computeSignature(): string {
const memberSignature = this._computeSignatureOfMembers();
const methodSignature = `${this.getDataItem().name}${memberSignature}`;
diff --git a/packages/utils/src/abi_encoder/index.ts b/packages/utils/src/abi_encoder/index.ts
index cfacfe075..976bac8e6 100644
--- a/packages/utils/src/abi_encoder/index.ts
+++ b/packages/utils/src/abi_encoder/index.ts
@@ -12,5 +12,6 @@ export {
Tuple,
UInt,
create,
+ createMethod,
} from './evm_data_type_factory';
export { DataType } from './abstract_data_types/data_type';
diff --git a/packages/utils/src/abi_encoder/utils/signature_parser.ts b/packages/utils/src/abi_encoder/utils/signature_parser.ts
index 315784cea..d3996bf8e 100644
--- a/packages/utils/src/abi_encoder/utils/signature_parser.ts
+++ b/packages/utils/src/abi_encoder/utils/signature_parser.ts
@@ -1,101 +1,88 @@
import { DataItem } from 'ethereum-types';
import * as _ from 'lodash';
+interface Node {
+ name: string;
+ value: string;
+ children: Node[];
+ parent?: Node;
+}
+
+function parseNode(node: Node): DataItem {
+ const components: DataItem[] = [];
+ _.each(node.children, (child: Node) => {
+ const component = parseNode(child);
+ components.push(component);
+ });
+ const dataItem: DataItem = {
+ name: node.name,
+ type: node.value,
+ };
+ if (!_.isEmpty(components)) {
+ dataItem.components = components;
+ }
+ return dataItem;
+}
+
/**
- * Returns an array of DataItem's corresponding to the input signature.
- * A signature can be in two forms: '<DataItem.type>' or '(<DataItem1.type>, <DataItem2.type>, ...)
- * An example of the first form would be 'address' or 'uint256'
- * An example of the second form would be '(address, uint256)'
- * Signatures can also include a name field, for example: 'foo address' or '(foo address, bar uint256)'
- * @param signature of input DataItems
- * @return DataItems derived from input signature
+ * Returns a DataItem corresponding to the input signature.
+ * A signature can be in two forms: `type` or `(type_1,type_2,...,type_n)`
+ * An example of the first form would be 'address' or 'uint256[]' or 'bytes[5][]'
+ * An example of the second form would be '(address,uint256)' or '(address,uint256)[]'
+ * @param signature of input DataItem.
+ * @return DataItem derived from input signature.
*/
-export function generateDataItemsFromSignature(signature: string): DataItem[] {
- let trimmedSignature = signature;
- if (signature.startsWith('(')) {
- if (!signature.endsWith(')')) {
- throw new Error(`Failed to generate data item. Must end with ')'`);
- }
- trimmedSignature = signature.substr(1, signature.length - 2);
+export function generateDataItemFromSignature(signature: string): DataItem {
+ // No data item corresponds to an empty signature
+ if (_.isEmpty(signature)) {
+ throw new Error(`Cannot parse data item from empty signature, ''`);
}
- trimmedSignature += ',';
- let isCurrTokenArray = false;
- let currTokenArrayModifier = '';
- let isParsingArrayModifier = false;
- let currToken = '';
- let parenCount = 0;
- let currTokenName = '';
- const dataItems: DataItem[] = [];
- for (const char of trimmedSignature) {
- // Tokenize the type string while keeping track of parentheses.
+ // Create a parse tree for data item
+ let node: Node = {
+ name: '',
+ value: '',
+ children: [],
+ };
+ for (const char of signature) {
switch (char) {
case '(':
- parenCount += 1;
- currToken += char;
+ const child = {
+ name: '',
+ value: '',
+ children: [],
+ parent: node,
+ };
+ node.value = 'tuple';
+ node.children.push(child);
+ node = child;
break;
+
case ')':
- parenCount -= 1;
- currToken += char;
+ node = node.parent as Node;
break;
- case '[':
- if (parenCount === 0) {
- isParsingArrayModifier = true;
- isCurrTokenArray = true;
- currTokenArrayModifier += '[';
- } else {
- currToken += char;
- }
- break;
- case ']':
- if (parenCount === 0) {
- isParsingArrayModifier = false;
- currTokenArrayModifier += ']';
- } else {
- currToken += char;
- }
+
+ case ',':
+ const sibling = {
+ name: '',
+ value: '',
+ children: [],
+ parent: node.parent,
+ };
+ (node.parent as Node).children.push(sibling);
+ node = sibling;
break;
+
case ' ':
- if (parenCount === 0) {
- currTokenName = currToken;
- currToken = '';
- } else {
- currToken += char;
- }
+ node.name = node.value;
+ node.value = '';
break;
- case ',':
- if (parenCount === 0) {
- // Generate new DataItem from token
- const components = currToken.startsWith('(') ? generateDataItemsFromSignature(currToken) : [];
- const isTuple = !_.isEmpty(components);
- const dataItem: DataItem = { name: currTokenName, type: '' };
- if (isTuple) {
- dataItem.type = 'tuple';
- dataItem.components = components;
- } else {
- dataItem.type = currToken;
- }
- if (isCurrTokenArray) {
- dataItem.type += currTokenArrayModifier;
- }
- dataItems.push(dataItem);
- // reset token state
- currTokenName = '';
- currToken = '';
- isCurrTokenArray = false;
- currTokenArrayModifier = '';
- break;
- } else {
- currToken += char;
- break;
- }
+
default:
- if (isParsingArrayModifier) {
- currTokenArrayModifier += char;
- } else {
- currToken += char;
- }
+ node.value += char;
break;
}
}
- return dataItems;
+ // Interpret data item from parse tree
+ const dataItem = parseNode(node);
+ return dataItem;
}
diff --git a/packages/utils/test/abi_encoder/evm_data_types_test.ts b/packages/utils/test/abi_encoder/evm_data_types_test.ts
index c09c0d929..c80290207 100644
--- a/packages/utils/test/abi_encoder/evm_data_types_test.ts
+++ b/packages/utils/test/abi_encoder/evm_data_types_test.ts
@@ -28,7 +28,7 @@ describe('ABI Encoder: EVM Data Type Encoding/Decoding', () => {
const decodedArgs = dataType.decode(encodedArgs);
expect(decodedArgs).to.be.deep.equal(args);
// Validate signature
- const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true));
+ const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(false));
const argsEncodedFromSignature = dataTypeFromSignature.encode(args);
expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs);
});
diff --git a/packages/utils/test/abi_encoder/signature_test.ts b/packages/utils/test/abi_encoder/signature_test.ts
new file mode 100644
index 000000000..cee6fa5e5
--- /dev/null
+++ b/packages/utils/test/abi_encoder/signature_test.ts
@@ -0,0 +1,393 @@
+import * as chai from 'chai';
+import 'mocha';
+
+import { AbiEncoder } from '../../src';
+import { chaiSetup } from '../utils/chai_setup';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+describe('ABI Encoder: Signatures', () => {
+ describe('Single type', () => {
+ it('Elementary', async () => {
+ const signature = 'uint256';
+ const dataType = AbiEncoder.create(signature);
+ const dataTypeId = dataType.getDataItem().type;
+ expect(dataTypeId).to.be.equal('uint256');
+ expect(dataType.getSignature()).to.be.equal(signature);
+ });
+ it('Array', async () => {
+ const signature = 'string[]';
+ const dataType = AbiEncoder.create(signature);
+ const dataItem = dataType.getDataItem();
+ const expectedDataItem = {
+ name: '',
+ type: 'string[]',
+ };
+ expect(dataItem).to.be.deep.equal(expectedDataItem);
+ expect(dataType.getSignature()).to.be.equal(signature);
+ });
+ it('Multidimensional Array', async () => {
+ // Decode return value
+ const signature = 'uint256[4][][5]';
+ const dataType = AbiEncoder.create(signature);
+ const dataTypeId = dataType.getDataItem().type;
+ expect(dataTypeId).to.be.equal(signature);
+ expect(dataType.getSignature()).to.be.equal(signature);
+ });
+ it('Tuple with single element', async () => {
+ const signature = '(uint256)';
+ const dataType = AbiEncoder.create(signature);
+ const dataItem = dataType.getDataItem();
+ const expectedDataItem = {
+ name: '',
+ type: 'tuple',
+ components: [
+ {
+ name: '',
+ type: 'uint256',
+ },
+ ],
+ };
+ expect(dataItem).to.be.deep.equal(expectedDataItem);
+ expect(dataType.getSignature()).to.be.equal(signature);
+ });
+ it('Tuple with multiple elements', async () => {
+ const signature = '(uint256,string,bytes4)';
+ const dataType = AbiEncoder.create(signature);
+ const dataItem = dataType.getDataItem();
+ const expectedDataItem = {
+ name: '',
+ type: 'tuple',
+ components: [
+ {
+ name: '',
+ type: 'uint256',
+ },
+ {
+ name: '',
+ type: 'string',
+ },
+ {
+ name: '',
+ type: 'bytes4',
+ },
+ ],
+ };
+ expect(dataItem).to.be.deep.equal(expectedDataItem);
+ expect(dataType.getSignature()).to.be.equal(signature);
+ });
+ it('Tuple with nested array and nested tuple', async () => {
+ const signature = '(uint256[],(bytes),string[4],bytes4)';
+ const dataType = AbiEncoder.create(signature);
+ const dataItem = dataType.getDataItem();
+ const expectedDataItem = {
+ name: '',
+ type: 'tuple',
+ components: [
+ {
+ name: '',
+ type: 'uint256[]',
+ },
+ {
+ name: '',
+ type: 'tuple',
+ components: [
+ {
+ name: '',
+ type: 'bytes',
+ },
+ ],
+ },
+ {
+ name: '',
+ type: 'string[4]',
+ },
+ {
+ name: '',
+ type: 'bytes4',
+ },
+ ],
+ };
+ expect(dataItem).to.be.deep.equal(expectedDataItem);
+ expect(dataType.getSignature()).to.be.equal(signature);
+ });
+ it('Array of complex tuples', async () => {
+ const signature = '(uint256[],(bytes),string[4],bytes4)[5][4][]';
+ const dataType = AbiEncoder.create(signature);
+ const dataItem = dataType.getDataItem();
+ const expectedDataItem = {
+ name: '',
+ type: 'tuple[5][4][]',
+ components: [
+ {
+ name: '',
+ type: 'uint256[]',
+ },
+ {
+ name: '',
+ type: 'tuple',
+ components: [
+ {
+ name: '',
+ type: 'bytes',
+ },
+ ],
+ },
+ {
+ name: '',
+ type: 'string[4]',
+ },
+ {
+ name: '',
+ type: 'bytes4',
+ },
+ ],
+ };
+ expect(dataItem).to.be.deep.equal(expectedDataItem);
+ expect(dataType.getSignature()).to.be.equal(signature);
+ });
+ });
+
+ describe('Function', () => {
+ it('No inputs and no outputs', async () => {
+ // create encoder
+ const functionName = 'foo';
+ const dataType = AbiEncoder.createMethod(functionName);
+ // create expected values
+ const expectedSignature = 'foo()';
+ const expectedInputDataItem = {
+ name: 'foo',
+ type: 'method',
+ components: [],
+ };
+ const expectedOutputDataItem = {
+ name: 'foo',
+ type: 'tuple',
+ components: [],
+ };
+ // check expected values
+ expect(dataType.getSignature()).to.be.equal(expectedSignature);
+ expect(dataType.getDataItem()).to.be.deep.equal(expectedInputDataItem);
+ expect(dataType.getReturnValueDataItem()).to.be.deep.equal(expectedOutputDataItem);
+ });
+ it('No inputs and no outputs (empty arrays as input)', async () => {
+ // create encoder
+ const functionName = 'foo';
+ const dataType = AbiEncoder.createMethod(functionName, [], []);
+ // create expected values
+ const expectedSignature = 'foo()';
+ const expectedInputDataItem = {
+ name: 'foo',
+ type: 'method',
+ components: [],
+ };
+ const expectedOutputDataItem = {
+ name: 'foo',
+ type: 'tuple',
+ components: [],
+ };
+ // check expected values
+ expect(dataType.getSignature()).to.be.equal(expectedSignature);
+ expect(dataType.getDataItem()).to.be.deep.equal(expectedInputDataItem);
+ expect(dataType.getReturnValueDataItem()).to.be.deep.equal(expectedOutputDataItem);
+ });
+ it('Single DataItem input and single DataItem output', async () => {
+ // create encoder
+ const functionName = 'foo';
+ const inputDataItem = {
+ name: 'input',
+ type: 'uint256',
+ };
+ const outputDataItem = {
+ name: 'output',
+ type: 'string',
+ };
+ const dataType = AbiEncoder.createMethod(functionName, inputDataItem, outputDataItem);
+ // create expected values
+ const expectedSignature = 'foo(uint256)';
+ const expectedInputDataItem = {
+ name: 'foo',
+ type: 'method',
+ components: [inputDataItem],
+ };
+ const expectedOutputDataItem = {
+ name: 'foo',
+ type: 'tuple',
+ components: [outputDataItem],
+ };
+ // check expected values
+ expect(dataType.getSignature()).to.be.equal(expectedSignature);
+ expect(dataType.getDataItem()).to.be.deep.equal(expectedInputDataItem);
+ expect(dataType.getReturnValueDataItem()).to.be.deep.equal(expectedOutputDataItem);
+ });
+ it('Single signature input and single signature output', async () => {
+ // create encoder
+ const functionName = 'foo';
+ const inputSignature = 'uint256';
+ const outputSignature = 'string';
+ const dataType = AbiEncoder.createMethod(functionName, inputSignature, outputSignature);
+ // create expected values
+ const expectedSignature = 'foo(uint256)';
+ const expectedInputDataItem = {
+ name: 'foo',
+ type: 'method',
+ components: [
+ {
+ name: '',
+ type: 'uint256',
+ },
+ ],
+ };
+ const expectedOutputDataItem = {
+ name: 'foo',
+ type: 'tuple',
+ components: [
+ {
+ name: '',
+ type: 'string',
+ },
+ ],
+ };
+ // check expected values
+ expect(dataType.getSignature()).to.be.equal(expectedSignature);
+ expect(dataType.getDataItem()).to.be.deep.equal(expectedInputDataItem);
+ expect(dataType.getReturnValueDataItem()).to.be.deep.equal(expectedOutputDataItem);
+ });
+ it('Single signature tuple input and single signature tuple output', async () => {
+ // create encoder
+ const functionName = 'foo';
+ const inputSignature = '(uint256,bytes[][4])';
+ const outputSignature = '(string,uint32)';
+ const dataType = AbiEncoder.createMethod(functionName, inputSignature, outputSignature);
+ // create expected values
+ const expectedSignature = 'foo((uint256,bytes[][4]))';
+ const expectedInputDataItem = {
+ name: 'foo',
+ type: 'method',
+ components: [
+ {
+ name: '',
+ type: 'tuple',
+ components: [
+ {
+ name: '',
+ type: 'uint256',
+ },
+ {
+ name: '',
+ type: 'bytes[][4]',
+ },
+ ],
+ },
+ ],
+ };
+ const expectedOutputDataItem = {
+ name: 'foo',
+ type: 'tuple',
+ components: [
+ {
+ name: '',
+ type: 'tuple',
+ components: [
+ {
+ name: '',
+ type: 'string',
+ },
+ {
+ name: '',
+ type: 'uint32',
+ },
+ ],
+ },
+ ],
+ };
+ // check expected values
+ expect(dataType.getSignature()).to.be.equal(expectedSignature);
+ expect(dataType.getDataItem()).to.be.deep.equal(expectedInputDataItem);
+ expect(dataType.getReturnValueDataItem()).to.be.deep.equal(expectedOutputDataItem);
+ });
+ it('Mutiple DataItem input and multiple DataItem output', async () => {
+ // create encoder
+ const functionName = 'foo';
+ const inputDataItems = [
+ {
+ name: '',
+ type: 'uint256',
+ },
+ {
+ name: '',
+ type: 'bytes[][4]',
+ },
+ ];
+ const outputDataItems = [
+ {
+ name: '',
+ type: 'string',
+ },
+ {
+ name: '',
+ type: 'uint32',
+ },
+ ];
+ const dataType = AbiEncoder.createMethod(functionName, inputDataItems, outputDataItems);
+ // create expected values
+ const expectedSignature = 'foo(uint256,bytes[][4])';
+ const expectedInputDataItem = {
+ name: 'foo',
+ type: 'method',
+ components: inputDataItems,
+ };
+ const expectedOutputDataItem = {
+ name: 'foo',
+ type: 'tuple',
+ components: outputDataItems,
+ };
+ // check expected values
+ expect(dataType.getSignature()).to.be.equal(expectedSignature);
+ expect(dataType.getDataItem()).to.be.deep.equal(expectedInputDataItem);
+ expect(dataType.getReturnValueDataItem()).to.be.deep.equal(expectedOutputDataItem);
+ });
+ it('Multiple signature input and multiple signature output', async () => {
+ // create encoder
+ const functionName = 'foo';
+ const inputSignatures = ['uint256', 'bytes[][4]'];
+ const outputSignatures = ['string', 'uint32'];
+ const dataType = AbiEncoder.createMethod(functionName, inputSignatures, outputSignatures);
+ // create expected values
+ const expectedSignature = 'foo(uint256,bytes[][4])';
+ const expectedInputDataItem = {
+ name: 'foo',
+ type: 'method',
+ components: [
+ {
+ name: '',
+ type: 'uint256',
+ },
+ {
+ name: '',
+ type: 'bytes[][4]',
+ },
+ ],
+ };
+ const expectedOutputDataItem = {
+ name: 'foo',
+ type: 'tuple',
+ components: [
+ {
+ name: '',
+ type: 'string',
+ },
+ {
+ name: '',
+ type: 'uint32',
+ },
+ ],
+ };
+ // check expected values
+ expect(dataType.getSignature()).to.be.equal(expectedSignature);
+ expect(dataType.getDataItem()).to.be.deep.equal(expectedInputDataItem);
+ expect(dataType.getReturnValueDataItem()).to.be.deep.equal(expectedOutputDataItem);
+ });
+ });
+});
diff --git a/packages/utils/test/abi_encoder/signature_tests.ts b/packages/utils/test/abi_encoder/signature_tests.ts
deleted file mode 100644
index e69de29bb..000000000
--- a/packages/utils/test/abi_encoder/signature_tests.ts
+++ /dev/null