Skip to content

Commit

Permalink
feat: add blockmeta provider notifications (#92)
Browse files Browse the repository at this point in the history
  • Loading branch information
jahabeebs authored Nov 19, 2024
1 parent f492a0d commit 96a84fc
Show file tree
Hide file tree
Showing 23 changed files with 277 additions and 80 deletions.
17 changes: 9 additions & 8 deletions apps/agent/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ import { isNativeError } from "util/types";
import {
EboActorsManager,
EboProcessor,
NotificationService,
NotificationServiceFactory,
ProtocolProvider,
} from "@ebo-agent/automated-dispute";
import { BlockNumberService } from "@ebo-agent/blocknumber";
import { Logger, stringify } from "@ebo-agent/shared";
import { Logger, NotificationService, stringify } from "@ebo-agent/shared";

import { config } from "./config/index.js";

Expand All @@ -17,13 +16,21 @@ const logger = Logger.getInstance();
const main = async (): Promise<void> => {
logger.debug("Initializing agent...");

logger.debug("Initializing notification service...");

const notifier: NotificationService = NotificationServiceFactory.create(logger);

logger.debug("Initialized notification service.");

logger.debug("Initializing block number service...");

logger.debug(stringify(config.blockNumberService));

const blockNumberService = new BlockNumberService(
config.blockNumberService.chainRpcUrls,
config.blockNumberService.blockmetaConfig,
logger,
notifier,
);

logger.debug("Block number service initialized.");
Expand All @@ -41,12 +48,6 @@ const main = async (): Promise<void> => {

logger.debug("Protocol provider initialized.");

logger.debug("Initializing notification service...");

const notifier: NotificationService = NotificationServiceFactory.create(logger);

logger.debug("Initialized notification service.");

const actorsManager = new EboActorsManager();

logger.debug("Initializing EBO processor...");
Expand Down
3 changes: 1 addition & 2 deletions packages/automated-dispute/src/exceptions/errorHandler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ILogger } from "@ebo-agent/shared";
import { ILogger, NotificationService } from "@ebo-agent/shared";

import { CustomContractError } from "../exceptions/index.js";
import { NotificationService } from "../interfaces/index.js";

export class ErrorHandler {
private notificationService: NotificationService;
Expand Down
1 change: 0 additions & 1 deletion packages/automated-dispute/src/external.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export { EboProcessor, EboActorsManager, DiscordNotifier, ProphetCodec } from "./services/index.js";
export type { NotificationService } from "./interfaces/index.js";
export { NullNotificationService, NotificationServiceFactory } from "./interfaces/index.js";
export { ProtocolProvider } from "./providers/index.js";
export type { AccountingModules } from "./types/index.js";
Expand Down
1 change: 0 additions & 1 deletion packages/automated-dispute/src/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export * from "./eboRegistry.js";
export * from "./eboRegistryCommand.js";
export * from "./protocolProvider.js";
export * from "./notificationService.js";
export * from "./nullNotificationService.js";
export * from "./notificationServiceFactory.js";
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { ILogger } from "@ebo-agent/shared";
import { ILogger, NotificationService } from "@ebo-agent/shared";

import { config } from "../config.js";
import { DiscordNotifier } from "../services/index.js";
import { NotificationService } from "./notificationService.js";
import { NullNotificationService } from "./nullNotificationService.js";

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IMessage, NotificationService } from "./notificationService.js";
import { IMessage, NotificationService } from "@ebo-agent/shared";

/**
* A null implementation of NotificationService that performs no actions but allows the application to have an undefined notificationService if desired
Expand Down
3 changes: 1 addition & 2 deletions packages/automated-dispute/src/services/discordNotifier.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { isNativeError } from "util/types";
import type { APIEmbed, JSONEncodable } from "discord.js";
import { ILogger, stringify } from "@ebo-agent/shared";
import { ILogger, IMessage, NotificationService, stringify } from "@ebo-agent/shared";
import { WebhookClient, WebhookMessageCreateOptions } from "discord.js";

import { NotificationFailureException } from "../exceptions/index.js";
import { IMessage, NotificationService } from "../interfaces/index.js";

export type WebhookMessage = WebhookMessageCreateOptions & {
content: string;
Expand Down
10 changes: 8 additions & 2 deletions packages/automated-dispute/src/services/eboActor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { isNativeError } from "util/types";
import { BlockNumberService } from "@ebo-agent/blocknumber";
import { Caip2ChainId, ILogger, stringify, UnixTimestamp } from "@ebo-agent/shared";
import {
Caip2ChainId,
ILogger,
NotificationService,
stringify,
UnixTimestamp,
} from "@ebo-agent/shared";
import { Mutex } from "async-mutex";
import { Heap } from "heap-js";
import { ContractFunctionRevertedError } from "viem";
Expand Down Expand Up @@ -30,7 +36,7 @@ import {
ResponseNotFound,
UnknownEvent,
} from "../exceptions/index.js";
import { EboRegistry, EboRegistryCommand, NotificationService } from "../interfaces/index.js";
import { EboRegistry, EboRegistryCommand } from "../interfaces/index.js";
import { ProtocolProvider } from "../providers/index.js";
import {
AddDispute,
Expand Down
3 changes: 1 addition & 2 deletions packages/automated-dispute/src/services/eboActorsManager.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { BlockNumberService } from "@ebo-agent/blocknumber";
import { ILogger } from "@ebo-agent/shared";
import { ILogger, NotificationService } from "@ebo-agent/shared";
import { Mutex } from "async-mutex";

import { RequestAlreadyHandled } from "../exceptions/index.js";
import { NotificationService } from "../interfaces/index.js";
import { ProtocolProvider } from "../providers/protocolProvider.js";
import { ActorRequest, RequestId } from "../types/index.js";
import { EboActor } from "./eboActor.js";
Expand Down
10 changes: 8 additions & 2 deletions packages/automated-dispute/src/services/eboProcessor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { isNativeError } from "util/types";
import { BlockNumberService } from "@ebo-agent/blocknumber";
import { Caip2ChainId, Caip2Utils, ILogger, stringify, UnixTimestamp } from "@ebo-agent/shared";
import {
Caip2ChainId,
Caip2Utils,
ILogger,
NotificationService,
stringify,
UnixTimestamp,
} from "@ebo-agent/shared";
import { Address, Block, ContractFunctionRevertedError } from "viem";

import {
Expand All @@ -9,7 +16,6 @@ import {
ProcessorAlreadyStarted,
} from "../exceptions/index.js";
import { isRequestCreatedEvent } from "../guards.js";
import { NotificationService } from "../interfaces/index.js";
import { ProtocolProvider } from "../providers/index.js";
import {
alreadyDeletedActorWarning,
Expand Down
3 changes: 1 addition & 2 deletions packages/automated-dispute/tests/mocks/eboActor.mocks.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { BlockNumberService } from "@ebo-agent/blocknumber";
import { Caip2ChainId, ILogger, UnixTimestamp } from "@ebo-agent/shared";
import { Caip2ChainId, ILogger, NotificationService, UnixTimestamp } from "@ebo-agent/shared";
import { Mutex } from "async-mutex";
import { Block, pad } from "viem";
import { vi } from "vitest";

import { NotificationService } from "../../src/index.js";
import { ProtocolProvider } from "../../src/providers/index.js";
import { EboActor, EboMemoryRegistry, ProphetCodec } from "../../src/services/index.js";
import {
Expand Down
4 changes: 2 additions & 2 deletions packages/automated-dispute/tests/mocks/eboProcessor.mocks.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { BlockNumberService } from "@ebo-agent/blocknumber";
import { Caip2ChainId, ILogger } from "@ebo-agent/shared";
import { Caip2ChainId, ILogger, NotificationService } from "@ebo-agent/shared";
import { vi } from "vitest";

import { NotificationService } from "../../src/index.js";
import { ProtocolProvider } from "../../src/providers/index.js";
import { EboActorsManager, EboProcessor } from "../../src/services/index.js";
import { AccountingModules } from "../../src/types/prophet.js";
Expand Down Expand Up @@ -35,6 +34,7 @@ export function buildEboProcessor(
},
},
logger,
notifier,
);

const protocolProvider = new ProtocolProvider(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { ILogger, stringify } from "@ebo-agent/shared";
import { ILogger, IMessage, stringify } from "@ebo-agent/shared";
import { WebhookClient } from "discord.js";
import { beforeEach, describe, expect, it, vi } from "vitest";

import { NotificationFailureException } from "../../src/exceptions/index.js";
import { DiscordNotifier } from "../../src/index.js";
import { IMessage } from "../../src/interfaces/index.js";

vi.mock("discord.js", () => {
const mockSend = vi.fn();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Caip2ChainId, UnixTimestamp } from "@ebo-agent/shared";
import { Caip2ChainId, NotificationService, UnixTimestamp } from "@ebo-agent/shared";
import { Caip2Utils } from "@ebo-agent/shared/src/index.js";
import { Block, Hex } from "viem";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
Expand All @@ -8,7 +8,7 @@ import {
PendingModulesApproval,
ProcessorAlreadyStarted,
} from "../../src/exceptions/index.js";
import { NotificationService, ProphetCodec } from "../../src/index.js";
import { ProphetCodec } from "../../src/index.js";
import {
AccountingModules,
EboEvent,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { ILogger } from "@ebo-agent/shared";
import { ILogger, NotificationService } from "@ebo-agent/shared";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";

import { NotificationService } from "../../src/index.js";

vi.mock("../../src/services/discordNotifier.js", () => ({
DiscordNotifier: vi.fn(),
}));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IMessage, NotificationService } from "@ebo-agent/shared";
import { beforeEach, describe, expect, it } from "vitest";

import { NotificationService } from "../../src/index.js";
import { IMessage, NullNotificationService } from "../../src/interfaces/index.js";
import { NullNotificationService } from "../../src/interfaces/index.js";

describe("NullNotificationService", () => {
let notifier: NotificationService;
Expand Down
17 changes: 15 additions & 2 deletions packages/blocknumber/src/providers/blockNumberProviderFactory.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { Caip2ChainId, Caip2Utils, EBO_SUPPORTED_CHAINS_CONFIG, ILogger } from "@ebo-agent/shared";
import {
Caip2ChainId,
Caip2Utils,
EBO_SUPPORTED_CHAINS_CONFIG,
ILogger,
NotificationService,
} from "@ebo-agent/shared";
import { FallbackTransport, HttpTransport, PublicClient } from "viem";

import { UnsupportedChain } from "../exceptions/unsupportedChain.js";
Expand All @@ -19,14 +25,17 @@ export class BlockNumberProviderFactory {
*
* @param chainId CAIP-2 chain id
* @param evmClient a viem public client
* @param blockmetaConfig a BlockmetaClientConfig instance
* @param logger a ILogger instance
* @param notificationService a NotificationService instance
* @returns
*/
public static buildProvider(
chainId: Caip2ChainId,
evmClient: PublicClient<FallbackTransport<HttpTransport[]>>,
blockmetaConfig: BlockmetaClientConfig,
logger: ILogger,
notificationService: NotificationService,
) {
// TODO: initialize factory instance with evmClient and blockmetaConfig and
// remove them from this method parameters
Expand All @@ -37,7 +46,11 @@ export class BlockNumberProviderFactory {
return new EvmBlockNumberProvider(evmClient, DEFAULT_PROVIDER_CONFIG, logger);

case EBO_SUPPORTED_CHAINS_CONFIG.solana.namespace:
return new BlockmetaJsonBlockNumberProvider(blockmetaConfig, logger);
return new BlockmetaJsonBlockNumberProvider(
blockmetaConfig,
logger,
notificationService,
);

default:
throw new UnsupportedChain(chainId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ILogger, UnixTimestamp } from "@ebo-agent/shared";
import { ILogger, NotificationService, UnixTimestamp } from "@ebo-agent/shared";
import axios, {
AxiosInstance,
AxiosResponse,
Expand Down Expand Up @@ -41,6 +41,7 @@ export class BlockmetaJsonBlockNumberProvider implements BlockNumberProvider {
constructor(
private readonly clientConfig: BlockmetaClientConfig,
private readonly logger: ILogger,
private readonly notificationService: NotificationService,
) {
const { baseUrl, bearerToken } = clientConfig;

Expand All @@ -62,8 +63,9 @@ export class BlockmetaJsonBlockNumberProvider implements BlockNumberProvider {
public static async initialize(
config: BlockmetaClientConfig,
logger: ILogger,
notificationService: NotificationService,
): Promise<BlockmetaJsonBlockNumberProvider> {
const provider = new BlockmetaJsonBlockNumberProvider(config, logger);
const provider = new BlockmetaJsonBlockNumberProvider(config, logger, notificationService);

const connectedSuccessfully = await provider.testConnection();

Expand Down Expand Up @@ -108,17 +110,31 @@ export class BlockmetaJsonBlockNumberProvider implements BlockNumberProvider {
if (currentTime + expirationWindow >= expTime) {
const timeRemaining = expTime - currentTime;

this.logger.warn(`Token will expire soon in ${timeRemaining}`);

// TODO: notify
this.logger.warn(`Token will expire soon in ${timeRemaining} seconds.`);

this.notificationService
.sendError(
"Token Expiration Warning",
{ timeRemaining },
null, // No error obj for warnings
)
.catch((err: unknown) => {
this.logger.error(`Failed to send expiration warning notification: ${err}`);
});
}

return requestConfig;
} catch (err) {
if (err instanceof InvalidTokenError) {
this.logger.error("Invalid JWT token.");

// TODO: notify
this.notificationService
.sendError("Invalid JWT Token Error", {}, err)
.catch((notificationError: unknown) => {
this.logger.error(
`Failed to send invalid token notification: ${notificationError}`,
);
});
}

return requestConfig;
Expand Down
12 changes: 11 additions & 1 deletion packages/blocknumber/src/services/blockNumberService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { Caip2ChainId, EBO_SUPPORTED_CHAIN_IDS, ILogger, UnixTimestamp } from "@ebo-agent/shared";
import {
Caip2ChainId,
EBO_SUPPORTED_CHAIN_IDS,
ILogger,
NotificationService,
UnixTimestamp,
} from "@ebo-agent/shared";
import { createPublicClient, fallback, http } from "viem";

import { ChainWithoutProvider, EmptyRpcUrls, UnsupportedChain } from "../exceptions/index.js";
Expand All @@ -16,12 +22,15 @@ export class BlockNumberService {
* of chains.
*
* @param chainRpcUrls a map of CAIP-2 chain ids with their RPC urls that this service will handle
* @param blockmetaConfig a `BlockmetaClientConfig` instance
* @param logger a `ILogger` instance
* @param notificationService a `NotificationService` instance
*/
constructor(
chainRpcUrls: Map<Caip2ChainId, RpcUrl[]>,
private readonly blockmetaConfig: BlockmetaClientConfig,
private readonly logger: ILogger,
private readonly notificationService: NotificationService,
) {
this.blockNumberProviders = this.buildBlockNumberProviders(chainRpcUrls);
}
Expand Down Expand Up @@ -90,6 +99,7 @@ export class BlockNumberService {
client,
this.blockmetaConfig,
this.logger,
this.notificationService,
);

if (!provider) throw new ChainWithoutProvider(chainId);
Expand Down
Loading

0 comments on commit 96a84fc

Please sign in to comment.