import { FrameSystemAccountInfo, FrameSystemEventRecord } from 'https://deno.land/x/polkadot@0.2.45/types/lookup.ts'; import { HexString } from 'https://deno.land/x/polkadot@0.2.45/util/types.ts'; import { UnsubscribePromise } from 'https://deno.land/x/polkadot@0.2.45/api/types/index.ts'; import { IBalanceCallback, IBlocksCallback } from '../types/index.ts'; import { IGearEvent, IGearVoucherEvent } from './types.ts'; import { Transfer, UserMessageSent } from './GearEvents.ts'; import { GearApi } from '../GearApi.ts'; import { Vec } from 'https://deno.land/x/polkadot@0.2.45/types-codec/index.ts'; export class GearEvents { private api: GearApi; constructor(gearApi: GearApi) { this.api = gearApi; } subscribeToGearEvent( method: M, callback: (event: IGearEvent[M]) => void | Promise, fromBlock?: number | HexString, blocks: 'finalized' | 'latest' = 'latest', ) { const handler = (events: Vec) => { events .filter(({ event }) => event.method === method) .forEach(({ event }) => { callback(event as IGearEvent[M]); }); }; if (fromBlock) { return this.api.blocks.subscribeToHeadsFrom( fromBlock, (header) => { this.api .at(header.hash) .then((apiAt) => apiAt.query.system.events()) .then(handler); }, blocks, ); } if (blocks === 'latest') { return this.api.query.system.events(handler); } return this.api.rpc.chain.subscribeFinalizedHeads((header) => { this.api .at(header.hash) .then((apiAt) => apiAt.query.system.events()) .then(handler); }); } subscribeToGearVoucherEvent( method: M, callback: (event: IGearVoucherEvent[M]) => void | Promise, ) { return this.api.query.system.events((events) => { events .filter(({ event }) => event.method === method) .forEach(({ event }) => { callback(event as IGearVoucherEvent[M]); }); }); } #umsActorsMatch(from: HexString, to: HexString, event: UserMessageSent): boolean { if (event.data.message.source.eq(from) || event.data.message.destination.eq(to)) { return true; } return false; } subscribeToUserMessageSentByActor( options: { from?: HexString; to?: HexString }, callback: (event: UserMessageSent) => void, ) { return this.api.query.system.events((events) => { events .filter(({ event }) => event.method === 'UserMessageSent') .forEach(({ event }) => { if (this.#umsActorsMatch(options.from, options.to, event as UserMessageSent)) { callback(event as UserMessageSent); } }); }); } subscribeToTransferEvents(callback: (event: Transfer) => void | Promise): UnsubscribePromise { return this.api.query.system.events((events) => { events .filter(({ event }) => this.api.events.balances.Transfer.is(event)) .forEach(({ event }) => { callback(event as Transfer); }); }); } /** * @deprecated Use api.blocks.subscribeNewHeads instead */ subscribeToNewBlocks(callback: IBlocksCallback): UnsubscribePromise { return this.api.rpc.chain.subscribeNewHeads((header) => { callback(header); }); } async subscribeToBalanceChanges(accountAddress: string, callback: IBalanceCallback): UnsubscribePromise { let { data: { free: previousFree }, } = (await this.api.query.system.account(accountAddress)) as FrameSystemAccountInfo; return this.api.query.system.account(accountAddress, ({ data: { free: currentFree } }) => { if (!currentFree.sub(previousFree).isZero()) { callback(this.api.createType('Balance', currentFree)); previousFree = currentFree; } }); } }