import { YlideMailerV8 } from '@ylide/ethereum-contracts'; import { BroadcastPushEventObject, BroadcastPushEvent } from '@ylide/ethereum-contracts/lib/YlideMailerV8'; import { Uint256 } from '@ylide/sdk'; import { ethers } from 'ethers'; import { BlockNumberRingBufferIndex, ethersEventToInternalEvent, ethersLogToInternalEvent } from '../../controllers'; import { IEVMMailerContractLink, IEVMEnrichedEvent, IEVMMessage, bnToUint256, encodeEvmMsgId, EVM_NAMES, EVM_CONTRACT_TO_NETWORK, IEVMEvent, } from '../../misc'; import { EthereumMailerV8Wrapper } from './EthereumMailerV8Wrapper'; import { parseOutLogs } from './utils'; export class EthereumMailerV8WrapperBroadcast { constructor(public readonly wrapper: EthereumMailerV8Wrapper) { // } processBroadcastPushEvent( mailer: IEVMMailerContractLink, event: IEVMEnrichedEvent, ): IEVMMessage { return { isBroadcast: true, feedId: bnToUint256(event.event.parsed.feedId), msgId: encodeEvmMsgId( true, mailer.id, event.event.blockNumber, event.event.transactionIndex, event.event.logIndex, ), createdAt: event.block.timestamp, senderAddress: event.tx.from, recipientAddress: '0'.repeat(64) as Uint256, blockchain: EVM_NAMES[EVM_CONTRACT_TO_NETWORK[mailer.id]], key: new Uint8Array(0), $$meta: { contentId: bnToUint256(event.event.parsed.contentId), index: BlockNumberRingBufferIndex.decodeIndexValue( bnToUint256(event.event.parsed.previousFeedEventsIndex), ), ...event, }, }; } async createBroadcastFeed( mailer: IEVMMailerContractLink, signer: ethers.Signer, from: string, isPublic: boolean, value: ethers.BigNumber, ): Promise<{ tx: ethers.ContractTransaction; receipt: ethers.ContractReceipt; events: { log: ethers.providers.Log; logDescription: ethers.utils.LogDescription }[]; feedId: Uint256 | null; }> { const contract = this.wrapper.cache.getContract(mailer.address, signer); const tx = await contract.createBroadcastFeed(isPublic, { from, value }); const receipt = await tx.wait(); const { byName: { BroadcastFeedCreated: events }, } = parseOutLogs(contract, receipt.logs); const feedId = events[0]?.logDescription.args?.feedId ? bnToUint256(events[0]?.logDescription.args?.feedId) : null; return { tx, receipt, events, feedId }; } async getBroadcastFeedParams( mailer: IEVMMailerContractLink, feedId: Uint256, ): Promise<{ owner: string; isPublic: boolean; messagesIndex: number[]; messagesCount: number; }> { return await this.wrapper.cache.contractOperation(mailer, async contract => { const [owner, isPublic, messagesIndex, messagesCount] = await contract.functions.broadcastFeeds( `0x${feedId}`, ); return { owner, isPublic, messagesIndex: BlockNumberRingBufferIndex.decodeIndexValue(bnToUint256(messagesIndex)), messagesCount: messagesCount.toNumber(), }; }); } async setBroadcastFeedPublicity( mailer: IEVMMailerContractLink, signer: ethers.Signer, from: string, feedId: Uint256, isPublic: boolean, ): Promise<{ tx: ethers.ContractTransaction; receipt: ethers.ContractReceipt }> { const contract = this.wrapper.cache.getContract(mailer.address, signer); const tx = await contract.changeBroadcastFeedPublicity(`0x${feedId}`, isPublic, { from }); const receipt = await tx.wait(); return { tx, receipt }; } async setBroadcastFeedOwner( mailer: IEVMMailerContractLink, signer: ethers.Signer, from: string, feedId: Uint256, newOwner: string, ): Promise<{ tx: ethers.ContractTransaction; receipt: ethers.ContractReceipt }> { const contract = this.wrapper.cache.getContract(mailer.address, signer); const tx = await contract.transferBroadcastFeedOwnership(`0x${feedId}`, newOwner, { from }); const receipt = await tx.wait(); return { tx, receipt }; } async addBroadcastFeedWriter( mailer: IEVMMailerContractLink, signer: ethers.Signer, from: string, feedId: Uint256, writer: string, ): Promise<{ tx: ethers.ContractTransaction; receipt: ethers.ContractReceipt }> { const contract = this.wrapper.cache.getContract(mailer.address, signer); const tx = await contract.addBroadcastFeedWriter(`0x${feedId}`, writer, { from }); const receipt = await tx.wait(); return { tx, receipt }; } async removeBroadcastFeedWriter( mailer: IEVMMailerContractLink, signer: ethers.Signer, from: string, feedId: Uint256, writer: string, ): Promise<{ tx: ethers.ContractTransaction; receipt: ethers.ContractReceipt }> { const contract = this.wrapper.cache.getContract(mailer.address, signer); const tx = await contract.removeBroadcastFeedWriter(`0x${feedId}`, writer, { from }); const receipt = await tx.wait(); return { tx, receipt }; } async isBroadcastFeedWriter(mailer: IEVMMailerContractLink, feedId: Uint256, address: string): Promise { return await this.wrapper.cache.contractOperation(mailer, async contract => { return await contract.isBroadcastFeedWriter(`0x${feedId}`, address); }); } async retrieveBroadcastHistoryDesc( mailer: IEVMMailerContractLink, feedId: Uint256, fromMessage: IEVMMessage | null, includeFromMessage: boolean, toMessage: IEVMMessage | null, includeToMessage: boolean, limit: number | null, ): Promise { const getBaseIndex: () => Promise = async () => (await this.getBroadcastFeedParams(mailer, feedId)).messagesIndex; const getFilter = (contract: YlideMailerV8) => contract.filters.BroadcastPush(null, `0x${feedId}`); const processEvent = (event: IEVMEnrichedEvent) => this.processBroadcastPushEvent(mailer, event); return await this.wrapper.retrieveHistoryDesc( mailer, getBaseIndex, getFilter, processEvent, fromMessage, includeFromMessage, toMessage, includeToMessage, limit, ); } async getBroadcastPushEvent( mailer: IEVMMailerContractLink, blockNumber: number, txIndex: number, logIndex: number, ): Promise { return await this.wrapper.cache.contractOperation(mailer, async (contract, provider) => { const events: BroadcastPushEvent[] = await contract.queryFilter( contract.filters.BroadcastPush(), blockNumber, blockNumber, ); const event = events.find( e => e.blockNumber === blockNumber && e.transactionIndex === txIndex && e.logIndex === logIndex, ); if (!event) { return null; } const [enriched] = await this.wrapper.blockchainReader.enrichEvents([ ethersEventToInternalEvent(event), ]); return this.processBroadcastPushEvent(mailer, enriched); }); } async sendBroadcast( mailer: IEVMMailerContractLink, signer: ethers.Signer, from: string, feedId: Uint256, uniqueId: number, content: Uint8Array, value: ethers.BigNumber, ): Promise<{ tx: ethers.ContractTransaction; receipt: ethers.ContractReceipt; logs: ethers.utils.LogDescription[]; broadcastPushEvents: IEVMEvent[]; messages: IEVMMessage[]; }> { const contract = this.wrapper.cache.getContract(mailer.address, signer); const tx = await contract.sendBroadcast(`0x${feedId}`, uniqueId, content, { from, value }); const receipt = await tx.wait(); const { logs, byName: { BroadcastPush: events }, } = parseOutLogs(contract, receipt.logs); const broadcastPushEvents = events.map(l => ethersLogToInternalEvent(l)); const enriched = await this.wrapper.blockchainReader.enrichEvents( broadcastPushEvents, ); const messages = enriched.map(e => this.processBroadcastPushEvent(mailer, e)); return { tx, receipt, logs: logs.map(l => l.logDescription), broadcastPushEvents, messages }; } async sendBroadcastHeader( mailer: IEVMMailerContractLink, signer: ethers.Signer, from: string, feedId: Uint256, uniqueId: number, firstBlockNumber: number, partsCount: number, blockCountLock: number, value: ethers.BigNumber, ): Promise<{ tx: ethers.ContractTransaction; receipt: ethers.ContractReceipt; logs: ethers.utils.LogDescription[]; broadcastPushEvents: IEVMEvent[]; messages: IEVMMessage[]; }> { const contract = this.wrapper.cache.getContract(mailer.address, signer); const tx = await contract.sendBroadcastHeader( `0x${feedId}`, uniqueId, firstBlockNumber, partsCount, blockCountLock, { from, value }, ); const receipt = await tx.wait(); const { logs, byName: { BroadcastPush: events }, } = parseOutLogs(contract, receipt.logs); const broadcastPushEvents = events.map(l => ethersLogToInternalEvent(l)); const enriched = await this.wrapper.blockchainReader.enrichEvents( broadcastPushEvents, ); const messages = enriched.map(e => this.processBroadcastPushEvent(mailer, e)); return { tx, receipt, logs: logs.map(l => l.logDescription), broadcastPushEvents, messages }; } }