use crate::*;
use solana_client::rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig};
use std::sync::Arc;
#[derive(Default, Debug, Clone)]
pub struct FunctionServiceFilters {
pub attestation_queue: Option<Pubkey>,
pub worker: Option<Pubkey>,
}
impl FunctionServiceFilters {
pub fn to_vec(&self) -> Vec<solana_client::rpc_filter::RpcFilterType> {
if self.attestation_queue.is_none() && self.worker.is_none() {
return vec![];
}
if self.attestation_queue.is_some() && self.worker.is_some() {
return vec![FunctionServiceAccountData::get_queue_and_worker_filter(
&self.attestation_queue.unwrap(),
&self.worker.unwrap(),
)];
}
let mut filters = vec![FunctionServiceAccountData::get_discriminator_filter()];
if let Some(attestation_queue) = &self.attestation_queue {
filters.push(FunctionServiceAccountData::get_queue_filter(
attestation_queue,
));
}
if let Some(worker) = &self.worker {
filters.push(FunctionServiceAccountData::get_worker_filter(worker));
}
filters
}
}
impl FunctionServiceAccountData {
pub async fn get_program_accounts(
rpc: &solana_client::nonblocking::rpc_client::RpcClient,
filters: FunctionServiceFilters,
) -> Result<Vec<(Pubkey, FunctionServiceAccountData)>, SbError> {
let mut routines = vec![];
let accounts = rpc
.get_program_accounts_with_config(
&*SWITCHBOARD_ATTESTATION_PROGRAM_ID,
RpcProgramAccountsConfig {
filters: Some(filters.to_vec()),
account_config: RpcAccountInfoConfig {
encoding: Some(solana_account_decoder::UiAccountEncoding::Base64Zstd),
..Default::default()
},
..Default::default()
},
)
.await
.map_err(|e| SbError::CustomError {
message: "Failed to get program accounts".to_string(),
source: Arc::new(e),
})?;
for (pubkey, account) in accounts {
if let Ok(routine_data) =
FunctionServiceAccountData::try_deserialize(&mut &account.data[..])
{
routines.push((pubkey, routine_data));
}
}
Ok(routines)
}
pub fn fetch(
client: &solana_client::rpc_client::RpcClient,
pubkey: Pubkey,
) -> std::result::Result<Self, switchboard_common::SbError> {
crate::client::fetch_borsh_account(client, pubkey)
}
pub async fn fetch_async(
client: &solana_client::nonblocking::rpc_client::RpcClient,
pubkey: Pubkey,
) -> std::result::Result<Self, switchboard_common::SbError> {
crate::client::fetch_borsh_account_async(client, pubkey).await
}
pub fn fetch_sync<T: solana_sdk::client::SyncClient>(
client: &T,
pubkey: Pubkey,
) -> std::result::Result<Self, switchboard_common::SbError> {
crate::client::fetch_borsh_account_sync(client, pubkey)
}
pub fn get_discriminator_filter() -> solana_client::rpc_filter::RpcFilterType {
solana_client::rpc_filter::RpcFilterType::Memcmp(
solana_client::rpc_filter::Memcmp::new_raw_bytes(
0,
FunctionServiceAccountData::discriminator().to_vec(),
),
)
}
pub fn get_authority_filter(
authority_pubkey: &Pubkey,
) -> solana_client::rpc_filter::RpcFilterType {
solana_client::rpc_filter::RpcFilterType::Memcmp(
solana_client::rpc_filter::Memcmp::new_raw_bytes(
419,
authority_pubkey.to_bytes().into(),
),
)
}
pub fn get_queue_filter(queue_pubkey: &Pubkey) -> solana_client::rpc_filter::RpcFilterType {
solana_client::rpc_filter::RpcFilterType::Memcmp(
solana_client::rpc_filter::Memcmp::new_raw_bytes(8, queue_pubkey.to_bytes().into()),
)
}
pub fn get_worker_filter(queue_pubkey: &Pubkey) -> solana_client::rpc_filter::RpcFilterType {
solana_client::rpc_filter::RpcFilterType::Memcmp(
solana_client::rpc_filter::Memcmp::new_raw_bytes(40, queue_pubkey.to_bytes().into()),
)
}
pub fn get_queue_and_worker_filter(
queue_pubkey: &Pubkey,
worker_pubkey: &Pubkey,
) -> solana_client::rpc_filter::RpcFilterType {
let bytes = vec![queue_pubkey.to_bytes(), worker_pubkey.to_bytes()].concat();
solana_client::rpc_filter::RpcFilterType::Memcmp(
solana_client::rpc_filter::Memcmp::new_raw_bytes(8, bytes.into()),
)
}
pub fn get_queue_idx_filter(queue_idx: &u32) -> solana_client::rpc_filter::RpcFilterType {
solana_client::rpc_filter::RpcFilterType::Memcmp(
solana_client::rpc_filter::Memcmp::new_raw_bytes(611, queue_idx.to_le_bytes().to_vec()),
)
}
pub fn get_is_enabled_filter() -> solana_client::rpc_filter::RpcFilterType {
solana_client::rpc_filter::RpcFilterType::Memcmp(
solana_client::rpc_filter::Memcmp::new_raw_bytes(344, 0u8.to_le_bytes().to_vec()),
)
}
pub fn get_metadata_filter(metadata: Vec<u8>) -> solana_client::rpc_filter::RpcFilterType {
solana_client::rpc_filter::RpcFilterType::Memcmp(
solana_client::rpc_filter::Memcmp::new_raw_bytes(72, metadata),
)
}
}