This commit is contained in:
julian merlo 2024-03-25 09:53:34 -03:00
parent 61283100be
commit 1cead33153
7 changed files with 355 additions and 15 deletions

View File

@ -125,7 +125,7 @@
},
"wormchain": {
"network": "mainnet",
"rpcs": ["https://wormchain-rpc.quickapi.com"]
"rpcs": ["https://tncnt-eu-wormchain-main-01.rpc.p2p.world"]
}
}
}

View File

@ -5,5 +5,12 @@ export * from "./evm/PollEvm";
export * from "./evm/types";
export * from "./solana/GetSolanaTransactions";
export * from "./solana/PollSolanaTransactions";
export * from "./wormchain/HandleWormchainLogs";
export * from "./wormchain/GetWormchainLogs";
export * from "./wormchain/PollWormchain";
export * from "./aptos/GetAptosTransactions";
export * from "./aptos/GetAptosTransactionsByEvents";
export * from "./aptos/HandleAptosTransactions";
export * from "./aptos/PollAptos";
export * from "./RunPollingJob";
export * from "./StartJobs";

View File

@ -39,7 +39,7 @@ export class GetWormchainLogs {
}
private populateLog(opts: GetWormchainOpts, fromBlock: bigint, toBlock: bigint): string {
return `[addresses:${opts.addresses}][topics:${opts.topics}][blocks:${fromBlock} - ${toBlock}]`;
return `[addresses:${opts.addresses}][blocks:${fromBlock} - ${toBlock}]`;
}
}

View File

@ -216,9 +216,9 @@ export class PollWormchainLogsConfig {
return this.props.chainId;
}
static fromBlock(chain: string, fromBlock: bigint) {
static fromBlock(fromBlock: bigint) {
return new PollWormchainLogsConfig({
chain,
chain: "wormchain",
fromBlock,
addresses: [],
topics: [],

View File

@ -2,20 +2,19 @@ import { LogFoundEvent, LogMessagePublished } from "../../../domain/entities";
import { WormchainLog } from "../../../domain/entities/wormchain";
import winston from "winston";
const CHAIN_ID_WORMCHAIN = 22;
const CHAIN_ID_WORMCHAIN = 3104;
const CORE_ADDRESS = "wormhole1ufs3tlq4umljk0qfe8k5ya0x6hpavn897u2cnf9k0en9jr7qarqqaqfk2j";
let logger: winston.Logger = winston.child({ module: "wormchainLogMessagePublishedMapper" });
export const wormchainLogMessagePublishedMapper = (
log: WormchainLog,
parsedArgs: ReadonlyArray<any>
log: WormchainLog
): LogFoundEvent<LogMessagePublished> | undefined => {
const { coreContract, sequence, emitter, hash } = transactionAttibutes(log);
const { coreContract, sequence, payload, emitter, nonce, hash } = transactionAttibutes(log);
if (coreContract && sequence && emitter && hash) {
if (coreContract && sequence && payload && emitter && payload && nonce && hash) {
logger.info(
`[wormchain] Source event info: [tx: ][emitterChain: ${CHAIN_ID_WORMCHAIN}][sender: }}][sequence: ]`
`[wormchain] Source event info: [tx: ${hash}][emitterChain: ${CHAIN_ID_WORMCHAIN}][sender: ${emitter} }}][sequence: ${sequence} ]`
);
return {
@ -28,9 +27,9 @@ export const wormchainLogMessagePublishedMapper = (
attributes: {
sender: emitter,
sequence: sequence,
payload: parsedArgs[3],
nonce: parsedArgs[2],
consistencyLevel: parsedArgs[4],
payload: payload,
nonce: nonce,
consistencyLevel: 0,
},
};
}
@ -39,7 +38,9 @@ export const wormchainLogMessagePublishedMapper = (
function transactionAttibutes(log: WormchainLog): TransactionAttributes {
let coreContract;
let sequence;
let payload;
let emitter;
let nonce;
let hash;
log.transactions?.forEach((tx) => {
@ -50,11 +51,18 @@ function transactionAttibutes(log: WormchainLog): TransactionAttributes {
const value = Buffer.from(attr.value, "base64").toString().toLowerCase();
switch (key) {
case "message.sequence":
console.log(key, value);
sequence = Number(value);
break;
case "message.message":
payload = value;
break;
case "message.sender":
emitter = value;
break;
case "message.sequence":
sequence = Number(value);
case "message.nonce":
nonce = Number(value);
break;
case "_contract_address":
case "contract_address":
@ -69,7 +77,9 @@ function transactionAttibutes(log: WormchainLog): TransactionAttributes {
return {
coreContract,
sequence,
payload,
emitter,
nonce,
hash,
};
}
@ -77,6 +87,8 @@ function transactionAttibutes(log: WormchainLog): TransactionAttributes {
type TransactionAttributes = {
coreContract: boolean | undefined;
sequence: number | undefined;
payload: string | undefined;
emitter: string | undefined;
nonce: number | undefined;
hash: string | undefined;
};

View File

@ -0,0 +1,150 @@
import { afterEach, describe, it, expect, jest } from "@jest/globals";
import {
PollEvmLogsConfig,
PollWormchain,
PollWormchainLogsConfig,
PollWormchainLogsMetadata,
} from "../../../../src/domain/actions";
import {
MetadataRepository,
StatRepository,
WormchainRepository,
} from "../../../../src/domain/repositories";
import { EvmBlock, EvmLog, ReceiptTransaction } from "../../../../src/domain/entities";
import { thenWaitForAssertion } from "../../../wait-assertion";
let cfg = PollWormchainLogsConfig.fromBlock(7626734n);
let getBlockHeightSpy: jest.SpiedFunction<WormchainRepository["getBlockHeight"]>;
let getBlockLogsSpy: jest.SpiedFunction<WormchainRepository["getBlockLogs"]>;
let handlerSpy: jest.SpiedFunction<(logs: EvmLog[]) => Promise<void>>;
let metadataSaveSpy: jest.SpiedFunction<MetadataRepository<PollWormchainLogsMetadata>["save"]>;
let metadataRepo: MetadataRepository<PollWormchainLogsMetadata>;
let wormchainBlockRepo: WormchainRepository;
let statsRepo: StatRepository;
let handlers = {
working: (logs: EvmLog[]) => Promise.resolve(),
failing: (logs: EvmLog[]) => Promise.reject(),
};
let pollWormchain: PollWormchain;
describe("PollWormchain", () => {
afterEach(async () => {
await pollWormchain.stop();
});
it("should be able to read logs from latest block when no fromBlock is configured", async () => {
const currentHeight = 10n;
const logs = {
transactions: [
{
hash: "0x47a54890a16ea9d924c32a1fa6fd1cf39176be532c8ba454d33f628d89be3388",
type: "wasm",
attributes: [
{
key: "X2NvbnRyYWN0X2FkZHJlc3M=",
value:
"d29ybWhvbGUxNGhqMnRhdnE4ZnBlc2R3eHhjdTQ0cnR5M2hoOTB2aHVqcnZjbXN0bDR6cjN0eG1mdnc5c3JyZzQ2NQ==",
index: true,
},
{ key: "YWN0aW9u", value: "c3VibWl0X29ic2VydmF0aW9ucw==", index: true },
{
key: "b3duZXI=",
value: "d29ybWhvbGUxOHl3NmY4OHA3Znc2bTk5eDlrbnJmejNwMHk2OTNoaDBhaDh5Mm0=",
index: true,
},
],
},
{
hash: "0x56e974e33c5c7403d23a5fe7fa414d9f1d6dd4f1b67601342100093c604b5d70",
type: "wasm",
attributes: [
{
key: "X2NvbnRyYWN0X2FkZHJlc3M=",
value:
"d29ybWhvbGUxNGhqMnRhdnE4ZnBlc2R3eHhjdTQ0cnR5M2hoOTB2aHVqcnZjbXN0bDR6cjN0eG1mdnc5c3JyZzQ2NQ==",
index: true,
},
{ key: "YWN0aW9u", value: "c3VibWl0X29ic2VydmF0aW9ucw==", index: true },
{
key: "b3duZXI=",
value: "d29ybWhvbGUxYWNxYTV2bDJudW5oc250djBldGpzNnllZTN2NnZjOGw5bTRxOGU=",
index: true,
},
],
},
],
blockHeight: "7626735",
timestamp: 1711143216257,
};
givenEvmBlockRepository(currentHeight, logs);
givenMetadataRepository();
givenStatsRepository();
givenPollWormchainLogs();
await whenPollWormchainLogsStarts();
await thenWaitForAssertion(
() => expect(getBlockHeightSpy).toHaveReturnedTimes(1),
() => expect(getBlockLogsSpy).toHaveBeenCalledWith(currentHeight)
);
});
it("should be return an empty array because to block is more greater than from block", async () => {
const currentHeight = 10n;
givenEvmBlockRepository(currentHeight);
givenMetadataRepository({ lastBlock: 15n });
givenStatsRepository();
givenPollWormchainLogs();
await whenPollWormchainLogsStarts();
await thenWaitForAssertion(() => expect(getBlockHeightSpy).toHaveReturnedTimes(1));
});
});
const givenEvmBlockRepository = (height?: bigint, logs: any = []) => {
wormchainBlockRepo = {
getBlockHeight: () => Promise.resolve(height),
getBlockLogs: () => Promise.resolve(logs),
};
getBlockHeightSpy = jest.spyOn(wormchainBlockRepo, "getBlockHeight");
getBlockLogsSpy = jest.spyOn(wormchainBlockRepo, "getBlockLogs");
handlerSpy = jest.spyOn(handlers, "working");
};
const givenMetadataRepository = (data?: PollWormchainLogsMetadata) => {
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);
pollWormchain = new PollWormchain(
wormchainBlockRepo,
metadataRepo,
statsRepo,
cfg,
"GetWormchainLogs"
);
};
const whenPollWormchainLogsStarts = async () => {
pollWormchain.run([handlers.working]);
};

View File

@ -0,0 +1,171 @@
import { wormchainLogMessagePublishedMapper } from "../../../../src/infrastructure/mappers/wormchain/wormchainLogMessagePublishedMapper";
import { describe, it, expect } from "@jest/globals";
import { WormchainLog } from "../../../../src/domain/entities/wormchain";
describe("wormchainLogMessagePublishedMapper", () => {
it("should be able to map log to aptosLogMessagePublishedMapper", async () => {
// When
const result = wormchainLogMessagePublishedMapper(log);
if (result) {
// Then
expect(result.name).toBe("log-message-published");
expect(result.chainId).toBe(3104);
expect(result.txHash).toBe(
"0xa08b0ac6ee67e21d3dd89f48f60cc907fc867288f4439bcf72731b0884d8aff2"
);
expect(result.address).toBe(
"wormhole1ufs3tlq4umljk0qfe8k5ya0x6hpavn897u2cnf9k0en9jr7qarqqaqfk2j"
);
expect(result.attributes.consistencyLevel).toBe(0);
expect(result.attributes.nonce).toBe(7671);
expect(result.attributes.payload).toBe(
"0100000000000000000000000000000000000000000000000000000000555643a3f5edec8471c75624ebc4079a634326d96a689e6157d79abe8f5a6f94472853bc00018622b98735cb870ae0cb22bd4ea58cfb512bd4002247ccd0b250eb6d0c5032fc00010000000000000000000000000000000000000000000000000000000000000000"
);
expect(result.attributes.sender).toBe(
"aeb534c45c3049d380b9d9b966f9895f53abd4301bfaff407fa09dea8ae7a924"
);
expect(result.attributes.sequence).toBe(28603);
}
});
});
const log: WormchainLog = {
transactions: [
{
hash: "0x987e77d2d8cf8b9c0b3998dc62dc94fad9de47c4e3b50ad9bfd3083d7ab958ff",
type: "wasm",
attributes: [
{
key: "X2NvbnRyYWN0X2FkZHJlc3M=",
value:
"d29ybWhvbGUxNGhqMnRhdnE4ZnBlc2R3eHhjdTQ0cnR5M2hoOTB2aHVqcnZjbXN0bDR6cjN0eG1mdnc5c3JyZzQ2NQ==",
index: true,
},
{ key: "YWN0aW9u", value: "c3VibWl0X29ic2VydmF0aW9ucw==", index: true },
{
key: "b3duZXI=",
value: "d29ybWhvbGUxODc4a3h6M3VnZXN2YTRoNGtmeng2Y3F0ZHk5NmN3d2RqajBwaHc=",
index: true,
},
],
},
{
hash: "0xa08b0ac6ee67e21d3dd89f48f60cc907fc867288f4439bcf72731b0884d8aff2",
type: "wasm",
attributes: [
{
key: "X2NvbnRyYWN0X2FkZHJlc3M=",
value:
"d29ybWhvbGUxajYydGt5cWhqeWpscXN5MzB1bnVhcW5uZDhkdDV3cXFucndqemYwZms3bnc0dzdkeHBzcWhheWFuZw==",
index: true,
},
{ key: "YWN0aW9u", value: "aW5jcmVhc2VfYWxsb3dhbmNl", index: true },
{ key: "YW1vdW50", value: "MTQzMTcxNjc3MQ==", index: true },
{
key: "b3duZXI=",
value:
"d29ybWhvbGUxNGVqcWp5cTh1bTRwM3hmcWo3NHlsZDV3YXFsamY4OGZ6MjV5eG5tYTBjbmdzcHhlM2xlczAwZnBqeA==",
index: true,
},
{
key: "c3BlbmRlcg==",
value:
"d29ybWhvbGUxNDY2bmYzenV4cHlhOHE5ZW14dWtkN3ZmdGFmNmg0cHNyMGEwN3NybDV6dzc0emg4NHlqcTRseWptaA==",
index: true,
},
],
},
{
hash: "0xa08b0ac6ee67e21d3dd89f48f60cc907fc867288f4439bcf72731b0884d8aff2",
type: "wasm",
attributes: [
{
key: "X2NvbnRyYWN0X2FkZHJlc3M=",
value:
"d29ybWhvbGUxNDY2bmYzenV4cHlhOHE5ZW14dWtkN3ZmdGFmNmg0cHNyMGEwN3NybDV6dzc0emg4NHlqcTRseWptaA==",
index: true,
},
{ key: "dHJhbnNmZXIuYW1vdW50", value: "MTQzMTcxNjc3MQ==", index: true },
{ key: "dHJhbnNmZXIuYmxvY2tfdGltZQ==", value: "MTcxMTE0MzIyMg==", index: true },
{ key: "dHJhbnNmZXIubm9uY2U=", value: "NzY3MQ==", index: true },
{
key: "dHJhbnNmZXIucmVjaXBpZW50",
value:
"ODYyMmI5ODczNWNiODcwYWUwY2IyMmJkNGVhNThjZmI1MTJiZDQwMDIyNDdjY2QwYjI1MGViNmQwYzUwMzJmYw==",
index: true,
},
{ key: "dHJhbnNmZXIucmVjaXBpZW50X2NoYWlu", value: "MQ==", index: true },
{
key: "dHJhbnNmZXIuc2VuZGVy",
value:
"YWU2NDA5MTAwN2U2ZWExODk5MjA5N2FhNGZiNjhlZTgzZjI0OWNlOTEyYTg0MzRmN2Q3ZTI2ODgwNGQ5OGZmMw==",
index: true,
},
{
key: "dHJhbnNmZXIudG9rZW4=",
value:
"ZjVlZGVjODQ3MWM3NTYyNGViYzQwNzlhNjM0MzI2ZDk2YTY4OWU2MTU3ZDc5YWJlOGY1YTZmOTQ0NzI4NTNiYw==",
index: true,
},
{ key: "dHJhbnNmZXIudG9rZW5fY2hhaW4=", value: "MQ==", index: true },
],
},
{
hash: "0xa08b0ac6ee67e21d3dd89f48f60cc907fc867288f4439bcf72731b0884d8aff2",
type: "wasm",
attributes: [
{
key: "X2NvbnRyYWN0X2FkZHJlc3M=",
value:
"d29ybWhvbGUxajYydGt5cWhqeWpscXN5MzB1bnVhcW5uZDhkdDV3cXFucndqemYwZms3bnc0dzdkeHBzcWhheWFuZw==",
index: true,
},
{ key: "YWN0aW9u", value: "YnVybl9mcm9t", index: true },
{ key: "YW1vdW50", value: "MTQzMTcxNjc3MQ==", index: true },
{
key: "Ynk=",
value:
"d29ybWhvbGUxNDY2bmYzenV4cHlhOHE5ZW14dWtkN3ZmdGFmNmg0cHNyMGEwN3NybDV6dzc0emg4NHlqcTRseWptaA==",
index: true,
},
{
key: "ZnJvbQ==",
value:
"d29ybWhvbGUxNGVqcWp5cTh1bTRwM3hmcWo3NHlsZDV3YXFsamY4OGZ6MjV5eG5tYTBjbmdzcHhlM2xlczAwZnBqeA==",
index: true,
},
],
},
{
hash: "0xa08b0ac6ee67e21d3dd89f48f60cc907fc867288f4439bcf72731b0884d8aff2",
type: "wasm",
attributes: [
{
key: "X2NvbnRyYWN0X2FkZHJlc3M=",
value:
"d29ybWhvbGUxdWZzM3RscTR1bWxqazBxZmU4azV5YTB4NmhwYXZuODk3dTJjbmY5azBlbjlqcjdxYXJxcWFxZmsyag==",
index: true,
},
{ key: "bWVzc2FnZS5ibG9ja190aW1l", value: "MTcxMTE0MzIyMg==", index: true },
{ key: "bWVzc2FnZS5jaGFpbl9pZA==", value: "MzEwNA==", index: true },
{
key: "bWVzc2FnZS5tZXNzYWdl",
value:
"MDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDU1NTY0M2EzZjVlZGVjODQ3MWM3NTYyNGViYzQwNzlhNjM0MzI2ZDk2YTY4OWU2MTU3ZDc5YWJlOGY1YTZmOTQ0NzI4NTNiYzAwMDE4NjIyYjk4NzM1Y2I4NzBhZTBjYjIyYmQ0ZWE1OGNmYjUxMmJkNDAwMjI0N2NjZDBiMjUwZWI2ZDBjNTAzMmZjMDAwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA=",
index: true,
},
{ key: "bWVzc2FnZS5ub25jZQ==", value: "NzY3MQ==", index: true },
{
key: "bWVzc2FnZS5zZW5kZXI=",
value:
"YWViNTM0YzQ1YzMwNDlkMzgwYjlkOWI5NjZmOTg5NWY1M2FiZDQzMDFiZmFmZjQwN2ZhMDlkZWE4YWU3YTkyNA==",
index: true,
},
{ key: "bWVzc2FnZS5zZXF1ZW5jZQ==", value: "Mjg2MDM=", index: true },
],
},
],
blockHeight: 7626736n,
timestamp: 1711143222043,
};