From 1ffd1e344a5ec86ccba716197d78599e6ba62d71 Mon Sep 17 00:00:00 2001 From: galactus <96341601+godmodegalactus@users.noreply.github.com> Date: Sat, 15 Apr 2023 12:17:15 +0200 Subject: [PATCH] =?UTF-8?q?canceling=20all=20transactions=20on=20all=20mar?= =?UTF-8?q?kets=20for=20a=20market=20maker=20before=20e=E2=80=A6=20(#14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * canceling all transactions on all markets for a market maker before each run --------- Co-authored-by: Maximilian Schneider --- src/confirmation_strategies.rs | 11 +++-- src/main.rs | 11 ++++- src/market_markers.rs | 85 ++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 5 deletions(-) diff --git a/src/confirmation_strategies.rs b/src/confirmation_strategies.rs index 29a6f82..36e5532 100644 --- a/src/confirmation_strategies.rs +++ b/src/confirmation_strategies.rs @@ -137,13 +137,14 @@ async fn get_blocks_with_retry( ) -> Result, ()> { const N_TRY_REQUEST_BLOCKS: u64 = 4; for _ in 0..N_TRY_REQUEST_BLOCKS { - let block_slots = client.get_blocks_with_commitment(start_block, None, commitment_confirmation) + let block_slots = client + .get_blocks_with_commitment(start_block, None, commitment_confirmation) .await; match block_slots { Ok(slots) => { return Ok(slots); - }, + } Err(error) => { warn!("Failed to download blocks: {}, retry", error); } @@ -268,7 +269,9 @@ pub fn confirmations_by_blocks( } start_instant = tokio::time::Instant::now(); - let block_slots = get_blocks_with_retry(client.clone(), start_block, commitment_confirmation).await; + let block_slots = + get_blocks_with_retry(client.clone(), start_block, commitment_confirmation) + .await; if block_slots.is_err() { break; } @@ -277,7 +280,7 @@ pub fn confirmations_by_blocks( if block_slots.is_empty() { continue; } - start_block = *block_slots.last().unwrap(); + start_block = *block_slots.last().unwrap() + 1; let blocks = block_slots.iter().map(|slot| { client.get_block_with_config( diff --git a/src/main.rs b/src/main.rs index 88db6c1..6b7488d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ use { }, keeper::start_keepers, mango::{AccountKeys, MangoConfig}, - market_markers::start_market_making_threads, + market_markers::{clean_market_makers, start_market_making_threads}, result_writer::initialize_result_writers, states::PerpMarketCache, stats::MangoSimulationStats, @@ -147,6 +147,15 @@ pub async fn main() -> anyhow::Result<()> { .iter() .map(|x| Pubkey::from_str(x.as_str()).unwrap()) .collect(); + + clean_market_makers( + nb_rpc_client.clone(), + &account_keys_parsed, + &perp_market_caches, + blockhash.clone(), + ) + .await; + // start keeper if keeper authority is present let keepers_jl = if let Some(keeper_authority) = keeper_authority { let jl = start_keepers( diff --git a/src/market_markers.rs b/src/market_markers.rs index 2109682..028ce14 100644 --- a/src/market_markers.rs +++ b/src/market_markers.rs @@ -15,6 +15,7 @@ use mango::{ matching::Side, }; use rand::{distributions::Uniform, prelude::Distribution, seq::SliceRandom}; +use solana_client::nonblocking::rpc_client::RpcClient; use solana_program::pubkey::Pubkey; use solana_sdk::{ compute_budget, hash::Hash, instruction::Instruction, message::Message, signature::Keypair, @@ -269,3 +270,87 @@ pub fn start_market_making_threads( }) .collect() } + +fn create_cancel_all_orders( + perp_market: &PerpMarketCache, + mango_account_pk: Pubkey, + mango_account_signer: &Keypair, +) -> Transaction { + let mango_account_signer_pk = to_sp_pk(&mango_account_signer.pubkey()); + + let cb_instruction = compute_budget::ComputeBudgetInstruction::set_compute_unit_limit(1000000); + let pf_instruction = compute_budget::ComputeBudgetInstruction::set_compute_unit_price(1000); + + let instruction: Instruction = to_sdk_instruction( + cancel_all_perp_orders( + &perp_market.mango_program_pk, + &perp_market.mango_group_pk, + &mango_account_pk, + &mango_account_signer_pk, + &perp_market.perp_market_pk, + &perp_market.bids, + &perp_market.asks, + 255, + ) + .unwrap(), + ); + + Transaction::new_unsigned(Message::new( + &[cb_instruction, pf_instruction, instruction], + Some(&mango_account_signer.pubkey()), + )) +} + +pub async fn clean_market_makers( + rpc_client: Arc, + account_keys_parsed: &Vec, + perp_market_caches: &Vec, + blockhash: Arc>, +) { + info!("Cleaning previous transactions by market makers"); + let mut tasks = vec![]; + + for market_maker in account_keys_parsed { + let mango_account_pk = + Pubkey::from_str(market_maker.mango_account_pks[0].as_str()).unwrap(); + for perp_market in perp_market_caches { + let market_maker = market_maker.clone(); + let perp_market = perp_market.clone(); + let rpc_client = rpc_client.clone(); + let mango_account_pk = mango_account_pk.clone(); + let blockhash = blockhash.clone(); + + let task = tokio::spawn(async move { + let mango_account_signer = + Keypair::from_bytes(market_maker.secret_key.as_slice()).unwrap(); + + for _ in 0..10 { + let mut tx = create_cancel_all_orders( + &perp_market, + mango_account_pk, + &mango_account_signer, + ); + + let recent_blockhash = *blockhash.read().await; + tx.sign(&[&mango_account_signer], recent_blockhash); + // send and confirm the transaction with an RPC + if let Ok(res) = tokio::time::timeout( + Duration::from_secs(10), + rpc_client.send_and_confirm_transaction(&tx), + ) + .await + { + match res { + Ok(_) => break, + Err(e) => info!("Error occured while doing cancel all for ma : {} and perp market : {} error : {}", mango_account_pk, perp_market.perp_market_pk, e), + } + } + } + }); + tasks.push(task); + } + } + + futures::future::join_all(tasks).await; + info!("finished cleaning market makers"); +}