@gearbox-protocol/cli-utils 6.16.1 → 9.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +436 -19
- package/dist/index.js +1402 -19
- package/dist/index.js.map +1 -0
- package/package.json +27 -13
- package/dist/CensoredString.d.ts +0 -8
- package/dist/CensoredString.js +0 -31
- package/dist/CensoredURL.d.ts +0 -11
- package/dist/CensoredURL.js +0 -53
- package/dist/SSMManager.d.ts +0 -5
- package/dist/SSMManager.js +0 -30
- package/dist/SecretsManager.d.ts +0 -6
- package/dist/SecretsManager.js +0 -52
- package/dist/Whitelist.d.ts +0 -30
- package/dist/Whitelist.js +0 -84
- package/dist/Zommand.d.ts +0 -25
- package/dist/Zommand.js +0 -98
- package/dist/compressedConfig.d.ts +0 -10
- package/dist/compressedConfig.js +0 -22
- package/dist/createPinoCensor.d.ts +0 -5
- package/dist/createPinoCensor.js +0 -53
- package/dist/fetchRetry.d.ts +0 -7
- package/dist/fetchRetry.js +0 -26
- package/dist/getFirstHttpTransportOptions.d.ts +0 -7
- package/dist/getFirstHttpTransportOptions.js +0 -13
- package/dist/getPromisePath.d.ts +0 -7
- package/dist/getPromisePath.js +0 -18
- package/dist/getProviders.d.ts +0 -4
- package/dist/getProviders.js +0 -104
- package/dist/notifications/NotificationsService.d.ts +0 -19
- package/dist/notifications/NotificationsService.js +0 -76
- package/dist/notifications/SignlNotifier.d.ts +0 -13
- package/dist/notifications/SignlNotifier.js +0 -58
- package/dist/notifications/SlackNotifier.d.ts +0 -8
- package/dist/notifications/SlackNotifier.js +0 -38
- package/dist/notifications/TelegramNotifier.d.ts +0 -14
- package/dist/notifications/TelegramNotifier.js +0 -119
- package/dist/notifications/ThrottleManager.d.ts +0 -18
- package/dist/notifications/ThrottleManager.js +0 -40
- package/dist/notifications/createNotifier.d.ts +0 -4
- package/dist/notifications/createNotifier.js +0 -18
- package/dist/notifications/index.d.ts +0 -4
- package/dist/notifications/index.js +0 -4
- package/dist/notifications/schema.d.ts +0 -33
- package/dist/notifications/schema.js +0 -46
- package/dist/notifications/types.d.ts +0 -91
- package/dist/notifications/types.js +0 -1
- package/dist/providers-schema.d.ts +0 -49
- package/dist/providers-schema.js +0 -122
- package/dist/providers.d.ts +0 -6
- package/dist/providers.js +0 -103
- package/dist/resolveYamlFiles.d.ts +0 -40
- package/dist/resolveYamlFiles.js +0 -170
- package/dist/schema-primitives.d.ts +0 -10
- package/dist/schema-primitives.js +0 -30
- package/dist/sleep.d.ts +0 -1
- package/dist/sleep.js +0 -6
- package/dist/uncensorMap.d.ts +0 -4
- package/dist/uncensorMap.js +0 -3
- package/dist/whitelist-schema.d.ts +0 -54
- package/dist/whitelist-schema.js +0 -21
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { md } from "@vlad-yakovlev/telegram-md";
|
|
2
|
-
import Queue from "p-queue";
|
|
3
|
-
import { withRetry } from "viem";
|
|
4
|
-
import { ThrottleManager } from "./ThrottleManager.js";
|
|
5
|
-
const DEFAULT_RETRY_INTERVAL = 1000;
|
|
6
|
-
const DEFAULT_RETRY_COUNT = 5;
|
|
7
|
-
const DEFAULT_MAX_CHUNK_SIZE = 4096;
|
|
8
|
-
export class TelegramNotifier {
|
|
9
|
-
#logger;
|
|
10
|
-
#alertsChannel;
|
|
11
|
-
#notificationsChannel;
|
|
12
|
-
#botToken;
|
|
13
|
-
#prefix;
|
|
14
|
-
#retryInterval;
|
|
15
|
-
#retryCount;
|
|
16
|
-
#maxChunkSize;
|
|
17
|
-
#fetchFn;
|
|
18
|
-
#queue = new Queue({
|
|
19
|
-
concurrency: 1,
|
|
20
|
-
// https://core.telegram.org/bots/faq#my-bot-is-hitting-limits-how-do-i-avoid-this
|
|
21
|
-
// 20 messages/minute limit
|
|
22
|
-
interval: 60_000,
|
|
23
|
-
intervalCap: 20,
|
|
24
|
-
strict: true,
|
|
25
|
-
});
|
|
26
|
-
#throttleManager = new ThrottleManager();
|
|
27
|
-
constructor(opts, logger) {
|
|
28
|
-
this.#logger = logger;
|
|
29
|
-
this.#alertsChannel = opts.alertsChannel.value;
|
|
30
|
-
this.#botToken = opts.token.value;
|
|
31
|
-
this.#notificationsChannel = opts.notificationsChannel?.value;
|
|
32
|
-
this.#prefix = opts.prefix;
|
|
33
|
-
this.#retryInterval = opts.retryInterval ?? DEFAULT_RETRY_INTERVAL;
|
|
34
|
-
this.#retryCount = opts.retryCount ?? DEFAULT_RETRY_COUNT;
|
|
35
|
-
this.#maxChunkSize = opts.maxChunkSize ?? DEFAULT_MAX_CHUNK_SIZE;
|
|
36
|
-
this.#fetchFn = opts.fetchFn ?? fetch;
|
|
37
|
-
}
|
|
38
|
-
notify(message, severity) {
|
|
39
|
-
const dest = severity === "alert" ? this.#alertsChannel : this.#notificationsChannel;
|
|
40
|
-
if (!dest) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
this.#enqueueTelegram(message, dest, severity === "alert");
|
|
44
|
-
}
|
|
45
|
-
async #enqueueTelegram(message, channelId, severe = false) {
|
|
46
|
-
if (!this.#throttleManager.canSend(message.dedupeKey)) {
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
const payloads = this.#toTelegramPayloads(message);
|
|
50
|
-
for (const payload of payloads) {
|
|
51
|
-
this.#queue.add(() => this.#sendToTelegram(payload, channelId, severe).catch(e => this.#logger?.error(e)), {
|
|
52
|
-
priority: severe ? 100 : 0,
|
|
53
|
-
timeout: this.#retryInterval * this.#retryCount * 2,
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
this.#throttleManager.onSent(message.dedupeKey, message.throttleFn);
|
|
57
|
-
}
|
|
58
|
-
async #sendToTelegram(payload, channelId, severe = false) {
|
|
59
|
-
const severity = severe ? "alert" : "notification";
|
|
60
|
-
this.#logger?.debug(`sending telegram ${severity} to channel ${channelId}...`);
|
|
61
|
-
const url = `https://api.telegram.org/bot${this.#botToken}/sendMessage`;
|
|
62
|
-
try {
|
|
63
|
-
await withRetry(async () => {
|
|
64
|
-
const resp = await this.#fetchFn(url, {
|
|
65
|
-
method: "POST",
|
|
66
|
-
headers: {
|
|
67
|
-
"Content-Type": "application/json",
|
|
68
|
-
},
|
|
69
|
-
body: JSON.stringify({
|
|
70
|
-
...payload,
|
|
71
|
-
chat_id: channelId,
|
|
72
|
-
}),
|
|
73
|
-
});
|
|
74
|
-
if (resp.ok) {
|
|
75
|
-
this.#logger?.debug(`telegram ${severity} sent successfully`);
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
const txt = await resp.text();
|
|
79
|
-
throw new Error(`api error ${resp.status}: ${txt}`);
|
|
80
|
-
}
|
|
81
|
-
}, { delay: this.#retryInterval, retryCount: this.#retryCount });
|
|
82
|
-
}
|
|
83
|
-
catch (e) {
|
|
84
|
-
this.#logger?.error(`cannot send telegram ${severity}: ${e}`);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
#toTelegramPayloads(message) {
|
|
88
|
-
const { md: mdMessage, plain } = message;
|
|
89
|
-
if (!mdMessage) {
|
|
90
|
-
return this.#slicePlainText(plain);
|
|
91
|
-
}
|
|
92
|
-
let text = mdMessage;
|
|
93
|
-
if (this.#prefix) {
|
|
94
|
-
text = md.join([md.bold(this.#prefix), text], " ");
|
|
95
|
-
}
|
|
96
|
-
const mdText = text.toString();
|
|
97
|
-
if (mdText.length > this.#maxChunkSize) {
|
|
98
|
-
return this.#slicePlainText(plain);
|
|
99
|
-
}
|
|
100
|
-
return [{ text: mdText, parse_mode: "MarkdownV2" }];
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Telegram has a limit on message size (default 4096 characters).
|
|
104
|
-
* This function slices the text into chunks respecting the limit.
|
|
105
|
-
* Each chunk is prefixed with the prefix (if set), ensuring the total length <= maxChunkSize.
|
|
106
|
-
* @param text - The text to slice.
|
|
107
|
-
* @returns An array of texts.
|
|
108
|
-
*/
|
|
109
|
-
#slicePlainText(text) {
|
|
110
|
-
const chunks = [];
|
|
111
|
-
const prefix = this.#prefix ? `${this.#prefix} ` : "";
|
|
112
|
-
const maxChunkSize = this.#maxChunkSize - prefix.length;
|
|
113
|
-
for (let i = 0; i < text.length; i += maxChunkSize) {
|
|
114
|
-
const chunkText = text.slice(i, i + maxChunkSize);
|
|
115
|
-
chunks.push({ text: `${prefix}${chunkText}` });
|
|
116
|
-
}
|
|
117
|
-
return chunks;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { ThrottleFn } from "./types.js";
|
|
2
|
-
export declare function defaultBackoffFn(prevWait: number): number;
|
|
3
|
-
/**
|
|
4
|
-
* Manages per-feed throttling with exponential backoff.
|
|
5
|
-
* Each dedupe key has its own independent throttle timer.
|
|
6
|
-
*/
|
|
7
|
-
export declare class ThrottleManager {
|
|
8
|
-
#private;
|
|
9
|
-
/**
|
|
10
|
-
* Checks if it's permitted to send a message for the given dedupe key
|
|
11
|
-
* @returns
|
|
12
|
-
*/
|
|
13
|
-
canSend(dedupeKey?: string): boolean;
|
|
14
|
-
/**
|
|
15
|
-
* Records that notification was sent for the given dedupe key
|
|
16
|
-
*/
|
|
17
|
-
onSent(dedupeKey?: string, throttleFn?: ThrottleFn): void;
|
|
18
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { LRUCache } from "lru-cache";
|
|
2
|
-
export function defaultBackoffFn(prevWait) {
|
|
3
|
-
return Math.min(prevWait ? prevWait * 2 : 10 * 60 * 1000, // 10 minutes
|
|
4
|
-
24 * 60 * 60 * 1000);
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Manages per-feed throttling with exponential backoff.
|
|
8
|
-
* Each dedupe key has its own independent throttle timer.
|
|
9
|
-
*/
|
|
10
|
-
export class ThrottleManager {
|
|
11
|
-
#state = new LRUCache({ max: 5000 });
|
|
12
|
-
/**
|
|
13
|
-
* Checks if it's permitted to send a message for the given dedupe key
|
|
14
|
-
* @returns
|
|
15
|
-
*/
|
|
16
|
-
canSend(dedupeKey) {
|
|
17
|
-
if (!dedupeKey) {
|
|
18
|
-
return true;
|
|
19
|
-
}
|
|
20
|
-
const state = this.#getState(dedupeKey);
|
|
21
|
-
const timeSinceLastAlert = Date.now() - state.lastAlertTime;
|
|
22
|
-
return timeSinceLastAlert >= state.currentWait;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Records that notification was sent for the given dedupe key
|
|
26
|
-
*/
|
|
27
|
-
onSent(dedupeKey, throttleFn = defaultBackoffFn) {
|
|
28
|
-
if (!dedupeKey) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
const state = this.#getState(dedupeKey);
|
|
32
|
-
this.#state.set(dedupeKey, {
|
|
33
|
-
lastAlertTime: Date.now(),
|
|
34
|
-
currentWait: throttleFn(state.currentWait),
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
#getState(dedupeKey) {
|
|
38
|
-
return this.#state.get(dedupeKey) ?? { lastAlertTime: 0, currentWait: 0 };
|
|
39
|
-
}
|
|
40
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { prettifyError } from "zod";
|
|
2
|
-
import { SlackNotifier } from "./SlackNotifier.js";
|
|
3
|
-
import { NotificationConfig } from "./schema.js";
|
|
4
|
-
import { TelegramNotifier } from "./TelegramNotifier.js";
|
|
5
|
-
export function createNotifier(config, logger) {
|
|
6
|
-
const parsed = NotificationConfig.safeParse(config);
|
|
7
|
-
if (!parsed.success) {
|
|
8
|
-
console.log(">>>>", parsed.error);
|
|
9
|
-
logger?.warn(`invalid notification config: ${prettifyError(parsed.error)}`);
|
|
10
|
-
return undefined;
|
|
11
|
-
}
|
|
12
|
-
switch (parsed.data.type) {
|
|
13
|
-
case "telegram":
|
|
14
|
-
return new TelegramNotifier(parsed.data, logger);
|
|
15
|
-
case "slack":
|
|
16
|
-
return new SlackNotifier(parsed.data, logger);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { z } from "zod/v4";
|
|
2
|
-
import { CensoredString } from "../CensoredString.js";
|
|
3
|
-
export declare const TelegramConfig: z.ZodObject<{
|
|
4
|
-
type: z.ZodLiteral<"telegram">;
|
|
5
|
-
token: z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<CensoredString<string>, CensoredString<string>>]>, z.ZodTransform<CensoredString<string>, string | CensoredString<string>>>;
|
|
6
|
-
alertsChannel: z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<CensoredString<string>, CensoredString<string>>]>, z.ZodTransform<CensoredString<string>, string | CensoredString<string>>>;
|
|
7
|
-
notificationsChannel: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<CensoredString<string>, CensoredString<string>>]>, z.ZodTransform<CensoredString<string>, string | CensoredString<string>>>>;
|
|
8
|
-
prefix: z.ZodOptional<z.ZodString>;
|
|
9
|
-
}, z.core.$strip>;
|
|
10
|
-
export type TelegramConfig = z.infer<typeof TelegramConfig>;
|
|
11
|
-
export declare const SlackConfig: z.ZodObject<{
|
|
12
|
-
type: z.ZodLiteral<"slack">;
|
|
13
|
-
webhookUrl: z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<CensoredString<string>, CensoredString<string>>]>, z.ZodTransform<CensoredString<string>, string | CensoredString<string>>>;
|
|
14
|
-
alertsOnly: z.ZodOptional<z.ZodPipe<z.ZodAny, z.ZodTransform<boolean, any>>>;
|
|
15
|
-
}, z.core.$strip>;
|
|
16
|
-
export type SlackConfig = z.infer<typeof SlackConfig>;
|
|
17
|
-
export declare const NotificationConfig: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
18
|
-
type: z.ZodLiteral<"telegram">;
|
|
19
|
-
token: z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<CensoredString<string>, CensoredString<string>>]>, z.ZodTransform<CensoredString<string>, string | CensoredString<string>>>;
|
|
20
|
-
alertsChannel: z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<CensoredString<string>, CensoredString<string>>]>, z.ZodTransform<CensoredString<string>, string | CensoredString<string>>>;
|
|
21
|
-
notificationsChannel: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<CensoredString<string>, CensoredString<string>>]>, z.ZodTransform<CensoredString<string>, string | CensoredString<string>>>>;
|
|
22
|
-
prefix: z.ZodOptional<z.ZodString>;
|
|
23
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
24
|
-
type: z.ZodLiteral<"slack">;
|
|
25
|
-
webhookUrl: z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<CensoredString<string>, CensoredString<string>>]>, z.ZodTransform<CensoredString<string>, string | CensoredString<string>>>;
|
|
26
|
-
alertsOnly: z.ZodOptional<z.ZodPipe<z.ZodAny, z.ZodTransform<boolean, any>>>;
|
|
27
|
-
}, z.core.$strip>], "type">;
|
|
28
|
-
export type NotificationConfig = z.infer<typeof NotificationConfig>;
|
|
29
|
-
export declare const SignlConfig: z.ZodObject<{
|
|
30
|
-
apiKey: z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<CensoredString<string>, CensoredString<string>>]>, z.ZodTransform<CensoredString<string>, string | CensoredString<string>>>;
|
|
31
|
-
teamId: z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<CensoredString<string>, CensoredString<string>>]>, z.ZodTransform<CensoredString<string>, string | CensoredString<string>>>;
|
|
32
|
-
}, z.core.$strip>;
|
|
33
|
-
export type SignlConfig = z.infer<typeof SignlConfig>;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { z } from "zod/v4";
|
|
2
|
-
import { CensoredString } from "../CensoredString.js";
|
|
3
|
-
import { boolLike } from "../schema-primitives.js";
|
|
4
|
-
export const TelegramConfig = z.object({
|
|
5
|
-
type: z.literal("telegram"),
|
|
6
|
-
token: z
|
|
7
|
-
.union([z.string(), z.instanceof(CensoredString)])
|
|
8
|
-
.transform(CensoredString.transform),
|
|
9
|
-
alertsChannel: z
|
|
10
|
-
.union([z.string().startsWith("-"), z.instanceof(CensoredString)])
|
|
11
|
-
.transform(CensoredString.transform),
|
|
12
|
-
/**
|
|
13
|
-
* Optional channel to send notifications to
|
|
14
|
-
* If not set, notifications will not be sent
|
|
15
|
-
*/
|
|
16
|
-
notificationsChannel: z
|
|
17
|
-
.union([z.string().startsWith("-"), z.instanceof(CensoredString)])
|
|
18
|
-
.transform(CensoredString.transform)
|
|
19
|
-
.optional(),
|
|
20
|
-
prefix: z.string().optional(),
|
|
21
|
-
});
|
|
22
|
-
export const SlackConfig = z.object({
|
|
23
|
-
type: z.literal("slack"),
|
|
24
|
-
/**
|
|
25
|
-
* Slack webhook URL for sending notifications
|
|
26
|
-
*/
|
|
27
|
-
webhookUrl: z
|
|
28
|
-
.union([z.string(), z.instanceof(CensoredString)])
|
|
29
|
-
.transform(CensoredString.transform),
|
|
30
|
-
/**
|
|
31
|
-
* If true, only alerts will be sent. Informational notifications are suppressed
|
|
32
|
-
*/
|
|
33
|
-
alertsOnly: boolLike().optional(),
|
|
34
|
-
});
|
|
35
|
-
export const NotificationConfig = z.discriminatedUnion("type", [
|
|
36
|
-
TelegramConfig,
|
|
37
|
-
SlackConfig,
|
|
38
|
-
]);
|
|
39
|
-
export const SignlConfig = z.object({
|
|
40
|
-
apiKey: z
|
|
41
|
-
.union([z.string(), z.instanceof(CensoredString)])
|
|
42
|
-
.transform(CensoredString.transform),
|
|
43
|
-
teamId: z
|
|
44
|
-
.union([z.string(), z.instanceof(CensoredString)])
|
|
45
|
-
.transform(CensoredString.transform),
|
|
46
|
-
});
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import type { Markdown } from "@vlad-yakovlev/telegram-md";
|
|
2
|
-
import type { Address } from "viem";
|
|
3
|
-
import type { NotificationConfig } from "./schema.js";
|
|
4
|
-
export type NotificationSeverity = "alert" | "notification";
|
|
5
|
-
/**
|
|
6
|
-
* Notification that can be deduplicated
|
|
7
|
-
*/
|
|
8
|
-
export interface IDedupableNotification {
|
|
9
|
-
/**
|
|
10
|
-
* Messages with the same dedupe key will be throttled to avoid spam
|
|
11
|
-
* If not provided, the message will not be throttled
|
|
12
|
-
*/
|
|
13
|
-
dedupeKey?: string;
|
|
14
|
-
/**
|
|
15
|
-
* Function to calculate the wait time between deduped messages
|
|
16
|
-
* If not provided, the default backoff will be used
|
|
17
|
-
*/
|
|
18
|
-
throttleFn?: ThrottleFn;
|
|
19
|
-
/**
|
|
20
|
-
* Plaintext notification message
|
|
21
|
-
*/
|
|
22
|
-
plain: string;
|
|
23
|
-
/**
|
|
24
|
-
* Optional markdown verison of notification message
|
|
25
|
-
*/
|
|
26
|
-
md?: Markdown;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Function to calculate the wait time between deduped messages
|
|
30
|
-
* @param prevWaitMs The wait time of the previous message, 0 for the first message
|
|
31
|
-
* @returns The wait time for the next message in milliseconds
|
|
32
|
-
*/
|
|
33
|
-
export type ThrottleFn = (prevWaitMs: number) => number;
|
|
34
|
-
/**
|
|
35
|
-
* Implement this interface for your notification classes
|
|
36
|
-
*/
|
|
37
|
-
export interface INotification {
|
|
38
|
-
/**
|
|
39
|
-
* Function to generate the message for a recipient. Undefined means global message (gearbox notifications)
|
|
40
|
-
* This allows us to put the logic to fan out message to different recipients inside the class that implements INotificationMessage,
|
|
41
|
-
* and not to put this logic into the service that sends the notifications (you can still put it there, though)
|
|
42
|
-
*
|
|
43
|
-
* @param recipient The recipient to generate the message for, or undefined for the default/global recipient (gearbox notifications)
|
|
44
|
-
* @returns The message for the recipient, or undefined for no message
|
|
45
|
-
*/
|
|
46
|
-
messageFor: (recipient?: Address) => string | IDedupableNotification | undefined;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* A notification message, dumb strings and markdowns are treated as global notifications
|
|
50
|
-
*/
|
|
51
|
-
export type NotificationLike = string | IDedupableNotification | INotification;
|
|
52
|
-
/**
|
|
53
|
-
* Notification service with deduplication and fan out logic
|
|
54
|
-
*/
|
|
55
|
-
export interface INotificationService {
|
|
56
|
-
/**
|
|
57
|
-
* Send an alert to Signl
|
|
58
|
-
* @param message
|
|
59
|
-
* @param dedupeKey
|
|
60
|
-
* Messages with the same dedupe key will be throttled to avoid spam
|
|
61
|
-
* If not provided, the message will not be throttled
|
|
62
|
-
* @returns
|
|
63
|
-
*/
|
|
64
|
-
signl: (message: string, dedupeKey?: string) => void;
|
|
65
|
-
/**
|
|
66
|
-
* Sends high priority notification
|
|
67
|
-
* @param message
|
|
68
|
-
* @returns
|
|
69
|
-
*/
|
|
70
|
-
alert: (message: NotificationLike) => void;
|
|
71
|
-
/**
|
|
72
|
-
* Sends low priority notification
|
|
73
|
-
* @param message
|
|
74
|
-
* @returns
|
|
75
|
-
*/
|
|
76
|
-
notify: (message: NotificationLike) => void;
|
|
77
|
-
/**
|
|
78
|
-
* Register a recipient for notifications
|
|
79
|
-
* @param address The address of the recipient
|
|
80
|
-
* @param options The options for the recipient
|
|
81
|
-
*/
|
|
82
|
-
registerRecipient: (address: Address, options: NotificationConfig) => void;
|
|
83
|
-
}
|
|
84
|
-
export interface INotifier {
|
|
85
|
-
/**
|
|
86
|
-
* Sends notification
|
|
87
|
-
* @param message
|
|
88
|
-
* @returns
|
|
89
|
-
*/
|
|
90
|
-
notify: (message: IDedupableNotification, severity: NotificationSeverity) => void;
|
|
91
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { z } from "zod/v4";
|
|
2
|
-
import { CensoredString } from "./CensoredString.js";
|
|
3
|
-
import { CensoredURL } from "./CensoredURL.js";
|
|
4
|
-
export declare const RpcProvider: z.ZodEnum<{
|
|
5
|
-
custom: "custom";
|
|
6
|
-
alchemy: "alchemy";
|
|
7
|
-
drpc: "drpc";
|
|
8
|
-
ankr: "ankr";
|
|
9
|
-
thirdweb: "thirdweb";
|
|
10
|
-
erpc: "erpc";
|
|
11
|
-
}>;
|
|
12
|
-
export type RpcProvider = z.infer<typeof RpcProvider>;
|
|
13
|
-
export declare const ProvidersSchema: z.ZodObject<{
|
|
14
|
-
network: z.ZodEnum<{
|
|
15
|
-
Mainnet: "Mainnet";
|
|
16
|
-
Arbitrum: "Arbitrum";
|
|
17
|
-
Optimism: "Optimism";
|
|
18
|
-
Base: "Base";
|
|
19
|
-
Sonic: "Sonic";
|
|
20
|
-
MegaETH: "MegaETH";
|
|
21
|
-
Monad: "Monad";
|
|
22
|
-
Berachain: "Berachain";
|
|
23
|
-
Avalanche: "Avalanche";
|
|
24
|
-
BNB: "BNB";
|
|
25
|
-
WorldChain: "WorldChain";
|
|
26
|
-
Etherlink: "Etherlink";
|
|
27
|
-
Hemi: "Hemi";
|
|
28
|
-
Lisk: "Lisk";
|
|
29
|
-
Plasma: "Plasma";
|
|
30
|
-
Somnia: "Somnia";
|
|
31
|
-
}>;
|
|
32
|
-
jsonRpcProviders: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodPipe<z.ZodString, z.ZodTransform<string[], string>>]>, z.ZodArray<z.ZodPipe<z.ZodURL, z.ZodTransform<CensoredURL, string>>>>, z.ZodTransform<CensoredURL[] | undefined, CensoredURL[]>>>;
|
|
33
|
-
enabledProviders: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodPipe<z.ZodString, z.ZodTransform<string[], string>>]>, z.ZodArray<z.ZodEnum<{
|
|
34
|
-
custom: "custom";
|
|
35
|
-
alchemy: "alchemy";
|
|
36
|
-
drpc: "drpc";
|
|
37
|
-
ankr: "ankr";
|
|
38
|
-
thirdweb: "thirdweb";
|
|
39
|
-
erpc: "erpc";
|
|
40
|
-
}>>>>;
|
|
41
|
-
alchemyKeys: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodPipe<z.ZodString, z.ZodTransform<string[], string>>]>, z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<CensoredString<string>, string>>>>, z.ZodTransform<CensoredString<string>[] | undefined, CensoredString<string>[]>>>;
|
|
42
|
-
drpcKeys: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodPipe<z.ZodString, z.ZodTransform<string[], string>>]>, z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<CensoredString<string>, string>>>>, z.ZodTransform<CensoredString<string>[] | undefined, CensoredString<string>[]>>>;
|
|
43
|
-
ankrKeys: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodPipe<z.ZodString, z.ZodTransform<string[], string>>]>, z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<CensoredString<string>, string>>>>, z.ZodTransform<CensoredString<string>[] | undefined, CensoredString<string>[]>>>;
|
|
44
|
-
thirdwebKeys: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodPipe<z.ZodString, z.ZodTransform<string[], string>>]>, z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<CensoredString<string>, string>>>>, z.ZodTransform<CensoredString<string>[] | undefined, CensoredString<string>[]>>>;
|
|
45
|
-
erpcProjectId: z.ZodOptional<z.ZodString>;
|
|
46
|
-
erpcUrl: z.ZodDefault<z.ZodURL>;
|
|
47
|
-
jsonRpcTimeout: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
48
|
-
}, z.core.$strip>;
|
|
49
|
-
export type ProvidersSchema = z.infer<typeof ProvidersSchema>;
|
package/dist/providers-schema.js
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { SUPPORTED_NETWORKS } from "@gearbox-protocol/sdk";
|
|
2
|
-
import { z } from "zod/v4";
|
|
3
|
-
import { CensoredString } from "./CensoredString.js";
|
|
4
|
-
import { CensoredURL } from "./CensoredURL.js";
|
|
5
|
-
import { stringArrayLike } from "./schema-primitives.js";
|
|
6
|
-
import { zommandRegistry } from "./Zommand.js";
|
|
7
|
-
export const RpcProvider = z.enum([
|
|
8
|
-
"alchemy",
|
|
9
|
-
"drpc",
|
|
10
|
-
"ankr",
|
|
11
|
-
"thirdweb",
|
|
12
|
-
"custom",
|
|
13
|
-
"erpc",
|
|
14
|
-
]);
|
|
15
|
-
export const ProvidersSchema = z.object({
|
|
16
|
-
network: z.enum(SUPPORTED_NETWORKS).register(zommandRegistry, {
|
|
17
|
-
flags: "--network <network>",
|
|
18
|
-
description: "Gearbox-supported network",
|
|
19
|
-
env: "NETWORK",
|
|
20
|
-
}),
|
|
21
|
-
/**
|
|
22
|
-
* RPC providers to use
|
|
23
|
-
*/
|
|
24
|
-
jsonRpcProviders: stringArrayLike()
|
|
25
|
-
.pipe(z.array(z.url().transform(CensoredURL.transform)))
|
|
26
|
-
.transform(a => (a.length ? a : undefined))
|
|
27
|
-
.optional()
|
|
28
|
-
.register(zommandRegistry, {
|
|
29
|
-
flags: "--json-rpc-providers <urls...>",
|
|
30
|
-
description: "RPC providers to use, comma separated full http urls.",
|
|
31
|
-
env: "JSON_RPC_PROVIDERS",
|
|
32
|
-
}),
|
|
33
|
-
/**
|
|
34
|
-
* RPC providers to use with their keys
|
|
35
|
-
* Order matters
|
|
36
|
-
*/
|
|
37
|
-
enabledProviders: stringArrayLike()
|
|
38
|
-
.pipe(z.array(RpcProvider))
|
|
39
|
-
.optional()
|
|
40
|
-
.register(zommandRegistry, {
|
|
41
|
-
flags: "--enabled-providers <providers...>",
|
|
42
|
-
description: "Keyed RPC providers to use, comma separated, order matters. Possible values: custom (for full json rpc urls)/alchemy/drpc/ankr/thirdweb",
|
|
43
|
-
env: "ENABLED_PROVIDERS",
|
|
44
|
-
}),
|
|
45
|
-
/**
|
|
46
|
-
* Alchemy API keys to use
|
|
47
|
-
*/
|
|
48
|
-
alchemyKeys: stringArrayLike()
|
|
49
|
-
.pipe(z.array(z.string().transform(CensoredString.transform)))
|
|
50
|
-
.transform(a => (a.length ? a : undefined))
|
|
51
|
-
.optional()
|
|
52
|
-
.register(zommandRegistry, {
|
|
53
|
-
flags: "--alchemy-keys <keys...>",
|
|
54
|
-
description: "Alchemy API keys to use, comma separated",
|
|
55
|
-
env: "ALCHEMY_KEYS",
|
|
56
|
-
}),
|
|
57
|
-
/**
|
|
58
|
-
* DRPC API keys to use
|
|
59
|
-
*/
|
|
60
|
-
drpcKeys: stringArrayLike()
|
|
61
|
-
.pipe(z.array(z.string().transform(CensoredString.transform)))
|
|
62
|
-
.transform(a => (a.length ? a : undefined))
|
|
63
|
-
.optional()
|
|
64
|
-
.register(zommandRegistry, {
|
|
65
|
-
flags: "--drpc-keys <keys...>",
|
|
66
|
-
description: "DRPC API keys to use, comma separated",
|
|
67
|
-
env: "DRPC_KEYS",
|
|
68
|
-
}),
|
|
69
|
-
/**
|
|
70
|
-
* Ankr API keys to use
|
|
71
|
-
*/
|
|
72
|
-
ankrKeys: stringArrayLike()
|
|
73
|
-
.pipe(z.array(z.string().transform(CensoredString.transform)))
|
|
74
|
-
.transform(a => (a.length ? a : undefined))
|
|
75
|
-
.optional()
|
|
76
|
-
.register(zommandRegistry, {
|
|
77
|
-
flags: "--ankr-keys <keys...>",
|
|
78
|
-
description: "Ankr API keys to use, comma separated",
|
|
79
|
-
env: "ANKR_KEYS",
|
|
80
|
-
}),
|
|
81
|
-
/**
|
|
82
|
-
* Thirdweb API keys to use
|
|
83
|
-
*/
|
|
84
|
-
thirdwebKeys: stringArrayLike()
|
|
85
|
-
.pipe(z.array(z.string().transform(CensoredString.transform)))
|
|
86
|
-
.transform(a => (a.length ? a : undefined))
|
|
87
|
-
.optional()
|
|
88
|
-
.register(zommandRegistry, {
|
|
89
|
-
flags: "--thirdweb-keys <keys...>",
|
|
90
|
-
description: "Thirdweb API keys to use, comma separated",
|
|
91
|
-
env: "THIRDWEB_KEYS",
|
|
92
|
-
}),
|
|
93
|
-
/**
|
|
94
|
-
* If set, eRPC will be added as first provider
|
|
95
|
-
*/
|
|
96
|
-
erpcProjectId: z.string().optional().register(zommandRegistry, {
|
|
97
|
-
flags: "--erpc-project-id <project-id>",
|
|
98
|
-
description: "If set, eRPC will be added as first provider",
|
|
99
|
-
env: "ERPC_PROJECT_ID",
|
|
100
|
-
}),
|
|
101
|
-
/**
|
|
102
|
-
* eRPC URL to use
|
|
103
|
-
*/
|
|
104
|
-
erpcUrl: z.url().default("http://erpc.local").register(zommandRegistry, {
|
|
105
|
-
flags: "--erpc-url <url>",
|
|
106
|
-
description: "eRPC URL to use",
|
|
107
|
-
env: "ERPC_URL",
|
|
108
|
-
}),
|
|
109
|
-
/**
|
|
110
|
-
* Timeout for JSON RPC requests, in milliseconds
|
|
111
|
-
*/
|
|
112
|
-
jsonRpcTimeout: z.coerce
|
|
113
|
-
.number()
|
|
114
|
-
.int()
|
|
115
|
-
.positive()
|
|
116
|
-
.optional()
|
|
117
|
-
.register(zommandRegistry, {
|
|
118
|
-
flags: "--json-rpc-timeout <timeout>",
|
|
119
|
-
description: "Timeout for JSON RPC requests, in milliseconds",
|
|
120
|
-
env: "JSON_RPC_TIMEOUT",
|
|
121
|
-
}),
|
|
122
|
-
});
|
package/dist/providers.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { type NetworkType } from "@gearbox-protocol/sdk";
|
|
2
|
-
export declare function getAlchemyUrl(network: NetworkType, apiKey: string, protocol?: "http" | "ws"): string | undefined;
|
|
3
|
-
export declare function getDrpcUrl(network: NetworkType, apiKey: string, protocol?: "http" | "ws"): string | undefined;
|
|
4
|
-
export declare function getAnkrUrl(network: NetworkType, apiKey: string, protocol?: "http" | "ws"): string | undefined;
|
|
5
|
-
export declare function getThirdWebUrl(network: NetworkType, apiKey: string, protocol?: "http" | "ws"): string | undefined;
|
|
6
|
-
export declare function getErpcKey(network: NetworkType, projectId?: string, urlBase?: string): string | undefined;
|
package/dist/providers.js
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { chains, getChain } from "@gearbox-protocol/sdk";
|
|
2
|
-
export function getAlchemyUrl(network, apiKey, protocol = "http") {
|
|
3
|
-
const alchemyDomain = ALCHEMY_DOMAINS[network];
|
|
4
|
-
if (!alchemyDomain) {
|
|
5
|
-
return undefined;
|
|
6
|
-
}
|
|
7
|
-
return `${protocol}s://${alchemyDomain}.g.alchemy.com/v2/${apiKey}`;
|
|
8
|
-
}
|
|
9
|
-
const DRPC_NETS = {
|
|
10
|
-
Arbitrum: "arbitrum",
|
|
11
|
-
Base: "base",
|
|
12
|
-
BNB: "bsc",
|
|
13
|
-
Mainnet: "ethereum",
|
|
14
|
-
Optimism: "optimism",
|
|
15
|
-
Sonic: "sonic",
|
|
16
|
-
WorldChain: "worldchain",
|
|
17
|
-
Berachain: "berachain",
|
|
18
|
-
Avalanche: "avalanche",
|
|
19
|
-
Monad: "monad",
|
|
20
|
-
Hemi: "hemi",
|
|
21
|
-
Lisk: "lisk",
|
|
22
|
-
MegaETH: null,
|
|
23
|
-
Etherlink: null,
|
|
24
|
-
Plasma: "plasma",
|
|
25
|
-
Somnia: null,
|
|
26
|
-
};
|
|
27
|
-
const ALCHEMY_DOMAINS = {
|
|
28
|
-
Mainnet: "eth-mainnet",
|
|
29
|
-
Arbitrum: "arb-mainnet",
|
|
30
|
-
Optimism: "opt-mainnet",
|
|
31
|
-
Base: "base-mainnet",
|
|
32
|
-
Sonic: "sonic-mainnet",
|
|
33
|
-
Monad: "monad-mainnet",
|
|
34
|
-
Berachain: "berachain-mainnet",
|
|
35
|
-
Avalanche: "avax-mainnet",
|
|
36
|
-
BNB: "bnb-mainnet",
|
|
37
|
-
WorldChain: "worldchain-mainnet",
|
|
38
|
-
MegaETH: null,
|
|
39
|
-
Etherlink: null,
|
|
40
|
-
Hemi: null,
|
|
41
|
-
Lisk: null,
|
|
42
|
-
Plasma: "plasma-mainnet",
|
|
43
|
-
Somnia: null,
|
|
44
|
-
};
|
|
45
|
-
export function getDrpcUrl(network, apiKey, protocol = "http") {
|
|
46
|
-
const net = DRPC_NETS[network];
|
|
47
|
-
return net ? `${protocol}s://lb.drpc.org/${net}/${apiKey}` : undefined;
|
|
48
|
-
}
|
|
49
|
-
const ANKR_DOMAINS = {
|
|
50
|
-
Arbitrum: "arbitrum",
|
|
51
|
-
Avalanche: "avalanche",
|
|
52
|
-
Base: "base",
|
|
53
|
-
Berachain: null,
|
|
54
|
-
BNB: "bsc",
|
|
55
|
-
Etherlink: "etherlink_mainnet",
|
|
56
|
-
Hemi: null,
|
|
57
|
-
Lisk: null,
|
|
58
|
-
Mainnet: "eth",
|
|
59
|
-
MegaETH: null,
|
|
60
|
-
Monad: null,
|
|
61
|
-
Optimism: "optimism",
|
|
62
|
-
Plasma: null,
|
|
63
|
-
Sonic: "sonic_mainnet",
|
|
64
|
-
WorldChain: null,
|
|
65
|
-
Somnia: "somnia_mainnet",
|
|
66
|
-
};
|
|
67
|
-
export function getAnkrUrl(network, apiKey, protocol = "http") {
|
|
68
|
-
const net = ANKR_DOMAINS[network];
|
|
69
|
-
const sep = protocol === "ws" ? "/ws/" : "/";
|
|
70
|
-
return net ? `${protocol}s://rpc.ankr.com/${net}${sep}${apiKey}` : undefined;
|
|
71
|
-
}
|
|
72
|
-
const THIRDWEB_DOMAINS = {
|
|
73
|
-
Arbitrum: chains.Arbitrum.id.toString(),
|
|
74
|
-
Avalanche: chains.Avalanche.id.toString(),
|
|
75
|
-
Base: chains.Base.id.toString(),
|
|
76
|
-
Berachain: chains.Berachain.id.toString(),
|
|
77
|
-
BNB: chains.BNB.id.toString(),
|
|
78
|
-
Etherlink: chains.Etherlink.id.toString(),
|
|
79
|
-
Hemi: chains.Hemi.id.toString(),
|
|
80
|
-
Lisk: chains.Lisk.id.toString(),
|
|
81
|
-
Mainnet: chains.Mainnet.id.toString(),
|
|
82
|
-
MegaETH: chains.MegaETH.id.toString(),
|
|
83
|
-
Monad: chains.Monad.id.toString(),
|
|
84
|
-
Optimism: chains.Optimism.id.toString(),
|
|
85
|
-
Plasma: chains.Plasma.id.toString(),
|
|
86
|
-
Sonic: chains.Sonic.id.toString(),
|
|
87
|
-
WorldChain: chains.WorldChain.id.toString(),
|
|
88
|
-
Somnia: chains.Somnia.id.toString(),
|
|
89
|
-
};
|
|
90
|
-
export function getThirdWebUrl(network, apiKey, protocol = "http") {
|
|
91
|
-
if (protocol === "ws") {
|
|
92
|
-
return undefined;
|
|
93
|
-
}
|
|
94
|
-
const net = THIRDWEB_DOMAINS[network];
|
|
95
|
-
return `https://${net}.rpc.thirdweb.com/${apiKey}`;
|
|
96
|
-
}
|
|
97
|
-
export function getErpcKey(network, projectId, urlBase) {
|
|
98
|
-
if (!projectId || !urlBase) {
|
|
99
|
-
return undefined;
|
|
100
|
-
}
|
|
101
|
-
const chain = getChain(network);
|
|
102
|
-
return `${urlBase}/${projectId}/evm/${chain.id}`;
|
|
103
|
-
}
|