2022-08-04 08:01:00 -07:00
|
|
|
use clap::{Args, Parser, Subcommand};
|
2023-02-20 05:08:38 -08:00
|
|
|
use mango_v4_client::{
|
2023-08-24 07:45:01 -07:00
|
|
|
keypair_from_cli, pubkey_from_cli, Client, MangoClient, TransactionBuilderConfig,
|
2023-02-20 05:08:38 -08:00
|
|
|
};
|
2022-08-01 08:53:13 -07:00
|
|
|
use solana_sdk::pubkey::Pubkey;
|
2022-08-04 08:01:00 -07:00
|
|
|
use std::str::FromStr;
|
|
|
|
use std::sync::Arc;
|
2022-08-01 08:53:13 -07:00
|
|
|
|
2023-11-08 01:27:55 -08:00
|
|
|
mod save_snapshot;
|
2023-07-05 03:58:42 -07:00
|
|
|
mod test_oracles;
|
|
|
|
|
2022-08-01 08:53:13 -07:00
|
|
|
#[derive(Parser, Debug, Clone)]
|
|
|
|
#[clap()]
|
|
|
|
struct Cli {
|
|
|
|
#[clap(subcommand)]
|
|
|
|
command: Command,
|
|
|
|
}
|
|
|
|
|
2022-08-04 08:01:00 -07:00
|
|
|
#[derive(Args, Debug, Clone)]
|
|
|
|
struct Rpc {
|
|
|
|
#[clap(short, long, default_value = "m")]
|
|
|
|
url: String,
|
|
|
|
|
|
|
|
#[clap(short, long, default_value = "")]
|
|
|
|
fee_payer: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Args, Debug, Clone)]
|
|
|
|
struct CreateAccount {
|
|
|
|
#[clap(short, long)]
|
|
|
|
group: String,
|
|
|
|
|
|
|
|
/// also pays for everything
|
|
|
|
#[clap(short, long)]
|
|
|
|
owner: String,
|
|
|
|
|
|
|
|
#[clap(short, long)]
|
|
|
|
account_num: Option<u32>,
|
|
|
|
|
|
|
|
#[clap(short, long, default_value = "")]
|
|
|
|
name: String,
|
|
|
|
|
|
|
|
#[clap(flatten)]
|
|
|
|
rpc: Rpc,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Args, Debug, Clone)]
|
|
|
|
struct Deposit {
|
|
|
|
#[clap(long)]
|
|
|
|
account: String,
|
|
|
|
|
|
|
|
/// also pays for everything
|
|
|
|
#[clap(short, long)]
|
|
|
|
owner: String,
|
|
|
|
|
|
|
|
#[clap(short, long)]
|
|
|
|
mint: String,
|
|
|
|
|
|
|
|
#[clap(short, long)]
|
|
|
|
amount: u64,
|
|
|
|
|
|
|
|
#[clap(flatten)]
|
|
|
|
rpc: Rpc,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Args, Debug, Clone)]
|
|
|
|
struct JupiterSwap {
|
|
|
|
#[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)]
|
2023-02-03 02:34:06 -08:00
|
|
|
slippage_bps: u64,
|
2022-08-04 08:01:00 -07:00
|
|
|
|
|
|
|
#[clap(flatten)]
|
|
|
|
rpc: Rpc,
|
|
|
|
}
|
|
|
|
|
2022-08-01 08:53:13 -07:00
|
|
|
#[derive(Subcommand, Debug, Clone)]
|
|
|
|
enum Command {
|
2022-08-04 08:01:00 -07:00
|
|
|
CreateAccount(CreateAccount),
|
|
|
|
Deposit(Deposit),
|
|
|
|
JupiterSwap(JupiterSwap),
|
2022-08-01 08:53:13 -07:00
|
|
|
GroupAddress {
|
|
|
|
#[clap(short, long)]
|
|
|
|
creator: String,
|
|
|
|
|
|
|
|
#[clap(short, long, default_value = "0")]
|
|
|
|
num: u32,
|
|
|
|
},
|
|
|
|
MangoAccountAddress {
|
|
|
|
#[clap(short, long)]
|
|
|
|
group: String,
|
|
|
|
|
|
|
|
#[clap(short, long)]
|
|
|
|
owner: String,
|
|
|
|
|
|
|
|
#[clap(short, long, default_value = "0")]
|
2022-08-04 08:01:00 -07:00
|
|
|
num: u32,
|
2022-08-01 08:53:13 -07:00
|
|
|
},
|
2023-07-05 03:58:42 -07:00
|
|
|
/// Regularly fetches all oracles and prints their prices
|
|
|
|
TestOracles {
|
|
|
|
#[clap(short, long)]
|
|
|
|
group: String,
|
|
|
|
|
|
|
|
#[clap(flatten)]
|
|
|
|
rpc: Rpc,
|
|
|
|
},
|
2023-11-08 01:27:55 -08:00
|
|
|
SaveSnapshot {
|
|
|
|
#[clap(short, long)]
|
|
|
|
group: String,
|
|
|
|
|
|
|
|
#[clap(flatten)]
|
|
|
|
rpc: Rpc,
|
|
|
|
|
|
|
|
#[clap(short, long)]
|
|
|
|
output: String,
|
|
|
|
},
|
2022-08-01 08:53:13 -07:00
|
|
|
}
|
2022-08-04 08:01:00 -07:00
|
|
|
|
|
|
|
impl Rpc {
|
2023-02-20 05:08:38 -08:00
|
|
|
fn client(&self, override_fee_payer: Option<&str>) -> anyhow::Result<Client> {
|
|
|
|
let fee_payer = keypair_from_cli(override_fee_payer.unwrap_or(&self.fee_payer));
|
|
|
|
Ok(Client::new(
|
2023-02-20 03:09:17 -08:00
|
|
|
anchor_client::Cluster::from_str(&self.url)?,
|
|
|
|
solana_sdk::commitment_config::CommitmentConfig::confirmed(),
|
|
|
|
Arc::new(fee_payer),
|
|
|
|
None,
|
|
|
|
TransactionBuilderConfig {
|
|
|
|
prioritization_micro_lamports: Some(5),
|
2023-10-19 01:03:07 -07:00
|
|
|
compute_budget_per_instruction: Some(250_000),
|
2023-02-20 03:09:17 -08:00
|
|
|
},
|
|
|
|
))
|
2022-08-04 08:01:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-16 04:10:46 -08:00
|
|
|
#[tokio::main]
|
|
|
|
async fn main() -> Result<(), anyhow::Error> {
|
2023-07-11 23:38:38 -07:00
|
|
|
mango_v4_client::tracing_subscriber_init();
|
2022-08-01 08:53:13 -07:00
|
|
|
|
|
|
|
dotenv::dotenv().ok();
|
|
|
|
let cli = Cli::parse();
|
|
|
|
|
|
|
|
match cli.command {
|
2022-08-04 08:01:00 -07:00
|
|
|
Command::CreateAccount(cmd) => {
|
|
|
|
let client = cmd.rpc.client(Some(&cmd.owner))?;
|
2023-02-20 05:08:38 -08:00
|
|
|
let group = pubkey_from_cli(&cmd.group);
|
2023-07-10 01:40:48 -07:00
|
|
|
let owner = Arc::new(keypair_from_cli(&cmd.owner));
|
2022-08-04 08:01:00 -07:00
|
|
|
|
|
|
|
let account_num = if let Some(num) = cmd.account_num {
|
|
|
|
num
|
|
|
|
} else {
|
|
|
|
// find free account_num
|
2022-12-16 04:10:46 -08:00
|
|
|
let accounts = MangoClient::find_accounts(&client, group, &owner).await?;
|
2022-08-04 08:01:00 -07:00
|
|
|
if accounts.is_empty() {
|
|
|
|
0
|
|
|
|
} else {
|
|
|
|
accounts
|
|
|
|
.iter()
|
|
|
|
.map(|(_, account)| account.fixed.account_num)
|
|
|
|
.max()
|
|
|
|
.unwrap()
|
|
|
|
+ 1
|
|
|
|
}
|
|
|
|
};
|
2023-07-10 01:40:48 -07:00
|
|
|
let (account, txsig) = MangoClient::create_account(
|
|
|
|
&client,
|
|
|
|
group,
|
|
|
|
owner.clone(),
|
|
|
|
owner.clone(),
|
|
|
|
account_num,
|
|
|
|
&cmd.name,
|
|
|
|
)
|
|
|
|
.await?;
|
2022-08-04 08:01:00 -07:00
|
|
|
println!("{}", account);
|
|
|
|
println!("{}", txsig);
|
|
|
|
}
|
|
|
|
Command::Deposit(cmd) => {
|
|
|
|
let client = cmd.rpc.client(Some(&cmd.owner))?;
|
2023-02-20 05:08:38 -08:00
|
|
|
let account = pubkey_from_cli(&cmd.account);
|
|
|
|
let owner = Arc::new(keypair_from_cli(&cmd.owner));
|
|
|
|
let mint = pubkey_from_cli(&cmd.mint);
|
2022-12-16 04:10:46 -08:00
|
|
|
let client = MangoClient::new_for_existing_account(client, account, owner).await?;
|
2023-01-04 00:24:40 -08:00
|
|
|
let txsig = client.token_deposit(mint, cmd.amount, false).await?;
|
2022-08-04 08:01:00 -07:00
|
|
|
println!("{}", txsig);
|
|
|
|
}
|
|
|
|
Command::JupiterSwap(cmd) => {
|
|
|
|
let client = cmd.rpc.client(Some(&cmd.owner))?;
|
2023-02-20 05:08:38 -08:00
|
|
|
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);
|
2022-12-16 04:10:46 -08:00
|
|
|
let client = MangoClient::new_for_existing_account(client, account, owner).await?;
|
|
|
|
let txsig = client
|
2023-09-18 00:21:46 -07:00
|
|
|
.jupiter_v4()
|
|
|
|
.swap(
|
|
|
|
input_mint,
|
|
|
|
output_mint,
|
|
|
|
cmd.amount,
|
|
|
|
cmd.slippage_bps,
|
|
|
|
mango_v4_client::JupiterSwapMode::ExactIn,
|
|
|
|
false,
|
|
|
|
)
|
2022-12-16 04:10:46 -08:00
|
|
|
.await?;
|
2022-08-04 08:01:00 -07:00
|
|
|
println!("{}", txsig);
|
|
|
|
}
|
2022-08-01 08:53:13 -07:00
|
|
|
Command::GroupAddress { creator, num } => {
|
2023-02-20 05:08:38 -08:00
|
|
|
let creator = pubkey_from_cli(&creator);
|
2022-08-01 08:53:13 -07:00
|
|
|
println!("{}", MangoClient::group_for_admin(creator, num));
|
|
|
|
}
|
|
|
|
Command::MangoAccountAddress { group, owner, num } => {
|
2023-02-20 05:08:38 -08:00
|
|
|
let group = pubkey_from_cli(&group);
|
|
|
|
let owner = pubkey_from_cli(&owner);
|
2022-08-01 08:53:13 -07:00
|
|
|
let address = Pubkey::find_program_address(
|
|
|
|
&[
|
|
|
|
group.as_ref(),
|
|
|
|
b"MangoAccount".as_ref(),
|
|
|
|
owner.as_ref(),
|
|
|
|
&num.to_le_bytes(),
|
|
|
|
],
|
|
|
|
&mango_v4::ID,
|
|
|
|
)
|
|
|
|
.0;
|
|
|
|
println!("{}", address);
|
|
|
|
}
|
2023-07-05 03:58:42 -07:00
|
|
|
Command::TestOracles { group, rpc } => {
|
|
|
|
let client = rpc.client(None)?;
|
|
|
|
let group = pubkey_from_cli(&group);
|
|
|
|
test_oracles::run(&client, group).await?;
|
|
|
|
}
|
2023-11-08 01:27:55 -08:00
|
|
|
Command::SaveSnapshot { group, rpc, output } => {
|
|
|
|
let mango_group = pubkey_from_cli(&group);
|
|
|
|
let client = rpc.client(None)?;
|
|
|
|
save_snapshot::save_snapshot(mango_group, client, output).await?
|
|
|
|
}
|
2022-08-01 08:53:13 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|