@gearbox-protocol/liquidator-v2-config 9.2.0 → 9.2.2

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.js CHANGED
@@ -1,548 +1,509 @@
1
- // src/config.ts
2
- import { createPublicClient } from "viem";
3
- var ConfigImplementation = class {
4
- #startBlock;
5
- #chainId;
6
- constructor(schema) {
7
- Object.assign(this, schema);
8
- }
9
- async initialize(transport) {
10
- const client = createPublicClient({
11
- transport,
12
- name: "preload client"
13
- });
14
- const [startBlock, chainId] = await Promise.all([
15
- client.getBlockNumber(),
16
- client.getChainId()
17
- ]);
18
- this.#startBlock = startBlock;
19
- this.#chainId = chainId;
20
- }
21
- get startBlock() {
22
- if (this.#startBlock === void 0) {
23
- throw new Error("config not initialized");
24
- }
25
- return this.#startBlock;
26
- }
27
- get chainId() {
28
- if (this.#chainId === void 0) {
29
- throw new Error("config not initialized");
30
- }
31
- return this.#chainId;
32
- }
33
- };
34
-
35
- // src/notifications.ts
36
- import { NotificationConfig } from "@gearbox-protocol/cli-utils";
1
+ import { createPublicClient, isHex } from "viem";
2
+ import { CensoredString, NotificationConfig, ProvidersSchema, addressLike, boolLike, clientWhitelistItemSchema, optionalAddressArrayLike, stringArrayLike, zommandRegistry } from "@gearbox-protocol/cli-utils";
37
3
  import { z } from "zod/v4";
38
- var extendedOptions = NotificationConfig.options.map(
39
- (o) => o.extend({
40
- /**
41
- * When undefined, defaults to all curators together (aka Gearbox internal)
42
- */
43
- curator: z.custom((s) => typeof s === "string").optional()
44
- })
45
- );
46
- var NotificationsConfig = z.object({
47
- notifications: z.array(
48
- z.discriminatedUnion(
49
- NotificationConfig.def.discriminator,
50
- extendedOptions
51
- )
52
- ).optional().default([])
53
- });
54
-
55
- // src/schema.ts
56
- import { z as z7 } from "zod/v4";
57
-
58
- // src/batch-liquidator.ts
59
- import { zommandRegistry as zommandRegistry2 } from "@gearbox-protocol/cli-utils";
60
- import { z as z3 } from "zod/v4";
61
-
62
- // src/common.ts
63
- import {
64
- addressLike,
65
- boolLike,
66
- CensoredString,
67
- clientWhitelistItemSchema,
68
- optionalAddressArrayLike,
69
- ProvidersSchema,
70
- stringArrayLike,
71
- zommandRegistry
72
- } from "@gearbox-protocol/cli-utils";
73
4
  import { MAX_UINT256, WAD } from "@gearbox-protocol/sdk";
74
- import { isHex } from "viem";
75
- import { z as z2 } from "zod/v4";
76
- var CommonSchema = z2.object({
77
- ...ProvidersSchema.shape,
78
- /**
79
- * By default uses address provider from @gearbox-protocol/sdk
80
- * Use this option to override address provider
81
- */
82
- addressProvider: addressLike().optional().register(zommandRegistry, {
83
- flags: "--address-provider <address>",
84
- description: "Address provider override, uses default value from SDK otherwise",
85
- env: "ADDRESS_PROVIDER"
86
- }),
87
- /**
88
- * Market configurators addresses to attach SDK
89
- */
90
- marketConfigurators: optionalAddressArrayLike().register(zommandRegistry, {
91
- flags: "--market-configurators <addresses...>",
92
- description: "Market configurators to use for the process, comma separated. Uses default value from SDK if not specified",
93
- env: "MARKET_CONFIGURATORS"
94
- }),
95
- /**
96
- * RWA factories addresses to attach SDK
97
- */
98
- rwaFactories: optionalAddressArrayLike().register(zommandRegistry, {
99
- flags: "--rwa-factories <addresses...>",
100
- description: "RWA factories to use for the process, comma separated. Uses default value from SDK if not specified",
101
- env: "RWA_FACTORIES"
102
- }),
103
- /**
104
- * App name used in various messages to distinguish instances
105
- */
106
- appName: z2.string().default("liquidator-ts").register(zommandRegistry, {
107
- flags: "--app-name <name>",
108
- description: "App name used in various messages to distinguish instances",
109
- env: "APP_NAME"
110
- }),
111
- /**
112
- * Port to expose some vital signals and metrics
113
- */
114
- port: z2.coerce.number().default(4e3).register(zommandRegistry, {
115
- flags: "--port <port>",
116
- description: "Port to expose some vital signals and metrics",
117
- env: "PORT"
118
- }),
119
- /**
120
- * Full URL of the whitelist endpoint. Entries can be credit account
121
- * addresses or credit manager addresses. Only applied in non-optimistic mode.
122
- */
123
- whitelistUrl: z2.url().optional().register(zommandRegistry, {
124
- flags: "--whitelist-url <url>",
125
- description: "Full URL of the liquidator soft whitelist endpoint. Entries are credit account or credit manager addresses. Does not prevent liquidation, but annotates failure notifications. Only applied in non-optimistic mode.",
126
- env: "WHITELIST_URL"
127
- }),
128
- /**
129
- * Static (hard) whitelist that prevents liquidation entirely.
130
- * Entries can be credit account, credit manager or token addresses.
131
- */
132
- hardWhitelist: z2.array(clientWhitelistItemSchema).optional(),
133
- /**
134
- * Only check this account during local debug session
135
- */
136
- debugAccount: addressLike().optional().register(zommandRegistry, {
137
- flags: "--debug-account <address>",
138
- description: "Only check this account during local debug session",
139
- env: "DEBUG_ACCOUNT"
140
- }),
141
- /**
142
- * Only check this credit manager during local debug session
143
- */
144
- debugManager: addressLike().optional().register(zommandRegistry, {
145
- flags: "--debug-manager <address>",
146
- description: "Only check this credit manager during local debug session",
147
- env: "DEBUG_MANAGER"
148
- }),
149
- /**
150
- * Path to foundry/cast binary, so that we can create tree-like traces in case of errors
151
- * Used during optimistic liquidations
152
- */
153
- castBin: z2.string().optional().register(zommandRegistry, {
154
- flags: "--cast-bin <path>",
155
- description: "Path to foundry/cast binary, so that we can create tree-like traces in case of errors",
156
- env: "CAST_BIN"
157
- }),
158
- /**
159
- * Timeout duration passed to `timeout` utility when running cast.
160
- * If unset, cast runs without a timeout. Accepts any value understood by `timeout(1)` (e.g. `30s`, `1m`).
161
- */
162
- castTimeout: z2.string().optional().default("1m").register(zommandRegistry, {
163
- flags: "--cast-timeout <duration>",
164
- description: "Timeout duration for cast invocations (e.g. 30s, 1m). If unset, cast runs without a timeout.",
165
- env: "CAST_TIMEOUT"
166
- }),
167
- /**
168
- * Stale block threshold in seconds, to notify and try to rotate rpc provider. 0 means no monitoring
169
- */
170
- staleBlockThreshold: z2.coerce.number().nonnegative().default(120).register(zommandRegistry, {
171
- flags: "--stale-block-threshold <threshold>",
172
- description: "Stale block threshold in seconds, to notify and try to rotate rpc provider. 0 means no monitoring",
173
- env: "STALE_BLOCK_THRESHOLD"
174
- }),
175
- /**
176
- * Max block range size for eth_getLogs
177
- */
178
- logsPageSize: z2.coerce.bigint().nonnegative().optional().register(zommandRegistry, {
179
- flags: "--logs-page-size <size>",
180
- description: "Max block range size for eth_getLogs",
181
- env: "LOGS_PAGE_SIZE"
182
- }),
183
- /**
184
- * Polling interval in milliseconds, default to what's default in viem
185
- */
186
- pollingInterval: z2.coerce.number().nonnegative().optional().register(zommandRegistry, {
187
- flags: "--polling-interval <interval>",
188
- description: "Polling interval in milliseconds, default to what's default in viem",
189
- env: "POLLING_INTERVAL"
190
- }),
191
- /**
192
- * Private key used to send liquidation transactions
193
- * Required in non-optimistic mode, must not be set in optimistic mode
194
- */
195
- privateKey: z2.string().min(1).transform((s) => {
196
- return isHex(s) ? s : `0x${s}`;
197
- }).transform(CensoredString.transform).optional().register(zommandRegistry, {
198
- flags: "--private-key <key>",
199
- description: "Private key used to send liquidation transactions. Required in non-optimistic mode, must not be set in optimistic mode",
200
- env: "PRIVATE_KEY"
201
- }),
202
- /**
203
- * Address to impersonate as transaction sender on anvil fork
204
- * Required in optimistic mode, must not be set in non-optimistic mode
205
- */
206
- liquidatorAddress: addressLike().optional().register(zommandRegistry, {
207
- flags: "--liquidator-address <address>",
208
- description: "Address to impersonate as transaction sender on anvil fork. Required in optimistic mode, must not be set in non-optimistic mode",
209
- env: "LIQUIDATOR_ADDRESS"
210
- }),
211
- /**
212
- * Minimum executor gas budget, in gas units. The required balance to send a
213
- * notification is computed as `minBalanceGas * currentGasPrice`.
214
- */
215
- minBalanceGas: z2.coerce.bigint().positive().default(85000000n).register(zommandRegistry, {
216
- flags: "--min-balance-gas <gas>",
217
- description: "Minimum executor gas budget (in gas units); required balance = this * current gas price",
218
- env: "MIN_BALANCE_GAS"
219
- }),
220
- /**
221
- * Filter out all accounts with HF >= threshold during scan stage
222
- */
223
- hfThreshold: z2.coerce.bigint().nonnegative().max(MAX_UINT256).default(WAD - 1n).register(zommandRegistry, {
224
- flags: "--hf-threshold <threshold>",
225
- description: "Filter out all accounts with HF >= threshold during scan stage",
226
- env: "HF_THRESHOLD"
227
- }),
228
- /**
229
- * Default numSplits for router v3.1 contract
230
- */
231
- numSplits: z2.coerce.bigint().positive().default(10n).register(zommandRegistry, {
232
- flags: "--num-splits <splits>",
233
- description: "Default numSplits for router v3.1 contract",
234
- env: "NUM_SPLITS"
235
- }),
236
- /**
237
- * Liquidator mode
238
- */
239
- liquidationMode: z2.enum(["full", "partial", "batch", "deleverage"]).default("full").register(zommandRegistry, {
240
- flags: "--liquidation-mode <mode>",
241
- description: "Liquidator mode (full/partial/batch/deleverage)",
242
- env: "LIQUIDATION_MODE"
243
- }),
244
- /**
245
- * Enable optimistic liquidations
246
- */
247
- optimistic: boolLike().optional().register(zommandRegistry, {
248
- flags: "--optimistic",
249
- description: "Enable optimistic liquidations",
250
- env: "OPTIMISTIC"
251
- }),
252
- /**
253
- * In optimistic mode, use real health factor range to scan for accounts
254
- * and do not force-enable deleverage bot on accounts.
255
- *
256
- * This mode can be used to test that deleverage bot is able to detect accounts correctly
257
- */
258
- useProductionScanner: boolLike().optional().register(zommandRegistry, {
259
- flags: "--use-production-scanner",
260
- description: "In optimistic mode, use real health factor range to scan for accounts and do not force-enable deleverage bot on accounts",
261
- env: "USE_PRODUCTION_SCANNER"
262
- }),
263
- /**
264
- * Optimistic timestamp to pass from external runner, in ms
265
- */
266
- optimisticTimestamp: z2.coerce.number().int().positive().nullish().register(zommandRegistry, {
267
- flags: "--optimistic-timestamp <timestamp>",
268
- description: "Optimistic timestamp to pass from external runner, in ms",
269
- env: "OPTIMISTIC_TIMESTAMP"
270
- }),
271
- /**
272
- * Fail on missing feeds (redstone and pyth)
273
- */
274
- failOnMissingFeeds: boolLike().optional().register(zommandRegistry, {
275
- flags: "--fail-on-missing-feeds",
276
- description: "Fail on missing feeds (redstone and pyth)",
277
- env: "FAIL_ON_MISSING_FEEDS"
278
- }),
279
- /**
280
- * Explicitly set gas limit for SDK
281
- * -1 to disable explicitly setting gas limit in SDK
282
- * If not set, SDK will use default gas limit
283
- */
284
- gasLimit: z2.coerce.bigint().optional().register(zommandRegistry, {
285
- flags: "--gas-limit <limit>",
286
- description: "Set gas limit for SDK",
287
- env: "GAS_LIMIT"
288
- }),
289
- /**
290
- * Do not send transactions in non-optimistic mode, just log them
291
- */
292
- dryRun: boolLike().optional().register(zommandRegistry, {
293
- flags: "--dry-run",
294
- description: "Do not send transactions in non-optimistic mode, just log them",
295
- env: "DRY_RUN"
296
- }),
297
- /**
298
- * Redstone gateways override
299
- * Set local caching proxies to avoid rate limiting in test environment
300
- */
301
- redstoneGateways: stringArrayLike().pipe(z2.array(z2.url())).transform((a) => a.length ? a : void 0).optional().register(zommandRegistry, {
302
- flags: "--redstone-gateways <urls...>",
303
- description: "Redstone gateways to use, comma separated",
304
- env: "REDSTONE_GATEWAYS"
305
- }),
306
- /**
307
- * Limit number of accounts to load from compressor. 0 = unlimited, let compressor decide
308
- */
309
- compressorBatchSize: z2.coerce.number().nonnegative().default(0).register(zommandRegistry, {
310
- flags: "--compressor-batch-size <size>",
311
- description: "Limit number of accounts to load from compressor. 0 = unlimited, let compressor decide",
312
- env: "COMPRESSOR_BATCH_SIZE"
313
- }),
314
- /**
315
- * Slippage value for pathfined
316
- */
317
- slippage: z2.coerce.number().min(0).max(1e4).int().default(50).register(zommandRegistry, {
318
- flags: "--slippage <value>",
319
- description: "Slippage value for pathfinder",
320
- env: "SLIPPAGE"
321
- }),
322
- /**
323
- * By default, reserve prices are not updated (except for deleverage mode)
324
- */
325
- updateReservePrices: boolLike().optional().default(false).register(zommandRegistry, {
326
- flags: "--update-reserve-prices",
327
- description: "Update reserve prices",
328
- env: "UPDATE_RESERVE_PRICES"
329
- }),
330
- /**
331
- * List of assets to keep on account after liquidation
332
- */
333
- keepAssets: optionalAddressArrayLike().register(zommandRegistry, {
334
- flags: "--keep-assets <assets...>",
335
- description: "List of assets to keep on account after liquidation",
336
- env: "KEEP_ASSETS"
337
- }),
338
- /**
339
- * Address that receives the liquidation premium and leftover underlying.
340
- * Defaults to the executor address when unset.
341
- */
342
- premiumReceiver: addressLike().optional().register(zommandRegistry, {
343
- flags: "--premium-receiver <address>",
344
- description: "Address that receives the liquidation premium and leftover underlying (defaults to executor address)",
345
- env: "PREMIUM_RECEIVER"
346
- }),
347
- /**
348
- * Directory to save json with optimistic liquidation results
349
- */
350
- outDir: z2.string().default(".").register(zommandRegistry, {
351
- flags: "--out-dir <dir>",
352
- description: "Directory to save json with optimistic liquidation results",
353
- env: "OUT_DIR"
354
- }),
355
- /**
356
- * REST endpoint to POST json with optimistic liquidation results
357
- */
358
- outEndpoint: z2.url().optional().register(zommandRegistry, {
359
- flags: "--out-endpoint <url>",
360
- description: "REST endpoint to POST json with optimistic liquidation results",
361
- env: "OUT_ENDPOINT"
362
- }),
363
- /**
364
- * Headers for REST endpoint
365
- */
366
- outHeaders: z2.string().default("{}").transform(CensoredString.transform).register(zommandRegistry, {
367
- flags: "--out-headers <headers>",
368
- description: "Headers for REST endpoint",
369
- env: "OUT_HEADERS"
370
- }),
371
- /**
372
- * s3 bucket to upload json with optimistic liquidation results
373
- */
374
- outS3Bucket: z2.string().optional().register(zommandRegistry, {
375
- flags: "--out-s3-bucket <bucket>",
376
- description: "S3 bucket to upload json with optimistic liquidation results",
377
- env: "OUT_S3_BUCKET"
378
- }),
379
- /**
380
- * s3 bucket path prefix
381
- */
382
- outS3Prefix: z2.string().default("").register(zommandRegistry, {
383
- flags: "--out-s3-prefix <prefix>",
384
- description: "S3 bucket path prefix",
385
- env: "OUT_S3_PREFIX"
386
- }),
387
- /**
388
- * Filename of json with optimistic liquidation results for s3 or dir output
389
- */
390
- outFileName: z2.string().optional().register(zommandRegistry, {
391
- flags: "--out-file-name <name>",
392
- description: "Filename of json with optimistic liquidation results for s3 or dir output",
393
- env: "OUT_FILE_NAME"
394
- }),
395
- /**
396
- * Notifications, global and per-curator
397
- */
398
- ...NotificationsConfig.shape
399
- });
400
-
401
- // src/batch-liquidator.ts
402
- var BatchLiquidatorSchema = z3.object({
403
- ...CommonSchema.shape,
404
- /**
405
- * Liquidator mode
406
- */
407
- liquidationMode: z3.literal("batch").register(zommandRegistry2, {
408
- flags: "--liquidation-mode <mode>",
409
- description: "Liquidator mode (full/partial/batch/deleverage)",
410
- env: "LIQUIDATION_MODE"
411
- }),
412
- /**
413
- * Number of accounts to liquidate at once using batch liquidator
414
- */
415
- batchSize: z3.coerce.number().nonnegative().default(10).register(zommandRegistry2, {
416
- flags: "--batch-size <size>",
417
- description: "Number of accounts to liquidate at once using batch liquidator",
418
- env: "BATCH_SIZE"
419
- })
5
+ //#region src/config.ts
6
+ var ConfigImplementation = class {
7
+ #startBlock;
8
+ #chainId;
9
+ constructor(schema) {
10
+ Object.assign(this, schema);
11
+ }
12
+ async initialize(transport) {
13
+ const client = createPublicClient({
14
+ transport,
15
+ name: "preload client"
16
+ });
17
+ const [startBlock, chainId] = await Promise.all([client.getBlockNumber(), client.getChainId()]);
18
+ this.#startBlock = startBlock;
19
+ this.#chainId = chainId;
20
+ }
21
+ get startBlock() {
22
+ if (this.#startBlock === void 0) throw new Error("config not initialized");
23
+ return this.#startBlock;
24
+ }
25
+ get chainId() {
26
+ if (this.#chainId === void 0) throw new Error("config not initialized");
27
+ return this.#chainId;
28
+ }
29
+ };
30
+ //#endregion
31
+ //#region src/notifications.ts
32
+ const extendedOptions = NotificationConfig.options.map((o) => o.extend({
33
+ /**
34
+ * When undefined, defaults to all curators together (aka Gearbox internal)
35
+ */
36
+ curator: z.custom((s) => typeof s === "string").optional() }));
37
+ const NotificationsConfig = z.object({ notifications: z.array(z.discriminatedUnion(NotificationConfig.def.discriminator, extendedOptions)).optional().default([]) });
38
+ //#endregion
39
+ //#region src/common.ts
40
+ const CommonSchema = z.object({
41
+ ...ProvidersSchema.shape,
42
+ /**
43
+ * By default uses address provider from @gearbox-protocol/sdk
44
+ * Use this option to override address provider
45
+ */
46
+ addressProvider: addressLike().optional().register(zommandRegistry, {
47
+ flags: "--address-provider <address>",
48
+ description: "Address provider override, uses default value from SDK otherwise",
49
+ env: "ADDRESS_PROVIDER"
50
+ }),
51
+ /**
52
+ * Market configurators addresses to attach SDK
53
+ */
54
+ marketConfigurators: optionalAddressArrayLike().register(zommandRegistry, {
55
+ flags: "--market-configurators <addresses...>",
56
+ description: "Market configurators to use for the process, comma separated. Uses default value from SDK if not specified",
57
+ env: "MARKET_CONFIGURATORS"
58
+ }),
59
+ /**
60
+ * RWA factories addresses to attach SDK
61
+ */
62
+ rwaFactories: optionalAddressArrayLike().register(zommandRegistry, {
63
+ flags: "--rwa-factories <addresses...>",
64
+ description: "RWA factories to use for the process, comma separated. Uses default value from SDK if not specified",
65
+ env: "RWA_FACTORIES"
66
+ }),
67
+ /**
68
+ * App name used in various messages to distinguish instances
69
+ */
70
+ appName: z.string().default("liquidator-ts").register(zommandRegistry, {
71
+ flags: "--app-name <name>",
72
+ description: "App name used in various messages to distinguish instances",
73
+ env: "APP_NAME"
74
+ }),
75
+ /**
76
+ * Port to expose some vital signals and metrics
77
+ */
78
+ port: z.coerce.number().default(4e3).register(zommandRegistry, {
79
+ flags: "--port <port>",
80
+ description: "Port to expose some vital signals and metrics",
81
+ env: "PORT"
82
+ }),
83
+ /**
84
+ * Full URL of the whitelist endpoint. Entries can be credit account
85
+ * addresses or credit manager addresses. Only applied in non-optimistic mode.
86
+ */
87
+ whitelistUrl: z.url().optional().register(zommandRegistry, {
88
+ flags: "--whitelist-url <url>",
89
+ description: "Full URL of the liquidator soft whitelist endpoint. Entries are credit account or credit manager addresses. Does not prevent liquidation, but annotates failure notifications. Only applied in non-optimistic mode.",
90
+ env: "WHITELIST_URL"
91
+ }),
92
+ /**
93
+ * Static (hard) whitelist that prevents liquidation entirely.
94
+ * Entries can be credit account, credit manager or token addresses.
95
+ */
96
+ hardWhitelist: z.array(clientWhitelistItemSchema).optional(),
97
+ /**
98
+ * Only check this account during local debug session
99
+ */
100
+ debugAccount: addressLike().optional().register(zommandRegistry, {
101
+ flags: "--debug-account <address>",
102
+ description: "Only check this account during local debug session",
103
+ env: "DEBUG_ACCOUNT"
104
+ }),
105
+ /**
106
+ * Only check this credit manager during local debug session
107
+ */
108
+ debugManager: addressLike().optional().register(zommandRegistry, {
109
+ flags: "--debug-manager <address>",
110
+ description: "Only check this credit manager during local debug session",
111
+ env: "DEBUG_MANAGER"
112
+ }),
113
+ /**
114
+ * Path to foundry/cast binary, so that we can create tree-like traces in case of errors
115
+ * Used during optimistic liquidations
116
+ */
117
+ castBin: z.string().optional().register(zommandRegistry, {
118
+ flags: "--cast-bin <path>",
119
+ description: "Path to foundry/cast binary, so that we can create tree-like traces in case of errors",
120
+ env: "CAST_BIN"
121
+ }),
122
+ /**
123
+ * Timeout duration passed to `timeout` utility when running cast.
124
+ * If unset, cast runs without a timeout. Accepts any value understood by `timeout(1)` (e.g. `30s`, `1m`).
125
+ */
126
+ castTimeout: z.string().optional().default("1m").register(zommandRegistry, {
127
+ flags: "--cast-timeout <duration>",
128
+ description: "Timeout duration for cast invocations (e.g. 30s, 1m). If unset, cast runs without a timeout.",
129
+ env: "CAST_TIMEOUT"
130
+ }),
131
+ /**
132
+ * Stale block threshold in seconds, to notify and try to rotate rpc provider. 0 means no monitoring
133
+ */
134
+ staleBlockThreshold: z.coerce.number().nonnegative().default(120).register(zommandRegistry, {
135
+ flags: "--stale-block-threshold <threshold>",
136
+ description: "Stale block threshold in seconds, to notify and try to rotate rpc provider. 0 means no monitoring",
137
+ env: "STALE_BLOCK_THRESHOLD"
138
+ }),
139
+ /**
140
+ * Max block range size for eth_getLogs
141
+ */
142
+ logsPageSize: z.coerce.bigint().nonnegative().optional().register(zommandRegistry, {
143
+ flags: "--logs-page-size <size>",
144
+ description: "Max block range size for eth_getLogs",
145
+ env: "LOGS_PAGE_SIZE"
146
+ }),
147
+ /**
148
+ * Polling interval in milliseconds, default to what's default in viem
149
+ */
150
+ pollingInterval: z.coerce.number().nonnegative().optional().register(zommandRegistry, {
151
+ flags: "--polling-interval <interval>",
152
+ description: "Polling interval in milliseconds, default to what's default in viem",
153
+ env: "POLLING_INTERVAL"
154
+ }),
155
+ /**
156
+ * Private key used to send liquidation transactions
157
+ * Required in non-optimistic mode, must not be set in optimistic mode
158
+ */
159
+ privateKey: z.string().min(1).transform((s) => {
160
+ return isHex(s) ? s : `0x${s}`;
161
+ }).transform(CensoredString.transform).optional().register(zommandRegistry, {
162
+ flags: "--private-key <key>",
163
+ description: "Private key used to send liquidation transactions. Required in non-optimistic mode, must not be set in optimistic mode",
164
+ env: "PRIVATE_KEY"
165
+ }),
166
+ /**
167
+ * Address to impersonate as transaction sender on anvil fork
168
+ * Required in optimistic mode, must not be set in non-optimistic mode
169
+ */
170
+ liquidatorAddress: addressLike().optional().register(zommandRegistry, {
171
+ flags: "--liquidator-address <address>",
172
+ description: "Address to impersonate as transaction sender on anvil fork. Required in optimistic mode, must not be set in non-optimistic mode",
173
+ env: "LIQUIDATOR_ADDRESS"
174
+ }),
175
+ /**
176
+ * Minimum executor gas budget, in gas units. The required balance to send a
177
+ * notification is computed as `minBalanceGas * currentGasPrice`.
178
+ */
179
+ minBalanceGas: z.coerce.bigint().positive().default(85000000n).register(zommandRegistry, {
180
+ flags: "--min-balance-gas <gas>",
181
+ description: "Minimum executor gas budget (in gas units); required balance = this * current gas price",
182
+ env: "MIN_BALANCE_GAS"
183
+ }),
184
+ /**
185
+ * Filter out all accounts with HF >= threshold during scan stage
186
+ */
187
+ hfThreshold: z.coerce.bigint().nonnegative().max(MAX_UINT256).default(WAD - 1n).register(zommandRegistry, {
188
+ flags: "--hf-threshold <threshold>",
189
+ description: "Filter out all accounts with HF >= threshold during scan stage",
190
+ env: "HF_THRESHOLD"
191
+ }),
192
+ /**
193
+ * Default numSplits for router v3.1 contract
194
+ */
195
+ numSplits: z.coerce.bigint().positive().default(10n).register(zommandRegistry, {
196
+ flags: "--num-splits <splits>",
197
+ description: "Default numSplits for router v3.1 contract",
198
+ env: "NUM_SPLITS"
199
+ }),
200
+ /**
201
+ * Liquidator mode
202
+ */
203
+ liquidationMode: z.enum([
204
+ "full",
205
+ "partial",
206
+ "batch",
207
+ "deleverage"
208
+ ]).default("full").register(zommandRegistry, {
209
+ flags: "--liquidation-mode <mode>",
210
+ description: "Liquidator mode (full/partial/batch/deleverage)",
211
+ env: "LIQUIDATION_MODE"
212
+ }),
213
+ /**
214
+ * Enable optimistic liquidations
215
+ */
216
+ optimistic: boolLike().optional().register(zommandRegistry, {
217
+ flags: "--optimistic",
218
+ description: "Enable optimistic liquidations",
219
+ env: "OPTIMISTIC"
220
+ }),
221
+ /**
222
+ * In optimistic mode, use real health factor range to scan for accounts
223
+ * and do not force-enable deleverage bot on accounts.
224
+ *
225
+ * This mode can be used to test that deleverage bot is able to detect accounts correctly
226
+ */
227
+ useProductionScanner: boolLike().optional().register(zommandRegistry, {
228
+ flags: "--use-production-scanner",
229
+ description: "In optimistic mode, use real health factor range to scan for accounts and do not force-enable deleverage bot on accounts",
230
+ env: "USE_PRODUCTION_SCANNER"
231
+ }),
232
+ /**
233
+ * Optimistic timestamp to pass from external runner, in ms
234
+ */
235
+ optimisticTimestamp: z.coerce.number().int().positive().nullish().register(zommandRegistry, {
236
+ flags: "--optimistic-timestamp <timestamp>",
237
+ description: "Optimistic timestamp to pass from external runner, in ms",
238
+ env: "OPTIMISTIC_TIMESTAMP"
239
+ }),
240
+ /**
241
+ * Fail on missing feeds (redstone and pyth)
242
+ */
243
+ failOnMissingFeeds: boolLike().optional().register(zommandRegistry, {
244
+ flags: "--fail-on-missing-feeds",
245
+ description: "Fail on missing feeds (redstone and pyth)",
246
+ env: "FAIL_ON_MISSING_FEEDS"
247
+ }),
248
+ /**
249
+ * Explicitly set gas limit for SDK
250
+ * -1 to disable explicitly setting gas limit in SDK
251
+ * If not set, SDK will use default gas limit
252
+ */
253
+ gasLimit: z.coerce.bigint().optional().register(zommandRegistry, {
254
+ flags: "--gas-limit <limit>",
255
+ description: "Set gas limit for SDK",
256
+ env: "GAS_LIMIT"
257
+ }),
258
+ /**
259
+ * Do not send transactions in non-optimistic mode, just log them
260
+ */
261
+ dryRun: boolLike().optional().register(zommandRegistry, {
262
+ flags: "--dry-run",
263
+ description: "Do not send transactions in non-optimistic mode, just log them",
264
+ env: "DRY_RUN"
265
+ }),
266
+ /**
267
+ * Redstone gateways override
268
+ * Set local caching proxies to avoid rate limiting in test environment
269
+ */
270
+ redstoneGateways: stringArrayLike().pipe(z.array(z.url())).transform((a) => a.length ? a : void 0).optional().register(zommandRegistry, {
271
+ flags: "--redstone-gateways <urls...>",
272
+ description: "Redstone gateways to use, comma separated",
273
+ env: "REDSTONE_GATEWAYS"
274
+ }),
275
+ /**
276
+ * Limit number of accounts to load from compressor. 0 = unlimited, let compressor decide
277
+ */
278
+ compressorBatchSize: z.coerce.number().nonnegative().default(0).register(zommandRegistry, {
279
+ flags: "--compressor-batch-size <size>",
280
+ description: "Limit number of accounts to load from compressor. 0 = unlimited, let compressor decide",
281
+ env: "COMPRESSOR_BATCH_SIZE"
282
+ }),
283
+ /**
284
+ * Slippage value for pathfined
285
+ */
286
+ slippage: z.coerce.number().min(0).max(1e4).int().default(50).register(zommandRegistry, {
287
+ flags: "--slippage <value>",
288
+ description: "Slippage value for pathfinder",
289
+ env: "SLIPPAGE"
290
+ }),
291
+ /**
292
+ * By default, reserve prices are not updated (except for deleverage mode)
293
+ */
294
+ updateReservePrices: boolLike().optional().default(false).register(zommandRegistry, {
295
+ flags: "--update-reserve-prices",
296
+ description: "Update reserve prices",
297
+ env: "UPDATE_RESERVE_PRICES"
298
+ }),
299
+ /**
300
+ * List of assets to keep on account after liquidation
301
+ */
302
+ keepAssets: optionalAddressArrayLike().register(zommandRegistry, {
303
+ flags: "--keep-assets <assets...>",
304
+ description: "List of assets to keep on account after liquidation",
305
+ env: "KEEP_ASSETS"
306
+ }),
307
+ /**
308
+ * Address that receives the liquidation premium and leftover underlying.
309
+ * Defaults to the executor address when unset.
310
+ */
311
+ premiumReceiver: addressLike().optional().register(zommandRegistry, {
312
+ flags: "--premium-receiver <address>",
313
+ description: "Address that receives the liquidation premium and leftover underlying (defaults to executor address)",
314
+ env: "PREMIUM_RECEIVER"
315
+ }),
316
+ /**
317
+ * Directory to save json with optimistic liquidation results
318
+ */
319
+ outDir: z.string().default(".").register(zommandRegistry, {
320
+ flags: "--out-dir <dir>",
321
+ description: "Directory to save json with optimistic liquidation results",
322
+ env: "OUT_DIR"
323
+ }),
324
+ /**
325
+ * REST endpoint to POST json with optimistic liquidation results
326
+ */
327
+ outEndpoint: z.url().optional().register(zommandRegistry, {
328
+ flags: "--out-endpoint <url>",
329
+ description: "REST endpoint to POST json with optimistic liquidation results",
330
+ env: "OUT_ENDPOINT"
331
+ }),
332
+ /**
333
+ * Headers for REST endpoint
334
+ */
335
+ outHeaders: z.string().default("{}").transform(CensoredString.transform).register(zommandRegistry, {
336
+ flags: "--out-headers <headers>",
337
+ description: "Headers for REST endpoint",
338
+ env: "OUT_HEADERS"
339
+ }),
340
+ /**
341
+ * s3 bucket to upload json with optimistic liquidation results
342
+ */
343
+ outS3Bucket: z.string().optional().register(zommandRegistry, {
344
+ flags: "--out-s3-bucket <bucket>",
345
+ description: "S3 bucket to upload json with optimistic liquidation results",
346
+ env: "OUT_S3_BUCKET"
347
+ }),
348
+ /**
349
+ * s3 bucket path prefix
350
+ */
351
+ outS3Prefix: z.string().default("").register(zommandRegistry, {
352
+ flags: "--out-s3-prefix <prefix>",
353
+ description: "S3 bucket path prefix",
354
+ env: "OUT_S3_PREFIX"
355
+ }),
356
+ /**
357
+ * Filename of json with optimistic liquidation results for s3 or dir output
358
+ */
359
+ outFileName: z.string().optional().register(zommandRegistry, {
360
+ flags: "--out-file-name <name>",
361
+ description: "Filename of json with optimistic liquidation results for s3 or dir output",
362
+ env: "OUT_FILE_NAME"
363
+ }),
364
+ /**
365
+ * Notifications, global and per-curator
366
+ */
367
+ ...NotificationsConfig.shape
420
368
  });
421
-
422
- // src/deleverage-liquidator.ts
423
- import { zommandRegistry as zommandRegistry3 } from "@gearbox-protocol/cli-utils";
424
- import { z as z4 } from "zod/v4";
425
- var DeleverageLiquidatorSchema = z4.object({
426
- ...CommonSchema.shape,
427
- /**
428
- * Liquidator mode
429
- */
430
- liquidationMode: z4.literal("deleverage").register(zommandRegistry3, {
431
- flags: "--liquidation-mode <mode>",
432
- description: "Liquidator mode (full/partial/batch/deleverage)",
433
- env: "LIQUIDATION_MODE"
434
- })
369
+ //#endregion
370
+ //#region src/batch-liquidator.ts
371
+ const BatchLiquidatorSchema = z.object({
372
+ ...CommonSchema.shape,
373
+ /**
374
+ * Liquidator mode
375
+ */
376
+ liquidationMode: z.literal("batch").register(zommandRegistry, {
377
+ flags: "--liquidation-mode <mode>",
378
+ description: "Liquidator mode (full/partial/batch/deleverage)",
379
+ env: "LIQUIDATION_MODE"
380
+ }),
381
+ /**
382
+ * Number of accounts to liquidate at once using batch liquidator
383
+ */
384
+ batchSize: z.coerce.number().nonnegative().default(10).register(zommandRegistry, {
385
+ flags: "--batch-size <size>",
386
+ description: "Number of accounts to liquidate at once using batch liquidator",
387
+ env: "BATCH_SIZE"
388
+ })
435
389
  });
436
-
437
- // src/full-liquidator.ts
438
- import { zommandRegistry as zommandRegistry4 } from "@gearbox-protocol/cli-utils";
439
- import { z as z5 } from "zod/v4";
440
- var FullLiquidatorSchema = z5.object({
441
- ...CommonSchema.shape,
442
- /**
443
- * Liquidator mode
444
- */
445
- liquidationMode: z5.literal("full").register(zommandRegistry4, {
446
- flags: "--liquidation-mode <mode>",
447
- description: "Liquidator mode (full/partial/batch/deleverage)",
448
- env: "LIQUIDATION_MODE"
449
- }),
450
- /**
451
- * Debt policy
452
- * full - liquidate fully
453
- * debt-only - try to liquidate only debt
454
- * debt-expired - try to liquidate only debt for expired accounts
455
- */
456
- debtPolicy: z5.enum(["full", "debt-only", "debt-expired"]).default("full").register(zommandRegistry4, {
457
- flags: "--debt-policy <policy>",
458
- description: "Liquidate fully/debt only/debt only for expired accounts",
459
- env: "DEBT_POLICY"
460
- }),
461
- /**
462
- * Full-mode liquidation strategy set for this process.
463
- *
464
- * Values:
465
- * - `auto`: production default. Includes loss-policy, normal full, and RWA
466
- * stablecoin strategies. Routing is decided by account type and
467
- * per-strategy `isApplicable`: non-RWA accounts use loss policy when they
468
- * have bad debt and fall back to normal full liquidation otherwise, while
469
- * RWA accounts use only the RWA stablecoin strategy.
470
- * - `rwa`: include only `LiquidationStrategyRWAViaStablecoins`
471
- * Intended for optimistic RWA tracks.
472
- * - `loss`: include only `LiquidationStrategyLossPolicy`
473
- * Intended for optimistic loss-policy tracks.
474
- * - `full`: include only `LiquidationStrategyFull`
475
- * Intended for optimistic normal-full tracks.
476
- *
477
- * Optimistic mode rejects `auto`, so the external runner must invoke
478
- * explicit tracks: `rwa`, `loss`, and `full`.
479
- */
480
- strategy: z5.enum(["auto", "rwa", "loss", "full"]).default("auto").register(zommandRegistry4, {
481
- flags: "--strategy <strategy>",
482
- description: "Full-mode liquidation strategy set (auto/rwa/loss/full). Optimistic mode requires an explicit track.",
483
- env: "STRATEGY"
484
- })
485
- }).refine((data) => !(data.optimistic === true && data.strategy === "auto"), {
486
- message: "strategy=auto is not allowed in optimistic mode; pick one of rwa/loss/full"
390
+ //#endregion
391
+ //#region src/deleverage-liquidator.ts
392
+ const DeleverageLiquidatorSchema = z.object({
393
+ ...CommonSchema.shape,
394
+ /**
395
+ * Liquidator mode
396
+ */
397
+ liquidationMode: z.literal("deleverage").register(zommandRegistry, {
398
+ flags: "--liquidation-mode <mode>",
399
+ description: "Liquidator mode (full/partial/batch/deleverage)",
400
+ env: "LIQUIDATION_MODE"
401
+ })
487
402
  });
488
-
489
- // src/partial-liquidator.ts
490
- import {
491
- boolLike as boolLike2,
492
- optionalAddressArrayLike as optionalAddressArrayLike2,
493
- zommandRegistry as zommandRegistry5
494
- } from "@gearbox-protocol/cli-utils";
495
- import { z as z6 } from "zod/v4";
496
- var PartialLiquidatorSchema = z6.object({
497
- ...CommonSchema.shape,
498
- /**
499
- * Liquidator mode
500
- */
501
- liquidationMode: z6.literal("partial").register(zommandRegistry5, {
502
- flags: "--liquidation-mode <mode>",
503
- description: "Liquidator mode (full/partial/batch/deleverage)",
504
- env: "LIQUIDATION_MODE"
505
- }),
506
- /**
507
- * Fallback to use full liquidator when partial liquidator fails
508
- */
509
- partialFallback: boolLike2().optional().register(zommandRegistry5, {
510
- flags: "--partial-fallback",
511
- description: "Fallback to use full liquidator when partial liquidator fails",
512
- env: "PARTIAL_FALLBACK"
513
- }),
514
- /**
515
- * Desired HF after partial liquidation, with 4 decimals (100% = 10000)
516
- */
517
- targetPartialHF: z6.coerce.bigint().default(10100n).register(zommandRegistry5, {
518
- flags: "--target-partial-hf <hf>",
519
- description: "Desired HF after partial liquidation, with 4 decimals (100% = 10000)",
520
- env: "TARGET_PARTIAL_HF"
521
- }),
522
- /**
523
- * Optimal HF for partial liquidation will be calculated for accounts with following underlying tokens
524
- * Takes precedence over targetPartialHF
525
- */
526
- calculatePartialHF: optionalAddressArrayLike2().register(zommandRegistry5, {
527
- flags: "--calculate-partial-hf <tokens>",
528
- description: "Optimal HF for partial liquidation will be calculated for accounts with following underlying tokens",
529
- env: "CALCULATE_PARTIAL_HF"
530
- })
531
- }).refine(
532
- (data) => !(data.optimistic === true && data.partialFallback === true),
533
- { message: "partialFallback=true is not allowed in optimistic mode" }
534
- );
535
-
536
- // src/schema.ts
537
- var ConfigSchema = z7.discriminatedUnion("liquidationMode", [
538
- FullLiquidatorSchema,
539
- PartialLiquidatorSchema,
540
- BatchLiquidatorSchema,
541
- DeleverageLiquidatorSchema
403
+ //#endregion
404
+ //#region src/full-liquidator.ts
405
+ const FullLiquidatorSchema = z.object({
406
+ ...CommonSchema.shape,
407
+ /**
408
+ * Liquidator mode
409
+ */
410
+ liquidationMode: z.literal("full").register(zommandRegistry, {
411
+ flags: "--liquidation-mode <mode>",
412
+ description: "Liquidator mode (full/partial/batch/deleverage)",
413
+ env: "LIQUIDATION_MODE"
414
+ }),
415
+ /**
416
+ * Debt policy
417
+ * full - liquidate fully
418
+ * debt-only - try to liquidate only debt
419
+ * debt-expired - try to liquidate only debt for expired accounts
420
+ */
421
+ debtPolicy: z.enum([
422
+ "full",
423
+ "debt-only",
424
+ "debt-expired"
425
+ ]).default("full").register(zommandRegistry, {
426
+ flags: "--debt-policy <policy>",
427
+ description: "Liquidate fully/debt only/debt only for expired accounts",
428
+ env: "DEBT_POLICY"
429
+ }),
430
+ /**
431
+ * Full-mode liquidation strategy set for this process.
432
+ *
433
+ * Values:
434
+ * - `auto`: production default. Includes loss-policy, normal full, and RWA
435
+ * stablecoin strategies. Routing is decided by account type and
436
+ * per-strategy `isApplicable`: non-RWA accounts use loss policy when they
437
+ * have bad debt and fall back to normal full liquidation otherwise, while
438
+ * RWA accounts use only the RWA stablecoin strategy.
439
+ * - `rwa`: include only `LiquidationStrategyRWAViaStablecoins`
440
+ * Intended for optimistic RWA tracks.
441
+ * - `loss`: include only `LiquidationStrategyLossPolicy`
442
+ * Intended for optimistic loss-policy tracks.
443
+ * - `full`: include only `LiquidationStrategyFull`
444
+ * Intended for optimistic normal-full tracks.
445
+ *
446
+ * Optimistic mode rejects `auto`, so the external runner must invoke
447
+ * explicit tracks: `rwa`, `loss`, and `full`.
448
+ */
449
+ strategy: z.enum([
450
+ "auto",
451
+ "rwa",
452
+ "loss",
453
+ "full"
454
+ ]).default("auto").register(zommandRegistry, {
455
+ flags: "--strategy <strategy>",
456
+ description: "Full-mode liquidation strategy set (auto/rwa/loss/full). Optimistic mode requires an explicit track.",
457
+ env: "STRATEGY"
458
+ })
459
+ }).refine((data) => !(data.optimistic === true && data.strategy === "auto"), { message: "strategy=auto is not allowed in optimistic mode; pick one of rwa/loss/full" });
460
+ //#endregion
461
+ //#region src/partial-liquidator.ts
462
+ const PartialLiquidatorSchema = z.object({
463
+ ...CommonSchema.shape,
464
+ /**
465
+ * Liquidator mode
466
+ */
467
+ liquidationMode: z.literal("partial").register(zommandRegistry, {
468
+ flags: "--liquidation-mode <mode>",
469
+ description: "Liquidator mode (full/partial/batch/deleverage)",
470
+ env: "LIQUIDATION_MODE"
471
+ }),
472
+ /**
473
+ * Fallback to use full liquidator when partial liquidator fails
474
+ */
475
+ partialFallback: boolLike().optional().register(zommandRegistry, {
476
+ flags: "--partial-fallback",
477
+ description: "Fallback to use full liquidator when partial liquidator fails",
478
+ env: "PARTIAL_FALLBACK"
479
+ }),
480
+ /**
481
+ * Desired HF after partial liquidation, with 4 decimals (100% = 10000)
482
+ */
483
+ targetPartialHF: z.coerce.bigint().default(10100n).register(zommandRegistry, {
484
+ flags: "--target-partial-hf <hf>",
485
+ description: "Desired HF after partial liquidation, with 4 decimals (100% = 10000)",
486
+ env: "TARGET_PARTIAL_HF"
487
+ }),
488
+ /**
489
+ * Optimal HF for partial liquidation will be calculated for accounts with following underlying tokens
490
+ * Takes precedence over targetPartialHF
491
+ */
492
+ calculatePartialHF: optionalAddressArrayLike().register(zommandRegistry, {
493
+ flags: "--calculate-partial-hf <tokens>",
494
+ description: "Optimal HF for partial liquidation will be calculated for accounts with following underlying tokens",
495
+ env: "CALCULATE_PARTIAL_HF"
496
+ })
497
+ }).refine((data) => !(data.optimistic === true && data.partialFallback === true), { message: "partialFallback=true is not allowed in optimistic mode" });
498
+ //#endregion
499
+ //#region src/schema.ts
500
+ const ConfigSchema = z.discriminatedUnion("liquidationMode", [
501
+ FullLiquidatorSchema,
502
+ PartialLiquidatorSchema,
503
+ BatchLiquidatorSchema,
504
+ DeleverageLiquidatorSchema
542
505
  ]);
543
- export {
544
- ConfigImplementation,
545
- ConfigSchema,
546
- NotificationsConfig
547
- };
506
+ //#endregion
507
+ export { ConfigImplementation, ConfigSchema, NotificationsConfig };
508
+
548
509
  //# sourceMappingURL=index.js.map