Liq: format, error handling, logging
This commit is contained in:
parent
0158239a56
commit
74873ad46b
|
@ -10,7 +10,7 @@ use mango_v4::state::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::chain_data::ChainData, anyhow::Context, fixed::types::I80F48, log::*,
|
crate::chain_data::ChainData, anyhow::Context, fixed::types::I80F48,
|
||||||
solana_sdk::account::AccountSharedData, solana_sdk::pubkey::Pubkey,
|
solana_sdk::account::AccountSharedData, solana_sdk::pubkey::Pubkey,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -111,6 +111,93 @@ pub fn new_health_cache_(
|
||||||
new_health_cache(account, &retriever)
|
new_health_cache(account, &retriever)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn process_account(
|
||||||
|
mango_client: &MangoClient,
|
||||||
|
chain_data: &ChainData,
|
||||||
|
mint_infos: &HashMap<TokenIndex, Pubkey>,
|
||||||
|
perp_markets: &HashMap<PerpMarketIndex, Pubkey>,
|
||||||
|
pubkey: &Pubkey,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
// TODO: configurable
|
||||||
|
let min_health_ratio = I80F48::from_num(50.0f64);
|
||||||
|
|
||||||
|
let account = load_mango_account_from_chain::<MangoAccount>(chain_data, pubkey)?;
|
||||||
|
|
||||||
|
// compute maint health for account
|
||||||
|
let maint_health = new_health_cache_(chain_data, mint_infos, perp_markets, account)
|
||||||
|
.expect("always ok")
|
||||||
|
.health(HealthType::Maint);
|
||||||
|
|
||||||
|
// try liquidating
|
||||||
|
if maint_health.is_negative() {
|
||||||
|
// find asset and liab tokens
|
||||||
|
let mut tokens = account
|
||||||
|
.tokens
|
||||||
|
.iter_active()
|
||||||
|
.map(|token| {
|
||||||
|
let mint_info_pk = mint_infos.get(&token.token_index).expect("always Ok");
|
||||||
|
let mint_info =
|
||||||
|
load_mango_account_from_chain::<MintInfo>(chain_data, mint_info_pk)?;
|
||||||
|
let bank =
|
||||||
|
load_mango_account_from_chain::<Bank>(chain_data, &mint_info.first_bank())?;
|
||||||
|
let oracle = chain_data.account(&mint_info.oracle)?;
|
||||||
|
let price = oracle_price(
|
||||||
|
&KeyedAccountSharedData::new(mint_info.oracle, oracle.clone()),
|
||||||
|
bank.oracle_config.conf_filter,
|
||||||
|
bank.mint_decimals,
|
||||||
|
)?;
|
||||||
|
Ok((token.token_index, bank, token.native(bank) * price))
|
||||||
|
})
|
||||||
|
.collect::<anyhow::Result<Vec<(TokenIndex, &Bank, I80F48)>>>()?;
|
||||||
|
tokens.sort_by(|a, b| a.2.cmp(&b.2));
|
||||||
|
if tokens.len() < 2 {
|
||||||
|
anyhow::bail!("mango account {}, has less than 2 active tokens", pubkey);
|
||||||
|
}
|
||||||
|
let (asset_token_index, _asset_bank, _asset_price) = tokens.last().unwrap();
|
||||||
|
let (liab_token_index, _liab_bank, _liab_price) = tokens.first().unwrap();
|
||||||
|
|
||||||
|
let max_liab_transfer = {
|
||||||
|
let liqor = load_mango_account_from_chain::<MangoAccount>(
|
||||||
|
chain_data,
|
||||||
|
&mango_client.mango_account_cache.0,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let health_cache =
|
||||||
|
new_health_cache_(chain_data, mint_infos, perp_markets, liqor).expect("always ok");
|
||||||
|
|
||||||
|
health_cache.max_swap_source_for_health_ratio(
|
||||||
|
*liab_token_index,
|
||||||
|
*asset_token_index,
|
||||||
|
min_health_ratio,
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO: log liqor's assets in UI form
|
||||||
|
// TODO: log liquee's liab_needed, need to refactor program code to be able to be accessed from client side
|
||||||
|
// TODO: swap inherited liabs to desired asset for liqor
|
||||||
|
// TODO: hook ChainData into MangoClient
|
||||||
|
// TODO: liq_token_with_token() re-gets the liqor account via rpc unnecessarily
|
||||||
|
//
|
||||||
|
let sig = mango_client
|
||||||
|
.liq_token_with_token(
|
||||||
|
(pubkey, account),
|
||||||
|
*asset_token_index,
|
||||||
|
*liab_token_index,
|
||||||
|
max_liab_transfer,
|
||||||
|
)
|
||||||
|
.context("sending liq_token_with_token")?;
|
||||||
|
log::info!(
|
||||||
|
"Liquidated {}..., maint_health was {}, tx sig {:?}",
|
||||||
|
&pubkey.to_string()[..3],
|
||||||
|
maint_health,
|
||||||
|
sig
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn process_accounts<'a>(
|
pub fn process_accounts<'a>(
|
||||||
mango_client: &MangoClient,
|
mango_client: &MangoClient,
|
||||||
|
@ -119,96 +206,11 @@ pub fn process_accounts<'a>(
|
||||||
mint_infos: &HashMap<TokenIndex, Pubkey>,
|
mint_infos: &HashMap<TokenIndex, Pubkey>,
|
||||||
perp_markets: &HashMap<PerpMarketIndex, Pubkey>,
|
perp_markets: &HashMap<PerpMarketIndex, Pubkey>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
// TODO: configurable
|
|
||||||
let min_health_ratio = I80F48::from_num(50.0f64);
|
|
||||||
|
|
||||||
for pubkey in accounts {
|
for pubkey in accounts {
|
||||||
let account_result = load_mango_account_from_chain::<MangoAccount>(chain_data, pubkey);
|
match process_account(mango_client, chain_data, mint_infos, perp_markets, pubkey) {
|
||||||
let account = match account_result {
|
Err(err) => log::error!("error liquidating account {}: {:?}", pubkey, err),
|
||||||
Ok(account) => account,
|
_ => {}
|
||||||
Err(err) => {
|
|
||||||
warn!("could not load account {}: {:?}", pubkey, err);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// compute maint health for account
|
|
||||||
let maint_health = new_health_cache_(chain_data, mint_infos, perp_markets, account)
|
|
||||||
.expect("always ok")
|
|
||||||
.health(HealthType::Maint);
|
|
||||||
|
|
||||||
// try liquidating
|
|
||||||
if maint_health.is_negative() {
|
|
||||||
// find asset and liab tokens
|
|
||||||
let mut tokens = account
|
|
||||||
.tokens
|
|
||||||
.iter_active()
|
|
||||||
.map(|token| {
|
|
||||||
let mint_info_pk = mint_infos.get(&token.token_index).expect("always Ok");
|
|
||||||
let mint_info =
|
|
||||||
load_mango_account_from_chain::<MintInfo>(chain_data, mint_info_pk)?;
|
|
||||||
let bank =
|
|
||||||
load_mango_account_from_chain::<Bank>(chain_data, &mint_info.first_bank())?;
|
|
||||||
let oracle = chain_data.account(&mint_info.oracle)?;
|
|
||||||
let price = oracle_price(
|
|
||||||
&KeyedAccountSharedData::new(mint_info.oracle, oracle.clone()),
|
|
||||||
bank.oracle_config.conf_filter,
|
|
||||||
bank.mint_decimals,
|
|
||||||
)?;
|
|
||||||
Ok((token.token_index, bank, token.native(bank) * price))
|
|
||||||
})
|
|
||||||
.collect::<anyhow::Result<Vec<(TokenIndex, &Bank, I80F48)>>>()?;
|
|
||||||
tokens.sort_by(|a, b| a.2.cmp(&b.2));
|
|
||||||
if tokens.len() < 2 {
|
|
||||||
anyhow::bail!(format!(
|
|
||||||
"mango account {}, has less than 2 active tokens",
|
|
||||||
pubkey
|
|
||||||
));
|
|
||||||
}
|
|
||||||
let (asset_token_index, _asset_bank, _asset_price) = tokens.last().unwrap();
|
|
||||||
let (liab_token_index, _liab_bank, _liab_price) = tokens.first().unwrap();
|
|
||||||
|
|
||||||
let max_liab_transfer = {
|
|
||||||
let liqor = load_mango_account_from_chain::<MangoAccount>(
|
|
||||||
chain_data,
|
|
||||||
&mango_client.mango_account_cache.0,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let health_cache = new_health_cache_(chain_data, mint_infos, perp_markets, liqor)
|
|
||||||
.expect("always ok");
|
|
||||||
|
|
||||||
health_cache.max_swap_source_for_health_ratio(
|
|
||||||
*liab_token_index,
|
|
||||||
*asset_token_index,
|
|
||||||
min_health_ratio,
|
|
||||||
)?
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// TODO: log liqor's assets in UI form
|
|
||||||
// TODO: log liquee's liab_needed, need to refactor program code to be able to be accessed from client side
|
|
||||||
// TODO: swap inherited liabs to desired asset for liqor
|
|
||||||
// TODO: hook ChainData into MangoClient
|
|
||||||
// TODO: liq_token_with_token() re-gets the liqor account via rpc unnecessarily
|
|
||||||
//
|
|
||||||
let sig = mango_client.liq_token_with_token(
|
|
||||||
(pubkey, account),
|
|
||||||
*asset_token_index,
|
|
||||||
*liab_token_index,
|
|
||||||
max_liab_transfer,
|
|
||||||
);
|
|
||||||
match sig {
|
|
||||||
Ok(sig) => log::info!(
|
|
||||||
"Liquidated {}..., maint_health was {}, tx sig {:?}",
|
|
||||||
&pubkey.to_string()[..3],
|
|
||||||
maint_health,
|
|
||||||
sig
|
|
||||||
),
|
|
||||||
Err(err) => {
|
|
||||||
log::error!("{:?}", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in New Issue