torch-liquidation-bot 2.0.1 → 2.0.3
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/package.json +6 -7
- package/readme.md +13 -32
- package/dist/config.d.ts +0 -6
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -51
- package/dist/config.js.map +0 -1
- package/dist/index.d.ts +0 -28
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -172
- package/dist/index.js.map +0 -1
- package/dist/liquidator.d.ts +0 -17
- package/dist/liquidator.d.ts.map +0 -1
- package/dist/liquidator.js +0 -72
- package/dist/liquidator.js.map +0 -1
- package/dist/logger.d.ts +0 -17
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -54
- package/dist/logger.js.map +0 -1
- package/dist/monitor.d.ts +0 -27
- package/dist/monitor.d.ts.map +0 -1
- package/dist/monitor.js +0 -136
- package/dist/monitor.js.map +0 -1
- package/dist/risk-scorer.d.ts +0 -13
- package/dist/risk-scorer.d.ts.map +0 -1
- package/dist/risk-scorer.js +0 -102
- package/dist/risk-scorer.js.map +0 -1
- package/dist/scanner.d.ts +0 -11
- package/dist/scanner.d.ts.map +0 -1
- package/dist/scanner.js +0 -55
- package/dist/scanner.js.map +0 -1
- package/dist/types.d.ts +0 -69
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -8
- package/dist/types.js.map +0 -1
- package/dist/utils.d.ts +0 -9
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js +0 -24
- package/dist/utils.js.map +0 -1
- package/dist/wallet-profiler.d.ts +0 -21
- package/dist/wallet-profiler.d.ts.map +0 -1
- package/dist/wallet-profiler.js +0 -116
- package/dist/wallet-profiler.js.map +0 -1
package/dist/monitor.js
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* monitor.ts — main orchestration loop.
|
|
4
|
-
*
|
|
5
|
-
* two loops running on intervals:
|
|
6
|
-
* 1. scan loop: discover tokens with active lending
|
|
7
|
-
* 2. score loop: profile borrowers, score loans, execute liquidations
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.Monitor = void 0;
|
|
11
|
-
const torchsdk_1 = require("torchsdk");
|
|
12
|
-
const logger_1 = require("./logger");
|
|
13
|
-
const wallet_profiler_1 = require("./wallet-profiler");
|
|
14
|
-
const liquidator_1 = require("./liquidator");
|
|
15
|
-
const scanner_1 = require("./scanner");
|
|
16
|
-
const risk_scorer_1 = require("./risk-scorer");
|
|
17
|
-
const utils_1 = require("./utils");
|
|
18
|
-
class Monitor {
|
|
19
|
-
constructor(connection, config) {
|
|
20
|
-
this.tokens = new Map();
|
|
21
|
-
this.running = false;
|
|
22
|
-
this.connection = connection;
|
|
23
|
-
this.config = config;
|
|
24
|
-
this.log = new logger_1.Logger('monitor', config.logLevel);
|
|
25
|
-
this.profiler = new wallet_profiler_1.WalletProfiler(this.log.child('profiler'));
|
|
26
|
-
this.liquidator = new liquidator_1.Liquidator(config, this.log.child('liquidator'));
|
|
27
|
-
}
|
|
28
|
-
async start() {
|
|
29
|
-
this.running = true;
|
|
30
|
-
const wallet = this.config.walletKeypair.publicKey.toBase58();
|
|
31
|
-
this.log.info('starting liquidation bot', {
|
|
32
|
-
wallet: `${wallet.slice(0, 8)}...`,
|
|
33
|
-
scanInterval: `${this.config.scanIntervalMs / 1000}s`,
|
|
34
|
-
scoreInterval: `${this.config.scoreIntervalMs / 1000}s`,
|
|
35
|
-
minProfit: `${(0, utils_1.sol)(this.config.minProfitLamports)} SOL`,
|
|
36
|
-
riskThreshold: this.config.riskThreshold,
|
|
37
|
-
});
|
|
38
|
-
// initial scan before starting loops
|
|
39
|
-
await this.scan();
|
|
40
|
-
// run both loops concurrently
|
|
41
|
-
await Promise.all([this.scanLoop(), this.scoreLoop()]);
|
|
42
|
-
}
|
|
43
|
-
stop() {
|
|
44
|
-
this.running = false;
|
|
45
|
-
this.log.info('stopping bot...');
|
|
46
|
-
}
|
|
47
|
-
async scanLoop() {
|
|
48
|
-
while (this.running) {
|
|
49
|
-
await (0, utils_1.sleep)(this.config.scanIntervalMs);
|
|
50
|
-
await this.scan();
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
async scan() {
|
|
54
|
-
try {
|
|
55
|
-
this.tokens = await (0, scanner_1.scanForLendingMarkets)(this.connection, this.tokens, this.config.priceHistoryDepth, this.log.child('scanner'));
|
|
56
|
-
}
|
|
57
|
-
catch (err) {
|
|
58
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
59
|
-
this.log.error('scan failed', { error: msg });
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
async scoreLoop() {
|
|
63
|
-
while (this.running) {
|
|
64
|
-
await this.scoreAllPositions();
|
|
65
|
-
await (0, utils_1.sleep)(this.config.scoreIntervalMs);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
async scoreAllPositions() {
|
|
69
|
-
if (this.tokens.size === 0)
|
|
70
|
-
return;
|
|
71
|
-
const allScored = [];
|
|
72
|
-
for (const token of this.tokens.values()) {
|
|
73
|
-
try {
|
|
74
|
-
const scored = await this.scoreToken(token);
|
|
75
|
-
allScored.push(...scored);
|
|
76
|
-
}
|
|
77
|
-
catch (err) {
|
|
78
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
79
|
-
this.log.error(`failed scoring ${token.symbol}`, { error: msg });
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
// sort by risk: highest risk first
|
|
83
|
-
allScored.sort((a, b) => b.riskScore - a.riskScore);
|
|
84
|
-
// log high-risk positions
|
|
85
|
-
const highRisk = allScored.filter((l) => l.riskScore >= this.config.riskThreshold);
|
|
86
|
-
if (highRisk.length > 0) {
|
|
87
|
-
this.log.info(`${highRisk.length} high-risk positions detected`);
|
|
88
|
-
for (const loan of highRisk) {
|
|
89
|
-
this.log.info(` ${loan.tokenName} | ${loan.borrower.slice(0, 8)}...`, {
|
|
90
|
-
risk: loan.riskScore,
|
|
91
|
-
health: loan.position.health,
|
|
92
|
-
ltv: (0, utils_1.bpsToPercent)(loan.position.current_ltv_bps),
|
|
93
|
-
profit: `${(0, utils_1.sol)(loan.estimatedProfitLamports)} SOL`,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// attempt liquidations on any liquidatable positions (highest profit first)
|
|
98
|
-
const liquidatable = allScored
|
|
99
|
-
.filter((l) => l.position.health === 'liquidatable')
|
|
100
|
-
.sort((a, b) => b.estimatedProfitLamports - a.estimatedProfitLamports);
|
|
101
|
-
for (const loan of liquidatable) {
|
|
102
|
-
const result = await this.liquidator.tryLiquidate(this.connection, loan);
|
|
103
|
-
if (result) {
|
|
104
|
-
this.log.info('liquidation successful!', {
|
|
105
|
-
token: loan.tokenName,
|
|
106
|
-
borrower: `${result.borrower.slice(0, 8)}...`,
|
|
107
|
-
profit: `${(0, utils_1.sol)(result.profitLamports)} SOL`,
|
|
108
|
-
sig: result.signature,
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
async scoreToken(token) {
|
|
114
|
-
const { holders } = await (0, torchsdk_1.getHolders)(this.connection, token.mint, 100);
|
|
115
|
-
const scored = [];
|
|
116
|
-
// update active borrowers list
|
|
117
|
-
const borrowers = [];
|
|
118
|
-
for (const holder of holders) {
|
|
119
|
-
try {
|
|
120
|
-
const position = await (0, torchsdk_1.getLoanPosition)(this.connection, token.mint, holder.address);
|
|
121
|
-
if (position.health === 'none')
|
|
122
|
-
continue;
|
|
123
|
-
borrowers.push(holder.address);
|
|
124
|
-
const profile = await this.profiler.profile(this.connection, holder.address, token.mint);
|
|
125
|
-
scored.push((0, risk_scorer_1.scoreLoan)(token, holder.address, position, profile));
|
|
126
|
-
}
|
|
127
|
-
catch {
|
|
128
|
-
// skip holders we can't score
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
token.activeBorrowers = borrowers;
|
|
132
|
-
return scored;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
exports.Monitor = Monitor;
|
|
136
|
-
//# sourceMappingURL=monitor.js.map
|
package/dist/monitor.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"monitor.js","sourceRoot":"","sources":["../src/monitor.ts"],"names":[],"mappings":"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"}
|
package/dist/risk-scorer.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* risk-scorer.ts — scores loan positions by likelihood of liquidation.
|
|
3
|
-
*
|
|
4
|
-
* four weighted factors:
|
|
5
|
-
* - ltv proximity (40%): how close to the liquidation threshold
|
|
6
|
-
* - price momentum (30%): is the collateral price trending down
|
|
7
|
-
* - wallet risk (20%): borrower reputation + trade history
|
|
8
|
-
* - interest burden (10%): is interest eating their margin
|
|
9
|
-
*/
|
|
10
|
-
import type { LoanPositionInfo } from 'torchsdk';
|
|
11
|
-
import type { WalletProfile, ScoredLoan, MonitoredToken } from './types';
|
|
12
|
-
export declare function scoreLoan(token: MonitoredToken, borrower: string, position: LoanPositionInfo, profile: WalletProfile): ScoredLoan;
|
|
13
|
-
//# sourceMappingURL=risk-scorer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"risk-scorer.d.ts","sourceRoot":"","sources":["../src/risk-scorer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAe,MAAM,UAAU,CAAA;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAe,UAAU,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAUrF,wBAAgB,SAAS,CACvB,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,aAAa,GACrB,UAAU,CAmCZ"}
|
package/dist/risk-scorer.js
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* risk-scorer.ts — scores loan positions by likelihood of liquidation.
|
|
4
|
-
*
|
|
5
|
-
* four weighted factors:
|
|
6
|
-
* - ltv proximity (40%): how close to the liquidation threshold
|
|
7
|
-
* - price momentum (30%): is the collateral price trending down
|
|
8
|
-
* - wallet risk (20%): borrower reputation + trade history
|
|
9
|
-
* - interest burden (10%): is interest eating their margin
|
|
10
|
-
*/
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.scoreLoan = scoreLoan;
|
|
13
|
-
const utils_1 = require("./utils");
|
|
14
|
-
const WEIGHTS = {
|
|
15
|
-
ltvProximity: 0.4,
|
|
16
|
-
priceMomentum: 0.3,
|
|
17
|
-
walletRisk: 0.2,
|
|
18
|
-
interestBurden: 0.1,
|
|
19
|
-
};
|
|
20
|
-
function scoreLoan(token, borrower, position, profile) {
|
|
21
|
-
const factors = computeFactors(position, token.lendingInfo, token.priceHistory, profile);
|
|
22
|
-
const riskScore = (0, utils_1.clamp)(Math.round(factors.ltvProximity * WEIGHTS.ltvProximity +
|
|
23
|
-
factors.priceMomentum * WEIGHTS.priceMomentum +
|
|
24
|
-
factors.walletRisk * WEIGHTS.walletRisk +
|
|
25
|
-
factors.interestBurden * WEIGHTS.interestBurden), 0, 100);
|
|
26
|
-
// estimated profit = collateral value * liquidation bonus - fees
|
|
27
|
-
const bonusPct = token.lendingInfo.liquidation_bonus_bps / 10000;
|
|
28
|
-
const grossProfit = position.collateral_value_sol * bonusPct;
|
|
29
|
-
const txFeeLamports = 5000; // ~0.000005 SOL per tx
|
|
30
|
-
const transferFeeLamports = Math.floor(position.collateral_value_sol * 0.01); // Token-2022 1% fee
|
|
31
|
-
const estimatedProfitLamports = Math.max(0, Math.floor(grossProfit) - txFeeLamports - transferFeeLamports);
|
|
32
|
-
return {
|
|
33
|
-
mint: token.mint,
|
|
34
|
-
tokenName: token.name,
|
|
35
|
-
borrower,
|
|
36
|
-
position,
|
|
37
|
-
walletProfile: profile,
|
|
38
|
-
riskScore,
|
|
39
|
-
factors,
|
|
40
|
-
estimatedProfitLamports,
|
|
41
|
-
lastScored: Date.now(),
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
function computeFactors(position, lending, priceHistory, profile) {
|
|
45
|
-
return {
|
|
46
|
-
ltvProximity: computeLtvProximity(position, lending),
|
|
47
|
-
priceMomentum: computePriceMomentum(priceHistory),
|
|
48
|
-
walletRisk: profile.riskScore,
|
|
49
|
-
interestBurden: computeInterestBurden(position),
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* how close is current LTV to the liquidation threshold?
|
|
54
|
-
* at threshold = 100, at 0 LTV = 0
|
|
55
|
-
*/
|
|
56
|
-
function computeLtvProximity(position, lending) {
|
|
57
|
-
if (lending.liquidation_threshold_bps === 0)
|
|
58
|
-
return 0;
|
|
59
|
-
const ratio = position.current_ltv_bps / lending.liquidation_threshold_bps;
|
|
60
|
-
return (0, utils_1.clamp)(Math.round(ratio * 100), 0, 100);
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* is the price trending down?
|
|
64
|
-
* uses simple slope of recent price history.
|
|
65
|
-
* negative slope = price dropping = higher risk.
|
|
66
|
-
*/
|
|
67
|
-
function computePriceMomentum(priceHistory) {
|
|
68
|
-
if (priceHistory.length < 2)
|
|
69
|
-
return 50; // not enough data, assume neutral
|
|
70
|
-
// simple linear regression slope
|
|
71
|
-
const n = priceHistory.length;
|
|
72
|
-
let sumX = 0;
|
|
73
|
-
let sumY = 0;
|
|
74
|
-
let sumXY = 0;
|
|
75
|
-
let sumX2 = 0;
|
|
76
|
-
for (let i = 0; i < n; i++) {
|
|
77
|
-
sumX += i;
|
|
78
|
-
sumY += priceHistory[i];
|
|
79
|
-
sumXY += i * priceHistory[i];
|
|
80
|
-
sumX2 += i * i;
|
|
81
|
-
}
|
|
82
|
-
const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
|
|
83
|
-
// normalize: negative slope = high risk, positive = low risk
|
|
84
|
-
// use avg price as baseline for relative change
|
|
85
|
-
const avgPrice = sumY / n;
|
|
86
|
-
if (avgPrice === 0)
|
|
87
|
-
return 50;
|
|
88
|
-
const relativeSlopePerTick = slope / avgPrice;
|
|
89
|
-
// scale: -5% per tick = 100 risk, +5% = 0 risk
|
|
90
|
-
const score = 50 - relativeSlopePerTick * 1000;
|
|
91
|
-
return (0, utils_1.clamp)(Math.round(score), 0, 100);
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* how much is interest eating into the collateral margin?
|
|
95
|
-
*/
|
|
96
|
-
function computeInterestBurden(position) {
|
|
97
|
-
if (position.collateral_value_sol === 0)
|
|
98
|
-
return 100;
|
|
99
|
-
const ratio = position.accrued_interest / position.collateral_value_sol;
|
|
100
|
-
return (0, utils_1.clamp)(Math.round(ratio * 1000), 0, 100); // 10% interest/collateral = 100
|
|
101
|
-
}
|
|
102
|
-
//# sourceMappingURL=risk-scorer.js.map
|
package/dist/risk-scorer.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"risk-scorer.js","sourceRoot":"","sources":["../src/risk-scorer.ts"],"names":[],"mappings":"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"}
|
package/dist/scanner.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* scanner.ts — discovers tokens with active lending markets.
|
|
3
|
-
*
|
|
4
|
-
* scans all migrated tokens, checks which ones have active loans,
|
|
5
|
-
* and returns them as MonitoredToken objects with price snapshots.
|
|
6
|
-
*/
|
|
7
|
-
import type { Connection } from '@solana/web3.js';
|
|
8
|
-
import type { MonitoredToken } from './types';
|
|
9
|
-
import type { Logger } from './logger';
|
|
10
|
-
export declare function scanForLendingMarkets(connection: Connection, existing: Map<string, MonitoredToken>, priceHistoryDepth: number, log: Logger): Promise<Map<string, MonitoredToken>>;
|
|
11
|
-
//# sourceMappingURL=scanner.d.ts.map
|
package/dist/scanner.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEtC,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EACrC,iBAAiB,EAAE,MAAM,EACzB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAmDtC"}
|
package/dist/scanner.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* scanner.ts — discovers tokens with active lending markets.
|
|
4
|
-
*
|
|
5
|
-
* scans all migrated tokens, checks which ones have active loans,
|
|
6
|
-
* and returns them as MonitoredToken objects with price snapshots.
|
|
7
|
-
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.scanForLendingMarkets = scanForLendingMarkets;
|
|
10
|
-
const torchsdk_1 = require("torchsdk");
|
|
11
|
-
async function scanForLendingMarkets(connection, existing, priceHistoryDepth, log) {
|
|
12
|
-
log.info('scanning for tokens with active lending...');
|
|
13
|
-
const { tokens } = await (0, torchsdk_1.getTokens)(connection, {
|
|
14
|
-
status: 'migrated',
|
|
15
|
-
sort: 'volume',
|
|
16
|
-
limit: 50,
|
|
17
|
-
});
|
|
18
|
-
log.debug(`found ${tokens.length} migrated tokens`);
|
|
19
|
-
const monitored = new Map(existing);
|
|
20
|
-
for (const token of tokens) {
|
|
21
|
-
try {
|
|
22
|
-
const lending = await (0, torchsdk_1.getLendingInfo)(connection, token.mint);
|
|
23
|
-
if (lending.active_loans === 0)
|
|
24
|
-
continue;
|
|
25
|
-
const priceSol = token.price_sol / torchsdk_1.LAMPORTS_PER_SOL;
|
|
26
|
-
const prev = existing.get(token.mint);
|
|
27
|
-
// build price history: append new price, trim to depth
|
|
28
|
-
const priceHistory = prev?.priceHistory ?? [];
|
|
29
|
-
priceHistory.push(priceSol);
|
|
30
|
-
if (priceHistory.length > priceHistoryDepth) {
|
|
31
|
-
priceHistory.splice(0, priceHistory.length - priceHistoryDepth);
|
|
32
|
-
}
|
|
33
|
-
monitored.set(token.mint, {
|
|
34
|
-
mint: token.mint,
|
|
35
|
-
name: token.name,
|
|
36
|
-
symbol: token.symbol,
|
|
37
|
-
lendingInfo: lending,
|
|
38
|
-
priceSol,
|
|
39
|
-
priceHistory,
|
|
40
|
-
activeBorrowers: prev?.activeBorrowers ?? [],
|
|
41
|
-
lastScanned: Date.now(),
|
|
42
|
-
});
|
|
43
|
-
log.info(`tracking: ${token.symbol}`, {
|
|
44
|
-
loans: lending.active_loans,
|
|
45
|
-
price: priceSol.toFixed(6),
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
// token may not have lending enabled — skip
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
log.info(`monitoring ${monitored.size} tokens with active lending`);
|
|
53
|
-
return monitored;
|
|
54
|
-
}
|
|
55
|
-
//# sourceMappingURL=scanner.js.map
|
package/dist/scanner.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAOH,sDAwDC;AA5DD,uCAAsE;AAI/D,KAAK,UAAU,qBAAqB,CACzC,UAAsB,EACtB,QAAqC,EACrC,iBAAyB,EACzB,GAAW;IAEX,GAAG,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAA;IAEtD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAA,oBAAS,EAAC,UAAU,EAAE;QAC7C,MAAM,EAAE,UAAU;QAClB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,EAAE;KACV,CAAC,CAAA;IAEF,GAAG,CAAC,KAAK,CAAC,SAAS,MAAM,CAAC,MAAM,kBAAkB,CAAC,CAAA;IAEnD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAyB,QAAQ,CAAC,CAAA;IAE3D,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,IAAA,yBAAc,EAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;YAE5D,IAAI,OAAO,CAAC,YAAY,KAAK,CAAC;gBAAE,SAAQ;YAExC,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,GAAG,2BAAgB,CAAA;YACnD,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAErC,uDAAuD;YACvD,MAAM,YAAY,GAAG,IAAI,EAAE,YAAY,IAAI,EAAE,CAAA;YAC7C,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YAC3B,IAAI,YAAY,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;gBAC5C,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,YAAY,CAAC,MAAM,GAAG,iBAAiB,CAAC,CAAA;YACjE,CAAC;YAED,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;gBACxB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,WAAW,EAAE,OAAO;gBACpB,QAAQ;gBACR,YAAY;gBACZ,eAAe,EAAE,IAAI,EAAE,eAAe,IAAI,EAAE;gBAC5C,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;aACxB,CAAC,CAAA;YAEF,GAAG,CAAC,IAAI,CAAC,aAAa,KAAK,CAAC,MAAM,EAAE,EAAE;gBACpC,KAAK,EAAE,OAAO,CAAC,YAAY;gBAC3B,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;aAC3B,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,4CAA4C;QAC9C,CAAC;IACH,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,cAAc,SAAS,CAAC,IAAI,6BAA6B,CAAC,CAAA;IACnE,OAAO,SAAS,CAAA;AAClB,CAAC"}
|
package/dist/types.d.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* types.ts — all interfaces and contracts for the liquidation bot.
|
|
3
|
-
*
|
|
4
|
-
* this is the blueprint. everything else implements these shapes.
|
|
5
|
-
*/
|
|
6
|
-
import type { Keypair } from '@solana/web3.js';
|
|
7
|
-
import type { LendingInfo, LoanPositionInfo } from 'torchsdk';
|
|
8
|
-
export interface TradeStats {
|
|
9
|
-
totalTrades: number;
|
|
10
|
-
wins: number;
|
|
11
|
-
losses: number;
|
|
12
|
-
winRate: number;
|
|
13
|
-
netPnlSol: number;
|
|
14
|
-
}
|
|
15
|
-
export interface WalletProfile {
|
|
16
|
-
address: string;
|
|
17
|
-
saidVerified: boolean;
|
|
18
|
-
trustTier: 'high' | 'medium' | 'low' | null;
|
|
19
|
-
tradeStats: TradeStats;
|
|
20
|
-
riskScore: number;
|
|
21
|
-
lastUpdated: number;
|
|
22
|
-
}
|
|
23
|
-
export interface RiskFactors {
|
|
24
|
-
ltvProximity: number;
|
|
25
|
-
priceMomentum: number;
|
|
26
|
-
walletRisk: number;
|
|
27
|
-
interestBurden: number;
|
|
28
|
-
}
|
|
29
|
-
export interface ScoredLoan {
|
|
30
|
-
mint: string;
|
|
31
|
-
tokenName: string;
|
|
32
|
-
borrower: string;
|
|
33
|
-
position: LoanPositionInfo;
|
|
34
|
-
walletProfile: WalletProfile;
|
|
35
|
-
riskScore: number;
|
|
36
|
-
factors: RiskFactors;
|
|
37
|
-
estimatedProfitLamports: number;
|
|
38
|
-
lastScored: number;
|
|
39
|
-
}
|
|
40
|
-
export interface MonitoredToken {
|
|
41
|
-
mint: string;
|
|
42
|
-
name: string;
|
|
43
|
-
symbol: string;
|
|
44
|
-
lendingInfo: LendingInfo;
|
|
45
|
-
priceSol: number;
|
|
46
|
-
priceHistory: number[];
|
|
47
|
-
activeBorrowers: string[];
|
|
48
|
-
lastScanned: number;
|
|
49
|
-
}
|
|
50
|
-
export interface LiquidationResult {
|
|
51
|
-
mint: string;
|
|
52
|
-
borrower: string;
|
|
53
|
-
signature: string;
|
|
54
|
-
profitLamports: number;
|
|
55
|
-
timestamp: number;
|
|
56
|
-
confirmed: boolean;
|
|
57
|
-
}
|
|
58
|
-
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
59
|
-
export interface BotConfig {
|
|
60
|
-
rpcUrl: string;
|
|
61
|
-
walletKeypair: Keypair;
|
|
62
|
-
scanIntervalMs: number;
|
|
63
|
-
scoreIntervalMs: number;
|
|
64
|
-
minProfitLamports: number;
|
|
65
|
-
riskThreshold: number;
|
|
66
|
-
priceHistoryDepth: number;
|
|
67
|
-
logLevel: LogLevel;
|
|
68
|
-
}
|
|
69
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAM7D,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,OAAO,CAAA;IACrB,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,IAAI,CAAA;IAC3C,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;CACpB;AAMD,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,aAAa,EAAE,aAAa,CAAA;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,WAAW,CAAA;IACpB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,UAAU,EAAE,MAAM,CAAA;CACnB;AAMD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,WAAW,CAAA;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,WAAW,EAAE,MAAM,CAAA;CACpB;AAMD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,OAAO,CAAA;CACnB;AAMD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAE1D,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,OAAO,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,iBAAiB,EAAE,MAAM,CAAA;IACzB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,EAAE,MAAM,CAAA;IACzB,QAAQ,EAAE,QAAQ,CAAA;CACnB"}
|
package/dist/types.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* types.ts — all interfaces and contracts for the liquidation bot.
|
|
4
|
-
*
|
|
5
|
-
* this is the blueprint. everything else implements these shapes.
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;;GAIG"}
|
package/dist/utils.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* utils.ts — shared helpers used across modules.
|
|
3
|
-
*/
|
|
4
|
-
export declare function sleep(ms: number): Promise<void>;
|
|
5
|
-
export declare function sol(lamports: number): string;
|
|
6
|
-
export declare function bpsToPercent(bps: number): string;
|
|
7
|
-
/** clamp a value between min and max */
|
|
8
|
-
export declare function clamp(value: number, min: number, max: number): number;
|
|
9
|
-
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED,wBAAgB,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wCAAwC;AACxC,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAErE"}
|
package/dist/utils.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* utils.ts — shared helpers used across modules.
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.sleep = sleep;
|
|
7
|
-
exports.sol = sol;
|
|
8
|
-
exports.bpsToPercent = bpsToPercent;
|
|
9
|
-
exports.clamp = clamp;
|
|
10
|
-
const torchsdk_1 = require("torchsdk");
|
|
11
|
-
function sleep(ms) {
|
|
12
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
13
|
-
}
|
|
14
|
-
function sol(lamports) {
|
|
15
|
-
return (lamports / torchsdk_1.LAMPORTS_PER_SOL).toFixed(4);
|
|
16
|
-
}
|
|
17
|
-
function bpsToPercent(bps) {
|
|
18
|
-
return (bps / 100).toFixed(2) + '%';
|
|
19
|
-
}
|
|
20
|
-
/** clamp a value between min and max */
|
|
21
|
-
function clamp(value, min, max) {
|
|
22
|
-
return Math.min(Math.max(value, min), max);
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=utils.js.map
|
package/dist/utils.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAIH,sBAEC;AAED,kBAEC;AAED,oCAEC;AAGD,sBAEC;AAjBD,uCAA2C;AAE3C,SAAgB,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;AAC9C,CAAC;AAED,SAAgB,GAAG,CAAC,QAAgB;IAClC,OAAO,CAAC,QAAQ,GAAG,2BAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;AACjD,CAAC;AAED,SAAgB,YAAY,CAAC,GAAW;IACtC,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,CAAA;AACrC,CAAC;AAED,wCAAwC;AACxC,SAAgB,KAAK,CAAC,KAAa,EAAE,GAAW,EAAE,GAAW;IAC3D,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAA;AAC5C,CAAC"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* wallet-profiler.ts — assesses wallet risk using SAID reputation + trade history.
|
|
3
|
-
*
|
|
4
|
-
* checks each borrower's trust tier and analyzes their trade messages
|
|
5
|
-
* to determine if they tend to lose money (higher liquidation risk).
|
|
6
|
-
*
|
|
7
|
-
* profiles are cached in-memory with a cooldown to avoid hammering RPC.
|
|
8
|
-
*/
|
|
9
|
-
import type { Connection } from '@solana/web3.js';
|
|
10
|
-
import type { WalletProfile } from './types';
|
|
11
|
-
import type { Logger } from './logger';
|
|
12
|
-
export declare class WalletProfiler {
|
|
13
|
-
private cache;
|
|
14
|
-
private log;
|
|
15
|
-
constructor(log: Logger);
|
|
16
|
-
profile(connection: Connection, address: string, mint: string): Promise<WalletProfile>;
|
|
17
|
-
private analyzeTradeHistory;
|
|
18
|
-
private computeWalletRisk;
|
|
19
|
-
private evictStale;
|
|
20
|
-
}
|
|
21
|
-
//# sourceMappingURL=wallet-profiler.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"wallet-profiler.d.ts","sourceRoot":"","sources":["../src/wallet-profiler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,SAAS,CAAA;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAOtC,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,GAAG,CAAQ;gBAEP,GAAG,EAAE,MAAM;IAIjB,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAgC9E,mBAAmB;IAsCjC,OAAO,CAAC,iBAAiB;IA2BzB,OAAO,CAAC,UAAU;CAgBnB"}
|
package/dist/wallet-profiler.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* wallet-profiler.ts — assesses wallet risk using SAID reputation + trade history.
|
|
4
|
-
*
|
|
5
|
-
* checks each borrower's trust tier and analyzes their trade messages
|
|
6
|
-
* to determine if they tend to lose money (higher liquidation risk).
|
|
7
|
-
*
|
|
8
|
-
* profiles are cached in-memory with a cooldown to avoid hammering RPC.
|
|
9
|
-
*/
|
|
10
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.WalletProfiler = void 0;
|
|
12
|
-
const torchsdk_1 = require("torchsdk");
|
|
13
|
-
const utils_1 = require("./utils");
|
|
14
|
-
const PROFILE_COOLDOWN_MS = 5 * 60 * 1000; // refresh profiles every 5 min
|
|
15
|
-
const MAX_CACHE_AGE_MS = 30 * 60 * 1000; // evict entries older than 30 min
|
|
16
|
-
const MAX_CACHE_SIZE = 1000; // hard cap on cache entries
|
|
17
|
-
class WalletProfiler {
|
|
18
|
-
constructor(log) {
|
|
19
|
-
this.cache = new Map();
|
|
20
|
-
this.log = log;
|
|
21
|
-
}
|
|
22
|
-
async profile(connection, address, mint) {
|
|
23
|
-
this.evictStale();
|
|
24
|
-
const cached = this.cache.get(address);
|
|
25
|
-
if (cached && Date.now() - cached.lastUpdated < PROFILE_COOLDOWN_MS) {
|
|
26
|
-
return cached;
|
|
27
|
-
}
|
|
28
|
-
this.log.debug(`profiling wallet ${address.slice(0, 8)}...`);
|
|
29
|
-
// SAID reputation
|
|
30
|
-
const said = await (0, torchsdk_1.verifySaid)(address);
|
|
31
|
-
// trade history from messages
|
|
32
|
-
const tradeStats = await this.analyzeTradeHistory(connection, mint, address);
|
|
33
|
-
// compute wallet risk score (0-100)
|
|
34
|
-
const riskScore = this.computeWalletRisk(said.trustTier, tradeStats);
|
|
35
|
-
const profile = {
|
|
36
|
-
address,
|
|
37
|
-
saidVerified: said.verified,
|
|
38
|
-
trustTier: said.trustTier,
|
|
39
|
-
tradeStats,
|
|
40
|
-
riskScore,
|
|
41
|
-
lastUpdated: Date.now(),
|
|
42
|
-
};
|
|
43
|
-
this.cache.set(address, profile);
|
|
44
|
-
return profile;
|
|
45
|
-
}
|
|
46
|
-
async analyzeTradeHistory(connection, mint, address) {
|
|
47
|
-
try {
|
|
48
|
-
const { messages } = await (0, torchsdk_1.getMessages)(connection, mint, 50);
|
|
49
|
-
// filter messages from this wallet and analyze buy/sell patterns
|
|
50
|
-
const walletMsgs = messages.filter((m) => m.sender === address);
|
|
51
|
-
let wins = 0;
|
|
52
|
-
let losses = 0;
|
|
53
|
-
let netPnlSol = 0;
|
|
54
|
-
for (const msg of walletMsgs) {
|
|
55
|
-
const m = msg;
|
|
56
|
-
if (m.pnl_sol !== undefined) {
|
|
57
|
-
if (m.pnl_sol > 0)
|
|
58
|
-
wins++;
|
|
59
|
-
else
|
|
60
|
-
losses++;
|
|
61
|
-
netPnlSol += m.pnl_sol;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
const totalTrades = wins + losses;
|
|
65
|
-
return {
|
|
66
|
-
totalTrades,
|
|
67
|
-
wins,
|
|
68
|
-
losses,
|
|
69
|
-
winRate: totalTrades > 0 ? wins / totalTrades : 0.5,
|
|
70
|
-
netPnlSol,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
// if we can't get trade history, assume neutral
|
|
75
|
-
return { totalTrades: 0, wins: 0, losses: 0, winRate: 0.5, netPnlSol: 0 };
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
computeWalletRisk(trustTier, stats) {
|
|
79
|
-
// base risk from trust tier
|
|
80
|
-
const tierRisk = {
|
|
81
|
-
high: 10,
|
|
82
|
-
medium: 40,
|
|
83
|
-
low: 70,
|
|
84
|
-
};
|
|
85
|
-
let risk = tierRisk[trustTier ?? ''] ?? 50; // unverified = 50
|
|
86
|
-
// modifier from trade history: bad traders are riskier
|
|
87
|
-
if (stats.totalTrades > 0) {
|
|
88
|
-
// low win rate increases risk, high win rate decreases it
|
|
89
|
-
const winRateModifier = (0.5 - stats.winRate) * 40; // -20 to +20
|
|
90
|
-
risk += winRateModifier;
|
|
91
|
-
// net losses increase risk
|
|
92
|
-
if (stats.netPnlSol < 0) {
|
|
93
|
-
risk += Math.min(Math.abs(stats.netPnlSol) * 5, 20); // up to +20
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return (0, utils_1.clamp)(Math.round(risk), 0, 100);
|
|
97
|
-
}
|
|
98
|
-
evictStale() {
|
|
99
|
-
const now = Date.now();
|
|
100
|
-
for (const [key, profile] of this.cache) {
|
|
101
|
-
if (now - profile.lastUpdated > MAX_CACHE_AGE_MS) {
|
|
102
|
-
this.cache.delete(key);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
// hard cap: if still too large, evict oldest entries
|
|
106
|
-
if (this.cache.size > MAX_CACHE_SIZE) {
|
|
107
|
-
const sorted = [...this.cache.entries()].sort((a, b) => a[1].lastUpdated - b[1].lastUpdated);
|
|
108
|
-
const toEvict = sorted.slice(0, this.cache.size - MAX_CACHE_SIZE);
|
|
109
|
-
for (const [key] of toEvict) {
|
|
110
|
-
this.cache.delete(key);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
exports.WalletProfiler = WalletProfiler;
|
|
116
|
-
//# sourceMappingURL=wallet-profiler.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"wallet-profiler.js","sourceRoot":"","sources":["../src/wallet-profiler.ts"],"names":[],"mappings":"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"}
|