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 }