Add a ComputeHealth instruction

This way the client can ask for simulation to determine an account's
health.
This commit is contained in:
Christian Kamm 2022-06-20 17:55:30 +02:00
parent 712bece0b2
commit 6ff4ff5910
6 changed files with 88 additions and 2 deletions

View File

@ -0,0 +1,21 @@
use crate::state::*;
use anchor_lang::prelude::*;
use fixed::types::I80F48;
#[derive(Accounts)]
pub struct ComputeHealth<'info> {
pub group: AccountLoader<'info, Group>,
#[account(
has_one = group,
)]
pub account: AccountLoader<'info, MangoAccount>,
}
pub fn compute_health(ctx: Context<ComputeHealth>, health_type: HealthType) -> Result<I80F48> {
let account = ctx.accounts.account.load()?;
let health = compute_health_from_fixed_accounts(&account, health_type, ctx.remaining_accounts)?;
msg!("health: {}", health);
Ok(health)
}

View File

@ -3,6 +3,7 @@ pub use benchmark::*;
pub use close_account::*;
pub use close_group::*;
pub use close_stub_oracle::*;
pub use compute_health::*;
pub use create_account::*;
pub use create_group::*;
pub use create_stub_oracle::*;
@ -36,6 +37,7 @@ mod benchmark;
mod close_account;
mod close_group;
mod close_stub_oracle;
mod compute_health;
mod create_account;
mod create_group;
mod create_stub_oracle;

View File

@ -17,7 +17,9 @@ mod serum3_cpi;
pub mod state;
pub mod types;
use state::{OracleConfig, OrderType, PerpMarketIndex, Serum3MarketIndex, Side, TokenIndex};
use state::{
HealthType, OracleConfig, OrderType, PerpMarketIndex, Serum3MarketIndex, Side, TokenIndex,
};
declare_id!("m43thNJ58XCjL798ZSq6JGAG1BnWskhdq5or6kcnfsD");
@ -340,6 +342,10 @@ pub mod mango_v4 {
// resolve_banktruptcy
pub fn compute_health(ctx: Context<ComputeHealth>, health_type: HealthType) -> Result<I80F48> {
instructions::compute_health(ctx, health_type)
}
///
/// benchmark
///

View File

@ -258,7 +258,7 @@ impl<'a, 'info> AccountRetriever for ScanningAccountRetriever<'a, 'info> {
/// slightly smaller weights for the liabilities. Zero is used as the bright line for both
/// i.e. if your init health falls below zero, you cannot open new positions and if your maint. health
/// falls below zero you will be liquidated.
#[derive(PartialEq, Copy, Clone)]
#[derive(PartialEq, Copy, Clone, AnchorSerialize, AnchorDeserialize)]
pub enum HealthType {
Init,
Maint,

View File

@ -2059,3 +2059,47 @@ impl ClientInstruction for UpdateIndexInstruction {
vec![]
}
}
pub struct ComputeHealthInstruction {
pub account: Pubkey,
pub health_type: HealthType,
}
#[async_trait::async_trait(?Send)]
impl ClientInstruction for ComputeHealthInstruction {
type Accounts = mango_v4::accounts::ComputeHealth;
type Instruction = mango_v4::instruction::ComputeHealth;
async fn to_instruction(
&self,
account_loader: impl ClientAccountLoader + 'async_trait,
) -> (Self::Accounts, instruction::Instruction) {
let program_id = mango_v4::id();
let instruction = Self::Instruction {
health_type: self.health_type,
};
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
let health_check_metas = derive_health_check_remaining_account_metas(
&account_loader,
&account,
None,
false,
None,
)
.await;
let accounts = Self::Accounts {
group: account.group,
account: self.account,
};
let mut instruction = make_instruction(program_id, &accounts, instruction);
instruction.accounts.extend(health_check_metas.into_iter());
(accounts, instruction)
}
fn signers(&self) -> Vec<&Keypair> {
vec![]
}
}

View File

@ -84,6 +84,19 @@ async fn test_basic() -> Result<(), TransportError> {
);
}
//
// TEST: Compute the account health
//
send_tx(
solana,
ComputeHealthInstruction {
account,
health_type: HealthType::Init,
},
)
.await
.unwrap();
//
// TEST: Withdraw funds
//