use log::debug;
use serde::Deserialize;
use serde_json::Value;
use crate::http::http_send;
use crate::types::{JsonRpc, JsonRpcRequest};
use crate::utils::random_number;
mod http;
pub mod types;
mod utils;
#[derive(Default, Deserialize, Debug, Clone)]
pub struct BlockScanner {
pub url: Vec<String>,
pub retry: Retry,
pub id: String,
}
#[derive(Deserialize, Debug, Clone)]
pub struct Retry(u32);
impl Default for Retry {
fn default() -> Self {
Retry(3)
}
}
impl BlockScanner {
pub async fn get_block_latest_number(&self) -> Option<JsonRpc> {
let query = JsonRpcRequest {
method: "eth_blockNumber".to_string(),
params: Value::Array(vec![]),
id: self.id.parse().unwrap(),
jsonrpc: "2.0".to_string(),
};
debug!("Query {:?}", query);
http_send(self.url.as_ref(), self.retry.0, query).await
}
pub async fn get_transactions_for_block(&self, number: &str, is_show: bool) -> Option<JsonRpc> {
let query = JsonRpcRequest {
method: "eth_getBlockByNumber".to_string(),
params: Value::Array(vec![
Value::String(number.to_string()),
Value::Bool(is_show),
]),
id: self.id.parse().unwrap(),
jsonrpc: "2.0".to_string(),
};
debug!("Query {:?}", query);
http_send(self.url.as_ref(), self.retry.0, query).await
}
pub async fn get_transaction_receipt_for_hash(&self, hash: &str) -> Option<JsonRpc> {
let query = JsonRpcRequest {
method: "eth_getTransactionReceipt".to_string(),
params: Value::Array(vec![Value::String(hash.to_string())]),
id: self.id.parse().unwrap(),
jsonrpc: "2.0".to_string(),
};
debug!("Query {:?}", query);
http_send(self.url.as_ref(), self.retry.0, query).await
}
}
#[cfg(test)]
mod tests {
use super::*;
#[async_std::test]
async fn test_get_latest_number() {
let bs = BlockScanner {
url: vec![
"https://cloudflare-eth.com/".to_string(),
"https://mainnet.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161".to_string(),
],
retry: Default::default(),
id: "1".to_string(),
};
assert_eq!(true, bs.get_block_latest_number().await.is_some())
}
#[async_std::test]
async fn test_get_transactions_for_block() {
let bs = BlockScanner {
url: vec![
"https://cloudflare-eth.com/".to_string(),
"https://mainnet.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161".to_string(),
],
retry: Default::default(),
id: "1".to_string(),
};
assert_eq!(
true,
bs.get_transactions_for_block("0xe5b544", false)
.await
.unwrap()
.result
.is_some()
);
}
#[async_std::test]
async fn test_get_transactions_for_block_error() {
let bs = BlockScanner {
url: vec![
"https://cloudflare-eth.com/".to_string(),
"https://mainnet.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161".to_string(),
],
retry: Default::default(),
id: "1".to_string(),
};
assert_eq!(
false,
bs.get_transactions_for_block("0xe5a2h0", false)
.await
.unwrap()
.result
.is_some()
);
}
#[async_std::test]
async fn test_get_transaction_receipt_for_hash_error() {
let bs = BlockScanner {
url: vec![
"https://cloudflare-eth.com/".to_string(),
"https://mainnet.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161".to_string(),
],
retry: Default::default(),
id: "1".to_string(),
};
assert_eq!(
false,
bs.get_transaction_receipt_for_hash(
"0x890137f33ba2ddfa9778d55336e83bcac477232d1de7abb3f3dca0ae019798"
)
.await
.unwrap()
.result
.is_some()
);
}
#[async_std::test]
async fn test_get_transaction_receipt_for_hash() {
let bs = BlockScanner {
url: vec![
"https://cloudflare-eth.com/".to_string(),
"https://mainnet.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161".to_string(),
],
retry: Default::default(),
id: "1".to_string(),
};
assert_eq!(
true,
bs.get_transaction_receipt_for_hash(
"0x80fdaa7f5f54cbe28b84f41afb9543cf0c9eb0d9f4b8a620c2fb5faf0b1c2810"
)
.await
.unwrap()
.result
.is_some()
);
}
}