@gearbox-protocol/cli-utils 6.10.1 → 6.13.0
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/Whitelist.d.ts +30 -0
- package/dist/Whitelist.js +83 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { WhitelistItemSchema } from "@gearbox-protocol/deploy-tools-shared";
|
|
2
|
+
import type { ILogger, NetworkType } from "@gearbox-protocol/sdk";
|
|
3
|
+
export interface WhitelistOptions {
|
|
4
|
+
url: string;
|
|
5
|
+
network: NetworkType;
|
|
6
|
+
logger?: ILogger;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Fetches a network-scoped whitelist from the deploy-tools backend and keeps
|
|
10
|
+
* it in memory with a 10-minute refresh interval.
|
|
11
|
+
*
|
|
12
|
+
* On fetch failure the previous in-memory copy is retained; if no successful
|
|
13
|
+
* fetch has occurred yet the whitelist is considered empty.
|
|
14
|
+
*/
|
|
15
|
+
export declare class Whitelist {
|
|
16
|
+
#private;
|
|
17
|
+
constructor({ url, network, logger }: WhitelistOptions);
|
|
18
|
+
/**
|
|
19
|
+
* Performs the initial fetch and starts the periodic refresh timer.
|
|
20
|
+
* Failure of the initial fetch is non-fatal: the whitelist stays empty.
|
|
21
|
+
*/
|
|
22
|
+
start(): Promise<void>;
|
|
23
|
+
/** Stops the refresh timer. */
|
|
24
|
+
stop(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Returns the matching whitelist entry for the given address, or
|
|
27
|
+
* `undefined` if absent or expired.
|
|
28
|
+
*/
|
|
29
|
+
has(address: string): WhitelistItemSchema | undefined;
|
|
30
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { setInterval } from "node:timers";
|
|
2
|
+
import { fetchRetry, WhitelistItemSchema, } from "@gearbox-protocol/deploy-tools-shared";
|
|
3
|
+
import { AddressMap } from "@gearbox-protocol/sdk";
|
|
4
|
+
import { z } from "zod/v4";
|
|
5
|
+
const REFRESH_INTERVAL_MS = 10 * 60 * 1000;
|
|
6
|
+
const WhitelistResponse = z.array(WhitelistItemSchema);
|
|
7
|
+
/**
|
|
8
|
+
* Fetches a network-scoped whitelist from the deploy-tools backend and keeps
|
|
9
|
+
* it in memory with a 10-minute refresh interval.
|
|
10
|
+
*
|
|
11
|
+
* On fetch failure the previous in-memory copy is retained; if no successful
|
|
12
|
+
* fetch has occurred yet the whitelist is considered empty.
|
|
13
|
+
*/
|
|
14
|
+
export class Whitelist {
|
|
15
|
+
#url;
|
|
16
|
+
#network;
|
|
17
|
+
#logger;
|
|
18
|
+
#items = new AddressMap();
|
|
19
|
+
#refreshInterval;
|
|
20
|
+
constructor({ url, network, logger }) {
|
|
21
|
+
this.#url = url;
|
|
22
|
+
this.#network = network;
|
|
23
|
+
this.#logger = logger?.child?.({ name: "whitelist" }) ?? logger;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Performs the initial fetch and starts the periodic refresh timer.
|
|
27
|
+
* Failure of the initial fetch is non-fatal: the whitelist stays empty.
|
|
28
|
+
*/
|
|
29
|
+
async start() {
|
|
30
|
+
this.#logger?.info(`loading ${this.#network} whitelist from ${this.#url}, refresh every ${REFRESH_INTERVAL_MS / 1000}s`);
|
|
31
|
+
await this.#refresh();
|
|
32
|
+
this.#refreshInterval = setInterval(() => {
|
|
33
|
+
this.#refresh().catch(e => {
|
|
34
|
+
this.#logger?.warn(`unexpected whitelist refresh error: ${e}`);
|
|
35
|
+
});
|
|
36
|
+
}, REFRESH_INTERVAL_MS);
|
|
37
|
+
}
|
|
38
|
+
/** Stops the refresh timer. */
|
|
39
|
+
stop() {
|
|
40
|
+
if (this.#refreshInterval) {
|
|
41
|
+
clearInterval(this.#refreshInterval);
|
|
42
|
+
this.#refreshInterval = undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Fetches the whitelist from the backend, parses it and atomically
|
|
47
|
+
* replaces the in-memory map. On any error logs a warning and retains
|
|
48
|
+
* the previous map.
|
|
49
|
+
*/
|
|
50
|
+
async #refresh() {
|
|
51
|
+
try {
|
|
52
|
+
const resp = await fetchRetry(this.#url);
|
|
53
|
+
if (!resp.ok) {
|
|
54
|
+
throw new Error(`whitelist fetch failed: ${resp.status} ${resp.statusText}`);
|
|
55
|
+
}
|
|
56
|
+
const data = await resp.json();
|
|
57
|
+
const items = WhitelistResponse.parse(data).filter(i => i.network === this.#network);
|
|
58
|
+
const next = new AddressMap();
|
|
59
|
+
for (const item of items) {
|
|
60
|
+
next.upsert(item.address, item);
|
|
61
|
+
}
|
|
62
|
+
this.#items = next;
|
|
63
|
+
this.#logger?.debug(`loaded ${items.length} whitelist entries for ${this.#network}`);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
this.#logger?.warn(`failed to refresh whitelist from ${this.#url}, keeping previous version: ${e}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Returns the matching whitelist entry for the given address, or
|
|
71
|
+
* `undefined` if absent or expired.
|
|
72
|
+
*/
|
|
73
|
+
has(address) {
|
|
74
|
+
const item = this.#items.get(address);
|
|
75
|
+
if (!item) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
if (item.expiresAt !== undefined && Date.now() / 1000 >= item.expiresAt) {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
return item;
|
|
82
|
+
}
|
|
83
|
+
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED