Compare commits

...

8 Commits

Author SHA1 Message Date
microwavedcola1 4841e11b2b
Merge 3d1e8b6984 into f4c6a086c1 2024-04-24 12:18:10 +00:00
microwavedcola1 3d1e8b6984 Fixes from review
Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
2024-04-24 14:18:05 +02:00
microwavedcola1 128992f6c4 Fixes from review
Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
2024-04-24 14:02:22 +02:00
microwavedcola1 f4c6a086c1 small updates to token withdraw script
Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
2024-04-24 11:29:46 +02:00
Christian Kamm 88451debed keeper: fix collateral fee charging on main group
- longer timeout of 120s for gPA call
- filter out mango accounts for foreign groups
2024-04-23 08:12:04 +02:00
Christian Kamm d08ef26a99
rust client: rename Client::owner to "authority" (#948)
It could be the owner or the delegate
2024-04-22 14:52:36 +02:00
Christian Kamm 0fe18b59af rust client: fix withdraws as delegate
they need to go to the owner's ata
2024-04-22 14:20:32 +02:00
Christian Kamm 66c6ae1cff liquidator: fix rebalance loops
selling 100% with flash loan swap fee charged on top meant creating a
borrow
2024-04-22 14:10:01 +02:00
12 changed files with 108 additions and 90 deletions

View File

@ -23,7 +23,9 @@ use mango_v4_client::{
RpcAccountFetcher, TransactionBuilder, RpcAccountFetcher, TransactionBuilder,
}; };
use prometheus::{register_histogram, Encoder, Histogram, IntCounter, Registry}; use prometheus::{register_histogram, Encoder, Histogram, IntCounter, Registry};
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_sdk::{ use solana_sdk::{
commitment_config::CommitmentConfig,
instruction::{AccountMeta, Instruction}, instruction::{AccountMeta, Instruction},
pubkey::Pubkey, pubkey::Pubkey,
signature::Signature, signature::Signature,
@ -105,7 +107,7 @@ pub async fn runner(
.context .context
.tokens .tokens
.values() .values()
.filter(|t| t.closed == false) .filter(|t| !t.closed)
.map(|t| &t.token_index) .map(|t| &t.token_index)
// TODO: grouping tokens whose oracle might have less confidencen e.g. ORCA with the rest, fails whole ix // TODO: grouping tokens whose oracle might have less confidencen e.g. ORCA with the rest, fails whole ix
// TokenUpdateIndexAndRate is known to take max 71k cu // TokenUpdateIndexAndRate is known to take max 71k cu
@ -473,9 +475,16 @@ pub async fn loop_charge_collateral_fees(
} }
// Make a new one separate from the mango_client.account_fetcher, // Make a new one separate from the mango_client.account_fetcher,
// because we don't want cached responses // because we don't want cached responses and we need a longer timeout
let fetcher = RpcAccountFetcher { let fetcher = {
rpc: mango_client.client.new_rpc_async(), let config = mango_client.client.config();
RpcAccountFetcher {
rpc: RpcClient::new_with_timeout_and_commitment(
config.cluster.url().to_string(),
Duration::from_secs(120),
CommitmentConfig::confirmed(),
),
}
}; };
let group: Group = account_fetcher_fetch_anchor_account(&fetcher, &mango_client.context.group) let group: Group = account_fetcher_fetch_anchor_account(&fetcher, &mango_client.context.group)
@ -530,6 +539,9 @@ async fn charge_collateral_fees_inner(
.unwrap() .unwrap()
.as_secs() as u64; .as_secs() as u64;
for (pk, account) in mango_accounts { for (pk, account) in mango_accounts {
if account.fixed.group != client.group() {
continue;
}
let should_reset = let should_reset =
collateral_fee_interval == 0 && account.fixed.last_collateral_fee_charge > 0; collateral_fee_interval == 0 && account.fixed.last_collateral_fee_charge > 0;
let should_charge = collateral_fee_interval > 0 let should_charge = collateral_fee_interval > 0

View File

@ -263,7 +263,7 @@ impl<'a> LiquidateHelper<'a> {
liq_ixs.cu = liq_ixs.cu.max(self.config.compute_limit_for_liq_ix); liq_ixs.cu = liq_ixs.cu.max(self.config.compute_limit_for_liq_ix);
let txsig = self let txsig = self
.client .client
.send_and_confirm_owner_tx(liq_ixs.to_instructions()) .send_and_confirm_authority_tx(liq_ixs.to_instructions())
.await .await
.context("sending perp_liq_base_or_positive_pnl_instruction")?; .context("sending perp_liq_base_or_positive_pnl_instruction")?;
info!( info!(
@ -309,7 +309,7 @@ impl<'a> LiquidateHelper<'a> {
liq_ixs.cu = liq_ixs.cu.max(self.config.compute_limit_for_liq_ix); liq_ixs.cu = liq_ixs.cu.max(self.config.compute_limit_for_liq_ix);
let txsig = self let txsig = self
.client .client
.send_and_confirm_owner_tx(liq_ixs.to_instructions()) .send_and_confirm_authority_tx(liq_ixs.to_instructions())
.await .await
.context("sending perp_liq_negative_pnl_or_bankruptcy_instruction")?; .context("sending perp_liq_negative_pnl_or_bankruptcy_instruction")?;
info!( info!(
@ -503,7 +503,7 @@ impl<'a> LiquidateHelper<'a> {
liq_ixs.cu = liq_ixs.cu.max(self.config.compute_limit_for_liq_ix); liq_ixs.cu = liq_ixs.cu.max(self.config.compute_limit_for_liq_ix);
let txsig = self let txsig = self
.client .client
.send_and_confirm_owner_tx(liq_ixs.to_instructions()) .send_and_confirm_authority_tx(liq_ixs.to_instructions())
.await .await
.context("sending liq_token_with_token")?; .context("sending liq_token_with_token")?;
info!( info!(
@ -560,7 +560,7 @@ impl<'a> LiquidateHelper<'a> {
liq_ixs.cu = liq_ixs.cu.max(self.config.compute_limit_for_liq_ix); liq_ixs.cu = liq_ixs.cu.max(self.config.compute_limit_for_liq_ix);
let txsig = self let txsig = self
.client .client
.send_and_confirm_owner_tx(liq_ixs.to_instructions()) .send_and_confirm_authority_tx(liq_ixs.to_instructions())
.await .await
.context("sending liq_token_with_token")?; .context("sending liq_token_with_token")?;
info!( info!(

View File

@ -498,8 +498,11 @@ impl Rebalancer {
if amount > dust_threshold { if amount > dust_threshold {
// Sell // Sell
// To avoid creating a borrow when paying flash loan fees, sell only a fraction
let input_amount = amount * I80F48::from_num(0.99);
let (txsig, route) = self let (txsig, route) = self
.token_swap_sell(token_mint, amount.to_num::<u64>()) .token_swap_sell(token_mint, input_amount.to_num::<u64>())
.await?; .await?;
let out_token = self let out_token = self
.mango_client .mango_client
@ -641,7 +644,7 @@ impl Rebalancer {
let tx_builder = TransactionBuilder { let tx_builder = TransactionBuilder {
instructions: ixs.to_instructions(), instructions: ixs.to_instructions(),
signers: vec![self.mango_client.owner.clone()], signers: vec![self.mango_client.authority.clone()],
..self.mango_client.transaction_builder().await? ..self.mango_client.transaction_builder().await?
}; };

View File

@ -21,9 +21,9 @@ async fn report(client: &MangoClient, min_health_ratio: f64) -> anyhow::Result<(
}) })
.to_string(); .to_string();
let signature = client.owner.sign_message(message.as_bytes()); let signature = client.authority.sign_message(message.as_bytes());
let payload = serde_json::json!({ let payload = serde_json::json!({
"wallet_pk": client.owner.pubkey().to_string(), "wallet_pk": client.authority.pubkey().to_string(),
"message": message, "message": message,
"signature": signature.to_string(), "signature": signature.to_string(),
}); });

View File

@ -1202,7 +1202,7 @@ impl Context {
let fee_payer = self.mango_client.client.fee_payer(); let fee_payer = self.mango_client.client.fee_payer();
TransactionBuilder { TransactionBuilder {
instructions: vec![compute_ix], instructions: vec![compute_ix],
signers: vec![self.mango_client.owner.clone(), fee_payer], signers: vec![self.mango_client.authority.clone(), fee_payer],
..self.mango_client.transaction_builder().await? ..self.mango_client.transaction_builder().await?
} }
}; };

View File

@ -142,7 +142,7 @@ impl State {
} }
let txsig = match mango_client let txsig = match mango_client
.send_and_confirm_owner_tx(instructions.to_instructions()) .send_and_confirm_authority_tx(instructions.to_instructions())
.await .await
{ {
Ok(v) => v, Ok(v) => v,

View File

@ -273,7 +273,7 @@ pub struct MangoClient {
// call to refresh banks etc -- if it's backed by websockets, these could just do nothing // call to refresh banks etc -- if it's backed by websockets, these could just do nothing
pub account_fetcher: Arc<dyn AccountFetcher>, pub account_fetcher: Arc<dyn AccountFetcher>,
pub owner: Arc<Keypair>, pub authority: Arc<Keypair>,
pub mango_account_address: Pubkey, pub mango_account_address: Pubkey,
pub context: MangoGroupContext, pub context: MangoGroupContext,
@ -406,7 +406,7 @@ impl MangoClient {
pub async fn new_for_existing_account( pub async fn new_for_existing_account(
client: Client, client: Client,
account: Pubkey, account: Pubkey,
owner: Arc<Keypair>, authority: Arc<Keypair>,
) -> anyhow::Result<Self> { ) -> anyhow::Result<Self> {
let rpc = client.new_rpc_async(); let rpc = client.new_rpc_async();
let account_fetcher = Arc::new(CachedAccountFetcher::new(Arc::new(RpcAccountFetcher { let account_fetcher = Arc::new(CachedAccountFetcher::new(Arc::new(RpcAccountFetcher {
@ -415,25 +415,25 @@ impl MangoClient {
let mango_account = let mango_account =
account_fetcher_fetch_mango_account(&*account_fetcher, &account).await?; account_fetcher_fetch_mango_account(&*account_fetcher, &account).await?;
let group = mango_account.fixed.group; let group = mango_account.fixed.group;
if mango_account.fixed.owner != owner.pubkey() { if mango_account.fixed.owner != authority.pubkey() {
anyhow::bail!( anyhow::bail!(
"bad owner for account: expected {} got {}", "bad owner for account: expected {} got {}",
mango_account.fixed.owner, mango_account.fixed.owner,
owner.pubkey() authority.pubkey()
); );
} }
let rpc = client.rpc_async(); let rpc = client.rpc_async();
let group_context = MangoGroupContext::new_from_rpc(&rpc, group).await?; let group_context = MangoGroupContext::new_from_rpc(&rpc, group).await?;
Self::new_detail(client, account, owner, group_context, account_fetcher) Self::new_detail(client, account, authority, group_context, account_fetcher)
} }
/// Allows control of AccountFetcher and externally created MangoGroupContext /// Allows control of AccountFetcher and externally created MangoGroupContext
pub fn new_detail( pub fn new_detail(
client: Client, client: Client,
account: Pubkey, account: Pubkey,
owner: Arc<Keypair>, authority: Arc<Keypair>,
// future: maybe pass Arc<MangoGroupContext>, so it can be extenally updated? // future: maybe pass Arc<MangoGroupContext>, so it can be extenally updated?
group_context: MangoGroupContext, group_context: MangoGroupContext,
account_fetcher: Arc<dyn AccountFetcher>, account_fetcher: Arc<dyn AccountFetcher>,
@ -441,15 +441,15 @@ impl MangoClient {
Ok(Self { Ok(Self {
client, client,
account_fetcher, account_fetcher,
owner, authority,
mango_account_address: account, mango_account_address: account,
context: group_context, context: group_context,
http_client: reqwest::Client::new(), http_client: reqwest::Client::new(),
}) })
} }
pub fn owner(&self) -> Pubkey { pub fn authority(&self) -> Pubkey {
self.owner.pubkey() self.authority.pubkey()
} }
pub fn group(&self) -> Pubkey { pub fn group(&self) -> Pubkey {
@ -554,12 +554,15 @@ impl MangoClient {
&mango_v4::accounts::TokenDeposit { &mango_v4::accounts::TokenDeposit {
group: self.group(), group: self.group(),
account: self.mango_account_address, account: self.mango_account_address,
owner: self.owner(), owner: self.authority(),
bank: token.first_bank(), bank: token.first_bank(),
vault: token.first_vault(), vault: token.first_vault(),
oracle: token.oracle, oracle: token.oracle,
token_account: get_associated_token_address(&self.owner(), &token.mint), token_account: get_associated_token_address(
token_authority: self.owner(), &self.authority(),
&token.mint,
),
token_authority: self.authority(),
token_program: Token::id(), token_program: Token::id(),
}, },
None, None,
@ -574,7 +577,8 @@ impl MangoClient {
}, },
self.instruction_cu(health_cu), self.instruction_cu(health_cu),
); );
self.send_and_confirm_owner_tx(ixs.to_instructions()).await self.send_and_confirm_authority_tx(ixs.to_instructions())
.await
} }
/// Assert that health of account is > N /// Assert that health of account is > N
@ -639,8 +643,8 @@ impl MangoClient {
let ixs = PreparedInstructions::from_vec( let ixs = PreparedInstructions::from_vec(
vec![ vec![
spl_associated_token_account::instruction::create_associated_token_account_idempotent( spl_associated_token_account::instruction::create_associated_token_account_idempotent(
&self.owner(), &self.authority(),
&self.owner(), &account.fixed.owner,
&mint, &mint,
&Token::id(), &Token::id(),
), ),
@ -651,12 +655,12 @@ impl MangoClient {
&mango_v4::accounts::TokenWithdraw { &mango_v4::accounts::TokenWithdraw {
group: self.group(), group: self.group(),
account: self.mango_account_address, account: self.mango_account_address,
owner: self.owner(), owner: self.authority(),
bank: token.first_bank(), bank: token.first_bank(),
vault: token.first_vault(), vault: token.first_vault(),
oracle: token.oracle, oracle: token.oracle,
token_account: get_associated_token_address( token_account: get_associated_token_address(
&self.owner(), &account.fixed.owner,
&token.mint, &token.mint,
), ),
token_program: Token::id(), token_program: Token::id(),
@ -687,7 +691,8 @@ impl MangoClient {
let ixs = self let ixs = self
.token_withdraw_instructions(&account, mint, amount, allow_borrow) .token_withdraw_instructions(&account, mint, amount, allow_borrow)
.await?; .await?;
self.send_and_confirm_owner_tx(ixs.to_instructions()).await self.send_and_confirm_authority_tx(ixs.to_instructions())
.await
} }
pub async fn bank_oracle_price(&self, token_index: TokenIndex) -> anyhow::Result<I80F48> { pub async fn bank_oracle_price(&self, token_index: TokenIndex) -> anyhow::Result<I80F48> {
@ -739,8 +744,8 @@ impl MangoClient {
serum_program: s3.serum_program, serum_program: s3.serum_program,
serum_market_external: s3.serum_market_external, serum_market_external: s3.serum_market_external,
open_orders, open_orders,
owner: self.owner(), owner: self.authority(),
sol_destination: self.owner(), sol_destination: self.authority(),
}, },
None, None,
), ),
@ -755,7 +760,8 @@ impl MangoClient {
pub async fn serum3_close_open_orders(&self, name: &str) -> anyhow::Result<Signature> { pub async fn serum3_close_open_orders(&self, name: &str) -> anyhow::Result<Signature> {
let market_index = self.context.serum3_market_index(name); let market_index = self.context.serum3_market_index(name);
let ix = self.serum3_close_open_orders_instruction(market_index); let ix = self.serum3_close_open_orders_instruction(market_index);
self.send_and_confirm_owner_tx(ix.to_instructions()).await self.send_and_confirm_authority_tx(ix.to_instructions())
.await
} }
pub fn serum3_create_open_orders_instruction( pub fn serum3_create_open_orders_instruction(
@ -777,8 +783,8 @@ impl MangoClient {
serum_program: s3.serum_program, serum_program: s3.serum_program,
serum_market_external: s3.serum_market_external, serum_market_external: s3.serum_market_external,
open_orders, open_orders,
owner: self.owner(), owner: self.authority(),
payer: self.owner(), payer: self.authority(),
system_program: System::id(), system_program: System::id(),
rent: sysvar::rent::id(), rent: sysvar::rent::id(),
}, },
@ -810,7 +816,7 @@ impl MangoClient {
pub async fn serum3_create_open_orders(&self, name: &str) -> anyhow::Result<Signature> { pub async fn serum3_create_open_orders(&self, name: &str) -> anyhow::Result<Signature> {
let market_index = self.context.serum3_market_index(name); let market_index = self.context.serum3_market_index(name);
let ix = self.serum3_create_open_orders_instruction(market_index); let ix = self.serum3_create_open_orders_instruction(market_index);
self.send_and_confirm_owner_tx(vec![ix]).await self.send_and_confirm_authority_tx(vec![ix]).await
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
@ -868,7 +874,7 @@ impl MangoClient {
market_base_vault: s3.coin_vault, market_base_vault: s3.coin_vault,
market_quote_vault: s3.pc_vault, market_quote_vault: s3.pc_vault,
market_vault_signer: s3.vault_signer, market_vault_signer: s3.vault_signer,
owner: self.owner(), owner: self.authority(),
token_program: Token::id(), token_program: Token::id(),
}, },
None, None,
@ -1131,7 +1137,8 @@ impl MangoClient {
let mut ixs = PreparedInstructions::new(); let mut ixs = PreparedInstructions::new();
ixs.append(create_or_replace_ixs); ixs.append(create_or_replace_ixs);
ixs.append(place_order_ixs); ixs.append(place_order_ixs);
self.send_and_confirm_owner_tx(ixs.to_instructions()).await self.send_and_confirm_authority_tx(ixs.to_instructions())
.await
} }
pub async fn serum3_settle_funds(&self, name: &str) -> anyhow::Result<Signature> { pub async fn serum3_settle_funds(&self, name: &str) -> anyhow::Result<Signature> {
@ -1161,7 +1168,7 @@ impl MangoClient {
market_base_vault: s3.coin_vault, market_base_vault: s3.coin_vault,
market_quote_vault: s3.pc_vault, market_quote_vault: s3.pc_vault,
market_vault_signer: s3.vault_signer, market_vault_signer: s3.vault_signer,
owner: self.owner(), owner: self.authority(),
token_program: Token::id(), token_program: Token::id(),
}, },
v2: mango_v4::accounts::Serum3SettleFundsV2Extra { v2: mango_v4::accounts::Serum3SettleFundsV2Extra {
@ -1175,7 +1182,7 @@ impl MangoClient {
fees_to_dao: true, fees_to_dao: true,
}), }),
}; };
self.send_and_confirm_owner_tx(vec![ix]).await self.send_and_confirm_authority_tx(vec![ix]).await
} }
pub fn serum3_cancel_all_orders_instruction( pub fn serum3_cancel_all_orders_instruction(
@ -1201,7 +1208,7 @@ impl MangoClient {
serum_market: s3.address, serum_market: s3.address,
serum_program: s3.serum_program, serum_program: s3.serum_program,
serum_market_external: s3.serum_market_external, serum_market_external: s3.serum_market_external,
owner: self.owner(), owner: self.authority(),
}, },
None, None,
), ),
@ -1340,7 +1347,7 @@ impl MangoClient {
market_bids: s3.bids, market_bids: s3.bids,
market_asks: s3.asks, market_asks: s3.asks,
market_event_queue: s3.event_q, market_event_queue: s3.event_q,
owner: self.owner(), owner: self.authority(),
}, },
None, None,
) )
@ -1350,7 +1357,7 @@ impl MangoClient {
order_id, order_id,
}), }),
}; };
self.send_and_confirm_owner_tx(vec![ix]).await self.send_and_confirm_authority_tx(vec![ix]).await
} }
// //
@ -1403,7 +1410,7 @@ impl MangoClient {
&mango_v4::accounts::PerpPlaceOrder { &mango_v4::accounts::PerpPlaceOrder {
group: self.group(), group: self.group(),
account: self.mango_account_address, account: self.mango_account_address,
owner: self.owner(), owner: self.authority(),
perp_market: perp.address, perp_market: perp.address,
bids: perp.bids, bids: perp.bids,
asks: perp.asks, asks: perp.asks,
@ -1508,7 +1515,8 @@ impl MangoClient {
self_trade_behavior, self_trade_behavior,
) )
.await?; .await?;
self.send_and_confirm_owner_tx(ixs.to_instructions()).await self.send_and_confirm_authority_tx(ixs.to_instructions())
.await
} }
pub fn perp_cancel_all_orders_instruction( pub fn perp_cancel_all_orders_instruction(
@ -1526,7 +1534,7 @@ impl MangoClient {
&mango_v4::accounts::PerpCancelAllOrders { &mango_v4::accounts::PerpCancelAllOrders {
group: self.group(), group: self.group(),
account: self.mango_account_address, account: self.mango_account_address,
owner: self.owner(), owner: self.authority(),
perp_market: perp.address, perp_market: perp.address,
bids: perp.bids, bids: perp.bids,
asks: perp.asks, asks: perp.asks,
@ -1551,7 +1559,8 @@ impl MangoClient {
let ixs = self let ixs = self
.perp_deactivate_position_instruction(market_index) .perp_deactivate_position_instruction(market_index)
.await?; .await?;
self.send_and_confirm_owner_tx(ixs.to_instructions()).await self.send_and_confirm_authority_tx(ixs.to_instructions())
.await
} }
async fn perp_deactivate_position_instruction( async fn perp_deactivate_position_instruction(
@ -1568,7 +1577,7 @@ impl MangoClient {
&mango_v4::accounts::PerpDeactivatePosition { &mango_v4::accounts::PerpDeactivatePosition {
group: self.group(), group: self.group(),
account: self.mango_account_address, account: self.mango_account_address,
owner: self.owner(), owner: self.authority(),
perp_market: perp.address, perp_market: perp.address,
}, },
None, None,
@ -1611,7 +1620,7 @@ impl MangoClient {
&mango_v4::accounts::PerpSettlePnl { &mango_v4::accounts::PerpSettlePnl {
group: self.group(), group: self.group(),
settler: self.mango_account_address, settler: self.mango_account_address,
settler_owner: self.owner(), settler_owner: self.authority(),
perp_market: perp.address, perp_market: perp.address,
account_a: *account_a.0, account_a: *account_a.0,
account_b: *account_b.0, account_b: *account_b.0,
@ -1715,7 +1724,7 @@ impl MangoClient {
perp_market: perp.address, perp_market: perp.address,
oracle: perp.oracle, oracle: perp.oracle,
liqor: self.mango_account_address, liqor: self.mango_account_address,
liqor_owner: self.owner(), liqor_owner: self.authority(),
liqee: *liqee.0, liqee: *liqee.0,
settle_bank: settle_token_info.first_bank(), settle_bank: settle_token_info.first_bank(),
settle_vault: settle_token_info.first_vault(), settle_vault: settle_token_info.first_vault(),
@ -1775,7 +1784,7 @@ impl MangoClient {
perp_market: perp.address, perp_market: perp.address,
oracle: perp.oracle, oracle: perp.oracle,
liqor: self.mango_account_address, liqor: self.mango_account_address,
liqor_owner: self.owner(), liqor_owner: self.authority(),
liqee: *liqee.0, liqee: *liqee.0,
settle_bank: settle_token_info.first_bank(), settle_bank: settle_token_info.first_bank(),
settle_vault: settle_token_info.first_vault(), settle_vault: settle_token_info.first_vault(),
@ -1883,7 +1892,7 @@ impl MangoClient {
group: self.group(), group: self.group(),
liqee: *liqee.0, liqee: *liqee.0,
liqor: self.mango_account_address, liqor: self.mango_account_address,
liqor_owner: self.owner(), liqor_owner: self.authority(),
}, },
None, None,
); );
@ -1944,7 +1953,7 @@ impl MangoClient {
group: self.group(), group: self.group(),
liqee: *liqee.0, liqee: *liqee.0,
liqor: self.mango_account_address, liqor: self.mango_account_address,
liqor_owner: self.owner(), liqor_owner: self.authority(),
liab_mint_info: liab_info.mint_info_address, liab_mint_info: liab_info.mint_info_address,
quote_vault: quote_info.first_vault(), quote_vault: quote_info.first_vault(),
insurance_vault: group.insurance_vault, insurance_vault: group.insurance_vault,
@ -2004,7 +2013,7 @@ impl MangoClient {
group: self.group(), group: self.group(),
liqee: *liqee.0, liqee: *liqee.0,
liqor: self.mango_account_address, liqor: self.mango_account_address,
liqor_authority: self.owner(), liqor_authority: self.authority(),
}, },
None, None,
); );
@ -2051,7 +2060,7 @@ impl MangoClient {
group: self.group(), group: self.group(),
liqee: *account.0, liqee: *account.0,
liqor: self.mango_account_address, liqor: self.mango_account_address,
liqor_authority: self.owner(), liqor_authority: self.authority(),
}, },
None, None,
); );
@ -2252,7 +2261,7 @@ impl MangoClient {
self.context.compute_estimates.cu_per_mango_instruction + health_cu self.context.compute_estimates.cu_per_mango_instruction + health_cu
} }
pub async fn send_and_confirm_owner_tx( pub async fn send_and_confirm_authority_tx(
&self, &self,
instructions: Vec<Instruction>, instructions: Vec<Instruction>,
) -> anyhow::Result<Signature> { ) -> anyhow::Result<Signature> {
@ -2260,7 +2269,7 @@ impl MangoClient {
instructions, instructions,
..self.transaction_builder().await? ..self.transaction_builder().await?
}; };
tx_builder.signers.push(self.owner.clone()); tx_builder.signers.push(self.authority.clone());
tx_builder.send_and_confirm(&self.client).await tx_builder.send_and_confirm(&self.client).await
} }

View File

@ -272,7 +272,7 @@ impl MangoGroupContext {
name: String::new(), name: String::new(),
mint_info_address: *pk, mint_info_address: *pk,
decimals: u8::MAX, decimals: u8::MAX,
closed: false, closed: true,
banks: mi.banks, banks: mi.banks,
vaults: mi.vaults, vaults: mi.vaults,
oracle: mi.oracle, oracle: mi.oracle,
@ -299,7 +299,7 @@ impl MangoGroupContext {
let fallback_oracle_accounts = fetch_multiple_accounts(rpc, &fallback_keys[..]).await?; let fallback_oracle_accounts = fetch_multiple_accounts(rpc, &fallback_keys[..]).await?;
for (index, (_, bank)) in bank_tuples.iter().enumerate() { for (index, (_, bank)) in bank_tuples.iter().enumerate() {
let token = tokens.get_mut(&bank.token_index).unwrap(); let token = tokens.get_mut(&bank.token_index).unwrap();
token.closed = token.closed &=
bank.native_deposits() == 0 && bank.native_borrows() == 0 && bank.reduce_only == 1; bank.native_deposits() == 0 && bank.native_borrows() == 0 && bank.reduce_only == 1;
token.name = bank.name().into(); token.name = bank.name().into();
token.decimals = bank.mint_decimals; token.decimals = bank.mint_decimals;

View File

@ -230,14 +230,14 @@ impl<'a> JupiterV6<'a> {
.map(util::to_writable_account_meta) .map(util::to_writable_account_meta)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let owner = self.mango_client.owner(); let authority = self.mango_client.authority();
let account = &self.mango_client.mango_account().await?; let account = &self.mango_client.mango_account().await?;
let token_ams = [source_token.mint, target_token.mint] let token_ams = [source_token.mint, target_token.mint]
.into_iter() .into_iter()
.map(|mint| { .map(|mint| {
util::to_writable_account_meta( util::to_writable_account_meta(
anchor_spl::associated_token::get_associated_token_address(&owner, &mint), anchor_spl::associated_token::get_associated_token_address(&authority, &mint),
) )
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -274,7 +274,7 @@ impl<'a> JupiterV6<'a> {
.post(format!("{}/swap-instructions", config.jupiter_v6_url)) .post(format!("{}/swap-instructions", config.jupiter_v6_url))
.query(&query_args) .query(&query_args)
.json(&SwapRequest { .json(&SwapRequest {
user_public_key: owner.to_string(), user_public_key: authority.to_string(),
wrap_and_unwrap_sol: false, wrap_and_unwrap_sol: false,
use_shared_accounts: true, use_shared_accounts: true,
fee_account: None, fee_account: None,
@ -304,8 +304,8 @@ impl<'a> JupiterV6<'a> {
// Ensure the source token account is created (jupiter takes care of the output account) // Ensure the source token account is created (jupiter takes care of the output account)
instructions.push( instructions.push(
spl_associated_token_account::instruction::create_associated_token_account_idempotent( spl_associated_token_account::instruction::create_associated_token_account_idempotent(
&owner, &authority,
&owner, &authority,
&source_token.mint, &source_token.mint,
&Token::id(), &Token::id(),
), ),
@ -317,7 +317,7 @@ impl<'a> JupiterV6<'a> {
let mut ams = anchor_lang::ToAccountMetas::to_account_metas( let mut ams = anchor_lang::ToAccountMetas::to_account_metas(
&mango_v4::accounts::FlashLoanBegin { &mango_v4::accounts::FlashLoanBegin {
account: self.mango_client.mango_account_address, account: self.mango_client.mango_account_address,
owner, owner: authority,
token_program: Token::id(), token_program: Token::id(),
instructions: solana_sdk::sysvar::instructions::id(), instructions: solana_sdk::sysvar::instructions::id(),
}, },
@ -340,7 +340,7 @@ impl<'a> JupiterV6<'a> {
let mut ams = anchor_lang::ToAccountMetas::to_account_metas( let mut ams = anchor_lang::ToAccountMetas::to_account_metas(
&mango_v4::accounts::FlashLoanEnd { &mango_v4::accounts::FlashLoanEnd {
account: self.mango_client.mango_account_address, account: self.mango_client.mango_account_address,
owner, owner: authority,
token_program: Token::id(), token_program: Token::id(),
}, },
None, None,
@ -375,13 +375,13 @@ impl<'a> JupiterV6<'a> {
.await?; .await?;
address_lookup_tables.extend(jup_alts.into_iter()); address_lookup_tables.extend(jup_alts.into_iter());
let payer = owner; // maybe use fee_payer? but usually it's the same let payer = authority; // maybe use fee_payer? but usually it's the same
Ok(TransactionBuilder { Ok(TransactionBuilder {
instructions, instructions,
address_lookup_tables, address_lookup_tables,
payer, payer,
signers: vec![self.mango_client.owner.clone()], signers: vec![self.mango_client.authority.clone()],
config: self config: self
.mango_client .mango_client
.client .client

View File

@ -124,14 +124,14 @@ impl<'a> Sanctum<'a> {
.map(util::to_writable_account_meta) .map(util::to_writable_account_meta)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let owner = self.mango_client.owner(); let authority = self.mango_client.authority();
let account = &self.mango_client.mango_account().await?; let account = &self.mango_client.mango_account().await?;
let token_ams = [source_token.mint, target_token.mint] let token_ams = [source_token.mint, target_token.mint]
.into_iter() .into_iter()
.map(|mint| { .map(|mint| {
util::to_writable_account_meta( util::to_writable_account_meta(
anchor_spl::associated_token::get_associated_token_address(&owner, &mint), anchor_spl::associated_token::get_associated_token_address(&authority, &mint),
) )
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -176,7 +176,7 @@ impl<'a> Sanctum<'a> {
input: input_mint.to_string(), input: input_mint.to_string(),
mode: "ExactIn".to_string(), mode: "ExactIn".to_string(),
output_lst_mint: output_mint.to_string(), output_lst_mint: output_mint.to_string(),
signer: owner.to_string(), signer: authority.to_string(),
swap_src: quote.swap_src.clone(), swap_src: quote.swap_src.clone(),
}) })
.timeout(self.timeout_duration) .timeout(self.timeout_duration)
@ -244,8 +244,8 @@ impl<'a> Sanctum<'a> {
// Ensure the source token account is created (sanctum takes care of the output account) // Ensure the source token account is created (sanctum takes care of the output account)
instructions.push( instructions.push(
spl_associated_token_account::instruction::create_associated_token_account_idempotent( spl_associated_token_account::instruction::create_associated_token_account_idempotent(
&owner, &authority,
&owner, &authority,
&source_token.mint, &source_token.mint,
&Token::id(), &Token::id(),
), ),
@ -257,7 +257,7 @@ impl<'a> Sanctum<'a> {
let mut ams = anchor_lang::ToAccountMetas::to_account_metas( let mut ams = anchor_lang::ToAccountMetas::to_account_metas(
&mango_v4::accounts::FlashLoanBegin { &mango_v4::accounts::FlashLoanBegin {
account: self.mango_client.mango_account_address, account: self.mango_client.mango_account_address,
owner, owner: authority,
token_program: Token::id(), token_program: Token::id(),
instructions: solana_sdk::sysvar::instructions::id(), instructions: solana_sdk::sysvar::instructions::id(),
}, },
@ -284,7 +284,7 @@ impl<'a> Sanctum<'a> {
let mut ams = anchor_lang::ToAccountMetas::to_account_metas( let mut ams = anchor_lang::ToAccountMetas::to_account_metas(
&mango_v4::accounts::FlashLoanEnd { &mango_v4::accounts::FlashLoanEnd {
account: self.mango_client.mango_account_address, account: self.mango_client.mango_account_address,
owner, owner: authority,
token_program: Token::id(), token_program: Token::id(),
}, },
None, None,
@ -308,13 +308,13 @@ impl<'a> Sanctum<'a> {
let mut address_lookup_tables = self.mango_client.mango_address_lookup_tables().await?; let mut address_lookup_tables = self.mango_client.mango_address_lookup_tables().await?;
address_lookup_tables.extend(sanctum_alts.into_iter()); address_lookup_tables.extend(sanctum_alts.into_iter());
let payer = owner; // maybe use fee_payer? but usually it's the same let payer = authority; // maybe use fee_payer? but usually it's the same
Ok(TransactionBuilder { Ok(TransactionBuilder {
instructions, instructions,
address_lookup_tables, address_lookup_tables,
payer, payer,
signers: vec![self.mango_client.owner.clone()], signers: vec![self.mango_client.authority.clone()],
config: self config: self
.mango_client .mango_client
.client .client

View File

@ -38,16 +38,6 @@ async function forceWithdrawTokens(): Promise<void> {
const group = await client.getGroup(new PublicKey(GROUP_PK)); const group = await client.getGroup(new PublicKey(GROUP_PK));
const forceWithdrawBank = group.getFirstBankByTokenIndex(TOKEN_INDEX); const forceWithdrawBank = group.getFirstBankByTokenIndex(TOKEN_INDEX);
if (forceWithdrawBank.reduceOnly != 2) {
throw new Error(
`Unexpected reduce only state ${forceWithdrawBank.reduceOnly}`,
);
}
if (!forceWithdrawBank.forceWithdraw) {
throw new Error(
`Unexpected force withdraw state ${forceWithdrawBank.forceWithdraw}`,
);
}
// Get all mango accounts with deposits for given token // Get all mango accounts with deposits for given token
const mangoAccountsWithDeposits = ( const mangoAccountsWithDeposits = (

View File

@ -725,7 +725,11 @@ export class MangoClient {
vault: bank.vault, vault: bank.vault,
oracle: bank.oracle, oracle: bank.oracle,
ownerAtaTokenAccount, ownerAtaTokenAccount,
alternateOwnerTokenAccount, alternateOwnerTokenAccount: alternateOwnerTokenAccount.equals(
PublicKey.default,
)
? ownerAtaTokenAccount
: alternateOwnerTokenAccount,
}) })
.instruction(); .instruction();
return await this.sendAndConfirmTransactionForGroup(group, [ return await this.sendAndConfirmTransactionForGroup(group, [