2022-05-06 05:19:49 -07:00
mod crank ;
2022-05-27 22:05:34 -07:00
mod taker ;
2022-05-06 01:13:33 -07:00
2022-05-06 07:45:04 -07:00
use std ::sync ::Arc ;
2022-08-04 08:01:00 -07:00
use std ::time ::Duration ;
2022-04-09 12:18:07 -07:00
2022-05-27 22:05:34 -07:00
use anchor_client ::Cluster ;
2022-05-06 01:13:33 -07:00
2022-04-13 07:41:15 -07:00
use clap ::{ Parser , Subcommand } ;
2023-02-20 05:08:38 -08:00
use mango_v4_client ::{ keypair_from_cli , Client , MangoClient , TransactionBuilderConfig } ;
2022-08-01 05:19:52 -07:00
use solana_sdk ::commitment_config ::CommitmentConfig ;
2022-07-14 03:57:19 -07:00
use solana_sdk ::pubkey ::Pubkey ;
2022-05-06 07:45:04 -07:00
use tokio ::time ;
2022-04-09 12:18:07 -07:00
2022-04-14 03:42:13 -07:00
// TODO
// - may be nice to have one-shot cranking as well as the interval cranking
// - doing a gPA for all banks call every 10millis may be too often,
// might make sense that we maintain a service when users should query group for changes
// - I'm really annoyed about Keypair not being clonable. Seems everyone works around that manually. Should make a PR to solana to newtype it and provide that function.
// keypair_from_arg_or_env could be a function
2022-07-19 04:43:14 -07:00
#[ derive(Parser, Debug) ]
#[ clap() ]
struct CliDotenv {
// When --dotenv <file> is passed, read the specified dotenv file before parsing args
#[ clap(long) ]
dotenv : std ::path ::PathBuf ,
remaining_args : Vec < std ::ffi ::OsString > ,
}
2022-07-31 00:25:11 -07:00
#[ derive(Parser, Debug, Clone) ]
2022-04-13 07:41:15 -07:00
#[ clap() ]
struct Cli {
2022-07-19 00:59:30 -07:00
#[ clap(short, long, env) ]
rpc_url : String ,
2022-04-13 07:41:15 -07:00
2022-07-19 00:59:30 -07:00
#[ clap(short, long, env) ]
2022-08-01 05:19:52 -07:00
mango_account : Pubkey ,
2022-04-13 07:41:15 -07:00
2022-07-19 00:59:30 -07:00
#[ clap(short, long, env) ]
2022-08-01 05:19:52 -07:00
owner : String ,
2022-05-29 03:25:12 -07:00
2022-04-13 07:41:15 -07:00
#[ clap(subcommand) ]
command : Command ,
2022-11-21 10:35:04 -08:00
#[ clap(long, env, default_value_t = 60) ]
2023-01-23 11:31:10 -08:00
// TODO: use duration type from rust instead of u64 for all these below intervals
2022-11-21 10:35:04 -08:00
interval_update_banks : u64 ,
#[ clap(long, env, default_value_t = 5) ]
interval_consume_events : u64 ,
#[ clap(long, env, default_value_t = 5) ]
interval_update_funding : u64 ,
2023-01-21 02:35:31 -08:00
#[ clap(long, env, default_value_t = 120) ]
interval_check_new_listings_and_abort : u64 ,
2022-11-21 10:35:04 -08:00
#[ clap(long, env, default_value_t = 10) ]
timeout : u64 ,
2023-02-02 05:23:33 -08:00
/// prioritize each transaction with this many microlamports/cu
#[ clap(long, env, default_value = " 0 " ) ]
prioritization_micro_lamports : u64 ,
2022-04-13 07:41:15 -07:00
}
2022-07-31 00:25:11 -07:00
#[ derive(Subcommand, Debug, Clone) ]
2022-04-13 07:41:15 -07:00
enum Command {
Crank { } ,
2022-05-27 22:05:34 -07:00
Taker { } ,
2022-04-13 07:41:15 -07:00
}
2022-12-16 04:10:46 -08:00
#[ tokio::main ]
async fn main ( ) -> Result < ( ) , anyhow ::Error > {
2022-04-13 07:41:15 -07:00
env_logger ::init_from_env (
env_logger ::Env ::default ( ) . filter_or ( env_logger ::DEFAULT_FILTER_ENV , " info " ) ,
) ;
2022-07-19 04:43:14 -07:00
let args = if let Ok ( cli_dotenv ) = CliDotenv ::try_parse ( ) {
dotenv ::from_path ( cli_dotenv . dotenv ) ? ;
cli_dotenv . remaining_args
} else {
dotenv ::dotenv ( ) . ok ( ) ;
std ::env ::args_os ( ) . collect ( )
} ;
let cli = Cli ::parse_from ( args ) ;
2022-04-13 07:41:15 -07:00
2023-02-10 05:22:07 -08:00
let owner = Arc ::new ( keypair_from_cli ( & cli . owner ) ) ;
2022-04-13 07:41:15 -07:00
2022-07-19 00:59:30 -07:00
let rpc_url = cli . rpc_url ;
2022-04-13 07:41:15 -07:00
let ws_url = rpc_url . replace ( " https " , " wss " ) ;
let cluster = Cluster ::Custom ( rpc_url , ws_url ) ;
2022-07-14 03:57:19 -07:00
let commitment = match cli . command {
2022-05-06 01:13:33 -07:00
Command ::Crank { .. } = > CommitmentConfig ::confirmed ( ) ,
2022-05-27 22:05:34 -07:00
Command ::Taker { .. } = > CommitmentConfig ::confirmed ( ) ,
2022-04-13 07:41:15 -07:00
} ;
2022-12-16 04:10:46 -08:00
let mango_client = Arc ::new (
MangoClient ::new_for_existing_account (
Client ::new (
cluster ,
commitment ,
2023-02-10 05:22:07 -08:00
owner . clone ( ) ,
2022-12-16 04:10:46 -08:00
Some ( Duration ::from_secs ( cli . timeout ) ) ,
2023-02-20 05:08:38 -08:00
TransactionBuilderConfig {
2023-02-20 03:09:17 -08:00
prioritization_micro_lamports : ( cli . prioritization_micro_lamports > 0 )
. then_some ( cli . prioritization_micro_lamports ) ,
} ,
2022-12-16 04:10:46 -08:00
) ,
cli . mango_account ,
2023-02-10 05:22:07 -08:00
owner . clone ( ) ,
2022-12-16 04:10:46 -08:00
)
. await ? ,
) ;
2022-04-09 12:18:07 -07:00
2022-05-06 07:45:04 -07:00
let debugging_handle = async {
let mut interval = time ::interval ( time ::Duration ::from_secs ( 5 ) ) ;
loop {
interval . tick ( ) . await ;
let client = mango_client . clone ( ) ;
tokio ::task ::spawn_blocking ( move | | {
log ::info! (
2022-05-27 22:05:34 -07:00
" Arc<MangoClient>::strong_count() {} " ,
2022-05-06 07:45:04 -07:00
Arc ::< MangoClient > ::strong_count ( & client )
)
} ) ;
}
} ;
2022-07-14 03:57:19 -07:00
match cli . command {
2022-05-06 01:13:33 -07:00
Command ::Crank { .. } = > {
2022-05-06 07:45:04 -07:00
let client = mango_client . clone ( ) ;
2022-12-16 04:10:46 -08:00
crank ::runner (
2022-11-21 10:35:04 -08:00
client ,
debugging_handle ,
cli . interval_update_banks ,
cli . interval_consume_events ,
cli . interval_update_funding ,
2023-01-21 02:35:31 -08:00
cli . interval_check_new_listings_and_abort ,
2022-12-16 04:10:46 -08:00
)
. await
2022-04-13 10:47:31 -07:00
}
2022-05-27 22:05:34 -07:00
Command ::Taker { .. } = > {
let client = mango_client . clone ( ) ;
2022-12-16 04:10:46 -08:00
taker ::runner ( client , debugging_handle ) . await
2022-05-06 05:19:49 -07:00
}
2022-04-13 07:41:15 -07:00
}
2022-04-09 12:18:07 -07:00
}