diff --git a/CHANGELOG.md b/CHANGELOG.md index 44b0cb3ef..a35cc366f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Features - program: add spot market pool ids ([#1250](https://github.com/drift-labs/protocol-v2/pull/1250)) -- program: make oracle map work with different sources ([#1346](https://github.com/drift-labs/protocol-v2/pull/1346)) ### Fixes diff --git a/programs/drift/src/controller/funding.rs b/programs/drift/src/controller/funding.rs index a66d7c9cc..1cd15e38b 100644 --- a/programs/drift/src/controller/funding.rs +++ b/programs/drift/src/controller/funding.rs @@ -170,7 +170,7 @@ pub fn update_funding_rate( // Pause funding if oracle is invalid or if mark/oracle spread is too divergent let block_funding_rate_update = oracle::block_operation( market, - oracle_map.get_price_data(&market.oracle_id())?, + oracle_map.get_price_data(&market.amm.oracle)?, guard_rails, reserve_price, slot, @@ -186,7 +186,7 @@ pub fn update_funding_rate( !funding_paused && !block_funding_rate_update && (time_until_next_update == 0); if valid_funding_update { - let oracle_price_data = oracle_map.get_price_data(&market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&market.amm.oracle)?; let sanitize_clamp_denominator = market.get_sanitize_clamp_denominator()?; let oracle_price_twap = amm::update_oracle_price_twap( diff --git a/programs/drift/src/controller/liquidation.rs b/programs/drift/src/controller/liquidation.rs index 3b43f4f32..27727bda8 100644 --- a/programs/drift/src/controller/liquidation.rs +++ b/programs/drift/src/controller/liquidation.rs @@ -201,7 +201,7 @@ pub fn liquidate_perp( )?; let mut market = perp_market_map.get_ref_mut(&market_index)?; - let oracle_price_data = oracle_map.get_price_data(&market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&market.amm.oracle)?; update_amm_and_check_validity( &mut market, @@ -340,9 +340,7 @@ pub fn liquidate_perp( let market = perp_market_map.get_ref(&market_index)?; let quote_spot_market = spot_market_map.get_ref(&market.quote_spot_market_index)?; - let quote_oracle_price = oracle_map - .get_price_data("e_spot_market.oracle_id())? - .price; + let quote_oracle_price = oracle_map.get_price_data("e_spot_market.oracle)?.price; let liquidator_fee = market.liquidator_fee; let if_liquidation_fee = calculate_perp_if_fee( intermediate_margin_calculation.tracked_market_margin_shortage(margin_shortage)?, @@ -789,7 +787,7 @@ pub fn liquidate_perp_with_fill( )?; let mut market = perp_market_map.get_ref_mut(&market_index)?; - let oracle_price_data = oracle_map.get_price_data(&market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&market.amm.oracle)?; update_amm_and_check_validity( &mut market, @@ -917,9 +915,7 @@ pub fn liquidate_perp_with_fill( let market = perp_market_map.get_ref(&market_index)?; let quote_spot_market = spot_market_map.get_ref(&market.quote_spot_market_index)?; - let quote_oracle_price = oracle_map - .get_price_data("e_spot_market.oracle_id())? - .price; + let quote_oracle_price = oracle_map.get_price_data("e_spot_market.oracle)?.price; let liquidator_fee = market.liquidator_fee; let if_liquidation_fee = calculate_perp_if_fee( intermediate_margin_calculation.tracked_market_margin_shortage(margin_shortage)?, @@ -1237,7 +1233,7 @@ pub fn liquidate_spot( let (asset_amount, asset_price, asset_decimals, asset_weight, asset_liquidation_multiplier) = { let mut asset_market = spot_market_map.get_ref_mut(&asset_market_index)?; let (asset_price_data, validity_guard_rails) = - oracle_map.get_price_data_and_guard_rails(&asset_market.oracle_id())?; + oracle_map.get_price_data_and_guard_rails(&asset_market.oracle)?; update_spot_market_and_check_validity( &mut asset_market, @@ -1286,7 +1282,7 @@ pub fn liquidate_spot( ) = { let mut liability_market = spot_market_map.get_ref_mut(&liability_market_index)?; let (liability_price_data, validity_guard_rails) = - oracle_map.get_price_data_and_guard_rails(&liability_market.oracle_id())?; + oracle_map.get_price_data_and_guard_rails(&liability_market.oracle)?; update_spot_market_and_check_validity( &mut liability_market, @@ -1824,9 +1820,7 @@ pub fn liquidate_borrow_for_perp_pnl( let market = perp_market_map.get_ref(&perp_market_index)?; let quote_spot_market = spot_market_map.get_ref(&market.quote_spot_market_index)?; - let quote_price = oracle_map - .get_price_data("e_spot_market.oracle_id())? - .price; + let quote_price = oracle_map.get_price_data("e_spot_market.oracle)?.price; let pnl_asset_weight = market.get_unrealized_asset_weight(pnl, MarginRequirementType::Maintenance)?; @@ -1852,7 +1846,7 @@ pub fn liquidate_borrow_for_perp_pnl( ) = { let mut liability_market = spot_market_map.get_ref_mut(&liability_market_index)?; let (liability_price_data, validity_guard_rails) = - oracle_map.get_price_data_and_guard_rails(&liability_market.oracle_id())?; + oracle_map.get_price_data_and_guard_rails(&liability_market.oracle)?; update_spot_market_and_check_validity( &mut liability_market, @@ -1946,7 +1940,7 @@ pub fn liquidate_borrow_for_perp_pnl( if intermediate_margin_calculation.can_exit_liquidation()? { let market = perp_market_map.get_ref(&perp_market_index)?; - let market_oracle_price = oracle_map.get_price_data(&market.oracle_id())?.price; + let market_oracle_price = oracle_map.get_price_data(&market.amm.oracle)?.price; emit!(LiquidationRecord { ts: now, @@ -2137,7 +2131,7 @@ pub fn liquidate_borrow_for_perp_pnl( let market_oracle_price = { let market = perp_market_map.get_ref_mut(&perp_market_index)?; - oracle_map.get_price_data(&market.oracle_id())?.price + oracle_map.get_price_data(&market.amm.oracle)?.price }; emit!(LiquidationRecord { @@ -2282,7 +2276,7 @@ pub fn liquidate_perp_pnl_for_deposit( ) = { let mut asset_market = spot_market_map.get_ref_mut(&asset_market_index)?; let (asset_price_data, validity_guard_rails) = - oracle_map.get_price_data_and_guard_rails(&asset_market.oracle_id())?; + oracle_map.get_price_data_and_guard_rails(&asset_market.oracle)?; update_spot_market_and_check_validity( &mut asset_market, @@ -2359,9 +2353,7 @@ pub fn liquidate_perp_pnl_for_deposit( let market = perp_market_map.get_ref(&perp_market_index)?; let quote_spot_market = spot_market_map.get_ref(&market.quote_spot_market_index)?; - let quote_price = oracle_map - .get_price_data("e_spot_market.oracle_id())? - .price; + let quote_price = oracle_map.get_price_data("e_spot_market.oracle)?.price; ( unsettled_pnl.unsigned_abs(), @@ -2438,7 +2430,7 @@ pub fn liquidate_perp_pnl_for_deposit( if exiting_liq_territory || is_contract_tier_violation { let market = perp_market_map.get_ref(&perp_market_index)?; - let market_oracle_price = oracle_map.get_price_data(&market.oracle_id())?.price; + let market_oracle_price = oracle_map.get_price_data(&market.amm.oracle)?.price; emit!(LiquidationRecord { ts: now, @@ -2641,7 +2633,7 @@ pub fn liquidate_perp_pnl_for_deposit( let market_oracle_price = { let market = perp_market_map.get_ref_mut(&perp_market_index)?; - oracle_map.get_price_data(&market.oracle_id())?.price + oracle_map.get_price_data(&market.amm.oracle)?.price }; emit!(LiquidationRecord { @@ -2767,7 +2759,7 @@ pub fn resolve_perp_bankruptcy( // move if payment to pnl pool let spot_market = &mut spot_market_map.get_ref_mut("E_SPOT_MARKET_INDEX)?; - let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle)?; update_spot_market_cumulative_interest(spot_market, Some(oracle_price_data), now)?; update_spot_balances( @@ -2988,7 +2980,7 @@ pub fn resolve_spot_bankruptcy( { let mut spot_market = spot_market_map.get_ref_mut(&market_index)?; - let oracle_price_data = &oracle_map.get_price_data(&spot_market.oracle_id())?; + let oracle_price_data = &oracle_map.get_price_data(&spot_market.oracle)?; let quote_social_loss = get_token_value( -borrow_amount.cast()?, spot_market.decimals, diff --git a/programs/drift/src/controller/liquidation/tests.rs b/programs/drift/src/controller/liquidation/tests.rs index c04b8e7dd..116f47118 100644 --- a/programs/drift/src/controller/liquidation/tests.rs +++ b/programs/drift/src/controller/liquidation/tests.rs @@ -775,10 +775,7 @@ pub mod liquidate_perp { margin_requirement_plus_buffer ); - let oracle_price = oracle_map - .get_price_data(&(oracle_price_key, OracleSource::Pyth)) - .unwrap() - .price; + let oracle_price = oracle_map.get_price_data(&oracle_price_key).unwrap().price; let perp_value = calculate_base_asset_value_with_oracle_price( user.perp_positions[0].base_asset_amount as i128, @@ -2360,10 +2357,7 @@ pub mod liquidate_perp { margin_requirement_plus_buffer ); - let oracle_price = oracle_map - .get_price_data(&(oracle_price_key, OracleSource::Pyth)) - .unwrap() - .price; + let oracle_price = oracle_map.get_price_data(&oracle_price_key).unwrap().price; let perp_value = calculate_base_asset_value_with_oracle_price( user.perp_positions[0].base_asset_amount as i128, @@ -3680,9 +3674,7 @@ pub mod liquidate_spot { &user.spot_positions[1].balance_type, ) .unwrap(); - let oracle_price_data = oracle_map - .get_price_data(&(sol_oracle_price_key, OracleSource::Pyth)) - .unwrap(); + let oracle_price_data = oracle_map.get_price_data(&sol_oracle_price_key).unwrap(); let token_value = get_token_value(token_amount as i128, 6, oracle_price_data.price).unwrap(); @@ -4892,9 +4884,7 @@ pub mod liquidate_borrow_for_perp_pnl { &user.spot_positions[0].balance_type, ) .unwrap(); - let oracle_price_data = oracle_map - .get_price_data(&(sol_oracle_price_key, OracleSource::Pyth)) - .unwrap(); + let oracle_price_data = oracle_map.get_price_data(&sol_oracle_price_key).unwrap(); let token_value = get_token_value(token_amount as i128, 6, oracle_price_data.price).unwrap(); diff --git a/programs/drift/src/controller/lp.rs b/programs/drift/src/controller/lp.rs index e9e3f37e3..69761369a 100644 --- a/programs/drift/src/controller/lp.rs +++ b/programs/drift/src/controller/lp.rs @@ -382,7 +382,7 @@ pub fn remove_perp_lp_shares( ErrorCode::InsufficientLPTokens )?; - let oracle_price = oracle_map.get_price_data(&market.oracle_id())?.price; + let oracle_price = oracle_map.get_price_data(&market.amm.oracle)?.price; let (position_delta, pnl) = burn_lp_shares(position, &mut market, shares_to_burn, oracle_price)?; diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index 2a8085c4d..f90e587c0 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -217,7 +217,7 @@ pub fn place_perp_order( (existing_position_direction, base_asset_amount) }; - let oracle_price_data = oracle_map.get_price_data(&market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&market.amm.oracle)?; // updates auction params for crossing limit orders w/out auction duration // dont modify if it's a liquidation @@ -293,7 +293,7 @@ pub fn place_perp_order( padding: [0; 3], }; - let valid_oracle_price = Some(oracle_map.get_price_data(&market.oracle_id())?.price); + let valid_oracle_price = Some(oracle_map.get_price_data(&market.amm.oracle)?.price); match validate_order(&new_order, market, valid_oracle_price, slot) { Ok(()) => {} Err(ErrorCode::PlacePostOnlyLimitFailure) @@ -389,7 +389,7 @@ pub fn place_perp_order( taker_order, maker, maker_order, - oracle_map.get_price_data(&market.oracle_id())?.price, + oracle_map.get_price_data(&market.amm.oracle)?.price, )?; emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?; @@ -808,10 +808,10 @@ pub fn cancel_order( validate!(order_status == OrderStatus::Open, ErrorCode::OrderNotOpen)?; - let oracle_id = if is_perp_order { - perp_market_map.get_ref(&order_market_index)?.oracle_id() + let oracle = if is_perp_order { + perp_market_map.get_ref(&order_market_index)?.amm.oracle } else { - spot_market_map.get_ref(&order_market_index)?.oracle_id() + spot_market_map.get_ref(&order_market_index)?.oracle }; if !skip_log { @@ -837,7 +837,7 @@ pub fn cancel_order( taker_order, maker, maker_order, - oracle_map.get_price_data(&oracle_id)?.price, + oracle_map.get_price_data(&oracle)?.price, )?; emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?; } @@ -1186,7 +1186,7 @@ pub fn fill_perp_order( let (oracle_price_data, _oracle_validity) = oracle_map.get_price_data_and_validity( MarketType::Perp, market.market_index, - &market.oracle_id(), + &market.amm.oracle, market.amm.historical_oracle_data.last_oracle_price_twap, market.get_max_confidence_interval_multiplier()?, )?; @@ -1816,7 +1816,7 @@ fn fulfill_perp_order( let fulfillment_methods = { let market = perp_market_map.get_ref(&market_index)?; - let oracle_price = oracle_map.get_price_data(&market.oracle_id())?.price; + let oracle_price = oracle_map.get_price_data(&market.amm.oracle)?.price; determine_perp_fulfillment_methods( &user.orders[user_order_index], @@ -2424,7 +2424,7 @@ pub fn fulfill_perp_order_with_amm( taker_order, maker, maker_order, - oracle_map.get_price_data(&market.oracle_id())?.price, + oracle_map.get_price_data(&market.amm.oracle)?.price, )?; emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?; @@ -2501,7 +2501,7 @@ pub fn fulfill_perp_order_with_match( return Ok((0_u64, 0_u64, 0_u64)); } - let oracle_price = oracle_map.get_price_data(&market.oracle_id())?.price; + let oracle_price = oracle_map.get_price_data(&market.amm.oracle)?.price; let taker_direction: PositionDirection = taker.orders[taker_order_index].direction; let taker_price = if let Some(taker_limit_price) = taker_limit_price { @@ -2845,7 +2845,7 @@ pub fn fulfill_perp_order_with_match( Some(taker.orders[taker_order_index]), Some(*maker_key), Some(maker.orders[maker_order_index]), - oracle_map.get_price_data(&market.oracle_id())?.price, + oracle_map.get_price_data(&market.amm.oracle)?.price, )?; emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?; @@ -2964,7 +2964,7 @@ pub fn trigger_order( let (oracle_price_data, oracle_validity) = oracle_map.get_price_data_and_validity( MarketType::Perp, perp_market.market_index, - &perp_market.oracle_id(), + &perp_market.amm.oracle, perp_market .amm .historical_oracle_data @@ -3312,12 +3312,12 @@ pub fn burn_user_lp_shares_for_risk_reduction( let mut market = perp_market_map.get_ref_mut(&market_index)?; - let quote_oracle_id = spot_market_map + let quote_oracle = spot_market_map .get_ref(&market.quote_spot_market_index)? - .oracle_id(); - let quote_oracle_price = oracle_map.get_price_data("e_oracle_id)?.price; + .oracle; + let quote_oracle_price = oracle_map.get_price_data("e_oracle)?.price; - let oracle_price_data = oracle_map.get_price_data(&market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&market.amm.oracle)?; let oracle_price = if market.status == MarketStatus::Settlement { market.expiry_price @@ -3557,7 +3557,7 @@ pub fn place_spot_order( let token_amount = user.spot_positions[spot_position_index].get_token_amount(spot_market)?; let signed_token_amount = get_signed_token_amount(token_amount, &balance_type)?; - let oracle_price_data = *oracle_map.get_price_data(&spot_market.oracle_id())?; + let oracle_price_data = *oracle_map.get_price_data(&spot_market.oracle)?; // Increment open orders for existing position let (existing_position_direction, order_base_asset_amount) = { @@ -3842,11 +3842,7 @@ pub fn fill_spot_order( }; let oracle_price = oracle_map - .get_price_data( - &spot_market_map - .get_ref_mut(&order_market_index)? - .oracle_id(), - )? + .get_price_data(&spot_market_map.get_ref_mut(&order_market_index)?.oracle)? .price; let maker_order_info = get_spot_maker_orders_info( perp_market_map, @@ -3866,11 +3862,11 @@ pub fn fill_spot_order( { let mut quote_market = spot_market_map.get_quote_spot_market_mut()?; - let oracle_price_data = oracle_map.get_price_data("e_market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data("e_market.oracle)?; update_spot_market_cumulative_interest(&mut quote_market, Some(oracle_price_data), now)?; let mut base_market = spot_market_map.get_ref_mut(&order_market_index)?; - let oracle_price_data = oracle_map.get_price_data(&base_market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&base_market.oracle)?; update_spot_market_cumulative_interest(&mut base_market, Some(oracle_price_data), now)?; fulfillment_params.validate_markets(&base_market, "e_market)?; @@ -3986,7 +3982,7 @@ pub fn fill_spot_order( spot_market.get_precision(), )?; - let oracle_price = oracle_map.get_price_data(&spot_market.oracle_id())?.price; + let oracle_price = oracle_map.get_price_data(&spot_market.oracle)?.price; let oracle_twap_5min = spot_market .historical_oracle_data .last_oracle_price_twap_5min; @@ -4299,7 +4295,7 @@ fn fulfill_spot_order( } // todo come up with fallback price - let oracle_price = oracle_map.get_price_data(&base_market.oracle_id())?.price; + let oracle_price = oracle_map.get_price_data(&base_market.oracle)?.price; let limit_price = user.orders[user_order_index].get_limit_price( Some(oracle_price), None, @@ -4401,8 +4397,8 @@ fn fulfill_spot_order( .force_get_spot_position_mut(base_market_index)? .get_signed_token_amount(&base_market)?; - let quote_price = oracle_map.get_price_data("e_market.oracle_id())?.price; - let base_price = oracle_map.get_price_data(&base_market.oracle_id())?.price; + let quote_price = oracle_map.get_price_data("e_market.oracle)?.price; + let base_price = oracle_map.get_price_data(&base_market.oracle)?.price; let strict_quote_price = StrictOraclePrice::new( quote_price, @@ -4613,7 +4609,7 @@ pub fn fulfill_spot_order_with_match( } let market_index = taker.orders[taker_order_index].market_index; - let oracle_price = oracle_map.get_price_data(&base_market.oracle_id())?.price; + let oracle_price = oracle_map.get_price_data(&base_market.oracle)?.price; let taker_price = match taker.orders[taker_order_index].get_limit_price( Some(oracle_price), None, @@ -4915,7 +4911,7 @@ pub fn fulfill_spot_order_with_match( Some(taker.orders[taker_order_index]), Some(*maker_key), Some(maker.orders[maker_order_index]), - oracle_map.get_price_data(&base_market.oracle_id())?.price, + oracle_map.get_price_data(&base_market.oracle)?.price, )?; emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?; @@ -4951,7 +4947,7 @@ pub fn fulfill_spot_order_with_external_market( fee_structure: &FeeStructure, fulfillment_params: &mut dyn SpotFulfillmentParams, ) -> DriftResult<(u64, u64)> { - let oracle_price = oracle_map.get_price_data(&base_market.oracle_id())?.price; + let oracle_price = oracle_map.get_price_data(&base_market.oracle)?.price; let taker_price = taker.orders[taker_order_index].get_limit_price( Some(oracle_price), None, @@ -5258,7 +5254,7 @@ pub fn trigger_spot_order( let (oracle_price_data, oracle_validity) = oracle_map.get_price_data_and_validity( MarketType::Spot, spot_market.market_index, - &spot_market.oracle_id(), + &spot_market.oracle, spot_market.historical_oracle_data.last_oracle_price_twap, spot_market.get_max_confidence_interval_multiplier()?, )?; diff --git a/programs/drift/src/controller/orders/tests.rs b/programs/drift/src/controller/orders/tests.rs index f03d2fcae..e6899479e 100644 --- a/programs/drift/src/controller/orders/tests.rs +++ b/programs/drift/src/controller/orders/tests.rs @@ -47,7 +47,7 @@ pub mod fulfill_order_with_maker_order { }; use super::*; - use crate::state::oracle::{HistoricalOracleData, OracleSource}; + use crate::state::oracle::HistoricalOracleData; use std::str::FromStr; #[test] @@ -1758,7 +1758,7 @@ pub mod fulfill_order_with_maker_order { .get_price_data_and_validity( MarketType::Perp, market.market_index, - &(oracle_price_key, OracleSource::Pyth), + &oracle_price_key, market.amm.historical_oracle_data.last_oracle_price_twap, market.get_max_confidence_interval_multiplier().unwrap(), ) @@ -1909,12 +1909,7 @@ pub mod fulfill_order_with_maker_order { let taker_price = taker.orders[0] .get_limit_price( - Some( - oracle_map - .get_price_data(&(oracle_price_key, OracleSource::Pyth)) - .unwrap() - .price, - ), + Some(oracle_map.get_price_data(&oracle_price_key).unwrap().price), None, slot, 1, @@ -2064,12 +2059,7 @@ pub mod fulfill_order_with_maker_order { let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); - let valid_oracle_price = Some( - oracle_map - .get_price_data(&(oracle_price_key, OracleSource::Pyth)) - .unwrap() - .price, - ); + let valid_oracle_price = Some(oracle_map.get_price_data(&oracle_price_key).unwrap().price); let taker_limit_price = taker.orders[0] .get_limit_price( valid_oracle_price, @@ -2206,12 +2196,7 @@ pub mod fulfill_order_with_maker_order { let taker_price = taker.orders[0] .get_limit_price( - Some( - oracle_map - .get_price_data(&(oracle_price_key, OracleSource::Pyth)) - .unwrap() - .price, - ), + Some(oracle_map.get_price_data(&oracle_price_key).unwrap().price), None, slot, 1, diff --git a/programs/drift/src/controller/pnl.rs b/programs/drift/src/controller/pnl.rs index f1d88ed93..af4075807 100644 --- a/programs/drift/src/controller/pnl.rs +++ b/programs/drift/src/controller/pnl.rs @@ -70,7 +70,7 @@ pub fn settle_pnl( let mut market = perp_market_map.get_ref_mut(&market_index)?; - let oracle_price = oracle_map.get_price_data(&market.oracle_id())?.price; + let oracle_price = oracle_map.get_price_data(&market.amm.oracle)?.price; validate_market_within_price_band(&market, state, oracle_price)?; @@ -159,7 +159,7 @@ pub fn settle_pnl( let (_, oracle_validity) = oracle_map.get_price_data_and_validity( MarketType::Perp, perp_market.market_index, - &perp_market.oracle_id(), + &perp_market.amm.oracle, perp_market .amm .historical_oracle_data diff --git a/programs/drift/src/controller/pnl/delisting.rs b/programs/drift/src/controller/pnl/delisting.rs index eafbd2148..bd472fed7 100644 --- a/programs/drift/src/controller/pnl/delisting.rs +++ b/programs/drift/src/controller/pnl/delisting.rs @@ -2333,7 +2333,7 @@ pub mod delisting_test { assert_eq!(shorter.perp_positions[0].base_asset_amount, -1000000000000); assert_eq!(shorter.perp_positions[0].quote_asset_amount, 97000000000); - let oracle_price_data = oracle_map.get_price_data(&market.oracle_id()).unwrap(); + let oracle_price_data = oracle_map.get_price_data(&market.amm.oracle).unwrap(); let strict_quote_price = StrictOraclePrice::test(QUOTE_PRECISION_I64); let (perp_margin_requirement, weighted_pnl, _, _, _) = @@ -2413,7 +2413,7 @@ pub mod delisting_test { { let market = market_map.get_ref_mut(&0).unwrap(); - let oracle_price_data = oracle_map.get_price_data(&market.oracle_id()).unwrap(); + let oracle_price_data = oracle_map.get_price_data(&market.amm.oracle).unwrap(); let strict_quote_price = StrictOraclePrice::test(QUOTE_PRECISION_I64); let (perp_margin_requirement, weighted_pnl, _, _, _) = @@ -2496,7 +2496,7 @@ pub mod delisting_test { { let mut market = market_map.get_ref_mut(&0).unwrap(); - let oracle_price_data = oracle_map.get_price_data(&market.oracle_id()).unwrap(); + let oracle_price_data = oracle_map.get_price_data(&market.amm.oracle).unwrap(); assert_eq!(market.amm.quote_asset_amount, 97200000000); @@ -2588,7 +2588,7 @@ pub mod delisting_test { { let market = market_map.get_ref_mut(&0).unwrap(); - let oracle_price_data = oracle_map.get_price_data(&market.oracle_id()).unwrap(); + let oracle_price_data = oracle_map.get_price_data(&market.amm.oracle).unwrap(); assert_eq!(market.amm.quote_asset_amount, 20000010000 + 77199990000); @@ -2832,7 +2832,7 @@ pub mod delisting_test { assert_eq!(market.amm.total_social_loss, 3449991000); - let oracle_price_data = oracle_map.get_price_data(&market.oracle_id()).unwrap(); + let oracle_price_data = oracle_map.get_price_data(&market.amm.oracle).unwrap(); assert_eq!(oracle_price_data.price, 100 * PRICE_PRECISION_I64); let net_pnl = calculate_net_user_pnl(&market.amm, oracle_price_data.price).unwrap(); assert_eq!(net_pnl, 3449991000); diff --git a/programs/drift/src/controller/position/tests.rs b/programs/drift/src/controller/position/tests.rs index 12e9eec67..86dd443d3 100644 --- a/programs/drift/src/controller/position/tests.rs +++ b/programs/drift/src/controller/position/tests.rs @@ -17,7 +17,7 @@ use crate::math::constants::{ use crate::math::lp::calculate_settle_lp_metrics; use crate::math::position::swap_direction_to_close_position; use crate::math::repeg; -use crate::state::oracle::{OraclePriceData, PrelaunchOracle}; +use crate::state::oracle::OraclePriceData; use crate::state::oracle_map::OracleMap; use crate::state::perp_market::{AMMLiquiditySplit, PerpMarket, AMM}; use crate::state::perp_market_map::PerpMarketMap; @@ -110,19 +110,16 @@ fn amm_pred_expiry_price_yes_market_example() { // let mut oracle_map: OracleMap<'_> = // OracleMap::load_one(&jto_market_account_info, clock_slot, None).unwrap(); - let mut prelaunch_oracle_price = PrelaunchOracle { - price: PRICE_PRECISION_I64, - confidence: 1655389, - ..PrelaunchOracle::default() - }; + let mut sol_oracle_price: pyth::pc::Price = get_hardcoded_pyth_price(1000000, 6); + sol_oracle_price.agg.conf = 1655389; - let prelaunch_oracle_price_key: Pubkey = + let sol_oracle_price_key: Pubkey = Pubkey::from_str("3TVuLmEGBRfVgrmFRtYTheczXaaoRBwcHw1yibZHSeNA").unwrap(); - let drift_program = crate::id(); - create_anchor_account_info!( - prelaunch_oracle_price, - &prelaunch_oracle_price_key, - PrelaunchOracle, + let pyth_program = crate::ids::pyth_program::id(); + create_account_info!( + sol_oracle_price, + &sol_oracle_price_key, + &pyth_program, oracle_account_info ); let mut oracle_map = OracleMap::load_one(&oracle_account_info, clock_slot, None).unwrap(); @@ -225,19 +222,16 @@ fn amm_pred_expiry_price_market_example() { // let mut oracle_map: OracleMap<'_> = // OracleMap::load_one(&jto_market_account_info, clock_slot, None).unwrap(); - let mut prelaunch_oracle_price = PrelaunchOracle { - price: PRICE_PRECISION_I64, - confidence: 1655389, - ..PrelaunchOracle::default() - }; + let mut sol_oracle_price: pyth::pc::Price = get_hardcoded_pyth_price(1, 6); + sol_oracle_price.agg.conf = 1655389; - let prelaunch_oracle_price_key: Pubkey = + let sol_oracle_price_key: Pubkey = Pubkey::from_str("3TVuLmEGBRfVgrmFRtYTheczXaaoRBwcHw1yibZHSeNA").unwrap(); - let drift_program = crate::id(); - create_anchor_account_info!( - prelaunch_oracle_price, - &prelaunch_oracle_price_key, - PrelaunchOracle, + let pyth_program = crate::ids::pyth_program::id(); + create_account_info!( + sol_oracle_price, + &sol_oracle_price_key, + &pyth_program, oracle_account_info ); let mut oracle_map = OracleMap::load_one(&oracle_account_info, clock_slot, None).unwrap(); @@ -339,19 +333,16 @@ fn amm_pred_settle_market_example() { // let mut oracle_map: OracleMap<'_> = // OracleMap::load_one(&jto_market_account_info, clock_slot, None).unwrap(); - let mut prelaunch_oracle_price = PrelaunchOracle { - price: PRICE_PRECISION_I64, - confidence: 1655389, - ..PrelaunchOracle::default() - }; + let mut sol_oracle_price: pyth::pc::Price = get_hardcoded_pyth_price(1, 6); + sol_oracle_price.agg.conf = 1655389; - let prelaunch_oracle_price_key: Pubkey = + let sol_oracle_price_key: Pubkey = Pubkey::from_str("3TVuLmEGBRfVgrmFRtYTheczXaaoRBwcHw1yibZHSeNA").unwrap(); - let drift_program = crate::id(); - create_anchor_account_info!( - prelaunch_oracle_price, - &prelaunch_oracle_price_key, - PrelaunchOracle, + let pyth_program = crate::ids::pyth_program::id(); + create_account_info!( + sol_oracle_price, + &sol_oracle_price_key, + &pyth_program, oracle_account_info ); let mut oracle_map = OracleMap::load_one(&oracle_account_info, clock_slot, None).unwrap(); @@ -2007,7 +1998,7 @@ fn update_amm_near_boundary() { println!("perp_market: {:?}", perp_market.amm.last_update_slot); - let oracle_price_data = oracle_map.get_price_data(&perp_market.oracle_id()).unwrap(); + let oracle_price_data = oracle_map.get_price_data(&key).unwrap(); let state = State::default(); @@ -2049,7 +2040,7 @@ fn update_amm_near_boundary2() { println!("perp_market: {:?}", perp_market.amm.last_update_slot); - let oracle_price_data = oracle_map.get_price_data(&perp_market.oracle_id()).unwrap(); + let oracle_price_data = oracle_map.get_price_data(&key).unwrap(); let state = State::default(); @@ -2091,7 +2082,7 @@ fn recenter_amm_1() { println!("perp_market: {:?}", perp_market.amm.last_update_slot); - let oracle_price_data = oracle_map.get_price_data(&perp_market.oracle_id()).unwrap(); + let oracle_price_data = oracle_map.get_price_data(&key).unwrap(); let state = State::default(); @@ -2189,9 +2180,7 @@ fn recenter_amm_2() { assert_eq!(perp_market.amm.quote_asset_reserve, 64381518181749930705); assert_eq!(perp_market.amm.base_asset_reserve, 307161425106214); - let oracle_price_data = oracle_map - .get_price_data(&(oracle_price_key, OracleSource::Pyth)) - .unwrap(); + let oracle_price_data = oracle_map.get_price_data(&oracle_price_key).unwrap(); let state = State::default(); @@ -2318,9 +2307,7 @@ fn test_move_amm() { assert_eq!(perp_market.amm.quote_asset_reserve, 64381518181749930705); assert_eq!(perp_market.amm.base_asset_reserve, 307161425106214); - let oracle_price_data = oracle_map - .get_price_data(&(oracle_price_key, OracleSource::Pyth)) - .unwrap(); + let oracle_price_data = oracle_map.get_price_data(&oracle_price_key).unwrap(); let state = State::default(); diff --git a/programs/drift/src/controller/repeg.rs b/programs/drift/src/controller/repeg.rs index 79d0c033d..de886db4c 100644 --- a/programs/drift/src/controller/repeg.rs +++ b/programs/drift/src/controller/repeg.rs @@ -110,7 +110,7 @@ pub fn update_amms( let updated = true; // todo for (_key, market_account_loader) in perp_market_map.0.iter_mut() { let market = &mut load_mut!(market_account_loader)?; - let oracle_price_data = &oracle_map.get_price_data(&market.oracle_id())?; + let oracle_price_data = &oracle_map.get_price_data(&market.amm.oracle)?; _update_amm(market, oracle_price_data, state, now, clock_slot)?; } @@ -125,7 +125,7 @@ pub fn update_amm( clock: &Clock, ) -> DriftResult { let market = &mut perp_market_map.get_ref_mut(&market_index)?; - let oracle_price_data = oracle_map.get_price_data(&market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&market.amm.oracle)?; let cost_of_update = _update_amm( market, diff --git a/programs/drift/src/ids.rs b/programs/drift/src/ids.rs index 2db1c30ea..020886a61 100644 --- a/programs/drift/src/ids.rs +++ b/programs/drift/src/ids.rs @@ -29,6 +29,63 @@ pub mod switchboard_on_demand { declare_id!("Aio4gaXjXzJNVLtzwtNVmSqGKpANtXhybbkhtAC94ji2"); } +pub mod bonk_oracle { + use solana_program::declare_id; + #[cfg(feature = "mainnet-beta")] + declare_id!("8ihFLu5FimgTQ1Unh4dVyEHUGodJ5gJQCrQf4KUVB9bN"); + #[cfg(not(feature = "mainnet-beta"))] + declare_id!("6bquU99ktV1VRiHDr8gMhDFt3kMfhCQo5nfNrg2Urvsn"); +} + +pub mod bonk_pull_oracle { + use solana_program::declare_id; + declare_id!("GojbSnJuPdKDT1ZuHuAM5t9oz6bxTo1xhUKpTua2F72p"); +} + +pub mod pepe_oracle { + use solana_program::declare_id; + #[cfg(feature = "mainnet-beta")] + declare_id!("FSfxunDmjjbDV2QxpyxFCAPKmYJHSLnLuvQXDLkMzLBm"); + #[cfg(not(feature = "mainnet-beta"))] + declare_id!("Gz9RfgDeAFSsH7BHDGyNTgCik74rjNwsodJpsCizzmkj"); +} + +pub mod pepe_pull_oracle { + use solana_program::declare_id; + declare_id!("CLxofhtzvLiErpn25wvUzpZXEqBhuZ6WMEckEraxyuGt"); +} + +pub mod wen_oracle { + use solana_program::declare_id; + #[cfg(feature = "mainnet-beta")] + declare_id!("6Uo93N83iF5U9KwC8eQpogx4XptMT4wSKfje7hB1Ufko"); + #[cfg(not(feature = "mainnet-beta"))] + declare_id!("HuobqtT6QaJ8napVARKRxqZN33NqYzQJKLTKKrGy8Bvo"); +} + +pub mod wen_pull_oracle { + use solana_program::declare_id; + declare_id!("F47c7aJgYkfKXQ9gzrJaEpsNwUKHprysregTWXrtYLFp"); +} + +pub mod mew_pull_oracle { + use solana_program::declare_id; + declare_id!("DKGwCUcwngwmgifGxnme7zVR695LCBGk2pnuksRnbhfD"); +} + +pub mod usdc_oracle { + use solana_program::declare_id; + #[cfg(feature = "mainnet-beta")] + declare_id!("Gnt27xtC473ZT2Mw5u8wZ68Z3gULkSTb5DuxJy7eJotD"); + #[cfg(not(feature = "mainnet-beta"))] + declare_id!("5SSkXsEKQepHHAewytPVwdej4epN1nxgLVM84L4KXgy7"); +} + +pub mod usdc_pull_oracle { + use solana_program::declare_id; + declare_id!("En8hkHLkRe9d9DraYmBTrus518BvmVH448YcvmrFM6Ce"); +} + pub mod serum_program { use solana_program::declare_id; #[cfg(feature = "mainnet-beta")] @@ -65,6 +122,16 @@ pub mod marinade_mainnet { declare_id!("MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD"); } +pub mod usdt_oracle { + use solana_program::declare_id; + declare_id!("3vxLXJqLqF3JG5TCbYycbKWRBbCJQLxQmBGCkyqEEefL"); +} + +pub mod usdt_pull_oracle { + use solana_program::declare_id; + declare_id!("BekJ3P5G3iFeC97sXHuKnUHofCFj9Sbo7uyF2fkKwvit"); +} + pub mod admin_hot_wallet { use solana_program::declare_id; declare_id!("5hMjmxexWu954pX9gB9jkHxMqdjpxArQS2XdvkaevRax"); diff --git a/programs/drift/src/instructions/keeper.rs b/programs/drift/src/instructions/keeper.rs index b79d8b6ed..2205daac6 100644 --- a/programs/drift/src/instructions/keeper.rs +++ b/programs/drift/src/instructions/keeper.rs @@ -1400,7 +1400,7 @@ pub fn handle_resolve_perp_pnl_deficit<'c: 'info, 'info>( "Market is in settlement mode", )?; - let oracle_price = oracle_map.get_price_data(&perp_market.oracle_id())?.price; + let oracle_price = oracle_map.get_price_data(&perp_market.amm.oracle)?.price; controller::orders::validate_market_within_price_band(perp_market, state, oracle_price)?; controller::insurance::resolve_perp_pnl_deficit( @@ -1683,7 +1683,7 @@ pub fn handle_update_funding_rate( Some(state.oracle_guard_rails), )?; - let oracle_price_data = &oracle_map.get_price_data(&perp_market.oracle_id())?; + let oracle_price_data = &oracle_map.get_price_data(&perp_market.amm.oracle)?; controller::repeg::_update_amm(perp_market, oracle_price_data, state, now, clock_slot)?; validate!( @@ -1778,7 +1778,7 @@ pub fn handle_update_perp_bid_ask_twap<'c: 'info, 'info>( min_if_stake )?; - let oracle_price_data = oracle_map.get_price_data(&perp_market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&perp_market.amm.oracle)?; controller::repeg::_update_amm(perp_market, oracle_price_data, state, now, slot)?; let remaining_accounts_iter = &mut ctx.remaining_accounts.iter().peekable(); @@ -1940,7 +1940,7 @@ pub fn handle_update_spot_market_cumulative_interest( Some(state.oracle_guard_rails), )?; - let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle)?; if !state.funding_paused()? { controller::spot_balance::update_spot_market_cumulative_interest( @@ -2214,7 +2214,7 @@ pub fn handle_force_delete_user<'c: 'info, 'info>( } let spot_market = &mut spot_market_map.get_ref_mut(&spot_position.market_index)?; - let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle)?; controller::spot_balance::update_spot_market_cumulative_interest( spot_market, diff --git a/programs/drift/src/instructions/user.rs b/programs/drift/src/instructions/user.rs index c6e92e295..35179e578 100644 --- a/programs/drift/src/instructions/user.rs +++ b/programs/drift/src/instructions/user.rs @@ -356,7 +356,7 @@ pub fn handle_deposit<'c: 'info, 'info>( validate!(!user.is_bankrupt(), ErrorCode::UserBankrupt)?; let mut spot_market = spot_market_map.get_ref_mut(&market_index)?; - let oracle_price_data = *oracle_map.get_price_data(&spot_market.oracle_id())?; + let oracle_price_data = &oracle_map.get_price_data(&spot_market.oracle)?.clone(); validate!( user.pool_id == spot_market.pool_id, @@ -374,7 +374,7 @@ pub fn handle_deposit<'c: 'info, 'info>( controller::spot_balance::update_spot_market_cumulative_interest( &mut spot_market, - Some(&oracle_price_data), + Some(oracle_price_data), now, )?; @@ -532,7 +532,7 @@ pub fn handle_withdraw<'c: 'info, 'info>( let spot_market_is_reduce_only = { let spot_market = &mut spot_market_map.get_ref_mut(&market_index)?; - let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle)?; controller::spot_balance::update_spot_market_cumulative_interest( spot_market, @@ -575,7 +575,7 @@ pub fn handle_withdraw<'c: 'info, 'info>( }; let spot_market = &mut spot_market_map.get_ref_mut(&market_index)?; - let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle)?; user.increment_total_withdraws( amount, @@ -614,7 +614,7 @@ pub fn handle_withdraw<'c: 'info, 'info>( user.update_last_active_slot(slot); let mut spot_market = spot_market_map.get_ref_mut(&market_index)?; - let oracle_price = oracle_map.get_price_data(&spot_market.oracle_id())?.price; + let oracle_price = oracle_map.get_price_data(&spot_market.oracle)?.price; let is_borrow = user .get_spot_position(market_index) @@ -723,7 +723,7 @@ pub fn handle_transfer_deposit<'c: 'info, 'info>( { let spot_market = &mut spot_market_map.get_ref_mut(&market_index)?; - let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle)?; controller::spot_balance::update_spot_market_cumulative_interest( spot_market, Some(oracle_price_data), @@ -733,7 +733,7 @@ pub fn handle_transfer_deposit<'c: 'info, 'info>( let oracle_price = { let spot_market = &spot_market_map.get_ref(&market_index)?; - oracle_map.get_price_data(&spot_market.oracle_id())?.price + oracle_map.get_price_data(&spot_market.oracle)?.price }; { @@ -3021,7 +3021,7 @@ pub fn handle_begin_swap<'c: 'info, 'info>( "begin_swap ended in invalid state" )?; - let in_oracle_data = oracle_map.get_price_data(&in_spot_market.oracle_id())?; + let in_oracle_data = oracle_map.get_price_data(&in_spot_market.oracle)?; controller::spot_balance::update_spot_market_cumulative_interest( &mut in_spot_market, Some(in_oracle_data), @@ -3044,7 +3044,7 @@ pub fn handle_begin_swap<'c: 'info, 'info>( "begin_swap ended in invalid state" )?; - let out_oracle_data = oracle_map.get_price_data(&out_spot_market.oracle_id())?; + let out_oracle_data = oracle_map.get_price_data(&out_spot_market.oracle)?; controller::spot_balance::update_spot_market_cumulative_interest( &mut out_spot_market, Some(out_oracle_data), @@ -3278,7 +3278,7 @@ pub fn handle_end_swap<'c: 'info, 'info>( "the in_spot_market must have a flash loan amount set" )?; - let in_oracle_data = oracle_map.get_price_data(&in_spot_market.oracle_id())?; + let in_oracle_data = oracle_map.get_price_data(&in_spot_market.oracle)?; let in_oracle_price = in_oracle_data.price; let mut out_spot_market = spot_market_map.get_ref_mut(&out_market_index)?; @@ -3290,7 +3290,7 @@ pub fn handle_end_swap<'c: 'info, 'info>( out_market_index )?; - let out_oracle_data = oracle_map.get_price_data(&out_spot_market.oracle_id())?; + let out_oracle_data = oracle_map.get_price_data(&out_spot_market.oracle)?; let out_oracle_price = out_oracle_data.price; let in_vault = &mut ctx.accounts.in_spot_market_vault; diff --git a/programs/drift/src/math/funding/tests.rs b/programs/drift/src/math/funding/tests.rs index 114159d75..b2668b9fc 100644 --- a/programs/drift/src/math/funding/tests.rs +++ b/programs/drift/src/math/funding/tests.rs @@ -652,7 +652,7 @@ fn unsettled_funding_pnl() { market.amm.funding_period, ) .unwrap(); - let oracle_price_data = oracle_map.get_price_data(&market.oracle_id()).unwrap(); + let oracle_price_data = oracle_map.get_price_data(&market.amm.oracle).unwrap(); assert_eq!(time_until_next_update, 0); let block_funding_rate_update = block_operation( diff --git a/programs/drift/src/math/margin.rs b/programs/drift/src/math/margin.rs index ab6038e5d..8c4c3ef7c 100644 --- a/programs/drift/src/math/margin.rs +++ b/programs/drift/src/math/margin.rs @@ -261,7 +261,7 @@ pub fn calculate_margin_requirement_and_total_collateral_and_liability_info( let (oracle_price_data, oracle_validity) = oracle_map.get_price_data_and_validity( MarketType::Spot, spot_market.market_index, - &spot_market.oracle_id(), + &spot_market.oracle, spot_market.historical_oracle_data.last_oracle_price_twap, spot_market.get_max_confidence_interval_multiplier()?, )?; @@ -500,7 +500,7 @@ pub fn calculate_margin_requirement_and_total_collateral_and_liability_info( .get_price_data_and_validity( MarketType::Spot, quote_spot_market.market_index, - "e_spot_market.oracle_id(), + "e_spot_market.oracle, quote_spot_market .historical_oracle_data .last_oracle_price_twap, @@ -519,7 +519,7 @@ pub fn calculate_margin_requirement_and_total_collateral_and_liability_info( let (oracle_price_data, oracle_validity) = oracle_map.get_price_data_and_validity( MarketType::Perp, market.market_index, - &market.oracle_id(), + &market.amm.oracle, market.amm.historical_oracle_data.last_oracle_price_twap, market.get_max_confidence_interval_multiplier()?, )?; @@ -780,7 +780,7 @@ pub fn calculate_max_withdrawable_amount( .get_spot_position(market_index)? .get_token_amount(spot_market)?; - let oracle_price = oracle_map.get_price_data(&spot_market.oracle_id())?.price; + let oracle_price = oracle_map.get_price_data(&spot_market.oracle)?.price; let asset_weight = spot_market.get_asset_weight( token_amount, @@ -854,7 +854,7 @@ pub fn validate_spot_margin_trading( let bids = spot_position.open_bids; if bids > 0 { let spot_market = spot_market_map.get_ref(&spot_position.market_index)?; - let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle)?; let open_bids_value = get_token_value(-bids as i128, spot_market.decimals, oracle_price_data.price)?; @@ -897,7 +897,7 @@ pub fn calculate_user_equity( let (oracle_price_data, oracle_validity) = oracle_map.get_price_data_and_validity( MarketType::Spot, spot_market.market_index, - &spot_market.oracle_id(), + &spot_market.oracle, spot_market.historical_oracle_data.last_oracle_price_twap, spot_market.get_max_confidence_interval_multiplier()?, )?; @@ -924,7 +924,7 @@ pub fn calculate_user_equity( .get_price_data_and_validity( MarketType::Spot, quote_spot_market.market_index, - "e_spot_market.oracle_id(), + "e_spot_market.oracle, quote_spot_market .historical_oracle_data .last_oracle_price_twap, @@ -940,7 +940,7 @@ pub fn calculate_user_equity( let (oracle_price_data, oracle_validity) = oracle_map.get_price_data_and_validity( MarketType::Perp, market.market_index, - &market.oracle_id(), + &market.amm.oracle, market.amm.historical_oracle_data.last_oracle_price_twap, market.get_max_confidence_interval_multiplier()?, )?; diff --git a/programs/drift/src/math/margin/tests.rs b/programs/drift/src/math/margin/tests.rs index 0f4d7e48b..ac77ca37e 100644 --- a/programs/drift/src/math/margin/tests.rs +++ b/programs/drift/src/math/margin/tests.rs @@ -2217,7 +2217,7 @@ mod calculate_margin_requirement_and_total_collateral_and_liability_info { let mut usdc_spot_market = SpotMarket { market_index: 0, - oracle_source: OracleSource::PythStableCoin, + oracle_source: OracleSource::QuoteAsset, cumulative_deposit_interest: SPOT_CUMULATIVE_INTEREST_PRECISION, decimals: 6, initial_asset_weight: SPOT_WEIGHT_PRECISION, @@ -2278,12 +2278,6 @@ mod calculate_margin_requirement_and_total_collateral_and_liability_info { ) .unwrap(); - let usdc_price = oracle_map - .get_price_data(&(usdc_oracle_price_key, OracleSource::QuoteAsset)) - .unwrap() - .price; - println!("usdc_price: {}", usdc_price); - assert_eq!(margin_requirement, 0); assert_eq!(total_collateral, 990000); @@ -2368,7 +2362,7 @@ mod calculate_margin_requirement_and_total_collateral_and_liability_info { let mut usdc_spot_market = SpotMarket { market_index: 0, - oracle_source: OracleSource::PythStableCoin, + oracle_source: OracleSource::QuoteAsset, cumulative_deposit_interest: SPOT_CUMULATIVE_INTEREST_PRECISION, cumulative_borrow_interest: SPOT_CUMULATIVE_INTEREST_PRECISION, decimals: 6, @@ -2514,7 +2508,7 @@ mod calculate_margin_requirement_and_total_collateral_and_liability_info { let mut usdc_spot_market = SpotMarket { market_index: 0, - oracle_source: OracleSource::PythStableCoin, + oracle_source: OracleSource::QuoteAsset, cumulative_deposit_interest: SPOT_CUMULATIVE_INTEREST_PRECISION, decimals: 6, initial_asset_weight: SPOT_WEIGHT_PRECISION, diff --git a/programs/drift/src/math/orders.rs b/programs/drift/src/math/orders.rs index 45553ab34..bead1d5a4 100644 --- a/programs/drift/src/math/orders.rs +++ b/programs/drift/src/math/orders.rs @@ -825,11 +825,11 @@ pub fn calculate_max_perp_order_size( let perp_market = perp_market_map.get_ref(&market_index)?; - let oracle_price_data_price = oracle_map.get_price_data(&perp_market.oracle_id())?.price; + let oracle_price_data_price = oracle_map.get_price_data(&perp_market.amm.oracle)?.price; let quote_spot_market = spot_market_map.get_ref(&perp_market.quote_spot_market_index)?; let quote_oracle_price = oracle_map - .get_price_data("e_spot_market.oracle_id())? + .get_price_data("e_spot_market.oracle)? .price .max( quote_spot_market @@ -971,7 +971,7 @@ pub fn calculate_max_spot_order_size( let spot_market = spot_market_map.get_ref(&market_index)?; - let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle_id())?; + let oracle_price_data = oracle_map.get_price_data(&spot_market.oracle)?; let twap = spot_market .historical_oracle_data .last_oracle_price_twap_5min; diff --git a/programs/drift/src/state/oracle.rs b/programs/drift/src/state/oracle.rs index 560a639d3..b5d62bb46 100644 --- a/programs/drift/src/state/oracle.rs +++ b/programs/drift/src/state/oracle.rs @@ -107,9 +107,7 @@ impl HistoricalIndexData { } } -#[derive( - AnchorSerialize, AnchorDeserialize, Clone, Copy, Eq, PartialEq, Debug, Default, Ord, PartialOrd, -)] +#[derive(AnchorSerialize, AnchorDeserialize, Clone, Copy, Eq, PartialEq, Debug, Default)] pub enum OracleSource { #[default] Pyth, diff --git a/programs/drift/src/state/oracle/tests.rs b/programs/drift/src/state/oracle/tests.rs index 0b737c6c3..0fe9cf089 100644 --- a/programs/drift/src/state/oracle/tests.rs +++ b/programs/drift/src/state/oracle/tests.rs @@ -3,7 +3,6 @@ use std::str::FromStr; use crate::create_account_info; use crate::state::oracle::{get_oracle_price, OracleSource}; -use crate::state::oracle_map::OracleMap; use crate::state::perp_market::AMM; use crate::test_utils::*; @@ -127,33 +126,3 @@ fn switchboard_on_demand() { let twap = amm.get_oracle_twap(&dsol_oracle_info, 0).unwrap(); assert_eq!(twap, Some(226556945)); } - -#[test] -fn oracle_map_diff_oracle_source() { - let oracle_price_key = - Pubkey::from_str("DBE3N8uNjhKPRHfANdwGvCZghWXyLPdqdSbEW2XFwBiX").unwrap(); - let oracle_market_str = String::from("IvEjY51+9M206svkAq6RZcKrffzb5QRNJ/KEEG+IqQv93vpfv/YMoAFysCEhfKP+aJIqGar5kBCcudhOmtAEtNICWtb1KTFEGbZFBQAAAAAABQIAAAAAAAD2////xXhYZgAAAADFeFhmAAAAAJMfBQAAAAAAnwEAAAAAAAAFMwYQAAAAAAA="); - let mut decoded_bytes = base64::decode(oracle_market_str).unwrap(); - let oracle_market_bytes = decoded_bytes.as_mut_slice(); - let mut lamports = 0; - let pyth_program = crate::ids::drift_oracle_receiver_program::id(); - let bonk_market_account_info = create_account_info( - &oracle_price_key, - true, - &mut lamports, - oracle_market_bytes, - &pyth_program, - ); - - let mut oracle_map = OracleMap::load_one(&bonk_market_account_info, 0, None).unwrap(); - - let oracle_price_data = oracle_map - .get_price_data(&(oracle_price_key, OracleSource::Pyth1MPull)) - .unwrap(); - assert_eq!(oracle_price_data.price, 34552600); - - let oracle_price_data = oracle_map - .get_price_data(&(oracle_price_key, OracleSource::PythPull)) - .unwrap(); - assert_eq!(oracle_price_data.price, 34); -} diff --git a/programs/drift/src/state/oracle_map.rs b/programs/drift/src/state/oracle_map.rs index 4fb044020..e541d5471 100644 --- a/programs/drift/src/state/oracle_map.rs +++ b/programs/drift/src/state/oracle_map.rs @@ -1,7 +1,9 @@ use crate::error::ErrorCode::UnableToLoadOracle; use crate::error::{DriftResult, ErrorCode}; use crate::ids::{ - drift_oracle_receiver_program, pyth_program, switchboard_on_demand, switchboard_program, + bonk_oracle, bonk_pull_oracle, drift_oracle_receiver_program, mew_pull_oracle, pepe_oracle, + pepe_pull_oracle, pyth_program, switchboard_on_demand, switchboard_program, usdc_oracle, + usdc_pull_oracle, usdt_oracle, usdt_pull_oracle, wen_oracle, wen_pull_oracle, }; use crate::math::constants::PRICE_PRECISION_I64; use crate::math::oracle::{oracle_validity, OracleValidity}; @@ -22,19 +24,25 @@ use crate::math::safe_unwrap::SafeUnwrap; use crate::state::traits::Size; use crate::validate; -pub(crate) type OracleIdentifier = (Pubkey, OracleSource); +pub const PYTH_1M_IDS: [Pubkey; 2] = [bonk_oracle::id(), pepe_oracle::id()]; +pub const PYTH_PULL_1M_IDS: [Pubkey; 2] = [bonk_pull_oracle::id(), pepe_pull_oracle::id()]; -const EXTERNAL_ORACLE_PROGRAM_IDS: [Pubkey; 4] = [ - pyth_program::id(), - drift_oracle_receiver_program::id(), - switchboard_program::id(), - switchboard_on_demand::id(), -]; +pub const PYTH_1K_IDS: [Pubkey; 1] = [wen_oracle::id()]; +pub const PYTH_PULL_1K_IDS: [Pubkey; 2] = [wen_pull_oracle::id(), mew_pull_oracle::id()]; + +pub const PYTH_STABLECOIN_IDS: [Pubkey; 2] = [usdc_oracle::id(), usdt_oracle::id()]; +pub const PYTH_PULL_STABLECOIN_IDS: [Pubkey; 2] = [usdc_pull_oracle::id(), usdt_pull_oracle::id()]; + +pub struct AccountInfoAndOracleSource<'a> { + /// CHECK: ownders are validated in OracleMap::load + pub account_info: AccountInfo<'a>, + pub oracle_source: OracleSource, +} pub struct OracleMap<'a> { - oracles: BTreeMap>, - price_data: BTreeMap, - validity: BTreeMap, + oracles: BTreeMap>, + price_data: BTreeMap, + validity: BTreeMap, pub slot: u64, pub oracle_guard_rails: OracleGuardRails, pub quote_asset_price_data: OraclePriceData, @@ -50,6 +58,7 @@ impl<'a> OracleMap<'a> { .oracles .get(pubkey) .ok_or(ErrorCode::OracleNotFound)? + .account_info .clone()) } @@ -57,47 +66,60 @@ impl<'a> OracleMap<'a> { pubkey == &Pubkey::default() } - pub fn get_price_data(&mut self, id: &OracleIdentifier) -> DriftResult<&OraclePriceData> { - if self.should_get_quote_asset_price_data(&id.0) { + pub fn get_price_data(&mut self, pubkey: &Pubkey) -> DriftResult<&OraclePriceData> { + if self.should_get_quote_asset_price_data(pubkey) { return Ok(&self.quote_asset_price_data); } - if self.price_data.contains_key(id) { - return self.price_data.get(id).safe_unwrap(); + if self.price_data.contains_key(pubkey) { + return self.price_data.get(pubkey).safe_unwrap(); } - let account_info = match self.oracles.get(&id.0) { - Some(account_info) => account_info, + let (account_info, oracle_source) = match self.oracles.get(pubkey) { + Some(AccountInfoAndOracleSource { + account_info, + oracle_source, + }) => (account_info, oracle_source), None => { - msg!("oracle pubkey not found in oracle_map: {}", id.0); + msg!("oracle pubkey not found in oracle_map: {}", pubkey); return Err(ErrorCode::OracleNotFound); } }; - let price_data = get_oracle_price(&id.1, account_info, self.slot)?; + let price_data = get_oracle_price(oracle_source, account_info, self.slot)?; - self.price_data.insert(*id, price_data); - self.price_data.get(id).safe_unwrap() + self.price_data.insert(*pubkey, price_data); + + self.price_data.get(pubkey).safe_unwrap() + } + + pub fn get_oracle_source(&self, pubkey: &Pubkey) -> DriftResult { + Ok(self + .oracles + .get(pubkey) + .ok_or(ErrorCode::OracleNotFound)? + .oracle_source) } pub fn get_price_data_and_validity( &mut self, market_type: MarketType, market_index: u16, - oracle_id: &OracleIdentifier, + pubkey: &Pubkey, last_oracle_price_twap: i64, max_confidence_interval_multiplier: u64, ) -> DriftResult<(&OraclePriceData, OracleValidity)> { - if self.should_get_quote_asset_price_data(&oracle_id.0) { + if self.should_get_quote_asset_price_data(pubkey) { return Ok((&self.quote_asset_price_data, OracleValidity::Valid)); } - if self.price_data.contains_key(oracle_id) { - let oracle_price_data = self.price_data.get(oracle_id).safe_unwrap()?; + if self.price_data.contains_key(pubkey) { + let oracle_price_data = self.price_data.get(pubkey).safe_unwrap()?; - let oracle_validity = if let Some(oracle_validity) = self.validity.get(oracle_id) { + let oracle_validity = if let Some(oracle_validity) = self.validity.get(pubkey) { *oracle_validity } else { + let oracle_source = self.get_oracle_source(pubkey)?; let oracle_validity = oracle_validity( market_type, market_index, @@ -105,28 +127,31 @@ impl<'a> OracleMap<'a> { oracle_price_data, &self.oracle_guard_rails.validity, max_confidence_interval_multiplier, - &oracle_id.1, + &oracle_source, true, )?; - self.validity.insert(*oracle_id, oracle_validity); + self.validity.insert(*pubkey, oracle_validity); oracle_validity }; return Ok((oracle_price_data, oracle_validity)); } - let account_info = match self.oracles.get(&oracle_id.0) { - Some(account_info) => account_info, + let (account_info, oracle_source) = match self.oracles.get(pubkey) { + Some(AccountInfoAndOracleSource { + account_info, + oracle_source, + }) => (account_info, oracle_source), None => { - msg!("oracle pubkey not found in oracle_map: {}", oracle_id.0); + msg!("oracle pubkey not found in oracle_map: {}", pubkey); return Err(ErrorCode::OracleNotFound); } }; - let price_data = get_oracle_price(&oracle_id.1, account_info, self.slot)?; + let price_data = get_oracle_price(oracle_source, account_info, self.slot)?; - self.price_data.insert(*oracle_id, price_data); + self.price_data.insert(*pubkey, price_data); - let oracle_price_data = self.price_data.get(oracle_id).safe_unwrap()?; + let oracle_price_data = self.price_data.get(pubkey).safe_unwrap()?; let oracle_validity = oracle_validity( market_type, market_index, @@ -134,43 +159,46 @@ impl<'a> OracleMap<'a> { oracle_price_data, &self.oracle_guard_rails.validity, max_confidence_interval_multiplier, - &oracle_id.1, + &oracle_source, true, )?; - self.validity.insert(*oracle_id, oracle_validity); + self.validity.insert(*pubkey, oracle_validity); Ok((oracle_price_data, oracle_validity)) } pub fn get_price_data_and_guard_rails( &mut self, - oracle_id: &OracleIdentifier, + pubkey: &Pubkey, ) -> DriftResult<(&OraclePriceData, &ValidityGuardRails)> { - if self.should_get_quote_asset_price_data(&oracle_id.0) { + if self.should_get_quote_asset_price_data(pubkey) { let validity_guard_rails = &self.oracle_guard_rails.validity; return Ok((&self.quote_asset_price_data, validity_guard_rails)); } - if self.price_data.contains_key(oracle_id) { - let oracle_price_data = self.price_data.get(oracle_id).safe_unwrap()?; + if self.price_data.contains_key(pubkey) { + let oracle_price_data = self.price_data.get(pubkey).safe_unwrap()?; let validity_guard_rails = &self.oracle_guard_rails.validity; return Ok((oracle_price_data, validity_guard_rails)); } - let account_info = match self.oracles.get(&oracle_id.0) { - Some(account_info) => account_info, + let (account_info, oracle_source) = match self.oracles.get(pubkey) { + Some(AccountInfoAndOracleSource { + account_info, + oracle_source, + }) => (account_info, oracle_source), None => { - msg!("oracle pubkey not found in oracle_map: {}", oracle_id.0); + msg!("oracle pubkey not found in oracle_map: {}", pubkey); return Err(ErrorCode::OracleNotFound); } }; - let price_data = get_oracle_price(&oracle_id.1, account_info, self.slot)?; + let price_data = get_oracle_price(oracle_source, account_info, self.slot)?; - self.price_data.insert(*oracle_id, price_data); + self.price_data.insert(*pubkey, price_data); - let oracle_price_data = self.price_data.get(oracle_id).safe_unwrap()?; + let oracle_price_data = self.price_data.get(pubkey).safe_unwrap()?; let validity_guard_rails = &self.oracle_guard_rails.validity; Ok((oracle_price_data, validity_guard_rails)) @@ -181,14 +209,53 @@ impl<'a> OracleMap<'a> { slot: u64, oracle_guard_rails: Option, ) -> DriftResult> { - let mut oracles: BTreeMap> = BTreeMap::new(); + let mut oracles: BTreeMap> = BTreeMap::new(); while let Some(account_info) = account_info_iter.peek() { - if EXTERNAL_ORACLE_PROGRAM_IDS.contains(&account_info.owner) { + if account_info.owner == &pyth_program::id() { let account_info: &AccountInfo<'a> = account_info_iter.next().safe_unwrap()?; let pubkey = account_info.key(); - oracles.insert(pubkey, account_info.clone()); + let oracle_source = if PYTH_1M_IDS.contains(&pubkey) { + OracleSource::Pyth1M + } else if PYTH_1K_IDS.contains(&pubkey) { + OracleSource::Pyth1K + } else if PYTH_STABLECOIN_IDS.contains(&pubkey) { + OracleSource::PythStableCoin + } else { + OracleSource::Pyth + }; + + oracles.insert( + pubkey, + AccountInfoAndOracleSource { + account_info: account_info.clone(), + oracle_source, + }, + ); + + continue; + } else if account_info.owner == &drift_oracle_receiver_program::id() { + let account_info: &AccountInfo<'a> = account_info_iter.next().safe_unwrap()?; + let pubkey = account_info.key(); + + let oracle_source = if PYTH_PULL_1M_IDS.contains(&pubkey) { + OracleSource::Pyth1MPull + } else if PYTH_PULL_1K_IDS.contains(&pubkey) { + OracleSource::Pyth1KPull + } else if PYTH_PULL_STABLECOIN_IDS.contains(&pubkey) { + OracleSource::PythStableCoinPull + } else { + OracleSource::PythPull + }; + + oracles.insert( + pubkey, + AccountInfoAndOracleSource { + account_info: account_info.clone(), + oracle_source, + }, + ); continue; } else if account_info.owner == &crate::id() { @@ -210,7 +277,39 @@ impl<'a> OracleMap<'a> { let account_info = account_info_iter.next().safe_unwrap()?; let pubkey = account_info.key(); - oracles.insert(pubkey, account_info.clone()); + oracles.insert( + pubkey, + AccountInfoAndOracleSource { + account_info: account_info.clone(), + oracle_source: OracleSource::Prelaunch, + }, + ); + + continue; + } else if account_info.owner == &switchboard_program::id() { + let account_info = account_info_iter.next().safe_unwrap()?; + let pubkey = account_info.key(); + + oracles.insert( + pubkey, + AccountInfoAndOracleSource { + account_info: account_info.clone(), + oracle_source: OracleSource::Switchboard, + }, + ); + + continue; + } else if account_info.owner == &switchboard_on_demand::id() { + let account_info = account_info_iter.next().safe_unwrap()?; + let pubkey = account_info.key(); + + oracles.insert( + pubkey, + AccountInfoAndOracleSource { + account_info: account_info.clone(), + oracle_source: OracleSource::SwitchboardOnDemand, + }, + ); continue; } @@ -244,12 +343,48 @@ impl<'a> OracleMap<'a> { slot: u64, oracle_guard_rails: Option, ) -> DriftResult> { - let mut oracles: BTreeMap> = BTreeMap::new(); + let mut oracles: BTreeMap> = BTreeMap::new(); - if EXTERNAL_ORACLE_PROGRAM_IDS.contains(&account_info.owner) { + if account_info.owner == &pyth_program::id() { let pubkey = account_info.key(); - oracles.insert(pubkey, account_info.clone()); + let oracle_source = if PYTH_1M_IDS.contains(&pubkey) { + OracleSource::Pyth1M + } else if PYTH_1K_IDS.contains(&pubkey) { + OracleSource::Pyth1K + } else if PYTH_STABLECOIN_IDS.contains(&pubkey) { + OracleSource::PythStableCoin + } else { + OracleSource::Pyth + }; + + oracles.insert( + pubkey, + AccountInfoAndOracleSource { + account_info: account_info.clone(), + oracle_source, + }, + ); + } else if account_info.owner == &drift_oracle_receiver_program::id() { + let pubkey = account_info.key(); + + let oracle_source = if PYTH_PULL_1M_IDS.contains(&pubkey) { + OracleSource::Pyth1MPull + } else if PYTH_PULL_1K_IDS.contains(&pubkey) { + OracleSource::Pyth1KPull + } else if PYTH_PULL_STABLECOIN_IDS.contains(&pubkey) { + OracleSource::PythStableCoinPull + } else { + OracleSource::PythPull + }; + + oracles.insert( + pubkey, + AccountInfoAndOracleSource { + account_info: account_info.clone(), + oracle_source, + }, + ); } else if account_info.owner == &crate::id() { let data = account_info.try_borrow_data().map_err(|e| { msg!("Failed to borrow data while loading oracle map {:?}", e); @@ -269,7 +404,31 @@ impl<'a> OracleMap<'a> { } let pubkey = account_info.key(); - oracles.insert(pubkey, account_info.clone()); + oracles.insert( + pubkey, + AccountInfoAndOracleSource { + account_info: account_info.clone(), + oracle_source: OracleSource::Prelaunch, + }, + ); + } else if account_info.owner == &switchboard_program::id() { + let pubkey = account_info.key(); + oracles.insert( + pubkey, + AccountInfoAndOracleSource { + account_info: account_info.clone(), + oracle_source: OracleSource::Switchboard, + }, + ); + } else if account_info.owner == &switchboard_on_demand::id() { + let pubkey = account_info.key(); + oracles.insert( + pubkey, + AccountInfoAndOracleSource { + account_info: account_info.clone(), + oracle_source: OracleSource::SwitchboardOnDemand, + }, + ); } else if account_info.key() != Pubkey::default() { return Err(ErrorCode::InvalidOracle); } diff --git a/programs/drift/src/state/perp_market.rs b/programs/drift/src/state/perp_market.rs index 08c80d111..1d2b882a4 100644 --- a/programs/drift/src/state/perp_market.rs +++ b/programs/drift/src/state/perp_market.rs @@ -41,8 +41,6 @@ use crate::state::paused_operations::PerpOperation; use drift_macros::assert_no_slop; use static_assertions::const_assert_eq; -use super::oracle_map::OracleIdentifier; - #[cfg(test)] mod tests; @@ -300,10 +298,6 @@ impl MarketIndexOffset for PerpMarket { } impl PerpMarket { - pub fn oracle_id(&self) -> OracleIdentifier { - (self.amm.oracle, self.amm.oracle_source) - } - pub fn is_in_settlement(&self, now: i64) -> bool { let in_settlement = matches!( self.status, diff --git a/programs/drift/src/state/spot_market.rs b/programs/drift/src/state/spot_market.rs index 3df84e082..c5a1da9b7 100644 --- a/programs/drift/src/state/spot_market.rs +++ b/programs/drift/src/state/spot_market.rs @@ -25,8 +25,6 @@ use crate::state::perp_market::{MarketStatus, PoolBalance}; use crate::state::traits::{MarketIndexOffset, Size}; use crate::{validate, PERCENTAGE_PRECISION}; -use super::oracle_map::OracleIdentifier; - #[account(zero_copy(unsafe))] #[derive(PartialEq, Eq, Debug)] #[repr(C)] @@ -287,10 +285,6 @@ impl MarketIndexOffset for SpotMarket { } impl SpotMarket { - pub fn oracle_id(&self) -> OracleIdentifier { - (self.oracle, self.oracle_source) - } - pub fn is_in_settlement(&self, now: i64) -> bool { let in_settlement = matches!( self.status, diff --git a/sdk/src/accounts/grpcDriftClientAccountSubscriber.ts b/sdk/src/accounts/grpcDriftClientAccountSubscriber.ts index 5d00a0aaa..d23f5207c 100644 --- a/sdk/src/accounts/grpcDriftClientAccountSubscriber.ts +++ b/sdk/src/accounts/grpcDriftClientAccountSubscriber.ts @@ -10,7 +10,6 @@ import { import { DelistedMarketSetting, GrpcConfigs, ResubOpts } from './types'; import { grpcAccountSubscriber } from './grpcAccountSubscriber'; import { PerpMarketAccount, SpotMarketAccount, StateAccount } from '../types'; -import { getOracleId } from '../oracles/oracleId'; export class gprcDriftClientAccountSubscriber extends WebSocketDriftClientAccountSubscriber { private grpcConfigs: GrpcConfigs; @@ -170,7 +169,7 @@ export class gprcDriftClientAccountSubscriber extends WebSocketDriftClientAccoun } async subscribeToOracle(oracleInfo: OracleInfo): Promise { - const oracleId = getOracleId(oracleInfo.publicKey, oracleInfo.source); + const oracleString = oracleInfo.publicKey.toString(); const client = this.oracleClientCache.get( oracleInfo.source, this.program.provider.connection, @@ -186,18 +185,13 @@ export class gprcDriftClientAccountSubscriber extends WebSocketDriftClientAccoun }, this.resubOpts ); - accountSubscriber.setData(this.initialOraclePriceData.get(oracleId)); + accountSubscriber.setData(this.initialOraclePriceData.get(oracleString)); await accountSubscriber.subscribe((data: OraclePriceData) => { - this.eventEmitter.emit( - 'oraclePriceUpdate', - oracleInfo.publicKey, - oracleInfo.source, - data - ); + this.eventEmitter.emit('oraclePriceUpdate', oracleInfo.publicKey, data); this.eventEmitter.emit('update'); }); - this.oracleSubscribers.set(oracleId, accountSubscriber); + this.oracleSubscribers.set(oracleString, accountSubscriber); return true; } } diff --git a/sdk/src/accounts/pollingDriftClientAccountSubscriber.ts b/sdk/src/accounts/pollingDriftClientAccountSubscriber.ts index 18da8df65..de96b3927 100644 --- a/sdk/src/accounts/pollingDriftClientAccountSubscriber.ts +++ b/sdk/src/accounts/pollingDriftClientAccountSubscriber.ts @@ -15,7 +15,6 @@ import { SpotMarketAccount, StateAccount, UserAccount, - OracleSource, } from '../types'; import { getDriftStateAccountPublicKey, @@ -29,12 +28,8 @@ import { OracleInfo, OraclePriceData } from '../oracles/types'; import { OracleClientCache } from '../oracles/oracleClientCache'; import { QUOTE_ORACLE_PRICE_DATA } from '../oracles/quoteAssetOracleClient'; import { findAllMarketAndOracles } from '../config'; -import { getOracleId } from '../oracles/oracleId'; -const ORACLE_DEFAULT_ID = getOracleId( - PublicKey.default, - OracleSource.QUOTE_ASSET -); +const ORACLE_DEFAULT_KEY = PublicKey.default.toBase58(); export class PollingDriftClientAccountSubscriber implements DriftClientAccountSubscriber @@ -222,13 +217,10 @@ export class PollingDriftClientAccountSubscriber } addOracleToPoll(oracleInfo: OracleInfo): boolean { - this.oraclesToPoll.set( - getOracleId(oracleInfo.publicKey, oracleInfo.source), - { - publicKey: oracleInfo.publicKey, - source: oracleInfo.source, - } - ); + this.oraclesToPoll.set(oracleInfo.publicKey.toString(), { + publicKey: oracleInfo.publicKey, + source: oracleInfo.source, + }); return true; } @@ -287,8 +279,6 @@ export class PollingDriftClientAccountSubscriber this.program ); - const oracleId = getOracleId(oracleToPoll.publicKey, oracleToPoll.source); - oracleToPoll.callbackId = await this.accountLoader.addAccount( oracleToPoll.publicKey, (buffer: Buffer, slot: number) => { @@ -301,12 +291,11 @@ export class PollingDriftClientAccountSubscriber slot, }; - this.oracles.set(oracleId, dataAndSlot); + this.oracles.set(oracleToPoll.publicKey.toString(), dataAndSlot); this.eventEmitter.emit( 'oraclePriceUpdate', oracleToPoll.publicKey, - oracleToPoll.source, oraclePriceData ); this.eventEmitter.emit('update'); @@ -364,13 +353,10 @@ export class PollingDriftClientAccountSubscriber ); const oraclePriceData = oracleClient.getOraclePriceDataFromBuffer(buffer); - this.oracles.set( - getOracleId(oracleToPoll.publicKey, oracleToPoll.source), - { - data: oraclePriceData, - slot, - } - ); + this.oracles.set(oracleToPoll.publicKey.toString(), { + data: oraclePriceData, + slot, + }); } } } @@ -441,23 +427,23 @@ export class PollingDriftClientAccountSubscriber } async addOracle(oracleInfo: OracleInfo): Promise { - const oracleId = getOracleId(oracleInfo.publicKey, oracleInfo.source); if ( oracleInfo.publicKey.equals(PublicKey.default) || - this.oracles.has(oracleId) + this.oracles.has(oracleInfo.publicKey.toBase58()) ) { return true; } + const oracleString = oracleInfo.publicKey.toBase58(); // this func can be called multiple times before the first pauseForOracleToBeAdded finishes // avoid adding to oraclesToPoll multiple time - if (!this.oraclesToPoll.has(oracleId)) { + if (!this.oraclesToPoll.has(oracleString)) { this.addOracleToPoll(oracleInfo); - const oracleToPoll = this.oraclesToPoll.get(oracleId); + const oracleToPoll = this.oraclesToPoll.get(oracleString); await this.addOracleToAccountLoader(oracleToPoll); } - await this.pauseForOracleToBeAdded(3, oracleInfo.publicKey.toBase58()); + await this.pauseForOracleToBeAdded(3, oracleString); return true; } @@ -478,7 +464,6 @@ export class PollingDriftClientAccountSubscriber } console.log(`Pausing to find oracle ${oracle} failed`); } - async setPerpOracleMap() { const perpMarkets = this.getMarketAccountsAndSlots(); const oraclePromises = []; @@ -486,8 +471,7 @@ export class PollingDriftClientAccountSubscriber const perpMarketAccount = perpMarket.data; const perpMarketIndex = perpMarketAccount.marketIndex; const oracle = perpMarketAccount.amm.oracle; - const oracleId = getOracleId(oracle, perpMarketAccount.amm.oracleSource); - if (!this.oracles.has(oracleId)) { + if (!this.oracles.has(oracle.toBase58())) { oraclePromises.push( this.addOracle({ publicKey: oracle, @@ -496,7 +480,7 @@ export class PollingDriftClientAccountSubscriber ); } this.perpOracleMap.set(perpMarketIndex, oracle); - this.perpOracleStringMap.set(perpMarketIndex, oracleId); + this.perpOracleStringMap.set(perpMarketIndex, oracle.toBase58()); } await Promise.all(oraclePromises); } @@ -508,8 +492,7 @@ export class PollingDriftClientAccountSubscriber const spotMarketAccount = spotMarket.data; const spotMarketIndex = spotMarketAccount.marketIndex; const oracle = spotMarketAccount.oracle; - const oracleId = getOracleId(oracle, spotMarketAccount.oracleSource); - if (!this.oracles.has(oracleId)) { + if (!this.oracles.has(oracle.toBase58())) { oraclePromises.push( this.addOracle({ publicKey: oracle, @@ -518,7 +501,7 @@ export class PollingDriftClientAccountSubscriber ); } this.spotOracleMap.set(spotMarketIndex, oracle); - this.spotOracleStringMap.set(spotMarketIndex, oracleId); + this.spotOracleStringMap.set(spotMarketIndex, oracle.toBase58()); } await Promise.all(oraclePromises); } @@ -545,11 +528,10 @@ export class PollingDriftClientAccountSubscriber } for (const oracle of oracles) { - const oracleId = getOracleId(oracle.publicKey, oracle.source); - const callbackId = this.oraclesToPoll.get(oracleId).callbackId; - this.accountLoader.removeAccount(oracle.publicKey, callbackId); + const callbackId = this.oraclesToPoll.get(oracle.toBase58()).callbackId; + this.accountLoader.removeAccount(oracle, callbackId); if (this.delistedMarketSetting === DelistedMarketSetting.Discard) { - this.oracles.delete(oracleId); + this.oracles.delete(oracle.toBase58()); } } } @@ -588,17 +570,21 @@ export class PollingDriftClientAccountSubscriber } public getOraclePriceDataAndSlot( - oracleId: string + oraclePublicKey: PublicKey | string ): DataAndSlot | undefined { this.assertIsSubscribed(); - if (oracleId === ORACLE_DEFAULT_ID) { + const oracleString = + typeof oraclePublicKey === 'string' + ? oraclePublicKey + : oraclePublicKey.toBase58(); + if (oracleString === ORACLE_DEFAULT_KEY) { return { data: QUOTE_ORACLE_PRICE_DATA, slot: 0, }; } - return this.oracles.get(oracleId); + return this.oracles.get(oracleString); } public getOraclePriceDataAndSlotForPerpMarket( @@ -606,7 +592,7 @@ export class PollingDriftClientAccountSubscriber ): DataAndSlot | undefined { const perpMarketAccount = this.getMarketAccountAndSlot(marketIndex); const oracle = this.perpOracleMap.get(marketIndex); - const oracleId = this.perpOracleStringMap.get(marketIndex); + const oracleString = this.perpOracleStringMap.get(marketIndex); if (!perpMarketAccount || !oracle) { return undefined; @@ -617,7 +603,7 @@ export class PollingDriftClientAccountSubscriber this.setPerpOracleMap(); } - return this.getOraclePriceDataAndSlot(oracleId); + return this.getOraclePriceDataAndSlot(oracleString); } public getOraclePriceDataAndSlotForSpotMarket( @@ -625,7 +611,7 @@ export class PollingDriftClientAccountSubscriber ): DataAndSlot | undefined { const spotMarketAccount = this.getSpotMarketAccountAndSlot(marketIndex); const oracle = this.spotOracleMap.get(marketIndex); - const oracleId = this.spotOracleStringMap.get(marketIndex); + const oracleString = this.spotOracleStringMap.get(marketIndex); if (!spotMarketAccount || !oracle) { return undefined; } @@ -635,7 +621,7 @@ export class PollingDriftClientAccountSubscriber this.setSpotOracleMap(); } - return this.getOraclePriceDataAndSlot(oracleId); + return this.getOraclePriceDataAndSlot(oracleString); } public updateAccountLoaderPollingFrequency(pollingFrequency: number): void { diff --git a/sdk/src/accounts/types.ts b/sdk/src/accounts/types.ts index 73dfb438c..8eb55ba58 100644 --- a/sdk/src/accounts/types.ts +++ b/sdk/src/accounts/types.ts @@ -43,11 +43,7 @@ export interface DriftClientAccountEvents { stateAccountUpdate: (payload: StateAccount) => void; perpMarketAccountUpdate: (payload: PerpMarketAccount) => void; spotMarketAccountUpdate: (payload: SpotMarketAccount) => void; - oraclePriceUpdate: ( - publicKey: PublicKey, - oracleSource: OracleSource, - data: OraclePriceData - ) => void; + oraclePriceUpdate: (publicKey: PublicKey, data: OraclePriceData) => void; userAccountUpdate: (payload: UserAccount) => void; update: void; error: (e: Error) => void; @@ -77,7 +73,7 @@ export interface DriftClientAccountSubscriber { ): DataAndSlot | undefined; getSpotMarketAccountsAndSlots(): DataAndSlot[]; getOraclePriceDataAndSlot( - oracleId: string + oraclePublicKey: PublicKey | string ): DataAndSlot | undefined; getOraclePriceDataAndSlotForPerpMarket( marketIndex: number diff --git a/sdk/src/accounts/utils.ts b/sdk/src/accounts/utils.ts index 5f91ce37d..b0c57bb94 100644 --- a/sdk/src/accounts/utils.ts +++ b/sdk/src/accounts/utils.ts @@ -1,7 +1,6 @@ +import { PublicKey } from '@solana/web3.js'; import { DataAndSlot } from './types'; import { isVariant, PerpMarketAccount, SpotMarketAccount } from '../types'; -import { OracleInfo } from '../oracles/types'; -import { getOracleId } from '../oracles/oracleId'; export function capitalize(value: string): string { return value[0].toUpperCase() + value.slice(1); @@ -10,9 +9,9 @@ export function capitalize(value: string): string { export function findDelistedPerpMarketsAndOracles( perpMarkets: DataAndSlot[], spotMarkets: DataAndSlot[] -): { perpMarketIndexes: number[]; oracles: OracleInfo[] } { +): { perpMarketIndexes: number[]; oracles: PublicKey[] } { const delistedPerpMarketIndexes = []; - const delistedOracles: OracleInfo[] = []; + const delistedOracles = []; for (const perpMarket of perpMarkets) { if (!perpMarket.data) { continue; @@ -20,39 +19,23 @@ export function findDelistedPerpMarketsAndOracles( if (isVariant(perpMarket.data.status, 'delisted')) { delistedPerpMarketIndexes.push(perpMarket.data.marketIndex); - delistedOracles.push({ - publicKey: perpMarket.data.amm.oracle, - source: perpMarket.data.amm.oracleSource, - }); + delistedOracles.push(perpMarket.data.amm.oracle); } } // make sure oracle isn't used by spot market const filteredDelistedOracles = []; for (const delistedOracle of delistedOracles) { - let isUsedBySpotMarket = false; for (const spotMarket of spotMarkets) { if (!spotMarket.data) { continue; } - const delistedOracleId = getOracleId( - delistedOracle.publicKey, - delistedOracle.source - ); - const spotMarketOracleId = getOracleId( - spotMarket.data.oracle, - spotMarket.data.oracleSource - ); - if (spotMarketOracleId === delistedOracleId) { - isUsedBySpotMarket = true; + if (spotMarket.data.oracle.equals(delistedOracle)) { break; } } - - if (!isUsedBySpotMarket) { - filteredDelistedOracles.push(delistedOracle); - } + filteredDelistedOracles.push(delistedOracle); } return { diff --git a/sdk/src/accounts/webSocketDriftClientAccountSubscriber.ts b/sdk/src/accounts/webSocketDriftClientAccountSubscriber.ts index a21e12d2f..14c93e4ca 100644 --- a/sdk/src/accounts/webSocketDriftClientAccountSubscriber.ts +++ b/sdk/src/accounts/webSocketDriftClientAccountSubscriber.ts @@ -26,13 +26,8 @@ import * as Buffer from 'buffer'; import { QUOTE_ORACLE_PRICE_DATA } from '../oracles/quoteAssetOracleClient'; import { findAllMarketAndOracles } from '../config'; import { findDelistedPerpMarketsAndOracles } from './utils'; -import { getOracleId } from '../oracles/oracleId'; -import { OracleSource } from '../types'; -const ORACLE_DEFAULT_ID = getOracleId( - PublicKey.default, - OracleSource.QUOTE_ASSET -); +const ORACLE_DEFAULT_KEY = PublicKey.default.toBase58(); export class WebSocketDriftClientAccountSubscriber implements DriftClientAccountSubscriber @@ -238,10 +233,7 @@ export class WebSocketDriftClientAccountSubscriber oracleAccountInfos[i].data ); - result.push([ - getOracleId(oracleInfo.publicKey, oracleInfo.source), - oraclePriceData, - ]); + result.push([oracleInfo.publicKey.toString(), oraclePriceData]); return result; }, []) ); @@ -330,7 +322,7 @@ export class WebSocketDriftClientAccountSubscriber } async subscribeToOracle(oracleInfo: OracleInfo): Promise { - const oracleId = getOracleId(oracleInfo.publicKey, oracleInfo.source); + const oracleString = oracleInfo.publicKey.toString(); const client = this.oracleClientCache.get( oracleInfo.source, this.program.provider.connection, @@ -346,21 +338,17 @@ export class WebSocketDriftClientAccountSubscriber this.resubOpts, this.commitment ); - const initialOraclePriceData = this.initialOraclePriceData.get(oracleId); + const initialOraclePriceData = + this.initialOraclePriceData.get(oracleString); if (initialOraclePriceData) { accountSubscriber.setData(initialOraclePriceData); } await accountSubscriber.subscribe((data: OraclePriceData) => { - this.eventEmitter.emit( - 'oraclePriceUpdate', - oracleInfo.publicKey, - oracleInfo.source, - data - ); + this.eventEmitter.emit('oraclePriceUpdate', oracleInfo.publicKey, data); this.eventEmitter.emit('update'); }); - this.oracleSubscribers.set(oracleId, accountSubscriber); + this.oracleSubscribers.set(oracleString, accountSubscriber); return true; } @@ -441,8 +429,7 @@ export class WebSocketDriftClientAccountSubscriber } async addOracle(oracleInfo: OracleInfo): Promise { - const oracleId = getOracleId(oracleInfo.publicKey, oracleInfo.source); - if (this.oracleSubscribers.has(oracleId)) { + if (this.oracleSubscribers.has(oracleInfo.publicKey.toString())) { return true; } @@ -463,8 +450,7 @@ export class WebSocketDriftClientAccountSubscriber const perpMarketAccount = perpMarket.data; const perpMarketIndex = perpMarketAccount.marketIndex; const oracle = perpMarketAccount.amm.oracle; - const oracleId = getOracleId(oracle, perpMarket.data.amm.oracleSource); - if (!this.oracleSubscribers.has(oracleId)) { + if (!this.oracleSubscribers.has(oracle.toBase58())) { addOraclePromises.push( this.addOracle({ publicKey: oracle, @@ -473,7 +459,7 @@ export class WebSocketDriftClientAccountSubscriber ); } this.perpOracleMap.set(perpMarketIndex, oracle); - this.perpOracleStringMap.set(perpMarketIndex, oracleId); + this.perpOracleStringMap.set(perpMarketIndex, oracle.toBase58()); } await Promise.all(addOraclePromises); } @@ -488,8 +474,7 @@ export class WebSocketDriftClientAccountSubscriber const spotMarketAccount = spotMarket.data; const spotMarketIndex = spotMarketAccount.marketIndex; const oracle = spotMarketAccount.oracle; - const oracleId = getOracleId(oracle, spotMarketAccount.oracleSource); - if (!this.oracleSubscribers.has(oracleId)) { + if (!this.oracleSubscribers.has(oracle.toBase58())) { addOraclePromises.push( this.addOracle({ publicKey: oracle, @@ -498,7 +483,7 @@ export class WebSocketDriftClientAccountSubscriber ); } this.spotOracleMap.set(spotMarketIndex, oracle); - this.spotOracleStringMap.set(spotMarketIndex, oracleId); + this.spotOracleStringMap.set(spotMarketIndex, oracle.toBase58()); } await Promise.all(addOraclePromises); } @@ -523,10 +508,9 @@ export class WebSocketDriftClientAccountSubscriber } for (const oracle of oracles) { - const oracleId = getOracleId(oracle.publicKey, oracle.source); - await this.oracleSubscribers.get(oracleId).unsubscribe(); + await this.oracleSubscribers.get(oracle.toBase58()).unsubscribe(); if (this.delistedMarketSetting === DelistedMarketSetting.Discard) { - this.oracleSubscribers.delete(oracleId); + this.oracleSubscribers.delete(oracle.toBase58()); } } } @@ -571,16 +555,20 @@ export class WebSocketDriftClientAccountSubscriber } public getOraclePriceDataAndSlot( - oracleId: string + oraclePublicKey: PublicKey | string ): DataAndSlot | undefined { this.assertIsSubscribed(); - if (oracleId === ORACLE_DEFAULT_ID) { + const oracleString = + typeof oraclePublicKey === 'string' + ? oraclePublicKey + : oraclePublicKey.toBase58(); + if (oracleString === ORACLE_DEFAULT_KEY) { return { data: QUOTE_ORACLE_PRICE_DATA, slot: 0, }; } - return this.oracleSubscribers.get(oracleId).dataAndSlot; + return this.oracleSubscribers.get(oracleString).dataAndSlot; } public getOraclePriceDataAndSlotForPerpMarket( @@ -588,8 +576,8 @@ export class WebSocketDriftClientAccountSubscriber ): DataAndSlot | undefined { const perpMarketAccount = this.getMarketAccountAndSlot(marketIndex); const oracle = this.perpOracleMap.get(marketIndex); - const oracleId = this.perpOracleStringMap.get(marketIndex); - if (!perpMarketAccount || !oracleId) { + const oracleString = this.perpOracleStringMap.get(marketIndex); + if (!perpMarketAccount || !oracle) { return undefined; } @@ -598,7 +586,7 @@ export class WebSocketDriftClientAccountSubscriber this.setPerpOracleMap(); } - return this.getOraclePriceDataAndSlot(oracleId); + return this.getOraclePriceDataAndSlot(oracleString); } public getOraclePriceDataAndSlotForSpotMarket( @@ -606,8 +594,8 @@ export class WebSocketDriftClientAccountSubscriber ): DataAndSlot | undefined { const spotMarketAccount = this.getSpotMarketAccountAndSlot(marketIndex); const oracle = this.spotOracleMap.get(marketIndex); - const oracleId = this.spotOracleStringMap.get(marketIndex); - if (!spotMarketAccount || !oracleId) { + const oracleString = this.spotOracleStringMap.get(marketIndex); + if (!spotMarketAccount || !oracle) { return undefined; } @@ -616,6 +604,6 @@ export class WebSocketDriftClientAccountSubscriber this.setSpotOracleMap(); } - return this.getOraclePriceDataAndSlot(oracleId); + return this.getOraclePriceDataAndSlot(oracleString); } } diff --git a/sdk/src/config.ts b/sdk/src/config.ts index 32adc95b1..33e6be442 100644 --- a/sdk/src/config.ts +++ b/sdk/src/config.ts @@ -18,7 +18,6 @@ import { ON_DEMAND_DEVNET_PID, ON_DEMAND_MAINNET_PID, } from '@switchboard-xyz/on-demand'; -import { getOracleId } from './oracles/oracleId'; type DriftConfig = { ENV: DriftEnv; @@ -135,7 +134,7 @@ export function getMarketsAndOraclesForSubscription( for (const market of perpMarketsToUse) { perpMarketIndexes.push(market.marketIndex); - oracleInfos.set(getOracleId(market.oracle, market.oracleSource), { + oracleInfos.set(market.oracle.toString(), { publicKey: market.oracle, source: market.oracleSource, }); @@ -143,7 +142,7 @@ export function getMarketsAndOraclesForSubscription( for (const spotMarket of spotMarketsToUse) { spotMarketIndexes.push(spotMarket.marketIndex); - oracleInfos.set(getOracleId(spotMarket.oracle, spotMarket.oracleSource), { + oracleInfos.set(spotMarket.oracle.toString(), { publicKey: spotMarket.oracle, source: spotMarket.oracleSource, }); @@ -175,19 +174,16 @@ export async function findAllMarketAndOracles(program: Program): Promise<{ for (const perpMarketProgramAccount of perpMarketProgramAccounts) { const perpMarket = perpMarketProgramAccount.account as PerpMarketAccount; perpMarketIndexes.push(perpMarket.marketIndex); - oracleInfos.set( - getOracleId(perpMarket.amm.oracle, perpMarket.amm.oracleSource), - { - publicKey: perpMarket.amm.oracle, - source: perpMarket.amm.oracleSource, - } - ); + oracleInfos.set(perpMarket.amm.oracle.toString(), { + publicKey: perpMarket.amm.oracle, + source: perpMarket.amm.oracleSource, + }); } for (const spotMarketProgramAccount of spotMarketProgramAccounts) { const spotMarket = spotMarketProgramAccount.account as SpotMarketAccount; spotMarketIndexes.push(spotMarket.marketIndex); - oracleInfos.set(getOracleId(spotMarket.oracle, spotMarket.oracleSource), { + oracleInfos.set(spotMarket.oracle.toString(), { publicKey: spotMarket.oracle, source: spotMarket.oracleSource, }); diff --git a/sdk/src/driftClient.ts b/sdk/src/driftClient.ts index fb1305992..f64b1ad0a 100644 --- a/sdk/src/driftClient.ts +++ b/sdk/src/driftClient.ts @@ -31,7 +31,6 @@ import { ModifyOrderPolicy, OpenbookV2FulfillmentConfigAccount, OptionalOrderParams, - OracleSource, Order, OrderParams, OrderTriggerCondition, @@ -176,7 +175,6 @@ import { gprcDriftClientAccountSubscriber } from './accounts/grpcDriftClientAcco import nacl from 'tweetnacl'; import { digest } from './util/digest'; import { Slothash } from './slot/SlothashSubscriber'; -import { getOracleId } from './oracles/oracleId'; type RemainingAccountParams = { userAccounts: UserAccount[]; @@ -602,11 +600,10 @@ export class DriftClient { } public getOraclePriceDataAndSlot( - oraclePublicKey: PublicKey, - oracleSource: OracleSource + oraclePublicKey: PublicKey ): DataAndSlot | undefined { return this.accountSubscriber.getOraclePriceDataAndSlot( - getOracleId(oraclePublicKey, oracleSource) + oraclePublicKey.toBase58() ); } diff --git a/sdk/src/oracles/oracleId.ts b/sdk/src/oracles/oracleId.ts deleted file mode 100644 index 396c85660..000000000 --- a/sdk/src/oracles/oracleId.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { PublicKey } from '@solana/web3.js'; -import { OracleSource, OracleSourceNum } from '../types'; - -export function getOracleSourceNum(source: OracleSource): number { - if ('pyth' in source) return OracleSourceNum.PYTH; - if ('pyth1K' in source) return OracleSourceNum.PYTH_1K; - if ('pyth1M' in source) return OracleSourceNum.PYTH_1M; - if ('pythPull' in source) return OracleSourceNum.PYTH_PULL; - if ('pyth1KPull' in source) return OracleSourceNum.PYTH_1K_PULL; - if ('pyth1MPull' in source) return OracleSourceNum.PYTH_1M_PULL; - if ('switchboard' in source) return OracleSourceNum.SWITCHBOARD; - if ('quoteAsset' in source) return OracleSourceNum.QUOTE_ASSET; - if ('pythStableCoin' in source) return OracleSourceNum.PYTH_STABLE_COIN; - if ('pythStableCoinPull' in source) - return OracleSourceNum.PYTH_STABLE_COIN_PULL; - if ('prelaunch' in source) return OracleSourceNum.PRELAUNCH; - if ('switchboardOnDemand' in source) - return OracleSourceNum.SWITCHBOARD_ON_DEMAND; - throw new Error('Invalid oracle source'); -} - -export function getOracleId( - publicKey: PublicKey, - source: OracleSource -): string { - return `${publicKey.toBase58()}-${getOracleSourceNum(source)}`; -} diff --git a/sdk/src/types.ts b/sdk/src/types.ts index 611fc0bb4..6a48ac5ca 100644 --- a/sdk/src/types.ts +++ b/sdk/src/types.ts @@ -132,21 +132,6 @@ export class OracleSource { static readonly SWITCHBOARD_ON_DEMAND = { switchboardOnDemand: {} }; } -export class OracleSourceNum { - static readonly PYTH = 0; - static readonly PYTH_1K = 1; - static readonly PYTH_1M = 2; - static readonly PYTH_PULL = 3; - static readonly PYTH_1K_PULL = 4; - static readonly PYTH_1M_PULL = 5; - static readonly SWITCHBOARD = 6; - static readonly QUOTE_ASSET = 7; - static readonly PYTH_STABLE_COIN = 8; - static readonly PYTH_STABLE_COIN_PULL = 9; - static readonly PRELAUNCH = 10; - static readonly SWITCHBOARD_ON_DEMAND = 11; -} - export class OrderType { static readonly LIMIT = { limit: {} }; static readonly TRIGGER_MARKET = { triggerMarket: {} }; diff --git a/test-scripts/run-anchor-tests.sh b/test-scripts/run-anchor-tests.sh index d3dc96070..eb436fe7c 100644 --- a/test-scripts/run-anchor-tests.sh +++ b/test-scripts/run-anchor-tests.sh @@ -44,7 +44,6 @@ test_files=( multipleMakerOrders.ts multipleSpotMakerOrders.ts openbookTest.ts - oracleDiffSources.ts oracleFillPriceGuardrails.ts oracleOffsetOrders.ts order.ts diff --git a/test-scripts/single-anchor-test.sh b/test-scripts/single-anchor-test.sh index 0011ebe5c..06fd3065d 100644 --- a/test-scripts/single-anchor-test.sh +++ b/test-scripts/single-anchor-test.sh @@ -6,7 +6,7 @@ fi export ANCHOR_WALLET=~/.config/solana/id.json -test_files=(oracleDiffSources.ts) +test_files=(forceUserDelete.ts) for test_file in ${test_files[@]}; do ts-mocha -t 300000 ./tests/${test_file} diff --git a/tests/oracleDiffSources.ts b/tests/oracleDiffSources.ts deleted file mode 100644 index 3971f6037..000000000 --- a/tests/oracleDiffSources.ts +++ /dev/null @@ -1,229 +0,0 @@ -import * as anchor from '@coral-xyz/anchor'; -import { assert } from 'chai'; - -import { Program } from '@coral-xyz/anchor'; - -import { PublicKey } from '@solana/web3.js'; - -import { - TestClient, - BN, - EventSubscriber, - OracleSource, - OracleInfo, - PRICE_PRECISION, - Wallet, - DriftClient, - PEG_PRECISION, -} from '../sdk/src'; - -import { - createFundedKeyPair, - createUserWithUSDCAccount, - initializeQuoteSpotMarket, - initializeSolSpotMarket, - mockOracleNoProgram, - mockUSDCMint, - mockUserUSDCAccount, -} from './testHelpers'; -// import { PRICE_PRECISION, PEG_PRECISION, Wallet, DriftClient } from '../sdk'; -import { startAnchor } from 'solana-bankrun'; -import { TestBulkAccountLoader } from '../sdk/src/accounts/testBulkAccountLoader'; -import { BankrunContextWrapper } from '../sdk/src/bankrun/bankrunConnection'; - -describe('oracle diff sources', () => { - const chProgram = anchor.workspace.Drift as Program; - - let admin: TestClient; - let eventSubscriber: EventSubscriber; - - let bulkAccountLoader: TestBulkAccountLoader; - - let bankrunContextWrapper: BankrunContextWrapper; - - let solOracle: PublicKey; - - let usdcMint; - - const usdcAmount = new BN(10 * 10 ** 6); - const largeUsdcAmount = new BN(10_000 * 10 ** 6); - - const mantissaSqrtScale = new BN(Math.sqrt(PRICE_PRECISION.toNumber())); - const ammInitialQuoteAssetReserve = new anchor.BN(5 * 10 ** 13).mul( - mantissaSqrtScale - ); - const ammInitialBaseAssetReserve = new anchor.BN(5 * 10 ** 13).mul( - mantissaSqrtScale - ); - - let marketIndexes: number[]; - let spotMarketIndexes: number[]; - let oracleInfos: OracleInfo[]; - - before(async () => { - const context = await startAnchor('', [], []); - - bankrunContextWrapper = new BankrunContextWrapper(context); - - bulkAccountLoader = new TestBulkAccountLoader( - bankrunContextWrapper.connection, - 'processed', - 1 - ); - - eventSubscriber = new EventSubscriber( - bankrunContextWrapper.connection.toConnection(), - chProgram - ); - - await eventSubscriber.subscribe(); - - usdcMint = await mockUSDCMint(bankrunContextWrapper); - await mockUserUSDCAccount(usdcMint, largeUsdcAmount, bankrunContextWrapper); - - solOracle = await mockOracleNoProgram(bankrunContextWrapper, 3); - - marketIndexes = [0, 1]; - spotMarketIndexes = [0, 1, 2]; - oracleInfos = [ - { publicKey: solOracle, source: OracleSource.PYTH }, - { publicKey: solOracle, source: OracleSource.PYTH_1K }, - ]; - - admin = new TestClient({ - connection: bankrunContextWrapper.connection.toConnection(), - wallet: bankrunContextWrapper.provider.wallet, - programID: chProgram.programId, - opts: { - commitment: 'confirmed', - }, - activeSubAccountId: 0, - perpMarketIndexes: marketIndexes, - spotMarketIndexes: spotMarketIndexes, - subAccountIds: [], - oracleInfos, - accountSubscription: { - type: 'polling', - accountLoader: bulkAccountLoader, - }, - }); - - await admin.initialize(usdcMint.publicKey, true); - await admin.subscribe(); - await initializeQuoteSpotMarket(admin, usdcMint.publicKey); - - await initializeSolSpotMarket( - admin, - solOracle, - undefined, - OracleSource.PYTH - ); - - await initializeSolSpotMarket( - admin, - solOracle, - undefined, - OracleSource.PYTH_1K - ); - - const periodicity = new BN(0); - await admin.initializePerpMarket( - 0, - solOracle, - ammInitialBaseAssetReserve, - ammInitialQuoteAssetReserve, - periodicity, - new BN(3 * PEG_PRECISION.toNumber()), - OracleSource.PYTH - ); - - await admin.initializePerpMarket( - 1, - solOracle, - ammInitialBaseAssetReserve, - ammInitialQuoteAssetReserve, - periodicity, - new BN(3000 * PEG_PRECISION.toNumber()), - OracleSource.PYTH_1K - ); - }); - - beforeEach(async () => { - // await admin.updateSpotMarketOracle(1, solOracle, OracleSource.PYTH); - // await admin.updatePerpMarketOracle(0, solOracle, OracleSource.PYTH); - }); - - after(async () => { - await admin.unsubscribe(); - await eventSubscriber.unsubscribe(); - }); - - it('polling', async () => { - const [driftClient, _usdcAccount, _userKeyPair] = - await createUserWithUSDCAccount( - bankrunContextWrapper, - usdcMint, - chProgram, - usdcAmount, - marketIndexes, - spotMarketIndexes, - oracleInfos, - bulkAccountLoader - ); - - assert(driftClient.getSpotMarketAccount(1).oracle.equals(solOracle)); - assert(driftClient.getSpotMarketAccount(2).oracle.equals(solOracle)); - - const normalPrice = await driftClient.getOracleDataForSpotMarket(1); - assert(normalPrice.price.eq(PRICE_PRECISION.muln(3))); - - const oneKPrice = await driftClient.getOracleDataForSpotMarket(2); - assert(oneKPrice.price.eq(PRICE_PRECISION.muln(3000))); - - assert(driftClient.getPerpMarketAccount(0).amm.oracle.equals(solOracle)); - assert(driftClient.getPerpMarketAccount(1).amm.oracle.equals(solOracle)); - - const normalPerpPrice = await driftClient.getOracleDataForPerpMarket(0); - assert(normalPerpPrice.price.eq(PRICE_PRECISION.muln(3))); - - const oneKPerpPrice = await driftClient.getOracleDataForPerpMarket(1); - assert(oneKPerpPrice.price.eq(PRICE_PRECISION.muln(3000))); - - await driftClient.unsubscribe(); - }); - - it('ws', async () => { - const userKeyPair = await createFundedKeyPair(bankrunContextWrapper); - const driftClient = new DriftClient({ - connection: bankrunContextWrapper.connection.toConnection(), - wallet: new Wallet(userKeyPair), - programID: admin.program.programId, - opts: { - commitment: 'confirmed', - }, - activeSubAccountId: 0, - perpMarketIndexes: marketIndexes, - spotMarketIndexes: spotMarketIndexes, - subAccountIds: [], - oracleInfos, - accountSubscription: { - type: 'websocket', - }, - }); - await driftClient.subscribe(); - - const normalPrice = await driftClient.getOracleDataForSpotMarket(1); - assert(normalPrice.price.eq(PRICE_PRECISION.muln(3))); - - const oneKPrice = await driftClient.getOracleDataForSpotMarket(2); - assert(oneKPrice.price.eq(PRICE_PRECISION.muln(3000))); - - const normalPerpPrice = await driftClient.getOracleDataForPerpMarket(0); - assert(normalPerpPrice.price.eq(PRICE_PRECISION.muln(3))); - - const oneKPerpPrice = await driftClient.getOracleDataForPerpMarket(1); - assert(oneKPerpPrice.price.eq(PRICE_PRECISION.muln(3000))); - - await driftClient.unsubscribe(); - }); -}); diff --git a/tests/testHelpers.ts b/tests/testHelpers.ts index f3d93719f..9f332d5e5 100644 --- a/tests/testHelpers.ts +++ b/tests/testHelpers.ts @@ -1033,8 +1033,7 @@ export async function initializeQuoteSpotMarket( export async function initializeSolSpotMarket( admin: TestClient, solOracle: PublicKey, - solMint = NATIVE_MINT, - oracleSource: OracleSource = OracleSource.PYTH + solMint = NATIVE_MINT ): Promise { const optimalUtilization = SPOT_MARKET_RATE_PRECISION.div( new BN(2) @@ -1063,7 +1062,7 @@ export async function initializeSolSpotMarket( optimalRate, maxRate, solOracle, - oracleSource, + OracleSource.PYTH, initialAssetWeight, maintenanceAssetWeight, initialLiabilityWeight,