115 lines
3.0 KiB
Rust
115 lines
3.0 KiB
Rust
use std::sync::atomic::{AtomicU64, Ordering};
|
|
|
|
use bytes::Bytes;
|
|
use serde_json::{json, Value};
|
|
use solana_client::rpc_request::RpcRequest;
|
|
use solana_program::pubkey::Pubkey;
|
|
use solana_rpc_client::nonblocking::rpc_client::RpcClient;
|
|
use solana_rpc_client::rpc_client::SerializableTransaction;
|
|
|
|
use crate::bencher::Run;
|
|
|
|
#[derive(derive_more::Deref)]
|
|
pub struct CustomRpcClient {
|
|
client: reqwest::Client,
|
|
url: String,
|
|
id: AtomicU64,
|
|
metric: Run,
|
|
#[deref]
|
|
rpc_client: RpcClient,
|
|
}
|
|
|
|
// Don't transfer id and bytes_sent
|
|
impl Clone for CustomRpcClient {
|
|
fn clone(&self) -> Self {
|
|
Self::new(self.url.clone())
|
|
}
|
|
}
|
|
|
|
impl From<CustomRpcClient> for Run {
|
|
fn from(val: CustomRpcClient) -> Self {
|
|
val.metric
|
|
}
|
|
}
|
|
|
|
impl CustomRpcClient {
|
|
pub fn new(url: String) -> Self {
|
|
let client = reqwest::Client::new();
|
|
Self {
|
|
client,
|
|
rpc_client: RpcClient::new(url.clone()),
|
|
url,
|
|
id: 1.into(),
|
|
metric: Run::default(),
|
|
}
|
|
}
|
|
|
|
pub async fn raw_get_slot(&mut self) {
|
|
self.send(RpcRequest::GetSlot, Value::Null).await
|
|
}
|
|
|
|
pub async fn raw_get_block(&mut self, slot: impl Into<u64>) {
|
|
self.send(RpcRequest::GetBlock, json! {[slot.into()]}).await
|
|
}
|
|
|
|
pub async fn raw_get_multiple_accounts(&mut self, accounts: Vec<Pubkey>) {
|
|
self.send(
|
|
RpcRequest::GetMultipleAccounts,
|
|
serde_json::to_value(accounts).unwrap(),
|
|
)
|
|
.await
|
|
}
|
|
|
|
pub async fn raw_send_transaction(&mut self, tx: impl SerializableTransaction) {
|
|
self.send(RpcRequest::SendTransaction, json! {[tx]}).await
|
|
}
|
|
|
|
pub async fn raw_simulate_transaction(&mut self, tx: impl SerializableTransaction) {
|
|
self.send(RpcRequest::SimulateTransaction, json! {[tx]})
|
|
.await
|
|
}
|
|
|
|
pub async fn send(&mut self, request: RpcRequest, params: Value) {
|
|
let id = self.id.fetch_add(1, Ordering::Relaxed);
|
|
|
|
let req_raw_body = request
|
|
.build_request_json(id, params)
|
|
.to_string()
|
|
.into_bytes();
|
|
|
|
let bytes_sent = req_raw_body.len();
|
|
self.metric.bytes_sent += bytes_sent as u64;
|
|
|
|
let err = match self.send_raw(req_raw_body).await {
|
|
Ok(res_bytes) => {
|
|
self.metric.bytes_received += 1;
|
|
|
|
let res: Value =
|
|
serde_json::from_slice(&res_bytes).expect("Server invalid response json");
|
|
|
|
if res.get("result").is_some() {
|
|
self.metric.requests_completed += 1;
|
|
return;
|
|
}
|
|
|
|
res["error"].to_string()
|
|
}
|
|
Err(err) => err.to_string(),
|
|
};
|
|
|
|
self.metric.errors.push(err);
|
|
self.metric.requests_failed += 1;
|
|
}
|
|
|
|
pub async fn send_raw(&self, req_raw_body: Vec<u8>) -> anyhow::Result<Bytes> {
|
|
Ok(self
|
|
.client
|
|
.post(&self.url)
|
|
.body(req_raw_body)
|
|
.send()
|
|
.await?
|
|
.bytes()
|
|
.await?)
|
|
}
|
|
}
|