github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/js/src/solts/lib/deployer.ts (about) 1 import ts, { factory, FunctionDeclaration, SyntaxKind } from 'typescript'; 2 import { ABI } from '../../contracts/abi'; 3 import { contractFunctionName, contractTypeName } from './contract'; 4 import { callEncodeDeploy, Provider } from './provider'; 5 import { getRealType, libraryName, sha3 } from './solidity'; 6 import { 7 AsyncToken, 8 BooleanType, 9 BufferType, 10 createCall, 11 createParameter, 12 createPromiseOf, 13 declareConstant, 14 ExportToken, 15 hexToBuffer, 16 hexToKeccak256, 17 linkerName, 18 PromiseType, 19 prop, 20 QuestionToken, 21 StringType, 22 } from './syntax'; 23 24 export const deployName = factory.createIdentifier('deploy'); 25 export const deployContractName = factory.createIdentifier('deployContract'); 26 export const bytecodeName = factory.createIdentifier('bytecode'); 27 export const deployedBytecodeName = factory.createIdentifier('deployedBytecode'); 28 export const withContractMetaName = factory.createIdentifier('withContractMeta'); 29 30 // Variable names 31 const linkedBytecodeName = factory.createIdentifier('linkedBytecode'); 32 const dataName = factory.createIdentifier('data'); 33 const clientName = factory.createIdentifier('client'); 34 const librariesName = factory.createIdentifier('libraries'); 35 const depsName = factory.createIdentifier('deps'); 36 37 export function generateDeployFunction( 38 abi: ABI.Func | undefined, 39 links: string[], 40 provider: Provider, 41 abiName: ts.Identifier, 42 contractNames: ts.Identifier[], 43 ): FunctionDeclaration { 44 const output = factory.createExpressionWithTypeArguments(PromiseType, [StringType]); 45 46 const statements: ts.Statement[] = []; 47 statements.push(provider.declareContractCodec(clientName, abiName)); 48 49 let bytecode = bytecodeName; 50 const linksName = factory.createIdentifier('links'); 51 52 if (links.length) { 53 const linksArray = factory.createArrayLiteralExpression( 54 links.map((link) => 55 factory.createObjectLiteralExpression([ 56 factory.createPropertyAssignment( 57 'name', 58 factory.createStringLiteral('$' + sha3(link).toLowerCase().slice(0, 34) + '$'), 59 ), 60 factory.createPropertyAssignment('address', factory.createIdentifier(libraryName(link))), 61 ]), 62 ), 63 ); 64 statements.push(declareConstant(linksName, linksArray)); 65 statements.push(declareConstant(linkedBytecodeName, createCall(linkerName, [bytecodeName, linksName]))); 66 67 bytecode = linkedBytecodeName; 68 } 69 70 const args = abi?.inputs?.map((arg) => factory.createIdentifier(arg.name)) ?? []; 71 72 statements.push( 73 declareConstant( 74 dataName, 75 createCall(prop(BufferType, 'concat'), [ 76 factory.createArrayLiteralExpression([hexToBuffer(bytecode), callEncodeDeploy(args)]), 77 ]), 78 ), 79 ); 80 81 const contractMeta = contractNames.map((n) => { 82 const deployedBytecode = prop(n, deployedBytecodeName); 83 return { 84 abi: prop(n, abiName), 85 codeHash: hexToKeccak256(links.length ? createCall(linkerName, [deployedBytecode, linksName]) : deployedBytecode), 86 }; 87 }); 88 89 const deployFn = provider.methods.deploy.call(clientName, dataName, withContractMetaName, contractMeta); 90 91 statements.push(factory.createReturnStatement(deployFn)); 92 93 return factory.createFunctionDeclaration( 94 undefined, 95 [ExportToken], 96 undefined, 97 deployName, 98 undefined, 99 deployParameters(abi, links, provider, true), 100 output, 101 factory.createBlock(statements, true), 102 ); 103 } 104 105 export function generateDeployContractFunction( 106 abi: ABI.Func | undefined, 107 links: string[], 108 provider: Provider, 109 ): ts.FunctionDeclaration { 110 const parameters = deployParameters(abi, links, provider); 111 const addressName = factory.createIdentifier('address'); 112 const callDeploy = factory.createAwaitExpression( 113 createCall(deployName, [ 114 ...parameters.map((p) => p.name).filter((n): n is ts.Identifier => n.kind === SyntaxKind.Identifier), 115 ]), 116 ); 117 return factory.createFunctionDeclaration( 118 undefined, 119 [ExportToken, AsyncToken], 120 undefined, 121 deployContractName, 122 undefined, 123 parameters, 124 createPromiseOf(factory.createTypeReferenceNode(contractTypeName)), 125 factory.createBlock([ 126 declareConstant(addressName, callDeploy), 127 factory.createReturnStatement(createCall(contractFunctionName, [prop(depsName, clientName), addressName])), 128 ]), 129 ); 130 } 131 132 function deployParameters( 133 abi: ABI.Func | undefined, 134 links: string[], 135 provider: Provider, 136 destructure = false, 137 ): ts.ParameterDeclaration[] { 138 const parameters = abi ? abi.inputs?.map((input) => createParameter(input.name, getRealType(input.type))) ?? [] : []; 139 return [depsParameter(links, provider, destructure), ...parameters]; 140 } 141 142 function depsParameter(links: string[], provider: Provider, destructure: boolean): ts.ParameterDeclaration { 143 const libsType = links.length 144 ? [ 145 factory.createPropertySignature( 146 undefined, 147 librariesName, 148 undefined, 149 factory.createTypeLiteralNode( 150 links.map((link) => factory.createPropertySignature(undefined, libraryName(link), undefined, StringType)), 151 ), 152 ), 153 ] 154 : []; 155 const typeNode = factory.createTypeLiteralNode([ 156 factory.createPropertySignature(undefined, clientName, undefined, provider.type()), 157 factory.createPropertySignature(undefined, withContractMetaName, QuestionToken, BooleanType), 158 ...libsType, 159 ]); 160 const libsPattern = links.length 161 ? [ 162 factory.createBindingElement( 163 undefined, 164 librariesName, 165 factory.createObjectBindingPattern( 166 links.map((link) => factory.createBindingElement(undefined, undefined, libraryName(link))), 167 ), 168 ), 169 ] 170 : []; 171 const deps = destructure 172 ? factory.createObjectBindingPattern([ 173 factory.createBindingElement(undefined, undefined, clientName), 174 factory.createBindingElement(undefined, undefined, withContractMetaName), 175 ...libsPattern, 176 ]) 177 : depsName; 178 return createParameter(deps, typeNode); 179 }