import { getRetryProvider } from "@uma/common"; import { delay } from "@uma/financial-templates-lib"; import type { Provider } from "@ethersproject/abstract-provider"; export { OptimisticOracleV3Ethers } from "@uma/contracts-node"; export { Logger } from "@uma/financial-templates-lib"; export { getContractInstanceWithProvider } from "../utils/contracts"; export { generateOOv3UILink } from "../utils/logger"; export interface BotModes { assertionsEnabled: boolean; disputesEnabled: boolean; settlementsEnabled: boolean; } export interface BlockRange { start: number; end: number; } export interface MonitoringParams { provider: Provider; chainId: number; blockRange: BlockRange; pollingDelay: number; botModes: BotModes; } export const initMonitoringParams = async (env: NodeJS.ProcessEnv): Promise => { if (!env.CHAIN_ID) throw new Error("CHAIN_ID must be defined in env"); const chainId = Number(env.CHAIN_ID); const STARTING_BLOCK_KEY = `STARTING_BLOCK_NUMBER_${chainId}`; const ENDING_BLOCK_KEY = `ENDING_BLOCK_NUMBER_${chainId}`; // Creating provider will check for other chainId specific env variables. const provider = getRetryProvider(chainId) as Provider; // Default to 1 minute polling delay. const pollingDelay = env.POLLING_DELAY ? Number(env.POLLING_DELAY) : 60; if (pollingDelay === 0 && (!env[STARTING_BLOCK_KEY] || !env[ENDING_BLOCK_KEY])) { throw new Error(`Must provide ${STARTING_BLOCK_KEY} and ${ENDING_BLOCK_KEY} if running serverless`); } // If no block numbers are provided, default to the latest block. const latestBlockNumber: number = await provider.getBlockNumber(); const startingBlock = env[STARTING_BLOCK_KEY] ? Number(env[STARTING_BLOCK_KEY]) : latestBlockNumber; const endingBlock = env[ENDING_BLOCK_KEY] ? Number(env[ENDING_BLOCK_KEY]) : latestBlockNumber; // In serverless it is possible for start block to be larger than end block if no new blocks were mined since last run. if (startingBlock > endingBlock && pollingDelay !== 0) { throw new Error(`${STARTING_BLOCK_KEY} must be less than or equal to ${ENDING_BLOCK_KEY}`); } const botModes = { assertionsEnabled: env.ASSERTIONS_ENABLED === "true", disputesEnabled: env.DISPUTES_ENABLED === "true", settlementsEnabled: env.SETTLEMENTS_ENABLED === "true", }; return { provider, chainId, blockRange: { start: startingBlock, end: endingBlock }, pollingDelay, botModes, }; }; export const waitNextBlockRange = async (params: MonitoringParams): Promise => { await delay(Number(params.pollingDelay)); const latestBlockNumber: number = await params.provider.getBlockNumber(); return { start: params.blockRange.end + 1, end: latestBlockNumber }; }; export const startupLogLevel = (params: MonitoringParams): "debug" | "info" => { return params.pollingDelay === 0 ? "debug" : "info"; };