torch-liquidation-bot 2.0.8 → 3.0.1

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 CHANGED
@@ -1,8 +1,13 @@
1
1
  /**
2
- * config.ts — loads environment variables into a typed ReadOnlyConfig.
2
+ * config.ts — loads environment variables into a typed BotConfig.
3
3
  *
4
- * no wallet loaded, no keypair decoded, no signing possible.
4
+ * env vars:
5
+ * SOLANA_RPC_URL — solana RPC endpoint (required, fallback: RPC_URL)
6
+ * VAULT_CREATOR — vault creator pubkey (required)
7
+ * SOLANA_PRIVATE_KEY — disposable controller keypair, base58 (optional)
8
+ * SCAN_INTERVAL_MS — ms between scan cycles (default 30000, min 5000)
9
+ * LOG_LEVEL — debug | info | warn | error (default info)
5
10
  */
6
- import type { ReadOnlyConfig } from './types';
7
- export declare function loadReadOnlyConfig(): ReadOnlyConfig;
11
+ import type { BotConfig } from './types';
12
+ export declare const loadConfig: () => BotConfig;
8
13
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAY,MAAM,SAAS,CAAA;AAIvD,wBAAgB,kBAAkB,IAAI,cAAc,CAUnD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,SAAS,CAAA;AAIlD,eAAO,MAAM,UAAU,QAAO,SAoB7B,CAAA"}
package/dist/config.js CHANGED
@@ -1,20 +1,34 @@
1
1
  "use strict";
2
2
  /**
3
- * config.ts — loads environment variables into a typed ReadOnlyConfig.
3
+ * config.ts — loads environment variables into a typed BotConfig.
4
4
  *
5
- * no wallet loaded, no keypair decoded, no signing possible.
5
+ * env vars:
6
+ * SOLANA_RPC_URL — solana RPC endpoint (required, fallback: RPC_URL)
7
+ * VAULT_CREATOR — vault creator pubkey (required)
8
+ * SOLANA_PRIVATE_KEY — disposable controller keypair, base58 (optional)
9
+ * SCAN_INTERVAL_MS — ms between scan cycles (default 30000, min 5000)
10
+ * LOG_LEVEL — debug | info | warn | error (default info)
6
11
  */
7
12
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.loadReadOnlyConfig = loadReadOnlyConfig;
13
+ exports.loadConfig = void 0;
9
14
  const LOG_LEVELS = ['debug', 'info', 'warn', 'error'];
10
- function loadReadOnlyConfig() {
11
- const rpcUrl = process.env.RPC_URL;
15
+ const loadConfig = () => {
16
+ const rpcUrl = process.env.SOLANA_RPC_URL ?? process.env.RPC_URL;
12
17
  if (!rpcUrl)
13
- throw new Error('RPC_URL env var is required');
18
+ throw new Error('SOLANA_RPC_URL env var is required (fallback: RPC_URL)');
19
+ const vaultCreator = process.env.VAULT_CREATOR;
20
+ if (!vaultCreator)
21
+ throw new Error('VAULT_CREATOR env var is required (vault creator pubkey)');
22
+ const privateKey = process.env.SOLANA_PRIVATE_KEY ?? null;
23
+ const scanIntervalMs = parseInt(process.env.SCAN_INTERVAL_MS ?? '30000', 10);
24
+ if (isNaN(scanIntervalMs) || scanIntervalMs < 5000) {
25
+ throw new Error('SCAN_INTERVAL_MS must be a number >= 5000');
26
+ }
14
27
  const logLevel = (process.env.LOG_LEVEL ?? 'info');
15
28
  if (!LOG_LEVELS.includes(logLevel)) {
16
29
  throw new Error(`LOG_LEVEL must be one of: ${LOG_LEVELS.join(', ')}`);
17
30
  }
18
- return { rpcUrl, logLevel };
19
- }
31
+ return { rpcUrl, vaultCreator, privateKey, scanIntervalMs, logLevel };
32
+ };
33
+ exports.loadConfig = loadConfig;
20
34
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAMH,gDAUC;AAZD,MAAM,UAAU,GAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;AAEjE,SAAgB,kBAAkB;IAChC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAA;IAClC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;IAE3D,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM,CAAa,CAAA;IAC9D,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,6BAA6B,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACvE,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;AAC7B,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAIH,MAAM,UAAU,GAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;AAE1D,MAAM,UAAU,GAAG,GAAc,EAAE;IACxC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAA;IAChE,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAA;IAEtF,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAA;IAC9C,IAAI,CAAC,YAAY;QAAE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAA;IAE9F,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,IAAI,CAAA;IAEzD,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,OAAO,EAAE,EAAE,CAAC,CAAA;IAC5E,IAAI,KAAK,CAAC,cAAc,CAAC,IAAI,cAAc,GAAG,IAAI,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAC9D,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM,CAAa,CAAA;IAC9D,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,6BAA6B,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACvE,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAA;AACvE,CAAC,CAAA;AApBY,QAAA,UAAU,cAoBtB"}
package/dist/index.d.ts CHANGED
@@ -1,16 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * torch-lending-monitorread-only lending market scanner.
3
+ * torch-liquidation-botvault-based liquidation bot.
4
4
  *
5
- * displays lending parameters for tokens on Torch Market.
6
- * no wallet required. no signing. no state changes.
5
+ * generates an agent keypair in-process (or uses SOLANA_PRIVATE_KEY if provided).
6
+ * all operations route through a torch vault identified by VAULT_CREATOR.
7
7
  *
8
8
  * usage:
9
- * # show all migrated tokens with lending
10
- * RPC_URL=<rpc> npx tsx src/index.ts
9
+ * VAULT_CREATOR=<pubkey> SOLANA_RPC_URL=<rpc> npx tsx src/index.ts
11
10
  *
12
- * # show lending info for one token
13
- * MINT=<mint> RPC_URL=<rpc> npx tsx src/index.ts
11
+ * env:
12
+ * SOLANA_RPC_URL — solana RPC endpoint (required, fallback: RPC_URL)
13
+ * VAULT_CREATOR — vault creator pubkey (required)
14
+ * SOLANA_PRIVATE_KEY — disposable controller keypair, base58 (optional)
15
+ * SCAN_INTERVAL_MS — ms between scan cycles (default 30000, min 5000)
16
+ * LOG_LEVEL — debug | info | warn | error (default info)
14
17
  */
15
18
  export {};
16
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG"}
package/dist/index.js CHANGED
@@ -1,17 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
  /**
4
- * torch-lending-monitorread-only lending market scanner.
4
+ * torch-liquidation-botvault-based liquidation bot.
5
5
  *
6
- * displays lending parameters for tokens on Torch Market.
7
- * no wallet required. no signing. no state changes.
6
+ * generates an agent keypair in-process (or uses SOLANA_PRIVATE_KEY if provided).
7
+ * all operations route through a torch vault identified by VAULT_CREATOR.
8
8
  *
9
9
  * usage:
10
- * # show all migrated tokens with lending
11
- * RPC_URL=<rpc> npx tsx src/index.ts
10
+ * VAULT_CREATOR=<pubkey> SOLANA_RPC_URL=<rpc> npx tsx src/index.ts
12
11
  *
13
- * # show lending info for one token
14
- * MINT=<mint> RPC_URL=<rpc> npx tsx src/index.ts
12
+ * env:
13
+ * SOLANA_RPC_URL — solana RPC endpoint (required, fallback: RPC_URL)
14
+ * VAULT_CREATOR — vault creator pubkey (required)
15
+ * SOLANA_PRIVATE_KEY — disposable controller keypair, base58 (optional)
16
+ * SCAN_INTERVAL_MS — ms between scan cycles (default 30000, min 5000)
17
+ * LOG_LEVEL — debug | info | warn | error (default info)
15
18
  */
16
19
  Object.defineProperty(exports, "__esModule", { value: true });
17
20
  const web3_js_1 = require("@solana/web3.js");
@@ -19,56 +22,150 @@ const torchsdk_1 = require("torchsdk");
19
22
  const config_1 = require("./config");
20
23
  const utils_1 = require("./utils");
21
24
  // ---------------------------------------------------------------------------
22
- // read-only info display
25
+ // scan & liquidate
23
26
  // ---------------------------------------------------------------------------
24
- async function showLendingInfo(connection, mint) {
25
- const token = await (0, torchsdk_1.getToken)(connection, mint);
26
- const lending = await (0, torchsdk_1.getLendingInfo)(connection, mint);
27
- console.log(`\n=== lending info: ${token.name} (${token.symbol}) ===`);
28
- console.log(`status: ${token.status}`);
29
- console.log(`token price: ${(0, utils_1.sol)(token.price_sol)} SOL`);
30
- console.log(`interest rate: ${(0, utils_1.bpsToPercent)(lending.interest_rate_bps)}`);
31
- console.log(`max LTV: ${(0, utils_1.bpsToPercent)(lending.max_ltv_bps)}`);
32
- console.log(`liquidation threshold: ${(0, utils_1.bpsToPercent)(lending.liquidation_threshold_bps)}`);
33
- console.log(`liquidation bonus: ${(0, utils_1.bpsToPercent)(lending.liquidation_bonus_bps)}`);
34
- console.log(`treasury SOL avail: ${(0, utils_1.sol)(lending.treasury_sol_available)} SOL`);
35
- console.log(`total SOL lent: ${lending.total_sol_lent ? (0, utils_1.sol)(lending.total_sol_lent) : (0, utils_1.sol)(0)} SOL`);
36
- console.log(`active loans: ${lending.active_loans}`);
37
- }
38
- async function showAllLending(connection) {
39
- console.log('=== torch lending monitor ===\n');
40
- console.log('no MINT specified — showing all migrated tokens with lending\n');
27
+ const scanAndLiquidate = async (connection, log, vaultCreator, agentKeypair) => {
41
28
  const { tokens } = await (0, torchsdk_1.getTokens)(connection, {
42
29
  status: 'migrated',
43
30
  sort: 'volume',
44
- limit: 10,
31
+ limit: 50,
45
32
  });
46
- for (const t of tokens) {
33
+ log('debug', `discovered ${tokens.length} migrated tokens`);
34
+ for (const token of tokens) {
35
+ let lending;
47
36
  try {
48
- const lending = await (0, torchsdk_1.getLendingInfo)(connection, t.mint);
49
- console.log(`${t.symbol.padEnd(10)} | ` +
50
- `rate: ${(0, utils_1.bpsToPercent)(lending.interest_rate_bps).padEnd(7)} | ` +
51
- `loans: ${String(lending.active_loans).padEnd(4)} | ` +
52
- `avail: ${(0, utils_1.sol)(lending.treasury_sol_available)} SOL`);
37
+ lending = await (0, torchsdk_1.getLendingInfo)(connection, token.mint);
53
38
  }
54
39
  catch {
55
- // token may not have lending enabled yet
40
+ continue; // lending not enabled for this token
41
+ }
42
+ if (!lending.active_loans || lending.active_loans === 0)
43
+ continue;
44
+ log('debug', `${token.symbol} — ${lending.active_loans} active loans, ` +
45
+ `threshold: ${(0, utils_1.bpsToPercent)(lending.liquidation_threshold_bps)}, ` +
46
+ `bonus: ${(0, utils_1.bpsToPercent)(lending.liquidation_bonus_bps)}`);
47
+ // get holders as potential borrowers
48
+ let holders;
49
+ try {
50
+ const result = await (0, torchsdk_1.getHolders)(connection, token.mint);
51
+ holders = result.holders;
52
+ }
53
+ catch {
54
+ log('debug', `${token.symbol} — could not fetch holders, skipping`);
55
+ continue;
56
+ }
57
+ for (const holder of holders) {
58
+ let position;
59
+ try {
60
+ position = await (0, torchsdk_1.getLoanPosition)(connection, token.mint, holder.address);
61
+ }
62
+ catch {
63
+ continue; // no loan position for this holder
64
+ }
65
+ // SDK provides health status directly — skip non-liquidatable positions
66
+ if (position.health !== 'liquidatable')
67
+ continue;
68
+ log('info', `LIQUIDATABLE | ${token.symbol} | borrower=${holder.address.slice(0, 8)}... | ` +
69
+ `LTV=${position.current_ltv_bps != null ? (0, utils_1.bpsToPercent)(position.current_ltv_bps) : '?'} > ` +
70
+ `threshold=${(0, utils_1.bpsToPercent)(lending.liquidation_threshold_bps)} | ` +
71
+ `owed=${(0, utils_1.sol)(position.total_owed)} SOL`);
72
+ // build and execute liquidation through the vault
73
+ try {
74
+ const { transaction, message } = await (0, torchsdk_1.buildLiquidateTransaction)(connection, {
75
+ mint: token.mint,
76
+ liquidator: agentKeypair.publicKey.toBase58(),
77
+ borrower: holder.address,
78
+ vault: vaultCreator,
79
+ });
80
+ transaction.sign(agentKeypair);
81
+ const signature = await connection.sendRawTransaction(transaction.serialize());
82
+ await (0, torchsdk_1.confirmTransaction)(connection, signature, agentKeypair.publicKey.toBase58());
83
+ log('info', `LIQUIDATED | ${token.symbol} | borrower=${holder.address.slice(0, 8)}... | ` +
84
+ `sig=${signature.slice(0, 16)}... | ${message}`);
85
+ }
86
+ catch (err) {
87
+ log('warn', `LIQUIDATION FAILED | ${token.symbol} | ${holder.address.slice(0, 8)}... | ${err.message}`);
88
+ }
56
89
  }
57
90
  }
58
- }
91
+ };
59
92
  // ---------------------------------------------------------------------------
60
- // main — read-only only
93
+ // main — vault-routed liquidation loop
61
94
  // ---------------------------------------------------------------------------
62
- async function main() {
63
- const config = (0, config_1.loadReadOnlyConfig)();
95
+ const main = async () => {
96
+ const config = (0, config_1.loadConfig)();
97
+ const log = (0, utils_1.createLogger)(config.logLevel);
64
98
  const connection = new web3_js_1.Connection(config.rpcUrl, 'confirmed');
65
- const MINT = process.env.MINT;
66
- if (MINT) {
67
- await showLendingInfo(connection, MINT);
99
+ // load or generate agent keypair
100
+ let agentKeypair;
101
+ if (config.privateKey) {
102
+ try {
103
+ const parsed = JSON.parse(config.privateKey);
104
+ if (Array.isArray(parsed)) {
105
+ agentKeypair = web3_js_1.Keypair.fromSecretKey(Uint8Array.from(parsed));
106
+ }
107
+ else {
108
+ throw new Error('SOLANA_PRIVATE_KEY JSON must be a byte array');
109
+ }
110
+ }
111
+ catch (e) {
112
+ if (e.message?.includes('byte array'))
113
+ throw e;
114
+ // not JSON — try base58
115
+ agentKeypair = web3_js_1.Keypair.fromSecretKey((0, utils_1.decodeBase58)(config.privateKey));
116
+ }
117
+ log('info', 'loaded keypair from SOLANA_PRIVATE_KEY');
68
118
  }
69
119
  else {
70
- await showAllLending(connection);
120
+ agentKeypair = web3_js_1.Keypair.generate();
121
+ log('info', 'generated fresh agent keypair');
122
+ }
123
+ console.log('=== torch liquidation bot ===');
124
+ console.log(`agent wallet: ${agentKeypair.publicKey.toBase58()}`);
125
+ console.log(`vault creator: ${config.vaultCreator}`);
126
+ console.log(`scan interval: ${config.scanIntervalMs}ms`);
127
+ console.log();
128
+ // verify vault exists
129
+ const vault = await (0, torchsdk_1.getVault)(connection, config.vaultCreator);
130
+ if (!vault) {
131
+ throw new Error(`vault not found for creator ${config.vaultCreator}`);
132
+ }
133
+ log('info', `vault found — authority=${vault.authority}`);
134
+ // verify agent wallet is linked to vault
135
+ const link = await (0, torchsdk_1.getVaultForWallet)(connection, agentKeypair.publicKey.toBase58());
136
+ if (!link) {
137
+ console.log();
138
+ console.log('--- ACTION REQUIRED ---');
139
+ console.log('agent wallet is NOT linked to the vault.');
140
+ console.log('link it by running (from your authority wallet):');
141
+ console.log();
142
+ console.log(` buildLinkWalletTransaction(connection, {`);
143
+ console.log(` authority: "<your-authority-pubkey>",`);
144
+ console.log(` vault_creator: "${config.vaultCreator}",`);
145
+ console.log(` wallet_to_link: "${agentKeypair.publicKey.toBase58()}"`);
146
+ console.log(` })`);
147
+ console.log();
148
+ console.log('then restart the bot.');
149
+ console.log('-----------------------');
150
+ process.exit(1);
151
+ }
152
+ log('info', 'agent wallet linked to vault — starting scan loop');
153
+ log('info', `treasury: ${(0, utils_1.sol)(vault.sol_balance ?? 0)} SOL`);
154
+ // scan loop
155
+ while (true) {
156
+ try {
157
+ log('debug', '--- scan cycle start ---');
158
+ await scanAndLiquidate(connection, log, config.vaultCreator, agentKeypair);
159
+ log('debug', '--- scan cycle end ---');
160
+ }
161
+ catch (err) {
162
+ log('error', `scan cycle error: ${err.message}`);
163
+ }
164
+ await new Promise((resolve) => setTimeout(resolve, config.scanIntervalMs));
71
165
  }
72
- }
73
- main();
166
+ };
167
+ main().catch((err) => {
168
+ console.error('FATAL:', err.message ?? err);
169
+ process.exit(1);
170
+ });
74
171
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,9 +1,12 @@
1
1
  /**
2
- * types.ts — interfaces for the read-only lending scanner.
2
+ * types.ts — interfaces for the vault-based liquidation bot.
3
3
  */
4
4
  export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
5
- export interface ReadOnlyConfig {
5
+ export interface BotConfig {
6
6
  rpcUrl: string;
7
+ vaultCreator: string;
8
+ privateKey: string | null;
9
+ scanIntervalMs: number;
7
10
  logLevel: LogLevel;
8
11
  }
9
12
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAE1D,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,QAAQ,CAAA;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAE1D,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,QAAQ,CAAA;CACnB"}
package/dist/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /**
3
- * types.ts — interfaces for the read-only lending scanner.
3
+ * types.ts — interfaces for the vault-based liquidation bot.
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  //# sourceMappingURL=types.js.map
package/dist/utils.d.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  /**
2
2
  * utils.ts — shared helpers.
3
3
  */
4
- export declare function sol(lamports: number): string;
5
- export declare function bpsToPercent(bps: number): string;
4
+ import type { LogLevel } from './types';
5
+ export declare const sol: (lamports: number) => string;
6
+ export declare const bpsToPercent: (bps: number) => string;
7
+ export declare const decodeBase58: (s: string) => Uint8Array;
8
+ export declare function createLogger(minLevel: LogLevel): (level: LogLevel, msg: string) => void;
6
9
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAgB,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEvC,eAAO,MAAM,GAAG,GAAI,UAAU,MAAM,WAA6C,CAAA;AAEjF,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,WAAiC,CAAA;AAKzE,eAAO,MAAM,YAAY,GAAI,GAAG,MAAM,KAAG,UAmBxC,CAAA;AAID,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,IAGzB,OAAO,QAAQ,EAAE,KAAK,MAAM,UAMjD"}
package/dist/utils.js CHANGED
@@ -3,13 +3,46 @@
3
3
  * utils.ts — shared helpers.
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.decodeBase58 = exports.bpsToPercent = exports.sol = void 0;
7
+ exports.createLogger = createLogger;
8
+ const torchsdk_1 = require("torchsdk");
9
+ const sol = (lamports) => (lamports / torchsdk_1.LAMPORTS_PER_SOL).toFixed(4);
6
10
  exports.sol = sol;
11
+ const bpsToPercent = (bps) => (bps / 100).toFixed(2) + '%';
7
12
  exports.bpsToPercent = bpsToPercent;
8
- const torchsdk_1 = require("torchsdk");
9
- function sol(lamports) {
10
- return (lamports / torchsdk_1.LAMPORTS_PER_SOL).toFixed(4);
11
- }
12
- function bpsToPercent(bps) {
13
- return (bps / 100).toFixed(2) + '%';
13
+ // base58 decoder — avoids ESM-only bs58 dependency
14
+ const B58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
15
+ const decodeBase58 = (s) => {
16
+ const result = [];
17
+ for (let i = 0; i < s.length; i++) {
18
+ let carry = B58.indexOf(s[i]);
19
+ if (carry < 0)
20
+ throw new Error(`invalid base58 character: ${s[i]}`);
21
+ for (let j = 0; j < result.length; j++) {
22
+ carry += result[j] * 58;
23
+ result[j] = carry & 0xff;
24
+ carry >>= 8;
25
+ }
26
+ while (carry > 0) {
27
+ result.push(carry & 0xff);
28
+ carry >>= 8;
29
+ }
30
+ }
31
+ for (let i = 0; i < s.length && s[i] === '1'; i++) {
32
+ result.push(0);
33
+ }
34
+ return new Uint8Array(result.reverse());
35
+ };
36
+ exports.decodeBase58 = decodeBase58;
37
+ const LEVEL_ORDER = ['debug', 'info', 'warn', 'error'];
38
+ function createLogger(minLevel) {
39
+ const minIdx = LEVEL_ORDER.indexOf(minLevel);
40
+ return function log(level, msg) {
41
+ if (LEVEL_ORDER.indexOf(level) < minIdx)
42
+ return;
43
+ const ts = new Date().toISOString().substr(11, 12);
44
+ const tag = level.toUpperCase().padEnd(5);
45
+ console.log(`[${ts}] ${tag} ${msg}`);
46
+ };
14
47
  }
15
48
  //# sourceMappingURL=utils.js.map
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAIH,kBAEC;AAED,oCAEC;AARD,uCAA2C;AAE3C,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"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAmCH,oCASC;AA1CD,uCAA2C;AAGpC,MAAM,GAAG,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC,QAAQ,GAAG,2BAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;AAApE,QAAA,GAAG,OAAiE;AAE1E,MAAM,YAAY,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,CAAA;AAA5D,QAAA,YAAY,gBAAgD;AAEzE,mDAAmD;AACnD,MAAM,GAAG,GAAG,4DAA4D,CAAA;AAEjE,MAAM,YAAY,GAAG,CAAC,CAAS,EAAc,EAAE;IACpD,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,IAAI,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC7B,IAAI,KAAK,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QACnE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAA;YACvB,MAAM,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,CAAA;YACxB,KAAK,KAAK,CAAC,CAAA;QACb,CAAC;QACD,OAAO,KAAK,GAAG,CAAC,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAA;YACzB,KAAK,KAAK,CAAC,CAAA;QACb,CAAC;IACH,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAChB,CAAC;IACD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAA;AACzC,CAAC,CAAA;AAnBY,QAAA,YAAY,gBAmBxB;AAED,MAAM,WAAW,GAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;AAElE,SAAgB,YAAY,CAAC,QAAkB;IAC7C,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAE5C,OAAO,SAAS,GAAG,CAAC,KAAe,EAAE,GAAW;QAC9C,IAAI,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM;YAAE,OAAM;QAC/C,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;QAClD,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACzC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC,CAAA;IACtC,CAAC,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "torch-liquidation-bot",
3
- "version": "2.0.8",
4
- "description": "read-only lending market scanner for Torch Market on Solana",
3
+ "version": "3.0.1",
4
+ "description": "autonomous vault-based liquidation keeper for Torch Market lending on Solana using torchsdk",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "bin": {
@@ -13,12 +13,12 @@
13
13
  "scripts": {
14
14
  "build": "tsc",
15
15
  "clean": "rm -rf dist",
16
- "test": "npx tsx tests/test_readonly.ts",
16
+ "test": "npx tsx tests/test_e2e.ts",
17
17
  "format": "prettier --write src/ tests/"
18
18
  },
19
19
  "dependencies": {
20
20
  "@solana/web3.js": "1.98.4",
21
- "torchsdk": "2.0.0"
21
+ "torchsdk": "3.2.3"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/node": "20.19.33",
@@ -30,7 +30,7 @@
30
30
  },
31
31
  "repository": {
32
32
  "type": "git",
33
- "url": "https://github.com/mrsirg97-rgb/torch-liquidation-bot-ro"
33
+ "url": "https://github.com/mrsirg97-rgb/torch-liquidation-kit"
34
34
  },
35
35
  "license": "MIT",
36
36
  "packageManager": "pnpm@9.10.0+sha512.73a29afa36a0d092ece5271de5177ecbf8318d454ecd701343131b8ebc0c1a91c487da46ab77c8e596d6acf1461e3594ced4becedf8921b074fbd8653ed7051c"
package/readme.md CHANGED
@@ -1,8 +1,8 @@
1
- # torch-liquidation-bot v2.0.7 (Read-Only)
1
+ # torch-liquidation-bot v3.0.1 (Vault Mode)
2
2
 
3
- Read-only lending market scanner for [Torch Market](https://torch.market) on Solana. No wallet required. Only an RPC endpoint is needed.
3
+ Vault-based liquidation bot for [Torch Market](https://torch.market) on Solana. Generates an agent keypair in-process — no user wallet required. All operations route through a Torch Vault.
4
4
 
5
- > **v2.0.0 Breaking Change:** All wallet-dependent code (bot mode, watch mode, transaction signing) was removed. The source tree contains only read-only code. No wallet, no keypair, no signing.
5
+ > **v3.0.0+ Breaking Change:** The bot now operates through the torchsdk v3.2.3+ vault model. It generates a disposable agent keypair at startup, scans for underwater loan positions, and executes liquidations. The user never provides a wallet — only a vault creator pubkey and an RPC endpoint.
6
6
 
7
7
  ## Install
8
8
 
@@ -13,48 +13,101 @@ npm install torch-liquidation-bot
13
13
  ## Quick Start
14
14
 
15
15
  ```bash
16
- # show lending info for all migrated tokens
17
- RPC_URL=<rpc> npx torch-liquidation-bot
16
+ # 1. start the bot it prints its agent wallet on startup
17
+ VAULT_CREATOR=<your-vault-creator-pubkey> SOLANA_RPC_URL=<rpc> npx torch-liquidation-bot
18
18
 
19
- # show lending info for a specific token
20
- MINT=<mint> RPC_URL=<rpc> npx torch-liquidation-bot
19
+ # 2. link the printed agent wallet to your vault (one-time, from your authority wallet)
20
+ # the bot will print the exact instructions if the wallet is not yet linked
21
+
22
+ # 3. restart the bot — it will begin scanning and liquidating
21
23
  ```
22
24
 
23
25
  ## What It Does
24
26
 
25
- Every migrated token on Torch has a built-in lending market. This skill discovers those markets and displays their parameters interest rates, LTV thresholds, treasury balances, and active loan counts.
27
+ Every migrated token on Torch has a built-in lending market. Borrowers lock tokens as collateral and borrow SOL. When a position's LTV exceeds the liquidation threshold, anyone can liquidate it and earn the liquidation bonus.
28
+
29
+ This bot:
26
30
 
27
- That's it. No wallet loaded. No transactions built. No state changes.
31
+ 1. Generates a disposable `Keypair` in-process (no private key leaves the process)
32
+ 2. Verifies the vault exists and the agent wallet is linked
33
+ 3. Scans migrated tokens for active loans
34
+ 4. Checks each borrower's position health via `getLoanPosition()`
35
+ 5. Executes `buildLiquidateTransaction()` for any position with `health === 'liquidatable'`
36
+ 6. Confirms the transaction via `confirmTransaction()`
37
+ 7. Repeats on a configurable interval
38
+
39
+ All value flows through the vault. The agent wallet is a stateless controller.
28
40
 
29
41
  ## Configuration
30
42
 
31
43
  | Variable | Required | Default | Description |
32
44
  |----------|----------|---------|-------------|
33
- | `RPC_URL` | yes | -- | Solana RPC endpoint. If your provider embeds an API key in the URL, use a read-only key or a public endpoint. |
34
- | `MINT` | no | -- | Token mint address (omit to show all tokens) |
45
+ | `SOLANA_RPC_URL` | yes | -- | Solana RPC endpoint (fallback: `RPC_URL`) |
46
+ | `VAULT_CREATOR` | yes | -- | Vault creator pubkey (identifies which vault to use) |
47
+ | `SOLANA_PRIVATE_KEY` | no | -- | Disposable controller keypair (base58 or JSON byte array). If omitted, generates fresh keypair on startup |
48
+ | `SCAN_INTERVAL_MS` | no | `30000` | Milliseconds between scan cycles (min 5000) |
35
49
  | `LOG_LEVEL` | no | `info` | `debug`, `info`, `warn`, `error` |
36
50
 
37
- No `WALLET`, no `MODE`, no bot-specific config.
51
+ ## Vault Setup
52
+
53
+ The bot uses the torchsdk v3.2.3 vault model:
54
+
55
+ ```
56
+ User (hardware wallet) → Creates vault, deposits SOL
57
+ → Links bot's agent wallet
58
+ Bot (disposable) → Scans for liquidatable positions
59
+ → Executes liquidations using vault funds
60
+ → All proceeds return to vault
61
+ User → Withdraws from vault (authority only)
62
+ ```
63
+
64
+ The agent wallet needs minimal SOL for gas (~0.01 SOL). All liquidation value flows through the vault.
38
65
 
39
66
  ## Programmatic Usage
40
67
 
41
68
  ```typescript
42
- import { loadReadOnlyConfig } from 'torch-liquidation-bot/config'
43
- import { Connection } from '@solana/web3.js'
44
- import { getTokens, getLendingInfo } from 'torchsdk'
45
-
46
- const config = loadReadOnlyConfig()
47
- const connection = new Connection(config.rpcUrl, 'confirmed')
48
-
49
- const { tokens } = await getTokens(connection, {
50
- status: 'migrated',
51
- sort: 'volume',
52
- limit: 50,
53
- })
54
-
55
- for (const t of tokens) {
56
- const lending = await getLendingInfo(connection, t.mint)
57
- console.log(`${t.symbol}: ${lending.active_loans} active loans`)
69
+ import { Connection, Keypair } from '@solana/web3.js'
70
+ import {
71
+ getTokens,
72
+ getLendingInfo,
73
+ getHolders,
74
+ getLoanPosition,
75
+ getVault,
76
+ getVaultForWallet,
77
+ buildLiquidateTransaction,
78
+ confirmTransaction,
79
+ } from 'torchsdk'
80
+
81
+ const connection = new Connection('<rpc>', 'confirmed')
82
+ const agent = Keypair.generate()
83
+
84
+ // verify vault and link
85
+ const vaultCreator = '<vault-creator-pubkey>'
86
+ const vault = await getVault(connection, vaultCreator)
87
+ const link = await getVaultForWallet(connection, agent.publicKey.toBase58())
88
+
89
+ // scan and liquidate
90
+ const { tokens } = await getTokens(connection, { status: 'migrated', sort: 'volume', limit: 50 })
91
+
92
+ for (const token of tokens) {
93
+ const lending = await getLendingInfo(connection, token.mint)
94
+ if (!lending.active_loans) continue
95
+
96
+ const { holders } = await getHolders(connection, token.mint)
97
+ for (const holder of holders) {
98
+ const pos = await getLoanPosition(connection, token.mint, holder.address)
99
+ if (pos.health !== 'liquidatable') continue
100
+
101
+ const { transaction } = await buildLiquidateTransaction(connection, {
102
+ mint: token.mint,
103
+ liquidator: agent.publicKey.toBase58(),
104
+ borrower: holder.address,
105
+ vault: vaultCreator,
106
+ })
107
+ transaction.sign(agent)
108
+ const sig = await connection.sendRawTransaction(transaction.serialize())
109
+ await confirmTransaction(connection, sig, agent.publicKey.toBase58())
110
+ }
58
111
  }
59
112
  ```
60
113
 
@@ -62,10 +115,10 @@ for (const t of tokens) {
62
115
 
63
116
  ```
64
117
  src/
65
- ├── types.ts — ReadOnlyConfig interface
66
- ├── config.ts — loadReadOnlyConfig()
67
- ├── utils.ts — sol() + bpsToPercent() helpers
68
- └── index.ts — read-only entry point
118
+ ├── types.ts — BotConfig interface
119
+ ├── config.ts — loadConfig() (SOLANA_RPC_URL, VAULT_CREATOR, SOLANA_PRIVATE_KEY, SCAN_INTERVAL_MS, LOG_LEVEL)
120
+ ├── utils.ts — sol(), bpsToPercent(), createLogger()
121
+ └── index.ts — vault-based liquidation loop
69
122
  ```
70
123
 
71
124
  ## Lending Parameters
@@ -84,23 +137,23 @@ Requires [Surfpool](https://github.com/nicholasgasior/surfpool) running a mainne
84
137
 
85
138
  ```bash
86
139
  surfpool start --network mainnet --no-tui
87
- pnpm test # read-only test
140
+ pnpm test
88
141
  ```
89
142
 
90
143
  ## Security
91
144
 
92
- - No wallet loaded, no keypair decoded, no private key in memory
93
- - No transaction building, no signing, no state changes
94
- - Outbound connections: Solana RPC only
95
- - Minimal dependencies: `@solana/web3.js` + `torchsdk`
145
+ - Agent keypair generated in-process with `Keypair.generate()` (or loaded from optional `SOLANA_PRIVATE_KEY`)
146
+ - Vault model: agent is a stateless controller, all value stays in the vault
147
+ - Authority can unlink the agent wallet instantly via `buildUnlinkWalletTransaction()`
148
+ - Minimal dependencies: `@solana/web3.js` + `torchsdk` -- both pinned to exact versions
96
149
  - No post-install hooks, no remote code fetching
97
- - RPC_URL is used only for read-only RPC calls never logged, transmitted externally, or stored
150
+ - SDK contacts three external services (SAID Protocol, CoinGecko, Irys) -- all read-only, no credentials sent
98
151
 
99
152
  ## Links
100
153
 
101
- - [torchsdk](https://github.com/mrsirg97-rgb/torchsdk) -- the SDK this skill reads from
154
+ - [torchsdk](https://github.com/mrsirg97-rgb/torchsdk) -- the SDK powering this bot
102
155
  - [Torch Market](https://torch.market) -- the protocol
103
- - [ClawHub](https://clawhub.ai/mrsirg97-rgb/torchliquidationbot) -- skill registry
156
+ - [ClawHub](https://clawhub.ai/mrsirg97-rgb/torch-liquidation-bot) -- skill registry
104
157
 
105
158
  ## License
106
159