From b4a5836935ac23e69a9dc8174a67e459fa513968 Mon Sep 17 00:00:00 2001 From: Julian <52217955+julianmerlo95@users.noreply.github.com> Date: Wed, 12 Jun 2024 09:21:37 -0300 Subject: [PATCH] [Blockchain Watcher] (SEI) Map redeems events for sei (#1482) * Create new process for sei redeems * Improve sei process * Resolve test * Create GetSevRedeems test * Create action test * Improve code style * Resolve PR comments * Resolve PR comments * Map total_count property --------- Co-authored-by: julian merlo --- blockchain-watcher/config/default.json | 2 +- blockchain-watcher/config/mainnet.json | 5 + .../src/domain/actions/evm/PollEvm.ts | 4 +- .../src/domain/actions/sei/GetSeiRedeems.ts | 76 +++ .../domain/actions/sei/HandleSeiRedeems.ts | 44 ++ .../src/domain/actions/sei/PollSei.ts | 197 ++++++ blockchain-watcher/src/domain/entities/sei.ts | 16 + blockchain-watcher/src/domain/repositories.ts | 6 + .../sei/seiRedeemedTransactionFoundMapper.ts | 117 ++++ ...wormchainRedeemedTransactionFoundMapper.ts | 2 +- .../repositories/RepositoriesBuilder.ts | 22 + .../repositories/StaticJobRepository.ts | 31 + .../RateLimitedSeiJsonRPCBlockRepository.ts | 25 + .../sei/SeiJsonRPCBlockRepository.ts | 217 +++++++ .../domain/actions/sei/GetSeiRedeems.test.ts | 591 ++++++++++++++++++ .../actions/sei/HandleSeiRedeems.test.ts | 575 +++++++++++++++++ .../test/domain/actions/sei/PollSei.test.ts | 570 +++++++++++++++++ .../seiRedeemedTransactionFoundMapper.test.ts | 510 +++++++++++++++ ...hainRedeemedTransactionFoundMapper.test.ts | 4 +- .../repositories/RepositoriesBuilder.test.ts | 4 +- .../repositories/StaticJobRepository.test.ts | 11 +- blockchain-watcher/test/mocks/configMock.ts | 9 +- .../workers/target-events-3.yaml | 33 + 23 files changed, 3058 insertions(+), 13 deletions(-) create mode 100644 blockchain-watcher/src/domain/actions/sei/GetSeiRedeems.ts create mode 100644 blockchain-watcher/src/domain/actions/sei/HandleSeiRedeems.ts create mode 100644 blockchain-watcher/src/domain/actions/sei/PollSei.ts create mode 100644 blockchain-watcher/src/domain/entities/sei.ts create mode 100644 blockchain-watcher/src/infrastructure/mappers/sei/seiRedeemedTransactionFoundMapper.ts create mode 100644 blockchain-watcher/src/infrastructure/repositories/sei/RateLimitedSeiJsonRPCBlockRepository.ts create mode 100644 blockchain-watcher/src/infrastructure/repositories/sei/SeiJsonRPCBlockRepository.ts create mode 100644 blockchain-watcher/test/domain/actions/sei/GetSeiRedeems.test.ts create mode 100644 blockchain-watcher/test/domain/actions/sei/HandleSeiRedeems.test.ts create mode 100644 blockchain-watcher/test/domain/actions/sei/PollSei.test.ts create mode 100644 blockchain-watcher/test/infrastructure/mappers/sei/seiRedeemedTransactionFoundMapper.test.ts diff --git a/blockchain-watcher/config/default.json b/blockchain-watcher/config/default.json index b50c89c3..4848c94c 100644 --- a/blockchain-watcher/config/default.json +++ b/blockchain-watcher/config/default.json @@ -3,7 +3,7 @@ "port": 9090, "logLevel": "debug", "dryRun": true, - "enabledPlatforms": ["solana", "evm", "sui", "aptos", "wormchain"], + "enabledPlatforms": ["solana", "evm", "sui", "aptos", "wormchain", "sei"], "sns": { "topicArn": "arn:aws:sns:us-east-1:000000000000:localstack-topic.fifo", "region": "us-east-1", diff --git a/blockchain-watcher/config/mainnet.json b/blockchain-watcher/config/mainnet.json index 12ea8b9d..e7c00996 100644 --- a/blockchain-watcher/config/mainnet.json +++ b/blockchain-watcher/config/mainnet.json @@ -146,6 +146,11 @@ "https://rpc.notadegen.com/base" ] }, + "sei": { + "network": "mainnet", + "chainId": 32, + "rpcs": ["https://rpc-sei.stingray.plus/", "https://rpc-sei.whispernode.com:443"] + }, "scroll": { "network": "mainnet", "chainId": 34, diff --git a/blockchain-watcher/src/domain/actions/evm/PollEvm.ts b/blockchain-watcher/src/domain/actions/evm/PollEvm.ts index 8cdc0c32..3f826e02 100644 --- a/blockchain-watcher/src/domain/actions/evm/PollEvm.ts +++ b/blockchain-watcher/src/domain/actions/evm/PollEvm.ts @@ -71,10 +71,10 @@ export class PollEvm extends RunPollingJob { const range = this.getBlockRange(this.latestBlockHeight); const records = await this.getEvm.execute(range, { - chain: this.cfg.chain, + environment: this.cfg.environment, chainId: this.cfg.chainId, filters: this.cfg.filters, - environment: this.cfg.environment, + chain: this.cfg.chain, }); this.lastRange = range; diff --git a/blockchain-watcher/src/domain/actions/sei/GetSeiRedeems.ts b/blockchain-watcher/src/domain/actions/sei/GetSeiRedeems.ts new file mode 100644 index 00000000..bcf8e856 --- /dev/null +++ b/blockchain-watcher/src/domain/actions/sei/GetSeiRedeems.ts @@ -0,0 +1,76 @@ +import { GetSeiOpts, PreviousRange } from "./PollSei"; +import { SeiRepository } from "../../repositories"; +import { SeiRedeem } from "../../entities/sei"; +import winston from "winston"; + +export class GetSeiRedeems { + private readonly blockRepo: SeiRepository; + protected readonly logger: winston.Logger; + + private previousFrom?: bigint; + private lastFrom?: bigint; + + constructor(blockRepo: SeiRepository) { + this.logger = winston.child({ module: "GetSeiRedeems" }); + this.blockRepo = blockRepo; + } + + async execute(opts: GetSeiOpts): Promise { + this.logger.info( + `[sei][exec] Processing range [previousFrom: ${opts.previousFrom} - lastFrom: ${opts.lastFrom}]` + ); + const { chainId, addresses, blockBatchSize, previousFrom } = opts; + + const seiRedeems = await this.blockRepo.getRedeems(chainId, addresses[0], blockBatchSize); + if (seiRedeems.length === 0) { + return []; + } + + const newLastFrom = BigInt(seiRedeems[seiRedeems.length - 1].height); + if (previousFrom === newLastFrom) { + return []; + } + + const filteredSeiRedeems = + previousFrom && newLastFrom + ? seiRedeems.filter( + (seiRedeem) => seiRedeem.height >= previousFrom && seiRedeem.height <= newLastFrom + ) + : seiRedeems; + + await Promise.all( + filteredSeiRedeems.map(async (seiRedeem) => { + const timestamp = await this.blockRepo.getBlockTimestamp(BigInt(seiRedeem.height)); + seiRedeem.timestamp = timestamp; + }) + ); + + // Update previousFrom and lastFrom with opts lastFrom + this.previousFrom = BigInt(seiRedeems[seiRedeems.length - 1].height); + this.lastFrom = newLastFrom; + + this.logger.info( + `[sei][exec] Got ${filteredSeiRedeems?.length} transactions to process for ${this.populateLog( + opts, + this.previousFrom, + this.lastFrom + )}` + ); + return filteredSeiRedeems; + } + + getUpdatedRange(): PreviousRange { + return { + previousFrom: this.previousFrom, + lastFrom: this.lastFrom, + }; + } + + private populateLog( + opts: { addresses: string[] }, + previousFrom: bigint | undefined, + lastFrom: bigint + ): string { + return `[addresses:${opts.addresses}][previousFrom: ${previousFrom} - lastFrom: ${lastFrom}]`; + } +} diff --git a/blockchain-watcher/src/domain/actions/sei/HandleSeiRedeems.ts b/blockchain-watcher/src/domain/actions/sei/HandleSeiRedeems.ts new file mode 100644 index 00000000..942c8643 --- /dev/null +++ b/blockchain-watcher/src/domain/actions/sei/HandleSeiRedeems.ts @@ -0,0 +1,44 @@ +import { TransactionFoundEvent } from "../../entities"; +import { StatRepository } from "../../repositories"; +import { SeiRedeem } from "../../entities/sei"; + +export class HandleSeiRedeems { + constructor( + private readonly cfg: HandleSeiRedeemsOptions, + private readonly mapper: (addresses: string[], seiRedeem: SeiRedeem) => TransactionFoundEvent, + private readonly target: (parsed: TransactionFoundEvent[]) => Promise, + private readonly statsRepo: StatRepository + ) {} + + public async handle(seiRedeem: SeiRedeem[]): Promise { + const filterLogs: TransactionFoundEvent[] = []; + + seiRedeem.forEach((redeem) => { + const redeemMapped = this.mapper(this.cfg.filter.addresses, redeem); + + if (redeemMapped) { + this.report(redeemMapped.attributes.protocol); + filterLogs.push(redeemMapped); + } + }); + + await this.target(filterLogs); + return filterLogs; + } + + private report(protocol: string) { + const labels = { + commitment: "immediate", + chain: "sei", + job: this.cfg.id, + protocol, + }; + this.statsRepo.count(this.cfg.metricName, labels); + } +} + +export interface HandleSeiRedeemsOptions { + metricName: string; + filter: { addresses: string[] }; + id: string; +} diff --git a/blockchain-watcher/src/domain/actions/sei/PollSei.ts b/blockchain-watcher/src/domain/actions/sei/PollSei.ts new file mode 100644 index 00000000..2bc46fa9 --- /dev/null +++ b/blockchain-watcher/src/domain/actions/sei/PollSei.ts @@ -0,0 +1,197 @@ +import { MetadataRepository, SeiRepository, StatRepository } from "../../repositories"; +import { RunPollingJob } from "../RunPollingJob"; +import { GetSeiRedeems } from "./GetSeiRedeems"; +import winston from "winston"; + +const ID = "watch-sei-logs"; + +export class PollSei extends RunPollingJob { + protected readonly logger: winston.Logger; + private readonly metadataRepo: MetadataRepository; + private readonly getSeiRedeems: GetSeiRedeems; + private readonly blockRepo: SeiRepository; + private readonly statsRepo: StatRepository; + + private previousFrom?: bigint; + private lastFrom?: bigint; + private latestBlockHeight?: bigint; + private blockHeightCursor?: bigint; + private lastRange?: { fromBlock: bigint; toBlock: bigint }; + private cfg: PollSeiConfig; + + constructor( + blockRepo: SeiRepository, + metadataRepo: MetadataRepository, + statsRepo: StatRepository, + cfg: PollSeiConfig + ) { + super(cfg.id, statsRepo, cfg.interval); + this.blockRepo = blockRepo; + this.metadataRepo = metadataRepo; + this.statsRepo = statsRepo; + this.cfg = cfg; + this.logger = winston.child({ module: "PollSei", label: this.cfg.id }); + this.getSeiRedeems = new GetSeiRedeems(blockRepo); + } + + protected async preHook(): Promise { + const metadata = await this.metadataRepo.get(this.cfg.id); + if (metadata) { + this.previousFrom = metadata.previousFrom; + this.lastFrom = metadata.lastFrom; + } + } + + protected async hasNext(): Promise { + const hasFinished = this.cfg.hasFinished(this.blockHeightCursor); + if (hasFinished) { + this.logger.info( + `[hasNext] PollSei: (${this.cfg.id}) Finished processing all blocks from ${this.cfg.fromBlock} to ${this.cfg.toBlock}` + ); + } + return !hasFinished; + } + + protected async get(): Promise { + const seiRedeems = await this.getSeiRedeems.execute({ + addresses: this.cfg.addresses, + previousFrom: this.previousFrom, + lastFrom: this.lastFrom, + chainId: this.cfg.chainId, + blockBatchSize: this.cfg.getBlockBatchSize(), + }); + + this.updateRange(); + return seiRedeems; + } + + private updateRange(): void { + // Update the previousFrom and lastFrom based on the executed range + const updatedRange = this.getSeiRedeems.getUpdatedRange(); + if (updatedRange) { + this.previousFrom = updatedRange.previousFrom; + this.lastFrom = updatedRange.lastFrom; + } + } + + protected async persist(): Promise { + if (this.lastFrom) { + await this.metadataRepo.save(this.cfg.id, { + previousFrom: this.previousFrom, + lastFrom: this.lastFrom, + }); + } + } + + protected report(): void { + const labels = { + job: this.cfg.id, + chain: "sei", + commitment: "latest", + }; + const lastFrom = this.lastFrom ?? 0n; + const previousFrom = this.previousFrom ?? 0n; + const diffCursor = BigInt(lastFrom) - BigInt(previousFrom); + + this.statsRepo.count("job_execution", labels); + + this.statsRepo.measure("polling_cursor", lastFrom, { + ...labels, + type: "max", + }); + + this.statsRepo.measure("polling_cursor", previousFrom, { + ...labels, + type: "current", + }); + + this.statsRepo.measure("polling_cursor", diffCursor, { + ...labels, + type: "diff", + }); + } +} + +export type PreviousRange = { + previousFrom: bigint | undefined; + lastFrom: bigint | undefined; +}; + +export type PollSeiMetadata = { + previousFrom?: bigint; + lastFrom?: bigint; +}; + +export interface PollSeiConfigProps { + blockBatchSize?: number; + fromBlock?: bigint; + addresses: string[]; + interval?: number; + toBlock?: bigint; + chainId: number; + chain: string; + id?: string; +} + +export type GetSeiOpts = { + addresses: string[]; + previousFrom?: bigint | undefined; + lastFrom?: bigint | undefined; + chainId: number; + blockBatchSize: number; +}; + +export class PollSeiConfig { + private props: PollSeiConfigProps; + + constructor(props: PollSeiConfigProps) { + if (props.fromBlock && props.toBlock && props.fromBlock > props.toBlock) { + throw new Error("fromBlock must be less than or equal to toBlock"); + } + + this.props = props; + } + public getBlockBatchSize() { + return this.props.blockBatchSize ?? 100; + } + + public hasFinished(currentFromBlock?: bigint): boolean { + return ( + currentFromBlock != undefined && + this.props.toBlock != undefined && + currentFromBlock >= this.props.toBlock + ); + } + + public get fromBlock() { + return this.props.fromBlock ? BigInt(this.props.fromBlock) : undefined; + } + + public setFromBlock(fromBlock: bigint | undefined) { + this.props.fromBlock = fromBlock; + } + + public get toBlock() { + return this.props.toBlock; + } + + public get interval() { + return this.props.interval; + } + + public get addresses() { + return this.props.addresses.map((address) => address.toLowerCase()); + } + + public get id() { + return this.props.id ?? ID; + } + + public get chain() { + return this.props.chain; + } + + public get chainId() { + return this.props.chainId; + } +} diff --git a/blockchain-watcher/src/domain/entities/sei.ts b/blockchain-watcher/src/domain/entities/sei.ts new file mode 100644 index 00000000..d4108cf6 --- /dev/null +++ b/blockchain-watcher/src/domain/entities/sei.ts @@ -0,0 +1,16 @@ +export type SeiRedeem = { + timestamp?: number; + chainId: number; + height: bigint; + hash: string; + data: string; + tx: Buffer; + events: { + type: string; + attributes: { + index: boolean; + value: string; + key: string; + }[]; + }[]; +}; diff --git a/blockchain-watcher/src/domain/repositories.ts b/blockchain-watcher/src/domain/repositories.ts index 7142b1e3..1a435f2f 100644 --- a/blockchain-watcher/src/domain/repositories.ts +++ b/blockchain-watcher/src/domain/repositories.ts @@ -21,6 +21,7 @@ import { Range, } from "./entities"; import { IbcTransaction, WormchainBlockLogs, CosmosRedeem } from "./entities/wormchain"; +import { SeiRedeem } from "./entities/sei"; export interface EvmBlockRepository { getBlockHeight(chain: string, finality: string): Promise; @@ -91,6 +92,11 @@ export interface WormchainRepository { getRedeems(ibcTransaction: IbcTransaction): Promise; } +export interface SeiRepository { + getRedeems(chainId: number, address: string, blockBatchSize: number): Promise; + getBlockTimestamp(blockNumber: bigint): Promise; +} + export interface MetadataRepository { get(id: string): Promise; save(id: string, metadata: Metadata): Promise; diff --git a/blockchain-watcher/src/infrastructure/mappers/sei/seiRedeemedTransactionFoundMapper.ts b/blockchain-watcher/src/infrastructure/mappers/sei/seiRedeemedTransactionFoundMapper.ts new file mode 100644 index 00000000..bb0d9296 --- /dev/null +++ b/blockchain-watcher/src/infrastructure/mappers/sei/seiRedeemedTransactionFoundMapper.ts @@ -0,0 +1,117 @@ +import { TransactionFoundEvent } from "../../../domain/entities"; +import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx"; +import { decodeTxRaw } from "@cosmjs/proto-signing"; +import { SeiRedeem } from "../../../domain/entities/sei"; +import { parseVaa } from "@certusone/wormhole-sdk"; +import { base64 } from "ethers/lib/utils"; +import winston from "winston"; + +const MSG_EXECUTE_CONTRACT_TYPE_URL = "/cosmwasm.wasm.v1.MsgExecuteContract"; +const SEI_CHAIN_ID = 32; +const PROTOCOL = "Token Bridge"; + +let logger: winston.Logger = winston.child({ module: "seiRedeemedTransactionFoundMapper" }); + +export const seiRedeemedTransactionFoundMapper = ( + addresses: string[], + transaction: SeiRedeem +): TransactionFoundEvent | undefined => { + const vaaInformation = mappedVaaInformation(transaction.tx); + if (!vaaInformation) { + return undefined; + } + const txAttributes = transactionAttributes(addresses, transaction); + if (!txAttributes) { + return undefined; + } + const hash = transaction.hash; + + const emitterAddress = vaaInformation.emitterAddress; + const emitterChain = vaaInformation.emitterChain; + const sequence = vaaInformation.sequence; + + logger.info( + `[sei] Redeemed transaction info: [hash: ${hash}][VAA: ${emitterChain}/${emitterAddress}/${sequence}]` + ); + + return { + name: "transfer-redeemed", + address: txAttributes.receiver, + chainId: SEI_CHAIN_ID, + txHash: hash, + blockHeight: BigInt(transaction.height), + blockTime: Math.floor(transaction.timestamp! / 1000), + attributes: { + emitterAddress: emitterAddress, + emitterChain: emitterChain, + sequence: sequence, + protocol: PROTOCOL, + status: TxStatus.Completed, + }, + }; +}; + +function mappedVaaInformation(tx: Buffer): VaaInformation | undefined { + const decodedTx = decodeTxRaw(tx); + const message = decodedTx.body.messages.find( + (tx) => tx.typeUrl === MSG_EXECUTE_CONTRACT_TYPE_URL + ); + + if (message) { + const parsedMessage = MsgExecuteContract.decode(message.value); + + const instruction = JSON.parse(Buffer.from(parsedMessage.msg).toString()); + const base64Vaa = instruction?.complete_transfer_and_convert?.vaa; + + if (base64Vaa) { + const vaa = parseVaa(base64.decode(base64Vaa)); + + return { + emitterAddress: vaa.emitterAddress.toString("hex"), + emitterChain: vaa.emitterChain, + sequence: Number(vaa.sequence), + }; + } + } +} + +function transactionAttributes( + addresses: string[], + tx: SeiRedeem +): TransactionAttributes | undefined { + let receiver: string | undefined; + + for (const event of tx.events) { + for (const attr of event.attributes) { + const key = Buffer.from(attr.key, "base64").toString().toLowerCase(); + const value = Buffer.from(attr.value, "base64").toString().toLowerCase(); + + switch (key) { + case "_contract_address": + case "contract_address": + if (addresses.includes(value.toLowerCase())) { + receiver = value.toLowerCase(); + } + break; + } + } + } + if (receiver) { + return { receiver }; + } +} + +type VaaInformation = { + emitterChain?: number; + emitterAddress?: string; + sequence?: number; +}; + +enum TxStatus { + Completed = "completed", + Failed = "failed", +} + +type TransactionAttributes = { + receiver: string; +}; diff --git a/blockchain-watcher/src/infrastructure/mappers/wormchain/wormchainRedeemedTransactionFoundMapper.ts b/blockchain-watcher/src/infrastructure/mappers/wormchain/wormchainRedeemedTransactionFoundMapper.ts index fa05eefb..e8fdedea 100644 --- a/blockchain-watcher/src/infrastructure/mappers/wormchain/wormchainRedeemedTransactionFoundMapper.ts +++ b/blockchain-watcher/src/infrastructure/mappers/wormchain/wormchainRedeemedTransactionFoundMapper.ts @@ -38,7 +38,7 @@ export const wormchainRedeemedTransactionFoundMapper = ( name: "transfer-redeemed", address: sender, chainId: chainId, - txHash: `0x${hash}`, + txHash: hash, blockHeight: BigInt(cosmosRedeem.height), blockTime: Math.floor(Number(cosmosRedeem.blockTimestamp) / 1000), attributes: { diff --git a/blockchain-watcher/src/infrastructure/repositories/RepositoriesBuilder.ts b/blockchain-watcher/src/infrastructure/repositories/RepositoriesBuilder.ts index 4e908123..50a1f750 100644 --- a/blockchain-watcher/src/infrastructure/repositories/RepositoriesBuilder.ts +++ b/blockchain-watcher/src/infrastructure/repositories/RepositoriesBuilder.ts @@ -1,10 +1,12 @@ import { RateLimitedWormchainJsonRPCBlockRepository } from "./wormchain/RateLimitedWormchainJsonRPCBlockRepository"; import { RateLimitedAptosJsonRPCBlockRepository } from "./aptos/RateLimitedAptosJsonRPCBlockRepository"; import { RateLimitedEvmJsonRPCBlockRepository } from "./evm/RateLimitedEvmJsonRPCBlockRepository"; +import { RateLimitedSeiJsonRPCBlockRepository } from "./sei/RateLimitedSeiJsonRPCBlockRepository"; import { RateLimitedSuiJsonRPCBlockRepository } from "./sui/RateLimitedSuiJsonRPCBlockRepository"; import { WormchainJsonRPCBlockRepository } from "./wormchain/WormchainJsonRPCBlockRepository"; import { AptosJsonRPCBlockRepository } from "./aptos/AptosJsonRPCBlockRepository"; import { SNSClient, SNSClientConfig } from "@aws-sdk/client-sns"; +import { SeiJsonRPCBlockRepository } from "./sei/SeiJsonRPCBlockRepository"; import { InstrumentedHttpProvider } from "../rpc/http/InstrumentedHttpProvider"; import { Config } from "../config"; import { @@ -12,6 +14,7 @@ import { AptosRepository, JobRepository, SuiRepository, + SeiRepository, } from "../../domain/repositories"; import { InstrumentedConnection, @@ -42,6 +45,7 @@ const SOLANA_CHAIN = "solana"; const APTOS_CHAIN = "aptos"; const EVM_CHAIN = "evm"; const SUI_CHAIN = "sui"; +const SEI_CHAIN = "sei"; const EVM_CHAINS = new Map([ ["ethereum", "evmRepo"], ["ethereum-sepolia", "evmRepo"], @@ -96,6 +100,7 @@ export class RepositoriesBuilder { this.buildAptosRepository(chain); this.buildEvmRepository(chain); this.buildSuiRepository(chain); + this.buildSeiRepository(chain); }); this.repositories.set( @@ -113,6 +118,7 @@ export class RepositoriesBuilder { suiRepo: this.getSuiRepository(), aptosRepo: this.getAptosRepository(), wormchainRepo: this.getWormchainRepository(), + seiRepo: this.getSeiRepository(), } ) ); @@ -157,6 +163,10 @@ export class RepositoriesBuilder { return this.getRepo("wormchain-repo"); } + public getSeiRepository(): SeiRepository { + return this.getRepo("sei-repo"); + } + public close(): void { this.snsClient?.destroy(); } @@ -241,6 +251,18 @@ export class RepositoriesBuilder { } } + private buildSeiRepository(chain: string): void { + if (chain == SEI_CHAIN) { + const pools = this.createDefaultProviderPools(chain); + + const seiRepository = new RateLimitedSeiJsonRPCBlockRepository( + new SeiJsonRPCBlockRepository(pools) + ); + + this.repositories.set("sei-repo", seiRepository); + } + } + private buildWormchainRepository(chain: string): void { if (chain == WORMCHAIN_CHAIN) { const injectivePools = this.createDefaultProviderPools("injective"); diff --git a/blockchain-watcher/src/infrastructure/repositories/StaticJobRepository.ts b/blockchain-watcher/src/infrastructure/repositories/StaticJobRepository.ts index a8b11639..d5a695d1 100644 --- a/blockchain-watcher/src/infrastructure/repositories/StaticJobRepository.ts +++ b/blockchain-watcher/src/infrastructure/repositories/StaticJobRepository.ts @@ -1,8 +1,10 @@ +import { PollSei, PollSeiConfig, PollSeiConfigProps } from "../../domain/actions/sei/PollSei"; import { FileMetadataRepository, SnsEventRepository } from "./index"; import { wormchainRedeemedTransactionFoundMapper } from "../mappers/wormchain/wormchainRedeemedTransactionFoundMapper"; import { JobDefinition, Handler, LogFoundEvent } from "../../domain/entities"; import { aptosRedeemedTransactionFoundMapper } from "../mappers/aptos/aptosRedeemedTransactionFoundMapper"; import { wormchainLogMessagePublishedMapper } from "../mappers/wormchain/wormchainLogMessagePublishedMapper"; +import { seiRedeemedTransactionFoundMapper } from "../mappers/sei/seiRedeemedTransactionFoundMapper"; import { suiRedeemedTransactionFoundMapper } from "../mappers/sui/suiRedeemedTransactionFoundMapper"; import { aptosLogMessagePublishedMapper } from "../mappers/aptos/aptosLogMessagePublishedMapper"; import { suiLogMessagePublishedMapper } from "../mappers/sui/suiLogMessagePublishedMapper"; @@ -12,6 +14,7 @@ import { HandleWormchainRedeems } from "../../domain/actions/wormchain/HandleWor import { HandleEvmTransactions } from "../../domain/actions/evm/HandleEvmTransactions"; import { HandleSuiTransactions } from "../../domain/actions/sui/HandleSuiTransactions"; import { HandleWormchainLogs } from "../../domain/actions/wormchain/HandleWormchainLogs"; +import { HandleSeiRedeems } from "../../domain/actions/sei/HandleSeiRedeems"; import log from "../log"; import { PollWormchainLogsConfigProps, @@ -27,6 +30,7 @@ import { StatRepository, JobRepository, SuiRepository, + SeiRepository, } from "../../domain/repositories"; import { PollSolanaTransactionsConfig, @@ -70,6 +74,7 @@ export class StaticJobRepository implements JobRepository { private suiRepo: SuiRepository; private aptosRepo: AptosRepository; private wormchainRepo: WormchainRepository; + private seiRepo: SeiRepository; constructor( environment: string, @@ -84,6 +89,7 @@ export class StaticJobRepository implements JobRepository { suiRepo: SuiRepository; aptosRepo: AptosRepository; wormchainRepo: WormchainRepository; + seiRepo: SeiRepository; } ) { this.fileRepo = new FileMetadataRepository(path); @@ -95,6 +101,7 @@ export class StaticJobRepository implements JobRepository { this.suiRepo = repos.suiRepo; this.aptosRepo = repos.aptosRepo; this.wormchainRepo = repos.wormchainRepo; + this.seiRepo = repos.seiRepo; this.environment = environment; this.dryRun = dryRun; this.fill(); @@ -201,11 +208,23 @@ export class StaticJobRepository implements JobRepository { jobDef.source.records ); + const pollSei = (jobDef: JobDefinition) => + new PollSei( + this.seiRepo, + this.metadataRepo, + this.statsRepo, + new PollSeiConfig({ + ...(jobDef.source.config as PollSeiConfigProps), + id: jobDef.id, + }) + ); + this.sources.set("PollEvm", pollEvm); this.sources.set("PollSolanaTransactions", pollSolanaTransactions); this.sources.set("PollSuiTransactions", pollSuiTransactions); this.sources.set("PollAptos", pollAptos); this.sources.set("PollWormchain", pollWormchain); + this.sources.set("PollSei", pollSei); } private loadMappers(): void { @@ -218,6 +237,7 @@ export class StaticJobRepository implements JobRepository { this.mappers.set("aptosLogMessagePublishedMapper", aptosLogMessagePublishedMapper); this.mappers.set("aptosRedeemedTransactionFoundMapper", aptosRedeemedTransactionFoundMapper); this.mappers.set("wormchainLogMessagePublishedMapper", wormchainLogMessagePublishedMapper); + this.mappers.set("seiRedeemedTransactionFoundMapper", seiRedeemedTransactionFoundMapper); this.mappers.set( "wormchainRedeemedTransactionFoundMapper", wormchainRedeemedTransactionFoundMapper @@ -301,6 +321,16 @@ export class StaticJobRepository implements JobRepository { return instance.handle.bind(instance); }; + const handleSeiRedeems = async (config: any, target: string, mapper: any) => { + const instance = new HandleSeiRedeems( + config, + mapper, + await this.getTarget(target), + this.statsRepo + ); + return instance.handle.bind(instance); + }; + this.handlers.set("HandleEvmLogs", handleEvmLogs); this.handlers.set("HandleEvmTransactions", handleEvmTransactions); this.handlers.set("HandleSolanaTransactions", handleSolanaTx); @@ -308,6 +338,7 @@ export class StaticJobRepository implements JobRepository { this.handlers.set("HandleAptosTransactions", handleAptosTx); this.handlers.set("HandleWormchainLogs", handleWormchainLogs); this.handlers.set("HandleWormchainRedeems", handleWormchainRedeems); + this.handlers.set("HandleSeiRedeems", handleSeiRedeems); } private async getTarget(target: string): Promise<(items: any[]) => Promise> { diff --git a/blockchain-watcher/src/infrastructure/repositories/sei/RateLimitedSeiJsonRPCBlockRepository.ts b/blockchain-watcher/src/infrastructure/repositories/sei/RateLimitedSeiJsonRPCBlockRepository.ts new file mode 100644 index 00000000..2bd8228c --- /dev/null +++ b/blockchain-watcher/src/infrastructure/repositories/sei/RateLimitedSeiJsonRPCBlockRepository.ts @@ -0,0 +1,25 @@ +import { RateLimitedRPCRepository } from "../RateLimitedRPCRepository"; +import { SeiRepository } from "../../../domain/repositories"; +import { SeiRedeem } from "../../../domain/entities/sei"; +import { Options } from "../common/rateLimitedOptions"; +import winston from "winston"; + +export class RateLimitedSeiJsonRPCBlockRepository + extends RateLimitedRPCRepository + implements SeiRepository +{ + constructor(delegate: SeiRepository, opts: Options = { period: 10_000, limit: 1000 }) { + super(delegate, opts); + this.logger = winston.child({ module: "RateLimitedSeiJsonRPCBlockRepository" }); + } + + getBlockTimestamp(blockNumber: bigint): Promise { + return this.breaker.fn(() => this.delegate.getBlockTimestamp(blockNumber)).execute(); + } + + getRedeems(chainId: number, address: string, blockBatchSize: number): Promise { + return this.breaker + .fn(() => this.delegate.getRedeems(chainId, address, blockBatchSize)) + .execute(); + } +} diff --git a/blockchain-watcher/src/infrastructure/repositories/sei/SeiJsonRPCBlockRepository.ts b/blockchain-watcher/src/infrastructure/repositories/sei/SeiJsonRPCBlockRepository.ts new file mode 100644 index 00000000..33893d2b --- /dev/null +++ b/blockchain-watcher/src/infrastructure/repositories/sei/SeiJsonRPCBlockRepository.ts @@ -0,0 +1,217 @@ +import { InstrumentedHttpProvider } from "../../rpc/http/InstrumentedHttpProvider"; +import { SeiRepository } from "../../../domain/repositories"; +import { ProviderPool } from "@xlabs/rpc-pool"; +import { SeiRedeem } from "../../../domain/entities/sei"; +import winston from "winston"; + +const TRANSACTION_SEARCH_ENDPOINT = "/tx_search"; +const BLOCK_ENDPOINT = "/block"; +const ACTION = "complete_transfer_with_payload"; + +type ProviderPoolMap = ProviderPool; + +export class SeiJsonRPCBlockRepository implements SeiRepository { + private readonly logger: winston.Logger; + protected pool: ProviderPoolMap; + + constructor(pool: ProviderPool) { + this.logger = winston.child({ module: "SeiJsonRPCBlockRepository" }); + this.pool = pool; + } + + async getRedeems(chainId: number, address: string, blockBatchSize: number): Promise { + try { + let resultTransactionSearch: ResultTransactionSearch; + const query = `wasm._contract_address='${address}' AND wasm.action='${ACTION}'`; + + const perPageLimit = 20; + const seiRedeems = []; + let continuesFetching = true; + let page = 1; + + while (continuesFetching) { + try { + resultTransactionSearch = await this.pool + .get() + .get( + `${TRANSACTION_SEARCH_ENDPOINT}?query=${query}&page=${page}&per_page=${perPageLimit}` + ); + + if (resultTransactionSearch?.txs) { + seiRedeems.push(...resultTransactionSearch.txs); + } + + if (Number(resultTransactionSearch.total_count) >= blockBatchSize) { + continuesFetching = false; + } + page++; + } catch (e) { + this.handleError( + `[sei] Get transaction error: ${e} with query \n${query}\n`, + "getRedeems" + ); + continuesFetching = false; + } + } + + if (!seiRedeems) { + this.logger.warn(`[getRedeems] Do not find any transaction with query \n${query}\n`); + return []; + } + + const sortedSeiRedeems = seiRedeems.sort((a, b) => Number(a.height) - Number(b.height)); + return sortedSeiRedeems.map((tx) => { + return { + chainId: chainId, + events: tx.tx_result.events, + height: BigInt(tx.height), + data: tx.tx_result.data, + hash: tx.hash, + tx: Buffer.from(tx.tx, "base64"), + }; + }); + } catch (e) { + this.handleError(`Error: ${e}`, "getRedeems"); + throw e; + } + } + + async getBlockTimestamp(blockNumber: bigint): Promise { + try { + const blockEndpoint = `${BLOCK_ENDPOINT}?height=${blockNumber}`; + let resultsBlock: ResultBlock; + + resultsBlock = await this.pool.get().get(blockEndpoint); + + if ( + !resultsBlock || + !resultsBlock.block || + !resultsBlock.block.header || + !resultsBlock.block.header.time + ) { + return undefined; + } + + const dateTime: Date = new Date(resultsBlock.block.header.time); + const timestamp: number = dateTime.getTime(); + + return timestamp; + } catch (e) { + this.handleError(`Error: ${e}`, "getBlockTimestamp"); + throw e; + } + } + + private handleError(e: any, method: string) { + this.logger.error(`[sei] Error calling ${method}: ${e.message ?? e}`); + } +} + +type ResultTransactionSearch = { + total_count: string; + txs: [ + { + height: string; + hash: string; + tx_result: { + height: string; + txhash: string; + codespace: string; + code: 0; + data: string; + raw_log: string; + logs: [{ msg_index: number; log: string; events: EventsType }]; + info: string; + gas_wanted: string; + gas_used: string; + tx: { + "@type": "/cosmos.tx.v1beta1.Tx"; + body: { + messages: [ + { + "@type": "/cosmos.staking.v1beta1.MsgBeginRedelegate"; + delegator_address: string; + validator_src_address: string; + validator_dst_address: string; + amount: { denom: string; amount: string }; + } + ]; + memo: ""; + timeout_height: "0"; + extension_options: []; + non_critical_extension_options: []; + }; + auth_info: { + signer_infos: [ + { + public_key: { + "@type": "/cosmos.crypto.secp256k1.PubKey"; + key: string; + }; + mode_info: { single: { mode: string } }; + sequence: string; + } + ]; + fee: { + amount: [{ denom: string; amount: string }]; + gas_limit: string; + payer: string; + granter: string; + }; + }; + signatures: string[]; + }; + timestamp: string; // eg. '2023-01-03T12:12:54Z' + events: EventsType[]; + }; + tx: string; + } + ]; +}; + +type EventsType = { + type: string; + attributes: [ + { + key: string; + value: string; + index: boolean; + } + ]; +}; + +type ResultBlock = { + block_id: { + hash: string; + parts: { + total: number; + hash: string; + }; + }; + block: { + header: { + version: { block: string }; + chain_id: string; + height: string; + time: string; // eg. '2023-01-03T12:13:00.849094631Z' + last_block_id: { hash: string; parts: { total: number; hash: string } }; + last_commit_hash: string; + data_hash: string; + validators_hash: string; + next_validators_hash: string; + consensus_hash: string; + app_hash: string; + last_results_hash: string; + evidence_hash: string; + proposer_address: string; + }; + data: { txs: string[] | null }; + evidence: { evidence: null }; + last_commit: { + height: string; + round: number; + block_id: { hash: string; parts: { total: number; hash: string } }; + signatures: string[]; + }; + }; +}; diff --git a/blockchain-watcher/test/domain/actions/sei/GetSeiRedeems.test.ts b/blockchain-watcher/test/domain/actions/sei/GetSeiRedeems.test.ts new file mode 100644 index 00000000..905a3bf4 --- /dev/null +++ b/blockchain-watcher/test/domain/actions/sei/GetSeiRedeems.test.ts @@ -0,0 +1,591 @@ +import { afterEach, describe, it, expect, jest } from "@jest/globals"; +import { thenWaitForAssertion } from "../../../wait-assertion"; +import { SeiRedeem } from "../../../../src/domain/entities/sei"; +import { + PollSeiMetadata, + PollSeiConfig, + PollSei, +} from "../../../../src/domain/actions/sei/PollSei"; +import { + MetadataRepository, + SeiRepository, + StatRepository, +} from "../../../../src/domain/repositories"; + +let getBlockTimestampSpy: jest.SpiedFunction; +let metadataSaveSpy: jest.SpiedFunction["save"]>; +let getRedeemsSpy: jest.SpiedFunction; +let handlerSpy: jest.SpiedFunction<(txs: SeiRedeem[]) => Promise>; +let metadataRepo: MetadataRepository; +let seiRepo: SeiRepository; +let statsRepo: StatRepository; + +let handlers = { + working: (txs: SeiRedeem[]) => Promise.resolve(), + failing: (txs: SeiRedeem[]) => Promise.reject(), +}; + +let pollSei: PollSei; + +let props = { + blockBatchSize: 20, + environment: "testnet", + commitment: "latest", + addresses: ["sei1smzlm9t79kur392nu9egl8p8je9j92q4gzguewj56a05kyxxra0qy0nuf3"], + interval: 5000, + topics: [], + chainId: 32, + filter: { + address: "sei1smzlm9t79kur392nu9egl8p8je9j92q4gzguewj56a05kyxxra0qy0nuf3", + }, + chain: "sei", + id: "poll-redeemed-transactions-sei", +}; + +let cfg = new PollSeiConfig(props); + +describe("GetSeiRedeems", () => { + afterEach(async () => { + await pollSei.stop(); + }); + + it("should be skip the transations blocks, because the transactions will be empty", async () => { + // Given + givenSeiBlockRepository(8418529, []); + givenMetadataRepository({ lastFrom: 8418528n }); + givenStatsRepository(); + givenPollSeinTx(cfg); + + // When + await whenPollSeiStarts(); + + // Then + await thenWaitForAssertion(() => + expect(getRedeemsSpy).toBeCalledWith( + 32, + "sei1smzlm9t79kur392nu9egl8p8je9j92q4gzguewj56a05kyxxra0qy0nuf3", + 20 + ) + ); + }); + + it("should be process the txs from sei blockchain and send to mapper method", async () => { + // Given + const txs = [ + { + chainId: 32, + events: [ + { + type: "coin_spent", + attributes: [ + { + key: "c3BlbmRlcg==", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3pl", + index: true, + }, + { key: "YW1vdW50", value: "NjcyODZ1c2Vp", index: true }, + ], + }, + { + type: "tx", + attributes: [ + { key: "ZmVl", value: "NjcyODZ1c2Vp", index: true }, + { + key: "ZmVlX3BheWVy", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3pl", + index: true, + }, + ], + }, + { + type: "tx", + attributes: [ + { + key: "YWNjX3NlcQ==", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3plLzM2NjU=", + index: true, + }, + ], + }, + { + type: "tx", + attributes: [ + { + key: "c2lnbmF0dXJl", + value: + "eWROMjlWM1lhWHNjUUlidUNDcUR5UFBGYjZvWWtJMVVvc2Z5SVBMTVhMa09La1ZSZWdZNTYzb3lwVzFzSTdZUXZCdkxKV1pzQlNtQmFKdGZvRjh2cVE9PQ==", + index: true, + }, + ], + }, + { + type: "signer", + attributes: [ + { + key: "ZXZtX2FkZHI=", + value: "MHgzNUM4NEUzN2RkOTM2OTFFQzZFZUY1MTdmODc1MGI3NjVlMjQ5OTkz", + index: true, + }, + { + key: "c2VpX2FkZHI=", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3pl", + index: true, + }, + ], + }, + { + type: "message", + attributes: [ + { + key: "YWN0aW9u", + value: "L2Nvc213YXNtLndhc20udjEuTXNnRXhlY3V0ZUNvbnRyYWN0", + index: true, + }, + ], + }, + { + type: "message", + attributes: [ + { key: "bW9kdWxl", value: "d2FzbQ==", index: true }, + { + key: "c2VuZGVy", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3pl", + index: true, + }, + ], + }, + { + type: "execute", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + ], + }, + { + type: "wasm", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { key: "YWN0aW9u", value: "Y29tcGxldGVfdHJhbnNmZXJfd2l0aF9wYXlsb2Fk", index: true }, + { + key: "dHJhbnNmZXJfcGF5bG9hZA==", + value: + "ZXlKaVlYTnBZMTl5WldOcGNHbGxiblFpT25zaWNtVmphWEJwWlc1MElqb2lZekpXY0UxWFkzcE9hbWd4V1ZSc2VHVlhkSGxhUjA1M1lVZFdjbGxVV1RCYVYwWjVUa2QzTTAweVJqWk9XR2hzV25wTmQwMHpjR3dpZlgwPQ==", + index: true, + }, + ], + }, + { + type: "execute", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMXNtemxtOXQ3OWt1cjM5Mm51OWVnbDhwOGplOWo5MnE0Z3pndWV3ajU2YTA1a3l4eHJhMHF5MG51ZjM=", + index: true, + }, + ], + }, + { + type: "wasm", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMXNtemxtOXQ3OWt1cjM5Mm51OWVnbDhwOGplOWo5MnE0Z3pndWV3ajU2YTA1a3l4eHJhMHF5MG51ZjM=", + index: true, + }, + { key: "YWN0aW9u", value: "Y29tcGxldGVfdHJhbnNmZXJfd3JhcHBlZA==", index: true }, + { + key: "Y29udHJhY3Q=", + value: + "c2VpMWxnOTV2enFrMzUzbXM5YXBwem5oZDZyMzM2c3NjcXJjNTA3NDM5bjc0d3I3cmZkdno3ZHFxYTlzbGw=", + index: true, + }, + { + key: "cmVjaXBpZW50", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { key: "YW1vdW50", value: "NTEyOTcwODY=", index: true }, + { + key: "cmVsYXllcg==", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3pl", + index: true, + }, + { key: "ZmVl", value: "MA==", index: true }, + ], + }, + { + type: "execute", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMWxnOTV2enFrMzUzbXM5YXBwem5oZDZyMzM2c3NjcXJjNTA3NDM5bjc0d3I3cmZkdno3ZHFxYTlzbGw=", + index: true, + }, + ], + }, + { + type: "wasm", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMWxnOTV2enFrMzUzbXM5YXBwem5oZDZyMzM2c3NjcXJjNTA3NDM5bjc0d3I3cmZkdno3ZHFxYTlzbGw=", + index: true, + }, + { key: "YWN0aW9u", value: "bWludA==", index: true }, + { + key: "dG8=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { key: "YW1vdW50", value: "NTEyOTcwODY=", index: true }, + ], + }, + { + type: "reply", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + ], + }, + { + type: "coin_received", + attributes: [ + { + key: "cmVjZWl2ZXI=", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "coinbase", + attributes: [ + { + key: "bWludGVy", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "coin_spent", + attributes: [ + { + key: "c3BlbmRlcg==", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "coin_received", + attributes: [ + { + key: "cmVjZWl2ZXI=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "transfer", + attributes: [ + { + key: "cmVjaXBpZW50", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "c2VuZGVy", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "mint", + attributes: [ + { + key: "bWludF90b19hZGRyZXNz", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "coin_spent", + attributes: [ + { + key: "c3BlbmRlcg==", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "coin_received", + attributes: [ + { + key: "cmVjZWl2ZXI=", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3pl", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "transfer", + attributes: [ + { + key: "cmVjaXBpZW50", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3pl", + index: true, + }, + { + key: "c2VuZGVy", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + ], + height: "80542798", + data: "CiYKJC9jb3Ntd2FzbS53YXNtLnYxLk1zZ0V4ZWN1dGVDb250cmFjdA==", + hash: "C94451E3FCDC064E9E7FCAB6FBBFADD9C909910817BB185FF651580A72B3034B", + tx: { + type: Buffer.from([ + 10, 230, 13, 10, 180, 13, 10, 36, 47, 99, 111, 115, 109, 119, 97, 115, 109, 46, 119, 97, + 115, 109, 46, 118, 49, 46, 77, 115, 103, 69, 120, 101, 99, 117, 116, 101, 67, 111, 110, + 116, 114, 97, 99, 116, 18, 139, 13, 10, 42, 115, 101, 105, 49, 113, 51, 114, 50, 118, + 57, 106, 55, 112, 102, 48, 114, 109, 106, 56, 52, 54, 104, 51, 108, 97, 107, 107, 56, + 53, 114, 118, 54, 114, 50, 53, 116, 108, 112, 103, 53, 57, 122, 18, 62, 115, 101, 105, + 49, 56, 57, 97, 100, 103, 117, 97, 119, 117, 103, 107, 51, 101, 53, 53, 122, 110, 54, + 51, 122, 56, 114, 57, 108, 108, 50, 57, 120, 114, 106, 119, 99, 97, 54, 51, 54, 114, 97, + 55, 118, 55, 103, 120, 117, 122, 110, 57, 56, 115, 120, 121, 113, 119, 122, 116, 52, 55, + 108, 26, 156, 12, 123, 34, 99, 111, 109, 112, 108, 101, 116, 101, 95, 116, 114, 97, 110, + 115, 102, 101, 114, 95, 97, 110, 100, 95, 99, 111, 110, 118, 101, 114, 116, 34, 58, 123, + 34, 118, 97, 97, 34, 58, 34, 65, 81, 65, 65, 65, 65, 81, 78, 65, 80, 115, 111, 57, 97, + 73, 43, 99, 65, 48, 100, 56, 70, 114, 74, 98, 74, 71, 101, 97, 71, 70, 68, 113, 104, 49, + 98, 81, 98, 87, 75, 79, 102, 68, 77, 70, 105, 111, 102, 69, 76, 102, 111, 79, 103, 106, + 102, 73, 118, 111, 87, 89, 83, 104, 55, 110, 53, 43, 48, 88, 82, 74, 68, 84, 43, 113, + 48, 102, 120, 121, 90, 66, 101, 115, 68, 73, 71, 85, 106, 50, 52, 80, 114, 107, 88, 73, + 65, 65, 85, 113, 121, 87, 122, 52, 110, 54, 104, 112, 77, 89, 75, 85, 122, 97, 103, 53, + 49, 56, 120, 121, 99, 66, 86, 76, 69, 50, 48, 51, 47, 88, 74, 85, 56, 65, 75, 70, 76, + 101, 118, 120, 101, 76, 71, 98, 55, 72, 48, 43, 113, 54, 53, 73, 105, 112, 53, 118, 56, + 109, 116, 70, 78, 78, 71, 88, 116, 104, 104, 119, 49, 81, 113, 83, 99, 114, 122, 119, + 121, 77, 84, 67, 107, 79, 85, 56, 65, 66, 74, 99, 106, 82, 78, 87, 70, 109, 105, 100, + 112, 88, 84, 51, 75, 118, 55, 68, 79, 103, 78, 120, 81, 57, 75, 50, 84, 78, 97, 106, 86, + 121, 97, 111, 118, 81, 51, 120, 78, 71, 86, 80, 82, 80, 86, 74, 117, 110, 68, 118, 71, + 47, 89, 68, 90, 112, 106, 102, 110, 66, 78, 67, 111, 99, 52, 106, 80, 102, 55, 79, 90, + 52, 111, 119, 83, 102, 74, 65, 76, 111, 119, 113, 43, 73, 70, 89, 65, 66, 113, 87, 67, + 87, 65, 72, 67, 76, 82, 83, 122, 107, 65, 116, 112, 106, 106, 82, 98, 73, 47, 56, 97, + 110, 117, 97, 74, 85, 89, 114, 52, 47, 119, 66, 98, 72, 107, 98, 71, 109, 89, 113, 87, + 86, 53, 119, 117, 67, 104, 121, 49, 84, 105, 80, 103, 102, 118, 73, 118, 76, 66, 78, + 106, 71, 80, 99, 88, 65, 84, 49, 65, 48, 108, 111, 97, 79, 55, 110, 78, 52, 47, 116, 52, + 53, 83, 111, 66, 66, 55, 55, 99, 88, 113, 99, 117, 106, 49, 109, 118, 67, 121, 99, 100, + 121, 70, 65, 108, 80, 75, 69, 69, 78, 56, 55, 101, 101, 52, 50, 109, 112, 109, 50, 56, + 97, 98, 84, 80, 72, 72, 86, 83, 66, 100, 82, 80, 52, 77, 112, 57, 104, 111, 114, 53, 86, + 121, 120, 87, 121, 66, 47, 73, 48, 76, 84, 68, 88, 54, 82, 49, 71, 55, 102, 122, 77, 57, + 52, 71, 116, 70, 48, 121, 104, 73, 69, 65, 67, 69, 50, 102, 75, 86, 118, 118, 104, 117, + 66, 49, 118, 103, 84, 119, 86, 55, 82, 71, 78, 109, 114, 121, 76, 75, 89, 105, 52, 110, + 74, 103, 65, 119, 87, 116, 56, 71, 88, 113, 51, 55, 65, 43, 87, 99, 79, 117, 101, 102, + 101, 70, 53, 53, 75, 114, 90, 86, 101, 118, 71, 101, 99, 80, 115, 74, 114, 74, 72, 110, + 90, 71, 114, 86, 99, 54, 122, 86, 75, 110, 43, 105, 50, 118, 73, 43, 89, 65, 67, 98, 48, + 88, 108, 100, 51, 67, 84, 49, 65, 81, 83, 55, 51, 109, 101, 52, 79, 80, 119, 109, 72, + 113, 52, 119, 76, 75, 71, 114, 77, 52, 115, 89, 76, 78, 48, 87, 111, 70, 85, 49, 53, 51, + 86, 103, 112, 90, 53, 110, 113, 110, 88, 112, 117, 122, 122, 70, 71, 84, 90, 57, 88, 66, + 116, 113, 51, 81, 111, 53, 102, 52, 116, 119, 108, 116, 71, 57, 72, 104, 90, 101, 121, + 47, 103, 80, 81, 66, 67, 110, 102, 112, 66, 99, 83, 100, 107, 75, 69, 83, 50, 74, 80, + 105, 109, 77, 107, 110, 84, 43, 112, 116, 68, 113, 50, 117, 68, 100, 88, 50, 120, 77, + 117, 114, 56, 85, 119, 83, 71, 50, 111, 82, 81, 122, 110, 77, 77, 98, 81, 122, 114, 53, + 115, 111, 53, 82, 72, 113, 71, 55, 48, 43, 74, 80, 89, 72, 104, 47, 105, 108, 101, 79, + 49, 86, 54, 75, 107, 75, 52, 69, 65, 57, 120, 120, 99, 65, 68, 88, 70, 88, 70, 77, 104, + 111, 69, 108, 116, 90, 86, 76, 47, 78, 108, 66, 97, 49, 115, 69, 50, 74, 117, 75, 120, + 67, 70, 81, 55, 56, 88, 54, 55, 81, 107, 87, 119, 119, 53, 108, 102, 69, 88, 111, 65, + 119, 47, 98, 118, 110, 117, 47, 115, 77, 74, 48, 99, 43, 86, 71, 84, 113, 83, 49, 99, + 89, 77, 69, 55, 98, 112, 111, 51, 56, 107, 51, 67, 52, 79, 115, 53, 114, 117, 117, 89, + 66, 68, 107, 76, 82, 90, 89, 52, 116, 85, 99, 120, 118, 75, 43, 106, 104, 65, 47, 51, + 87, 86, 87, 110, 109, 106, 103, 107, 98, 108, 68, 97, 112, 74, 109, 81, 50, 65, 69, 57, + 88, 56, 100, 90, 88, 84, 90, 50, 103, 111, 49, 54, 110, 71, 89, 76, 80, 97, 100, 43, + 122, 43, 90, 74, 53, 107, 50, 57, 72, 51, 102, 117, 69, 86, 71, 110, 99, 66, 87, 47, 65, + 117, 69, 78, 98, 109, 114, 115, 66, 68, 43, 99, 78, 109, 70, 97, 43, 49, 80, 87, 71, 51, + 97, 105, 77, 102, 110, 105, 107, 101, 111, 98, 111, 78, 122, 79, 102, 70, 102, 113, 43, + 111, 76, 114, 118, 75, 72, 55, 116, 103, 114, 51, 105, 68, 69, 119, 87, 69, 99, 101, + 119, 83, 98, 55, 112, 79, 105, 111, 121, 88, 50, 69, 108, 54, 78, 52, 114, 118, 85, 113, + 112, 102, 82, 66, 84, 105, 103, 56, 109, 118, 86, 84, 99, 105, 84, 77, 65, 69, 74, 90, + 56, 115, 110, 90, 121, 113, 111, 122, 53, 83, 56, 85, 79, 76, 116, 67, 121, 111, 102, + 57, 100, 101, 83, 89, 72, 51, 48, 111, 105, 81, 98, 68, 84, 111, 90, 75, 97, 72, 114, + 83, 80, 70, 81, 55, 105, 47, 78, 107, 52, 122, 103, 98, 54, 50, 113, 104, 43, 120, 98, + 108, 88, 112, 87, 102, 52, 75, 112, 68, 68, 105, 87, 43, 53, 117, 54, 72, 88, 66, 89, + 51, 88, 74, 47, 115, 65, 69, 106, 115, 102, 75, 79, 113, 55, 68, 103, 109, 89, 116, 118, + 73, 120, 68, 100, 56, 66, 50, 98, 57, 122, 49, 116, 89, 68, 57, 122, 102, 100, 70, 49, + 98, 107, 52, 85, 112, 71, 86, 119, 83, 122, 70, 111, 80, 54, 55, 57, 81, 43, 103, 84, + 75, 43, 120, 67, 49, 55, 57, 51, 118, 80, 78, 65, 86, 116, 109, 76, 113, 81, 98, 84, 84, + 54, 54, 115, 79, 81, 75, 111, 79, 102, 112, 99, 107, 66, 90, 108, 86, 121, 116, 81, 65, + 65, 103, 74, 115, 65, 65, 101, 120, 122, 99, 112, 108, 100, 88, 77, 104, 122, 73, 53, + 102, 55, 67, 116, 78, 99, 65, 83, 72, 103, 54, 113, 107, 78, 74, 118, 103, 111, 112, 84, + 84, 75, 116, 85, 79, 82, 115, 54, 84, 49, 65, 65, 65, 65, 65, 65, 65, 78, 99, 109, 81, + 103, 65, 119, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 79, 53, 114, + 75, 65, 120, 118, 112, 54, 56, 55, 55, 98, 114, 84, 111, 57, 90, 102, 78, 113, 113, 56, + 108, 48, 77, 98, 71, 55, 53, 77, 76, 83, 57, 117, 68, 107, 102, 75, 89, 67, 65, 48, 85, + 118, 88, 87, 69, 65, 65, 84, 108, 54, 49, 72, 79, 117, 52, 105, 48, 99, 48, 111, 75, + 101, 111, 105, 79, 77, 118, 47, 113, 75, 89, 99, 110, 89, 55, 113, 79, 104, 57, 56, 122, + 121, 68, 99, 70, 77, 112, 52, 71, 73, 65, 67, 67, 57, 109, 108, 100, 84, 83, 52, 79, 83, + 86, 118, 117, 56, 74, 107, 121, 70, 70, 104, 79, 117, 104, 79, 43, 47, 100, 119, 87, 80, + 51, 99, 115, 56, 73, 84, 110, 103, 113, 89, 113, 82, 69, 110, 115, 105, 89, 109, 70, + 122, 97, 87, 78, 102, 99, 109, 86, 106, 97, 88, 66, 112, 90, 87, 53, 48, 73, 106, 112, + 55, 73, 110, 74, 108, 89, 50, 108, 119, 97, 87, 86, 117, 100, 67, 73, 54, 73, 109, 77, + 121, 86, 110, 66, 78, 86, 122, 69, 49, 84, 84, 78, 119, 78, 107, 53, 85, 85, 110, 104, + 104, 98, 108, 111, 48, 89, 48, 100, 107, 101, 70, 111, 121, 86, 88, 112, 108, 86, 51, + 104, 116, 90, 71, 112, 115, 101, 108, 108, 88, 77, 72, 108, 107, 87, 69, 112, 117, 89, + 50, 112, 97, 97, 108, 108, 85, 81, 88, 112, 79, 86, 48, 48, 48, 73, 110, 49, 57, 34, + 125, 125, 18, 45, 87, 111, 114, 109, 104, 111, 108, 101, 32, 45, 32, 67, 111, 109, 112, + 108, 101, 116, 101, 32, 84, 111, 107, 101, 110, 32, 84, 114, 97, 110, 115, 108, 97, 116, + 111, 114, 32, 84, 114, 97, 110, 115, 102, 101, 114, 18, 151, 1, 10, 82, 10, 70, 10, 31, + 47, 99, 111, 115, 109, 111, 115, 46, 99, 114, 121, 112, 116, 111, 46, 115, 101, 99, 112, + 50, 53, 54, 107, 49, 46, 80, 117, 98, 75, 101, 121, 18, 35, 10, 33, 3, 185, 116, 9, 72, + 116, 44, 202, 69, 71, 52, 114, 33, 78, 210, 187, 51, 206, 29, 125, 231, 178, 228, 13, + 138, 230, 163, 33, 114, 14, 214, 28, 212, 18, 4, 10, 2, 8, 1, 24, 184, 215, 1, 18, 65, + 10, 14, 10, 4, 117, 115, 101, 105, 18, 6, 51, 48, 48, 48, 48, 48, 16, 192, 141, 183, 1, + 34, 42, 115, 101, 105, 49, 122, 51, 114, 48, 99, 99, 115, 115, 115, 110, 118, 117, 97, + 104, 101, 117, 97, 107, 117, 108, 53, 56, 122, 108, 117, 54, 53, 114, 110, 103, 119, 55, + 110, 106, 114, 106, 99, 122, 26, 64, 149, 61, 175, 131, 175, 91, 106, 106, 66, 225, 99, + 170, 24, 61, 32, 138, 116, 119, 199, 204, 144, 193, 231, 139, 236, 226, 189, 39, 160, + 72, 104, 183, 108, 9, 253, 45, 17, 28, 158, 91, 188, 252, 20, 75, 13, 48, 8, 253, 45, + 67, 193, 181, 32, 24, 126, 152, 15, 242, 109, 18, 211, 225, 99, 16, + ]), + }, + }, + ]; + + givenSeiBlockRepository(8418529, txs); + givenMetadataRepository({ lastFrom: 8418528n }); + givenStatsRepository(); + givenPollSeinTx(cfg); + + // When + await whenPollSeiStarts(); + + // Then + await thenWaitForAssertion(() => { + expect(getRedeemsSpy).toBeCalledWith( + 32, + "sei1smzlm9t79kur392nu9egl8p8je9j92q4gzguewj56a05kyxxra0qy0nuf3", + 20 + ), + expect(getBlockTimestampSpy).toBeCalledWith(80542798n); + }); + }); +}); + +const givenSeiBlockRepository = (timestamp: number, txs: any) => { + seiRepo = { + getBlockTimestamp: () => Promise.resolve(timestamp), + getRedeems: () => Promise.resolve(txs), + }; + + getBlockTimestampSpy = jest.spyOn(seiRepo, "getBlockTimestamp"); + getRedeemsSpy = jest.spyOn(seiRepo, "getRedeems"); +}; + +const givenMetadataRepository = (data?: PollSeiMetadata) => { + metadataRepo = { + get: () => Promise.resolve(data), + save: () => Promise.resolve(), + }; + metadataSaveSpy = jest.spyOn(metadataRepo, "save"); +}; + +const givenStatsRepository = () => { + statsRepo = { + count: () => {}, + measure: () => {}, + report: () => Promise.resolve(""), + }; +}; + +const givenPollSeinTx = (cfg: PollSeiConfig) => { + pollSei = new PollSei(seiRepo, metadataRepo, statsRepo, cfg); +}; + +const whenPollSeiStarts = async () => { + pollSei.run([handlers.working]); +}; diff --git a/blockchain-watcher/test/domain/actions/sei/HandleSeiRedeems.test.ts b/blockchain-watcher/test/domain/actions/sei/HandleSeiRedeems.test.ts new file mode 100644 index 00000000..fb15964b --- /dev/null +++ b/blockchain-watcher/test/domain/actions/sei/HandleSeiRedeems.test.ts @@ -0,0 +1,575 @@ +import { afterEach, describe, it, expect, jest } from "@jest/globals"; +import { LogFoundEvent, TransactionFoundEvent } from "../../../../src/domain/entities"; +import { StatRepository } from "../../../../src/domain/repositories"; +import { SeiRedeem } from "../../../../src/domain/entities/sei"; +import { + HandleSeiRedeemsOptions, + HandleSeiRedeems, +} from "../../../../src/domain/actions/sei/HandleSeiRedeems"; + +let targetRepoSpy: jest.SpiedFunction<(typeof targetRepo)["save"]>; +let statsRepo: StatRepository; + +let handleSeiRedeems: HandleSeiRedeems; +let txs: SeiRedeem[]; +let cfg: HandleSeiRedeemsOptions; + +describe("HandleSeiRedeems", () => { + afterEach(async () => {}); + + it("should be able to map redeems events txs", async () => { + // Given + givenConfig(); + givenStatsRepository(); + givenHandleSeiLogs(); + + // When + const result = await handleSeiRedeems.handle(txs); + + // Then + expect(result).toHaveLength(1); + expect(result[0].name).toBe("transfer-redeemed"); + expect(result[0].chainId).toBe(20); + expect(result[0].txHash).toBe( + "0xC196E9E445748AB4BE26E980F685F8F1FD02E8F327F9F1929CE5C426C936BF74" + ); + expect(result[0].address).toBe("osmo1hhzf9u376mg8zcuvx3jsls7t805kzcrsfsaydv"); + }); +}); + +const mapper = (addresses: string[], tx: SeiRedeem): TransactionFoundEvent => { + return { + name: "transfer-redeemed", + address: "osmo1hhzf9u376mg8zcuvx3jsls7t805kzcrsfsaydv", + chainId: 20, + txHash: "0xC196E9E445748AB4BE26E980F685F8F1FD02E8F327F9F1929CE5C426C936BF74", + blockHeight: 15778340n, + blockTime: 1715867714, + attributes: { + emitterAddress: "ccceeb29348f71bdd22ffef43a2a19c1f5b5e17c5cca5411529120182672ade5", + emitterChain: 21, + sequence: 128751, + protocol: "Wormhole Gateway", + status: "completed", + }, + }; +}; + +const targetRepo = { + save: async (events: LogFoundEvent>[]) => { + Promise.resolve(); + }, + failingSave: async (events: LogFoundEvent>[]) => { + Promise.reject(); + }, +}; + +const givenHandleSeiLogs = (targetFn: "save" | "failingSave" = "save") => { + targetRepoSpy = jest.spyOn(targetRepo, targetFn); + handleSeiRedeems = new HandleSeiRedeems(cfg, mapper, () => Promise.resolve(), statsRepo); +}; + +const givenConfig = () => { + cfg = { + filter: { + addresses: ["sei1smzlm9t79kur392nu9egl8p8je9j92q4gzguewj56a05kyxxra0qy0nuf3"], + }, + metricName: "process_vaa_event", + id: "poll-redeemed-transactions-wormchain", + }; +}; + +const givenStatsRepository = () => { + statsRepo = { + count: () => {}, + measure: () => {}, + report: () => Promise.resolve(""), + }; +}; + +txs = [ + { + chainId: 32, + events: [ + { + type: "use_feegrant", + attributes: [ + { + key: "Z3JhbnRlcg==", + value: "c2VpMXozcjBjY3Nzc252dWFoZXVha3VsNTh6bHU2NXJuZ3c3bmpyamN6", + index: true, + }, + { + key: "Z3JhbnRlZQ==", + value: "c2VpMXEzcjJ2OWo3cGYwcm1qODQ2aDNsYWtrODVydjZyMjV0bHBnNTl6", + index: true, + }, + ], + }, + { + type: "set_feegrant", + attributes: [ + { + key: "Z3JhbnRlcg==", + value: "c2VpMXozcjBjY3Nzc252dWFoZXVha3VsNTh6bHU2NXJuZ3c3bmpyamN6", + index: true, + }, + { + key: "Z3JhbnRlZQ==", + value: "c2VpMXEzcjJ2OWo3cGYwcm1qODQ2aDNsYWtrODVydjZyMjV0bHBnNTl6", + index: true, + }, + ], + }, + { + type: "coin_spent", + attributes: [ + { + key: "c3BlbmRlcg==", + value: "c2VpMXozcjBjY3Nzc252dWFoZXVha3VsNTh6bHU2NXJuZ3c3bmpyamN6", + index: true, + }, + { key: "YW1vdW50", value: "MzAwMDAwdXNlaQ==", index: true }, + ], + }, + { + type: "tx", + attributes: [ + { key: "ZmVl", value: "MzAwMDAwdXNlaQ==", index: true }, + { + key: "ZmVlX3BheWVy", + value: "c2VpMXozcjBjY3Nzc252dWFoZXVha3VsNTh6bHU2NXJuZ3c3bmpyamN6", + index: true, + }, + ], + }, + { + type: "tx", + attributes: [ + { + key: "YWNjX3NlcQ==", + value: "c2VpMXEzcjJ2OWo3cGYwcm1qODQ2aDNsYWtrODVydjZyMjV0bHBnNTl6LzI3NTc2", + index: true, + }, + ], + }, + { + type: "tx", + attributes: [ + { + key: "c2lnbmF0dXJl", + value: + "bFQydmc2OWJhbXBDNFdPcUdEMGdpblIzeDh5UXdlZUw3T0s5SjZCSWFMZHNDZjB0RVJ5ZVc3ejhGRXNOTUFqOUxVUEJ0U0FZZnBnUDhtMFMwK0ZqRUE9PQ==", + index: true, + }, + ], + }, + { + type: "signer", + attributes: [ + { + key: "ZXZtX2FkZHI=", + value: "MHg0NjZGMzU3OTNlNTc5MjMxM0JmRDQyZDhGQmE5MjI0MjExOUYzZGZE", + index: true, + }, + { + key: "c2VpX2FkZHI=", + value: "c2VpMXEzcjJ2OWo3cGYwcm1qODQ2aDNsYWtrODVydjZyMjV0bHBnNTl6", + index: true, + }, + ], + }, + { + type: "message", + attributes: [ + { + key: "YWN0aW9u", + value: "L2Nvc213YXNtLndhc20udjEuTXNnRXhlY3V0ZUNvbnRyYWN0", + index: true, + }, + ], + }, + { + type: "message", + attributes: [ + { key: "bW9kdWxl", value: "d2FzbQ==", index: true }, + { + key: "c2VuZGVy", + value: "c2VpMXEzcjJ2OWo3cGYwcm1qODQ2aDNsYWtrODVydjZyMjV0bHBnNTl6", + index: true, + }, + ], + }, + { + type: "execute", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + ], + }, + { + type: "wasm", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { key: "YWN0aW9u", value: "Y29tcGxldGVfdHJhbnNmZXJfd2l0aF9wYXlsb2Fk", index: true }, + { + key: "dHJhbnNmZXJfcGF5bG9hZA==", + value: + "ZXlKaVlYTnBZMTl5WldOcGNHbGxiblFpT25zaWNtVmphWEJwWlc1MElqb2lZekpXY0UxWE1UVk5NM0EyVGxSU2VHRnVXalJqUjJSNFdqSlZlbVZYZUcxa2FteDZXVmN3ZVdSWVNtNWphbHBxV1ZSQmVrNVhUVFFpZlgwPQ==", + index: true, + }, + ], + }, + { + type: "execute", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMXNtemxtOXQ3OWt1cjM5Mm51OWVnbDhwOGplOWo5MnE0Z3pndWV3ajU2YTA1a3l4eHJhMHF5MG51ZjM=", + index: true, + }, + ], + }, + { + type: "wasm", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMXNtemxtOXQ3OWt1cjM5Mm51OWVnbDhwOGplOWo5MnE0Z3pndWV3ajU2YTA1a3l4eHJhMHF5MG51ZjM=", + index: true, + }, + { key: "YWN0aW9u", value: "Y29tcGxldGVfdHJhbnNmZXJfd3JhcHBlZA==", index: true }, + { + key: "Y29udHJhY3Q=", + value: + "c2VpMXN6NTJ3NHVrMnk1ZGF0c2Mzamo2NHAwczh5YTV1OTNuNDNkMzloeDdzNDYzM2Vuc2NtenEyMHZseTc=", + index: true, + }, + { + key: "cmVjaXBpZW50", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { key: "YW1vdW50", value: "MjUwMDAwMDAw", index: true }, + { + key: "cmVsYXllcg==", + value: "c2VpMXEzcjJ2OWo3cGYwcm1qODQ2aDNsYWtrODVydjZyMjV0bHBnNTl6", + index: true, + }, + { key: "ZmVl", value: "MA==", index: true }, + ], + }, + { + type: "execute", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMXN6NTJ3NHVrMnk1ZGF0c2Mzamo2NHAwczh5YTV1OTNuNDNkMzloeDdzNDYzM2Vuc2NtenEyMHZseTc=", + index: true, + }, + ], + }, + { + type: "wasm", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMXN6NTJ3NHVrMnk1ZGF0c2Mzamo2NHAwczh5YTV1OTNuNDNkMzloeDdzNDYzM2Vuc2NtenEyMHZseTc=", + index: true, + }, + { key: "YWN0aW9u", value: "bWludA==", index: true }, + { + key: "dG8=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { key: "YW1vdW50", value: "MjUwMDAwMDAw", index: true }, + ], + }, + { + type: "reply", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + ], + }, + { + type: "coin_received", + attributes: [ + { + key: "cmVjZWl2ZXI=", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "coinbase", + attributes: [ + { + key: "bWludGVy", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "coin_spent", + attributes: [ + { + key: "c3BlbmRlcg==", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "coin_received", + attributes: [ + { + key: "cmVjZWl2ZXI=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "transfer", + attributes: [ + { + key: "cmVjaXBpZW50", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "c2VuZGVy", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "mint", + attributes: [ + { + key: "bWludF90b19hZGRyZXNz", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "coin_spent", + attributes: [ + { + key: "c3BlbmRlcg==", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "coin_received", + attributes: [ + { + key: "cmVjZWl2ZXI=", + value: "c2VpMW15M3p6NTRxanZ4cGdxZ2UzeWxmdjlzYW0ydXJncjZjYTAzNWM4", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "transfer", + attributes: [ + { + key: "cmVjaXBpZW50", + value: "c2VpMW15M3p6NTRxanZ4cGdxZ2UzeWxmdjlzYW0ydXJncjZjYTAzNWM4", + index: true, + }, + { + key: "c2VuZGVy", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + ], + height: 79268744n, + data: "CiYKJC9jb3Ntd2FzbS53YXNtLnYxLk1zZ0V4ZWN1dGVDb250cmFjdA==", + hash: "7CC18417F02E8859A928A56E2080C9AFEC2C81AE206B388B025C034F686D63B8", + tx: Buffer.from([ + 10, 230, 13, 10, 180, 13, 10, 36, 47, 99, 111, 115, 109, 119, 97, 115, 109, 46, 119, 97, 115, + 109, 46, 118, 49, 46, 77, 115, 103, 69, 120, 101, 99, 117, 116, 101, 67, 111, 110, 116, 114, + 97, 99, 116, 18, 139, 13, 10, 42, 115, 101, 105, 49, 113, 51, 114, 50, 118, 57, 106, 55, 112, + 102, 48, 114, 109, 106, 56, 52, 54, 104, 51, 108, 97, 107, 107, 56, 53, 114, 118, 54, 114, 50, + 53, 116, 108, 112, 103, 53, 57, 122, 18, 62, 115, 101, 105, 49, 56, 57, 97, 100, 103, 117, 97, + 119, 117, 103, 107, 51, 101, 53, 53, 122, 110, 54, 51, 122, 56, 114, 57, 108, 108, 50, 57, + 120, 114, 106, 119, 99, 97, 54, 51, 54, 114, 97, 55, 118, 55, 103, 120, 117, 122, 110, 57, 56, + 115, 120, 121, 113, 119, 122, 116, 52, 55, 108, 26, 156, 12, 123, 34, 99, 111, 109, 112, 108, + 101, 116, 101, 95, 116, 114, 97, 110, 115, 102, 101, 114, 95, 97, 110, 100, 95, 99, 111, 110, + 118, 101, 114, 116, 34, 58, 123, 34, 118, 97, 97, 34, 58, 34, 65, 81, 65, 65, 65, 65, 81, 78, + 65, 80, 115, 111, 57, 97, 73, 43, 99, 65, 48, 100, 56, 70, 114, 74, 98, 74, 71, 101, 97, 71, + 70, 68, 113, 104, 49, 98, 81, 98, 87, 75, 79, 102, 68, 77, 70, 105, 111, 102, 69, 76, 102, + 111, 79, 103, 106, 102, 73, 118, 111, 87, 89, 83, 104, 55, 110, 53, 43, 48, 88, 82, 74, 68, + 84, 43, 113, 48, 102, 120, 121, 90, 66, 101, 115, 68, 73, 71, 85, 106, 50, 52, 80, 114, 107, + 88, 73, 65, 65, 85, 113, 121, 87, 122, 52, 110, 54, 104, 112, 77, 89, 75, 85, 122, 97, 103, + 53, 49, 56, 120, 121, 99, 66, 86, 76, 69, 50, 48, 51, 47, 88, 74, 85, 56, 65, 75, 70, 76, 101, + 118, 120, 101, 76, 71, 98, 55, 72, 48, 43, 113, 54, 53, 73, 105, 112, 53, 118, 56, 109, 116, + 70, 78, 78, 71, 88, 116, 104, 104, 119, 49, 81, 113, 83, 99, 114, 122, 119, 121, 77, 84, 67, + 107, 79, 85, 56, 65, 66, 74, 99, 106, 82, 78, 87, 70, 109, 105, 100, 112, 88, 84, 51, 75, 118, + 55, 68, 79, 103, 78, 120, 81, 57, 75, 50, 84, 78, 97, 106, 86, 121, 97, 111, 118, 81, 51, 120, + 78, 71, 86, 80, 82, 80, 86, 74, 117, 110, 68, 118, 71, 47, 89, 68, 90, 112, 106, 102, 110, 66, + 78, 67, 111, 99, 52, 106, 80, 102, 55, 79, 90, 52, 111, 119, 83, 102, 74, 65, 76, 111, 119, + 113, 43, 73, 70, 89, 65, 66, 113, 87, 67, 87, 65, 72, 67, 76, 82, 83, 122, 107, 65, 116, 112, + 106, 106, 82, 98, 73, 47, 56, 97, 110, 117, 97, 74, 85, 89, 114, 52, 47, 119, 66, 98, 72, 107, + 98, 71, 109, 89, 113, 87, 86, 53, 119, 117, 67, 104, 121, 49, 84, 105, 80, 103, 102, 118, 73, + 118, 76, 66, 78, 106, 71, 80, 99, 88, 65, 84, 49, 65, 48, 108, 111, 97, 79, 55, 110, 78, 52, + 47, 116, 52, 53, 83, 111, 66, 66, 55, 55, 99, 88, 113, 99, 117, 106, 49, 109, 118, 67, 121, + 99, 100, 121, 70, 65, 108, 80, 75, 69, 69, 78, 56, 55, 101, 101, 52, 50, 109, 112, 109, 50, + 56, 97, 98, 84, 80, 72, 72, 86, 83, 66, 100, 82, 80, 52, 77, 112, 57, 104, 111, 114, 53, 86, + 121, 120, 87, 121, 66, 47, 73, 48, 76, 84, 68, 88, 54, 82, 49, 71, 55, 102, 122, 77, 57, 52, + 71, 116, 70, 48, 121, 104, 73, 69, 65, 67, 69, 50, 102, 75, 86, 118, 118, 104, 117, 66, 49, + 118, 103, 84, 119, 86, 55, 82, 71, 78, 109, 114, 121, 76, 75, 89, 105, 52, 110, 74, 103, 65, + 119, 87, 116, 56, 71, 88, 113, 51, 55, 65, 43, 87, 99, 79, 117, 101, 102, 101, 70, 53, 53, 75, + 114, 90, 86, 101, 118, 71, 101, 99, 80, 115, 74, 114, 74, 72, 110, 90, 71, 114, 86, 99, 54, + 122, 86, 75, 110, 43, 105, 50, 118, 73, 43, 89, 65, 67, 98, 48, 88, 108, 100, 51, 67, 84, 49, + 65, 81, 83, 55, 51, 109, 101, 52, 79, 80, 119, 109, 72, 113, 52, 119, 76, 75, 71, 114, 77, 52, + 115, 89, 76, 78, 48, 87, 111, 70, 85, 49, 53, 51, 86, 103, 112, 90, 53, 110, 113, 110, 88, + 112, 117, 122, 122, 70, 71, 84, 90, 57, 88, 66, 116, 113, 51, 81, 111, 53, 102, 52, 116, 119, + 108, 116, 71, 57, 72, 104, 90, 101, 121, 47, 103, 80, 81, 66, 67, 110, 102, 112, 66, 99, 83, + 100, 107, 75, 69, 83, 50, 74, 80, 105, 109, 77, 107, 110, 84, 43, 112, 116, 68, 113, 50, 117, + 68, 100, 88, 50, 120, 77, 117, 114, 56, 85, 119, 83, 71, 50, 111, 82, 81, 122, 110, 77, 77, + 98, 81, 122, 114, 53, 115, 111, 53, 82, 72, 113, 71, 55, 48, 43, 74, 80, 89, 72, 104, 47, 105, + 108, 101, 79, 49, 86, 54, 75, 107, 75, 52, 69, 65, 57, 120, 120, 99, 65, 68, 88, 70, 88, 70, + 77, 104, 111, 69, 108, 116, 90, 86, 76, 47, 78, 108, 66, 97, 49, 115, 69, 50, 74, 117, 75, + 120, 67, 70, 81, 55, 56, 88, 54, 55, 81, 107, 87, 119, 119, 53, 108, 102, 69, 88, 111, 65, + 119, 47, 98, 118, 110, 117, 47, 115, 77, 74, 48, 99, 43, 86, 71, 84, 113, 83, 49, 99, 89, 77, + 69, 55, 98, 112, 111, 51, 56, 107, 51, 67, 52, 79, 115, 53, 114, 117, 117, 89, 66, 68, 107, + 76, 82, 90, 89, 52, 116, 85, 99, 120, 118, 75, 43, 106, 104, 65, 47, 51, 87, 86, 87, 110, 109, + 106, 103, 107, 98, 108, 68, 97, 112, 74, 109, 81, 50, 65, 69, 57, 88, 56, 100, 90, 88, 84, 90, + 50, 103, 111, 49, 54, 110, 71, 89, 76, 80, 97, 100, 43, 122, 43, 90, 74, 53, 107, 50, 57, 72, + 51, 102, 117, 69, 86, 71, 110, 99, 66, 87, 47, 65, 117, 69, 78, 98, 109, 114, 115, 66, 68, 43, + 99, 78, 109, 70, 97, 43, 49, 80, 87, 71, 51, 97, 105, 77, 102, 110, 105, 107, 101, 111, 98, + 111, 78, 122, 79, 102, 70, 102, 113, 43, 111, 76, 114, 118, 75, 72, 55, 116, 103, 114, 51, + 105, 68, 69, 119, 87, 69, 99, 101, 119, 83, 98, 55, 112, 79, 105, 111, 121, 88, 50, 69, 108, + 54, 78, 52, 114, 118, 85, 113, 112, 102, 82, 66, 84, 105, 103, 56, 109, 118, 86, 84, 99, 105, + 84, 77, 65, 69, 74, 90, 56, 115, 110, 90, 121, 113, 111, 122, 53, 83, 56, 85, 79, 76, 116, 67, + 121, 111, 102, 57, 100, 101, 83, 89, 72, 51, 48, 111, 105, 81, 98, 68, 84, 111, 90, 75, 97, + 72, 114, 83, 80, 70, 81, 55, 105, 47, 78, 107, 52, 122, 103, 98, 54, 50, 113, 104, 43, 120, + 98, 108, 88, 112, 87, 102, 52, 75, 112, 68, 68, 105, 87, 43, 53, 117, 54, 72, 88, 66, 89, 51, + 88, 74, 47, 115, 65, 69, 106, 115, 102, 75, 79, 113, 55, 68, 103, 109, 89, 116, 118, 73, 120, + 68, 100, 56, 66, 50, 98, 57, 122, 49, 116, 89, 68, 57, 122, 102, 100, 70, 49, 98, 107, 52, 85, + 112, 71, 86, 119, 83, 122, 70, 111, 80, 54, 55, 57, 81, 43, 103, 84, 75, 43, 120, 67, 49, 55, + 57, 51, 118, 80, 78, 65, 86, 116, 109, 76, 113, 81, 98, 84, 84, 54, 54, 115, 79, 81, 75, 111, + 79, 102, 112, 99, 107, 66, 90, 108, 86, 121, 116, 81, 65, 65, 103, 74, 115, 65, 65, 101, 120, + 122, 99, 112, 108, 100, 88, 77, 104, 122, 73, 53, 102, 55, 67, 116, 78, 99, 65, 83, 72, 103, + 54, 113, 107, 78, 74, 118, 103, 111, 112, 84, 84, 75, 116, 85, 79, 82, 115, 54, 84, 49, 65, + 65, 65, 65, 65, 65, 65, 78, 99, 109, 81, 103, 65, 119, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 79, 53, 114, 75, 65, 120, 118, 112, 54, 56, 55, 55, 98, 114, 84, 111, 57, 90, + 102, 78, 113, 113, 56, 108, 48, 77, 98, 71, 55, 53, 77, 76, 83, 57, 117, 68, 107, 102, 75, 89, + 67, 65, 48, 85, 118, 88, 87, 69, 65, 65, 84, 108, 54, 49, 72, 79, 117, 52, 105, 48, 99, 48, + 111, 75, 101, 111, 105, 79, 77, 118, 47, 113, 75, 89, 99, 110, 89, 55, 113, 79, 104, 57, 56, + 122, 121, 68, 99, 70, 77, 112, 52, 71, 73, 65, 67, 67, 57, 109, 108, 100, 84, 83, 52, 79, 83, + 86, 118, 117, 56, 74, 107, 121, 70, 70, 104, 79, 117, 104, 79, 43, 47, 100, 119, 87, 80, 51, + 99, 115, 56, 73, 84, 110, 103, 113, 89, 113, 82, 69, 110, 115, 105, 89, 109, 70, 122, 97, 87, + 78, 102, 99, 109, 86, 106, 97, 88, 66, 112, 90, 87, 53, 48, 73, 106, 112, 55, 73, 110, 74, + 108, 89, 50, 108, 119, 97, 87, 86, 117, 100, 67, 73, 54, 73, 109, 77, 121, 86, 110, 66, 78, + 86, 122, 69, 49, 84, 84, 78, 119, 78, 107, 53, 85, 85, 110, 104, 104, 98, 108, 111, 48, 89, + 48, 100, 107, 101, 70, 111, 121, 86, 88, 112, 108, 86, 51, 104, 116, 90, 71, 112, 115, 101, + 108, 108, 88, 77, 72, 108, 107, 87, 69, 112, 117, 89, 50, 112, 97, 97, 108, 108, 85, 81, 88, + 112, 79, 86, 48, 48, 48, 73, 110, 49, 57, 34, 125, 125, 18, 45, 87, 111, 114, 109, 104, 111, + 108, 101, 32, 45, 32, 67, 111, 109, 112, 108, 101, 116, 101, 32, 84, 111, 107, 101, 110, 32, + 84, 114, 97, 110, 115, 108, 97, 116, 111, 114, 32, 84, 114, 97, 110, 115, 102, 101, 114, 18, + 151, 1, 10, 82, 10, 70, 10, 31, 47, 99, 111, 115, 109, 111, 115, 46, 99, 114, 121, 112, 116, + 111, 46, 115, 101, 99, 112, 50, 53, 54, 107, 49, 46, 80, 117, 98, 75, 101, 121, 18, 35, 10, + 33, 3, 185, 116, 9, 72, 116, 44, 202, 69, 71, 52, 114, 33, 78, 210, 187, 51, 206, 29, 125, + 231, 178, 228, 13, 138, 230, 163, 33, 114, 14, 214, 28, 212, 18, 4, 10, 2, 8, 1, 24, 184, 215, + 1, 18, 65, 10, 14, 10, 4, 117, 115, 101, 105, 18, 6, 51, 48, 48, 48, 48, 48, 16, 192, 141, + 183, 1, 34, 42, 115, 101, 105, 49, 122, 51, 114, 48, 99, 99, 115, 115, 115, 110, 118, 117, 97, + 104, 101, 117, 97, 107, 117, 108, 53, 56, 122, 108, 117, 54, 53, 114, 110, 103, 119, 55, 110, + 106, 114, 106, 99, 122, 26, 64, 149, 61, 175, 131, 175, 91, 106, 106, 66, 225, 99, 170, 24, + 61, 32, 138, 116, 119, 199, 204, 144, 193, 231, 139, 236, 226, 189, 39, 160, 72, 104, 183, + 108, 9, 253, 45, 17, 28, 158, 91, 188, 252, 20, 75, 13, 48, 8, 253, 45, 67, 193, 181, 32, 24, + 126, 152, 15, 242, 109, 18, 211, 225, 99, 16, + ]), + }, +]; diff --git a/blockchain-watcher/test/domain/actions/sei/PollSei.test.ts b/blockchain-watcher/test/domain/actions/sei/PollSei.test.ts new file mode 100644 index 00000000..0d186737 --- /dev/null +++ b/blockchain-watcher/test/domain/actions/sei/PollSei.test.ts @@ -0,0 +1,570 @@ +import { afterEach, describe, it, expect, jest } from "@jest/globals"; +import { thenWaitForAssertion } from "../../../wait-assertion"; +import { SeiRedeem } from "../../../../src/domain/entities/sei"; +import { + MetadataRepository, + StatRepository, + SeiRepository, +} from "../../../../src/domain/repositories"; +import { + PollSeiMetadata, + PollSeiConfig, + PollSei, +} from "../../../../src/domain/actions/sei/PollSei"; + +let props = { + blockBatchSize: 20, + environment: "testnet", + commitment: "latest", + addresses: ["sei1smzlm9t79kur392nu9egl8p8je9j92q4gzguewj56a05kyxxra0qy0nuf3"], + interval: 5000, + topics: [], + chainId: 32, + filter: { + address: "sei1smzlm9t79kur392nu9egl8p8je9j92q4gzguewj56a05kyxxra0qy0nuf3", + }, + chain: "sei", + id: "poll-redeemed-transactions-sei", +}; + +let cfg = new PollSeiConfig(props); + +let getRedeemsSpy: jest.SpiedFunction; +let getBlockTimestampSpy: jest.SpiedFunction; +let handlerSpy: jest.SpiedFunction<(txs: SeiRedeem[]) => Promise>; +let metadataSaveSpy: jest.SpiedFunction["save"]>; + +let metadataRepo: MetadataRepository; +let seiRepo: SeiRepository; +let statsRepo: StatRepository; + +let handlers = { + working: (txs: SeiRepository[]) => Promise.resolve(), + failing: (txs: SeiRepository[]) => Promise.reject(), +}; +let pollSei: PollSei; + +describe("PollWormchain", () => { + afterEach(async () => { + await pollSei.stop(); + }); + + it("should be process the txs from sei blockchain and update the lastFrom height", async () => { + const txs = [ + { + chainId: 32, + events: [ + { + type: "coin_spent", + attributes: [ + { + key: "c3BlbmRlcg==", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3pl", + index: true, + }, + { key: "YW1vdW50", value: "NjcyODZ1c2Vp", index: true }, + ], + }, + { + type: "tx", + attributes: [ + { key: "ZmVl", value: "NjcyODZ1c2Vp", index: true }, + { + key: "ZmVlX3BheWVy", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3pl", + index: true, + }, + ], + }, + { + type: "tx", + attributes: [ + { + key: "YWNjX3NlcQ==", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3plLzM2NjU=", + index: true, + }, + ], + }, + { + type: "tx", + attributes: [ + { + key: "c2lnbmF0dXJl", + value: + "eWROMjlWM1lhWHNjUUlidUNDcUR5UFBGYjZvWWtJMVVvc2Z5SVBMTVhMa09La1ZSZWdZNTYzb3lwVzFzSTdZUXZCdkxKV1pzQlNtQmFKdGZvRjh2cVE9PQ==", + index: true, + }, + ], + }, + { + type: "signer", + attributes: [ + { + key: "ZXZtX2FkZHI=", + value: "MHgzNUM4NEUzN2RkOTM2OTFFQzZFZUY1MTdmODc1MGI3NjVlMjQ5OTkz", + index: true, + }, + { + key: "c2VpX2FkZHI=", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3pl", + index: true, + }, + ], + }, + { + type: "message", + attributes: [ + { + key: "YWN0aW9u", + value: "L2Nvc213YXNtLndhc20udjEuTXNnRXhlY3V0ZUNvbnRyYWN0", + index: true, + }, + ], + }, + { + type: "message", + attributes: [ + { key: "bW9kdWxl", value: "d2FzbQ==", index: true }, + { + key: "c2VuZGVy", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3pl", + index: true, + }, + ], + }, + { + type: "execute", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + ], + }, + { + type: "wasm", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { key: "YWN0aW9u", value: "Y29tcGxldGVfdHJhbnNmZXJfd2l0aF9wYXlsb2Fk", index: true }, + { + key: "dHJhbnNmZXJfcGF5bG9hZA==", + value: + "ZXlKaVlYTnBZMTl5WldOcGNHbGxiblFpT25zaWNtVmphWEJwWlc1MElqb2lZekpXY0UxWFkzcE9hbWd4V1ZSc2VHVlhkSGxhUjA1M1lVZFdjbGxVV1RCYVYwWjVUa2QzTTAweVJqWk9XR2hzV25wTmQwMHpjR3dpZlgwPQ==", + index: true, + }, + ], + }, + { + type: "execute", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMXNtemxtOXQ3OWt1cjM5Mm51OWVnbDhwOGplOWo5MnE0Z3pndWV3ajU2YTA1a3l4eHJhMHF5MG51ZjM=", + index: true, + }, + ], + }, + { + type: "wasm", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMXNtemxtOXQ3OWt1cjM5Mm51OWVnbDhwOGplOWo5MnE0Z3pndWV3ajU2YTA1a3l4eHJhMHF5MG51ZjM=", + index: true, + }, + { key: "YWN0aW9u", value: "Y29tcGxldGVfdHJhbnNmZXJfd3JhcHBlZA==", index: true }, + { + key: "Y29udHJhY3Q=", + value: + "c2VpMWxnOTV2enFrMzUzbXM5YXBwem5oZDZyMzM2c3NjcXJjNTA3NDM5bjc0d3I3cmZkdno3ZHFxYTlzbGw=", + index: true, + }, + { + key: "cmVjaXBpZW50", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { key: "YW1vdW50", value: "NTEyOTcwODY=", index: true }, + { + key: "cmVsYXllcg==", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3pl", + index: true, + }, + { key: "ZmVl", value: "MA==", index: true }, + ], + }, + { + type: "execute", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMWxnOTV2enFrMzUzbXM5YXBwem5oZDZyMzM2c3NjcXJjNTA3NDM5bjc0d3I3cmZkdno3ZHFxYTlzbGw=", + index: true, + }, + ], + }, + { + type: "wasm", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMWxnOTV2enFrMzUzbXM5YXBwem5oZDZyMzM2c3NjcXJjNTA3NDM5bjc0d3I3cmZkdno3ZHFxYTlzbGw=", + index: true, + }, + { key: "YWN0aW9u", value: "bWludA==", index: true }, + { + key: "dG8=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { key: "YW1vdW50", value: "NTEyOTcwODY=", index: true }, + ], + }, + { + type: "reply", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + ], + }, + { + type: "coin_received", + attributes: [ + { + key: "cmVjZWl2ZXI=", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "coinbase", + attributes: [ + { + key: "bWludGVy", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "coin_spent", + attributes: [ + { + key: "c3BlbmRlcg==", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "coin_received", + attributes: [ + { + key: "cmVjZWl2ZXI=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "transfer", + attributes: [ + { + key: "cmVjaXBpZW50", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "c2VuZGVy", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "mint", + attributes: [ + { + key: "bWludF90b19hZGRyZXNz", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "coin_spent", + attributes: [ + { + key: "c3BlbmRlcg==", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "coin_received", + attributes: [ + { + key: "cmVjZWl2ZXI=", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3pl", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + { + type: "transfer", + attributes: [ + { + key: "cmVjaXBpZW50", + value: "c2VpMWczNjh1YTlxeWtyZGNwaGVrYTY0ZWFyNGw3M2F6NXhlZzMwM3pl", + index: true, + }, + { + key: "c2VuZGVy", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "NTEyOTcwODZmYWN0b3J5L3NlaTE4OWFkZ3Vhd3VnazNlNTV6bjYzejhyOWxsMjl4cmp3Y2E2MzZyYTd2N2d4dXpuOThzeHlxd3p0NDdsL0hxNHR1RHpoUkJueHczdEZBNW42TTUyTlZNVmNDMTlYZ2dieURpSktDRDZI", + index: true, + }, + ], + }, + ], + height: "80542798", + data: "CiYKJC9jb3Ntd2FzbS53YXNtLnYxLk1zZ0V4ZWN1dGVDb250cmFjdA==", + hash: "C94451E3FCDC064E9E7FCAB6FBBFADD9C909910817BB185FF651580A72B3034B", + tx: { + type: Buffer.from([ + 10, 230, 13, 10, 180, 13, 10, 36, 47, 99, 111, 115, 109, 119, 97, 115, 109, 46, 119, 97, + 115, 109, 46, 118, 49, 46, 77, 115, 103, 69, 120, 101, 99, 117, 116, 101, 67, 111, 110, + 116, 114, 97, 99, 116, 18, 139, 13, 10, 42, 115, 101, 105, 49, 113, 51, 114, 50, 118, + 57, 106, 55, 112, 102, 48, 114, 109, 106, 56, 52, 54, 104, 51, 108, 97, 107, 107, 56, + 53, 114, 118, 54, 114, 50, 53, 116, 108, 112, 103, 53, 57, 122, 18, 62, 115, 101, 105, + 49, 56, 57, 97, 100, 103, 117, 97, 119, 117, 103, 107, 51, 101, 53, 53, 122, 110, 54, + 51, 122, 56, 114, 57, 108, 108, 50, 57, 120, 114, 106, 119, 99, 97, 54, 51, 54, 114, 97, + 55, 118, 55, 103, 120, 117, 122, 110, 57, 56, 115, 120, 121, 113, 119, 122, 116, 52, 55, + 108, 26, 156, 12, 123, 34, 99, 111, 109, 112, 108, 101, 116, 101, 95, 116, 114, 97, 110, + 115, 102, 101, 114, 95, 97, 110, 100, 95, 99, 111, 110, 118, 101, 114, 116, 34, 58, 123, + 34, 118, 97, 97, 34, 58, 34, 65, 81, 65, 65, 65, 65, 81, 78, 65, 80, 115, 111, 57, 97, + 73, 43, 99, 65, 48, 100, 56, 70, 114, 74, 98, 74, 71, 101, 97, 71, 70, 68, 113, 104, 49, + 98, 81, 98, 87, 75, 79, 102, 68, 77, 70, 105, 111, 102, 69, 76, 102, 111, 79, 103, 106, + 102, 73, 118, 111, 87, 89, 83, 104, 55, 110, 53, 43, 48, 88, 82, 74, 68, 84, 43, 113, + 48, 102, 120, 121, 90, 66, 101, 115, 68, 73, 71, 85, 106, 50, 52, 80, 114, 107, 88, 73, + 65, 65, 85, 113, 121, 87, 122, 52, 110, 54, 104, 112, 77, 89, 75, 85, 122, 97, 103, 53, + 49, 56, 120, 121, 99, 66, 86, 76, 69, 50, 48, 51, 47, 88, 74, 85, 56, 65, 75, 70, 76, + 101, 118, 120, 101, 76, 71, 98, 55, 72, 48, 43, 113, 54, 53, 73, 105, 112, 53, 118, 56, + 109, 116, 70, 78, 78, 71, 88, 116, 104, 104, 119, 49, 81, 113, 83, 99, 114, 122, 119, + 121, 77, 84, 67, 107, 79, 85, 56, 65, 66, 74, 99, 106, 82, 78, 87, 70, 109, 105, 100, + 112, 88, 84, 51, 75, 118, 55, 68, 79, 103, 78, 120, 81, 57, 75, 50, 84, 78, 97, 106, 86, + 121, 97, 111, 118, 81, 51, 120, 78, 71, 86, 80, 82, 80, 86, 74, 117, 110, 68, 118, 71, + 47, 89, 68, 90, 112, 106, 102, 110, 66, 78, 67, 111, 99, 52, 106, 80, 102, 55, 79, 90, + 52, 111, 119, 83, 102, 74, 65, 76, 111, 119, 113, 43, 73, 70, 89, 65, 66, 113, 87, 67, + 87, 65, 72, 67, 76, 82, 83, 122, 107, 65, 116, 112, 106, 106, 82, 98, 73, 47, 56, 97, + 110, 117, 97, 74, 85, 89, 114, 52, 47, 119, 66, 98, 72, 107, 98, 71, 109, 89, 113, 87, + 86, 53, 119, 117, 67, 104, 121, 49, 84, 105, 80, 103, 102, 118, 73, 118, 76, 66, 78, + 106, 71, 80, 99, 88, 65, 84, 49, 65, 48, 108, 111, 97, 79, 55, 110, 78, 52, 47, 116, 52, + 53, 83, 111, 66, 66, 55, 55, 99, 88, 113, 99, 117, 106, 49, 109, 118, 67, 121, 99, 100, + 121, 70, 65, 108, 80, 75, 69, 69, 78, 56, 55, 101, 101, 52, 50, 109, 112, 109, 50, 56, + 97, 98, 84, 80, 72, 72, 86, 83, 66, 100, 82, 80, 52, 77, 112, 57, 104, 111, 114, 53, 86, + 121, 120, 87, 121, 66, 47, 73, 48, 76, 84, 68, 88, 54, 82, 49, 71, 55, 102, 122, 77, 57, + 52, 71, 116, 70, 48, 121, 104, 73, 69, 65, 67, 69, 50, 102, 75, 86, 118, 118, 104, 117, + 66, 49, 118, 103, 84, 119, 86, 55, 82, 71, 78, 109, 114, 121, 76, 75, 89, 105, 52, 110, + 74, 103, 65, 119, 87, 116, 56, 71, 88, 113, 51, 55, 65, 43, 87, 99, 79, 117, 101, 102, + 101, 70, 53, 53, 75, 114, 90, 86, 101, 118, 71, 101, 99, 80, 115, 74, 114, 74, 72, 110, + 90, 71, 114, 86, 99, 54, 122, 86, 75, 110, 43, 105, 50, 118, 73, 43, 89, 65, 67, 98, 48, + 88, 108, 100, 51, 67, 84, 49, 65, 81, 83, 55, 51, 109, 101, 52, 79, 80, 119, 109, 72, + 113, 52, 119, 76, 75, 71, 114, 77, 52, 115, 89, 76, 78, 48, 87, 111, 70, 85, 49, 53, 51, + 86, 103, 112, 90, 53, 110, 113, 110, 88, 112, 117, 122, 122, 70, 71, 84, 90, 57, 88, 66, + 116, 113, 51, 81, 111, 53, 102, 52, 116, 119, 108, 116, 71, 57, 72, 104, 90, 101, 121, + 47, 103, 80, 81, 66, 67, 110, 102, 112, 66, 99, 83, 100, 107, 75, 69, 83, 50, 74, 80, + 105, 109, 77, 107, 110, 84, 43, 112, 116, 68, 113, 50, 117, 68, 100, 88, 50, 120, 77, + 117, 114, 56, 85, 119, 83, 71, 50, 111, 82, 81, 122, 110, 77, 77, 98, 81, 122, 114, 53, + 115, 111, 53, 82, 72, 113, 71, 55, 48, 43, 74, 80, 89, 72, 104, 47, 105, 108, 101, 79, + 49, 86, 54, 75, 107, 75, 52, 69, 65, 57, 120, 120, 99, 65, 68, 88, 70, 88, 70, 77, 104, + 111, 69, 108, 116, 90, 86, 76, 47, 78, 108, 66, 97, 49, 115, 69, 50, 74, 117, 75, 120, + 67, 70, 81, 55, 56, 88, 54, 55, 81, 107, 87, 119, 119, 53, 108, 102, 69, 88, 111, 65, + 119, 47, 98, 118, 110, 117, 47, 115, 77, 74, 48, 99, 43, 86, 71, 84, 113, 83, 49, 99, + 89, 77, 69, 55, 98, 112, 111, 51, 56, 107, 51, 67, 52, 79, 115, 53, 114, 117, 117, 89, + 66, 68, 107, 76, 82, 90, 89, 52, 116, 85, 99, 120, 118, 75, 43, 106, 104, 65, 47, 51, + 87, 86, 87, 110, 109, 106, 103, 107, 98, 108, 68, 97, 112, 74, 109, 81, 50, 65, 69, 57, + 88, 56, 100, 90, 88, 84, 90, 50, 103, 111, 49, 54, 110, 71, 89, 76, 80, 97, 100, 43, + 122, 43, 90, 74, 53, 107, 50, 57, 72, 51, 102, 117, 69, 86, 71, 110, 99, 66, 87, 47, 65, + 117, 69, 78, 98, 109, 114, 115, 66, 68, 43, 99, 78, 109, 70, 97, 43, 49, 80, 87, 71, 51, + 97, 105, 77, 102, 110, 105, 107, 101, 111, 98, 111, 78, 122, 79, 102, 70, 102, 113, 43, + 111, 76, 114, 118, 75, 72, 55, 116, 103, 114, 51, 105, 68, 69, 119, 87, 69, 99, 101, + 119, 83, 98, 55, 112, 79, 105, 111, 121, 88, 50, 69, 108, 54, 78, 52, 114, 118, 85, 113, + 112, 102, 82, 66, 84, 105, 103, 56, 109, 118, 86, 84, 99, 105, 84, 77, 65, 69, 74, 90, + 56, 115, 110, 90, 121, 113, 111, 122, 53, 83, 56, 85, 79, 76, 116, 67, 121, 111, 102, + 57, 100, 101, 83, 89, 72, 51, 48, 111, 105, 81, 98, 68, 84, 111, 90, 75, 97, 72, 114, + 83, 80, 70, 81, 55, 105, 47, 78, 107, 52, 122, 103, 98, 54, 50, 113, 104, 43, 120, 98, + 108, 88, 112, 87, 102, 52, 75, 112, 68, 68, 105, 87, 43, 53, 117, 54, 72, 88, 66, 89, + 51, 88, 74, 47, 115, 65, 69, 106, 115, 102, 75, 79, 113, 55, 68, 103, 109, 89, 116, 118, + 73, 120, 68, 100, 56, 66, 50, 98, 57, 122, 49, 116, 89, 68, 57, 122, 102, 100, 70, 49, + 98, 107, 52, 85, 112, 71, 86, 119, 83, 122, 70, 111, 80, 54, 55, 57, 81, 43, 103, 84, + 75, 43, 120, 67, 49, 55, 57, 51, 118, 80, 78, 65, 86, 116, 109, 76, 113, 81, 98, 84, 84, + 54, 54, 115, 79, 81, 75, 111, 79, 102, 112, 99, 107, 66, 90, 108, 86, 121, 116, 81, 65, + 65, 103, 74, 115, 65, 65, 101, 120, 122, 99, 112, 108, 100, 88, 77, 104, 122, 73, 53, + 102, 55, 67, 116, 78, 99, 65, 83, 72, 103, 54, 113, 107, 78, 74, 118, 103, 111, 112, 84, + 84, 75, 116, 85, 79, 82, 115, 54, 84, 49, 65, 65, 65, 65, 65, 65, 65, 78, 99, 109, 81, + 103, 65, 119, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 79, 53, 114, + 75, 65, 120, 118, 112, 54, 56, 55, 55, 98, 114, 84, 111, 57, 90, 102, 78, 113, 113, 56, + 108, 48, 77, 98, 71, 55, 53, 77, 76, 83, 57, 117, 68, 107, 102, 75, 89, 67, 65, 48, 85, + 118, 88, 87, 69, 65, 65, 84, 108, 54, 49, 72, 79, 117, 52, 105, 48, 99, 48, 111, 75, + 101, 111, 105, 79, 77, 118, 47, 113, 75, 89, 99, 110, 89, 55, 113, 79, 104, 57, 56, 122, + 121, 68, 99, 70, 77, 112, 52, 71, 73, 65, 67, 67, 57, 109, 108, 100, 84, 83, 52, 79, 83, + 86, 118, 117, 56, 74, 107, 121, 70, 70, 104, 79, 117, 104, 79, 43, 47, 100, 119, 87, 80, + 51, 99, 115, 56, 73, 84, 110, 103, 113, 89, 113, 82, 69, 110, 115, 105, 89, 109, 70, + 122, 97, 87, 78, 102, 99, 109, 86, 106, 97, 88, 66, 112, 90, 87, 53, 48, 73, 106, 112, + 55, 73, 110, 74, 108, 89, 50, 108, 119, 97, 87, 86, 117, 100, 67, 73, 54, 73, 109, 77, + 121, 86, 110, 66, 78, 86, 122, 69, 49, 84, 84, 78, 119, 78, 107, 53, 85, 85, 110, 104, + 104, 98, 108, 111, 48, 89, 48, 100, 107, 101, 70, 111, 121, 86, 88, 112, 108, 86, 51, + 104, 116, 90, 71, 112, 115, 101, 108, 108, 88, 77, 72, 108, 107, 87, 69, 112, 117, 89, + 50, 112, 97, 97, 108, 108, 85, 81, 88, 112, 79, 86, 48, 48, 48, 73, 110, 49, 57, 34, + 125, 125, 18, 45, 87, 111, 114, 109, 104, 111, 108, 101, 32, 45, 32, 67, 111, 109, 112, + 108, 101, 116, 101, 32, 84, 111, 107, 101, 110, 32, 84, 114, 97, 110, 115, 108, 97, 116, + 111, 114, 32, 84, 114, 97, 110, 115, 102, 101, 114, 18, 151, 1, 10, 82, 10, 70, 10, 31, + 47, 99, 111, 115, 109, 111, 115, 46, 99, 114, 121, 112, 116, 111, 46, 115, 101, 99, 112, + 50, 53, 54, 107, 49, 46, 80, 117, 98, 75, 101, 121, 18, 35, 10, 33, 3, 185, 116, 9, 72, + 116, 44, 202, 69, 71, 52, 114, 33, 78, 210, 187, 51, 206, 29, 125, 231, 178, 228, 13, + 138, 230, 163, 33, 114, 14, 214, 28, 212, 18, 4, 10, 2, 8, 1, 24, 184, 215, 1, 18, 65, + 10, 14, 10, 4, 117, 115, 101, 105, 18, 6, 51, 48, 48, 48, 48, 48, 16, 192, 141, 183, 1, + 34, 42, 115, 101, 105, 49, 122, 51, 114, 48, 99, 99, 115, 115, 115, 110, 118, 117, 97, + 104, 101, 117, 97, 107, 117, 108, 53, 56, 122, 108, 117, 54, 53, 114, 110, 103, 119, 55, + 110, 106, 114, 106, 99, 122, 26, 64, 149, 61, 175, 131, 175, 91, 106, 106, 66, 225, 99, + 170, 24, 61, 32, 138, 116, 119, 199, 204, 144, 193, 231, 139, 236, 226, 189, 39, 160, + 72, 104, 183, 108, 9, 253, 45, 17, 28, 158, 91, 188, 252, 20, 75, 13, 48, 8, 253, 45, + 67, 193, 181, 32, 24, 126, 152, 15, 242, 109, 18, 211, 225, 99, 16, + ]), + }, + }, + ]; + givenSeiBlockRepository(12312312312, txs); + givenMetadataRepository(); + givenStatsRepository(); + givenPollWormchainLogs(); + + await whenPollWormchainLogsStarts(); + + await thenWaitForAssertion( + () => expect(getRedeemsSpy).toHaveReturnedTimes(1), + () => + expect(getRedeemsSpy).toHaveBeenCalledWith( + 32, + "sei1smzlm9t79kur392nu9egl8p8je9j92q4gzguewj56a05kyxxra0qy0nuf3", + 20 + ), + () => expect(getBlockTimestampSpy).toHaveBeenCalledWith(80542798n) + ); + }); +}); + +const givenSeiBlockRepository = (timestamp?: number, txs: any = []) => { + seiRepo = { + getRedeems: () => Promise.resolve(txs), + getBlockTimestamp: () => Promise.resolve(timestamp), + }; + + getRedeemsSpy = jest.spyOn(seiRepo, "getRedeems"); + getBlockTimestampSpy = jest.spyOn(seiRepo, "getBlockTimestamp"); +}; + +const givenMetadataRepository = (data?: PollSeiMetadata) => { + metadataRepo = { + get: () => Promise.resolve(data), + save: () => Promise.resolve(), + }; + metadataSaveSpy = jest.spyOn(metadataRepo, "save"); +}; + +const givenStatsRepository = () => { + statsRepo = { + count: () => {}, + measure: () => {}, + report: () => Promise.resolve(""), + }; +}; + +const givenPollWormchainLogs = (from?: bigint) => { + cfg.setFromBlock(from); + pollSei = new PollSei(seiRepo, metadataRepo, statsRepo, cfg); +}; + +const whenPollWormchainLogsStarts = async () => { + pollSei.run([handlers.working]); +}; diff --git a/blockchain-watcher/test/infrastructure/mappers/sei/seiRedeemedTransactionFoundMapper.test.ts b/blockchain-watcher/test/infrastructure/mappers/sei/seiRedeemedTransactionFoundMapper.test.ts new file mode 100644 index 00000000..1f278aa5 --- /dev/null +++ b/blockchain-watcher/test/infrastructure/mappers/sei/seiRedeemedTransactionFoundMapper.test.ts @@ -0,0 +1,510 @@ +import { seiRedeemedTransactionFoundMapper } from "../../../../src/infrastructure/mappers/sei/seiRedeemedTransactionFoundMapper"; +import { describe, it, expect } from "@jest/globals"; +import { SeiRedeem } from "../../../../src/domain/entities/sei"; + +describe("seiRedeemedTransactionFoundMapper", () => { + it("should be able to map log to seiRedeemedTransactionFoundMapper", async () => { + // When + const result = seiRedeemedTransactionFoundMapper( + ["sei1smzlm9t79kur392nu9egl8p8je9j92q4gzguewj56a05kyxxra0qy0nuf3"], + log + ) as any; + + // Then + expect(result.name).toBe("transfer-redeemed"); + expect(result.chainId).toBe(32); + expect(result.txHash).toBe("7CC18417F02E8859A928A56E2080C9AFEC2C81AE206B388B025C034F686D63B8"); + expect(result.address).toBe("sei1smzlm9t79kur392nu9egl8p8je9j92q4gzguewj56a05kyxxra0qy0nuf3"); + expect(result.attributes.emitterAddress).toBe( + "ec7372995d5cc8732397fb0ad35c0121e0eaa90d26f828a534cab54391b3a4f5" + ); + expect(result.attributes.sequence).toBe(881252); + expect(result.attributes.protocol).toBe("Token Bridge"); + expect(result.attributes.emitterChain).toBe(1); + }); + + const log: SeiRedeem = { + chainId: 32, + events: [ + { + type: "use_feegrant", + attributes: [ + { + key: "Z3JhbnRlcg==", + value: "c2VpMXozcjBjY3Nzc252dWFoZXVha3VsNTh6bHU2NXJuZ3c3bmpyamN6", + index: true, + }, + { + key: "Z3JhbnRlZQ==", + value: "c2VpMXEzcjJ2OWo3cGYwcm1qODQ2aDNsYWtrODVydjZyMjV0bHBnNTl6", + index: true, + }, + ], + }, + { + type: "set_feegrant", + attributes: [ + { + key: "Z3JhbnRlcg==", + value: "c2VpMXozcjBjY3Nzc252dWFoZXVha3VsNTh6bHU2NXJuZ3c3bmpyamN6", + index: true, + }, + { + key: "Z3JhbnRlZQ==", + value: "c2VpMXEzcjJ2OWo3cGYwcm1qODQ2aDNsYWtrODVydjZyMjV0bHBnNTl6", + index: true, + }, + ], + }, + { + type: "coin_spent", + attributes: [ + { + key: "c3BlbmRlcg==", + value: "c2VpMXozcjBjY3Nzc252dWFoZXVha3VsNTh6bHU2NXJuZ3c3bmpyamN6", + index: true, + }, + { key: "YW1vdW50", value: "MzAwMDAwdXNlaQ==", index: true }, + ], + }, + { + type: "tx", + attributes: [ + { key: "ZmVl", value: "MzAwMDAwdXNlaQ==", index: true }, + { + key: "ZmVlX3BheWVy", + value: "c2VpMXozcjBjY3Nzc252dWFoZXVha3VsNTh6bHU2NXJuZ3c3bmpyamN6", + index: true, + }, + ], + }, + { + type: "tx", + attributes: [ + { + key: "YWNjX3NlcQ==", + value: "c2VpMXEzcjJ2OWo3cGYwcm1qODQ2aDNsYWtrODVydjZyMjV0bHBnNTl6LzI3NTc2", + index: true, + }, + ], + }, + { + type: "tx", + attributes: [ + { + key: "c2lnbmF0dXJl", + value: + "bFQydmc2OWJhbXBDNFdPcUdEMGdpblIzeDh5UXdlZUw3T0s5SjZCSWFMZHNDZjB0RVJ5ZVc3ejhGRXNOTUFqOUxVUEJ0U0FZZnBnUDhtMFMwK0ZqRUE9PQ==", + index: true, + }, + ], + }, + { + type: "signer", + attributes: [ + { + key: "ZXZtX2FkZHI=", + value: "MHg0NjZGMzU3OTNlNTc5MjMxM0JmRDQyZDhGQmE5MjI0MjExOUYzZGZE", + index: true, + }, + { + key: "c2VpX2FkZHI=", + value: "c2VpMXEzcjJ2OWo3cGYwcm1qODQ2aDNsYWtrODVydjZyMjV0bHBnNTl6", + index: true, + }, + ], + }, + { + type: "message", + attributes: [ + { + key: "YWN0aW9u", + value: "L2Nvc213YXNtLndhc20udjEuTXNnRXhlY3V0ZUNvbnRyYWN0", + index: true, + }, + ], + }, + { + type: "message", + attributes: [ + { key: "bW9kdWxl", value: "d2FzbQ==", index: true }, + { + key: "c2VuZGVy", + value: "c2VpMXEzcjJ2OWo3cGYwcm1qODQ2aDNsYWtrODVydjZyMjV0bHBnNTl6", + index: true, + }, + ], + }, + { + type: "execute", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + ], + }, + { + type: "wasm", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { key: "YWN0aW9u", value: "Y29tcGxldGVfdHJhbnNmZXJfd2l0aF9wYXlsb2Fk", index: true }, + { + key: "dHJhbnNmZXJfcGF5bG9hZA==", + value: + "ZXlKaVlYTnBZMTl5WldOcGNHbGxiblFpT25zaWNtVmphWEJwWlc1MElqb2lZekpXY0UxWE1UVk5NM0EyVGxSU2VHRnVXalJqUjJSNFdqSlZlbVZYZUcxa2FteDZXVmN3ZVdSWVNtNWphbHBxV1ZSQmVrNVhUVFFpZlgwPQ==", + index: true, + }, + ], + }, + { + type: "execute", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMXNtemxtOXQ3OWt1cjM5Mm51OWVnbDhwOGplOWo5MnE0Z3pndWV3ajU2YTA1a3l4eHJhMHF5MG51ZjM=", + index: true, + }, + ], + }, + { + type: "wasm", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMXNtemxtOXQ3OWt1cjM5Mm51OWVnbDhwOGplOWo5MnE0Z3pndWV3ajU2YTA1a3l4eHJhMHF5MG51ZjM=", + index: true, + }, + { key: "YWN0aW9u", value: "Y29tcGxldGVfdHJhbnNmZXJfd3JhcHBlZA==", index: true }, + { + key: "Y29udHJhY3Q=", + value: + "c2VpMXN6NTJ3NHVrMnk1ZGF0c2Mzamo2NHAwczh5YTV1OTNuNDNkMzloeDdzNDYzM2Vuc2NtenEyMHZseTc=", + index: true, + }, + { + key: "cmVjaXBpZW50", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { key: "YW1vdW50", value: "MjUwMDAwMDAw", index: true }, + { + key: "cmVsYXllcg==", + value: "c2VpMXEzcjJ2OWo3cGYwcm1qODQ2aDNsYWtrODVydjZyMjV0bHBnNTl6", + index: true, + }, + { key: "ZmVl", value: "MA==", index: true }, + ], + }, + { + type: "execute", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMXN6NTJ3NHVrMnk1ZGF0c2Mzamo2NHAwczh5YTV1OTNuNDNkMzloeDdzNDYzM2Vuc2NtenEyMHZseTc=", + index: true, + }, + ], + }, + { + type: "wasm", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMXN6NTJ3NHVrMnk1ZGF0c2Mzamo2NHAwczh5YTV1OTNuNDNkMzloeDdzNDYzM2Vuc2NtenEyMHZseTc=", + index: true, + }, + { key: "YWN0aW9u", value: "bWludA==", index: true }, + { + key: "dG8=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { key: "YW1vdW50", value: "MjUwMDAwMDAw", index: true }, + ], + }, + { + type: "reply", + attributes: [ + { + key: "X2NvbnRyYWN0X2FkZHJlc3M=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + ], + }, + { + type: "coin_received", + attributes: [ + { + key: "cmVjZWl2ZXI=", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "coinbase", + attributes: [ + { + key: "bWludGVy", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "coin_spent", + attributes: [ + { + key: "c3BlbmRlcg==", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "coin_received", + attributes: [ + { + key: "cmVjZWl2ZXI=", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "transfer", + attributes: [ + { + key: "cmVjaXBpZW50", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "c2VuZGVy", + value: "c2VpMTllank4bjlxc2VjdHJmNHNlbWRwOWNwa25mbGxkMGo2c3Z2bXRx", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "mint", + attributes: [ + { + key: "bWludF90b19hZGRyZXNz", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "coin_spent", + attributes: [ + { + key: "c3BlbmRlcg==", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "coin_received", + attributes: [ + { + key: "cmVjZWl2ZXI=", + value: "c2VpMW15M3p6NTRxanZ4cGdxZ2UzeWxmdjlzYW0ydXJncjZjYTAzNWM4", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + { + type: "transfer", + attributes: [ + { + key: "cmVjaXBpZW50", + value: "c2VpMW15M3p6NTRxanZ4cGdxZ2UzeWxmdjlzYW0ydXJncjZjYTAzNWM4", + index: true, + }, + { + key: "c2VuZGVy", + value: + "c2VpMTg5YWRndWF3dWdrM2U1NXpuNjN6OHI5bGwyOXhyandjYTYzNnJhN3Y3Z3h1em45OHN4eXF3enQ0N2w=", + index: true, + }, + { + key: "YW1vdW50", + value: + "MjUwMDAwMDAwZmFjdG9yeS9zZWkxODlhZGd1YXd1Z2szZTU1em42M3o4cjlsbDI5eHJqd2NhNjM2cmE3djdneHV6bjk4c3h5cXd6dDQ3bC85ZkVMdlVoRm82eVdMMzRaYUxnUGJDUHpkazlNRDF0QXpNeWNnSDQ1cVNoSA==", + index: true, + }, + ], + }, + ], + height: 79268744n, + data: "CiYKJC9jb3Ntd2FzbS53YXNtLnYxLk1zZ0V4ZWN1dGVDb250cmFjdA==", + hash: "7CC18417F02E8859A928A56E2080C9AFEC2C81AE206B388B025C034F686D63B8", + tx: Buffer.from([ + 10, 230, 13, 10, 180, 13, 10, 36, 47, 99, 111, 115, 109, 119, 97, 115, 109, 46, 119, 97, 115, + 109, 46, 118, 49, 46, 77, 115, 103, 69, 120, 101, 99, 117, 116, 101, 67, 111, 110, 116, 114, + 97, 99, 116, 18, 139, 13, 10, 42, 115, 101, 105, 49, 113, 51, 114, 50, 118, 57, 106, 55, 112, + 102, 48, 114, 109, 106, 56, 52, 54, 104, 51, 108, 97, 107, 107, 56, 53, 114, 118, 54, 114, 50, + 53, 116, 108, 112, 103, 53, 57, 122, 18, 62, 115, 101, 105, 49, 56, 57, 97, 100, 103, 117, 97, + 119, 117, 103, 107, 51, 101, 53, 53, 122, 110, 54, 51, 122, 56, 114, 57, 108, 108, 50, 57, + 120, 114, 106, 119, 99, 97, 54, 51, 54, 114, 97, 55, 118, 55, 103, 120, 117, 122, 110, 57, 56, + 115, 120, 121, 113, 119, 122, 116, 52, 55, 108, 26, 156, 12, 123, 34, 99, 111, 109, 112, 108, + 101, 116, 101, 95, 116, 114, 97, 110, 115, 102, 101, 114, 95, 97, 110, 100, 95, 99, 111, 110, + 118, 101, 114, 116, 34, 58, 123, 34, 118, 97, 97, 34, 58, 34, 65, 81, 65, 65, 65, 65, 81, 78, + 65, 80, 115, 111, 57, 97, 73, 43, 99, 65, 48, 100, 56, 70, 114, 74, 98, 74, 71, 101, 97, 71, + 70, 68, 113, 104, 49, 98, 81, 98, 87, 75, 79, 102, 68, 77, 70, 105, 111, 102, 69, 76, 102, + 111, 79, 103, 106, 102, 73, 118, 111, 87, 89, 83, 104, 55, 110, 53, 43, 48, 88, 82, 74, 68, + 84, 43, 113, 48, 102, 120, 121, 90, 66, 101, 115, 68, 73, 71, 85, 106, 50, 52, 80, 114, 107, + 88, 73, 65, 65, 85, 113, 121, 87, 122, 52, 110, 54, 104, 112, 77, 89, 75, 85, 122, 97, 103, + 53, 49, 56, 120, 121, 99, 66, 86, 76, 69, 50, 48, 51, 47, 88, 74, 85, 56, 65, 75, 70, 76, 101, + 118, 120, 101, 76, 71, 98, 55, 72, 48, 43, 113, 54, 53, 73, 105, 112, 53, 118, 56, 109, 116, + 70, 78, 78, 71, 88, 116, 104, 104, 119, 49, 81, 113, 83, 99, 114, 122, 119, 121, 77, 84, 67, + 107, 79, 85, 56, 65, 66, 74, 99, 106, 82, 78, 87, 70, 109, 105, 100, 112, 88, 84, 51, 75, 118, + 55, 68, 79, 103, 78, 120, 81, 57, 75, 50, 84, 78, 97, 106, 86, 121, 97, 111, 118, 81, 51, 120, + 78, 71, 86, 80, 82, 80, 86, 74, 117, 110, 68, 118, 71, 47, 89, 68, 90, 112, 106, 102, 110, 66, + 78, 67, 111, 99, 52, 106, 80, 102, 55, 79, 90, 52, 111, 119, 83, 102, 74, 65, 76, 111, 119, + 113, 43, 73, 70, 89, 65, 66, 113, 87, 67, 87, 65, 72, 67, 76, 82, 83, 122, 107, 65, 116, 112, + 106, 106, 82, 98, 73, 47, 56, 97, 110, 117, 97, 74, 85, 89, 114, 52, 47, 119, 66, 98, 72, 107, + 98, 71, 109, 89, 113, 87, 86, 53, 119, 117, 67, 104, 121, 49, 84, 105, 80, 103, 102, 118, 73, + 118, 76, 66, 78, 106, 71, 80, 99, 88, 65, 84, 49, 65, 48, 108, 111, 97, 79, 55, 110, 78, 52, + 47, 116, 52, 53, 83, 111, 66, 66, 55, 55, 99, 88, 113, 99, 117, 106, 49, 109, 118, 67, 121, + 99, 100, 121, 70, 65, 108, 80, 75, 69, 69, 78, 56, 55, 101, 101, 52, 50, 109, 112, 109, 50, + 56, 97, 98, 84, 80, 72, 72, 86, 83, 66, 100, 82, 80, 52, 77, 112, 57, 104, 111, 114, 53, 86, + 121, 120, 87, 121, 66, 47, 73, 48, 76, 84, 68, 88, 54, 82, 49, 71, 55, 102, 122, 77, 57, 52, + 71, 116, 70, 48, 121, 104, 73, 69, 65, 67, 69, 50, 102, 75, 86, 118, 118, 104, 117, 66, 49, + 118, 103, 84, 119, 86, 55, 82, 71, 78, 109, 114, 121, 76, 75, 89, 105, 52, 110, 74, 103, 65, + 119, 87, 116, 56, 71, 88, 113, 51, 55, 65, 43, 87, 99, 79, 117, 101, 102, 101, 70, 53, 53, 75, + 114, 90, 86, 101, 118, 71, 101, 99, 80, 115, 74, 114, 74, 72, 110, 90, 71, 114, 86, 99, 54, + 122, 86, 75, 110, 43, 105, 50, 118, 73, 43, 89, 65, 67, 98, 48, 88, 108, 100, 51, 67, 84, 49, + 65, 81, 83, 55, 51, 109, 101, 52, 79, 80, 119, 109, 72, 113, 52, 119, 76, 75, 71, 114, 77, 52, + 115, 89, 76, 78, 48, 87, 111, 70, 85, 49, 53, 51, 86, 103, 112, 90, 53, 110, 113, 110, 88, + 112, 117, 122, 122, 70, 71, 84, 90, 57, 88, 66, 116, 113, 51, 81, 111, 53, 102, 52, 116, 119, + 108, 116, 71, 57, 72, 104, 90, 101, 121, 47, 103, 80, 81, 66, 67, 110, 102, 112, 66, 99, 83, + 100, 107, 75, 69, 83, 50, 74, 80, 105, 109, 77, 107, 110, 84, 43, 112, 116, 68, 113, 50, 117, + 68, 100, 88, 50, 120, 77, 117, 114, 56, 85, 119, 83, 71, 50, 111, 82, 81, 122, 110, 77, 77, + 98, 81, 122, 114, 53, 115, 111, 53, 82, 72, 113, 71, 55, 48, 43, 74, 80, 89, 72, 104, 47, 105, + 108, 101, 79, 49, 86, 54, 75, 107, 75, 52, 69, 65, 57, 120, 120, 99, 65, 68, 88, 70, 88, 70, + 77, 104, 111, 69, 108, 116, 90, 86, 76, 47, 78, 108, 66, 97, 49, 115, 69, 50, 74, 117, 75, + 120, 67, 70, 81, 55, 56, 88, 54, 55, 81, 107, 87, 119, 119, 53, 108, 102, 69, 88, 111, 65, + 119, 47, 98, 118, 110, 117, 47, 115, 77, 74, 48, 99, 43, 86, 71, 84, 113, 83, 49, 99, 89, 77, + 69, 55, 98, 112, 111, 51, 56, 107, 51, 67, 52, 79, 115, 53, 114, 117, 117, 89, 66, 68, 107, + 76, 82, 90, 89, 52, 116, 85, 99, 120, 118, 75, 43, 106, 104, 65, 47, 51, 87, 86, 87, 110, 109, + 106, 103, 107, 98, 108, 68, 97, 112, 74, 109, 81, 50, 65, 69, 57, 88, 56, 100, 90, 88, 84, 90, + 50, 103, 111, 49, 54, 110, 71, 89, 76, 80, 97, 100, 43, 122, 43, 90, 74, 53, 107, 50, 57, 72, + 51, 102, 117, 69, 86, 71, 110, 99, 66, 87, 47, 65, 117, 69, 78, 98, 109, 114, 115, 66, 68, 43, + 99, 78, 109, 70, 97, 43, 49, 80, 87, 71, 51, 97, 105, 77, 102, 110, 105, 107, 101, 111, 98, + 111, 78, 122, 79, 102, 70, 102, 113, 43, 111, 76, 114, 118, 75, 72, 55, 116, 103, 114, 51, + 105, 68, 69, 119, 87, 69, 99, 101, 119, 83, 98, 55, 112, 79, 105, 111, 121, 88, 50, 69, 108, + 54, 78, 52, 114, 118, 85, 113, 112, 102, 82, 66, 84, 105, 103, 56, 109, 118, 86, 84, 99, 105, + 84, 77, 65, 69, 74, 90, 56, 115, 110, 90, 121, 113, 111, 122, 53, 83, 56, 85, 79, 76, 116, 67, + 121, 111, 102, 57, 100, 101, 83, 89, 72, 51, 48, 111, 105, 81, 98, 68, 84, 111, 90, 75, 97, + 72, 114, 83, 80, 70, 81, 55, 105, 47, 78, 107, 52, 122, 103, 98, 54, 50, 113, 104, 43, 120, + 98, 108, 88, 112, 87, 102, 52, 75, 112, 68, 68, 105, 87, 43, 53, 117, 54, 72, 88, 66, 89, 51, + 88, 74, 47, 115, 65, 69, 106, 115, 102, 75, 79, 113, 55, 68, 103, 109, 89, 116, 118, 73, 120, + 68, 100, 56, 66, 50, 98, 57, 122, 49, 116, 89, 68, 57, 122, 102, 100, 70, 49, 98, 107, 52, 85, + 112, 71, 86, 119, 83, 122, 70, 111, 80, 54, 55, 57, 81, 43, 103, 84, 75, 43, 120, 67, 49, 55, + 57, 51, 118, 80, 78, 65, 86, 116, 109, 76, 113, 81, 98, 84, 84, 54, 54, 115, 79, 81, 75, 111, + 79, 102, 112, 99, 107, 66, 90, 108, 86, 121, 116, 81, 65, 65, 103, 74, 115, 65, 65, 101, 120, + 122, 99, 112, 108, 100, 88, 77, 104, 122, 73, 53, 102, 55, 67, 116, 78, 99, 65, 83, 72, 103, + 54, 113, 107, 78, 74, 118, 103, 111, 112, 84, 84, 75, 116, 85, 79, 82, 115, 54, 84, 49, 65, + 65, 65, 65, 65, 65, 65, 78, 99, 109, 81, 103, 65, 119, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 79, 53, 114, 75, 65, 120, 118, 112, 54, 56, 55, 55, 98, 114, 84, 111, 57, 90, + 102, 78, 113, 113, 56, 108, 48, 77, 98, 71, 55, 53, 77, 76, 83, 57, 117, 68, 107, 102, 75, 89, + 67, 65, 48, 85, 118, 88, 87, 69, 65, 65, 84, 108, 54, 49, 72, 79, 117, 52, 105, 48, 99, 48, + 111, 75, 101, 111, 105, 79, 77, 118, 47, 113, 75, 89, 99, 110, 89, 55, 113, 79, 104, 57, 56, + 122, 121, 68, 99, 70, 77, 112, 52, 71, 73, 65, 67, 67, 57, 109, 108, 100, 84, 83, 52, 79, 83, + 86, 118, 117, 56, 74, 107, 121, 70, 70, 104, 79, 117, 104, 79, 43, 47, 100, 119, 87, 80, 51, + 99, 115, 56, 73, 84, 110, 103, 113, 89, 113, 82, 69, 110, 115, 105, 89, 109, 70, 122, 97, 87, + 78, 102, 99, 109, 86, 106, 97, 88, 66, 112, 90, 87, 53, 48, 73, 106, 112, 55, 73, 110, 74, + 108, 89, 50, 108, 119, 97, 87, 86, 117, 100, 67, 73, 54, 73, 109, 77, 121, 86, 110, 66, 78, + 86, 122, 69, 49, 84, 84, 78, 119, 78, 107, 53, 85, 85, 110, 104, 104, 98, 108, 111, 48, 89, + 48, 100, 107, 101, 70, 111, 121, 86, 88, 112, 108, 86, 51, 104, 116, 90, 71, 112, 115, 101, + 108, 108, 88, 77, 72, 108, 107, 87, 69, 112, 117, 89, 50, 112, 97, 97, 108, 108, 85, 81, 88, + 112, 79, 86, 48, 48, 48, 73, 110, 49, 57, 34, 125, 125, 18, 45, 87, 111, 114, 109, 104, 111, + 108, 101, 32, 45, 32, 67, 111, 109, 112, 108, 101, 116, 101, 32, 84, 111, 107, 101, 110, 32, + 84, 114, 97, 110, 115, 108, 97, 116, 111, 114, 32, 84, 114, 97, 110, 115, 102, 101, 114, 18, + 151, 1, 10, 82, 10, 70, 10, 31, 47, 99, 111, 115, 109, 111, 115, 46, 99, 114, 121, 112, 116, + 111, 46, 115, 101, 99, 112, 50, 53, 54, 107, 49, 46, 80, 117, 98, 75, 101, 121, 18, 35, 10, + 33, 3, 185, 116, 9, 72, 116, 44, 202, 69, 71, 52, 114, 33, 78, 210, 187, 51, 206, 29, 125, + 231, 178, 228, 13, 138, 230, 163, 33, 114, 14, 214, 28, 212, 18, 4, 10, 2, 8, 1, 24, 184, 215, + 1, 18, 65, 10, 14, 10, 4, 117, 115, 101, 105, 18, 6, 51, 48, 48, 48, 48, 48, 16, 192, 141, + 183, 1, 34, 42, 115, 101, 105, 49, 122, 51, 114, 48, 99, 99, 115, 115, 115, 110, 118, 117, 97, + 104, 101, 117, 97, 107, 117, 108, 53, 56, 122, 108, 117, 54, 53, 114, 110, 103, 119, 55, 110, + 106, 114, 106, 99, 122, 26, 64, 149, 61, 175, 131, 175, 91, 106, 106, 66, 225, 99, 170, 24, + 61, 32, 138, 116, 119, 199, 204, 144, 193, 231, 139, 236, 226, 189, 39, 160, 72, 104, 183, + 108, 9, 253, 45, 17, 28, 158, 91, 188, 252, 20, 75, 13, 48, 8, 253, 45, 67, 193, 181, 32, 24, + 126, 152, 15, 242, 109, 18, 211, 225, 99, 16, + ]), + }; +}); diff --git a/blockchain-watcher/test/infrastructure/mappers/wormchain/wormchainRedeemedTransactionFoundMapper.test.ts b/blockchain-watcher/test/infrastructure/mappers/wormchain/wormchainRedeemedTransactionFoundMapper.test.ts index 6240c6dd..10b0d3ae 100644 --- a/blockchain-watcher/test/infrastructure/mappers/wormchain/wormchainRedeemedTransactionFoundMapper.test.ts +++ b/blockchain-watcher/test/infrastructure/mappers/wormchain/wormchainRedeemedTransactionFoundMapper.test.ts @@ -10,9 +10,7 @@ describe("wormchainRedeemedTransactionFoundMapper", () => { // Then expect(result.name).toBe("transfer-redeemed"); expect(result.chainId).toBe(20); - expect(result.txHash).toBe( - "0xC196E9E445748AB4BE26E980F685F8F1FD02E8F327F9F1929CE5C426C936BF74" - ); + expect(result.txHash).toBe("C196E9E445748AB4BE26E980F685F8F1FD02E8F327F9F1929CE5C426C936BF74"); expect(result.address).toBe("osmo1hhzf9u376mg8zcuvx3jsls7t805kzcrsfsaydv"); expect(result.attributes.emitterAddress).toBe( "ccceeb29348f71bdd22ffef43a2a19c1f5b5e17c5cca5411529120182672ade5" diff --git a/blockchain-watcher/test/infrastructure/repositories/RepositoriesBuilder.test.ts b/blockchain-watcher/test/infrastructure/repositories/RepositoriesBuilder.test.ts index 26c3dd6f..9e9e17d6 100644 --- a/blockchain-watcher/test/infrastructure/repositories/RepositoriesBuilder.test.ts +++ b/blockchain-watcher/test/infrastructure/repositories/RepositoriesBuilder.test.ts @@ -9,11 +9,12 @@ import { describe, expect, it } from "@jest/globals"; import { RepositoriesBuilder } from "../../../src/infrastructure/repositories/RepositoriesBuilder"; import { configMock } from "../../mocks/configMock"; import { + RateLimitedSolanaSlotRepository, FileMetadataRepository, PromStatRepository, - RateLimitedSolanaSlotRepository, SnsEventRepository, } from "../../../src/infrastructure/repositories"; +import { RateLimitedSeiJsonRPCBlockRepository } from "../../../src/infrastructure/repositories/sei/RateLimitedSeiJsonRPCBlockRepository"; describe("RepositoriesBuilder", () => { it("should be throw error because dose not have any chain", async () => { @@ -123,5 +124,6 @@ describe("RepositoriesBuilder", () => { expect(repos.getWormchainRepository()).toBeInstanceOf( RateLimitedWormchainJsonRPCBlockRepository ); + expect(repos.getSeiRepository()).toBeInstanceOf(RateLimitedSeiJsonRPCBlockRepository); }); }); diff --git a/blockchain-watcher/test/infrastructure/repositories/StaticJobRepository.test.ts b/blockchain-watcher/test/infrastructure/repositories/StaticJobRepository.test.ts index 8d0e9f5b..ee7ff511 100644 --- a/blockchain-watcher/test/infrastructure/repositories/StaticJobRepository.test.ts +++ b/blockchain-watcher/test/infrastructure/repositories/StaticJobRepository.test.ts @@ -1,17 +1,18 @@ import { mockRpcPool } from "../../mocks/mockRpcPool"; mockRpcPool(); +import { SnsEventRepository, StaticJobRepository } from "../../../src/infrastructure/repositories"; import { beforeEach, describe, expect, it } from "@jest/globals"; import fs from "fs"; -import { SnsEventRepository, StaticJobRepository } from "../../../src/infrastructure/repositories"; import { - AptosRepository, + SolanaSlotRepository, + WormchainRepository, EvmBlockRepository, MetadataRepository, - SolanaSlotRepository, + AptosRepository, StatRepository, + SeiRepository, SuiRepository, - WormchainRepository, } from "../../../src/domain/repositories"; const dirPath = "./metadata-repo/jobs"; @@ -23,6 +24,7 @@ const solanaSlotRepo = {} as any as SolanaSlotRepository; const suiRepo = {} as any as SuiRepository; const aptosRepo = {} as any as AptosRepository; const wormchainRepo = {} as any as WormchainRepository; +const seiRepo = {} as any as SeiRepository; let repo: StaticJobRepository; @@ -39,6 +41,7 @@ describe("StaticJobRepository", () => { suiRepo, aptosRepo, wormchainRepo, + seiRepo, }); }); diff --git a/blockchain-watcher/test/mocks/configMock.ts b/blockchain-watcher/test/mocks/configMock.ts index 4e9d0ad6..0bf50bbd 100644 --- a/blockchain-watcher/test/mocks/configMock.ts +++ b/blockchain-watcher/test/mocks/configMock.ts @@ -122,6 +122,13 @@ export const configMock = (): Config => { rpcs: ["http://localhost"], timeout: 10000, }, + sei: { + name: "sei", + network: "mainnet", + chainId: 32, + rpcs: ["http://localhost"], + timeout: 10000, + }, scroll: { name: "scroll", network: "testnet", @@ -247,7 +254,7 @@ export const configMock = (): Config => { dir: "./metadata-repo/jobs", }, chains: chainsRecord, - enabledPlatforms: ["solana", "evm", "sui", "aptos", "wormchain"], + enabledPlatforms: ["solana", "evm", "sui", "aptos", "wormchain", "sei"], }; return cfg; diff --git a/deploy/blockchain-watcher/workers/target-events-3.yaml b/deploy/blockchain-watcher/workers/target-events-3.yaml index b71eb61e..059322e7 100644 --- a/deploy/blockchain-watcher/workers/target-events-3.yaml +++ b/deploy/blockchain-watcher/workers/target-events-3.yaml @@ -300,6 +300,39 @@ data: } } ] + }, + { + "id": "poll-redeemed-transactions-sei", + "chain": "sei", + "source": { + "action": "PollSei", + "config": { + "blockBatchSize": 20, + "commitment": "latest", + "interval": 60000, + "addresses": [ + "sei1smzlm9t79kur392nu9egl8p8je9j92q4gzguewj56a05kyxxra0qy0nuf3" + ], + "chain": "sei", + "chainId": 32 + } + }, + "handlers": [ + { + "action": "HandleSeiRedeems", + "target": "sns", + "mapper": "seiRedeemedTransactionFoundMapper", + "config": { + "abi": "", + "filter": { + "addresses": [ + "sei1smzlm9t79kur392nu9egl8p8je9j92q4gzguewj56a05kyxxra0qy0nuf3" + ] + }, + "metricName": "process_vaa_event" + } + } + ] } ] ---