github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/js/src/solts/lib/provider.ts (about)

     1  import ts, { factory } from 'typescript';
     2  import { BoundsType, CallbackReturnType } from './events';
     3  import {
     4    AddressType,
     5    ColonToken,
     6    ContractCodecType,
     7    createCall,
     8    createCallbackType,
     9    createParameter,
    10    createPromiseOf,
    11    declareConstant,
    12    ErrorType,
    13    EventType,
    14    ExportToken,
    15    MaybeUint8ArrayType,
    16    Method,
    17    QuestionToken,
    18    StringType,
    19    Uint8ArrayType,
    20    Undefined,
    21    UnknownType,
    22  } from './syntax';
    23  
    24  export const errName = factory.createIdentifier('err');
    25  export const contractCodecName = factory.createIdentifier('codec');
    26  export const eventName = factory.createIdentifier('event');
    27  
    28  export const EventErrParameter = createParameter(errName, ErrorType, undefined, true);
    29  export const EventParameter = createParameter(eventName, EventType, undefined, true);
    30  
    31  class Deploy extends Method {
    32    private abiName = factory.createIdentifier('abi');
    33    private codeHashName = factory.createIdentifier('codeHash');
    34  
    35    params = [
    36      createParameter('data', factory.createUnionTypeNode([StringType, Uint8ArrayType])),
    37      createParameter(
    38        'contractMeta',
    39        factory.createArrayTypeNode(
    40          factory.createTypeLiteralNode([
    41            factory.createPropertySignature(undefined, this.abiName, undefined, StringType),
    42            factory.createPropertySignature(undefined, this.codeHashName, undefined, Uint8ArrayType),
    43          ]),
    44        ),
    45        undefined,
    46        true,
    47      ),
    48    ];
    49    ret = createPromiseOf(AddressType);
    50  
    51    constructor() {
    52      super('deploy');
    53    }
    54  
    55    call(
    56      exp: ts.Expression,
    57      data: ts.Expression,
    58      withContractMeta: ts.Expression,
    59      contractMeta: { abi: ts.Expression; codeHash: ts.Expression }[],
    60    ): ts.CallExpression {
    61      const contractMetaLiteral = factory.createArrayLiteralExpression(
    62        contractMeta.map(({ abi, codeHash }) =>
    63          factory.createObjectLiteralExpression([
    64            factory.createPropertyAssignment(this.abiName, abi),
    65            factory.createPropertyAssignment(this.codeHashName, codeHash),
    66          ]),
    67        ),
    68      );
    69      return createCall(factory.createPropertyAccessExpression(exp, this.id), [
    70        data,
    71        // TODO: Contracts that may create contracts need to be deployed with contract meta for all contracts they create
    72        //  unfortunately we have no good way to determine from solc output which contracts a contract may create, so
    73        //  short of pushing all contract meta to every contract in a family of contracts we cannot safely deploy with meta
    74        //  in the general case this Burrow throws on creating a new contract if a) the parent has meta, and b) the child
    75        //  meta cannot be found. The solution is to delocalise the contract storage from the parent contract and have
    76        //  a global registry of metadata to query against when creating a contract
    77        factory.createConditionalExpression(withContractMeta, QuestionToken, contractMetaLiteral, ColonToken, Undefined),
    78      ]);
    79    }
    80  }
    81  
    82  class Call extends Method {
    83    params = [
    84      createParameter('data', factory.createUnionTypeNode([StringType, Uint8ArrayType])),
    85      createParameter('address', StringType),
    86    ];
    87    ret = createPromiseOf(MaybeUint8ArrayType);
    88  
    89    constructor() {
    90      super('call');
    91    }
    92  
    93    call(exp: ts.Expression, data: ts.Expression, address: ts.Expression) {
    94      return createCall(factory.createPropertyAccessExpression(exp, this.id), [data, address]);
    95    }
    96  }
    97  
    98  class CallSim extends Method {
    99    params = [
   100      createParameter('data', factory.createUnionTypeNode([StringType, Uint8ArrayType])),
   101      createParameter('address', StringType),
   102    ];
   103    ret = createPromiseOf(MaybeUint8ArrayType);
   104  
   105    constructor() {
   106      super('callSim');
   107    }
   108  
   109    call(exp: ts.Expression, data: ts.Expression, address: ts.Expression) {
   110      return createCall(factory.createPropertyAccessExpression(exp, this.id), [data, address]);
   111    }
   112  }
   113  
   114  class Listen extends Method {
   115    params = [
   116      createParameter('signatures', factory.createArrayTypeNode(StringType)),
   117      createParameter('address', StringType),
   118      createParameter('callback', createCallbackType([EventErrParameter, EventParameter], CallbackReturnType)),
   119      createParameter('start', BoundsType, undefined, true),
   120      createParameter('end', BoundsType, undefined, true),
   121    ];
   122    ret = UnknownType;
   123  
   124    constructor() {
   125      super('listen');
   126    }
   127  
   128    call(
   129      exp: ts.Expression,
   130      sig: ts.Expression,
   131      addr: ts.Expression,
   132      callback: ts.Expression,
   133      start: ts.Expression,
   134      end: ts.Expression,
   135    ) {
   136      return createCall(factory.createPropertyAccessExpression(exp, this.id), [sig, addr, callback, start, end]);
   137    }
   138  }
   139  
   140  class ContractCodec extends Method {
   141    params = [createParameter('contractABI', StringType)];
   142    ret = ContractCodecType;
   143  
   144    constructor() {
   145      super('contractCodec');
   146    }
   147  
   148    call(provider: ts.Expression, contractABI: ts.Expression) {
   149      return createCall(factory.createPropertyAccessExpression(provider, this.id), [contractABI]);
   150    }
   151  }
   152  
   153  export class Provider {
   154    private name = factory.createIdentifier('Provider');
   155  
   156    methods = {
   157      deploy: new Deploy(),
   158      call: new Call(),
   159      callSim: new CallSim(),
   160      listen: new Listen(),
   161      contractCodec: new ContractCodec(),
   162    };
   163  
   164    createInterface(extern?: boolean): ts.InterfaceDeclaration {
   165      return factory.createInterfaceDeclaration(
   166        undefined,
   167        extern ? [ExportToken] : undefined,
   168        this.name,
   169        undefined,
   170        undefined,
   171        [
   172          this.methods.deploy.signature(),
   173          this.methods.call.signature(),
   174          this.methods.callSim.signature(),
   175          this.methods.listen.signature(),
   176          this.methods.contractCodec.signature(),
   177        ],
   178      );
   179    }
   180  
   181    declareContractCodec(client: ts.Identifier, abiName: ts.Identifier): ts.VariableStatement {
   182      return declareConstant(contractCodecName, this.methods.contractCodec.call(client, abiName));
   183    }
   184  
   185    type(): ts.TypeReferenceNode {
   186      return factory.createTypeReferenceNode(this.name);
   187    }
   188  }
   189  
   190  const encodeDeploy = factory.createIdentifier('encodeDeploy');
   191  const encodeFunctionData = factory.createIdentifier('encodeFunctionData');
   192  const decodeFunctionResult = factory.createIdentifier('decodeFunctionResult ');
   193  const decodeEventLog = factory.createIdentifier('decodeEventLog ');
   194  
   195  export function callEncodeDeploy(args: ts.Expression[]): ts.CallExpression {
   196    return createCall(factory.createPropertyAccessExpression(contractCodecName, encodeDeploy), [...args]);
   197  }
   198  
   199  export function callEncodeFunctionData(signature: string, args: ts.Expression[]): ts.CallExpression {
   200    return createCall(factory.createPropertyAccessExpression(contractCodecName, encodeFunctionData), [
   201      factory.createStringLiteral(signature),
   202      ...args,
   203    ]);
   204  }
   205  
   206  export function callDecodeFunctionResult(signature: string, data: ts.Expression): ts.CallExpression {
   207    return createCall(factory.createPropertyAccessExpression(contractCodecName, decodeFunctionResult), [
   208      factory.createStringLiteral(signature),
   209      data,
   210    ]);
   211  }
   212  
   213  export function callDecodeEventLog(signature: string, data: ts.Expression, topics: ts.Expression): ts.CallExpression {
   214    return createCall(factory.createPropertyAccessExpression(contractCodecName, decodeEventLog), [
   215      factory.createStringLiteral(signature),
   216      data,
   217      topics,
   218    ]);
   219  }