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

     1  import * as ts from 'typescript';
     2  import { factory } from 'typescript';
     3  import { decodeName } from './decoder';
     4  import { EventErrParameter, eventName } from './provider';
     5  import { ContractMethodsList, getRealType, InputOutput, sha3 } from './solidity';
     6  import {
     7    arrowFuncT,
     8    CancelStreamSignalType,
     9    constObject,
    10    createCall,
    11    createParameter,
    12    declareConstant,
    13    EqualsGreaterThanToken,
    14    EventType,
    15    ExportToken,
    16    listenerForName,
    17    NumberType,
    18    prop,
    19    ReturnType,
    20    TType,
    21    UnknownType,
    22    VoidType,
    23  } from './syntax';
    24  
    25  export const eventsName = factory.createIdentifier('events');
    26  export const eventNameTypeName = factory.createIdentifier('EventName');
    27  export const BoundsType = factory.createUnionTypeNode([
    28    ...['first', 'latest', 'stream'].map((s) => factory.createLiteralTypeNode(factory.createStringLiteral(s))),
    29    NumberType,
    30  ]);
    31  export const CallbackReturnType = factory.createUnionTypeNode([CancelStreamSignalType, VoidType]);
    32  
    33  const typedListenerName = factory.createIdentifier('TypedListener');
    34  
    35  const logName = factory.createIdentifier('log');
    36  const dataName = factory.createIdentifier('data');
    37  const topicsName = factory.createIdentifier('topics');
    38  const taggedPayloadName = factory.createIdentifier('TaggedPayload');
    39  const solidityEventName = factory.createIdentifier('SolidityEvent');
    40  const eventRegistryName = factory.createIdentifier('EventRegistry');
    41  const signatureName = factory.createIdentifier('signature');
    42  const taggedName = factory.createIdentifier('tagged');
    43  const payloadName = factory.createIdentifier('payload');
    44  
    45  export function eventSignature(name: string, inputs: InputOutput[]): string {
    46    return `${name}(${inputs.map(({ type }) => type).join(',')})`;
    47  }
    48  
    49  export function eventSigHash(name: string, inputs: InputOutput[]): string {
    50    return sha3(eventSignature(name, inputs));
    51  }
    52  
    53  export function dataFromEvent(event: ts.Expression): ts.Expression {
    54    return prop(prop(event, logName, true), dataName);
    55  }
    56  
    57  export function topicsFromEvent(event: ts.Expression): ts.Expression {
    58    return prop(prop(event, logName, true), topicsName);
    59  }
    60  
    61  export function createListenerForFunction(clientName: ts.Identifier, addressName: ts.Identifier): ts.ArrowFunction {
    62    const eventNamesName = factory.createIdentifier('eventNames');
    63    const typedListener = factory.createTypeReferenceNode(typedListenerName, [TType]);
    64    return arrowFuncT(
    65      [createParameter(eventNamesName, factory.createArrayTypeNode(TType))],
    66      factory.createTypeReferenceNode(eventNameTypeName),
    67      typedListener,
    68      factory.createAsExpression(
    69        // The intermediate as unknown expression is not needed if tsconfig is in 'strict mode' but otherwise tsc complains
    70        // that the types do not sufficiently overlap
    71        factory.createAsExpression(
    72          createCall(listenerForName, [clientName, addressName, eventsName, decodeName, eventNamesName]),
    73          UnknownType,
    74        ),
    75        typedListener,
    76      ),
    77    );
    78  }
    79  
    80  export function createListener(clientName: ts.Identifier, addressName: ts.Identifier): ts.AsExpression {
    81    const eventNamesType = factory.createTypeReferenceNode(eventNameTypeName);
    82    const typedListener = factory.createTypeReferenceNode(typedListenerName, [eventNamesType]);
    83    return factory.createAsExpression(
    84      createCall(listenerForName, [
    85        clientName,
    86        addressName,
    87        eventsName,
    88        decodeName,
    89        factory.createAsExpression(
    90          createCall(prop('Object', 'keys'), [eventsName]),
    91          factory.createArrayTypeNode(eventNamesType),
    92        ),
    93      ]),
    94      typedListener,
    95    );
    96  }
    97  
    98  export function declareEvents(events: ContractMethodsList): ts.VariableStatement {
    99    return declareConstant(
   100      eventsName,
   101      constObject(
   102        events.map((a) => {
   103          const signature = a.signatures[0];
   104          return factory.createPropertyAssignment(
   105            a.name,
   106            constObject([
   107              factory.createPropertyAssignment(signatureName, factory.createStringLiteral(signature.hash)),
   108              factory.createPropertyAssignment(
   109                taggedName,
   110                factory.createArrowFunction(
   111                  undefined,
   112                  undefined,
   113                  signature.inputs.map((i) => createParameter(i.name, getRealType(i.type))),
   114                  undefined,
   115                  EqualsGreaterThanToken,
   116                  constObject([
   117                    factory.createPropertyAssignment('name', factory.createStringLiteral(a.name)),
   118                    factory.createPropertyAssignment(
   119                      payloadName,
   120                      constObject(
   121                        signature.inputs.map(({ name }) =>
   122                          factory.createPropertyAssignment(name, factory.createIdentifier(name)),
   123                        ),
   124                      ),
   125                    ),
   126                  ]),
   127                ),
   128              ),
   129            ]),
   130          );
   131        }),
   132      ),
   133    );
   134  }
   135  
   136  export function eventTypes(): ts.TypeAliasDeclaration[] {
   137    const tExtendsEventName = factory.createTypeParameterDeclaration(
   138      factory.createIdentifier('T'),
   139      factory.createTypeReferenceNode(eventNameTypeName, undefined),
   140      undefined,
   141    );
   142    const tType = factory.createTypeReferenceNode(factory.createIdentifier('T'), undefined);
   143    return [
   144      factory.createTypeAliasDeclaration(
   145        undefined,
   146        undefined,
   147        eventRegistryName,
   148        undefined,
   149        factory.createTypeQueryNode(eventsName),
   150      ),
   151      factory.createTypeAliasDeclaration(
   152        undefined,
   153        [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
   154        eventNameTypeName,
   155        undefined,
   156        factory.createTypeOperatorNode(
   157          ts.SyntaxKind.KeyOfKeyword,
   158          factory.createTypeReferenceNode(eventRegistryName, undefined),
   159        ),
   160      ),
   161      factory.createTypeAliasDeclaration(
   162        undefined,
   163        [ExportToken],
   164        taggedPayloadName,
   165        [tExtendsEventName],
   166        factory.createIntersectionTypeNode([
   167          factory.createTypeReferenceNode(ReturnType, [
   168            factory.createIndexedAccessTypeNode(
   169              factory.createIndexedAccessTypeNode(factory.createTypeReferenceNode(eventRegistryName, undefined), tType),
   170              factory.createLiteralTypeNode(factory.createStringLiteral(taggedName.text)),
   171            ),
   172          ]),
   173          factory.createTypeLiteralNode([factory.createPropertySignature(undefined, eventName, undefined, EventType)]),
   174        ]),
   175      ),
   176      factory.createTypeAliasDeclaration(
   177        undefined,
   178        [ExportToken],
   179        solidityEventName,
   180        [tExtendsEventName],
   181        factory.createIndexedAccessTypeNode(
   182          factory.createTypeReferenceNode(taggedPayloadName, [tType]),
   183          factory.createLiteralTypeNode(factory.createStringLiteral(payloadName.text)),
   184        ),
   185      ),
   186      factory.createTypeAliasDeclaration(
   187        undefined,
   188        [ExportToken],
   189        typedListenerName,
   190        [factory.createTypeParameterDeclaration('T', factory.createTypeReferenceNode(eventNameTypeName))],
   191        factory.createFunctionTypeNode(
   192          [],
   193          [
   194            createParameter(
   195              'callback',
   196              factory.createFunctionTypeNode(
   197                [],
   198                [
   199                  EventErrParameter,
   200                  createParameter(
   201                    eventName,
   202                    factory.createTypeReferenceNode(taggedPayloadName, [TType]),
   203                    undefined,
   204                    true,
   205                  ),
   206                ],
   207                VoidType,
   208              ),
   209            ),
   210            createParameter('start', BoundsType, undefined, true),
   211            createParameter('end', BoundsType, undefined, true),
   212          ],
   213          UnknownType,
   214        ),
   215      ),
   216    ];
   217  }