Skip to content

Commit

Permalink
oracle switchovers
Browse files Browse the repository at this point in the history
  • Loading branch information
soundsonacid committed Mar 21, 2024
1 parent 1687636 commit a3fff43
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 49 deletions.
94 changes: 89 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ tokio-tungstenite = { version = "0.21.0", features = ["native-tls"] }
regex = "1.10.2"
dashmap = "5.5.3"
rayon = "1.9.0"
clippy = "0.0.302"

[dev-dependencies]
pyth = { git = "https://github.com/drift-labs/protocol-v2.git", tag = "v2.67.0", features = [
Expand Down
57 changes: 40 additions & 17 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ pub struct DriftClientBackend<T: AccountProvider> {
program_data: ProgramData,
perp_market_map: MarketMap<PerpMarket>,
spot_market_map: MarketMap<SpotMarket>,
oracle_map: OracleMap,
oracle_map: Arc<OracleMap>,
}

impl<T: AccountProvider> DriftClientBackend<T> {
Expand All @@ -695,22 +695,12 @@ impl<T: AccountProvider> DriftClientBackend<T> {
let perp_oracles = perp_market_map.oracles();
let spot_oracles = spot_market_map.oracles();

let mut oracles = vec![];
oracles.extend(perp_oracles);
oracles.extend(spot_oracles);

let mut oracle_infos = vec![];
for oracle_info in oracles {
if !oracle_infos.contains(&oracle_info) {
oracle_infos.push(oracle_info)
}
}

let oracle_map = OracleMap::new(
account_provider.commitment_config(),
account_provider.endpoint(),
true,
oracle_infos,
perp_oracles,
spot_oracles,
);

let mut this = Self {
Expand All @@ -719,7 +709,7 @@ impl<T: AccountProvider> DriftClientBackend<T> {
program_data: ProgramData::uninitialized(),
perp_market_map,
spot_market_map,
oracle_map,
oracle_map: Arc::new(oracle_map),
};

let lookup_table_address = market_lookup_table(context);
Expand Down Expand Up @@ -790,14 +780,46 @@ impl<T: AccountProvider> DriftClientBackend<T> {
market_index: u16,
) -> Option<OraclePriceDataAndSlot> {
let market = self.get_perp_market_account_and_slot(market_index)?;
self.get_oracle_price_data_and_slot(market.data.amm.oracle)

let oracle = market.data.amm.oracle;
let current_oracle = self
.oracle_map
.current_perp_oracle(market_index)
.expect("oracle");

if oracle != current_oracle {
let source = market.data.amm.oracle_source;
let clone = self.oracle_map.clone();
tokio::task::spawn_local(async move {
let _ = clone.add_oracle(oracle, source).await;
clone.update_perp_oracle(market_index, oracle)
});
}

self.get_oracle_price_data_and_slot(current_oracle)
}

fn get_oracle_price_data_and_slot_for_spot_market(
&self,
market_index: u16,
) -> Option<OraclePriceDataAndSlot> {
let market = self.get_spot_market_account_and_slot(market_index)?;

let oracle = market.data.oracle;
let current_oracle = self
.oracle_map
.current_spot_oracle(market_index)
.expect("oracle");

if oracle != current_oracle {
let source = market.data.oracle_source;
let clone = self.oracle_map.clone();
tokio::task::spawn_local(async move {
let _ = clone.add_oracle(oracle, source).await;
clone.update_spot_oracle(market_index, oracle);
});
}

self.get_oracle_price_data_and_slot(market.data.oracle)
}

Expand Down Expand Up @@ -1809,12 +1831,13 @@ mod tests {
program_data: ProgramData::uninitialized(),
perp_market_map,
spot_market_map,
oracle_map: OracleMap::new(
oracle_map: Arc::new(OracleMap::new(
CommitmentConfig::processed(),
DEVNET_ENDPOINT.to_string(),
true,
vec![],
),
vec![],
)),
};

DriftClient {
Expand Down
28 changes: 12 additions & 16 deletions src/marketmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,36 +25,32 @@ use solana_sdk::commitment_config::CommitmentConfig;
use solana_sdk::pubkey::Pubkey;

pub trait Market {
const MARKET_TYPE: MarketType;
fn market_index(&self) -> u16;
fn market_type() -> MarketType;
fn oracle_info(&self) -> (Pubkey, OracleSource);
fn oracle_info(&self) -> (u16, Pubkey, OracleSource);
}

impl Market for PerpMarket {
const MARKET_TYPE: MarketType = MarketType::Perp;

fn market_index(&self) -> u16 {
self.market_index
}

fn market_type() -> MarketType {
MarketType::Perp
}

fn oracle_info(&self) -> (Pubkey, OracleSource) {
(self.amm.oracle, self.amm.oracle_source)
fn oracle_info(&self) -> (u16, Pubkey, OracleSource) {
(self.market_index(), self.amm.oracle, self.amm.oracle_source)
}
}

impl Market for SpotMarket {
const MARKET_TYPE: MarketType = MarketType::Spot;

fn market_index(&self) -> u16 {
self.market_index
}

fn market_type() -> MarketType {
MarketType::Spot
}

fn oracle_info(&self) -> (Pubkey, OracleSource) {
(self.oracle, self.oracle_source)
fn oracle_info(&self) -> (u16, Pubkey, OracleSource) {
(self.market_index(), self.oracle, self.oracle_source)
}
}

Expand All @@ -71,7 +67,7 @@ pub struct MarketMap<T: AccountDeserialize> {

impl<T: AccountDeserialize + Clone + Send + Sync + Market + 'static> MarketMap<T> {
pub fn new(commitment: CommitmentConfig, endpoint: String, sync: bool) -> Self {
let filters = vec![get_market_filter(T::market_type())];
let filters = vec![get_market_filter(T::MARKET_TYPE)];
let options = WebsocketProgramAccountOptions {
filters,
commitment,
Expand Down Expand Up @@ -150,7 +146,7 @@ impl<T: AccountDeserialize + Clone + Send + Sync + Market + 'static> MarketMap<T
self.marketmap.iter().map(|x| x.data.clone()).collect()
}

pub fn oracles(&self) -> Vec<(Pubkey, OracleSource)> {
pub fn oracles(&self) -> Vec<(u16, Pubkey, OracleSource)> {
self.values().iter().map(|x| x.oracle_info()).collect()
}

Expand Down
Loading

0 comments on commit a3fff43

Please sign in to comment.