Skip to main content

rootchain_rs/
client.rs

1use crate::error::Error;
2use crate::Result;
3use reqwest::Client;
4use rootchain_core::types::{Address, GovernanceProposal};
5use serde::{Deserialize, Serialize};
6use serde_json::json;
7
8#[derive(Debug, Serialize, Deserialize)]
9pub struct ChainInfo {
10    pub chain_id: String,
11    pub height: u64,
12}
13
14#[derive(Debug, Serialize, Deserialize)]
15pub struct BalanceInfo {
16    pub address: Address,
17    pub balance: u128,
18}
19
20#[derive(Debug, Serialize, Deserialize)]
21pub struct ContractCode {
22    pub address: Address,
23    pub bytecode_hex: String,
24}
25
26#[derive(Debug, Serialize, Deserialize)]
27pub struct StorageValue {
28    pub key: String,
29    pub value: Option<String>,
30}
31#[derive(Debug, Serialize, Deserialize)]
32pub struct TransactionResponse {
33    pub hash: String,
34}
35
36pub struct RpcProvider {
37    client: Client,
38    url: String,
39}
40
41impl RpcProvider {
42    pub fn new(url: &str) -> Self {
43        Self {
44            client: Client::new(),
45            url: url.to_string(),
46        }
47    }
48
49    pub(crate) async fn call<R: for<'de> Deserialize<'de>>(
50        &self,
51        method: &str,
52        params: serde_json::Value,
53    ) -> Result<R> {
54        let request = json!({
55            "jsonrpc": "2.0",
56            "id": 1,
57            "method": method,
58            "params": params
59        });
60
61        let response = self
62            .client
63            .post(&self.url)
64            .json(&request)
65            .send()
66            .await?
67            .json::<serde_json::Value>()
68            .await?;
69
70        if let Some(error) = response.get("error") {
71            return Err(Error::Rpc(error.to_string()));
72        }
73
74        let result = response
75            .get("result")
76            .ok_or_else(|| Error::Rpc("Missing result field".to_string()))?;
77
78        serde_json::from_value(result.clone()).map_err(Into::into)
79    }
80
81    pub async fn get_chain_info(&self) -> Result<ChainInfo> {
82        self.call("rootchain_getChainInfo", json!([])).await
83    }
84
85    pub async fn get_balance(&self, address: &Address) -> Result<BalanceInfo> {
86        self.call("rootchain_getBalance", json!([address])).await
87    }
88
89    pub async fn send_raw_transaction(&self, tx_hex: &str) -> Result<String> {
90        let resp: TransactionResponse = self
91            .call("rootchain_sendRawTransaction", json!([tx_hex]))
92            .await?;
93        Ok(resp.hash)
94    }
95
96    pub async fn list_proposals(&self) -> Result<Vec<GovernanceProposal>> {
97        self.call("rootchain_listProposals", json!([])).await
98    }
99
100    pub async fn get_code(&self, address: &Address) -> Result<ContractCode> {
101        self.call("rootchain_getCode", json!([address])).await
102    }
103
104    pub async fn get_storage_at(&self, address: &Address, key: &str) -> Result<StorageValue> {
105        self.call("rootchain_getStorageAt", json!([address, key]))
106            .await
107    }
108}