| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- import { parseVaa } from "@certusone/wormhole-sdk";
- import {
- DataSource,
- EvmExecute,
- decodeGovernancePayload,
- } from "xc_admin_common";
- import { DefaultStore } from "./store";
- import { PrivateKey, TxResult } from "./base";
- import { EvmExecutorContract } from "./contracts";
- import { EvmChain } from "./chains";
- // TODO: A better place for this would be `base.ts`. That will require
- // significant refactor. Todo in separate PR.
- interface GovernanceContract {
- getId(): string;
- getGovernanceDataSource(): Promise<DataSource>;
- getLastExecutedGovernanceSequence(): Promise<number>;
- executeGovernanceInstruction(
- senderPrivateKey: PrivateKey,
- vaa: Buffer
- ): Promise<TxResult>;
- }
- async function executeForGovernanceContract(
- contract: GovernanceContract,
- vaa: Buffer,
- senderPrivateKey: PrivateKey
- ) {
- const parsedVaa = parseVaa(vaa);
- const governanceSource = await contract.getGovernanceDataSource();
- if (
- governanceSource.emitterAddress ===
- parsedVaa.emitterAddress.toString("hex") &&
- governanceSource.emitterChain === parsedVaa.emitterChain
- ) {
- const lastExecutedSequence =
- await contract.getLastExecutedGovernanceSequence();
- if (lastExecutedSequence >= parsedVaa.sequence) {
- console.log(
- `Skipping on contract ${contract.getId()} as it was already executed`
- );
- return;
- }
- const { id } = await contract.executeGovernanceInstruction(
- senderPrivateKey,
- vaa
- );
- console.log(`Executed on contract ${contract.getId()} with txHash: ${id}`);
- }
- }
- /**
- * A general executor that tries to find any contract that can execute a given VAA and executes it
- * @param senderPrivateKey the private key to execute the governance instruction with
- * @param vaa the VAA to execute
- */
- export async function executeVaa(senderPrivateKey: PrivateKey, vaa: Buffer) {
- const parsedVaa = parseVaa(vaa);
- const action = decodeGovernancePayload(parsedVaa.payload);
- if (!action) return; //TODO: handle other actions
- if (action instanceof EvmExecute) {
- for (const chain of Object.values(DefaultStore.chains)) {
- if (
- chain instanceof EvmChain &&
- chain.wormholeChainName === action.targetChainId
- ) {
- const executorContract = new EvmExecutorContract(
- chain,
- action.executorAddress
- );
- await executeForGovernanceContract(
- executorContract,
- vaa,
- senderPrivateKey
- );
- }
- }
- } else {
- for (const contract of Object.values(DefaultStore.contracts)) {
- if (
- action.targetChainId === "unset" ||
- contract.getChain().wormholeChainName === action.targetChainId
- )
- await executeForGovernanceContract(contract, vaa, senderPrivateKey);
- }
- }
- }
|