From e3740fad9f301fdc9faeca97e8aecd8b46bf7944 Mon Sep 17 00:00:00 2001 From: jordy25519 Date: Thu, 3 Apr 2025 10:32:47 +0900 Subject: [PATCH 1/2] Add multiple LUT support --- crates/src/constants.rs | 20 +++++++++++--------- crates/src/jit_client.rs | 5 ++--- crates/src/lib.rs | 23 +++++++++++++++-------- crates/src/types.rs | 14 +++++++------- 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/crates/src/constants.rs b/crates/src/constants.rs index b3f3929..a1f737f 100644 --- a/crates/src/constants.rs +++ b/crates/src/constants.rs @@ -31,9 +31,14 @@ pub const TOKEN_PROGRAM_ID: Pubkey = solana_sdk::pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"); /// Drift market lookup table (DevNet) -pub const LUT_DEVNET: Pubkey = solana_sdk::pubkey!("FaMS3U4uBojvGn5FSDEPimddcXsCfwkKsFgMVVnDdxGb"); +pub const LUTS_DEVNET: &[Pubkey] = &[solana_sdk::pubkey!( + "FaMS3U4uBojvGn5FSDEPimddcXsCfwkKsFgMVVnDdxGb" +)]; /// Drift market lookup table (MainNet) -pub const LUT_MAINNET: Pubkey = solana_sdk::pubkey!("Fpys8GRa5RBWfyeN7AaDUwFGD1zkDCA4z3t4CJLV8dfL"); +pub const LUTS_MAINNET: &[Pubkey] = &[ + solana_sdk::pubkey!("Fpys8GRa5RBWfyeN7AaDUwFGD1zkDCA4z3t4CJLV8dfL"), + solana_sdk::pubkey!("EiWSskK5HXnBTptiS5DH6gpAJRVNQ3cAhTKBGaiaysAb"), +]; /// Drift state account pub fn state_account() -> &'static Pubkey { @@ -111,7 +116,7 @@ impl MarketExt for SpotMarket { pub struct ProgramData { spot_markets: &'static [SpotMarket], perp_markets: &'static [PerpMarket], - pub lookup_table: AddressLookupTableAccount, + pub lookup_tables: &'static [AddressLookupTableAccount], } impl ProgramData { @@ -120,17 +125,14 @@ impl ProgramData { Self { spot_markets: &[], perp_markets: &[], - lookup_table: AddressLookupTableAccount { - key: Pubkey::new_from_array([0; 32]), - addresses: vec![], - }, + lookup_tables: &[], } } /// Initialize `ProgramData` pub fn new( mut spot: Vec, mut perp: Vec, - lookup_table: AddressLookupTableAccount, + lookup_tables: Vec, ) -> Self { spot.sort_by(|a, b| a.market_index.cmp(&b.market_index)); perp.sort_by(|a, b| a.market_index.cmp(&b.market_index)); @@ -151,7 +153,7 @@ impl ProgramData { Self { spot_markets: Box::leak(spot.into_boxed_slice()), perp_markets: Box::leak(perp.into_boxed_slice()), - lookup_table, + lookup_tables: Box::leak(lookup_tables.into_boxed_slice()), } } diff --git a/crates/src/jit_client.rs b/crates/src/jit_client.rs index b277f6d..1487211 100644 --- a/crates/src/jit_client.rs +++ b/crates/src/jit_client.rs @@ -218,11 +218,10 @@ impl JitProxyClient { } ixs.push(ix); - let lut = program_data.lookup_table.clone(); + let luts = program_data.lookup_tables; - // TODO: update with multiple-LUTs let message = - v0::Message::try_compile(&maker_authority, ixs.as_slice(), &[lut], Default::default()) + v0::Message::try_compile(&maker_authority, ixs.as_slice(), luts, Default::default()) .expect("failed to compile message"); Ok(VersionedMessage::V0(message)) diff --git a/crates/src/lib.rs b/crates/src/lib.rs index b5b07a6..fc9bb72 100644 --- a/crates/src/lib.rs +++ b/crates/src/lib.rs @@ -737,16 +737,23 @@ impl DriftClientBackend { let spot_market_map = MarketMap::::new(Arc::clone(&pubsub_client), rpc_client.commitment()); - let lookup_table_address = context.lut(); + let lut_pubkeys = context.luts(); - let (_, _, lut) = tokio::try_join!( + let (_, _, lut_accounts) = tokio::try_join!( perp_market_map.sync(&rpc_client), spot_market_map.sync(&rpc_client), rpc_client - .get_account(&lookup_table_address) + .get_multiple_accounts(&lut_pubkeys) .map_err(Into::into), )?; - let lookup_table = utils::deserialize_alt(lookup_table_address, &lut)?; + + let lookup_tables = lut_pubkeys + .into_iter() + .zip(lut_accounts.into_iter()) + .map(|(pubkey, account_data)| { + utils::deserialize_alt(*pubkey, &account_data.unwrap()).expect("LUT decodes") + }) + .collect(); let mut all_oracles = Vec::<(MarketId, Pubkey, OracleSource)>::with_capacity( perp_market_map.len() + spot_market_map.len(), @@ -780,7 +787,7 @@ impl DriftClientBackend { program_data: ProgramData::new( spot_market_map.values(), perp_market_map.values(), - lookup_table, + lookup_tables, ), account_map, perp_market_map, @@ -1171,7 +1178,7 @@ impl<'a> TransactionBuilder<'a> { account_data: user, sub_account, ixs: Default::default(), - lookup_tables: vec![program_data.lookup_table.clone()], + lookup_tables: program_data.lookup_tables.to_vec(), legacy: false, force_markets: Default::default(), } @@ -1186,11 +1193,11 @@ impl<'a> TransactionBuilder<'a> { self.legacy = true; self } - /// Set the tx lookup tables + /// Extend the tx lookup tables (always includes the defacto drift LUTs) pub fn lookup_tables(mut self, lookup_tables: &[AddressLookupTableAccount]) -> Self { self.lookup_tables = lookup_tables.to_vec(); self.lookup_tables - .push(self.program_data.lookup_table.clone()); + .extend(self.program_data.lookup_tables.iter().cloned()); self } diff --git a/crates/src/types.rs b/crates/src/types.rs index 850257e..2da4c6d 100644 --- a/crates/src/types.rs +++ b/crates/src/types.rs @@ -28,7 +28,7 @@ pub use crate::drift_idl::{ types::*, }; use crate::{ - constants::{ids, LUT_DEVNET, LUT_MAINNET}, + constants::{ids, LUTS_DEVNET, LUTS_MAINNET}, drift_idl::errors::ErrorCode, Wallet, }; @@ -53,7 +53,7 @@ pub fn is_one_of_variant(value: &T, variants: &[T]) -> bool { pub struct Context { name: &'static str, /// market lookup table - lut: Pubkey, + luts: &'static [Pubkey], /// pyth program ID pyth: Pubkey, } @@ -63,20 +63,20 @@ impl Context { #[allow(non_upper_case_globals)] pub const MainNet: Context = Self { name: "mainnet", - lut: LUT_MAINNET, + luts: LUTS_MAINNET, pyth: ids::pyth_program::ID, }; /// Target DevNet context #[allow(non_upper_case_globals)] pub const DevNet: Context = Self { name: "devnet", - lut: LUT_DEVNET, + luts: LUTS_DEVNET, pyth: ids::pyth_program::ID_DEVNET, }; - /// Return drift lookup table address - pub fn lut(&self) -> Pubkey { - self.lut + /// Return drift lookup table address(es) + pub fn luts(&self) -> &[Pubkey] { + self.luts } /// Return pyth owner address From deefa6c57a5df28783dedf36dc37fa9a9f57dff2 Mon Sep 17 00:00:00 2001 From: jordy25519 Date: Thu, 3 Apr 2025 10:36:10 +0900 Subject: [PATCH 2/2] tidying --- crates/src/lib.rs | 9 +++++---- crates/src/oraclemap.rs | 12 ------------ 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/crates/src/lib.rs b/crates/src/lib.rs index fc9bb72..629b3ce 100644 --- a/crates/src/lib.rs +++ b/crates/src/lib.rs @@ -743,15 +743,16 @@ impl DriftClientBackend { perp_market_map.sync(&rpc_client), spot_market_map.sync(&rpc_client), rpc_client - .get_multiple_accounts(&lut_pubkeys) + .get_multiple_accounts(lut_pubkeys) .map_err(Into::into), )?; let lookup_tables = lut_pubkeys - .into_iter() - .zip(lut_accounts.into_iter()) + .iter() + .zip(lut_accounts.iter()) .map(|(pubkey, account_data)| { - utils::deserialize_alt(*pubkey, &account_data.unwrap()).expect("LUT decodes") + utils::deserialize_alt(*pubkey, account_data.as_ref().unwrap()) + .expect("LUT decodes") }) .collect(); diff --git a/crates/src/oraclemap.rs b/crates/src/oraclemap.rs index 28d6b29..4368f66 100644 --- a/crates/src/oraclemap.rs +++ b/crates/src/oraclemap.rs @@ -278,18 +278,6 @@ impl OracleMap { .map(|x| x.pubkey) } - /// Return Oracle data by pubkey, if known - /// deprecated, see `get_by_key` instead - // #[deprecated] - // pub fn get(&self, key: &Pubkey) -> Option { - // self.get_by_key(key) - // } - - // /// Return Oracle data by pubkey, if known - // pub fn get_by_key(&self, key: &Pubkey) -> Option { - // self.oraclemap.get(key).map(|o| o.value().clone()) - // } - /// Return Oracle data by market, if known pub fn get_by_market(&self, market: &MarketId) -> Option { if let Some((oracle_pubkey, oracle_source)) = self.oracle_by_market.get(market) {