Last active
September 25, 2024 08:36
-
-
Save zengzengzenghuy/0b22c6554dec6a25141c4616e1d39091 to your computer and use it in GitHub Desktop.
Hyperbridge script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require("log-timestamp"); | |
import { HyperClient, MessageStatusWithMeta } from "@polytope-labs/hyperclient"; | |
import { config } from "dotenv"; | |
import { | |
createPublicClient, | |
createWalletClient, | |
decodeFunctionData, | |
getContract, | |
http, | |
parseEventLogs, | |
} from "viem"; | |
import { privateKeyToAccount } from "viem/accounts"; | |
import { sepolia, gnosisChiado } from "viem/chains"; | |
import { ApiPromise, WsProvider } from "@polkadot/api"; | |
import Reporter_MODULE from "./abis/reporterModule"; | |
import EVM_HOST from "./abis/evmHost"; | |
import HANDLER from "./abis/handler"; | |
// sepolia Reporter | |
const Reporter_MODULE_ADDRESS = "0xbd21d63ccfd81242db0d84751fa838bf5dba3a36"; | |
// Chiado adapter | |
const Adapter_MODULE_ADDRESS = "0x59462f59Ab0A5EE90df9a34942FEB67d8a5e615E" | |
/* | |
Using a viem client, dispatches an onchain transaction to the Reporter module. | |
The Reporter module contract, dispatches an ISMP request to Hyperbridge. | |
Then tracks the resulting ISMP request using Hyperclient. | |
*/ | |
async function testPostAndGetRequest() { | |
const { | |
sepoliaClient, | |
SEPOLIA, | |
CHIADO, | |
gnosisChiadoHandler, | |
sepoliaReporter, | |
chiadoClient, | |
} = await setUp(); | |
const blockNumber = await sepoliaClient.getBlockNumber(); | |
console.log("Latest block number on sepolia: ", blockNumber); | |
console.log("Setting up hyperclient"); | |
const HyperbridgeConfig = { | |
// rpc_url: "ws://127.0.0.1:9001", | |
rpc_url: "wss://hyperbridge-paseo-rpc.blockops.network", | |
}; | |
const hyperclient = await HyperClient.init({ | |
source: SEPOLIA, | |
dest: CHIADO, | |
hyperbridge: HyperbridgeConfig, | |
indexer: "", | |
}); | |
console.log("Hyperclient init done") | |
const wsProvider = new WsProvider(HyperbridgeConfig.rpc_url); | |
const api = await ApiPromise.create({ provider: wsProvider }); | |
console.log("WS Setup done") | |
const height = ( | |
await api.query.ismp.latestStateMachineHeight({ | |
stateId: { | |
Evm: 10200, // chain ID of gnosisChiado | |
}, | |
consensusStateId: "ETH0", | |
}) | |
).toJSON() as number; | |
// This is a post request | |
const hash = await sepoliaReporter.write.dispatchBlocks([ | |
BigInt(10200), | |
"0x59462f59Ab0A5EE90df9a34942FEB67d8a5e615E", //adapter contract | |
[BigInt(blockNumber)-BigInt(1)] | |
],{}); // put an empty option here, otherwise will cause error in dispatchBlocks "expected 2 arguments, got 1" | |
const receipt = await sepoliaClient.waitForTransactionReceipt({ | |
hash, | |
confirmations: 1, | |
}); | |
console.log(`Transaction reciept: ${sepolia.blockExplorers.default.url}/tx/${hash}`); | |
console.log("Block: ", receipt.blockNumber); | |
// parse EvmHost PostRequestEvent emitted in the transcation logs | |
const event = parseEventLogs({ abi: EVM_HOST.ABI, logs: receipt.logs })[0]; | |
if (event.eventName !== "PostRequestEvent") { | |
throw new Error("Unexpected Event type"); | |
} | |
const request = event.args; | |
console.log({ request }); | |
const postRequest = { | |
...request, | |
txHeight: receipt.blockNumber, | |
}; | |
const status = await hyperclient.query_post_request_status(postRequest); | |
console.log("Request status: ", status); | |
const stream = await hyperclient.post_request_status_stream(postRequest); | |
console.log("Stream ", stream) | |
for await (const item of stream) { | |
let status: MessageStatusWithMeta; | |
if (item instanceof Map) { | |
status = Object.fromEntries((item as any).entries()) as MessageStatusWithMeta; | |
} else { | |
status = item; | |
} | |
console.log({ status }); | |
switch (status.kind) { | |
case "SourceFinalized": { | |
console.log( | |
`Status ${status.kind}, Transaction: https://gargantua.statescan.io/#/extrinsics/${status.transaction_hash}`, | |
); | |
break; | |
} | |
case "HyperbridgeDelivered": { | |
console.log( | |
`Status ${status.kind}, Transaction: https://gargantua.statescan.io/#/extrinsics/${status.transaction_hash}`, | |
); | |
break; | |
} | |
case "HyperbridgeFinalized": { | |
console.log( | |
`Status ${status.kind}, Transaction: https://sepolia-CHIADOtimism.etherscan.io/tx/${status.transaction_hash}`, | |
); | |
const { args, functionName } = decodeFunctionData({ | |
abi: HANDLER.ABI, | |
data: status.calldata, | |
}); | |
try { | |
const hash = await gnosisChiadoHandler.write.handlePostRequests(args as any); | |
await chiadoClient.waitForTransactionReceipt({ | |
hash, | |
confirmations: 1, | |
}); | |
console.log(`Transaction submitted: https://gnosis-chiado.blockscout.com/tx/${hash}`); | |
} catch (e) { | |
console.error("Error self-relaying: ", e); | |
} | |
break; | |
} | |
case "DestinationDelivered": { | |
console.log( | |
`Status ${status.kind}, Transaction: https://gnosis-chiado.blockscout.com/tx/${status.transaction_hash}`, | |
); | |
return; | |
} | |
} | |
} | |
} | |
async function setUp() { | |
const account = privateKeyToAccount(process.env.PRIVATE_KEY as any); | |
const sepoliaWalletClient = createWalletClient({ | |
chain: sepolia, | |
account, | |
transport: http(), | |
}); | |
const chiadoWalletClient = createWalletClient({ | |
chain: gnosisChiado, | |
account, | |
transport: http(), | |
}); | |
const sepoliaClient = createPublicClient({ | |
chain: sepolia, | |
transport: http(), | |
}); | |
const chiadoClient = createPublicClient({ | |
chain: gnosisChiado, | |
transport: http(), | |
}); | |
const sepoliaReporter = getContract({ | |
address: Reporter_MODULE_ADDRESS, | |
abi: Reporter_MODULE.ABI, | |
client: { public: sepoliaClient, wallet: sepoliaWalletClient }, | |
}); | |
const sepoliaIsmpHostAddress = await sepoliaReporter.read.host(); | |
const sepoliaIsmpHost = getContract({ | |
address: sepoliaIsmpHostAddress, | |
abi: EVM_HOST.ABI, | |
client: sepoliaClient, | |
}); | |
const sepoliaHostParams = await sepoliaIsmpHost.read.hostParams(); | |
const sepoliaHandler = getContract({ | |
address: sepoliaHostParams.handler, | |
abi: HANDLER.ABI, | |
client: { public: sepoliaClient, wallet: sepoliaWalletClient }, | |
}); | |
const chiadoAdapterContract = getContract({ | |
address: Adapter_MODULE_ADDRESS, | |
abi: Reporter_MODULE.ABI, | |
client: chiadoClient, | |
}); | |
const gnosisChiadoIsmpHostAddress = await chiadoAdapterContract.read.host(); | |
const gnosisChiadoIsmpHost = getContract({ | |
address: gnosisChiadoIsmpHostAddress, | |
abi: EVM_HOST.ABI, | |
client: { public: chiadoClient, wallet: chiadoWalletClient }, | |
}); | |
const gnosisChiadoHostParams = await gnosisChiadoIsmpHost.read.hostParams(); | |
const gnosisChiadoHandler = getContract({ | |
address: gnosisChiadoHostParams.handler, | |
abi: HANDLER.ABI, | |
client: { public: chiadoClient, wallet: chiadoWalletClient }, | |
}); | |
const SEPOLIA = { | |
rpc_url: process.env.SEPOLIA_URL!, | |
consensus_state_id: "ETH0", | |
host_address: sepoliaIsmpHostAddress, | |
state_machine: await sepoliaIsmpHost.read.host(), | |
}; | |
const CHIADO = { | |
rpc_url: process.env.CHIADO_URL!, | |
consensus_state_id: "ETH0", | |
host_address: gnosisChiadoIsmpHostAddress, | |
state_machine: await gnosisChiadoIsmpHost.read.host(), | |
}; | |
return { | |
sepoliaClient, | |
account, | |
SEPOLIA, | |
CHIADO, | |
gnosisChiadoHandler, | |
sepoliaHandler, | |
sepoliaReporter, | |
chiadoClient, | |
chiadoWalletClient, | |
gnosisChiadoIsmpHost, | |
}; | |
} | |
config(); | |
testPostAndGetRequest(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment