Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion relayer-cli/.env.dist
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ TRANSACTION_BATCHER_CONTRACT_SEPOLIA=0xe7953da7751063d0a41ba727c32c762d3523ade8
TRANSACTION_BATCHER_CONTRACT_CHIADO=0xcC0a08D4BCC5f91ee9a1587608f7a2975EA75d73

# Ensure the path ends with a trailing slash ("/")
STATE_DIR="/home/user/vea/relayer-cli/state/"
STATE_DIR="/home/user/vea/relayer-cli/state/"

# Hashi Executor enabler
HASHI_EXECUTOR_ENABLED=true
12 changes: 12 additions & 0 deletions relayer-cli/src/consts/bridgeRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ interface IBridge {
epochPeriod: number;
veaContracts: { [key in Network]: VeaContracts };
batcherAddress: string;
rpcInbox: string;
rpcOutbox: string;
yahoAddress?: string; // Hashi (Yaru) contract address
yaruAddress?: string; // Hashi (Yaru) contract address
hashiAddress?: string; // Hashi (Yaru) contract address
}

type VeaContracts = {
Expand Down Expand Up @@ -60,15 +64,23 @@ const bridges: { [chainId: number]: IBridge } = {
epochPeriod: 7200,
veaContracts: arbToEthContracts,
batcherAddress: process.env.TRANSACTION_BATCHER_CONTRACT_SEPOLIA!,
rpcInbox: process.env.RPC_ARBITRUM_SEPOLIA!,
rpcOutbox: process.env.RPC_SEPOLIA!,
yahoAddress: "0xDbdF80c87f414fac8342e04D870764197bD3bAC7", // Hashi (Yaho) contract address on Arbitrum Sepolia
yaruAddress: "0x231e48AAEaAC6398978a1dBA4Cd38fcA208Ec391", // Hashi (Yaru) contract address on Sepolia
hashiAddress: "0x78E4ae687De18B3B71Ccd0e8a3A76Fed49a02A02", // Hashi (Hashi) contract address on Sepolia
},
10200: {
chainId: 10200,
chain: "chiado",
epochPeriod: 3600,
veaContracts: arbToGnosisContracts,
batcherAddress: process.env.TRANSACTION_BATCHER_CONTRACT_CHIADO!,
rpcInbox: process.env.RPC_ARBITRUM_SEPOLIA!,
rpcOutbox: process.env.RPC_CHIADO!,
yahoAddress: "0xDbdF80c87f414fac8342e04D870764197bD3bAC7", // Hashi (Yaho) contract address on Arbitrum Sepolia
yaruAddress: "0x639c26C9F45C634dD14C599cBAa27363D4665C53", // Hashi (Yaru) contract address on Chiado
hashiAddress: "0x78E4ae687De18B3B71Ccd0e8a3A76Fed49a02A02", // Hashi (Hashi) contract address on Chiado
},
};

Expand Down
13 changes: 10 additions & 3 deletions relayer-cli/src/relayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { EventEmitter } from "node:events";
import { ethers } from "ethers";
import { relayBatch, relayAllFrom } from "./utils/relay";
import {
initialize as initializeNonce,
initialize as initializeNonces,
updateStateFile,
delay,
setupExitHandlers,
Expand All @@ -14,6 +14,7 @@ import {
import { initialize as initializeEmitter } from "./utils/logger";
import { BotEvents } from "./utils/botEvents";
import { getEpochPeriod, Network } from "./consts/bridgeRoutes";
import { runHashiExecutor } from "./utils/hashi";

interface RelayerConfig {
networkConfigs: RelayerNetworkConfig[];
Expand Down Expand Up @@ -59,17 +60,23 @@ async function processNetworkConfig(

await setupExitHandlers(chainId, shutdownManager, network, emitter);

let nonce = await initializeNonce(chainId, network, emitter);
let { nonce, hashiNonce } = await initializeNonces(chainId, network, emitter);
if (nonce == null) return currentDelay;

const hashiExecutorEnabled = process.env.HASHI_EXECUTOR_ENABLED === "true";
if (hashiExecutorEnabled) {
// Execute messages on Hashi
hashiNonce = await runHashiExecutor({ chainId, network, nonce: hashiNonce, emitter });
}

const toRelayAll = senders[0] === ethers.ZeroAddress;
nonce = toRelayAll
? await relayBatch({ chainId, network, nonce, maxBatchSize, emitter })
: await relayAllFrom(chainId, network, nonce, senders, emitter);

if (nonce == null) return currentDelay;

await updateStateFile(chainId, Math.floor(Date.now() / 1000), nonce, network, emitter);
await updateStateFile(chainId, Math.floor(Date.now() / 1000), nonce, hashiNonce, network, emitter);

if (network === Network.DEVNET) {
return 1000 * 10; // 10 seconds for devnet
Expand Down
6 changes: 6 additions & 0 deletions relayer-cli/src/utils/botEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,10 @@ export enum BotEvents {
RELAY_BATCH = "relay_batch",
RELAY_ALL_FROM = "relay_all_from",
MESSAGE_EXECUTION_FAILED = "message_execution_failed",

// Hashi executor
EXECUTING_HASHI = "executing_hashi",
HASHI_EXECUTED = "hashi_executed",
HASHI_BATCH_TXN = "hashi_batch_txn",
HASHI_EXECUTION_FAILED = "hashi_execution_failed",
}
88 changes: 88 additions & 0 deletions relayer-cli/src/utils/graphQueries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import request from "graphql-request";
import { VeaOutboxArbToEth, VeaOutboxArbToGnosis } from "@kleros/vea-contracts/typechain-types";

async function getVeaMsgTrnx(nonce: number, inboxAddress: string) {
console.log(`Fetching transaction hashes for nonce ${nonce} from inbox ${inboxAddress}`);
try {
const subgraph = process.env.RELAYER_SUBGRAPH;
const query = `{messageSents(first: 1, where: {nonce: ${nonce}, inbox: "${inboxAddress}"}) {
id
transactionHash
}}`;
const result = (await request(`https://api.studio.thegraph.com/query/${subgraph}`, query)) as {
messageSents: { id: string; transactionHash: string }[];
};
return result.messageSents.map((trnx) => trnx.transactionHash);
} catch (e) {
console.log(e);
return [];
}
}

interface SnapshotResponse {
snapshotSaveds: Array<{ count: string }>;
}
/**
* Get the count of the veaOutbox
* @param veaOutbox The veaOutbox contract instance
* @param chainId The chain id of the veaOutbox chain
* @returns The count of the veaOutbox
*/
const getCount = async (veaOutbox: VeaOutboxArbToEth | VeaOutboxArbToGnosis, chainId: number): Promise<number> => {
const subgraph = process.env.RELAYER_SUBGRAPH;
const stateRoot = await veaOutbox.stateRoot();

const result = (await request(
`https://api.studio.thegraph.com/query/${subgraph}`,
`{
snapshotSaveds(first: 1, where: { stateRoot: "${stateRoot}" }) {
count
}
}`
)) as SnapshotResponse;

if (result["snapshotSaveds"].length == 0) return 0;

return Number(result["snapshotSaveds"][0].count);
};

interface MessageSent {
nonce: number;
}

interface MessageSentsResponse {
messageSents: MessageSent[];
}

/**
* Get the nonces of messages sent by a given sender
* @param chainId The chain id of the veaOutbox chain
* @param nonce The nonce of the first message to relay
* @param msgSender The address of the sender
* @returns The nonces of the messages sent by the sender
*/
const getNonceFrom = async (chainId: number, inbox: string, nonce: number, msgSender: string) => {
const subgraph = process.env.RELAYER_SUBGRAPH;

const result = (await request(
`https://api.studio.thegraph.com/query/${subgraph}`,
`{
messageSents(
first: 1000,
where: {
inbox: "${inbox}",
nonce_gte: ${nonce},
msgSender_: {id: "${msgSender.toLowerCase()}"}
},
orderBy: nonce,
orderDirection: asc
) {
nonce
}
}`
)) as MessageSentsResponse;

return result[`messageSents`].map((a: { nonce: string | number }) => Number(a.nonce));
};

export { getVeaMsgTrnx, getCount, getNonceFrom };
Loading
Loading