From 285fb3deadd0413bf993557575a3f96a840f0e10 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Mon, 17 Dec 2018 18:26:03 -0800 Subject: Progress --- .../src/abi_encoder/abstract_data_types/types/set.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'packages/utils/src') diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts index 00059a4b6..f97f0bac3 100644 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts +++ b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts @@ -134,20 +134,21 @@ export abstract class AbstractSetDataType extends DataType { const block = new SetCalldataBlock(this.getDataItem().name, this.getSignature(), parentName); // Create blocks for members of set. const memberCalldataBlocks: CalldataBlock[] = []; - const childMap = _.cloneDeep(this._memberIndexByName); - _.forOwn(obj, (value: any, key: string) => { - if (!(key in childMap)) { + let duplicateObj = _.cloneDeep(obj) as {[key:string]: any}; + _.forEach(this._memberIndexByName, (memberIndex: number, memberName: string) => { + if (!(memberName in obj)) { throw new Error( - `Could not assign tuple to object: unrecognized key '${key}' in object ${this.getDataItem().name}`, + `Could not assign tuple to object: missing field '${memberName}' in object ${obj}`, ); } - const memberBlock = this._members[this._memberIndexByName[key]].generateCalldataBlock(value, block); + const memberValue: any = duplicateObj[memberName]; + const memberBlock = this._members[memberIndex].generateCalldataBlock(memberValue, block); memberCalldataBlocks.push(memberBlock); - delete childMap[key]; + delete duplicateObj[memberName]; }); // Sanity check that all members have been included. - if (Object.keys(childMap).length !== 0) { - throw new Error(`Could not assign tuple to object: missing keys ${Object.keys(childMap)}`); + if (Object.keys(duplicateObj).length !== 0) { + throw new Error(`Could not assign tuple to object: unrecognized keys ${Object.keys(duplicateObj)}`); } // Associate member blocks with Set block. block.setMembers(memberCalldataBlocks); -- cgit v1.2.3 From b89f9869492e369370bcef593d69e59172f13da4 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 18 Dec 2018 14:28:20 -0800 Subject: Ensure that addresses are lower case --- packages/utils/src/abi_encoder/evm_data_types/address.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'packages/utils/src') diff --git a/packages/utils/src/abi_encoder/evm_data_types/address.ts b/packages/utils/src/abi_encoder/evm_data_types/address.ts index 2e3a206c6..3ab823019 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/address.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/address.ts @@ -39,7 +39,8 @@ export class AddressDataType extends AbstractBlobDataType { const valueBufPadded = calldata.popWord(); const valueBuf = valueBufPadded.slice(AddressDataType._DECODED_ADDRESS_OFFSET_IN_BYTES); const value = ethUtil.bufferToHex(valueBuf); - return value; + const valueLowercase = _.toLower(value); + return valueLowercase; } public getSignature(): string { -- cgit v1.2.3 From 2f1454e90e5fd7d85c4deb3a8c674043e8a14564 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 18 Dec 2018 21:44:26 -0800 Subject: Working for almost every test --- .../src/abi_encoder/abstract_data_types/types/set.ts | 16 +++++++++++++--- packages/utils/src/abi_encoder/evm_data_types/int.ts | 5 ++++- packages/utils/src/abi_encoder/evm_data_types/method.ts | 7 +++++++ packages/utils/src/abi_encoder/evm_data_types/uint.ts | 5 ++++- 4 files changed, 28 insertions(+), 5 deletions(-) (limited to 'packages/utils/src') diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts index f97f0bac3..73e9cf778 100644 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts +++ b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts @@ -138,7 +138,7 @@ export abstract class AbstractSetDataType extends DataType { _.forEach(this._memberIndexByName, (memberIndex: number, memberName: string) => { if (!(memberName in obj)) { throw new Error( - `Could not assign tuple to object: missing field '${memberName}' in object ${obj}`, + `Could not assign tuple to object: missing key '${memberName}' in object ${JSON.stringify(obj)}`, ); } const memberValue: any = duplicateObj[memberName]; @@ -180,17 +180,27 @@ export abstract class AbstractSetDataType extends DataType { // Create one member for each component of `dataItem` const members: DataType[] = []; const memberIndexByName: MemberIndexByName = {}; + const memberNames: string[] = []; _.each(dataItem.components, (memberItem: DataItem) => { + // If a component with `name` already exists then + // rename to `name_nameIdx` to avoid naming conflicts. + let memberName = memberItem.name; + let nameIdx = 0; + while (_.includes(memberNames, memberName) || _.isEmpty(memberName)) { + nameIdx++; + memberName = `${memberItem.name}_${nameIdx}`; + } + memberNames.push(memberName); const childDataItem: DataItem = { type: memberItem.type, - name: `${dataItem.name}.${memberItem.name}`, + name: `${dataItem.name}.${memberName}` }; const components = memberItem.components; if (!_.isUndefined(components)) { childDataItem.components = components; } const child = this.getFactory().create(childDataItem, this); - memberIndexByName[memberItem.name] = members.length; + memberIndexByName[memberName] = members.length; members.push(child); }); return [members, memberIndexByName]; diff --git a/packages/utils/src/abi_encoder/evm_data_types/int.ts b/packages/utils/src/abi_encoder/evm_data_types/int.ts index f1dcf5ea1..c9f734799 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/int.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/int.ts @@ -47,9 +47,12 @@ export class IntDataType extends AbstractBlobDataType { return encodedValue; } - public decodeValue(calldata: RawCalldata): BigNumber { + public decodeValue(calldata: RawCalldata): BigNumber|number { const valueBuf = calldata.popWord(); const value = EncoderMath.safeDecodeNumericValue(valueBuf, this._minValue, this._maxValue); + if (this._width === 8) { + return value.toNumber(); + } return value; } 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 b1cd1377f..c777902e8 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/method.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/method.ts @@ -8,6 +8,7 @@ import { AbstractSetDataType } from '../abstract_data_types/types/set'; import { constants } from '../utils/constants'; import { DecodingRules, EncodingRules } from '../utils/rules'; +import { ArrayDataType } from './array'; import { TupleDataType } from './tuple'; export class MethodDataType extends AbstractSetDataType { @@ -44,6 +45,12 @@ export class MethodDataType extends AbstractSetDataType { return returnValues; } + public decodeReturnValuesAsArray(returndata: string, rules?: DecodingRules): any { + const returnValues = this.decodeReturnValues(returndata, rules); + const returnValuesAsArray = _.isObject(returnValues) ? _.values(returnValues) : [returnValues]; + return returnValuesAsArray; + } + public getSignature(): string { return this._methodSignature; } diff --git a/packages/utils/src/abi_encoder/evm_data_types/uint.ts b/packages/utils/src/abi_encoder/evm_data_types/uint.ts index 5180f0cf3..06cde4eea 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/uint.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/uint.ts @@ -46,9 +46,12 @@ export class UIntDataType extends AbstractBlobDataType { return encodedValue; } - public decodeValue(calldata: RawCalldata): BigNumber { + public decodeValue(calldata: RawCalldata): BigNumber|number { const valueBuf = calldata.popWord(); const value = EncoderMath.safeDecodeNumericValue(valueBuf, UIntDataType._MIN_VALUE, this._maxValue); + if (this._width === 8) { + return value.toNumber(); + } return value; } -- cgit v1.2.3 From e4551c8f6037302124cae4cda51b8f7624ade687 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 18 Dec 2018 22:01:48 -0800 Subject: Works for almost all tests --- packages/utils/src/abi_encoder/evm_data_types/method.ts | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'packages/utils/src') 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 c777902e8..bae0fdb5d 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/method.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/method.ts @@ -51,6 +51,12 @@ export class MethodDataType extends AbstractSetDataType { return returnValuesAsArray; } + public decodeReturnValuesAsArrayOrNull(returndata: string, rules?: DecodingRules): any { + const returnValuesAsArray = this.decodeReturnValuesAsArray(returndata, rules); + const returnValue = _.isEmpty(returnValuesAsArray) ? [] : returnValuesAsArray; + return returnValue; + } + public getSignature(): string { return this._methodSignature; } -- cgit v1.2.3 From e9a82905e35041d36c4c9be75e11c0399ee96b89 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Wed, 19 Dec 2018 13:01:22 -0800 Subject: Abi Encoder tests fixed + added a signature parser for cases where MethodAbi/DataItems are not readily available --- .../abi_encoder/abstract_data_types/data_type.ts | 10 +- .../abi_encoder/abstract_data_types/types/set.ts | 4 +- .../src/abi_encoder/evm_data_types/address.ts | 2 +- .../utils/src/abi_encoder/evm_data_types/array.ts | 18 ++- .../utils/src/abi_encoder/evm_data_types/bool.ts | 2 +- .../abi_encoder/evm_data_types/dynamic_bytes.ts | 2 +- .../utils/src/abi_encoder/evm_data_types/int.ts | 2 +- .../utils/src/abi_encoder/evm_data_types/method.ts | 2 +- .../src/abi_encoder/evm_data_types/pointer.ts | 8 +- .../src/abi_encoder/evm_data_types/static_bytes.ts | 2 +- .../utils/src/abi_encoder/evm_data_types/string.ts | 2 +- .../utils/src/abi_encoder/evm_data_types/tuple.ts | 17 ++- .../utils/src/abi_encoder/evm_data_types/uint.ts | 2 +- packages/utils/src/abi_encoder/index.ts | 1 + .../utils/src/abi_encoder/utils/signatureParser.ts | 154 +++++++++++++++++++++ 15 files changed, 206 insertions(+), 22 deletions(-) create mode 100644 packages/utils/src/abi_encoder/utils/signatureParser.ts (limited to 'packages/utils/src') diff --git a/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts b/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts index 13cc87e2a..5bd6aae03 100644 --- a/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts +++ b/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts @@ -51,8 +51,16 @@ export abstract class DataType { return value; } + public getSignature(detailed?: boolean): string { + if (_.isEmpty(this._dataItem.name) || !detailed) return this.getSignatureType(); + const name = this.getDataItem().name; + const shortName = name.indexOf('.') > 0 ? name.substr(name.lastIndexOf('.') + 1) : name; + const detailedSignature = `${shortName} ${this.getSignatureType()}`; + return detailedSignature; + } + public abstract generateCalldataBlock(value: any, parentBlock?: CalldataBlock): CalldataBlock; public abstract generateValue(calldata: RawCalldata, rules: DecodingRules): any; - public abstract getSignature(): string; + public abstract getSignatureType(): string; public abstract isStatic(): boolean; } diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts index 73e9cf778..d7105ff5f 100644 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts +++ b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts @@ -155,11 +155,11 @@ export abstract class AbstractSetDataType extends DataType { return block; } - protected _computeSignatureOfMembers(): string { + protected _computeSignatureOfMembers(detailed?: boolean): string { // Compute signature of members let signature = `(`; _.each(this._members, (member: DataType, i: number) => { - signature += member.getSignature(); + signature += member.getSignature(detailed); if (i < this._members.length - 1) { signature += ','; } diff --git a/packages/utils/src/abi_encoder/evm_data_types/address.ts b/packages/utils/src/abi_encoder/evm_data_types/address.ts index 3ab823019..2278830eb 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/address.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/address.ts @@ -43,7 +43,7 @@ export class AddressDataType extends AbstractBlobDataType { return valueLowercase; } - public getSignature(): string { + public getSignatureType(): string { return SolidityTypes.Address; } /* tslint:enable prefer-function-over-method */ diff --git a/packages/utils/src/abi_encoder/evm_data_types/array.ts b/packages/utils/src/abi_encoder/evm_data_types/array.ts index 7595cb667..8b71dc913 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/array.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/array.ts @@ -38,22 +38,30 @@ export class ArrayDataType extends AbstractSetDataType { this._arraySignature = this._computeSignature(); } - public getSignature(): string { - return this._arraySignature; + public getSignatureType(): string { + return this._computeSignature(false); } - private _computeSignature(): string { + public getSignature(detailed?: boolean): string { + if (_.isEmpty(this.getDataItem().name) || !detailed) return this.getSignatureType(); + const name = this.getDataItem().name; + const shortName = name.indexOf('.') > 0 ? name.substr(name.lastIndexOf('.') + 1) : name; + const detailedSignature = `${shortName} ${this._computeSignature(detailed)}`; + return detailedSignature; + } + + private _computeSignature(detailed?: boolean): string { // Compute signature for a single array element const elementDataItem: DataItem = { type: this._elementType, - name: 'N/A', + name: '', }; const elementComponents = this.getDataItem().components; if (!_.isUndefined(elementComponents)) { elementDataItem.components = elementComponents; } const elementDataType = this.getFactory().create(elementDataItem); - const elementSignature = elementDataType.getSignature(); + const elementSignature = elementDataType.getSignature(detailed); // Construct signature for array of type `element` if (_.isUndefined(this._arrayLength)) { return `${elementSignature}[]`; diff --git a/packages/utils/src/abi_encoder/evm_data_types/bool.ts b/packages/utils/src/abi_encoder/evm_data_types/bool.ts index d713d5a94..7f91f34e6 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/bool.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/bool.ts @@ -46,7 +46,7 @@ export class BoolDataType extends AbstractBlobDataType { return value; } - public getSignature(): string { + public getSignatureType(): string { return SolidityTypes.Bool; } /* tslint:enable prefer-function-over-method */ diff --git a/packages/utils/src/abi_encoder/evm_data_types/dynamic_bytes.ts b/packages/utils/src/abi_encoder/evm_data_types/dynamic_bytes.ts index 5277efd6c..fa38b63c0 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/dynamic_bytes.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/dynamic_bytes.ts @@ -65,7 +65,7 @@ export class DynamicBytesDataType extends AbstractBlobDataType { return value; } - public getSignature(): string { + public getSignatureType(): string { return SolidityTypes.Bytes; } /* tslint:enable prefer-function-over-method */ diff --git a/packages/utils/src/abi_encoder/evm_data_types/int.ts b/packages/utils/src/abi_encoder/evm_data_types/int.ts index c9f734799..865a76545 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/int.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/int.ts @@ -56,7 +56,7 @@ export class IntDataType extends AbstractBlobDataType { return value; } - public getSignature(): string { + public getSignatureType(): string { return `${SolidityTypes.Int}${this._width}`; } } 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 bae0fdb5d..44456cd0a 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/method.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/method.ts @@ -57,7 +57,7 @@ export class MethodDataType extends AbstractSetDataType { return returnValue; } - public getSignature(): string { + public getSignatureType(): string { return this._methodSignature; } diff --git a/packages/utils/src/abi_encoder/evm_data_types/pointer.ts b/packages/utils/src/abi_encoder/evm_data_types/pointer.ts index 389e75927..8c3afe0c3 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/pointer.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/pointer.ts @@ -11,7 +11,11 @@ export class PointerDataType extends AbstractPointerDataType { super(dataItem, dataTypeFactory, destDataType, parentDataType); } - public getSignature(): string { - return this._destination.getSignature(); + public getSignatureType(): string { + return this._destination.getSignature(false); + } + + public getSignature(detailed?: boolean): string { + return this._destination.getSignature(detailed); } } diff --git a/packages/utils/src/abi_encoder/evm_data_types/static_bytes.ts b/packages/utils/src/abi_encoder/evm_data_types/static_bytes.ts index 2e371c505..cbf1957d7 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/static_bytes.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/static_bytes.ts @@ -36,7 +36,7 @@ export class StaticBytesDataType extends AbstractBlobDataType { this._width = StaticBytesDataType._decodeWidthFromType(dataItem.type); } - public getSignature(): string { + public getSignatureType(): string { // Note that `byte` reduces to `bytes1` return `${SolidityTypes.Bytes}${this._width}`; } diff --git a/packages/utils/src/abi_encoder/evm_data_types/string.ts b/packages/utils/src/abi_encoder/evm_data_types/string.ts index 91a72ad3f..97ac46442 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/string.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/string.ts @@ -52,7 +52,7 @@ export class StringDataType extends AbstractBlobDataType { return value; } - public getSignature(): string { + public getSignatureType(): string { return SolidityTypes.String; } /* tslint:enable prefer-function-over-method */ diff --git a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts b/packages/utils/src/abi_encoder/evm_data_types/tuple.ts index 31593c882..587653f49 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/tuple.ts @@ -1,10 +1,11 @@ import { DataItem, SolidityTypes } from 'ethereum-types'; +import * as _ from 'lodash'; import { DataTypeFactory } from '../abstract_data_types/interfaces'; import { AbstractSetDataType } from '../abstract_data_types/types/set'; export class TupleDataType extends AbstractSetDataType { - private readonly _signature: string; + //private readonly _signature: string; public static matchType(type: string): boolean { return type === SolidityTypes.Tuple; @@ -15,10 +16,18 @@ export class TupleDataType extends AbstractSetDataType { if (!TupleDataType.matchType(dataItem.type)) { throw new Error(`Tried to instantiate Tuple with bad input: ${dataItem}`); } - this._signature = this._computeSignatureOfMembers(); + //this._signature = } - public getSignature(): string { - return this._signature; + public getSignatureType(): string { + return this._computeSignatureOfMembers(false); + } + + public getSignature(detailed?: boolean): string { + if (_.isEmpty(this.getDataItem().name) || !detailed) return this.getSignatureType(); + const name = this.getDataItem().name; + const shortName = name.indexOf('.') > 0 ? name.substr(name.lastIndexOf('.') + 1) : name; + const detailedSignature = `${shortName} ${this._computeSignatureOfMembers(detailed)}`; + return detailedSignature; } } diff --git a/packages/utils/src/abi_encoder/evm_data_types/uint.ts b/packages/utils/src/abi_encoder/evm_data_types/uint.ts index 06cde4eea..86d2705f0 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/uint.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/uint.ts @@ -55,7 +55,7 @@ export class UIntDataType extends AbstractBlobDataType { return value; } - public getSignature(): string { + public getSignatureType(): string { return `${SolidityTypes.Uint}${this._width}`; } } diff --git a/packages/utils/src/abi_encoder/index.ts b/packages/utils/src/abi_encoder/index.ts index baf844ac6..23422dd8b 100644 --- a/packages/utils/src/abi_encoder/index.ts +++ b/packages/utils/src/abi_encoder/index.ts @@ -12,3 +12,4 @@ export { Tuple, UInt, } from './evm_data_type_factory'; +export { fromSignature } from './utils/signatureParser'; diff --git a/packages/utils/src/abi_encoder/utils/signatureParser.ts b/packages/utils/src/abi_encoder/utils/signatureParser.ts new file mode 100644 index 000000000..fe5127032 --- /dev/null +++ b/packages/utils/src/abi_encoder/utils/signatureParser.ts @@ -0,0 +1,154 @@ +import * as _ from 'lodash'; + +import { DataType } from '../abstract_data_types/data_type'; +import { DataItem } from 'ethereum-protocol'; +import { MethodAbi } from 'ethereum-types'; +import * as EvmDataTypes from '../evm_data_type_factory'; + +// Valid signatures: +// functionName(param1, param2, ...): (output1, output2, ...) +// functionName(param1, param2, ...) +// (param1, param2, ...) +/* +export function fromSignature(signature: string): DataType { + const maxSignatureIndex = signature.length - 1; + // Function name + const isFunction = signature.startsWith('function '); + // Output components + const outputComponentsBeginIndex = signature.indexOf(':'); + const outputComponentsEndIndex = outputComponentsBeginIndex >= 0 ? maxSignatureIndex : 0; + const hasOutputComponents = outputComponentsBeginIndex >= 0; + const outputComponentsSignature = hasOutputComponents ? signature.substring(outputComponentsBeginIndex, outputComponentsEndIndex + 1) : ""; + // Input components + const inputComponentsBeginIndex = signature.indexOf('('); + const inputComponentsEndIndex = hasOutputComponents ? outputComponentsBeginIndex : maxSignatureIndex; + const inputComponentsSignature = signature.substring(inputComponentsBeginIndex, inputComponentsEndIndex + 1); + // Function anme + const functionName = signature.substr(0, inputComponentsBeginIndex); + const isFunction = !_.isEmpty(functionName); + + console.log(`sig - ` + inputComponentsSignature); + // Create data type + let dataType: DataType; + if (isFunction) { + const methodAbi = { + type: 'function', + name: functionName, + inputs: generateDataItems(inputComponentsSignature), + outputs: !_.isEmpty(outputComponentsSignature) ? generateDataItems(outputComponentsSignature) : [], + } as MethodAbi; + dataType = new EvmDataTypes.Method(methodAbi); + } else if(hasOutputComponents) { + throw new Error(`Invalid signature: Contains outputs but no function name.`); + } else { + const inputDataItem = generateDataItem(inputComponentsSignature); + console.log(JSON.stringify(inputDataItem)); + dataType = EvmDataTypes.EvmDataTypeFactory.getInstance().create(inputDataItem); + } + return dataType; +}*/ + +export function fromSignature(signature: string): DataType { + const dataItems = generateDataItems(signature); + if (dataItems.length === 1) { + return EvmDataTypes.EvmDataTypeFactory.getInstance().create(dataItems[0]); + } + // this is a tuple + return EvmDataTypes.EvmDataTypeFactory.getInstance().create({ + name: '', + type: 'tuple', + components: dataItems + }); +} + +function generateDataItems(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); + } + trimmedSignature += ','; + let currTokenIsArray = 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. + switch (char) { + case '(': + parenCount += 1; + currToken += char; + break; + case ')': + parenCount -= 1; + currToken += char; + break; + case '[': + if (parenCount === 0) { + isParsingArrayModifier = true; + currTokenIsArray = true; + currTokenArrayModifier += "["; + } else { + currToken += char; + } + break; + case ']': + if (parenCount === 0) { + isParsingArrayModifier = false; + currTokenArrayModifier += ']'; + } else { + currToken += char; + } + break; + case ' ': + if (parenCount === 0) { + currTokenName = currToken; + currToken = ""; + } else { + currToken += char; + } + break; + case ',': + if (parenCount === 0) { + //throw new Error(`Generating Data Items`); + const components = currToken.startsWith('(') ? generateDataItems(currToken) : []; + const isTuple = !_.isEmpty(components); + const isArray = currTokenIsArray; + let dataItem: DataItem = {name: currTokenName, type: ''}; + if (isTuple) { + dataItem.type = 'tuple'; + dataItem.components = components; + } else { + dataItem.type = currToken; + } + if (isArray) { + dataItem.type += currTokenArrayModifier; + } + + dataItems.push(dataItem); + + currTokenName = ''; + currToken = ''; + currTokenIsArray = false; + currTokenArrayModifier = ""; + break; + } else { + currToken += char; + break; + } + default: + if (isParsingArrayModifier) { + currTokenArrayModifier += char; + } else { + currToken += char; + } + break; + } + } + return dataItems; +} \ No newline at end of file -- cgit v1.2.3 From 7991de9ed0b5f1e8a38097d902eae09cc6b5cf11 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Wed, 19 Dec 2018 14:30:23 -0800 Subject: Generalized `create` for signature / dataItems. Cleaner. --- .../utils/src/abi_encoder/evm_data_type_factory.ts | 23 ++++++++ packages/utils/src/abi_encoder/index.ts | 3 +- .../utils/src/abi_encoder/utils/signatureParser.ts | 63 ++++------------------ 3 files changed, 34 insertions(+), 55 deletions(-) (limited to 'packages/utils/src') 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 4cc124e0a..5ff7366d6 100644 --- a/packages/utils/src/abi_encoder/evm_data_type_factory.ts +++ b/packages/utils/src/abi_encoder/evm_data_type_factory.ts @@ -2,6 +2,8 @@ import { DataItem, MethodAbi } from 'ethereum-types'; import * as _ from 'lodash'; +import { generateDataItemsFromSignature } from './utils/signatureParser'; + import { DataType } from './abstract_data_types/data_type'; import { DataTypeFactory } from './abstract_data_types/interfaces'; import { AddressDataType } from './evm_data_types/address'; @@ -129,4 +131,25 @@ export class EvmDataTypeFactory implements DataTypeFactory { private constructor() {} } + +// Convenience function +export function create(input: DataItem | DataItem[] | string): DataType { + // Handle different types of input + let dataItems: DataItem[] = []; + if (typeof(input) === 'string') { + dataItems = generateDataItemsFromSignature(input); + } else if(input instanceof Array) { + dataItems = input as DataItem[]; + } else { + dataItems = [input as DataItem]; + } + // Create single data item from input + let dataItem: DataItem = dataItems.length === 1 ? dataItems[0] : { + name: '', + type: 'tuple', + components: dataItems + }; + // Create data type + return EvmDataTypeFactory.getInstance().create(dataItem); +} /* tslint:enable no-construct */ diff --git a/packages/utils/src/abi_encoder/index.ts b/packages/utils/src/abi_encoder/index.ts index 23422dd8b..f7f1ceedc 100644 --- a/packages/utils/src/abi_encoder/index.ts +++ b/packages/utils/src/abi_encoder/index.ts @@ -11,5 +11,6 @@ export { String, Tuple, UInt, + create, } from './evm_data_type_factory'; -export { fromSignature } from './utils/signatureParser'; +//export { fromSignature } from './utils/signatureParser'; diff --git a/packages/utils/src/abi_encoder/utils/signatureParser.ts b/packages/utils/src/abi_encoder/utils/signatureParser.ts index fe5127032..9c1a59c82 100644 --- a/packages/utils/src/abi_encoder/utils/signatureParser.ts +++ b/packages/utils/src/abi_encoder/utils/signatureParser.ts @@ -1,67 +1,22 @@ import * as _ from 'lodash'; -import { DataType } from '../abstract_data_types/data_type'; import { DataItem } from 'ethereum-protocol'; -import { MethodAbi } from 'ethereum-types'; -import * as EvmDataTypes from '../evm_data_type_factory'; -// Valid signatures: -// functionName(param1, param2, ...): (output1, output2, ...) -// functionName(param1, param2, ...) -// (param1, param2, ...) /* -export function fromSignature(signature: string): DataType { - const maxSignatureIndex = signature.length - 1; - // Function name - const isFunction = signature.startsWith('function '); - // Output components - const outputComponentsBeginIndex = signature.indexOf(':'); - const outputComponentsEndIndex = outputComponentsBeginIndex >= 0 ? maxSignatureIndex : 0; - const hasOutputComponents = outputComponentsBeginIndex >= 0; - const outputComponentsSignature = hasOutputComponents ? signature.substring(outputComponentsBeginIndex, outputComponentsEndIndex + 1) : ""; - // Input components - const inputComponentsBeginIndex = signature.indexOf('('); - const inputComponentsEndIndex = hasOutputComponents ? outputComponentsBeginIndex : maxSignatureIndex; - const inputComponentsSignature = signature.substring(inputComponentsBeginIndex, inputComponentsEndIndex + 1); - // Function anme - const functionName = signature.substr(0, inputComponentsBeginIndex); - const isFunction = !_.isEmpty(functionName); - - console.log(`sig - ` + inputComponentsSignature); - // Create data type - let dataType: DataType; - if (isFunction) { - const methodAbi = { - type: 'function', - name: functionName, - inputs: generateDataItems(inputComponentsSignature), - outputs: !_.isEmpty(outputComponentsSignature) ? generateDataItems(outputComponentsSignature) : [], - } as MethodAbi; - dataType = new EvmDataTypes.Method(methodAbi); - } else if(hasOutputComponents) { - throw new Error(`Invalid signature: Contains outputs but no function name.`); - } else { - const inputDataItem = generateDataItem(inputComponentsSignature); - console.log(JSON.stringify(inputDataItem)); - dataType = EvmDataTypes.EvmDataTypeFactory.getInstance().create(inputDataItem); - } - return dataType; -}*/ - -export function fromSignature(signature: string): DataType { - const dataItems = generateDataItems(signature); +export function generateDataItemFromSignature(signature: string): DataItem { + const dataItems = generateDataItemsFromSignature(signature); if (dataItems.length === 1) { - return EvmDataTypes.EvmDataTypeFactory.getInstance().create(dataItems[0]); + return dataItems[0]; } - // this is a tuple - return EvmDataTypes.EvmDataTypeFactory.getInstance().create({ + // signature represents a tuple + return { name: '', type: 'tuple', components: dataItems - }); -} + }; +}*/ -function generateDataItems(signature: string): DataItem[] { +export function generateDataItemsFromSignature(signature: string): DataItem[] { let trimmedSignature = signature; if (signature.startsWith('(')) { if(!signature.endsWith(')')) { @@ -116,7 +71,7 @@ function generateDataItems(signature: string): DataItem[] { case ',': if (parenCount === 0) { //throw new Error(`Generating Data Items`); - const components = currToken.startsWith('(') ? generateDataItems(currToken) : []; + const components = currToken.startsWith('(') ? generateDataItemsFromSignature(currToken) : []; const isTuple = !_.isEmpty(components); const isArray = currTokenIsArray; let dataItem: DataItem = {name: currTokenName, type: ''}; -- cgit v1.2.3 From b06f8239e1fe75703f88d34c0d225701406e28c2 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Sat, 22 Dec 2018 17:23:02 -0800 Subject: Finished porting new abi encoder to contracts --- packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts | 2 ++ packages/utils/src/abi_encoder/abstract_data_types/types/set.ts | 9 ++------- packages/utils/src/abi_encoder/evm_data_types/method.ts | 6 ++++++ 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'packages/utils/src') diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts index a091e55b9..4252b782c 100644 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts +++ b/packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts @@ -9,6 +9,8 @@ import { DecodingRules } from '../../utils/rules'; import { DataType } from '../data_type'; import { DataTypeFactory } from '../interfaces'; +import * as ethUtil from 'ethereumjs-util'; + export abstract class AbstractBlobDataType extends DataType { protected _sizeKnownAtCompileTime: boolean; diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts index d7105ff5f..5eb29c47b 100644 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts +++ b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts @@ -13,6 +13,7 @@ import { DataType } from '../data_type'; import { DataTypeFactory, MemberIndexByName } from '../interfaces'; import { AbstractPointerDataType } from './pointer'; +import { logUtils } from '../../../log_utils'; export abstract class AbstractSetDataType extends DataType { protected readonly _arrayLength: number | undefined; @@ -134,22 +135,16 @@ export abstract class AbstractSetDataType extends DataType { const block = new SetCalldataBlock(this.getDataItem().name, this.getSignature(), parentName); // Create blocks for members of set. const memberCalldataBlocks: CalldataBlock[] = []; - let duplicateObj = _.cloneDeep(obj) as {[key:string]: any}; _.forEach(this._memberIndexByName, (memberIndex: number, memberName: string) => { if (!(memberName in obj)) { throw new Error( `Could not assign tuple to object: missing key '${memberName}' in object ${JSON.stringify(obj)}`, ); } - const memberValue: any = duplicateObj[memberName]; + const memberValue: any = (obj as {[key:string]: any})[memberName]; const memberBlock = this._members[memberIndex].generateCalldataBlock(memberValue, block); memberCalldataBlocks.push(memberBlock); - delete duplicateObj[memberName]; }); - // Sanity check that all members have been included. - if (Object.keys(duplicateObj).length !== 0) { - throw new Error(`Could not assign tuple to object: unrecognized keys ${Object.keys(duplicateObj)}`); - } // Associate member blocks with Set block. block.setMembers(memberCalldataBlocks); return block; 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 44456cd0a..212e2ca6b 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/method.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/method.ts @@ -35,6 +35,12 @@ export class MethodDataType extends AbstractSetDataType { return value; } + public decodeAsArray(returndata: string, rules?: DecodingRules): any { + const value = this.decode(returndata, rules); + const valuesAsArray = _.isObject(value) ? _.values(value) : [value]; + return valuesAsArray; + } + public encodeReturnValues(value: any, rules?: EncodingRules): string { const returnData = this._returnDataType.encode(value, rules); return returnData; -- cgit v1.2.3 From d1fd4421be0a7639b99b374bf04e57fac4e8a486 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Sun, 23 Dec 2018 19:27:38 -0800 Subject: Use string argument encoding with new encoder --- .../abi_encoder/abstract_data_types/data_type.ts | 6 +++++ .../utils/src/abi_encoder/evm_data_type_factory.ts | 28 ++++++++++++---------- .../utils/src/abi_encoder/evm_data_types/method.ts | 6 ----- packages/utils/src/abi_encoder/index.ts | 2 +- 4 files changed, 22 insertions(+), 20 deletions(-) (limited to 'packages/utils/src') diff --git a/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts b/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts index 5bd6aae03..dc897d810 100644 --- a/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts +++ b/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts @@ -51,6 +51,12 @@ export abstract class DataType { return value; } + public decodeAsArray(returndata: string, rules?: DecodingRules): any { + const value = this.decode(returndata, rules); + const valuesAsArray = _.isObject(value) ? _.values(value) : [value]; + return valuesAsArray; + } + public getSignature(detailed?: boolean): string { if (_.isEmpty(this._dataItem.name) || !detailed) return this.getSignatureType(); const name = this.getDataItem().name; 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 5ff7366d6..fdd4f0fde 100644 --- a/packages/utils/src/abi_encoder/evm_data_type_factory.ts +++ b/packages/utils/src/abi_encoder/evm_data_type_factory.ts @@ -135,21 +135,23 @@ export class EvmDataTypeFactory implements DataTypeFactory { // Convenience function export function create(input: DataItem | DataItem[] | string): DataType { // Handle different types of input - let dataItems: DataItem[] = []; - if (typeof(input) === 'string') { - dataItems = generateDataItemsFromSignature(input); - } else if(input instanceof Array) { - dataItems = input as DataItem[]; + const isSignature = typeof(input) === 'string'; + const isTupleSignature = isSignature && (input as string).startsWith('('); + const parseAsTuple = isTupleSignature || _.isArray(input); + // Create input `dataItem` + let dataItem: DataItem; + if(parseAsTuple) { + const dataItems = isSignature ? generateDataItemsFromSignature(input as string) : input as DataItem[]; + dataItem = { + name: '', + type: 'tuple', + components: dataItems + }; } else { - dataItems = [input as DataItem]; + dataItem = isSignature ? generateDataItemsFromSignature(input as string)[0] : input as DataItem; } - // Create single data item from input - let dataItem: DataItem = dataItems.length === 1 ? dataItems[0] : { - name: '', - type: 'tuple', - components: dataItems - }; // Create data type - return EvmDataTypeFactory.getInstance().create(dataItem); + const dataType = EvmDataTypeFactory.getInstance().create(dataItem); + return dataType; } /* 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 212e2ca6b..44456cd0a 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/method.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/method.ts @@ -35,12 +35,6 @@ export class MethodDataType extends AbstractSetDataType { return value; } - public decodeAsArray(returndata: string, rules?: DecodingRules): any { - const value = this.decode(returndata, rules); - const valuesAsArray = _.isObject(value) ? _.values(value) : [value]; - return valuesAsArray; - } - public encodeReturnValues(value: any, rules?: EncodingRules): string { const returnData = this._returnDataType.encode(value, rules); return returnData; diff --git a/packages/utils/src/abi_encoder/index.ts b/packages/utils/src/abi_encoder/index.ts index f7f1ceedc..cfacfe075 100644 --- a/packages/utils/src/abi_encoder/index.ts +++ b/packages/utils/src/abi_encoder/index.ts @@ -13,4 +13,4 @@ export { UInt, create, } from './evm_data_type_factory'; -//export { fromSignature } from './utils/signatureParser'; +export { DataType } from './abstract_data_types/data_type'; -- cgit v1.2.3 From 0b6c9c84688b565a9000b2c4e889c682ccaa7e51 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Sun, 23 Dec 2018 19:49:08 -0800 Subject: Ran prettier --- .../src/abi_encoder/abstract_data_types/types/set.ts | 4 ++-- .../utils/src/abi_encoder/evm_data_type_factory.ts | 10 +++++----- packages/utils/src/abi_encoder/evm_data_types/int.ts | 2 +- packages/utils/src/abi_encoder/evm_data_types/tuple.ts | 2 +- packages/utils/src/abi_encoder/evm_data_types/uint.ts | 2 +- .../utils/src/abi_encoder/utils/signatureParser.ts | 18 +++++++++--------- 6 files changed, 19 insertions(+), 19 deletions(-) (limited to 'packages/utils/src') diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts index 5eb29c47b..28d11c4b5 100644 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts +++ b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts @@ -141,7 +141,7 @@ export abstract class AbstractSetDataType extends DataType { `Could not assign tuple to object: missing key '${memberName}' in object ${JSON.stringify(obj)}`, ); } - const memberValue: any = (obj as {[key:string]: any})[memberName]; + const memberValue: any = (obj as { [key: string]: any })[memberName]; const memberBlock = this._members[memberIndex].generateCalldataBlock(memberValue, block); memberCalldataBlocks.push(memberBlock); }); @@ -188,7 +188,7 @@ export abstract class AbstractSetDataType extends DataType { memberNames.push(memberName); const childDataItem: DataItem = { type: memberItem.type, - name: `${dataItem.name}.${memberName}` + name: `${dataItem.name}.${memberName}`, }; const components = memberItem.components; if (!_.isUndefined(components)) { 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 fdd4f0fde..dcfcc9c5a 100644 --- a/packages/utils/src/abi_encoder/evm_data_type_factory.ts +++ b/packages/utils/src/abi_encoder/evm_data_type_factory.ts @@ -135,20 +135,20 @@ export class EvmDataTypeFactory implements DataTypeFactory { // Convenience function export function create(input: DataItem | DataItem[] | string): DataType { // Handle different types of input - const isSignature = typeof(input) === 'string'; + const isSignature = typeof input === 'string'; const isTupleSignature = isSignature && (input as string).startsWith('('); const parseAsTuple = isTupleSignature || _.isArray(input); // Create input `dataItem` let dataItem: DataItem; - if(parseAsTuple) { - const dataItems = isSignature ? generateDataItemsFromSignature(input as string) : input as DataItem[]; + if (parseAsTuple) { + const dataItems = isSignature ? generateDataItemsFromSignature(input as string) : (input as DataItem[]); dataItem = { name: '', type: 'tuple', - components: dataItems + components: dataItems, }; } else { - dataItem = isSignature ? generateDataItemsFromSignature(input as string)[0] : input as DataItem; + dataItem = isSignature ? generateDataItemsFromSignature(input as string)[0] : (input as DataItem); } // Create data type const dataType = EvmDataTypeFactory.getInstance().create(dataItem); diff --git a/packages/utils/src/abi_encoder/evm_data_types/int.ts b/packages/utils/src/abi_encoder/evm_data_types/int.ts index 865a76545..144a0eb6a 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/int.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/int.ts @@ -47,7 +47,7 @@ export class IntDataType extends AbstractBlobDataType { return encodedValue; } - public decodeValue(calldata: RawCalldata): BigNumber|number { + public decodeValue(calldata: RawCalldata): BigNumber | number { const valueBuf = calldata.popWord(); const value = EncoderMath.safeDecodeNumericValue(valueBuf, this._minValue, this._maxValue); if (this._width === 8) { diff --git a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts b/packages/utils/src/abi_encoder/evm_data_types/tuple.ts index 587653f49..54964235c 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/tuple.ts @@ -16,7 +16,7 @@ export class TupleDataType extends AbstractSetDataType { if (!TupleDataType.matchType(dataItem.type)) { throw new Error(`Tried to instantiate Tuple with bad input: ${dataItem}`); } - //this._signature = + //this._signature = } public getSignatureType(): string { diff --git a/packages/utils/src/abi_encoder/evm_data_types/uint.ts b/packages/utils/src/abi_encoder/evm_data_types/uint.ts index 86d2705f0..940fda072 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/uint.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/uint.ts @@ -46,7 +46,7 @@ export class UIntDataType extends AbstractBlobDataType { return encodedValue; } - public decodeValue(calldata: RawCalldata): BigNumber|number { + public decodeValue(calldata: RawCalldata): BigNumber | number { const valueBuf = calldata.popWord(); const value = EncoderMath.safeDecodeNumericValue(valueBuf, UIntDataType._MIN_VALUE, this._maxValue); if (this._width === 8) { diff --git a/packages/utils/src/abi_encoder/utils/signatureParser.ts b/packages/utils/src/abi_encoder/utils/signatureParser.ts index 9c1a59c82..c4796e24e 100644 --- a/packages/utils/src/abi_encoder/utils/signatureParser.ts +++ b/packages/utils/src/abi_encoder/utils/signatureParser.ts @@ -19,20 +19,20 @@ export function generateDataItemFromSignature(signature: string): DataItem { export function generateDataItemsFromSignature(signature: string): DataItem[] { let trimmedSignature = signature; if (signature.startsWith('(')) { - if(!signature.endsWith(')')) { + if (!signature.endsWith(')')) { throw new Error(`Failed to generate data item. Must end with ')'`); } trimmedSignature = signature.substr(1, signature.length - 2); } trimmedSignature += ','; let currTokenIsArray = false; - let currTokenArrayModifier = ""; + let currTokenArrayModifier = ''; let isParsingArrayModifier = false; let currToken = ''; let parenCount = 0; let currTokenName = ''; const dataItems: DataItem[] = []; - for(const char of trimmedSignature) { + for (const char of trimmedSignature) { // Tokenize the type string while keeping track of parentheses. switch (char) { case '(': @@ -47,7 +47,7 @@ export function generateDataItemsFromSignature(signature: string): DataItem[] { if (parenCount === 0) { isParsingArrayModifier = true; currTokenIsArray = true; - currTokenArrayModifier += "["; + currTokenArrayModifier += '['; } else { currToken += char; } @@ -63,7 +63,7 @@ export function generateDataItemsFromSignature(signature: string): DataItem[] { case ' ': if (parenCount === 0) { currTokenName = currToken; - currToken = ""; + currToken = ''; } else { currToken += char; } @@ -74,7 +74,7 @@ export function generateDataItemsFromSignature(signature: string): DataItem[] { const components = currToken.startsWith('(') ? generateDataItemsFromSignature(currToken) : []; const isTuple = !_.isEmpty(components); const isArray = currTokenIsArray; - let dataItem: DataItem = {name: currTokenName, type: ''}; + let dataItem: DataItem = { name: currTokenName, type: '' }; if (isTuple) { dataItem.type = 'tuple'; dataItem.components = components; @@ -84,13 +84,13 @@ export function generateDataItemsFromSignature(signature: string): DataItem[] { if (isArray) { dataItem.type += currTokenArrayModifier; } - + dataItems.push(dataItem); currTokenName = ''; currToken = ''; currTokenIsArray = false; - currTokenArrayModifier = ""; + currTokenArrayModifier = ''; break; } else { currToken += char; @@ -106,4 +106,4 @@ export function generateDataItemsFromSignature(signature: string): DataItem[] { } } return dataItems; -} \ No newline at end of file +} -- cgit v1.2.3 From 86caa4a0bb82e3ba7d362cca9b75565bf8944952 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Sun, 23 Dec 2018 20:50:02 -0800 Subject: Ran prettier and linter --- .../abi_encoder/abstract_data_types/data_type.ts | 8 +++-- .../abi_encoder/abstract_data_types/types/blob.ts | 2 -- .../abi_encoder/abstract_data_types/types/set.ts | 1 - .../utils/src/abi_encoder/evm_data_type_factory.ts | 14 ++++++-- .../utils/src/abi_encoder/evm_data_types/array.ts | 10 +++--- .../utils/src/abi_encoder/evm_data_types/int.ts | 3 +- .../utils/src/abi_encoder/evm_data_types/method.ts | 1 - .../utils/src/abi_encoder/evm_data_types/tuple.ts | 10 +++--- .../utils/src/abi_encoder/evm_data_types/uint.ts | 3 +- .../utils/src/abi_encoder/utils/signatureParser.ts | 42 +++++++++------------- 10 files changed, 50 insertions(+), 44 deletions(-) (limited to 'packages/utils/src') diff --git a/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts b/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts index dc897d810..d9e854f51 100644 --- a/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts +++ b/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts @@ -58,9 +58,13 @@ export abstract class DataType { } public getSignature(detailed?: boolean): string { - if (_.isEmpty(this._dataItem.name) || !detailed) return this.getSignatureType(); + if (_.isEmpty(this._dataItem.name) || !detailed) { + return this.getSignatureType(); + } const name = this.getDataItem().name; - const shortName = name.indexOf('.') > 0 ? name.substr(name.lastIndexOf('.') + 1) : name; + const lastIndexOfScopeDelimiter = name.lastIndexOf('.'); + const isScopedName = !_.isUndefined(lastIndexOfScopeDelimiter) && lastIndexOfScopeDelimiter > 0; + const shortName = isScopedName ? name.substr((lastIndexOfScopeDelimiter as number) + 1) : name; const detailedSignature = `${shortName} ${this.getSignatureType()}`; return detailedSignature; } diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts index 4252b782c..a091e55b9 100644 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts +++ b/packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts @@ -9,8 +9,6 @@ import { DecodingRules } from '../../utils/rules'; import { DataType } from '../data_type'; import { DataTypeFactory } from '../interfaces'; -import * as ethUtil from 'ethereumjs-util'; - export abstract class AbstractBlobDataType extends DataType { protected _sizeKnownAtCompileTime: boolean; diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts index 28d11c4b5..e4be96235 100644 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts +++ b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts @@ -13,7 +13,6 @@ import { DataType } from '../data_type'; import { DataTypeFactory, MemberIndexByName } from '../interfaces'; import { AbstractPointerDataType } from './pointer'; -import { logUtils } from '../../../log_utils'; export abstract class AbstractSetDataType extends DataType { protected readonly _arrayLength: number | undefined; 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 dcfcc9c5a..6d59ec01a 100644 --- a/packages/utils/src/abi_encoder/evm_data_type_factory.ts +++ b/packages/utils/src/abi_encoder/evm_data_type_factory.ts @@ -132,15 +132,23 @@ export class EvmDataTypeFactory implements DataTypeFactory { private constructor() {} } -// Convenience function +/** + * 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 '' is interpreted as a `DataItem` + * For example, 'string' is interpreted as {type: 'string'} + * A signature in the form '(, , ..., )' is interpreted as `DataItem[]` + * For eaxmple, '(string, uint256)' is interpreted as [{type: 'string'}, {type: 'uint256'}] + * @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 parseAsTuple = isTupleSignature || _.isArray(input); + const shouldParseAsTuple = isTupleSignature || _.isArray(input); // Create input `dataItem` let dataItem: DataItem; - if (parseAsTuple) { + if (shouldParseAsTuple) { const dataItems = isSignature ? generateDataItemsFromSignature(input as string) : (input as DataItem[]); dataItem = { name: '', diff --git a/packages/utils/src/abi_encoder/evm_data_types/array.ts b/packages/utils/src/abi_encoder/evm_data_types/array.ts index 8b71dc913..449de0568 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/array.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/array.ts @@ -7,7 +7,6 @@ import { constants } from '../utils/constants'; export class ArrayDataType extends AbstractSetDataType { private static readonly _MATCHER = RegExp('^(.+)\\[([0-9]*)\\]$'); - private readonly _arraySignature: string; private readonly _elementType: string; public static matchType(type: string): boolean { @@ -35,7 +34,6 @@ export class ArrayDataType extends AbstractSetDataType { super(dataItem, dataTypeFactory, isArray, arrayLength, arrayElementType); // Set array properties this._elementType = arrayElementType; - this._arraySignature = this._computeSignature(); } public getSignatureType(): string { @@ -43,9 +41,13 @@ export class ArrayDataType extends AbstractSetDataType { } public getSignature(detailed?: boolean): string { - if (_.isEmpty(this.getDataItem().name) || !detailed) return this.getSignatureType(); + if (_.isEmpty(this.getDataItem().name) || !detailed) { + return this.getSignatureType(); + } const name = this.getDataItem().name; - const shortName = name.indexOf('.') > 0 ? name.substr(name.lastIndexOf('.') + 1) : name; + const lastIndexOfScopeDelimiter = name.lastIndexOf('.'); + const isScopedName = !_.isUndefined(lastIndexOfScopeDelimiter) && lastIndexOfScopeDelimiter > 0; + const shortName = isScopedName ? name.substr((lastIndexOfScopeDelimiter as number) + 1) : name; const detailedSignature = `${shortName} ${this._computeSignature(detailed)}`; return detailedSignature; } diff --git a/packages/utils/src/abi_encoder/evm_data_types/int.ts b/packages/utils/src/abi_encoder/evm_data_types/int.ts index 144a0eb6a..8d98e195b 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/int.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/int.ts @@ -50,7 +50,8 @@ export class IntDataType extends AbstractBlobDataType { public decodeValue(calldata: RawCalldata): BigNumber | number { const valueBuf = calldata.popWord(); const value = EncoderMath.safeDecodeNumericValue(valueBuf, this._minValue, this._maxValue); - if (this._width === 8) { + const numberOfBytesInUint8 = 8; + if (this._width === numberOfBytesInUint8) { return value.toNumber(); } return value; 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 44456cd0a..6e3fdcf6d 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/method.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/method.ts @@ -8,7 +8,6 @@ import { AbstractSetDataType } from '../abstract_data_types/types/set'; import { constants } from '../utils/constants'; import { DecodingRules, EncodingRules } from '../utils/rules'; -import { ArrayDataType } from './array'; import { TupleDataType } from './tuple'; export class MethodDataType extends AbstractSetDataType { diff --git a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts b/packages/utils/src/abi_encoder/evm_data_types/tuple.ts index 54964235c..3d1cb5a92 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/tuple.ts @@ -5,7 +5,6 @@ import { DataTypeFactory } from '../abstract_data_types/interfaces'; import { AbstractSetDataType } from '../abstract_data_types/types/set'; export class TupleDataType extends AbstractSetDataType { - //private readonly _signature: string; public static matchType(type: string): boolean { return type === SolidityTypes.Tuple; @@ -16,7 +15,6 @@ export class TupleDataType extends AbstractSetDataType { if (!TupleDataType.matchType(dataItem.type)) { throw new Error(`Tried to instantiate Tuple with bad input: ${dataItem}`); } - //this._signature = } public getSignatureType(): string { @@ -24,9 +22,13 @@ export class TupleDataType extends AbstractSetDataType { } public getSignature(detailed?: boolean): string { - if (_.isEmpty(this.getDataItem().name) || !detailed) return this.getSignatureType(); + if (_.isEmpty(this.getDataItem().name) || !detailed) { + return this.getSignatureType(); + } const name = this.getDataItem().name; - const shortName = name.indexOf('.') > 0 ? name.substr(name.lastIndexOf('.') + 1) : name; + const lastIndexOfScopeDelimiter = name.lastIndexOf('.'); + const isScopedName = !_.isUndefined(lastIndexOfScopeDelimiter) && lastIndexOfScopeDelimiter > 0; + const shortName = isScopedName ? name.substr((lastIndexOfScopeDelimiter as number) + 1) : name; const detailedSignature = `${shortName} ${this._computeSignatureOfMembers(detailed)}`; return detailedSignature; } diff --git a/packages/utils/src/abi_encoder/evm_data_types/uint.ts b/packages/utils/src/abi_encoder/evm_data_types/uint.ts index 940fda072..8e382e8dc 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/uint.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/uint.ts @@ -49,7 +49,8 @@ export class UIntDataType extends AbstractBlobDataType { public decodeValue(calldata: RawCalldata): BigNumber | number { const valueBuf = calldata.popWord(); const value = EncoderMath.safeDecodeNumericValue(valueBuf, UIntDataType._MIN_VALUE, this._maxValue); - if (this._width === 8) { + const numberOfBytesInUint8 = 8; + if (this._width === numberOfBytesInUint8) { return value.toNumber(); } return value; diff --git a/packages/utils/src/abi_encoder/utils/signatureParser.ts b/packages/utils/src/abi_encoder/utils/signatureParser.ts index c4796e24e..315784cea 100644 --- a/packages/utils/src/abi_encoder/utils/signatureParser.ts +++ b/packages/utils/src/abi_encoder/utils/signatureParser.ts @@ -1,21 +1,15 @@ +import { DataItem } from 'ethereum-types'; import * as _ from 'lodash'; -import { DataItem } from 'ethereum-protocol'; - -/* -export function generateDataItemFromSignature(signature: string): DataItem { - const dataItems = generateDataItemsFromSignature(signature); - if (dataItems.length === 1) { - return dataItems[0]; - } - // signature represents a tuple - return { - name: '', - type: 'tuple', - components: dataItems - }; -}*/ - +/** + * Returns an array of DataItem's corresponding to the input signature. + * A signature can be in two forms: '' or '(, , ...) + * 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 + */ export function generateDataItemsFromSignature(signature: string): DataItem[] { let trimmedSignature = signature; if (signature.startsWith('(')) { @@ -25,7 +19,7 @@ export function generateDataItemsFromSignature(signature: string): DataItem[] { trimmedSignature = signature.substr(1, signature.length - 2); } trimmedSignature += ','; - let currTokenIsArray = false; + let isCurrTokenArray = false; let currTokenArrayModifier = ''; let isParsingArrayModifier = false; let currToken = ''; @@ -46,7 +40,7 @@ export function generateDataItemsFromSignature(signature: string): DataItem[] { case '[': if (parenCount === 0) { isParsingArrayModifier = true; - currTokenIsArray = true; + isCurrTokenArray = true; currTokenArrayModifier += '['; } else { currToken += char; @@ -70,26 +64,24 @@ export function generateDataItemsFromSignature(signature: string): DataItem[] { break; case ',': if (parenCount === 0) { - //throw new Error(`Generating Data Items`); + // Generate new DataItem from token const components = currToken.startsWith('(') ? generateDataItemsFromSignature(currToken) : []; const isTuple = !_.isEmpty(components); - const isArray = currTokenIsArray; - let dataItem: DataItem = { name: currTokenName, type: '' }; + const dataItem: DataItem = { name: currTokenName, type: '' }; if (isTuple) { dataItem.type = 'tuple'; dataItem.components = components; } else { dataItem.type = currToken; } - if (isArray) { + if (isCurrTokenArray) { dataItem.type += currTokenArrayModifier; } - dataItems.push(dataItem); - + // reset token state currTokenName = ''; currToken = ''; - currTokenIsArray = false; + isCurrTokenArray = false; currTokenArrayModifier = ''; break; } else { -- cgit v1.2.3 From f39c03191c8a8870aaf5180d2764cd8c8eb17d0c Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Sun, 23 Dec 2018 21:54:51 -0800 Subject: Ran linter --- packages/utils/src/abi_encoder/evm_data_types/tuple.ts | 1 - 1 file changed, 1 deletion(-) (limited to 'packages/utils/src') diff --git a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts b/packages/utils/src/abi_encoder/evm_data_types/tuple.ts index 3d1cb5a92..2370ecdef 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/tuple.ts @@ -5,7 +5,6 @@ import { DataTypeFactory } from '../abstract_data_types/interfaces'; import { AbstractSetDataType } from '../abstract_data_types/types/set'; export class TupleDataType extends AbstractSetDataType { - public static matchType(type: string): boolean { return type === SolidityTypes.Tuple; } -- cgit v1.2.3 From 4f53335db0a7c5ff12347ab1e2b83259f06e64bb Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Mon, 7 Jan 2019 17:07:39 -0800 Subject: Renamed signatureParser.ts to signature_parser.ts --- .../utils/src/abi_encoder/evm_data_type_factory.ts | 2 +- .../utils/src/abi_encoder/utils/signatureParser.ts | 101 --------------------- .../src/abi_encoder/utils/signature_parser.ts | 101 +++++++++++++++++++++ 3 files changed, 102 insertions(+), 102 deletions(-) delete mode 100644 packages/utils/src/abi_encoder/utils/signatureParser.ts create mode 100644 packages/utils/src/abi_encoder/utils/signature_parser.ts (limited to 'packages/utils/src') 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 6d59ec01a..268649148 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/signatureParser'; +import { generateDataItemsFromSignature } from './utils/signature_parser'; import { DataType } from './abstract_data_types/data_type'; import { DataTypeFactory } from './abstract_data_types/interfaces'; diff --git a/packages/utils/src/abi_encoder/utils/signatureParser.ts b/packages/utils/src/abi_encoder/utils/signatureParser.ts deleted file mode 100644 index 315784cea..000000000 --- a/packages/utils/src/abi_encoder/utils/signatureParser.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { DataItem } from 'ethereum-types'; -import * as _ from 'lodash'; - -/** - * Returns an array of DataItem's corresponding to the input signature. - * A signature can be in two forms: '' or '(, , ...) - * 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 - */ -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); - } - 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. - switch (char) { - case '(': - parenCount += 1; - currToken += char; - break; - case ')': - parenCount -= 1; - currToken += char; - break; - case '[': - if (parenCount === 0) { - isParsingArrayModifier = true; - isCurrTokenArray = true; - currTokenArrayModifier += '['; - } else { - currToken += char; - } - break; - case ']': - if (parenCount === 0) { - isParsingArrayModifier = false; - currTokenArrayModifier += ']'; - } else { - currToken += char; - } - break; - case ' ': - if (parenCount === 0) { - currTokenName = currToken; - currToken = ''; - } else { - currToken += char; - } - 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; - } - break; - } - } - return dataItems; -} diff --git a/packages/utils/src/abi_encoder/utils/signature_parser.ts b/packages/utils/src/abi_encoder/utils/signature_parser.ts new file mode 100644 index 000000000..315784cea --- /dev/null +++ b/packages/utils/src/abi_encoder/utils/signature_parser.ts @@ -0,0 +1,101 @@ +import { DataItem } from 'ethereum-types'; +import * as _ from 'lodash'; + +/** + * Returns an array of DataItem's corresponding to the input signature. + * A signature can be in two forms: '' or '(, , ...) + * 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 + */ +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); + } + 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. + switch (char) { + case '(': + parenCount += 1; + currToken += char; + break; + case ')': + parenCount -= 1; + currToken += char; + break; + case '[': + if (parenCount === 0) { + isParsingArrayModifier = true; + isCurrTokenArray = true; + currTokenArrayModifier += '['; + } else { + currToken += char; + } + break; + case ']': + if (parenCount === 0) { + isParsingArrayModifier = false; + currTokenArrayModifier += ']'; + } else { + currToken += char; + } + break; + case ' ': + if (parenCount === 0) { + currTokenName = currToken; + currToken = ''; + } else { + currToken += char; + } + 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; + } + break; + } + } + return dataItems; +} -- cgit v1.2.3 From 82a44559f6a3d795a6a8b0baa9486633bc884475 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Wed, 9 Jan 2019 11:18:56 -0800 Subject: Style cleanup for Compressed Calldata in Contract Wrappers PR --- .../utils/src/abi_encoder/abstract_data_types/data_type.ts | 6 +++--- .../utils/src/abi_encoder/abstract_data_types/types/set.ts | 7 ++++--- packages/utils/src/abi_encoder/evm_data_types/array.ts | 10 +++++----- packages/utils/src/abi_encoder/evm_data_types/method.ts | 8 ++++---- packages/utils/src/abi_encoder/evm_data_types/pointer.ts | 4 ++-- packages/utils/src/abi_encoder/evm_data_types/tuple.ts | 6 +++--- 6 files changed, 21 insertions(+), 20 deletions(-) (limited to 'packages/utils/src') diff --git a/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts b/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts index d9e854f51..f23324721 100644 --- a/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts +++ b/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts @@ -51,14 +51,14 @@ export abstract class DataType { return value; } - public decodeAsArray(returndata: string, rules?: DecodingRules): any { + public decodeAsArray(returndata: string, rules?: DecodingRules): any[] { const value = this.decode(returndata, rules); const valuesAsArray = _.isObject(value) ? _.values(value) : [value]; return valuesAsArray; } - public getSignature(detailed?: boolean): string { - if (_.isEmpty(this._dataItem.name) || !detailed) { + public getSignature(isDetailed?: boolean): string { + if (_.isEmpty(this._dataItem.name) || !isDetailed) { return this.getSignatureType(); } const name = this.getDataItem().name; diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts index e4be96235..2c6c4b0f6 100644 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts +++ b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts @@ -1,3 +1,4 @@ +import { ObjectMap } from '@0x/types'; import { DataItem } from 'ethereum-types'; import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; @@ -140,7 +141,7 @@ export abstract class AbstractSetDataType extends DataType { `Could not assign tuple to object: missing key '${memberName}' in object ${JSON.stringify(obj)}`, ); } - const memberValue: any = (obj as { [key: string]: any })[memberName]; + const memberValue: any = (obj as ObjectMap)[memberName]; const memberBlock = this._members[memberIndex].generateCalldataBlock(memberValue, block); memberCalldataBlocks.push(memberBlock); }); @@ -149,11 +150,11 @@ export abstract class AbstractSetDataType extends DataType { return block; } - protected _computeSignatureOfMembers(detailed?: boolean): string { + protected _computeSignatureOfMembers(isDetailed?: boolean): string { // Compute signature of members let signature = `(`; _.each(this._members, (member: DataType, i: number) => { - signature += member.getSignature(detailed); + signature += member.getSignature(isDetailed); if (i < this._members.length - 1) { signature += ','; } diff --git a/packages/utils/src/abi_encoder/evm_data_types/array.ts b/packages/utils/src/abi_encoder/evm_data_types/array.ts index 449de0568..d9607f47e 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/array.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/array.ts @@ -40,19 +40,19 @@ export class ArrayDataType extends AbstractSetDataType { return this._computeSignature(false); } - public getSignature(detailed?: boolean): string { - if (_.isEmpty(this.getDataItem().name) || !detailed) { + public getSignature(isDetailed?: boolean): string { + if (_.isEmpty(this.getDataItem().name) || !isDetailed) { return this.getSignatureType(); } const name = this.getDataItem().name; const lastIndexOfScopeDelimiter = name.lastIndexOf('.'); const isScopedName = !_.isUndefined(lastIndexOfScopeDelimiter) && lastIndexOfScopeDelimiter > 0; const shortName = isScopedName ? name.substr((lastIndexOfScopeDelimiter as number) + 1) : name; - const detailedSignature = `${shortName} ${this._computeSignature(detailed)}`; + const detailedSignature = `${shortName} ${this._computeSignature(isDetailed)}`; return detailedSignature; } - private _computeSignature(detailed?: boolean): string { + private _computeSignature(isDetailed?: boolean): string { // Compute signature for a single array element const elementDataItem: DataItem = { type: this._elementType, @@ -63,7 +63,7 @@ export class ArrayDataType extends AbstractSetDataType { elementDataItem.components = elementComponents; } const elementDataType = this.getFactory().create(elementDataItem); - const elementSignature = elementDataType.getSignature(detailed); + const elementSignature = elementDataType.getSignature(isDetailed); // Construct signature for array of type `element` if (_.isUndefined(this._arrayLength)) { return `${elementSignature}[]`; 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 6e3fdcf6d..c0cf80c74 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/method.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/method.ts @@ -44,14 +44,14 @@ export class MethodDataType extends AbstractSetDataType { return returnValues; } - public decodeReturnValuesAsArray(returndata: string, rules?: DecodingRules): any { - const returnValues = this.decodeReturnValues(returndata, rules); + public decodeReturnValuesAsArray(returnData: string, rules?: DecodingRules): any[] { + const returnValues = this.decodeReturnValues(returnData, rules); const returnValuesAsArray = _.isObject(returnValues) ? _.values(returnValues) : [returnValues]; return returnValuesAsArray; } - public decodeReturnValuesAsArrayOrNull(returndata: string, rules?: DecodingRules): any { - const returnValuesAsArray = this.decodeReturnValuesAsArray(returndata, rules); + public decodeReturnValuesAsArrayOrNull(returnData: string, rules?: DecodingRules): any { + const returnValuesAsArray = this.decodeReturnValuesAsArray(returnData, rules); const returnValue = _.isEmpty(returnValuesAsArray) ? [] : returnValuesAsArray; return returnValue; } diff --git a/packages/utils/src/abi_encoder/evm_data_types/pointer.ts b/packages/utils/src/abi_encoder/evm_data_types/pointer.ts index 8c3afe0c3..250db7c64 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/pointer.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/pointer.ts @@ -15,7 +15,7 @@ export class PointerDataType extends AbstractPointerDataType { return this._destination.getSignature(false); } - public getSignature(detailed?: boolean): string { - return this._destination.getSignature(detailed); + public getSignature(isDetailed?: boolean): string { + return this._destination.getSignature(isDetailed); } } diff --git a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts b/packages/utils/src/abi_encoder/evm_data_types/tuple.ts index 2370ecdef..5000c85e8 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/tuple.ts @@ -20,15 +20,15 @@ export class TupleDataType extends AbstractSetDataType { return this._computeSignatureOfMembers(false); } - public getSignature(detailed?: boolean): string { - if (_.isEmpty(this.getDataItem().name) || !detailed) { + public getSignature(isDetailed?: boolean): string { + if (_.isEmpty(this.getDataItem().name) || !isDetailed) { return this.getSignatureType(); } const name = this.getDataItem().name; const lastIndexOfScopeDelimiter = name.lastIndexOf('.'); const isScopedName = !_.isUndefined(lastIndexOfScopeDelimiter) && lastIndexOfScopeDelimiter > 0; const shortName = isScopedName ? name.substr((lastIndexOfScopeDelimiter as number) + 1) : name; - const detailedSignature = `${shortName} ${this._computeSignatureOfMembers(detailed)}`; + const detailedSignature = `${shortName} ${this._computeSignatureOfMembers(isDetailed)}`; return detailedSignature; } } -- cgit v1.2.3 From 3a28eb1c6a5e213f4874c34e8a3c85eadfe98fc9 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Wed, 9 Jan 2019 17:12:26 -0800 Subject: Fix build after rebase --- packages/utils/src/abi_encoder/utils/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/utils/src') diff --git a/packages/utils/src/abi_encoder/utils/constants.ts b/packages/utils/src/abi_encoder/utils/constants.ts index 36de2dd4f..fc586f295 100644 --- a/packages/utils/src/abi_encoder/utils/constants.ts +++ b/packages/utils/src/abi_encoder/utils/constants.ts @@ -11,7 +11,7 @@ export const constants = { HEX_SELECTOR_BYTE_OFFSET_IN_CALLDATA: 0, // Disable no-object-literal-type-assertion so we can enforce cast /* tslint:disable no-object-literal-type-assertion */ - DEFAULT_DECODING_RULES: { shouldConvertStructsToObjects: false } as DecodingRules, + DEFAULT_DECODING_RULES: { shouldConvertStructsToObjects: true } as DecodingRules, DEFAULT_ENCODING_RULES: { shouldOptimize: true, shouldAnnotate: false } as EncodingRules, /* tslint:enable no-object-literal-type-assertion */ }; -- cgit v1.2.3 From b0817854e81512ad95cca4d842a671304ae3b94a Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Fri, 11 Jan 2019 16:13:52 -0800 Subject: strict decoding of return values using generics --- .../utils/src/abi_encoder/evm_data_types/method.ts | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'packages/utils/src') 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 c0cf80c74..c852a0fdf 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/method.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/method.ts @@ -44,16 +44,17 @@ export class MethodDataType extends AbstractSetDataType { return returnValues; } - public decodeReturnValuesAsArray(returnData: string, rules?: DecodingRules): any[] { - const returnValues = this.decodeReturnValues(returnData, rules); - const returnValuesAsArray = _.isObject(returnValues) ? _.values(returnValues) : [returnValues]; - return returnValuesAsArray; - } - - public decodeReturnValuesAsArrayOrNull(returnData: string, rules?: DecodingRules): any { - const returnValuesAsArray = this.decodeReturnValuesAsArray(returnData, rules); - const returnValue = _.isEmpty(returnValuesAsArray) ? [] : returnValuesAsArray; - return returnValue; + public strictDecodeReturnValue(returndata: string, rules?: DecodingRules): T { + const returnValues = this._returnDataType.decode(returndata, rules); + const returnValuesAsArray: any = _.isObject(returnValues) ? _.values(returnValues) : [returnValues]; + switch (returnValuesAsArray.length) { + case 0: + return undefined as any; + case 1: + return returnValuesAsArray[0]; + default: + return returnValuesAsArray; + } } public getSignatureType(): string { -- cgit v1.2.3