torch-liquidation-agent 1.0.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/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +55 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +175 -0
- package/dist/index.js.map +1 -0
- package/dist/liquidator.d.ts +16 -0
- package/dist/liquidator.d.ts.map +1 -0
- package/dist/liquidator.js +65 -0
- package/dist/liquidator.js.map +1 -0
- package/dist/logger.d.ts +17 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +54 -0
- package/dist/logger.js.map +1 -0
- package/dist/monitor.d.ts +29 -0
- package/dist/monitor.d.ts.map +1 -0
- package/dist/monitor.js +165 -0
- package/dist/monitor.js.map +1 -0
- package/dist/risk-scorer.d.ts +13 -0
- package/dist/risk-scorer.d.ts.map +1 -0
- package/dist/risk-scorer.js +104 -0
- package/dist/risk-scorer.js.map +1 -0
- package/dist/scanner.d.ts +11 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +56 -0
- package/dist/scanner.js.map +1 -0
- package/dist/types.d.ts +68 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +9 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +24 -0
- package/dist/utils.js.map +1 -0
- package/dist/wallet-profiler.d.ts +24 -0
- package/dist/wallet-profiler.d.ts.map +1 -0
- package/dist/wallet-profiler.js +135 -0
- package/dist/wallet-profiler.js.map +1 -0
- package/package.json +39 -0
- package/readme.md +152 -0
|
@@ -0,0 +1,135 @@
|
|
|
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
|
+
* uses the torch agent kit for trade messages and calls the SAID API
|
|
11
|
+
* directly for wallet reputation verification.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.WalletProfiler = void 0;
|
|
15
|
+
const solana_agent_kit_torch_market_1 = require("solana-agent-kit-torch-market");
|
|
16
|
+
const utils_1 = require("./utils");
|
|
17
|
+
const PROFILE_COOLDOWN_MS = 5 * 60 * 1000; // refresh profiles every 5 min
|
|
18
|
+
const MAX_CACHE_AGE_MS = 30 * 60 * 1000; // evict entries older than 30 min
|
|
19
|
+
const MAX_CACHE_SIZE = 1000; // hard cap on cache entries
|
|
20
|
+
const SAID_API_URL = 'https://api.saidprotocol.com/api';
|
|
21
|
+
async function verifySaid(address) {
|
|
22
|
+
try {
|
|
23
|
+
const res = await fetch(`${SAID_API_URL}/verify/${address}`);
|
|
24
|
+
if (!res.ok)
|
|
25
|
+
return { verified: false, trustTier: null };
|
|
26
|
+
const data = (await res.json());
|
|
27
|
+
return {
|
|
28
|
+
verified: data.verified ?? false,
|
|
29
|
+
trustTier: data.trust_tier ?? null,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return { verified: false, trustTier: null };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
class WalletProfiler {
|
|
37
|
+
constructor(log) {
|
|
38
|
+
this.cache = new Map();
|
|
39
|
+
this.log = log;
|
|
40
|
+
}
|
|
41
|
+
async profile(agent, address, mint) {
|
|
42
|
+
this.evictStale();
|
|
43
|
+
const cached = this.cache.get(address);
|
|
44
|
+
if (cached && Date.now() - cached.lastUpdated < PROFILE_COOLDOWN_MS) {
|
|
45
|
+
return cached;
|
|
46
|
+
}
|
|
47
|
+
this.log.debug(`profiling wallet ${address.slice(0, 8)}...`);
|
|
48
|
+
// SAID reputation
|
|
49
|
+
const said = await verifySaid(address);
|
|
50
|
+
// trade history from messages
|
|
51
|
+
const tradeStats = await this.analyzeTradeHistory(agent, mint, address);
|
|
52
|
+
// compute wallet risk score (0-100)
|
|
53
|
+
const riskScore = this.computeWalletRisk(said.trustTier, tradeStats);
|
|
54
|
+
const profile = {
|
|
55
|
+
address,
|
|
56
|
+
saidVerified: said.verified,
|
|
57
|
+
trustTier: said.trustTier,
|
|
58
|
+
tradeStats,
|
|
59
|
+
riskScore,
|
|
60
|
+
lastUpdated: Date.now(),
|
|
61
|
+
};
|
|
62
|
+
this.cache.set(address, profile);
|
|
63
|
+
return profile;
|
|
64
|
+
}
|
|
65
|
+
async analyzeTradeHistory(agent, mint, address) {
|
|
66
|
+
try {
|
|
67
|
+
const messages = await (0, solana_agent_kit_torch_market_1.torchGetMessages)(agent, mint, 50);
|
|
68
|
+
// filter messages from this wallet and analyze buy/sell patterns
|
|
69
|
+
const walletMsgs = messages.filter((m) => m.sender === address);
|
|
70
|
+
let wins = 0;
|
|
71
|
+
let losses = 0;
|
|
72
|
+
let netPnlSol = 0;
|
|
73
|
+
for (const msg of walletMsgs) {
|
|
74
|
+
const m = msg;
|
|
75
|
+
if (m.pnl_sol !== undefined) {
|
|
76
|
+
if (m.pnl_sol > 0)
|
|
77
|
+
wins++;
|
|
78
|
+
else
|
|
79
|
+
losses++;
|
|
80
|
+
netPnlSol += m.pnl_sol;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const totalTrades = wins + losses;
|
|
84
|
+
return {
|
|
85
|
+
totalTrades,
|
|
86
|
+
wins,
|
|
87
|
+
losses,
|
|
88
|
+
winRate: totalTrades > 0 ? wins / totalTrades : 0.5,
|
|
89
|
+
netPnlSol,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// if we can't get trade history, assume neutral
|
|
94
|
+
return { totalTrades: 0, wins: 0, losses: 0, winRate: 0.5, netPnlSol: 0 };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
computeWalletRisk(trustTier, stats) {
|
|
98
|
+
// base risk from trust tier
|
|
99
|
+
const tierRisk = {
|
|
100
|
+
high: 10,
|
|
101
|
+
medium: 40,
|
|
102
|
+
low: 70,
|
|
103
|
+
};
|
|
104
|
+
let risk = tierRisk[trustTier ?? ''] ?? 50; // unverified = 50
|
|
105
|
+
// modifier from trade history: bad traders are riskier
|
|
106
|
+
if (stats.totalTrades > 0) {
|
|
107
|
+
// low win rate increases risk, high win rate decreases it
|
|
108
|
+
const winRateModifier = (0.5 - stats.winRate) * 40; // -20 to +20
|
|
109
|
+
risk += winRateModifier;
|
|
110
|
+
// net losses increase risk
|
|
111
|
+
if (stats.netPnlSol < 0) {
|
|
112
|
+
risk += Math.min(Math.abs(stats.netPnlSol) * 5, 20); // up to +20
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return (0, utils_1.clamp)(Math.round(risk), 0, 100);
|
|
116
|
+
}
|
|
117
|
+
evictStale() {
|
|
118
|
+
const now = Date.now();
|
|
119
|
+
for (const [key, profile] of this.cache) {
|
|
120
|
+
if (now - profile.lastUpdated > MAX_CACHE_AGE_MS) {
|
|
121
|
+
this.cache.delete(key);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// hard cap: if still too large, evict oldest entries
|
|
125
|
+
if (this.cache.size > MAX_CACHE_SIZE) {
|
|
126
|
+
const sorted = [...this.cache.entries()].sort((a, b) => a[1].lastUpdated - b[1].lastUpdated);
|
|
127
|
+
const toEvict = sorted.slice(0, this.cache.size - MAX_CACHE_SIZE);
|
|
128
|
+
for (const [key] of toEvict) {
|
|
129
|
+
this.cache.delete(key);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
exports.WalletProfiler = WalletProfiler;
|
|
135
|
+
//# sourceMappingURL=wallet-profiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet-profiler.js","sourceRoot":"","sources":["../src/wallet-profiler.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "torch-liquidation-agent",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "lending position monitor and auto-liquidation skill using the torch-agent-kit",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"torch-liquidation-agent": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"clean": "rm -rf dist",
|
|
16
|
+
"test": "npx tsx tests/test_lending.ts",
|
|
17
|
+
"test:bot": "npx tsx tests/test_bot.ts",
|
|
18
|
+
"format": "prettier --write src/ tests/"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@coral-xyz/anchor": "^0.32.1",
|
|
22
|
+
"@solana/spl-token": "^0.4.14",
|
|
23
|
+
"@solana/web3.js": "^1.98.4",
|
|
24
|
+
"bs58": "^6.0.0",
|
|
25
|
+
"solana-agent-kit": "^2.0.0",
|
|
26
|
+
"solana-agent-kit-torch-market": "^3.0.6"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^20",
|
|
30
|
+
"prettier": "^3.5.3",
|
|
31
|
+
"torchsdk": "^1.0.5",
|
|
32
|
+
"typescript": "^5"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@solana/web3.js": "^1.98.0"
|
|
36
|
+
},
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"packageManager": "pnpm@9.10.0+sha512.73a29afa36a0d092ece5271de5177ecbf8318d454ecd701343131b8ebc0c1a91c487da46ab77c8e596d6acf1461e3594ced4becedf8921b074fbd8653ed7051c"
|
|
39
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# torch-liquidation-agent
|
|
2
|
+
|
|
3
|
+
Multi-token liquidation bot for [Torch Market](https://torch.market) lending on Solana, built on [solana-agent-kit](https://github.com/sendaifun/solana-agent-kit) + [solana-agent-kit-torch-market](https://www.npmjs.com/package/solana-agent-kit-torch-market).
|
|
4
|
+
|
|
5
|
+
Same functionality as [`torch-liquidation-bot`](../bot/) but uses the Torch Agent Kit plugin instead of raw torchsdk — making it compatible with AI agent frameworks (LangChain, Vercel AI, OpenAI tools).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install torch-liquidation-agent
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## How It Works
|
|
14
|
+
|
|
15
|
+
Every migrated token on Torch has a built-in lending market. Holders borrow SOL against their tokens. When a borrower's loan-to-value ratio exceeds 65%, anyone can liquidate the position and collect a 10% bonus on the collateral.
|
|
16
|
+
|
|
17
|
+
This bot finds those opportunities before other bots do by **predicting** which positions will go underwater:
|
|
18
|
+
|
|
19
|
+
1. **Scan** -- discovers all tokens with active lending markets
|
|
20
|
+
2. **Profile** -- checks each borrower's SAID reputation and trade history
|
|
21
|
+
3. **Score** -- rates every loan on a 4-factor risk model (0-100)
|
|
22
|
+
4. **Liquidate** -- executes when a position crosses the threshold and the profit exceeds your minimum
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
MODE=bot WALLET=<base58-private-key> RPC_URL=<rpc-endpoint> npx torch-liquidation-agent
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Modes
|
|
31
|
+
|
|
32
|
+
### `bot` (default) -- full liquidation bot
|
|
33
|
+
|
|
34
|
+
Runs two concurrent loops:
|
|
35
|
+
- **Scan loop** (every 60s) -- finds tokens with active lending, snapshots prices
|
|
36
|
+
- **Score loop** (every 15s) -- profiles borrowers, scores loans, executes liquidations
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
MODE=bot WALLET=<key> RPC_URL=<rpc> npx torch-liquidation-agent
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### `info` -- display lending parameters
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# all migrated tokens with lending
|
|
46
|
+
MODE=info RPC_URL=<rpc> npx torch-liquidation-agent
|
|
47
|
+
|
|
48
|
+
# specific token
|
|
49
|
+
MODE=info MINT=<mint> RPC_URL=<rpc> npx torch-liquidation-agent
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### `watch` -- monitor your own loan health
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
MODE=watch MINT=<mint> WALLET=<key> RPC_URL=<rpc> npx torch-liquidation-agent
|
|
56
|
+
|
|
57
|
+
# with auto-repay if your position becomes liquidatable
|
|
58
|
+
MODE=watch MINT=<mint> WALLET=<key> AUTO_REPAY=true RPC_URL=<rpc> npx torch-liquidation-agent
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Risk Scoring
|
|
62
|
+
|
|
63
|
+
Every loan gets a composite score from four weighted factors:
|
|
64
|
+
|
|
65
|
+
| Factor | Weight | What It Measures |
|
|
66
|
+
|--------|--------|------------------|
|
|
67
|
+
| LTV proximity | 40% | How close to the 65% liquidation threshold |
|
|
68
|
+
| Price momentum | 30% | Collateral price trend (linear regression on recent snapshots) |
|
|
69
|
+
| Wallet risk | 20% | SAID trust tier + trade win/loss ratio |
|
|
70
|
+
| Interest burden | 10% | Accrued interest relative to collateral value |
|
|
71
|
+
|
|
72
|
+
Positions above the risk threshold (default: 60) are flagged and watched closely. Liquidatable positions with profit above your minimum are executed immediately, highest profit first.
|
|
73
|
+
|
|
74
|
+
## Configuration
|
|
75
|
+
|
|
76
|
+
| Variable | Required | Default | Description |
|
|
77
|
+
|----------|----------|---------|-------------|
|
|
78
|
+
| `RPC_URL` | yes | -- | Solana RPC endpoint |
|
|
79
|
+
| `WALLET` | bot/watch | -- | Base58 private key |
|
|
80
|
+
| `MODE` | no | `bot` | `bot`, `info`, or `watch` |
|
|
81
|
+
| `MINT` | info/watch | -- | Token mint address |
|
|
82
|
+
| `SCAN_INTERVAL_MS` | no | `60000` | Token discovery interval |
|
|
83
|
+
| `SCORE_INTERVAL_MS` | no | `15000` | Position scoring interval |
|
|
84
|
+
| `MIN_PROFIT_SOL` | no | `0.01` | Minimum profit to execute liquidation |
|
|
85
|
+
| `RISK_THRESHOLD` | no | `60` | Risk score cutoff for close monitoring |
|
|
86
|
+
| `PRICE_HISTORY` | no | `20` | Price snapshots to keep for momentum |
|
|
87
|
+
| `LOG_LEVEL` | no | `info` | `debug`, `info`, `warn`, `error` |
|
|
88
|
+
|
|
89
|
+
## Architecture
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
src/
|
|
93
|
+
├── types.ts — interfaces and contracts
|
|
94
|
+
├── config.ts — env vars → SolanaAgentKit + typed config
|
|
95
|
+
├── logger.ts — structured logging
|
|
96
|
+
├── utils.ts — shared helpers
|
|
97
|
+
├── scanner.ts — discovers tokens with active lending
|
|
98
|
+
├── wallet-profiler.ts — SAID reputation + trade history
|
|
99
|
+
├── risk-scorer.ts — 4-factor risk model
|
|
100
|
+
├── liquidator.ts — executes liquidation txs via agent kit
|
|
101
|
+
├── monitor.ts — scan + score orchestration
|
|
102
|
+
└── index.ts — entry point
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Differences from `torch-liquidation-bot`
|
|
106
|
+
|
|
107
|
+
| | `bot` (torchsdk) | `agent` (agent kit) |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| SDK | `torchsdk` direct | `solana-agent-kit-torch-market` plugin |
|
|
110
|
+
| Transaction signing | Manual (`sendAndConfirmTransaction`) | Handled by `SolanaAgentKit` |
|
|
111
|
+
| Holder discovery | `torchsdk.getHolders()` | Solana RPC `getTokenLargestAccounts` |
|
|
112
|
+
| SAID verification | `torchsdk.verifySaid()` | Direct SAID API call |
|
|
113
|
+
| AI agent compatible | No | Yes (LangChain, Vercel AI, OpenAI tools) |
|
|
114
|
+
|
|
115
|
+
## Lending Parameters
|
|
116
|
+
|
|
117
|
+
| Parameter | Value |
|
|
118
|
+
|-----------|-------|
|
|
119
|
+
| Max LTV | 50% |
|
|
120
|
+
| Liquidation threshold | 65% LTV |
|
|
121
|
+
| Interest rate | 2% per epoch (~7 days) |
|
|
122
|
+
| Liquidation bonus | 10% of collateral |
|
|
123
|
+
| Min borrow | 0.1 SOL |
|
|
124
|
+
|
|
125
|
+
## Testing
|
|
126
|
+
|
|
127
|
+
Requires [Surfpool](https://github.com/nicholasgasior/surfpool) running a mainnet fork:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
surfpool start --network mainnet --no-tui
|
|
131
|
+
pnpm test # lending lifecycle test
|
|
132
|
+
pnpm test:bot # bot module test (scanner, profiler, scorer, liquidator)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Security
|
|
136
|
+
|
|
137
|
+
- Private keys loaded from env, never logged or transmitted
|
|
138
|
+
- All transactions signed by `SolanaAgentKit` via `KeypairWallet` -- keys never leave your environment
|
|
139
|
+
- Minimum profit threshold prevents unprofitable executions
|
|
140
|
+
- Graceful shutdown on SIGINT
|
|
141
|
+
|
|
142
|
+
## Links
|
|
143
|
+
|
|
144
|
+
- [solana-agent-kit](https://github.com/sendaifun/solana-agent-kit) -- the agent framework
|
|
145
|
+
- [solana-agent-kit-torch-market](https://www.npmjs.com/package/solana-agent-kit-torch-market) -- Torch Market plugin
|
|
146
|
+
- [torch-liquidation-bot](../bot/) -- the torchsdk-based version
|
|
147
|
+
- [Torch Market](https://torch.market) -- the protocol
|
|
148
|
+
- [SAID Protocol](https://saidprotocol.com) -- wallet reputation layer
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT
|