mango-v4/lib/client/src/health_cache.rs

100 lines
3.4 KiB
Rust

use crate::{AccountFetcher, FallbackOracleConfig, MangoGroupContext};
use anyhow::Context;
use futures::{stream, StreamExt, TryStreamExt};
use mango_v4::accounts_zerocopy::KeyedAccountSharedData;
use mango_v4::health::{FixedOrderAccountRetriever, HealthCache};
use mango_v4::state::{pyth_mainnet_sol_oracle, pyth_mainnet_usdc_oracle, MangoAccountValue};
use std::collections::HashMap;
use std::time::{SystemTime, UNIX_EPOCH};
pub async fn new(
context: &MangoGroupContext,
fallback_config: &FallbackOracleConfig,
account_fetcher: &dyn AccountFetcher,
account: &MangoAccountValue,
) -> anyhow::Result<HealthCache> {
let active_token_len = account.active_token_positions().count();
let active_perp_len = account.active_perp_positions().count();
let fallback_keys = context
.derive_fallback_oracle_keys(fallback_config, account_fetcher)
.await?;
let (metas, _health_cu) = context.derive_health_check_remaining_account_metas(
account,
vec![],
vec![],
vec![],
fallback_keys,
)?;
let accounts: anyhow::Result<Vec<KeyedAccountSharedData>> = stream::iter(metas.iter())
.then(|meta| async {
Ok(KeyedAccountSharedData::new(
meta.pubkey,
account_fetcher.fetch_raw_account(&meta.pubkey).await?,
))
})
.try_collect()
.await;
let retriever = FixedOrderAccountRetriever {
ais: accounts?,
n_banks: active_token_len,
n_perps: active_perp_len,
begin_perp: active_token_len * 2,
begin_serum3: active_token_len * 2 + active_perp_len * 2,
staleness_slot: None,
begin_fallback_oracles: metas.len(),
usdc_oracle_index: metas
.iter()
.position(|m| m.pubkey == pyth_mainnet_usdc_oracle::ID),
sol_oracle_index: metas
.iter()
.position(|m| m.pubkey == pyth_mainnet_sol_oracle::ID),
};
let now_ts = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
mango_v4::health::new_health_cache(&account.borrow(), &retriever, now_ts)
.context("make health cache")
}
pub fn new_sync(
context: &MangoGroupContext,
account_fetcher: &crate::chain_data::AccountFetcher,
account: &MangoAccountValue,
) -> anyhow::Result<HealthCache> {
let active_token_len = account.active_token_positions().count();
let active_perp_len = account.active_perp_positions().count();
let (metas, _health_cu) = context.derive_health_check_remaining_account_metas(
account,
vec![],
vec![],
vec![],
HashMap::new(),
)?;
let accounts = metas
.iter()
.map(|meta| {
Ok(KeyedAccountSharedData::new(
meta.pubkey,
account_fetcher.fetch_raw(&meta.pubkey)?,
))
})
.collect::<anyhow::Result<Vec<_>>>()?;
let retriever = FixedOrderAccountRetriever {
ais: accounts,
n_banks: active_token_len,
n_perps: active_perp_len,
begin_perp: active_token_len * 2,
begin_serum3: active_token_len * 2 + active_perp_len * 2,
staleness_slot: None,
begin_fallback_oracles: metas.len(),
usdc_oracle_index: None,
sol_oracle_index: None,
};
let now_ts = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
mango_v4::health::new_health_cache(&account.borrow(), &retriever, now_ts)
.context("make health cache")
}