use crate::rpc::utils::verify_pubkey;
use super::{RpcContextConfig, RunloopContext};
use jsonrpc_core::{Error, Result};
use jsonrpc_derive::rpc;
use solana_client::{
rpc_config::{
RpcGetVoteAccountsConfig, RpcLeaderScheduleConfig, RpcLeaderScheduleConfigWrapper,
},
rpc_custom_error::RpcCustomError,
rpc_response::{
RpcIdentity, RpcLeaderSchedule, RpcSnapshotSlotInfo, RpcVersionInfo, RpcVoteAccountStatus,
},
};
use solana_program_runtime::loaded_programs::{BlockRelation, ForkGraph};
use solana_rpc_client_api::response::Response as RpcResponse;
use solana_sdk::{
clock::{Clock, Slot},
epoch_info::EpochInfo,
};
#[rpc]
pub trait Minimal {
type Metadata;
#[rpc(meta, name = "getBalance")]
fn get_balance(
&self,
meta: Self::Metadata,
pubkey_str: String,
config: Option<RpcContextConfig>,
) -> Result<RpcResponse<u64>>;
#[rpc(meta, name = "getEpochInfo")]
fn get_epoch_info(
&self,
meta: Self::Metadata,
config: Option<RpcContextConfig>,
) -> Result<EpochInfo>;
#[rpc(meta, name = "getGenesisHash")]
fn get_genesis_hash(&self, meta: Self::Metadata) -> Result<String>;
#[rpc(meta, name = "getHealth")]
fn get_health(&self, meta: Self::Metadata) -> Result<String>;
#[rpc(meta, name = "getIdentity")]
fn get_identity(&self, meta: Self::Metadata) -> Result<RpcIdentity>;
#[rpc(meta, name = "getSlot")]
fn get_slot(&self, meta: Self::Metadata, config: Option<RpcContextConfig>) -> Result<Slot>;
#[rpc(meta, name = "getBlockHeight")]
fn get_block_height(
&self,
meta: Self::Metadata,
config: Option<RpcContextConfig>,
) -> Result<u64>;
#[rpc(meta, name = "getHighestSnapshotSlot")]
fn get_highest_snapshot_slot(&self, meta: Self::Metadata) -> Result<RpcSnapshotSlotInfo>;
#[rpc(meta, name = "getTransactionCount")]
fn get_transaction_count(
&self,
meta: Self::Metadata,
config: Option<RpcContextConfig>,
) -> Result<u64>;
#[rpc(meta, name = "getVersion")]
fn get_version(&self, meta: Self::Metadata) -> Result<RpcVersionInfo>;
#[rpc(meta, name = "getVoteAccounts")]
fn get_vote_accounts(
&self,
meta: Self::Metadata,
config: Option<RpcGetVoteAccountsConfig>,
) -> Result<RpcVoteAccountStatus>;
#[rpc(meta, name = "getLeaderSchedule")]
fn get_leader_schedule(
&self,
meta: Self::Metadata,
options: Option<RpcLeaderScheduleConfigWrapper>,
config: Option<RpcLeaderScheduleConfig>,
) -> Result<Option<RpcLeaderSchedule>>;
}
pub struct SurfpoolMinimalRpc;
impl Minimal for SurfpoolMinimalRpc {
type Metadata = Option<RunloopContext>;
fn get_balance(
&self,
meta: Self::Metadata,
pubkey_str: String,
config: Option<RpcContextConfig>,
) -> Result<RpcResponse<u64>> {
println!("get_balance rpc request received: {:?}", pubkey_str);
let pubkey = verify_pubkey(&pubkey_str)?;
unimplemented!()
}
fn get_epoch_info(
&self,
meta: Self::Metadata,
config: Option<RpcContextConfig>,
) -> Result<EpochInfo> {
let Some(ctx) = meta else {
return Err(RpcCustomError::NodeUnhealthy {
num_slots_behind: None,
}
.into());
};
let Ok(state_reader) = ctx.state.try_read() else {
return Err(RpcCustomError::NodeUnhealthy {
num_slots_behind: None,
}
.into());
};
Ok(state_reader.epoch_info.clone())
}
fn get_genesis_hash(&self, meta: Self::Metadata) -> Result<String> {
println!("get_genesis_hash rpc request received");
unimplemented!()
}
fn get_health(&self, meta: Self::Metadata) -> Result<String> {
let Some(ctx) = meta else {
return Err(RpcCustomError::NodeUnhealthy {
num_slots_behind: None,
}
.into());
};
let Ok(_state_reader) = ctx.state.try_read() else {
return Err(RpcCustomError::NodeUnhealthy {
num_slots_behind: None,
}
.into());
};
Ok("ok".to_string())
}
fn get_identity(&self, meta: Self::Metadata) -> Result<RpcIdentity> {
println!("get_identity rpc request received");
unimplemented!()
}
fn get_slot(&self, meta: Self::Metadata, _config: Option<RpcContextConfig>) -> Result<Slot> {
let Some(ctx) = meta else {
return Err(RpcCustomError::NodeUnhealthy {
num_slots_behind: None,
}
.into());
};
let Ok(state_reader) = ctx.state.try_read() else {
return Err(RpcCustomError::NodeUnhealthy {
num_slots_behind: None,
}
.into());
};
let clock: Clock = state_reader.svm.get_sysvar();
Ok(clock.slot.into())
}
fn get_block_height(
&self,
meta: Self::Metadata,
config: Option<RpcContextConfig>,
) -> Result<u64> {
println!("get_block_height rpc request received");
unimplemented!()
}
fn get_highest_snapshot_slot(&self, meta: Self::Metadata) -> Result<RpcSnapshotSlotInfo> {
println!("get_highest_snapshot_slot rpc request received");
unimplemented!()
}
fn get_transaction_count(
&self,
meta: Self::Metadata,
config: Option<RpcContextConfig>,
) -> Result<u64> {
println!("get_transaction_count rpc request received");
unimplemented!()
}
fn get_version(&self, _: Self::Metadata) -> Result<RpcVersionInfo> {
println!("get_version rpc request received");
let version = solana_version::Version::default();
Ok(RpcVersionInfo {
solana_core: version.to_string(),
feature_set: Some(version.feature_set),
})
}
fn get_vote_accounts(
&self,
meta: Self::Metadata,
config: Option<RpcGetVoteAccountsConfig>,
) -> Result<RpcVoteAccountStatus> {
println!("get_vote_accounts rpc request received");
unimplemented!()
}
fn get_leader_schedule(
&self,
meta: Self::Metadata,
options: Option<RpcLeaderScheduleConfigWrapper>,
config: Option<RpcLeaderScheduleConfig>,
) -> Result<Option<RpcLeaderSchedule>> {
unimplemented!()
}
}
pub struct MockForkGraph {}
impl ForkGraph for MockForkGraph {
fn relationship(&self, a: Slot, b: Slot) -> BlockRelation {
match a.cmp(&b) {
std::cmp::Ordering::Less => BlockRelation::Ancestor,
std::cmp::Ordering::Equal => BlockRelation::Equal,
std::cmp::Ordering::Greater => BlockRelation::Descendant,
}
}
}