/** * Event emission functions */ import type { AppEvent } from './types'; import { getAbiManifest, getEventPayloadType } from '../abi/helpers'; import { serializeWithAbi } from '../utils/abi-serialize'; // This will be provided by QuickJS runtime declare const env: { emit(kind: Uint8Array, data: Uint8Array): void; emit_with_handler(kind: Uint8Array, data: Uint8Array, handler: Uint8Array): void; }; const encoder = new TextEncoder(); export function emit(event: unknown): void { const kind = encoder.encode(eventConstructorName(event)); const payload = extractPayload(event); env.emit(kind, payload); } export function emitWithHandler(event: unknown, handlerName: string): void { const kind = encoder.encode(eventConstructorName(event)); const payload = extractPayload(event); const handler = encoder.encode(handlerName); env.emit_with_handler(kind, payload, handler); } function extractPayload(event: unknown): Uint8Array { const eventName = eventConstructorName(event); // ABI-aware serialization is required const abi = getAbiManifest(); if (!abi) { throw new Error('ABI manifest is required but not available for event serialization'); } const payloadType = getEventPayloadType(abi, eventName); if (!payloadType) { // Event has no payload type, return empty payload return new Uint8Array(0); } // Extract the actual payload value from the event let payloadValue: unknown = event; // If event has a serialize method, use it first const maybeEvent = event as AppEvent | undefined; if (maybeEvent && typeof maybeEvent.serialize === 'function') { const serialized = maybeEvent.serialize(); if (serialized instanceof Uint8Array) { return serialized; } if (typeof serialized === 'string') { return encoder.encode(serialized); } payloadValue = serialized; } else if (typeof event === 'object' && event !== null) { // Extract payload from event object const eventObj = event as Record; if ('payload' in eventObj) { payloadValue = eventObj.payload; } else { // Use the event object itself as payload payloadValue = eventObj; } } // Serialize event payload according to ABI return serializeWithAbi(payloadValue, payloadType, abi); } function eventConstructorName(event: unknown): string { if (event && typeof event === 'object' && 'constructor' in event) { const ctor = (event as any).constructor; if (ctor) { if ('eventName' in ctor && typeof ctor.eventName === 'string') { return ctor.eventName; } if (typeof ctor.name === 'string' && ctor.name.length > 0) { return ctor.name; } } } return 'AnonymousEvent'; }