use rialo_api_types::messages::submit_epoch_change::{
SubmitEpochChangeRequest, SubmitEpochChangeResponse,
};
use crate::rpc::types::{
GetSecretSharingPubkeyResponse, GetTriggeredTransactionsResponse, GetWorkflowLineageResponse,
WorkflowLineage,
};
pub struct MockRpcClient {
pub account_info: Option<crate::rpc::types::AccountInfo>,
pub balance: u64,
pub signature: crate::rpc::types::Signature,
pub block_height: u64,
pub slot: u64,
pub transaction: Option<crate::rpc::types::Transaction>,
pub transaction_count: u64,
pub rent_exemption: u64,
pub signature_statuses: Vec<Option<crate::rpc::types::SignatureStatus>>,
pub subscriptions: Vec<rialo_shared_types::Subscription>,
pub triggered_transactions: crate::rpc::types::GetTriggeredTransactionsResponse,
pub workflow_lineage: crate::rpc::types::GetWorkflowLineageResponse,
pub error_message: Option<String>,
}
pub const MOCK_SIGNATURE: &str =
"4rWVz1CniwxGQJTZkxLfKc9qCCPGAL1HKLHJWkAdbfdiJeXRJkpvHxHjvEZMtWrJdXKFKBSRVdGLKFMK2jsQCXWx";
pub const MOCK_BLOCKHASH: &str = "EkSnNWid2cvwEVnVx9aBqawnmiCNiDgp3gUdkDPTKN1N";
pub const MOCK_SLOT: u64 = 123456789;
pub const MOCK_FEE: u64 = 5000;
pub const ERROR_MESSAGE: &str = "Invalid signature";
impl Default for MockRpcClient {
fn default() -> Self {
use std::str::FromStr;
use crate::rpc::types::*;
Self {
account_info: Some(AccountInfo {
kelvin: 100,
owner: rialo_s_sdk::system_program::id().to_string(),
data: vec![],
executable: false,
rent_epoch: 0,
space: 0,
}),
balance: 100,
signature: Signature::from_str(MOCK_SIGNATURE).unwrap(),
block_height: MOCK_SLOT, slot: MOCK_SLOT,
transaction: Some(Transaction {
signatures: vec![Signature::from_str(MOCK_SIGNATURE).unwrap().to_string()],
message: TransactionMessage {
header: MessageHeader {
num_required_signatures: 1,
num_readonly_signed_accounts: 0,
num_readonly_unsigned_accounts: 1,
},
account_keys: vec![
Pubkey::new_unique().to_string(),
rialo_s_sdk::system_program::id().to_string(),
],
instructions: vec![],
},
valid_from: 0, }),
transaction_count: 1000,
rent_exemption: 2039280,
signature_statuses: vec![Some(SignatureStatus {
slot: MOCK_SLOT,
err: None,
executed: true,
})],
subscriptions: vec![],
triggered_transactions: GetTriggeredTransactionsResponse {
transactions: vec![],
},
workflow_lineage: GetWorkflowLineageResponse {
lineage: WorkflowLineage {
workflow_nodes: vec![],
},
leaves: vec![],
truncated: false,
truncation_reason: crate::rpc::types::TruncationReason::None,
continuation_hints: vec![],
},
error_message: None,
}
}
}
impl MockRpcClient {
pub fn new() -> Self {
Self::default()
}
pub fn with_error(mut self, error_message: String) -> Self {
self.error_message = Some(error_message);
self
}
pub fn with_account_info(mut self, account_info: crate::rpc::types::AccountInfo) -> Self {
self.account_info = Some(account_info);
self
}
pub fn with_no_account(mut self) -> Self {
self.account_info = None;
self
}
pub fn with_balance(mut self, balance: u64) -> Self {
self.balance = balance;
self
}
pub fn with_signature(mut self, signature: crate::rpc::types::Signature) -> Self {
self.signature = signature;
self
}
pub fn with_transaction(mut self, transaction: crate::rpc::types::Transaction) -> Self {
self.transaction = Some(transaction);
self
}
pub fn with_transaction_count(mut self, count: u64) -> Self {
self.transaction_count = count;
self
}
pub fn with_rent_exemption(mut self, rent_exemption: u64) -> Self {
self.rent_exemption = rent_exemption;
self
}
pub fn with_slot(mut self, slot: u64) -> Self {
self.slot = slot;
self
}
pub fn with_block_height(mut self, block_height: u64) -> Self {
self.block_height = block_height;
self
}
pub fn with_subscriptions(
mut self,
subscriptions: Vec<rialo_shared_types::Subscription>,
) -> Self {
self.subscriptions = subscriptions;
self
}
pub fn with_triggered_transactions(
mut self,
triggered_transactions: crate::rpc::types::GetTriggeredTransactionsResponse,
) -> Self {
self.triggered_transactions = triggered_transactions;
self
}
pub fn with_signature_statuses(
mut self,
signature_statuses: Vec<Option<crate::rpc::types::SignatureStatus>>,
) -> Self {
self.signature_statuses = signature_statuses;
self
}
}
#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
impl crate::rpc::traits::RpcClient for MockRpcClient {
async fn call_with_json(
&self,
_method: &str,
_params: serde_json::Value,
) -> crate::error::Result<serde_json::Value> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(serde_json::json!({"success": true}))
}
async fn get_balance(&self, _pubkey: &crate::rpc::types::Pubkey) -> crate::error::Result<u64> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(self.balance)
}
async fn send_transaction(
&self,
_transaction: &[u8],
_options: Option<crate::rpc::types::SendTransactionOptions>,
) -> crate::error::Result<crate::rpc::types::Signature> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(self.signature)
}
async fn get_account_info(
&self,
_pubkey: &crate::rpc::types::Pubkey,
) -> crate::error::Result<crate::rpc::types::AccountInfo> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
match &self.account_info {
Some(info) => Ok(info.clone()),
None => Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message("Account not found".to_string()),
)),
}
}
async fn get_block_height(&self) -> crate::error::Result<u64> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(self.block_height)
}
async fn get_block_height_with_config(
&self,
_min_context_slot: Option<u64>,
) -> crate::error::Result<u64> {
self.get_block_height().await
}
async fn get_transaction(
&self,
_signature: &crate::rpc::types::Signature,
) -> crate::error::Result<crate::rpc::types::TransactionResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
match &self.transaction {
Some(tx) => Ok(crate::rpc::types::TransactionResponse {
block_height: self.block_height,
block_hash: MOCK_BLOCKHASH.to_string(),
meta: crate::rpc::types::TransactionStatusMetadata {
log_messages: Some(vec![]),
err: None,
fee: MOCK_FEE,
},
transaction: crate::rpc::types::Transaction {
signatures: tx.signatures.clone(),
message: crate::rpc::types::TransactionMessage {
header: crate::rpc::types::MessageHeader {
num_required_signatures: tx.message.header.num_required_signatures,
num_readonly_signed_accounts: tx
.message
.header
.num_readonly_signed_accounts,
num_readonly_unsigned_accounts: tx
.message
.header
.num_readonly_unsigned_accounts,
},
account_keys: tx.message.account_keys.clone(),
instructions: vec![], },
valid_from: 0, },
block_time: None,
}),
None => Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message("Transaction not found".to_string()),
)),
}
}
async fn get_transaction_count(&self) -> crate::error::Result<u64> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(self.transaction_count)
}
async fn get_minimum_balance_for_rent_exemption(
&self,
_size: u64,
) -> crate::error::Result<u64> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(self.rent_exemption)
}
async fn get_signature_statuses(
&self,
_signatures: &[crate::rpc::types::Signature],
) -> crate::error::Result<Vec<crate::rpc::types::SignatureStatus>> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
let result: Vec<crate::rpc::types::SignatureStatus> = self
.signature_statuses
.iter()
.filter_map(|opt_status| {
opt_status
.as_ref()
.map(|status| crate::rpc::types::SignatureStatus {
slot: status.slot,
err: status.err.clone(),
executed: status.executed,
})
})
.collect();
Ok(result)
}
async fn get_subscription(
&self,
_subscriber: &crate::rpc::types::Pubkey,
_nonce: &str,
) -> crate::error::Result<crate::rpc::types::GetSubscriptionResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
let subscription = self.subscriptions.first().cloned().ok_or_else(|| {
crate::error::RialoError::Rpc(crate::error::RpcErrorDetails::from_message(
"Subscription not found".to_string(),
))
})?;
Ok(crate::rpc::types::GetSubscriptionResponse {
context: crate::rpc::types::RpcResponseContext {
api_version: Some("1.0".to_string()),
slot: MOCK_SLOT,
},
subscription,
})
}
async fn get_triggered_transactions(
&self,
_subscription_account: &crate::rpc::types::Pubkey,
_limit: Option<u32>,
) -> crate::error::Result<crate::rpc::types::GetTriggeredTransactionsResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
let response = GetTriggeredTransactionsResponse {
transactions: self
.triggered_transactions
.transactions
.iter()
.map(|tx| crate::rpc::types::TriggeredTransaction {
signature: tx.signature.clone(),
block_number: tx.block_number,
})
.collect(),
};
Ok(response)
}
async fn get_workflow_lineage(
&self,
_request: &crate::rpc::types::GetWorkflowLineageRequest,
) -> crate::error::Result<crate::rpc::types::GetWorkflowLineageResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(GetWorkflowLineageResponse {
lineage: WorkflowLineage {
workflow_nodes: vec![],
},
leaves: vec![],
truncated: false,
truncation_reason: crate::rpc::types::TruncationReason::None,
continuation_hints: vec![],
})
}
async fn request_airdrop(
&self,
_pubkey: &crate::rpc::types::Pubkey,
_amount: u64,
) -> crate::error::Result<crate::rpc::types::Signature> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(self.signature)
}
async fn get_epoch_info(&self) -> crate::error::Result<crate::rpc::types::EpochInfoResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(crate::rpc::types::EpochInfoResponse {
absolute_slot: 166598,
block_height: 166500,
epoch: 27,
slot_index: 2790,
slots_in_epoch: 8192,
transaction_count: Some(22),
})
}
async fn get_fee_for_message(
&self,
_message: &str,
) -> crate::error::Result<crate::rpc::types::GetFeeForMessageResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(crate::rpc::types::GetFeeForMessageResponse {
context: crate::rpc::types::RpcResponseContext {
api_version: Some("1.0".to_string()),
slot: MOCK_SLOT,
},
value: Some(5000),
})
}
async fn get_multiple_accounts(
&self,
_pubkeys: &[crate::rpc::types::Pubkey],
) -> crate::error::Result<crate::rpc::types::MultipleAccountsResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(crate::rpc::types::MultipleAccountsResponse {
context: crate::rpc::types::RpcResponseContext {
api_version: Some("1.0".to_string()),
slot: MOCK_SLOT,
},
value: vec![],
})
}
async fn get_signatures_for_address(
&self,
_address: &crate::rpc::types::Pubkey,
_config: Option<crate::rpc::types::GetSignaturesForAddressConfig>,
) -> crate::error::Result<crate::rpc::types::GetSignaturesForAddressResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(crate::rpc::types::GetSignaturesForAddressResponse {
context: crate::rpc::types::RpcResponseContext {
api_version: Some("1.0".to_string()),
slot: MOCK_SLOT,
},
value: vec![],
})
}
async fn is_blockhash_valid(
&self,
_blockhash: &crate::rpc::types::Hash,
) -> crate::error::Result<crate::rpc::types::IsBlockhashValidResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(crate::rpc::types::IsBlockhashValidResponse {
context: crate::rpc::types::RpcResponseContext {
api_version: Some("1.0".to_string()),
slot: MOCK_SLOT,
},
value: true,
})
}
async fn get_health(&self) -> crate::error::Result<crate::rpc::types::GetHealthResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(
serde_json::from_str::<crate::rpc::types::GetHealthResponse>(r#"{\"status\":\"ok\"}"#)
.unwrap(),
)
}
async fn get_validator_health(
&self,
) -> crate::error::Result<crate::rpc::types::GetValidatorHealthResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(
serde_json::from_str::<crate::rpc::types::GetValidatorHealthResponse>(
r#"{\"status\":\"ok\"}"#,
)
.unwrap(),
)
}
async fn get_connected_full_nodes(
&self,
) -> crate::error::Result<crate::rpc::types::GetConnectedFullNodesResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(crate::rpc::types::GetConnectedFullNodesResponse::new(
vec![],
))
}
async fn get_transactions(
&self,
_config: Option<crate::rpc::types::GetTransactionsConfig>,
) -> crate::error::Result<crate::rpc::types::GetTransactionsResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(crate::rpc::types::GetTransactionsResponse::new(vec![], 0))
}
async fn get_secret_sharing_pubkey(
&self,
) -> crate::Result<crate::rpc::types::GetSecretSharingPubkeyResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(GetSecretSharingPubkeyResponse::new(&[1u8; 32]))
}
async fn send_admin_transaction(
&self,
_params: SubmitEpochChangeRequest,
) -> crate::Result<SubmitEpochChangeResponse> {
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(SubmitEpochChangeResponse { success: true })
}
async fn get_accounts_by_owner(
&self,
_owner: &crate::rpc::types::Pubkey,
) -> crate::Result<rialo_api_types::messages::get_accounts_by_owner::GetAccountsByOwnerResponse>
{
use rialo_api_types::messages::{
get_accounts_by_owner::GetAccountsByOwnerResponse,
rpc_response_context::RpcResponseContext,
};
if let Some(error_msg) = &self.error_message {
return Err(crate::error::RialoError::Rpc(
crate::error::RpcErrorDetails::from_message(error_msg.clone()),
));
}
Ok(GetAccountsByOwnerResponse {
context: RpcResponseContext::new(self.slot),
value: vec![],
pagination: None,
})
}
}