Prefer "group" argument to keeper/liquidator
The admin keypair doesn't need to be passed in. It's only convenient for testing.
This commit is contained in:
parent
5231ee7f98
commit
4e87c07a9a
|
@ -2522,6 +2522,7 @@ dependencies = [
|
|||
"mango-v4",
|
||||
"pyth-sdk-solana",
|
||||
"serum_dex",
|
||||
"shellexpand",
|
||||
"solana-client",
|
||||
"solana-sdk",
|
||||
"tokio",
|
||||
|
@ -4506,6 +4507,15 @@ dependencies = [
|
|||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shellexpand"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83bdb7831b2d85ddf4a7b148aa19d0587eddbe8671a436b7bd1182eaad0f2829"
|
||||
dependencies = [
|
||||
"dirs-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.1.0"
|
||||
|
|
|
@ -31,7 +31,6 @@ pub struct MangoClient {
|
|||
pub cluster: Cluster,
|
||||
pub commitment: CommitmentConfig,
|
||||
pub payer: Keypair,
|
||||
pub admin: Keypair,
|
||||
pub mango_account_cache: (Pubkey, MangoAccount),
|
||||
pub group: Pubkey,
|
||||
pub group_cache: Group,
|
||||
|
@ -53,11 +52,19 @@ pub struct MangoClient {
|
|||
// 2/ pubkey, can be both owned, but also delegated accouns
|
||||
|
||||
impl MangoClient {
|
||||
pub fn group_for_admin(admin: Pubkey, num: u32) -> Pubkey {
|
||||
Pubkey::find_program_address(
|
||||
&["Group".as_ref(), admin.as_ref(), num.to_le_bytes().as_ref()],
|
||||
&mango_v4::ID,
|
||||
)
|
||||
.0
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
cluster: Cluster,
|
||||
commitment: CommitmentConfig,
|
||||
payer: Keypair,
|
||||
admin: Keypair,
|
||||
group: Pubkey,
|
||||
mango_account_name: &str,
|
||||
) -> anyhow::Result<Self> {
|
||||
let program =
|
||||
|
@ -66,16 +73,6 @@ impl MangoClient {
|
|||
|
||||
let rpc = program.rpc();
|
||||
|
||||
let group = Pubkey::find_program_address(
|
||||
&[
|
||||
"Group".as_ref(),
|
||||
admin.pubkey().as_ref(),
|
||||
0u32.to_le_bytes().as_ref(),
|
||||
],
|
||||
&program.id(),
|
||||
)
|
||||
.0;
|
||||
|
||||
let group_data = program.account::<Group>(group)?;
|
||||
|
||||
// Mango Account
|
||||
|
@ -237,7 +234,6 @@ impl MangoClient {
|
|||
rpc,
|
||||
cluster,
|
||||
commitment,
|
||||
admin,
|
||||
payer,
|
||||
mango_account_cache,
|
||||
group,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
RPC_URL=https://mango.devnet.rpcpool.com
|
||||
PAYER_KEYPAIR=~/.config/solana/mango-devnet.json
|
||||
ADMIN_KEYPAIR=~/.config/solana/admin.json
|
||||
GROUP_FROM_ADMIN_KEYPAIR=~/.config/solana/admin.json
|
||||
MANGO_ACCOUNT_NAME=Account
|
|
@ -1,4 +1,4 @@
|
|||
RPC_URL=
|
||||
PAYER_KEYPAIR=
|
||||
ADMIN_KEYPAIR=
|
||||
GROUP=
|
||||
MANGO_ACCOUNT_NAME=
|
|
@ -1,4 +1,4 @@
|
|||
RPC_URL=https://mango.rpcpool.com/
|
||||
PAYER_KEYPAIR=~/.config/solana/mango-mainnet.json
|
||||
ADMIN_KEYPAIR=~/.config/solana/mango-mainnet.json
|
||||
GROUP=grouppubkey
|
||||
MANGO_ACCOUNT_NAME=Account
|
|
@ -11,16 +11,17 @@ anchor-lang = "0.24.2"
|
|||
anchor-spl = "0.24.2"
|
||||
anyhow = "1.0"
|
||||
clap = { version = "3.1.8", features = ["derive", "env"] }
|
||||
client = { path = "../client" }
|
||||
client = { path = "../client" }
|
||||
dotenv = "0.15.0"
|
||||
env_logger = "0.8.4"
|
||||
fixed = { version = "=1.11.0", features = ["serde", "borsh"] }
|
||||
fixed-macro = "^1.1.1"
|
||||
futures = "0.3.21"
|
||||
log = "0.4.0"
|
||||
mango-v4 = { path = "../programs/mango-v4" }
|
||||
mango-v4 = { path = "../programs/mango-v4" }
|
||||
pyth-sdk-solana = "0.1.0"
|
||||
serum_dex = { version = "0.4.0", git = "https://github.com/blockworks-foundation/serum-dex.git", default-features=false, features = ["no-entrypoint", "program"] }
|
||||
solana-client = "~1.9.13"
|
||||
solana-sdk = "~1.9.13"
|
||||
tokio = { version = "1.14.1", features = ["rt-multi-thread", "time", "macros", "sync"] }
|
||||
tokio = { version = "1.14.1", features = ["rt-multi-thread", "time", "macros", "sync"] }
|
||||
shellexpand = "2.1.0"
|
|
@ -2,13 +2,19 @@ mod crank;
|
|||
mod taker;
|
||||
|
||||
use std::env;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use anchor_client::Cluster;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use client::MangoClient;
|
||||
use solana_sdk::{commitment_config::CommitmentConfig, signer::keypair};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::{
|
||||
commitment_config::CommitmentConfig,
|
||||
signature::Signer,
|
||||
signer::{keypair, keypair::Keypair},
|
||||
};
|
||||
use tokio::time;
|
||||
|
||||
// TODO
|
||||
|
@ -27,8 +33,14 @@ struct Cli {
|
|||
#[clap(short, long, env = "PAYER_KEYPAIR")]
|
||||
payer: Option<std::path::PathBuf>,
|
||||
|
||||
#[clap(short, long, env = "ADMIN_KEYPAIR")]
|
||||
admin: Option<std::path::PathBuf>,
|
||||
#[clap(short, long, env = "GROUP")]
|
||||
group: Option<Pubkey>,
|
||||
|
||||
// These exist only as a shorthand to make testing easier. Normal users would provide the group.
|
||||
#[clap(long, env = "GROUP_FROM_ADMIN_KEYPAIR")]
|
||||
group_from_admin_keypair: Option<std::path::PathBuf>,
|
||||
#[clap(long, env = "GROUP_FROM_ADMIN_NUM", default_value = "0")]
|
||||
group_from_admin_num: u32,
|
||||
|
||||
#[clap(short, long, env = "MANGO_ACCOUNT_NAME")]
|
||||
mango_account_name: String,
|
||||
|
@ -37,6 +49,12 @@ struct Cli {
|
|||
command: Command,
|
||||
}
|
||||
|
||||
fn keypair_from_path(p: &std::path::PathBuf) -> Keypair {
|
||||
let path = std::path::PathBuf::from_str(&*shellexpand::tilde(p.to_str().unwrap())).unwrap();
|
||||
keypair::read_keypair_file(path)
|
||||
.unwrap_or_else(|_| panic!("Failed to read keypair from {}", p.to_string_lossy()))
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Command {
|
||||
Crank {},
|
||||
|
@ -49,27 +67,14 @@ fn main() -> Result<(), anyhow::Error> {
|
|||
|
||||
dotenv::dotenv().ok();
|
||||
|
||||
let Cli {
|
||||
rpc_url,
|
||||
payer,
|
||||
admin,
|
||||
command,
|
||||
mango_account_name,
|
||||
} = Cli::parse();
|
||||
let cli = Cli::parse();
|
||||
|
||||
let payer = match payer {
|
||||
Some(p) => keypair::read_keypair_file(&p)
|
||||
.unwrap_or_else(|_| panic!("Failed to read keypair from {}", p.to_string_lossy())),
|
||||
let payer = match cli.payer {
|
||||
Some(p) => keypair_from_path(&p),
|
||||
None => panic!("Payer keypair not provided..."),
|
||||
};
|
||||
|
||||
let admin = match admin {
|
||||
Some(p) => keypair::read_keypair_file(&p)
|
||||
.unwrap_or_else(|_| panic!("Failed to read keypair from {}", p.to_string_lossy())),
|
||||
None => panic!("Admin keypair not provided..."),
|
||||
};
|
||||
|
||||
let rpc_url = match rpc_url {
|
||||
let rpc_url = match cli.rpc_url {
|
||||
Some(rpc_url) => rpc_url,
|
||||
None => match env::var("RPC_URL").ok() {
|
||||
Some(rpc_url) => rpc_url,
|
||||
|
@ -79,17 +84,26 @@ fn main() -> Result<(), anyhow::Error> {
|
|||
let ws_url = rpc_url.replace("https", "wss");
|
||||
|
||||
let cluster = Cluster::Custom(rpc_url, ws_url);
|
||||
let commitment = match command {
|
||||
let commitment = match cli.command {
|
||||
Command::Crank { .. } => CommitmentConfig::confirmed(),
|
||||
Command::Taker { .. } => CommitmentConfig::confirmed(),
|
||||
};
|
||||
|
||||
let group = if let Some(group) = cli.group {
|
||||
group
|
||||
} else if let Some(p) = cli.group_from_admin_keypair {
|
||||
let admin = keypair_from_path(&p);
|
||||
MangoClient::group_for_admin(admin.pubkey(), cli.group_from_admin_num)
|
||||
} else {
|
||||
panic!("Must provide either group or group_from_admin_keypair");
|
||||
};
|
||||
|
||||
let mango_client = Arc::new(MangoClient::new(
|
||||
cluster,
|
||||
commitment,
|
||||
payer,
|
||||
admin,
|
||||
&mango_account_name,
|
||||
group,
|
||||
&cli.mango_account_name,
|
||||
)?);
|
||||
|
||||
let rt = tokio::runtime::Builder::new_multi_thread()
|
||||
|
@ -111,7 +125,7 @@ fn main() -> Result<(), anyhow::Error> {
|
|||
}
|
||||
};
|
||||
|
||||
match command {
|
||||
match cli.command {
|
||||
Command::Crank { .. } => {
|
||||
let client = mango_client.clone();
|
||||
rt.block_on(crank::runner(client, debugging_handle))
|
||||
|
|
|
@ -9,5 +9,4 @@ snapshot_interval_secs = 240
|
|||
parallel_rpc_requests = 10
|
||||
get_multiple_accounts_count = 100
|
||||
payer = "/root/.config/solana/mango-devnet.json"
|
||||
admin = "/root/.config/solana/admin.json"
|
||||
mango_account_name = "Taker"
|
||||
|
|
|
@ -27,5 +27,4 @@ get_multiple_accounts_count = 100
|
|||
# FUTURE: separate into a separate conf file? we are mixing feed + mango client conf in one place here
|
||||
# mango client specific
|
||||
payer = "/root/.config/solana/id.json"
|
||||
admin = "/root/.config/solana/admin.json"
|
||||
mango_account_name = "Taker"
|
||||
|
|
|
@ -66,7 +66,6 @@ pub struct Config {
|
|||
// FUTURE: split mango client and feed config
|
||||
// mango client specific
|
||||
pub payer: String,
|
||||
pub admin: String,
|
||||
pub mango_account_name: String,
|
||||
}
|
||||
|
||||
|
@ -89,12 +88,13 @@ async fn main() -> anyhow::Result<()> {
|
|||
toml::from_str(&contents).unwrap()
|
||||
};
|
||||
|
||||
let mango_group_id = Pubkey::from_str(&config.mango_group_id)?;
|
||||
|
||||
//
|
||||
// mango client setup
|
||||
//
|
||||
let mango_client = {
|
||||
let payer = keypair::read_keypair_file(&config.payer).unwrap();
|
||||
let admin = keypair::read_keypair_file(&config.admin).unwrap();
|
||||
|
||||
let rpc_url = config.rpc_http_url.to_owned();
|
||||
let ws_url = rpc_url.replace("https", "wss");
|
||||
|
@ -106,7 +106,7 @@ async fn main() -> anyhow::Result<()> {
|
|||
cluster,
|
||||
commitment,
|
||||
payer,
|
||||
admin,
|
||||
mango_group_id,
|
||||
&config.mango_account_name,
|
||||
)?)
|
||||
};
|
||||
|
@ -123,7 +123,6 @@ async fn main() -> anyhow::Result<()> {
|
|||
// FUTURE: decouple feed setup and liquidator business logic
|
||||
// feed should send updates to a channel which liquidator can consume
|
||||
let mango_program_id = Pubkey::from_str(&config.mango_program_id)?;
|
||||
let mango_group_id = Pubkey::from_str(&config.mango_group_id)?;
|
||||
|
||||
solana_logger::setup_with_default("info");
|
||||
info!("startup");
|
||||
|
|
Loading…
Reference in New Issue