Skip to content

Commit ab588ad

Browse files
committed
fix: create scanner diagnoster
1 parent 10104bc commit ab588ad

File tree

3 files changed

+133
-24
lines changed

3 files changed

+133
-24
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"@gearbox-protocol/cli-utils": "^5.45.14",
3030
"@gearbox-protocol/liquidator-contracts": "^1.36.0-experimental.41",
3131
"@gearbox-protocol/liquidator-v2-contracts": "^2.4.0",
32-
"@gearbox-protocol/sdk": "8.27.2",
32+
"@gearbox-protocol/sdk": "8.27.5",
3333
"@gearbox-protocol/types": "^1.14.8",
3434
"@types/node": "^24.3.1",
3535
"@uniswap/sdk-core": "^7.7.2",
@@ -45,7 +45,7 @@
4545
"lint-staged": "^16.1.6",
4646
"nanoid": "^5.1.5",
4747
"node-pty": "^1.0.0",
48-
"pino": "^9.9.1",
48+
"pino": "^9.9.2",
4949
"tsx": "4.20.5",
5050
"typescript": "^5.9.2",
5151
"viem": "^2.37.3",

src/services/Scanner.ts

Lines changed: 121 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
import type {
22
CreditAccountData,
3+
CreditAccountServiceOptions,
4+
GearboxSDK,
5+
GetCreditAccountsOptions,
36
ICreditAccountsService,
47
NetworkType,
58
} from "@gearbox-protocol/sdk";
69
import {
10+
AbstractCreditAccountService,
711
hexEq,
812
MAX_UINT256,
913
PERCENTAGE_FACTOR,
1014
WAD,
1115
} from "@gearbox-protocol/sdk";
1216
import { iBotListV310Abi } from "@gearbox-protocol/sdk/abi/v310";
17+
import { getAlchemyUrl, getDrpcUrl } from "@gearbox-protocol/sdk/dev";
1318
import {
1419
iCreditManagerV3Abi,
1520
iPartialLiquidationBotV3Abi,
1621
} from "@gearbox-protocol/types/abi";
17-
import type { Address, Block } from "viem";
18-
import { getContract } from "viem";
22+
import type { Address, Block, PublicClient } from "viem";
23+
import { createPublicClient, getContract, http } from "viem";
1924
import type { Config } from "../config/index.js";
2025
import { DI } from "../di.js";
2126
import { type ILogger, Logger } from "../log/index.js";
@@ -53,6 +58,7 @@ export class Scanner {
5358
#maxHealthFactor = MAX_UINT256;
5459
#minHealthFactor = 0n;
5560
#unwatch?: () => void;
61+
#diagnoster?: ScannerDiagnoster;
5662

5763
public async launch(): Promise<void> {
5864
await this.liquidatorService.launch();
@@ -86,6 +92,10 @@ export class Scanner {
8692
}
8793
}
8894

95+
if (this.config.debugScanner) {
96+
this.#diagnoster = new ScannerDiagnoster();
97+
}
98+
8999
// we should not pin block during optimistic liquidations
90100
// because during optimistic liquidations we need to call evm_mine to make redstone work
91101
await this.#updateAccounts(
@@ -134,7 +144,7 @@ export class Scanner {
134144

135145
/**
136146
* Loads new data and recompute all health factors
137-
* @param blockNumber Fiex block for archive node which is needed to get data
147+
* @param blockNumber Fixed block for archive node which is needed to get data
138148
*/
139149
async #updateAccounts(blockNumber?: bigint): Promise<void> {
140150
const start = Date.now();
@@ -147,15 +157,14 @@ export class Scanner {
147157
);
148158
accounts = acc ? [acc] : [];
149159
} else {
150-
accounts = await this.caService.getCreditAccounts(
151-
{
152-
minHealthFactor: this.#minHealthFactor,
153-
maxHealthFactor: this.#maxHealthFactor,
154-
includeZeroDebt: false,
155-
creditManager: this.config.debugManager,
156-
},
157-
blockNumber,
158-
);
160+
const queue: GetCreditAccountsOptions = {
161+
minHealthFactor: this.#minHealthFactor,
162+
maxHealthFactor: this.#maxHealthFactor,
163+
includeZeroDebt: false,
164+
creditManager: this.config.debugManager,
165+
};
166+
accounts = await this.caService.getCreditAccounts(queue, blockNumber);
167+
await this.#diagnoster?.checkAccounts(accounts, queue, blockNumber);
159168
}
160169
if (this.config.restakingWorkaround) {
161170
const before = accounts.length;
@@ -353,3 +362,103 @@ export class Scanner {
353362
this.log.info("stopped");
354363
}
355364
}
365+
366+
class ScannerDiagnoster {
367+
@Logger("ScannerDiagnoster")
368+
log!: ILogger;
369+
370+
@DI.Inject(DI.Config)
371+
config!: Config;
372+
373+
@DI.Inject(DI.CreditAccountService)
374+
caService!: ICreditAccountsService;
375+
376+
#drpc?: WorkaroundCAS;
377+
#alchemy?: WorkaroundCAS;
378+
379+
constructor() {
380+
if (this.config.drpcKeys?.length) {
381+
const rpcURL = getDrpcUrl(
382+
this.config.network,
383+
this.config.drpcKeys[0].value,
384+
"http",
385+
);
386+
if (rpcURL) {
387+
this.#drpc = new WorkaroundCAS(this.caService.sdk, { rpcURL });
388+
}
389+
}
390+
if (this.config.alchemyKeys?.length) {
391+
const rpcURL = getAlchemyUrl(
392+
this.config.network,
393+
this.config.alchemyKeys[0].value,
394+
"http",
395+
);
396+
if (rpcURL) {
397+
this.#alchemy = new WorkaroundCAS(this.caService.sdk, { rpcURL });
398+
}
399+
}
400+
if (!!this.#drpc && !!this.#alchemy) {
401+
this.log.info("scanner diagnoster enabled");
402+
}
403+
}
404+
405+
public async checkAccounts(
406+
accounts: CreditAccountData[],
407+
queue: GetCreditAccountsOptions,
408+
blockNumber?: bigint,
409+
): Promise<void> {
410+
try {
411+
if (!accounts.length || !blockNumber) {
412+
return;
413+
}
414+
let [success, drpcSuccess, alchemySuccess] = [0, 0, 0];
415+
for (const a of accounts) {
416+
success += a.success ? 1 : 0;
417+
}
418+
this.log.debug(
419+
`found ${accounts.length} liquidatable accounts (${success} successful) in block ${blockNumber}`,
420+
);
421+
if (!this.#drpc || !this.#alchemy) {
422+
return;
423+
}
424+
const [drpcAccs, alchemyAccs] = await Promise.all([
425+
this.#drpc.getCreditAccounts(queue, blockNumber),
426+
this.#alchemy.getCreditAccounts(queue, blockNumber),
427+
]);
428+
for (const a of drpcAccs) {
429+
drpcSuccess += a.success ? 1 : 0;
430+
}
431+
for (const a of alchemyAccs) {
432+
alchemySuccess += a.success ? 1 : 0;
433+
}
434+
this.log.debug(
435+
`found ${drpcAccs.length} liquidatable accounts (${drpcSuccess} successful) in block ${blockNumber} with drpc`,
436+
);
437+
this.log.debug(
438+
`found ${alchemyAccs.length} liquidatable accounts (${alchemySuccess} successful) in block ${blockNumber} with alchemy`,
439+
);
440+
} catch (e) {
441+
this.log.error(e);
442+
}
443+
}
444+
}
445+
446+
interface WorkaroundCASOptions extends CreditAccountServiceOptions {
447+
rpcURL: string;
448+
}
449+
450+
class WorkaroundCAS extends AbstractCreditAccountService {
451+
#client: PublicClient;
452+
453+
constructor(sdk: GearboxSDK, opts: WorkaroundCASOptions) {
454+
super(sdk, opts);
455+
this.#client = createPublicClient({
456+
transport: http(opts.rpcURL, { timeout: 600_000 }),
457+
chain: sdk.provider.chain,
458+
});
459+
}
460+
461+
public override get client(): PublicClient {
462+
return this.#client;
463+
}
464+
}

yarn.lock

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,7 +1770,7 @@ __metadata:
17701770
"@gearbox-protocol/cli-utils": "npm:^5.45.14"
17711771
"@gearbox-protocol/liquidator-contracts": "npm:^1.36.0-experimental.41"
17721772
"@gearbox-protocol/liquidator-v2-contracts": "npm:^2.4.0"
1773-
"@gearbox-protocol/sdk": "npm:8.27.2"
1773+
"@gearbox-protocol/sdk": "npm:8.27.5"
17741774
"@gearbox-protocol/types": "npm:^1.14.8"
17751775
"@types/node": "npm:^24.3.1"
17761776
"@uniswap/sdk-core": "npm:^7.7.2"
@@ -1786,7 +1786,7 @@ __metadata:
17861786
lint-staged: "npm:^16.1.6"
17871787
nanoid: "npm:^5.1.5"
17881788
node-pty: "npm:^1.0.0"
1789-
pino: "npm:^9.9.1"
1789+
pino: "npm:^9.9.2"
17901790
pino-pretty: "npm:^13.1.1"
17911791
tsx: "npm:4.20.5"
17921792
typescript: "npm:^5.9.2"
@@ -1796,9 +1796,9 @@ __metadata:
17961796
languageName: unknown
17971797
linkType: soft
17981798

1799-
"@gearbox-protocol/sdk@npm:8.27.2":
1800-
version: 8.27.2
1801-
resolution: "@gearbox-protocol/sdk@npm:8.27.2"
1799+
"@gearbox-protocol/sdk@npm:8.27.5":
1800+
version: 8.27.5
1801+
resolution: "@gearbox-protocol/sdk@npm:8.27.5"
18021802
dependencies:
18031803
"@redstone-finance/evm-connector": "npm:^0.7.5"
18041804
"@redstone-finance/protocol": "npm:^0.7.5"
@@ -1812,7 +1812,7 @@ __metadata:
18121812
zod: "npm:^4.1.1"
18131813
peerDependencies:
18141814
axios: ^1.0.0
1815-
checksum: 10c0/6f9aef76a638630c0a4aa6f485d22fa35889234eda9776807af6fd504e5a87ff68e4f95b61a774e02df9d06fb966fe4c2e6655afbf680ce63f6cade78ad3c658
1815+
checksum: 10c0/b426ad315b39bd3fe3222342e26d61db5aba4edb5162997b3bd4f0836723f2cbbd31695f0fd5b8d957cc4c6826d445d5e97eb0a1635e9bcff3c876d77040b0e0
18161816
languageName: node
18171817
linkType: hard
18181818

@@ -5324,9 +5324,9 @@ __metadata:
53245324
languageName: node
53255325
linkType: hard
53265326

5327-
"pino@npm:^9.9.1":
5328-
version: 9.9.1
5329-
resolution: "pino@npm:9.9.1"
5327+
"pino@npm:^9.9.2":
5328+
version: 9.9.2
5329+
resolution: "pino@npm:9.9.2"
53305330
dependencies:
53315331
atomic-sleep: "npm:^1.0.0"
53325332
fast-redact: "npm:^3.1.1"
@@ -5341,7 +5341,7 @@ __metadata:
53415341
thread-stream: "npm:^3.0.0"
53425342
bin:
53435343
pino: bin.js
5344-
checksum: 10c0/71fe3369ea80d66db847b715fc04a1a26df904a75fde861adcd549fdfca6b41365387b882e802c5663a6b4e9aeec7269e9956d66803ec2e191a35e0f15536014
5344+
checksum: 10c0/6574bcb865ff6601410e88c8089a9f7e191396f65d9f3a4a9173162a3f200b17fdb68b50d858dd93d10493351e4884edd293354ad1b90432f12a9a71445d8ee5
53455345
languageName: node
53465346
linkType: hard
53475347

0 commit comments

Comments
 (0)