Skip to content

Commit

Permalink
chore: merge
Browse files Browse the repository at this point in the history
  • Loading branch information
jahabeebs committed Sep 26, 2024
2 parents 7ac5c81 + bac1fea commit c4e04da
Show file tree
Hide file tree
Showing 46 changed files with 2,147 additions and 472 deletions.
3 changes: 3 additions & 0 deletions apps/agent/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
PROTOCOL_PROVIDER_PRIVATE_KEY=afdfd9c3d2095ef696594f6cedcae59e72dcd697e2a7521b1578140422a4f890
BLOCK_NUMBER_BLOCKMETA_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuaWNlIjoidHJ5Iiwibm90aGluZyI6InRvIiwic2VlIjoiaGVyZSJ9.gsWpvMzpzd5_7IN_GU0PhNLH7wuKHl29FHkL5-i18b4
EBO_AGENT_CONFIG_FILE_PATH="./config.example.yml"
25 changes: 25 additions & 0 deletions apps/agent/config.example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
protocolProvider:
rpcsConfig:
transactionReceiptConfirmations: 1
timeout: 10000
retryInterval: 150
contracts:
oracle: "0x1234567890123456789012345678901234567890"
epochManager: "0x1234567890123456789012345678901234567890"
eboRequestCreator: "0x1234567890123456789012345678901234567890"
bondEscalationModule: "0x1234567890123456789012345678901234567890"

blockNumberService:
blockmetaConfig:
baseUrl: "localhost:443"
servicePaths:
blockByTime: /sf.blockmeta.v2.BlockByTime
block: /sf.blockmeta.v2.Block
bearerTokenExpirationWindow: 31536000000

processor:
msBetweenChecks: 1000
accountingModules:
requestModule: "0x1234567890123456789012345678901234567890"
responseModule: "0x1234567890123456789012345678901234567890"
escalationModule: "0x1234567890123456789012345678901234567890"
6 changes: 5 additions & 1 deletion apps/agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
"dependencies": {
"@ebo-agent/automated-dispute": "workspace:*",
"@ebo-agent/blocknumber": "workspace:*",
"@ebo-agent/shared": "workspace:*"
"@ebo-agent/shared": "workspace:*",
"dotenv": "16.4.5",
"viem": "2.21.8",
"yaml": "2.5.1",
"zod": "3.23.8"
}
}
64 changes: 64 additions & 0 deletions apps/agent/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import fs from "fs";
import { isNativeError } from "util/types";
import { Logger } from "@ebo-agent/shared";
import dotenv from "dotenv";
import yaml from "yaml";

import { eboAgentConfigSchema, envSchema } from "./schemas.js";

const logger = Logger.getInstance();

dotenv.config();

const env = envSchema.safeParse(process.env);

if (!env.success) {
logger.error("Invalid environment variables:");
logger.error(env.error.issues.map((issue) => JSON.stringify(issue)).join("\n"));

process.exit(1);
}

let configFile: string;
let configContent: unknown;

try {
configFile = fs.readFileSync(env.data.EBO_AGENT_CONFIG_FILE_PATH, "utf-8");
configContent = yaml.parse(configFile);
} catch (err) {
logger.error(`Failed to read config file at ${env.data.EBO_AGENT_CONFIG_FILE_PATH}.`);
logger.error(`${isNativeError(err) ? err.message : err}`);

process.exit(1);
}

const parsedConfig = eboAgentConfigSchema.safeParse(configContent);

if (!parsedConfig.success) {
logger.error("Invalid config file:");
logger.error(parsedConfig.error.issues.map((issue) => JSON.stringify(issue)).join("\n"));

process.exit(1);
}

const { data: envData } = env;
const { data: configData } = parsedConfig;

export const config = {
protocolProvider: {
...configData.protocolProvider,
rpcsConfig: {
...configData.protocolProvider.rpcsConfig,
urls: envData.PROTOCOL_PROVIDER_RPC_URLS,
},
privateKey: envData.PROTOCOL_PROVIDER_PRIVATE_KEY,
},
blockNumberService: {
chainRpcUrls: envData.BLOCK_NUMBER_RPC_URLS_MAP,
blockmetaConfig: {
...configData.blockNumberService.blockmetaConfig,
bearerToken: envData.BLOCK_NUMBER_BLOCKMETA_TOKEN,
},
},
processor: { ...configData.processor },
} as const;
76 changes: 76 additions & 0 deletions apps/agent/src/config/schemas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { Caip2Utils } from "@ebo-agent/blocknumber";
import { Caip2ChainId } from "@ebo-agent/blocknumber/dist/types.js";
import { isAddress, isHex } from "viem";
import { z } from "zod";

// TODO: test schemas

const stringToJSONSchema = z.string().transform((str, ctx): z.infer<ReturnType<typeof Object>> => {
try {
return JSON.parse(str);
} catch (e) {
ctx.addIssue({ code: "custom", message: "Invalid JSON" });
return z.NEVER;
}
});

const chainIdSchema = z.string().refine((id) => Caip2Utils.validateChainId(id));
const chainRpcUrlSchema = z
.record(chainIdSchema, z.array(z.string().url()))
.transform((records) => new Map(Object.entries(records) as [Caip2ChainId, string[]][]));

export const envSchema = z.object({
PROTOCOL_PROVIDER_PRIVATE_KEY: z.string().refine((key) => isHex(key)),
PROTOCOL_PROVIDER_RPC_URLS: z
.string()
.transform((str) => str.split(","))
.refine((arr) => arr.every((url) => z.string().url().safeParse(url).success)),
BLOCK_NUMBER_RPC_URLS_MAP: stringToJSONSchema.pipe(chainRpcUrlSchema),
BLOCK_NUMBER_BLOCKMETA_TOKEN: z.string(),
EBO_AGENT_CONFIG_FILE_PATH: z.string(),
});

const addressSchema = z.string().refine((address) => isAddress(address));

const protocolProviderConfigSchema = z.object({
rpcsConfig: z.object({
transactionReceiptConfirmations: z.number().int().positive(),
timeout: z.number().int().positive(),
retryInterval: z.number().int().positive(),
}),
contracts: z.object({
oracle: addressSchema,
epochManager: addressSchema,
eboRequestCreator: addressSchema,
bondEscalationModule: addressSchema,
}),
});

const blockNumberServiceSchema = z.object({
blockmetaConfig: z.object({
baseUrl: z
.string()
.url()
.transform((url) => new URL(url)),
servicePaths: z.object({
blockByTime: z.string(),
block: z.string(),
}),
bearerTokenExpirationWindow: z.number().int().positive(),
}),
});

const processorSchema = z.object({
msBetweenChecks: z.number().int().positive(),
accountingModules: z.object({
requestModule: addressSchema,
responseModule: addressSchema,
escalationModule: addressSchema,
}),
});

export const eboAgentConfigSchema = z.object({
protocolProvider: protocolProviderConfigSchema,
blockNumberService: blockNumberServiceSchema,
processor: processorSchema,
});
51 changes: 19 additions & 32 deletions apps/agent/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,16 @@
import { inspect } from "util";
import { EboActorsManager, EboProcessor } from "@ebo-agent/automated-dispute";
import { ProtocolProvider } from "@ebo-agent/automated-dispute/dist/providers/protocolProvider.js";
import { isNativeError } from "util/types";
import { EboActorsManager, EboProcessor, ProtocolProvider } from "@ebo-agent/automated-dispute";
import { BlockNumberService } from "@ebo-agent/blocknumber";
import { Logger } from "@ebo-agent/shared";

// TODO: use env vars and validate config schema
const config = {
protocolProvider: {
rpcUrls: ["localhost"],
contracts: {
oracle: "0x00",
epochManager: "0x00",
eboRequestCreator: "0x00",
} as const,
privateKey: "0xsecret" as const,
},
blockNumberService: {
chainRpcUrls: new Map([["eip155:1" as const, ["localhost"]]]),
blockmetaConfig: {
baseUrl: new URL("localhost:443"),
servicePaths: {
blockByTime: "/sf.blockmeta.v2.BlockByTime",
block: "/sf.blockmeta.v2.Block",
},
bearerToken: "secret-token",
bearerTokenExpirationWindow: 365 * 24 * 60 * 60 * 1000, // 1 year
},
},
processor: {
msBetweenChecks: 1,
},
};
import { config } from "./config/index.js";

const logger = Logger.getInstance();

const main = async (): Promise<void> => {
const protocolProvider = new ProtocolProvider(
config.protocolProvider.rpcUrls,
config.protocolProvider.rpcsConfig,
config.protocolProvider.contracts,
config.protocolProvider.privateKey,
);
Expand All @@ -49,7 +23,13 @@ const main = async (): Promise<void> => {

const actorsManager = new EboActorsManager();

const processor = new EboProcessor(protocolProvider, blockNumberService, actorsManager, logger);
const processor = new EboProcessor(
config.processor.accountingModules,
protocolProvider,
blockNumberService,
actorsManager,
logger,
);

await processor.start(config.processor.msBetweenChecks);
};
Expand All @@ -67,7 +47,14 @@ process.on("uncaughtException", (error: Error) => {
});

main().catch((err) => {
logger.error(`Error in main handler: ${err}`);
logger.error(`Main handler failure.`);

if (isNativeError(err)) {
logger.error(`${err.stack}`);
logger.error(`${err.message}`);
} else {
logger.error(err);
}

process.exit(1);
});
Loading

0 comments on commit c4e04da

Please sign in to comment.