diff options
author | Jacob Evans <dekz@dekz.net> | 2018-04-12 08:20:52 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-12 08:20:52 +0800 |
commit | be73084e04264d44cfbd7cf6b8ba3a993368133d (patch) | |
tree | 68fc540971871fd99d0977957ac20132d6efed60 /packages/utils/src | |
parent | 63b941fbaf08167234cf7871e874c1a96e4347fa (diff) | |
parent | 5eb90697c824f1c98467cdb6cd71dbb94ff70805 (diff) | |
download | dexon-sol-tools-be73084e04264d44cfbd7cf6b8ba3a993368133d.tar dexon-sol-tools-be73084e04264d44cfbd7cf6b8ba3a993368133d.tar.gz dexon-sol-tools-be73084e04264d44cfbd7cf6b8ba3a993368133d.tar.bz2 dexon-sol-tools-be73084e04264d44cfbd7cf6b8ba3a993368133d.tar.lz dexon-sol-tools-be73084e04264d44cfbd7cf6b8ba3a993368133d.tar.xz dexon-sol-tools-be73084e04264d44cfbd7cf6b8ba3a993368133d.tar.zst dexon-sol-tools-be73084e04264d44cfbd7cf6b8ba3a993368133d.zip |
Merge branch 'development' into feature/subproviders/mnemonic-wallet-subprovider
Diffstat (limited to 'packages/utils/src')
-rw-r--r-- | packages/utils/src/abi_utils.ts | 71 | ||||
-rw-r--r-- | packages/utils/src/constants.ts | 1 | ||||
-rw-r--r-- | packages/utils/src/index.ts | 3 |
3 files changed, 75 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..c4533d42e --- /dev/null +++ b/packages/utils/src/abi_utils.ts @@ -0,0 +1,71 @@ +import { AbiDefinition, AbiType, ConstructorAbi, ContractAbi, DataItem, MethodAbi } from '@0xproject/types'; +import * as _ from 'lodash'; + +export const abiUtils = { + parseFunctionParam(param: DataItem): string { + if (param.type === 'tuple') { + // Parse out tuple types into {type_1, type_2, ..., type_N} + const tupleComponents = param.components; + const paramString = _.map(tupleComponents, component => this.parseFunctionParam(component)); + const tupleParamString = `{${paramString}}`; + return tupleParamString; + } + return param.type; + }, + getFunctionSignature(methodAbi: MethodAbi): string { + const functionName = methodAbi.name; + const parameterTypeList = _.map(methodAbi.inputs, (param: DataItem) => this.parseFunctionParam(param)); + const functionSignature = `${functionName}(${parameterTypeList})`; + return functionSignature; + }, + /** + * Solidity supports function overloading whereas TypeScript does not. + * See: https://solidity.readthedocs.io/en/v0.4.21/contracts.html?highlight=overload#function-overloading + * In order to support overloaded functions, we suffix overloaded function names with an index. + * This index should be deterministic, regardless of function ordering within the smart contract. To do so, + * we assign indexes based on the alphabetical order of function signatures. + * + * E.g + * ['f(uint)', 'f(uint,byte32)'] + * Should always be renamed to: + * ['f1(uint)', 'f2(uint,byte32)'] + * Regardless of the order in which these these overloaded functions are declared within the contract ABI. + */ + renameOverloadedMethods(inputContractAbi: ContractAbi): ContractAbi { + const contractAbi = _.cloneDeep(inputContractAbi); + const methodAbis = contractAbi.filter((abi: AbiDefinition) => abi.type === AbiType.Function) as MethodAbi[]; + // Sort method Abis into alphabetical order, by function signature + const methodAbisOrdered = _.sortBy(methodAbis, [ + (methodAbi: MethodAbi) => { + const functionSignature = this.getFunctionSignature(methodAbi); + return functionSignature; + }, + ]); + // Group method Abis by name (overloaded methods will be grouped together, in alphabetical order) + const methodAbisByName: { [key: string]: MethodAbi[] } = {}; + _.each(methodAbisOrdered, methodAbi => { + (methodAbisByName[methodAbi.name] || (methodAbisByName[methodAbi.name] = [])).push(methodAbi); + }); + // Rename overloaded methods to overloadedMethodName1, overloadedMethodName2, ... + _.each(methodAbisByName, methodAbisWithSameName => { + _.each(methodAbisWithSameName, (methodAbi, i: number) => { + if (methodAbisWithSameName.length > 1) { + const overloadedMethodId = i + 1; + const sanitizedMethodName = `${methodAbi.name}${overloadedMethodId}`; + const indexOfExistingAbiWithSanitizedMethodNameIfExists = _.findIndex( + methodAbis, + currentMethodAbi => currentMethodAbi.name === sanitizedMethodName, + ); + if (indexOfExistingAbiWithSanitizedMethodNameIfExists >= 0) { + const methodName = methodAbi.name; + throw new Error( + `Failed to rename overloaded method '${methodName}' to '${sanitizedMethodName}'. A method with this name already exists.`, + ); + } + methodAbi.name = sanitizedMethodName; + } + }); + }); + return contractAbi; + }, +}; diff --git a/packages/utils/src/constants.ts b/packages/utils/src/constants.ts new file mode 100644 index 000000000..2894d4747 --- /dev/null +++ b/packages/utils/src/constants.ts @@ -0,0 +1 @@ +export const NULL_BYTES = '0x'; diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index debcce746..75c096ee6 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -5,3 +5,6 @@ export { intervalUtils } from './interval_utils'; export { BigNumber } from './configured_bignumber'; export { AbiDecoder } from './abi_decoder'; export { logUtils } from './log_utils'; +export { abiUtils } from './abi_utils'; + +export { NULL_BYTES } from './constants'; |