trustless-generic-relayer/ethereum/ts-scripts/mockIntegration/messageUtils.ts

142 lines
4.3 KiB
TypeScript

import * as wh from "@certusone/wormhole-sdk"
import { Implementation__factory } from "@certusone/wormhole-sdk/lib/cjs/ethers-contracts"
import { LogMessagePublishedEvent } from "../../../sdk/src"
import {
ChainInfo,
getCoreRelayer,
getMockIntegration,
getMockIntegrationAddress,
} from "../helpers/env"
import * as grpcWebNodeHttpTransport from "@improbable-eng/grpc-web-node-http-transport"
import { ethers } from "ethers"
export async function sendMessage(
sourceChain: ChainInfo,
targetChain: ChainInfo,
fetchSignedVaa: boolean = false,
queryMessageOnTargetFlag: boolean = true
): Promise<boolean | undefined> {
console.log(
`Sending message from chain ${sourceChain.chainId} to ${targetChain.chainId}...`
)
const sourceRelayer = getCoreRelayer(sourceChain)
const relayQuote = await (
await sourceRelayer.quoteGas(
targetChain.chainId,
2000000,
await sourceRelayer.getDefaultRelayProvider()
)
).add(10000000000)
console.log("relay quote: " + relayQuote)
const mockIntegration = getMockIntegration(sourceChain)
const targetAddress = getMockIntegrationAddress(targetChain)
const sentMessage = "ID: " + String(Math.ceil(Math.random() * 10000))
console.log(`Sent message: ${sentMessage}`)
const tx = await mockIntegration.sendMessage(
Buffer.from(sentMessage),
targetChain.chainId,
targetAddress,
{
gasLimit: 1000000,
value: relayQuote,
}
)
const rx = await tx.wait()
const sequences = wh.parseSequencesFromLogEth(rx, sourceChain.wormholeAddress)
console.log("Tx hash: ", rx.transactionHash)
console.log(`Sequences: ${sequences}`)
if (fetchSignedVaa) {
for (let i = 0; i < 120; i++) {
try {
const vaa1 = await fetchVaaFromLog(rx.logs[0], sourceChain.chainId)
console.log(vaa1)
const vaa2 = await fetchVaaFromLog(rx.logs[1], sourceChain.chainId)
console.log(vaa2)
break
} catch (e) {
console.error(`${i} seconds`)
if (i === 0) {
console.error(e)
}
}
await new Promise((resolve) => setTimeout(resolve, 1_000))
}
}
if (queryMessageOnTargetFlag) {
return await queryMessageOnTarget(sentMessage, targetChain)
}
console.log("")
}
async function queryMessageOnTarget(
sentMessage: string,
targetChain: ChainInfo
): Promise<boolean> {
let messageHistory: string[][] = []
const targetIntegration = getMockIntegration(targetChain)
let notFound = true
for (let i = 0; i < 20 && notFound; i++) {
await new Promise<void>((resolve) => setTimeout(() => resolve(), 2000))
const messageHistoryResp = await targetIntegration.getMessageHistory()
messageHistory = messageHistoryResp.map((messages) =>
messages.map((message) => ethers.utils.toUtf8String(message))
)
notFound = !messageHistory
.slice(messageHistory.length - 20)
.find((msgs) => msgs.find((m) => m === sentMessage))
process.stdout.write("..")
}
console.log("")
if (notFound) {
console.log(`ERROR: Did not receive message!`)
return false
}
console.log(`Received message: ${messageHistory[messageHistory.length - 1][0]}`)
console.log(`Received messageHistory: ${messageHistory.join(", ")}`)
return true
}
export async function encodeEmitterAddress(
myChainId: wh.ChainId,
emitterAddressStr: string
): Promise<string> {
if (myChainId === wh.CHAIN_ID_SOLANA || myChainId === wh.CHAIN_ID_PYTHNET) {
return wh.getEmitterAddressSolana(emitterAddressStr)
}
if (wh.isTerraChain(myChainId)) {
return wh.getEmitterAddressTerra(emitterAddressStr)
}
if (wh.isEVMChain(myChainId)) {
return wh.getEmitterAddressEth(emitterAddressStr)
}
throw new Error(`Unrecognized wormhole chainId ${myChainId}`)
}
function fetchVaaFromLog(bridgeLog: any, chainId: wh.ChainId): Promise<wh.SignedVaa> {
const iface = Implementation__factory.createInterface()
const log = iface.parseLog(bridgeLog) as unknown as LogMessagePublishedEvent
const sequence = log.args.sequence.toString()
const emitter = wh.tryNativeToHexString(log.args.sender, "ethereum")
return wh
.getSignedVAA(
"https://wormhole-v2-testnet-api.certus.one",
chainId,
emitter,
sequence,
{ transport: grpcWebNodeHttpTransport.NodeHttpTransport() }
)
.then((r) => r.vaaBytes)
}
export async function sleep(ms: number) {
return new Promise((r) => setTimeout(r, ms))
}