Clarkeni/perp trade logging (#535)
* Emit the slot corresponding to the oracle price to PerpUpdateFundingLog. * Emit a new FilledPerpOrderLog consisting of just the group, perp market and seq num. This will be used to correlate perp fills to the transactions they were matched (not consumed).
This commit is contained in:
parent
c813940054
commit
37ae7549fb
|
@ -30,12 +30,13 @@ pub fn perp_place_order(
|
|||
asks: ctx.accounts.asks.load_mut()?,
|
||||
};
|
||||
|
||||
oracle_price = perp_market.oracle_price(
|
||||
let oracle_slot;
|
||||
(oracle_price, oracle_slot) = perp_market.oracle_price_and_slot(
|
||||
&AccountInfoRef::borrow(ctx.accounts.oracle.as_ref())?,
|
||||
None, // staleness checked in health
|
||||
)?;
|
||||
|
||||
perp_market.update_funding_and_stable_price(&book, oracle_price, now_ts)?;
|
||||
perp_market.update_funding_and_stable_price(&book, oracle_price, oracle_slot, now_ts)?;
|
||||
}
|
||||
|
||||
let mut account = ctx.accounts.account.load_full_mut()?;
|
||||
|
|
|
@ -14,12 +14,12 @@ pub fn perp_update_funding(ctx: Context<PerpUpdateFunding>) -> Result<()> {
|
|||
};
|
||||
|
||||
let now_slot = Clock::get()?.slot;
|
||||
let oracle_price = perp_market.oracle_price(
|
||||
let (oracle_price, oracle_slot) = perp_market.oracle_price_and_slot(
|
||||
&AccountInfoRef::borrow(ctx.accounts.oracle.as_ref())?,
|
||||
Some(now_slot),
|
||||
)?;
|
||||
|
||||
perp_market.update_funding_and_stable_price(&book, oracle_price, now_ts)?;
|
||||
perp_market.update_funding_and_stable_price(&book, oracle_price, oracle_slot, now_ts)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -144,6 +144,7 @@ pub struct PerpUpdateFundingLog {
|
|||
pub long_funding: i128,
|
||||
pub short_funding: i128,
|
||||
pub price: i128,
|
||||
pub oracle_slot: u64,
|
||||
pub stable_price: i128,
|
||||
pub fees_accrued: i128,
|
||||
pub fees_settled: i128,
|
||||
|
@ -371,3 +372,10 @@ pub struct AccountBuybackFeesWithMngoLog {
|
|||
pub mngo_buyback_price: i128,
|
||||
pub oracle_price: i128,
|
||||
}
|
||||
|
||||
#[event]
|
||||
pub struct FilledPerpOrderLog {
|
||||
pub mango_group: Pubkey,
|
||||
pub perp_market_index: u16,
|
||||
pub seq_num: u64,
|
||||
}
|
||||
|
|
|
@ -789,12 +789,14 @@ impl Bank {
|
|||
staleness_slot: Option<u64>,
|
||||
) -> Result<I80F48> {
|
||||
require_keys_eq!(self.oracle, *oracle_acc.key());
|
||||
oracle::oracle_price(
|
||||
let (price, _) = oracle::oracle_price_and_slot(
|
||||
oracle_acc,
|
||||
&self.oracle_config,
|
||||
self.mint_decimals,
|
||||
staleness_slot,
|
||||
)
|
||||
)?;
|
||||
|
||||
Ok(price)
|
||||
}
|
||||
|
||||
pub fn stable_price(&self) -> I80F48 {
|
||||
|
|
|
@ -135,18 +135,18 @@ pub fn determine_oracle_type(acc_info: &impl KeyedAccountReader) -> Result<Oracl
|
|||
/// This currently assumes that quote decimals is 6, like for USDC.
|
||||
///
|
||||
/// Pass `staleness_slot` = None to skip the staleness check
|
||||
pub fn oracle_price(
|
||||
pub fn oracle_price_and_slot(
|
||||
acc_info: &impl KeyedAccountReader,
|
||||
config: &OracleConfig,
|
||||
base_decimals: u8,
|
||||
staleness_slot: Option<u64>,
|
||||
) -> Result<I80F48> {
|
||||
) -> Result<(I80F48, u64)> {
|
||||
let data = &acc_info.data();
|
||||
let oracle_type = determine_oracle_type(acc_info)?;
|
||||
let staleness_slot = staleness_slot.unwrap_or(0);
|
||||
|
||||
Ok(match oracle_type {
|
||||
OracleType::Stub => acc_info.load::<StubOracle>()?.price,
|
||||
OracleType::Stub => (acc_info.load::<StubOracle>()?.price, 0),
|
||||
OracleType::Pyth => {
|
||||
let price_account = pyth_sdk_solana::state::load_price_account(data).unwrap();
|
||||
let price_data = price_account.to_price();
|
||||
|
@ -187,7 +187,7 @@ pub fn oracle_price(
|
|||
|
||||
let decimals = (price_account.expo as i8) + QUOTE_DECIMALS - (base_decimals as i8);
|
||||
let decimal_adj = power_of_ten(decimals);
|
||||
price * decimal_adj
|
||||
(price * decimal_adj, last_slot)
|
||||
}
|
||||
OracleType::SwitchboardV2 => {
|
||||
fn from_foreign_error(e: impl std::fmt::Display) -> Error {
|
||||
|
@ -233,7 +233,7 @@ pub fn oracle_price(
|
|||
|
||||
let decimals = QUOTE_DECIMALS - (base_decimals as i8);
|
||||
let decimal_adj = power_of_ten(decimals);
|
||||
price * decimal_adj
|
||||
(price * decimal_adj, round_open_slot)
|
||||
}
|
||||
OracleType::SwitchboardV1 => {
|
||||
let result = FastRoundResultAccountData::deserialize(data).unwrap();
|
||||
|
@ -269,7 +269,7 @@ pub fn oracle_price(
|
|||
|
||||
let decimals = QUOTE_DECIMALS - (base_decimals as i8);
|
||||
let decimal_adj = power_of_ten(decimals);
|
||||
price * decimal_adj
|
||||
(price * decimal_adj, round_open_slot)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::logs::FilledPerpOrderLog;
|
||||
use crate::state::MangoAccountRefMut;
|
||||
use crate::{
|
||||
error::*,
|
||||
|
@ -155,6 +156,12 @@ impl<'a> Orderbook<'a> {
|
|||
);
|
||||
event_queue.push_back(cast(fill)).unwrap();
|
||||
limit -= 1;
|
||||
|
||||
emit!(FilledPerpOrderLog {
|
||||
mango_group: market.group.key(),
|
||||
perp_market_index: market.perp_market_index,
|
||||
seq_num: event_queue.header.seq_num,
|
||||
});
|
||||
}
|
||||
let total_quote_lots_taken = order.max_quote_lots - remaining_quote_lots;
|
||||
let total_base_lots_taken = order.max_base_lots - remaining_base_lots;
|
||||
|
|
|
@ -241,7 +241,23 @@ impl PerpMarket {
|
|||
staleness_slot: Option<u64>,
|
||||
) -> Result<I80F48> {
|
||||
require_keys_eq!(self.oracle, *oracle_acc.key());
|
||||
oracle::oracle_price(
|
||||
let (price, _) = oracle::oracle_price_and_slot(
|
||||
oracle_acc,
|
||||
&self.oracle_config,
|
||||
self.base_decimals,
|
||||
staleness_slot,
|
||||
)?;
|
||||
|
||||
Ok(price)
|
||||
}
|
||||
|
||||
pub fn oracle_price_and_slot(
|
||||
&self,
|
||||
oracle_acc: &impl KeyedAccountReader,
|
||||
staleness_slot: Option<u64>,
|
||||
) -> Result<(I80F48, u64)> {
|
||||
require_keys_eq!(self.oracle, *oracle_acc.key());
|
||||
oracle::oracle_price_and_slot(
|
||||
oracle_acc,
|
||||
&self.oracle_config,
|
||||
self.base_decimals,
|
||||
|
@ -258,6 +274,7 @@ impl PerpMarket {
|
|||
&mut self,
|
||||
book: &Orderbook,
|
||||
oracle_price: I80F48,
|
||||
oracle_slot: u64,
|
||||
now_ts: u64,
|
||||
) -> Result<()> {
|
||||
if now_ts <= self.funding_last_updated {
|
||||
|
@ -315,6 +332,7 @@ impl PerpMarket {
|
|||
long_funding: self.long_funding.to_bits(),
|
||||
short_funding: self.short_funding.to_bits(),
|
||||
price: oracle_price.to_bits(),
|
||||
oracle_slot: oracle_slot,
|
||||
stable_price: self.stable_price().to_bits(),
|
||||
fees_accrued: self.fees_accrued.to_bits(),
|
||||
fees_settled: self.fees_settled.to_bits(),
|
||||
|
|
Loading…
Reference in New Issue