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  }