Skip to content
This repository has been archived by the owner on Oct 14, 2022. It is now read-only.

Commit

Permalink
Merge pull request #29 from solendprotocol/use-new-liquidate-obligati…
Browse files Browse the repository at this point in the history
…on-ix

use the new liquidateObligationAndRedeem instruction
  • Loading branch information
0xCactus authored Mar 17, 2022
2 parents 392a06b + 1cc9698 commit 12e655d
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 322 deletions.
20 changes: 17 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,24 @@ To run liquidator in background:
docker-compose up --build -d
```

To run a specific pool:

## FAQ
1. How to target a specific market?
The liquidator by default checks the health of all markets (aka isolated pools) e.g main, turbo sol, dog, invictus, etc... If you have the necessary assets in your wallet, the liquidator will attempt to liquidate the unhealhty obligation, otherwise, it simply tells you "insufficient fund" and move on to check the next obligation. If you want to target a specific market, you just need to specify the MARKET param in `docker-compose.yaml` with the market address. You may find all the market address for solend in `https://api.solend.fi/v1/config?deployment=production`

2. How to change RPC network
By default we use the public solana rpc which is slow and highly rate limited. We strongly suggest using a custom RPC network e.g rpcpool, figment, etc.. so your bot may be more competitive and win some liquidations. Once you have your rpc url, you may specify it in `config.ts`
```
{
name: 'production',
endpoint: '<YOUR CUSTOM RPC NETWORK URL>',
},
```

3. How to tweak throttling?
If you have a custom rpc network, you would want to disable the default throttling we have set up by specifying the THROTTLE environment variable in `docker-compose.yaml` to 0
```
docker-compose up --build liquidator-main
docker-compose up --build liquidator-turbo-sol
- THROTTLE=0 # Throttle not avoid rate limiting
```

## Support
Expand Down
15 changes: 2 additions & 13 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,8 @@ services:
environment:
- APP=production
- THROTTLE=1900 # Throttle not avoid rate limiting
- MARKET=4UpD2fh7xH3VP9QQaXtsS1YY3bxzWhtfpks7FatyKvdY # Lending market for main pool
secrets:
- keypair # secret to encrypte wallet details in container

liquidator-turbo-sol:
restart: unless-stopped
build:
context: .
dockerfile: Dockerfile
environment:
- APP=production
- THROTTLE=1900 # Throttle not avoid rate limiting
- MARKET=7RCz8wb6WXxUhAigok9ttgrVgDFFFbibcirECzWSBauM # Lending market for TURBO SOL pool
# Uncomment line below and specify lending market if you only want to target a single pool
# - MARKET=4UpD2fh7xH3VP9QQaXtsS1YY3bxzWhtfpks7FatyKvdY
secrets:
- keypair # secret to encrypte wallet details in container

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import {
import { getTokenInfo } from 'libs/utils';
import { findWhere, map } from 'underscore';
import { refreshReserveInstruction } from 'models/instructions/refreshReserve';
import { liquidateObligationInstruction } from 'models/instructions/liquidateObligation';
import { LiquidateObligationAndRedeemReserveCollateral } from 'models/instructions/LiquidateObligationAndRedeemReserveCollateral';
import { refreshObligationInstruction } from 'models/instructions/refreshObligation';
import { Config, Market } from 'global';

export const liquidateObligation = async (
export const liquidateAndRedeem = async (
connection: Connection,
config: Config,
payer: Account,
liquidityAmount: number,
liquidityAmount: number | string,
repayTokenSymbol: string,
withdrawTokenSymbol: string,
lendingMarket: Market,
Expand All @@ -45,6 +45,7 @@ export const liquidateObligation = async (
);
ixs.push(refreshReserveIx);
});

const refreshObligationIx = refreshObligationInstruction(
config,
obligation.pubkey,
Expand All @@ -65,8 +66,8 @@ export const liquidateObligation = async (

const repayReserve = findWhere(lendingMarket.reserves, { asset: repayTokenSymbol });
const withdrawReserve = findWhere(lendingMarket.reserves, { asset: withdrawTokenSymbol });
const withdrawTokenInfo = getTokenInfo(config, withdrawTokenSymbol);

// get account that will be getting the obligation's token account in return
const rewardedWithdrawalCollateralAccount = await Token.getAssociatedTokenAddress(
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
Expand All @@ -88,16 +89,41 @@ export const liquidateObligation = async (
ixs.push(createUserCollateralAccountIx);
}

const rewardedWithdrawalLiquidityAccount = await Token.getAssociatedTokenAddress(
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
new PublicKey(withdrawTokenInfo.mintAddress),
payer.publicKey,
);
const rewardedWithdrawalLiquidityAccountInfo = await connection.getAccountInfo(
rewardedWithdrawalLiquidityAccount,
);
if (!rewardedWithdrawalLiquidityAccountInfo) {
const createUserCollateralAccountIx = Token.createAssociatedTokenAccountInstruction(
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
new PublicKey(withdrawTokenInfo.mintAddress),
rewardedWithdrawalLiquidityAccount,
payer.publicKey,
payer.publicKey,
);
ixs.push(createUserCollateralAccountIx);
}

ixs.push(
liquidateObligationInstruction(
LiquidateObligationAndRedeemReserveCollateral(
config,
liquidityAmount,
repayAccount,
rewardedWithdrawalCollateralAccount,
rewardedWithdrawalLiquidityAccount,
new PublicKey(repayReserve.address),
new PublicKey(repayReserve.liquidityAddress),
new PublicKey(withdrawReserve.address),
new PublicKey(withdrawReserve.collateralMintAddress),
new PublicKey(withdrawReserve.collateralSupplyAddress),
new PublicKey(withdrawReserve.liquidityAddress),
new PublicKey(withdrawReserve.liquidityFeeReceiverAddress),
obligation.pubkey,
new PublicKey(lendingMarket.address),
new PublicKey(lendingMarket.authorityAddress),
Expand All @@ -111,8 +137,6 @@ export const liquidateObligation = async (
tx.feePayer = payer.publicKey;
tx.sign(payer);

const txHash = await connection.sendRawTransaction(tx.serialize());
await connection.confirmTransaction(txHash, 'finalized');
console.log(`liquidated obligation ${obligation.pubkey.toString()} in ${txHash}.
repayToken: ${repayTokenSymbol}. withdrawToken: ${withdrawTokenSymbol}`);
const txHash = await connection.sendRawTransaction(tx.serialize(), { skipPreflight: false });
await connection.confirmTransaction(txHash, 'processed');
};
104 changes: 0 additions & 104 deletions src/libs/actions/redeemCollateral.ts

This file was deleted.

8 changes: 4 additions & 4 deletions src/libs/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,14 @@ function stripEnd(s: string, c: string) {
return s.slice(0, i + 1);
}

export async function getObligations(connection: Connection, config: Config, lendingMarketPubKey) {
export async function getObligations(connection: Connection, config: Config, lendingMarket) {
const resp = await connection.getProgramAccounts(new PublicKey(config.programID), {
commitment: connection.commitment,
filters: [
{
memcmp: {
offset: 10,
bytes: lendingMarketPubKey.toBase58(),
bytes: lendingMarket,
},
},
{
Expand All @@ -123,14 +123,14 @@ export async function getObligations(connection: Connection, config: Config, len
return resp.map((account) => ObligationParser(account.pubkey, account.account));
}

export async function getReserves(connection: Connection, config: Config, lendingMarketPubKey) {
export async function getReserves(connection: Connection, config: Config, lendingMarket) {
const resp = await connection.getProgramAccounts(new PublicKey(config.programID), {
commitment: connection.commitment,
filters: [
{
memcmp: {
offset: 10,
bytes: lendingMarketPubKey.toBase58(),
bytes: lendingMarket,
},
},
{
Expand Down
Loading

0 comments on commit 12e655d

Please sign in to comment.