Skip to content

Commit

Permalink
Merge branch 'fb-wss'
Browse files Browse the repository at this point in the history
  • Loading branch information
Metroxe committed Dec 15, 2023
2 parents e52bcaa + c82d4fc commit 9317783
Show file tree
Hide file tree
Showing 12 changed files with 280 additions and 89 deletions.
25 changes: 25 additions & 0 deletions apps/cli/src/commands/event-listener.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { resilientEventListener, config, RefereeAbi } from '@sentry/core';
import Vorpal from 'vorpal';

export function eventListener(cli: Vorpal) {
cli
.command('event-listener', 'Starts the event listener with provided arguments')
.option('-r, --rpcUrl <rpcUrl>', 'RPC URL')
.option('-c, --contractAddress <contractAddress>', 'Contract address')
.option('-a, --abi <abi>', 'ABI of the contract')
.option('-e, --eventName <eventName>', 'Event name to listen for')
.action(async function (this: Vorpal.CommandInstance, args) {
const { rpcUrl, contractAddress, abi, eventName } = args.options;

const { stop } = resilientEventListener({
rpcUrl: rpcUrl ? rpcUrl : config.arbitrumOneWebSocketUrl,
contractAddress: contractAddress ? contractAddress : config.refereeAddress,
abi: abi ? JSON.parse(abi) : RefereeAbi,
eventName: eventName ? eventName : "RewardsClaimed",
log: (value: string) => this.log(value),
});

return new Promise((resolve, reject) => { }); // Keep the command alive

});
}
2 changes: 2 additions & 0 deletions apps/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { bootOperator } from './commands/operator-control/operator-runtime.js';
import { setOrAddPricingTiersCommand } from './commands/licenses/set-or-add-pricing-tiers.js';
import { addPromoCode } from './commands/licenses/add-promo-code.js';
import { removePromoCode } from './commands/licenses/remove-promo-code.js';
import { eventListener } from './commands/event-listener.js';

const cli = new Vorpal();

Expand All @@ -57,6 +58,7 @@ checkKycStatus(cli);
checkWhitelist(cli);
createBlsKeyPair(cli);
createMnemonic(cli);
eventListener(cli);
getAllContractAddresses(cli);
getAssertionCheckingStatus(cli);
getBalancesForAddresses(cli);
Expand Down
6 changes: 4 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
"license": "UNLICENSED",
"dependencies": {
"@noble/curves": "^1.2.0",
"alchemy-sdk": "^3.1.0"
"alchemy-sdk": "^3.1.0",
"isomorphic-ws": "^5.0.0"
},
"devDependencies": {
"@types/node": "^20.6.0"
"@types/node": "^20.6.0",
"@types/ws": "^8.5.10"
}
}
48 changes: 19 additions & 29 deletions packages/core/src/challenger/listenForAssertions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {ethers} from "ethers";
import { LogDescription } from "ethers";
import { RollupAdminLogicAbi } from "../abis/RollupAdminLogicAbi.js";
import { getProvider } from "../utils/getProvider.js";
import { config } from "../config.js";
import { resilientEventListener } from "../utils/resilientEventListener.js";

/**
* Listens for NodeConfirmed events and triggers a callback function when the event is emitted.
Expand All @@ -10,42 +10,32 @@ import { config } from "../config.js";
* @param log - The logging function to be used for logging.
* @returns A function that can be called to stop listening for the event.
*/
export function listenForAssertions(callback: (nodeNum: any, blockHash: any, sendRoot: any, event: any) => void, log: (log: string) => void): () => void {
const provider = getProvider("wss://arb-goerli.g.alchemy.com/v2/WNOJEZxrhn3a0PzKUVEZgeRJqxOL7brv"); // arb goerli while we run on testnet

// create an instance of the rollup contract
const rollupContract = new ethers.Contract(config.rollupAddress, RollupAdminLogicAbi, {provider});

export function listenForAssertions(callback: (nodeNum: any, blockHash: any, sendRoot: any, event: any) => void, _log: (log: string) => void): () => void {
// create a map to keep track of nodeNums that have called the callback
const nodeNumMap: { [nodeNum: string]: boolean } = {};

// listen for the NodeConfirmed event
rollupContract.on("NodeConfirmed", (nodeNum, blockHash, sendRoot, event) => {
const listener = resilientEventListener({
rpcUrl: "wss://arb-goerli.g.alchemy.com/v2/WNOJEZxrhn3a0PzKUVEZgeRJqxOL7brv",
contractAddress: config.rollupAddress,
abi: RollupAdminLogicAbi,
eventName: "NodeConfirmed",
log: _log,
callback: (log: LogDescription | null) => {
const nodeNum = BigInt(log?.args[0]);
const blockHash = log?.args[1];
const sendRoot = log?.args[2];

// if the nodeNum has not been seen before, call the callback and add it to the map
if (!nodeNumMap[nodeNum]) {
log(`[${new Date().toISOString()}] NodeConfirmed event received for new nodeNum: ${nodeNum}`);
nodeNumMap[nodeNum] = true;
void callback(nodeNum, blockHash, sendRoot, event);
// if the nodeNum has not been seen before, call the callback and add it to the map
if (!nodeNumMap[nodeNum.toString()]) {
nodeNumMap[nodeNum.toString()] = true;
void callback(nodeNum, blockHash, sendRoot, log);
}
}
});

// Request the current block number immediately and then every 5 minutes
const fetchBlockNumber = async () => {
try {
const blockNumber = await provider.getBlockNumber();
log(`[${new Date().toISOString()}] Health Check, Challenger still healthy. Current block number: ${blockNumber}`);
} catch (error) {
log(`[${new Date().toISOString()}] Error fetching block number, challenger may no longer be connected to the RPC: ${JSON.stringify(error)}`);
}
};
fetchBlockNumber();
const interval = setInterval(fetchBlockNumber, 300000);

// return a function that can be used to stop listening for the event
return () => {
log(`[${new Date().toISOString()}] Stopping listening for NodeConfirmed events`);
rollupContract.removeAllListeners("NodeConfirmed");
clearInterval(interval);
listener.stop();
};
}
2 changes: 2 additions & 0 deletions packages/core/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export let config = {
"arbitrumBlockExplorer": "https://arbiscan.io",
"arbitrumGoerliBlockExplorer": "https://goerli.arbiscan.io",
"arbitrumOneJsonRpcUrl": "https://arb-mainnet.g.alchemy.com/v2/p_LSgTIj_JtEt3JPM7IZIZFL1a70yvQJ",
"arbitrumOneWebSocketUrl": "wss://arb-mainnet.g.alchemy.com/v2/p_LSgTIj_JtEt3JPM7IZIZFL1a70yvQJ",
"defaultRpcUrl": "https://arb-mainnet.g.alchemy.com/v2/p_LSgTIj_JtEt3JPM7IZIZFL1a70yvQJ",
"esXaiAddress": "0x4C749d097832DE2FEcc989ce18fDc5f1BD76700c",
"esXaiDeployedBlockNumber": 157193630,
Expand Down
36 changes: 20 additions & 16 deletions packages/core/src/operator/listenForChallenges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { RefereeAbi } from "../abis/RefereeAbi.js";
import { getProvider } from "../utils/getProvider.js";
import { config } from "../config.js";
import { Challenge, getChallenge } from "../index.js";
import { resilientEventListener } from "../utils/resilientEventListener.js";

/**
* Listens for ChallengeSubmitted events and triggers a callback function when the event is emitted.
Expand All @@ -11,31 +12,34 @@ import { Challenge, getChallenge } from "../index.js";
* @returns A function that can be called to stop listening for the event.
*/
export function listenForChallenges(callback: (challengeNumber: bigint, challenge: Challenge, event: any) => void): () => void {
// get a provider for the arb one network
const provider = getProvider();

// create an instance of the Referee contract
const refereeContract = new ethers.Contract(config.refereeAddress, RefereeAbi, provider);

// create a map to keep track of challengeNumbers that have called the callback
const challengeNumberMap: { [challengeNumber: string]: boolean } = {};

// listen for the ChallengeSubmitted event
refereeContract.on("ChallengeSubmitted", async (challengeNumber, event) => {

// if the challengeNumber has not been seen before, call the callback and add it to the map
if (!challengeNumberMap[challengeNumber.toString()]) {
challengeNumberMap[challengeNumber.toString()] = true;

// lookup the challenge
const challenge = await getChallenge(challengeNumber);

void callback(challengeNumber, challenge, event);
const listener = resilientEventListener({
rpcUrl: config.arbitrumOneWebSocketUrl,
contractAddress: config.refereeAddress,
abi: RefereeAbi,
eventName: "ChallengeSubmitted",
log: console.info,
callback: async (log) => {
const challengeNumber = BigInt(log?.args[0]);

// if the challengeNumber has not been seen before, call the callback and add it to the map
if (!challengeNumberMap[challengeNumber.toString()]) {
challengeNumberMap[challengeNumber.toString()] = true;

// lookup the challenge
const challenge = await getChallenge(challengeNumber);

void callback(challengeNumber, challenge, log);
}
}
});

// return a function that can be used to stop listening for the event
return () => {
refereeContract.removeAllListeners("ChallengeSubmitted");
listener.stop();
};
}
Loading

0 comments on commit 9317783

Please sign in to comment.