Skip to content

Commit

Permalink
Liquidator: add Sanctum swap (#919)
Browse files Browse the repository at this point in the history
liquidator: add sanctum swap
  • Loading branch information
farnyser authored Apr 10, 2024
1 parent 653cf9f commit 01d5237
Show file tree
Hide file tree
Showing 16 changed files with 1,077 additions and 144 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 39 additions & 0 deletions bin/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,31 @@ struct JupiterSwap {
rpc: Rpc,
}

#[derive(Args, Debug, Clone)]
struct SanctumSwap {
#[clap(long)]
account: String,

/// also pays for everything
#[clap(short, long)]
owner: String,

#[clap(long)]
input_mint: String,

#[clap(long)]
output_mint: String,

#[clap(short, long)]
amount: u64,

#[clap(short, long, default_value = "50")]
max_slippage_bps: u64,

#[clap(flatten)]
rpc: Rpc,
}

#[derive(ArgEnum, Clone, Debug)]
#[repr(u8)]
pub enum CliSide {
Expand Down Expand Up @@ -189,6 +214,7 @@ enum Command {
CreateAccount(CreateAccount),
Deposit(Deposit),
JupiterSwap(JupiterSwap),
SanctumSwap(SanctumSwap),
GroupAddress {
#[clap(short, long)]
creator: String,
Expand Down Expand Up @@ -312,6 +338,19 @@ async fn main() -> Result<(), anyhow::Error> {
.await?;
println!("{}", txsig);
}
Command::SanctumSwap(cmd) => {
let client = cmd.rpc.client(Some(&cmd.owner))?;
let account = pubkey_from_cli(&cmd.account);
let owner = Arc::new(keypair_from_cli(&cmd.owner));
let input_mint = pubkey_from_cli(&cmd.input_mint);
let output_mint = pubkey_from_cli(&cmd.output_mint);
let client = MangoClient::new_for_existing_account(client, account, owner).await?;
let txsig = client
.sanctum()
.swap(input_mint, output_mint, cmd.max_slippage_bps, cmd.amount)
.await?;
println!("{}", txsig);
}
Command::GroupAddress { creator, num } => {
let creator = pubkey_from_cli(&creator);
println!("{}", MangoClient::group_for_admin(creator, num));
Expand Down
4 changes: 3 additions & 1 deletion bin/liquidator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ shellexpand = "2.1.0"
solana-account-decoder = { workspace = true }
solana-client = { workspace = true }
solana-logger = { workspace = true }
solana-address-lookup-table-program = "~1.16.7"
solana-rpc = { workspace = true }
solana-sdk = { workspace = true }
tokio = { version = "1", features = ["full"] }
Expand All @@ -50,4 +51,5 @@ tokio-tungstenite = "0.16.1"
tracing = "0.1"
regex = "1.9.5"
hdrhistogram = "7.5.4"
indexmap = "2.0.0"
indexmap = "2.0.0"
borsh = { version = "0.10.3", features = ["const-generics"] }
26 changes: 22 additions & 4 deletions bin/liquidator/src/cli_args.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::trigger_tcs;
use anchor_lang::prelude::Pubkey;
use clap::Parser;
use mango_v4_client::{jupiter, priority_fees_cli};
use mango_v4_client::{priority_fees_cli, swap};
use std::collections::HashSet;

#[derive(Parser, Debug)]
Expand All @@ -28,11 +28,11 @@ pub(crate) enum JupiterVersionArg {
V6,
}

impl From<JupiterVersionArg> for jupiter::Version {
impl From<JupiterVersionArg> for swap::Version {
fn from(a: JupiterVersionArg) -> Self {
match a {
JupiterVersionArg::Mock => jupiter::Version::Mock,
JupiterVersionArg::V6 => jupiter::Version::V6,
JupiterVersionArg::Mock => swap::Version::Mock,
JupiterVersionArg::V6 => swap::Version::V6,
}
}
}
Expand Down Expand Up @@ -121,6 +121,12 @@ pub struct Cli {
#[clap(long, env, value_parser, value_delimiter = ',')]
pub(crate) rebalance_alternate_jupiter_route_tokens: Option<Vec<u16>>,

/// query sanctum for routes to and from these tokens
///
/// These routes will only be used when trying to rebalance a LST token
#[clap(long, env, value_parser, value_delimiter = ',')]
pub(crate) rebalance_alternate_sanctum_route_tokens: Option<Vec<u16>>,

/// When closing borrows, the rebalancer can't close token positions exactly.
/// Instead it purchases too much and then gets rid of the excess in a second step.
/// If this is 0.05, then it'll swap borrow_value * (1 + 0.05) quote token into borrow token.
Expand Down Expand Up @@ -236,4 +242,16 @@ pub struct Cli {
/// max number of liquidation/tcs to do concurrently
#[clap(long, env, default_value = "5")]
pub(crate) max_parallel_operations: u64,

/// Also use sanctum for rebalancing
#[clap(long, env, value_enum, default_value = "false")]
pub(crate) sanctum_enabled: BoolArg,

/// override the url to sanctum
#[clap(long, env, default_value = "https://api.sanctum.so/v1")]
pub(crate) sanctum_url: String,

/// override the sanctum http request timeout
#[clap(long, env, default_value = "30")]
pub(crate) sanctum_timeout_secs: u64,
}
21 changes: 16 additions & 5 deletions bin/liquidator/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ async fn main() -> anyhow::Result<()> {
.jupiter_timeout(Duration::from_secs(cli.jupiter_timeout_secs))
.jupiter_v6_url(cli.jupiter_v6_url.clone())
.jupiter_token(cli.jupiter_token.clone())
.sanctum_url(cli.sanctum_url.clone())
.sanctum_timeout(Duration::from_secs(cli.sanctum_timeout_secs))
.transaction_builder_config(
TransactionBuilderConfig::builder()
.priority_fee_provider(prio_provider)
Expand Down Expand Up @@ -257,16 +259,26 @@ async fn main() -> anyhow::Result<()> {
.rebalance_alternate_jupiter_route_tokens
.clone()
.unwrap_or_default(),
alternate_sanctum_route_tokens: cli
.rebalance_alternate_sanctum_route_tokens
.clone()
.unwrap_or_default(),
allow_withdraws: signer_is_owner,
use_sanctum: cli.sanctum_enabled == BoolArg::True,
};
rebalance_config.validate(&mango_client.context);

let rebalancer = Arc::new(rebalance::Rebalancer {
let mut rebalancer = rebalance::Rebalancer {
mango_client: mango_client.clone(),
account_fetcher: account_fetcher.clone(),
mango_account_address: cli.liqor_mango_account,
config: rebalance_config,
});
sanctum_supported_mints: HashSet::<Pubkey>::new(),
};

let live_rpc_client = mango_client.client.new_rpc_async();
rebalancer.init(&live_rpc_client).await;
let rebalancer = Arc::new(rebalancer);

let liquidation = Box::new(LiquidationState {
mango_client: mango_client.clone(),
Expand Down Expand Up @@ -407,7 +419,7 @@ async fn main() -> anyhow::Result<()> {
// But need to take care to abort if the above job aborts beforehand.
if cli.rebalance == BoolArg::True {
let rebalance_job =
spawn_rebalance_job(&shared_state, rebalance_trigger_receiver, rebalancer);
spawn_rebalance_job(shared_state.clone(), rebalance_trigger_receiver, rebalancer);
optional_jobs.push(rebalance_job);
}

Expand Down Expand Up @@ -523,14 +535,13 @@ fn spawn_telemetry_job(cli: &Cli, mango_client: Arc<MangoClient>) -> JoinHandle<
}

fn spawn_rebalance_job(
shared_state: &Arc<RwLock<SharedState>>,
shared_state: Arc<RwLock<SharedState>>,
rebalance_trigger_receiver: async_channel::Receiver<()>,
rebalancer: Arc<Rebalancer>,
) -> JoinHandle<()> {
let mut rebalance_interval = tokio::time::interval(Duration::from_secs(30));

tokio::spawn({
let shared_state = shared_state.clone();
async move {
loop {
tokio::select! {
Expand Down
Loading

0 comments on commit 01d5237

Please sign in to comment.