torchliquidationbotAutonomous vault-based liquidation keeper for Torch Market lending on Solana. Scans all migrated tokens for underwater loan positions (LTV > 65%) using the S...
Install via ClawdBot CLI:
clawdbot install mrsirg97-rgb/torchliquidationbotYou're here because you want to run a liquidation keeper on Torch Market -- and you want to do it safely.
Every migrated token on Torch has a built-in lending market. Holders lock tokens as collateral and borrow SOL from the community treasury (up to 50% LTV, 2% weekly interest). When a loan's LTV crosses 65%, it becomes liquidatable. Anyone can liquidate it and collect a 10% bonus on the collateral value.
That's where this bot comes in.
It scans every migrated token's lending market, checks every borrower's loan position, and when it finds one that's underwater -- it liquidates it through your vault. The collateral tokens go to your vault ATA. The SOL cost comes from your vault. The agent wallet that signs the transaction holds nothing.
This is not a read-only scanner. This is a fully operational keeper that generates its own keypair, verifies vault linkage, and executes liquidation transactions autonomously in a continuous loop.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LIQUIDATION LOOP β
β β
β 1. Discover migrated tokens (getTokens) β
β 2. For each token, check lending state (getLendingInfo) β
β 3. Skip tokens with no active loans β
β 4. Get token holders (getHolders) β
β 5. For each holder, check loan position (getLoanPosition)β
β 6. If health === 'liquidatable': β
β β buildLiquidateTransaction(vault=creator) β
β β sign with agent keypair β
β β submit and confirm β
β 7. Sleep SCAN_INTERVAL_MS, repeat β
β β
β All SOL comes from vault. All collateral goes to vault. β
β Agent wallet holds nothing. Vault is the boundary. β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The bot generates a fresh Keypair in-process on every startup. No private key file. No environment variable (unless you want to provide one). The keypair is disposable -- it signs transactions but holds nothing of value.
On first run, the bot checks if this keypair is linked to your vault. If not, it prints the exact SDK call you need to link it:
--- ACTION REQUIRED ---
agent wallet is NOT linked to the vault.
link it by running (from your authority wallet):
buildLinkWalletTransaction(connection, {
authority: "<your-authority-pubkey>",
vault_creator: "<your-vault-creator>",
wallet_to_link: "<agent-pubkey>"
})
then restart the bot.
-----------------------
Link it from your authority wallet (hardware wallet, multisig, whatever you use). The agent never needs the authority's key. The authority never needs the agent's key. They share a vault, not keys.
This is the same Torch Vault from the full Torch Market protocol. It holds all assets -- SOL and tokens. The agent is a disposable controller.
When the bot liquidates a position:
The human principal retains full control:
withdrawVault() β pull SOL at any timewithdrawTokens(mint) β pull collateral tokens at any timeunlinkWallet(agent) β revoke agent access instantlyIf the agent keypair is compromised, the attacker gets dust and vault access that you revoke in one transaction.
npm install torch-liquidation-bot@3.0.2
Or use the bundled source from ClawHub β the Torch SDK is included in lib/torchsdk/ and the bot source is in lib/kit/.
From your authority wallet:
import { Connection } from "@solana/web3.js";
import {
buildCreateVaultTransaction,
buildDepositVaultTransaction,
} from "./lib/torchsdk/index.js";
const connection = new Connection(process.env.SOLANA_RPC_URL);
// Create vault
const { transaction: createTx } = await buildCreateVaultTransaction(connection, {
creator: authorityPubkey,
});
// sign and submit with authority wallet...
// Fund vault with SOL for liquidations
const { transaction: depositTx } = await buildDepositVaultTransaction(connection, {
depositor: authorityPubkey,
vault_creator: authorityPubkey,
amount_sol: 5_000_000_000, // 5 SOL
});
// sign and submit with authority wallet...
VAULT_CREATOR=<your-vault-creator-pubkey> SOLANA_RPC_URL=<rpc-url> npx torch-liquidation-bot
On first run, the bot prints the agent keypair and instructions to link it. Link it from your authority wallet, then restart.
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| SOLANA_RPC_URL | Yes | -- | Solana RPC endpoint (HTTPS). Fallback: RPC_URL |
| VAULT_CREATOR | Yes | -- | Vault creator pubkey |
| SOLANA_PRIVATE_KEY | No | -- | Disposable controller keypair (base58 or JSON byte array). If omitted, generates fresh keypair on startup (recommended) |
| SCAN_INTERVAL_MS | No | 30000 | Milliseconds between scan cycles (min 5000) |
| LOG_LEVEL | No | info | debug, info, warn, error |
packages/bot/src/
βββ index.ts β entry point: keypair generation, vault verification, scan loop
βββ config.ts β loadConfig(): validates SOLANA_RPC_URL, VAULT_CREATOR, SOLANA_PRIVATE_KEY, SCAN_INTERVAL_MS, LOG_LEVEL
βββ types.ts β BotConfig, LogLevel interfaces
βββ utils.ts β sol(), bpsToPercent(), createLogger()
The bot is ~190 lines of TypeScript. It does one thing: find underwater loans and liquidate them through the vault.
| Package | Version | Purpose |
|---------|---------|---------|
| @solana/web3.js | 1.98.4 | Solana RPC, keypair, transaction |
| torchsdk | 3.2.3 | Token queries, lending state, liquidation builder, vault queries |
Two runtime dependencies. Both pinned to exact versions. No ^ or ~ ranges.
The same seven guarantees from the Torch Market vault apply here:
| Property | Guarantee |
|----------|-----------|
| Full custody | Vault holds all SOL and all collateral tokens. Agent wallet holds nothing. |
| Closed loop | Liquidation SOL comes from vault, collateral tokens go to vault. No leakage to agent. |
| Authority separation | Creator (immutable PDA seed) vs Authority (transferable admin) vs Controller (disposable signer). |
| One link per wallet | Agent can only belong to one vault. PDA uniqueness enforces this on-chain. |
| Permissionless deposits | Anyone can top up the vault. Hardware wallet deposits, agent liquidates. |
| Instant revocation | Authority can unlink the agent at any time. One transaction. |
| Authority-only withdrawals | Only the vault authority can withdraw SOL or tokens. The agent cannot extract value. |
| Direction | Flow |
|-----------|------|
| SOL out | Vault β Borrower's treasury debt (covers the loan) |
| Tokens in | Borrower's collateral β Vault ATA (at 10% discount) |
| Net | Vault receives collateral worth 110% of SOL spent |
The bot is profitable by design β every successful liquidation returns more value than it costs. The profit accumulates in the vault. The authority withdraws when ready.
| Parameter | Value |
|-----------|-------|
| Max LTV | 50% |
| Liquidation Threshold | 65% |
| Interest Rate | 2% per epoch (~weekly) |
| Liquidation Bonus | 10% |
| Utilization Cap | 50% of treasury |
| Min Borrow | 0.1 SOL |
Collateral value is calculated from Raydium pool reserves. The 1% Token-2022 transfer fee applies on collateral deposits and withdrawals (~2% round-trip).
A loan becomes liquidatable when its LTV exceeds 65%. This happens when:
The bot checks position.health === 'liquidatable' β the SDK calculates LTV from on-chain Raydium reserves and the loan's accrued debt.
The bot uses a focused subset of the Torch SDK:
| Function | Purpose |
|----------|---------|
| getTokens(connection, { status: 'migrated' }) | Discover all tokens with active lending markets |
| getLendingInfo(connection, mint) | Check if a token has active loans |
| getHolders(connection, mint) | Get token holders (potential borrowers) |
| getLoanPosition(connection, mint, wallet) | Check a holder's loan health |
| getVault(connection, creator) | Verify vault exists on startup |
| getVaultForWallet(connection, wallet) | Verify agent is linked to vault |
| buildLiquidateTransaction(connection, params) | Build the liquidation transaction (vault-routed) |
| confirmTransaction(connection, sig, wallet) | Confirm transaction on-chain via RPC (verifies signer, checks Torch instructions) |
const { transaction, message } = await buildLiquidateTransaction(connection, {
mint: token.mint, // token with the underwater loan
liquidator: agentPubkey, // agent wallet (signer)
borrower: holderAddress, // borrower being liquidated
vault: vaultCreator, // vault creator pubkey (SOL from vault, tokens to vault)
});
=== torch liquidation bot ===
agent wallet: 7xK9...
vault creator: 4yN2...
scan interval: 30000ms
[09:15:32] INFO vault found β authority=8cpW...
[09:15:32] INFO agent wallet linked to vault β starting scan loop
[09:15:32] INFO treasury: 5.0000 SOL
[09:15:33] INFO LIQUIDATABLE | SDKTEST | borrower=3AyZ... | LTV=72.50% > threshold=65.00% | owed=0.5000 SOL
[09:15:34] INFO LIQUIDATED | SDKTEST | borrower=3AyZ... | sig=4vK9... | collateral received at 10% discount
The vault is the security boundary, not the key.
The agent keypair is generated fresh on every startup with Keypair.generate(). It holds ~0.01 SOL for gas fees. If the key is compromised, the attacker gets:
The agent never needs the authority's private key. The authority never needs the agent's private key. They share a vault, not keys.
| Variable | Required | Purpose |
|----------|----------|---------|
| SOLANA_RPC_URL / RPC_URL | Yes | Solana RPC endpoint (HTTPS) |
| VAULT_CREATOR | Yes | Vault creator pubkey β identifies which vault the bot operates through |
| SOLANA_PRIVATE_KEY | No | Optional β if omitted, the bot generates a fresh keypair on startup (recommended) |
The SDK contains functions that make outbound HTTPS requests to external services. The bot's runtime path contacts two of them:
| Service | Purpose | When Called | Bot Uses? |
|---------|---------|------------|-----------|
| CoinGecko (api.coingecko.com) | SOL/USD price for display | Token queries with USD pricing | Yes β via getTokens(), getToken() |
| Irys Gateway (gateway.irys.xyz) | Token metadata fallback (name, symbol, image) | getToken() when on-chain metadata URI points to Irys | Yes β via getTokens() |
| SAID Protocol (api.saidprotocol.com) | Agent identity verification and trust tier lookup | verifySaid() only | No β the bot does not call verifySaid() |
confirmTransaction() does NOT contact SAID. Despite living in the SDK's said.js module, it only calls connection.getParsedTransaction() (Solana RPC) to verify the transaction succeeded on-chain and determine the event type. No data is sent to any external service.
No credentials are sent to CoinGecko or Irys. All requests are read-only GET. If either service is unreachable, the SDK degrades gracefully. No private key material is ever transmitted to any external endpoint.
Requires Surfpool running a mainnet fork:
surfpool start --network mainnet --no-tui
pnpm test
Test result: 7 passed, 1 informational (Surfpool RPC limitation on getTokenLargestAccounts β works on mainnet).
| Test | What It Validates |
|------|-------------------|
| Connection | RPC reachable |
| getTokens | Discovers migrated tokens |
| getLendingInfo | Reads lending state for all tokens |
| getHolders + getLoanPosition | Checks holder positions |
| getToken | Token metadata, price, status |
| getVaultForWallet | Vault link returns null for unlinked wallet |
| In-process keypair | No external key required |
VAULT_NOT_FOUND: No vault exists for this creatorWALLET_NOT_LINKED: Agent wallet is not linked to the vaultNOT_LIQUIDATABLE: Position LTV below liquidation thresholdNO_ACTIVE_LOAN: No open loan for this wallet/tokenINVALID_MINT: Token not foundlib/torchsdk/ -- included in this skill8hbUkonssSEEtkqzwM7ZcZrD9evacM92TcWSooVF4BeTThis bot exists because Torch lending markets need keepers. When loans go underwater and nobody liquidates them, the treasury takes the loss. Active liquidation keepers protect treasury health and earn a profit doing it. The vault makes it safe β all value stays in the escrow, all risk is bounded, and the human principal keeps the keys.
AI Usage Analysis
Analysis is being generated⦠refresh in a few seconds.
Analyze stocks and cryptocurrencies using Yahoo Finance data. Supports portfolio management, watchlists with alerts, dividend analysis, 8-dimension stock scoring, viral trend detection (Hot Scanner), and rumor/early signal detection. Use for stock analysis, portfolio tracking, earnings reactions, crypto monitoring, trending stocks, or finding rumors before they hit mainstream.
Get stock prices, quotes, fundamentals, earnings, options, dividends, and analyst ratings using Yahoo Finance. Uses yfinance library - no API key required.
Yahoo Finance (yfinance) powered stock analysis skill: quotes, fundamentals, ASCII trends, high-resolution charts (RSI/MACD/BB/VWAP/ATR), plus optional web a...
Become an autonomous prediction market trader on Polymarket with AI-powered analysis and a performance-backed token on Base. Trade real markets, build a track record, and let the buyback flywheel run.
Get cryptocurrency token price and generate candlestick charts via CoinGecko API or Hyperliquid API. Use when user asks for token price, crypto price, price chart, or cryptocurrency market data.
Trade and monitor Hyperliquid perpetual futures. Check balances, view positions with P&L, place/cancel orders, execute market trades. Use when the user asks about Hyperliquid trading, portfolio status, crypto positions, or wants to execute trades on Hyperliquid.