Expose instruction builders for Openbook (#601)
This commit is contained in:
parent
eb662f34fc
commit
c956f153b0
|
@ -138,7 +138,7 @@ pub async fn loop_blocking_price_update(
|
|||
log::info!("{} Updated price is {:?}", token_name, fresh_price.price);
|
||||
if let Ok(mut price) = price.write() {
|
||||
*price = I80F48::from_num(fresh_price.price)
|
||||
/ I80F48::from_num(10u64.pow(-fresh_price.expo as u32));
|
||||
/ I80F48::from_num(10f64.powi(-fresh_price.expo));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -157,6 +157,18 @@ pub async fn loop_blocking_orders(
|
|||
.unwrap();
|
||||
log::info!("Cancelled orders - {:?} for {}", orders, market_name);
|
||||
|
||||
let market_index = mango_client.context.serum3_market_index(&market_name);
|
||||
let s3 = mango_client.context.serum3(market_index);
|
||||
|
||||
let base_decimals = mango_client
|
||||
.context
|
||||
.token(s3.market.base_token_index)
|
||||
.decimals as i32;
|
||||
let quote_decimals = mango_client
|
||||
.context
|
||||
.token(s3.market.quote_token_index)
|
||||
.decimals as i32;
|
||||
|
||||
loop {
|
||||
interval.tick().await;
|
||||
|
||||
|
@ -164,25 +176,23 @@ pub async fn loop_blocking_orders(
|
|||
let market_name = market_name.clone();
|
||||
let price = price.clone();
|
||||
|
||||
let res = (|| async move {
|
||||
let res: anyhow::Result<()> = (|| async move {
|
||||
client.serum3_settle_funds(&market_name).await?;
|
||||
|
||||
let fresh_price = match price.read() {
|
||||
Ok(price) => *price,
|
||||
Err(_) => {
|
||||
anyhow::bail!("Price RwLock PoisonError!");
|
||||
}
|
||||
};
|
||||
let fresh_price = price.read().unwrap().to_num::<f64>();
|
||||
let bid_price = fresh_price * 1.1;
|
||||
|
||||
let fresh_price = fresh_price.to_num::<f64>();
|
||||
let bid_price_lots =
|
||||
bid_price * 10f64.powi(quote_decimals - base_decimals) * s3.coin_lot_size as f64
|
||||
/ s3.pc_lot_size as f64;
|
||||
|
||||
let bid_price = fresh_price + fresh_price * 0.1;
|
||||
let res = client
|
||||
.serum3_place_order(
|
||||
&market_name,
|
||||
Serum3Side::Bid,
|
||||
bid_price,
|
||||
0.0001,
|
||||
bid_price_lots.round() as u64,
|
||||
1,
|
||||
u64::MAX,
|
||||
Serum3SelfTradeBehavior::DecrementTake,
|
||||
Serum3OrderType::ImmediateOrCancel,
|
||||
SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis() as u64,
|
||||
|
@ -195,13 +205,18 @@ pub async fn loop_blocking_orders(
|
|||
log::info!("Placed bid at {} for {}", bid_price, market_name)
|
||||
}
|
||||
|
||||
let ask_price = fresh_price - fresh_price * 0.1;
|
||||
let ask_price = fresh_price * 0.9;
|
||||
let ask_price_lots =
|
||||
ask_price * 10f64.powi(quote_decimals - base_decimals) * s3.coin_lot_size as f64
|
||||
/ s3.pc_lot_size as f64;
|
||||
|
||||
let res = client
|
||||
.serum3_place_order(
|
||||
&market_name,
|
||||
Serum3Side::Ask,
|
||||
ask_price,
|
||||
0.0001,
|
||||
ask_price_lots.round() as u64,
|
||||
1,
|
||||
u64::MAX,
|
||||
Serum3SelfTradeBehavior::DecrementTake,
|
||||
Serum3OrderType::ImmediateOrCancel,
|
||||
SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis() as u64,
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::str::FromStr;
|
|||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use anchor_client::{ClientError, Cluster};
|
||||
use anchor_client::Cluster;
|
||||
|
||||
use anchor_lang::__private::bytemuck;
|
||||
use anchor_lang::prelude::System;
|
||||
|
@ -31,7 +31,7 @@ use solana_sdk::signer::keypair;
|
|||
use solana_sdk::transaction::TransactionError;
|
||||
|
||||
use crate::account_fetcher::*;
|
||||
use crate::context::{MangoGroupContext, Serum3MarketContext, TokenContext};
|
||||
use crate::context::MangoGroupContext;
|
||||
use crate::gpa::{fetch_anchor_account, fetch_mango_accounts};
|
||||
use crate::jupiter;
|
||||
|
||||
|
@ -429,36 +429,32 @@ impl MangoClient {
|
|||
// Serum3
|
||||
//
|
||||
|
||||
pub async fn serum3_create_open_orders(&self, name: &str) -> anyhow::Result<Signature> {
|
||||
pub fn serum3_create_open_orders_instruction(
|
||||
&self,
|
||||
market_index: Serum3MarketIndex,
|
||||
) -> Instruction {
|
||||
let account_pubkey = self.mango_account_address;
|
||||
|
||||
let market_index = *self
|
||||
.context
|
||||
.serum3_market_indexes_by_name
|
||||
.get(name)
|
||||
.unwrap();
|
||||
let serum3_info = self.context.serum3_markets.get(&market_index).unwrap();
|
||||
let s3 = self.context.serum3(market_index);
|
||||
|
||||
let open_orders = Pubkey::find_program_address(
|
||||
&[
|
||||
account_pubkey.as_ref(),
|
||||
b"Serum3OO".as_ref(),
|
||||
serum3_info.address.as_ref(),
|
||||
account_pubkey.as_ref(),
|
||||
s3.address.as_ref(),
|
||||
],
|
||||
&mango_v4::ID,
|
||||
)
|
||||
.0;
|
||||
|
||||
let ix = Instruction {
|
||||
Instruction {
|
||||
program_id: mango_v4::id(),
|
||||
accounts: anchor_lang::ToAccountMetas::to_account_metas(
|
||||
&mango_v4::accounts::Serum3CreateOpenOrders {
|
||||
group: self.group(),
|
||||
account: account_pubkey,
|
||||
|
||||
serum_market: serum3_info.address,
|
||||
serum_program: serum3_info.market.serum_program,
|
||||
serum_market_external: serum3_info.market.serum_market_external,
|
||||
serum_market: s3.address,
|
||||
serum_program: s3.market.serum_program,
|
||||
serum_market_external: s3.market.serum_market_external,
|
||||
open_orders,
|
||||
owner: self.owner(),
|
||||
payer: self.owner(),
|
||||
|
@ -470,116 +466,47 @@ impl MangoClient {
|
|||
data: anchor_lang::InstructionData::data(
|
||||
&mango_v4::instruction::Serum3CreateOpenOrders {},
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn serum3_create_open_orders(&self, name: &str) -> anyhow::Result<Signature> {
|
||||
let market_index = self.context.serum3_market_index(name);
|
||||
let ix = self.serum3_create_open_orders_instruction(market_index);
|
||||
self.send_and_confirm_owner_tx(vec![ix]).await
|
||||
}
|
||||
|
||||
fn serum3_data_by_market_name<'a>(&'a self, name: &str) -> Result<Serum3Data<'a>, ClientError> {
|
||||
let market_index = *self
|
||||
.context
|
||||
.serum3_market_indexes_by_name
|
||||
.get(name)
|
||||
.unwrap();
|
||||
self.serum3_data_by_market_index(market_index)
|
||||
}
|
||||
|
||||
fn serum3_data_by_market_index<'a>(
|
||||
&'a self,
|
||||
market_index: Serum3MarketIndex,
|
||||
) -> Result<Serum3Data<'a>, ClientError> {
|
||||
let serum3_info = self.context.serum3_markets.get(&market_index).unwrap();
|
||||
|
||||
let quote_info = self.context.token(serum3_info.market.quote_token_index);
|
||||
let base_info = self.context.token(serum3_info.market.base_token_index);
|
||||
|
||||
Ok(Serum3Data {
|
||||
market_index,
|
||||
market: serum3_info,
|
||||
quote: quote_info,
|
||||
base: base_info,
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn serum3_place_order(
|
||||
pub fn serum3_place_order_instruction(
|
||||
&self,
|
||||
name: &str,
|
||||
account: &MangoAccountValue,
|
||||
market_index: Serum3MarketIndex,
|
||||
side: Serum3Side,
|
||||
price: f64,
|
||||
size: f64,
|
||||
limit_price: u64,
|
||||
max_base_qty: u64,
|
||||
max_native_quote_qty_including_fees: u64,
|
||||
self_trade_behavior: Serum3SelfTradeBehavior,
|
||||
order_type: Serum3OrderType,
|
||||
client_order_id: u64,
|
||||
limit: u16,
|
||||
) -> anyhow::Result<Signature> {
|
||||
let s3 = self.serum3_data_by_market_name(name)?;
|
||||
) -> anyhow::Result<Instruction> {
|
||||
let s3 = self.context.serum3(market_index);
|
||||
let base = self.context.serum3_base_token(market_index);
|
||||
let quote = self.context.serum3_quote_token(market_index);
|
||||
let open_orders = account
|
||||
.serum3_orders(market_index)
|
||||
.expect("oo is created")
|
||||
.open_orders;
|
||||
|
||||
let account = self.mango_account().await?;
|
||||
let open_orders = account.serum3_orders(s3.market_index).unwrap().open_orders;
|
||||
let health_check_metas = self.context.derive_health_check_remaining_account_metas(
|
||||
account,
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
)?;
|
||||
|
||||
let health_check_metas = self
|
||||
.derive_health_check_remaining_account_metas(vec![], vec![], vec![])
|
||||
.await?;
|
||||
|
||||
// https://github.com/project-serum/serum-ts/blob/master/packages/serum/src/market.ts#L1306
|
||||
let limit_price = {
|
||||
(price * ((10u64.pow(s3.quote.decimals as u32) * s3.market.coin_lot_size) as f64))
|
||||
as u64
|
||||
/ (10u64.pow(s3.base.decimals as u32) * s3.market.pc_lot_size)
|
||||
};
|
||||
// https://github.com/project-serum/serum-ts/blob/master/packages/serum/src/market.ts#L1333
|
||||
let max_base_qty =
|
||||
{ (size * 10u64.pow(s3.base.decimals as u32) as f64) as u64 / s3.market.coin_lot_size };
|
||||
let max_native_quote_qty_including_fees = {
|
||||
fn get_fee_tier(msrm_balance: u64, srm_balance: u64) -> u64 {
|
||||
if msrm_balance >= 1 {
|
||||
6
|
||||
} else if srm_balance >= 1_000_000 {
|
||||
5
|
||||
} else if srm_balance >= 100_000 {
|
||||
4
|
||||
} else if srm_balance >= 10_000 {
|
||||
3
|
||||
} else if srm_balance >= 1_000 {
|
||||
2
|
||||
} else if srm_balance >= 100 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn get_fee_rates(fee_tier: u64) -> (f64, f64) {
|
||||
if fee_tier == 1 {
|
||||
// SRM2
|
||||
return (0.002, -0.0003);
|
||||
} else if fee_tier == 2 {
|
||||
// SRM3
|
||||
return (0.0018, -0.0003);
|
||||
} else if fee_tier == 3 {
|
||||
// SRM4
|
||||
return (0.0016, -0.0003);
|
||||
} else if fee_tier == 4 {
|
||||
// SRM5
|
||||
return (0.0014, -0.0003);
|
||||
} else if fee_tier == 5 {
|
||||
// SRM6
|
||||
return (0.0012, -0.0003);
|
||||
} else if fee_tier == 6 {
|
||||
// MSRM
|
||||
return (0.001, -0.0005);
|
||||
}
|
||||
// Base
|
||||
(0.0022, -0.0003)
|
||||
}
|
||||
|
||||
let fee_tier = get_fee_tier(0, 0);
|
||||
let rates = get_fee_rates(fee_tier);
|
||||
(s3.market.pc_lot_size as f64 * (1f64 + rates.0)) as u64 * (limit_price * max_base_qty)
|
||||
};
|
||||
let payer_mint_info = match side {
|
||||
Serum3Side::Bid => s3.quote.mint_info,
|
||||
Serum3Side::Ask => s3.base.mint_info,
|
||||
Serum3Side::Bid => quote.mint_info,
|
||||
Serum3Side::Ask => base.mint_info,
|
||||
};
|
||||
|
||||
let ix = Instruction {
|
||||
|
@ -593,16 +520,16 @@ impl MangoClient {
|
|||
payer_bank: payer_mint_info.first_bank(),
|
||||
payer_vault: payer_mint_info.first_vault(),
|
||||
payer_oracle: payer_mint_info.oracle,
|
||||
serum_market: s3.market.address,
|
||||
serum_program: s3.market.market.serum_program,
|
||||
serum_market_external: s3.market.market.serum_market_external,
|
||||
market_bids: s3.market.bids,
|
||||
market_asks: s3.market.asks,
|
||||
market_event_queue: s3.market.event_q,
|
||||
market_request_queue: s3.market.req_q,
|
||||
market_base_vault: s3.market.coin_vault,
|
||||
market_quote_vault: s3.market.pc_vault,
|
||||
market_vault_signer: s3.market.vault_signer,
|
||||
serum_market: s3.address,
|
||||
serum_program: s3.market.serum_program,
|
||||
serum_market_external: s3.market.serum_market_external,
|
||||
market_bids: s3.bids,
|
||||
market_asks: s3.asks,
|
||||
market_event_queue: s3.event_q,
|
||||
market_request_queue: s3.req_q,
|
||||
market_base_vault: s3.coin_vault,
|
||||
market_quote_vault: s3.pc_vault,
|
||||
market_vault_signer: s3.vault_signer,
|
||||
owner: self.owner(),
|
||||
token_program: Token::id(),
|
||||
},
|
||||
|
@ -622,14 +549,48 @@ impl MangoClient {
|
|||
limit,
|
||||
}),
|
||||
};
|
||||
|
||||
Ok(ix)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn serum3_place_order(
|
||||
&self,
|
||||
name: &str,
|
||||
side: Serum3Side,
|
||||
limit_price: u64,
|
||||
max_base_qty: u64,
|
||||
max_native_quote_qty_including_fees: u64,
|
||||
self_trade_behavior: Serum3SelfTradeBehavior,
|
||||
order_type: Serum3OrderType,
|
||||
client_order_id: u64,
|
||||
limit: u16,
|
||||
) -> anyhow::Result<Signature> {
|
||||
let account = self.mango_account().await?;
|
||||
let market_index = self.context.serum3_market_index(name);
|
||||
let ix = self.serum3_place_order_instruction(
|
||||
&account,
|
||||
market_index,
|
||||
side,
|
||||
limit_price,
|
||||
max_base_qty,
|
||||
max_native_quote_qty_including_fees,
|
||||
self_trade_behavior,
|
||||
order_type,
|
||||
client_order_id,
|
||||
limit,
|
||||
)?;
|
||||
self.send_and_confirm_owner_tx(vec![ix]).await
|
||||
}
|
||||
|
||||
pub async fn serum3_settle_funds(&self, name: &str) -> anyhow::Result<Signature> {
|
||||
let s3 = self.serum3_data_by_market_name(name)?;
|
||||
let market_index = self.context.serum3_market_index(name);
|
||||
let s3 = self.context.serum3(market_index);
|
||||
let base = self.context.serum3_base_token(market_index);
|
||||
let quote = self.context.serum3_quote_token(market_index);
|
||||
|
||||
let account = self.mango_account().await?;
|
||||
let open_orders = account.serum3_orders(s3.market_index).unwrap().open_orders;
|
||||
let open_orders = account.serum3_orders(market_index).unwrap().open_orders;
|
||||
|
||||
let ix = Instruction {
|
||||
program_id: mango_v4::id(),
|
||||
|
@ -638,16 +599,16 @@ impl MangoClient {
|
|||
group: self.group(),
|
||||
account: self.mango_account_address,
|
||||
open_orders,
|
||||
quote_bank: s3.quote.mint_info.first_bank(),
|
||||
quote_vault: s3.quote.mint_info.first_vault(),
|
||||
base_bank: s3.base.mint_info.first_bank(),
|
||||
base_vault: s3.base.mint_info.first_vault(),
|
||||
serum_market: s3.market.address,
|
||||
serum_program: s3.market.market.serum_program,
|
||||
serum_market_external: s3.market.market.serum_market_external,
|
||||
market_base_vault: s3.market.coin_vault,
|
||||
market_quote_vault: s3.market.pc_vault,
|
||||
market_vault_signer: s3.market.vault_signer,
|
||||
quote_bank: quote.mint_info.first_bank(),
|
||||
quote_vault: quote.mint_info.first_vault(),
|
||||
base_bank: base.mint_info.first_bank(),
|
||||
base_vault: base.mint_info.first_vault(),
|
||||
serum_market: s3.address,
|
||||
serum_program: s3.market.serum_program,
|
||||
serum_market_external: s3.market.serum_market_external,
|
||||
market_base_vault: s3.coin_vault,
|
||||
market_quote_vault: s3.pc_vault,
|
||||
market_vault_signer: s3.vault_signer,
|
||||
owner: self.owner(),
|
||||
token_program: Token::id(),
|
||||
},
|
||||
|
@ -658,15 +619,45 @@ impl MangoClient {
|
|||
self.send_and_confirm_owner_tx(vec![ix]).await
|
||||
}
|
||||
|
||||
pub fn serum3_cancel_all_orders_instruction(
|
||||
&self,
|
||||
account: &MangoAccountValue,
|
||||
market_index: Serum3MarketIndex,
|
||||
limit: u8,
|
||||
) -> anyhow::Result<Instruction> {
|
||||
let s3 = self.context.serum3(market_index);
|
||||
let open_orders = account.serum3_orders(market_index)?.open_orders;
|
||||
|
||||
let ix = Instruction {
|
||||
program_id: mango_v4::id(),
|
||||
accounts: anchor_lang::ToAccountMetas::to_account_metas(
|
||||
&mango_v4::accounts::Serum3CancelAllOrders {
|
||||
group: self.group(),
|
||||
account: self.mango_account_address,
|
||||
open_orders,
|
||||
market_bids: s3.bids,
|
||||
market_asks: s3.asks,
|
||||
market_event_queue: s3.event_q,
|
||||
serum_market: s3.address,
|
||||
serum_program: s3.market.serum_program,
|
||||
serum_market_external: s3.market.serum_market_external,
|
||||
owner: self.owner(),
|
||||
},
|
||||
None,
|
||||
),
|
||||
data: anchor_lang::InstructionData::data(
|
||||
&mango_v4::instruction::Serum3CancelAllOrders { limit },
|
||||
),
|
||||
};
|
||||
|
||||
Ok(ix)
|
||||
}
|
||||
|
||||
pub async fn serum3_cancel_all_orders(
|
||||
&self,
|
||||
market_name: &str,
|
||||
) -> Result<Vec<u128>, anyhow::Error> {
|
||||
let market_index = *self
|
||||
.context
|
||||
.serum3_market_indexes_by_name
|
||||
.get(market_name)
|
||||
.unwrap();
|
||||
let market_index = self.context.serum3_market_index(market_name);
|
||||
let account = self.mango_account().await?;
|
||||
let open_orders = account.serum3_orders(market_index).unwrap().open_orders;
|
||||
let open_orders_acc = self.account_fetcher.fetch_raw_account(&open_orders).await?;
|
||||
|
@ -699,7 +690,9 @@ impl MangoClient {
|
|||
market_index: Serum3MarketIndex,
|
||||
open_orders: &Pubkey,
|
||||
) -> anyhow::Result<Signature> {
|
||||
let s3 = self.serum3_data_by_market_index(market_index)?;
|
||||
let s3 = self.context.serum3(market_index);
|
||||
let base = self.context.serum3_base_token(market_index);
|
||||
let quote = self.context.serum3_quote_token(market_index);
|
||||
|
||||
let health_remaining_ams = self
|
||||
.context
|
||||
|
@ -714,19 +707,19 @@ impl MangoClient {
|
|||
group: self.group(),
|
||||
account: *liqee.0,
|
||||
open_orders: *open_orders,
|
||||
serum_market: s3.market.address,
|
||||
serum_program: s3.market.market.serum_program,
|
||||
serum_market_external: s3.market.market.serum_market_external,
|
||||
market_bids: s3.market.bids,
|
||||
market_asks: s3.market.asks,
|
||||
market_event_queue: s3.market.event_q,
|
||||
market_base_vault: s3.market.coin_vault,
|
||||
market_quote_vault: s3.market.pc_vault,
|
||||
market_vault_signer: s3.market.vault_signer,
|
||||
quote_bank: s3.quote.mint_info.first_bank(),
|
||||
quote_vault: s3.quote.mint_info.first_vault(),
|
||||
base_bank: s3.base.mint_info.first_bank(),
|
||||
base_vault: s3.base.mint_info.first_vault(),
|
||||
serum_market: s3.address,
|
||||
serum_program: s3.market.serum_program,
|
||||
serum_market_external: s3.market.serum_market_external,
|
||||
market_bids: s3.bids,
|
||||
market_asks: s3.asks,
|
||||
market_event_queue: s3.event_q,
|
||||
market_base_vault: s3.coin_vault,
|
||||
market_quote_vault: s3.pc_vault,
|
||||
market_vault_signer: s3.vault_signer,
|
||||
quote_bank: quote.mint_info.first_bank(),
|
||||
quote_vault: quote.mint_info.first_vault(),
|
||||
base_bank: base.mint_info.first_bank(),
|
||||
base_vault: base.mint_info.first_vault(),
|
||||
token_program: Token::id(),
|
||||
},
|
||||
None,
|
||||
|
@ -747,10 +740,11 @@ impl MangoClient {
|
|||
side: Serum3Side,
|
||||
order_id: u128,
|
||||
) -> anyhow::Result<Signature> {
|
||||
let s3 = self.serum3_data_by_market_name(market_name)?;
|
||||
let market_index = self.context.serum3_market_index(market_name);
|
||||
let s3 = self.context.serum3(market_index);
|
||||
|
||||
let account = self.mango_account().await?;
|
||||
let open_orders = account.serum3_orders(s3.market_index).unwrap().open_orders;
|
||||
let open_orders = account.serum3_orders(market_index).unwrap().open_orders;
|
||||
|
||||
let ix = Instruction {
|
||||
program_id: mango_v4::id(),
|
||||
|
@ -759,13 +753,13 @@ impl MangoClient {
|
|||
&mango_v4::accounts::Serum3CancelOrder {
|
||||
group: self.group(),
|
||||
account: self.mango_account_address,
|
||||
serum_market: s3.market.address,
|
||||
serum_program: s3.market.market.serum_program,
|
||||
serum_market_external: s3.market.market.serum_market_external,
|
||||
serum_market: s3.address,
|
||||
serum_program: s3.market.serum_program,
|
||||
serum_market_external: s3.market.serum_market_external,
|
||||
open_orders,
|
||||
market_bids: s3.market.bids,
|
||||
market_asks: s3.market.asks,
|
||||
market_event_queue: s3.market.event_q,
|
||||
market_bids: s3.bids,
|
||||
market_asks: s3.asks,
|
||||
market_event_queue: s3.event_q,
|
||||
owner: self.owner(),
|
||||
},
|
||||
None,
|
||||
|
@ -782,6 +776,8 @@ impl MangoClient {
|
|||
//
|
||||
// Perps
|
||||
//
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn perp_place_order_instruction(
|
||||
&self,
|
||||
account: &MangoAccountValue,
|
||||
|
@ -841,6 +837,7 @@ impl MangoClient {
|
|||
Ok(ix)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn perp_place_order(
|
||||
&self,
|
||||
market_index: PerpMarketIndex,
|
||||
|
@ -1653,13 +1650,6 @@ impl MangoClient {
|
|||
}
|
||||
}
|
||||
|
||||
struct Serum3Data<'a> {
|
||||
market_index: Serum3MarketIndex,
|
||||
market: &'a Serum3MarketContext,
|
||||
quote: &'a TokenContext,
|
||||
base: &'a TokenContext,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum MangoClientError {
|
||||
#[error("Transaction simulation error. Error: {err:?}, Logs: {}",
|
||||
|
|
|
@ -78,14 +78,34 @@ impl MangoGroupContext {
|
|||
self.token(token_index).mint_info
|
||||
}
|
||||
|
||||
pub fn token(&self, token_index: TokenIndex) -> &TokenContext {
|
||||
self.tokens.get(&token_index).unwrap()
|
||||
}
|
||||
|
||||
pub fn perp(&self, perp_market_index: PerpMarketIndex) -> &PerpMarketContext {
|
||||
self.perp_markets.get(&perp_market_index).unwrap()
|
||||
}
|
||||
|
||||
pub fn perp_market_address(&self, perp_market_index: PerpMarketIndex) -> Pubkey {
|
||||
self.perp(perp_market_index).address
|
||||
}
|
||||
|
||||
pub fn serum3_market_index(&self, name: &str) -> Serum3MarketIndex {
|
||||
*self.serum3_market_indexes_by_name.get(name).unwrap()
|
||||
}
|
||||
|
||||
pub fn serum3(&self, market_index: Serum3MarketIndex) -> &Serum3MarketContext {
|
||||
self.serum3_markets.get(&market_index).unwrap()
|
||||
}
|
||||
|
||||
pub fn serum3_base_token(&self, market_index: Serum3MarketIndex) -> &TokenContext {
|
||||
self.token(self.serum3(market_index).market.base_token_index)
|
||||
}
|
||||
|
||||
pub fn serum3_quote_token(&self, market_index: Serum3MarketIndex) -> &TokenContext {
|
||||
self.token(self.serum3(market_index).market.quote_token_index)
|
||||
}
|
||||
|
||||
pub fn token(&self, token_index: TokenIndex) -> &TokenContext {
|
||||
self.tokens.get(&token_index).unwrap()
|
||||
}
|
||||
|
||||
pub fn token_by_mint(&self, mint: &Pubkey) -> anyhow::Result<&TokenContext> {
|
||||
self.tokens
|
||||
.iter()
|
||||
|
@ -93,10 +113,6 @@ impl MangoGroupContext {
|
|||
.ok_or_else(|| anyhow::anyhow!("no token for mint {}", mint))
|
||||
}
|
||||
|
||||
pub fn perp_market_address(&self, perp_market_index: PerpMarketIndex) -> Pubkey {
|
||||
self.perp(perp_market_index).address
|
||||
}
|
||||
|
||||
pub async fn new_from_rpc(rpc: &RpcClientAsync, group: Pubkey) -> anyhow::Result<Self> {
|
||||
let program = mango_v4::ID;
|
||||
|
||||
|
|
Loading…
Reference in New Issue