github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/js/src/solts/lib/solidity.ts (about) 1 import { camelCase } from 'camel-case'; 2 import { Keccak } from 'sha3'; 3 import ts, { factory, TypeNode } from 'typescript'; 4 import { ABI } from '../../contracts/abi'; 5 import { asArray, asRefNode, asTuple, BooleanType, BufferType, NumberType, StringType, VoidType } from './syntax'; 6 7 export function sha3(str: string): string { 8 const hash = new Keccak(256).update(str); 9 return hash.digest('hex').toUpperCase(); 10 } 11 12 export function nameFromABI(abi: ABI.Func | ABI.Event): string { 13 if (abi.name.indexOf('(') !== -1) { 14 return abi.name; 15 } 16 const typeName = (abi.inputs as (ABI.EventInput | ABI.FunctionIO)[]).map((i) => i.type).join(','); 17 return abi.name + '(' + typeName + ')'; 18 } 19 20 export function getSize(type: string): number { 21 return parseInt(type.replace(/.*\[|\].*/gi, ''), 10); 22 } 23 24 export function getRealType(type: string): ts.TypeNode { 25 if (/\[\]/i.test(type)) { 26 return asArray(getRealType(type.replace(/\[\]/, ''))); 27 } 28 if (/\[.*\]/i.test(type)) { 29 return asTuple(getRealType(type.replace(/\[.*\]/, '')), getSize(type)); 30 } else if (/int/i.test(type)) { 31 return NumberType; 32 } else if (/bool/i.test(type)) { 33 return BooleanType; 34 } else if (/bytes/i.test(type)) { 35 return asRefNode(BufferType); 36 } else { 37 return StringType; 38 } // address, bytes 39 } 40 41 export function inputOuputsToType(ios?: InputOutput[]): TypeNode { 42 if (!ios?.length) { 43 return VoidType; 44 } 45 const named = ios.filter((out) => out !== undefined && out.name !== ''); 46 if (ios.length === named.length) { 47 return factory.createTypeLiteralNode( 48 ios.map(({ name, type }) => factory.createPropertySignature(undefined, name, undefined, getRealType(type))), 49 ); 50 } else { 51 return factory.createTupleTypeNode(ios.map(({ type }) => getRealType(type))); 52 } 53 } 54 55 export type InputOutput = { 56 name: string; 57 type: string; 58 }; 59 export type MethodType = 'function' | 'event'; 60 export type Signature = { 61 hash: string; 62 constant: boolean; 63 inputs: Array<InputOutput>; 64 outputs?: Array<InputOutput>; 65 }; 66 export type Method = { 67 name: string; 68 type: MethodType; 69 signatures: Array<Signature>; 70 }; 71 export type ContractMethods = Map<string, Method>; 72 export type ContractMethodsList = Array<{ name: string } & Method>; 73 74 export function getContractMethods(abi: ABI.FunctionOrEvent[]): Method[] { 75 // solidity allows duplicate function names 76 const contractMethods = abi.reduce<ContractMethods>((signatures, abi) => { 77 if (abi.name === '') { 78 return signatures; 79 } 80 if (abi.type === 'function') { 81 const method = signatures.get(abi.name) || { 82 name: abi.name, 83 type: 'function', 84 signatures: [], 85 }; 86 87 const signature = { 88 hash: getFunctionSelector(abi), 89 constant: abi.constant || false, 90 inputs: getInputs(abi), 91 outputs: abi.outputs?.map((abi) => { 92 return { name: abi.name, type: abi.type }; 93 }), 94 }; 95 method.signatures.push(signature); 96 signatures.set(method.name, method); 97 } else if (abi.type === 'event') { 98 signatures.set(abi.name, { 99 name: abi.name, 100 type: 'event', 101 signatures: [ 102 { 103 hash: getEventSignature(abi), 104 constant: false, 105 inputs: getInputs(abi), 106 }, 107 ], 108 }); 109 } 110 return signatures; 111 }, new Map<string, Method>()); 112 return Array.from(contractMethods, ([name, method]) => { 113 return { name: name, type: method.type, signatures: method.signatures }; 114 }); 115 } 116 117 export function libraryName(link: string): string { 118 return link.split(':').slice(-1)[0]; 119 } 120 121 function getFunctionSelector(abi: ABI.Func): string { 122 return sha3(nameFromABI(abi)).slice(0, 8); 123 } 124 125 function getEventSignature(abi: ABI.Event): string { 126 return sha3(nameFromABI(abi)); 127 } 128 129 function getInputs(abi: ABI.FunctionOrEvent): InputOutput[] { 130 return ( 131 abi.inputs 132 ?.filter((abi) => abi.name !== '') 133 .map((abi) => { 134 return { name: abi.name, type: abi.type }; 135 }) ?? [] 136 ); 137 }