diff options
author | Greg Hysen <greg.hysen@gmail.com> | 2018-04-04 08:39:55 +0800 |
---|---|---|
committer | Greg Hysen <greg.hysen@gmail.com> | 2018-04-10 08:22:58 +0800 |
commit | 61fc3346c2fe2adc33dfe84aa50780d61e10efdf (patch) | |
tree | 1f5ab2cddf7093db8f8fb419ef70da66a9997c7b /packages/utils/src/abi_utils.ts | |
parent | 073bf738ddb271b6b4158798baf4cac3cb0608e9 (diff) | |
download | dexon-sol-tools-61fc3346c2fe2adc33dfe84aa50780d61e10efdf.tar.gz dexon-sol-tools-61fc3346c2fe2adc33dfe84aa50780d61e10efdf.tar.zst dexon-sol-tools-61fc3346c2fe2adc33dfe84aa50780d61e10efdf.zip |
Updated deployer to accept a list of contract directories as input. Contract directories are namespaced to a void clashes. Also in this commit is a fix for overloading contract functions.
Diffstat (limited to 'packages/utils/src/abi_utils.ts')
-rw-r--r-- | packages/utils/src/abi_utils.ts | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/packages/utils/src/abi_utils.ts b/packages/utils/src/abi_utils.ts new file mode 100644 index 000000000..843b8589b --- /dev/null +++ b/packages/utils/src/abi_utils.ts @@ -0,0 +1,74 @@ +import { AbiDefinition, AbiType, ConstructorAbi, ContractAbi, DataItem, MethodAbi } from '@0xproject/types'; +import * as _ from 'lodash'; + +export const abiUtils = { + parseFunctionParam(param: DataItem): string { + if (param.type === 'tuple') { + // Parse out tuple types into {type_1, type_2, ..., type_N} + const tupleComponents = param.components; + const paramString = _.map(tupleComponents, component => this.parseFunctionParam(component)); + const tupleParamString = `{${paramString}}`; + return tupleParamString; + } + return param.type; + }, + getFunctionSignature(abi: MethodAbi): string { + const functionName = abi.name; + const parameterTypeList = abi.inputs.map((param: DataItem) => this.parseFunctionParam(param)); + const functionSignature = `${functionName}(${parameterTypeList})`; + return functionSignature; + }, + renameOverloadedMethods(inputContractAbi: ContractAbi): ContractAbi { + const contractAbi = _.cloneDeep(inputContractAbi); + const methodAbis = contractAbi.filter((abi: AbiDefinition) => abi.type === AbiType.Function) as MethodAbi[]; + const methodAbisByOriginalIndex = _.transform( + methodAbis, + (result: Array<{ index: number; methodAbi: MethodAbi }>, methodAbi, i: number) => { + result.push({ index: i, methodAbi }); + }, + [], + ); + // Sort method Abis into alphabetical order, by function signature + const methodAbisByOriginalIndexOrdered = _.sortBy(methodAbisByOriginalIndex, [ + (entry: { index: number; methodAbi: MethodAbi }) => { + const functionSignature = this.getFunctionSignature(entry.methodAbi); + return functionSignature; + }, + ]); + // Group method Abis by name (overloaded methods will be grouped together, in alphabetical order) + const methodAbisByName = _.transform( + methodAbisByOriginalIndexOrdered, + (result: { [key: string]: Array<{ index: number; methodAbi: MethodAbi }> }, entry) => { + (result[entry.methodAbi.name] || (result[entry.methodAbi.name] = [])).push(entry); + }, + {}, + ); + // Rename overloaded methods to overloadedMethoName_1, overloadedMethoName_2, ... + const methodAbisRenamed = _.transform( + methodAbisByName, + (result: MethodAbi[], methodAbisWithSameName: Array<{ index: number; methodAbi: MethodAbi }>) => { + _.forEach(methodAbisWithSameName, (entry, i: number) => { + if (methodAbisWithSameName.length > 1) { + const overloadedMethodId = i + 1; + const sanitizedMethodName = `${entry.methodAbi.name}_${overloadedMethodId}`; + const indexOfExistingAbiWithSanitizedMethodNameIfExists = _.findIndex( + methodAbis, + methodAbi => methodAbi.name === sanitizedMethodName, + ); + if (indexOfExistingAbiWithSanitizedMethodNameIfExists >= 0) { + const methodName = entry.methodAbi.name; + throw new Error( + `Failed to rename overloaded method '${methodName}' to '${sanitizedMethodName}'. A method with this name already exists.`, + ); + } + entry.methodAbi.name = sanitizedMethodName; + } + // Add method to list of ABIs in its original position + result.splice(entry.index, 0, entry.methodAbi); + }); + }, + [...Array(methodAbis.length)], + ); + return contractAbi; + }, +}; |