Skip to main content

avalanche_types/jsonrpc/
evm.rs

1//! EVM JSON-RPC requests and responses.
2use crate::codec::serde::{hex_0x_bytes::Hex0xBytes, hex_0x_primitive_types_h256::Hex0xH256};
3use serde::{Deserialize, Serialize};
4use serde_with::serde_as;
5
6/// Response for "eth_blockNumber".
7/// ref. <https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_blocknumber>
8#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
9pub struct BlockNumberResponse {
10    pub jsonrpc: String,
11    pub id: u32,
12
13    #[serde(with = "crate::codec::serde::hex_0x_primitive_types_u256")]
14    pub result: primitive_types::U256,
15}
16
17/// RUST_LOG=debug cargo test --package avalanche-types --lib -- jsonrpc::evm::test_block_number --exact --show-output
18#[test]
19fn test_block_number() {
20    let resp: BlockNumberResponse = serde_json::from_str(
21        "
22
23{
24    \"jsonrpc\": \"2.0\",
25    \"result\": \"0x4b7\",
26    \"id\": 83
27}
28
29",
30    )
31    .unwrap();
32    let expected = BlockNumberResponse {
33        jsonrpc: "2.0".to_string(),
34        id: 83,
35        result: primitive_types::U256::from_str_radix("0x4b7", 16).unwrap(),
36    };
37    assert_eq!(resp, expected);
38}
39
40/// Response for "eth_chainId".
41/// ref. <https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_blocknumber>
42#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
43pub struct ChainIdResponse {
44    pub jsonrpc: String,
45    pub id: u32,
46
47    #[serde(with = "crate::codec::serde::hex_0x_primitive_types_u256")]
48    pub result: primitive_types::U256,
49}
50
51/// RUST_LOG=debug cargo test --package avalanche-types --lib -- jsonrpc::evm::test_chain_id --exact --show-output
52#[test]
53fn test_chain_id() {
54    let resp: ChainIdResponse = serde_json::from_str(
55        "
56
57{
58    \"jsonrpc\": \"2.0\",
59    \"result\": \"0x4b7\",
60    \"id\": 83
61}
62
63",
64    )
65    .unwrap();
66    let expected = ChainIdResponse {
67        jsonrpc: "2.0".to_string(),
68        id: 83,
69        result: primitive_types::U256::from_str_radix("0x4b7", 16).unwrap(),
70    };
71    assert_eq!(resp, expected);
72}
73
74/// Response for "eth_gasPrice".
75/// ref. <https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gasprice>
76#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
77pub struct GasPriceResponse {
78    pub jsonrpc: String,
79    pub id: u32,
80
81    #[serde(with = "crate::codec::serde::hex_0x_primitive_types_u256")]
82    pub result: primitive_types::U256,
83}
84
85/// RUST_LOG=debug cargo test --package avalanche-types --lib -- jsonrpc::evm::test_gas_price --exact --show-output
86#[test]
87fn test_gas_price() {
88    let resp: GasPriceResponse = serde_json::from_str(
89        "
90
91{
92    \"jsonrpc\": \"2.0\",
93    \"result\": \"0x1dfd14000\",
94    \"id\": 1
95}
96
97",
98    )
99    .unwrap();
100    let expected = GasPriceResponse {
101        jsonrpc: "2.0".to_string(),
102        id: 1,
103        result: primitive_types::U256::from_str_radix("0x1dfd14000", 16).unwrap(),
104    };
105    assert_eq!(resp, expected);
106}
107
108/// Response for "eth_getBalance".
109/// ref. <https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getbalance>
110/// ref. <https://docs.avax.network/build/avalanchego-apis/c-chain#eth_getassetbalance>
111#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
112pub struct GetBalanceResponse {
113    pub jsonrpc: String,
114    pub id: u32,
115
116    #[serde(with = "crate::codec::serde::hex_0x_primitive_types_u256")]
117    pub result: primitive_types::U256,
118}
119
120/// RUST_LOG=debug cargo test --package avalanche-types --lib -- jsonrpc::evm::test_get_balance --exact --show-output
121#[test]
122fn test_get_balance() {
123    // ref. https://docs.avax.network/build/avalanchego-apis/c-chain#eth_getassetbalance
124    let resp: GetBalanceResponse = serde_json::from_str(
125        "
126
127{
128    \"jsonrpc\": \"2.0\",
129    \"result\": \"0x1388\",
130    \"id\": 1
131}
132
133",
134    )
135    .unwrap();
136    let expected = GetBalanceResponse {
137        jsonrpc: "2.0".to_string(),
138        id: 1,
139        result: primitive_types::U256::from_str_radix("0x1388", 16).unwrap(),
140    };
141    assert_eq!(resp, expected);
142
143    let resp: GetBalanceResponse = serde_json::from_str(
144        "
145
146{
147    \"jsonrpc\": \"2.0\",
148    \"result\": \"0x0234c8a3397aab58\",
149    \"id\": 1
150}
151
152",
153    )
154    .unwrap();
155    let expected = GetBalanceResponse {
156        jsonrpc: "2.0".to_string(),
157        id: 1,
158        result: primitive_types::U256::from_str_radix("0x0234c8a3397aab58", 16).unwrap(),
159    };
160    assert_eq!(resp, expected);
161}
162
163/// Response for "eth_getTransactionCount".
164/// Returns the number of transactions send from this address.
165/// ref. <https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactioncount>
166#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
167pub struct GetTransactionCountResponse {
168    pub jsonrpc: String,
169    pub id: u32,
170
171    /// The number of transactions send from this address.
172    #[serde(with = "crate::codec::serde::hex_0x_primitive_types_u256")]
173    pub result: primitive_types::U256,
174}
175
176/// RUST_LOG=debug cargo test --package avalanche-types --lib -- jsonrpc::evm::test_get_transaction_count --exact --show-output
177#[test]
178fn test_get_transaction_count() {
179    let resp: GetTransactionCountResponse = serde_json::from_str(
180        "
181
182{
183    \"jsonrpc\": \"2.0\",
184    \"result\": \"0x1\",
185    \"id\": 1
186}
187
188",
189    )
190    .unwrap();
191    let expected = GetTransactionCountResponse {
192        jsonrpc: "2.0".to_string(),
193        id: 1,
194        result: primitive_types::U256::from_str_radix("0x1", 16).unwrap(),
195    };
196    assert_eq!(resp, expected);
197}
198
199/// Response for "eth_getTransactionReceipt".
200/// Returns the receipt of a transaction by transaction hash.
201/// ref. <https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionreceipt>
202#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
203pub struct GetTransactionReceiptResponse {
204    pub jsonrpc: String,
205    pub id: u32,
206
207    #[serde(skip_serializing_if = "Option::is_none")]
208    pub result: Option<GetTransactionReceiptResult>,
209}
210
211/// ref. <https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionreceipt>
212#[serde_as]
213#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
214#[serde(rename_all = "camelCase")]
215pub struct GetTransactionReceiptResult {
216    pub from: String,
217    pub to: String,
218
219    #[serde(with = "crate::codec::serde::hex_0x_primitive_types_u256")]
220    pub block_number: primitive_types::U256,
221    #[serde_as(as = "Hex0xBytes")]
222    pub block_hash: Vec<u8>,
223
224    /// Null, if none was created.
225    #[serde_as(as = "Option<Hex0xBytes>")]
226    #[serde(skip_serializing_if = "Option::is_none")]
227    pub contract_address: Option<Vec<u8>>,
228
229    #[serde(with = "crate::codec::serde::hex_0x_primitive_types_u256")]
230    pub cumulative_gas_used: primitive_types::U256,
231    #[serde(with = "crate::codec::serde::hex_0x_primitive_types_u256")]
232    pub gas_used: primitive_types::U256,
233
234    #[serde(with = "crate::codec::serde::hex_0x_primitive_types_u256")]
235    pub transaction_index: primitive_types::U256,
236    #[serde_as(as = "Hex0xBytes")]
237    pub transaction_hash: Vec<u8>,
238
239    #[serde(with = "crate::codec::serde::hex_0x_primitive_types_u256")]
240    pub status: primitive_types::U256,
241}
242
243/// RUST_LOG=debug cargo test --package avalanche-types --lib -- jsonrpc::evm::test_get_transaction_receipt --exact --show-output
244#[test]
245fn test_get_transaction_receipt() {
246    let resp: GetTransactionReceiptResponse = serde_json::from_str(
247        "
248
249{
250    \"jsonrpc\": \"2.0\",
251    \"result\": {
252        \"from\": \"0x7eb4c9d6b763324eea4852f5d40985bbf0f29832\",
253        \"to\": \"0x3c42649799074b438889b80312ea9f62bc798aa8\",
254        \"blockHash\": \"0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b\",
255        \"blockNumber\": \"0xb\",
256        \"cumulativeGasUsed\": \"0x33bc\",
257        \"gasUsed\": \"0x4dc\",
258        \"transactionIndex\": \"0x1\",
259        \"transactionHash\": \"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238\",
260        \"status\": \"0x1\"
261    },
262    \"id\": 1
263}
264
265",
266    )
267    .unwrap();
268    // println!("{:?}", resp);
269
270    let expected = GetTransactionReceiptResponse {
271        jsonrpc: "2.0".to_string(),
272        id: 1,
273        result: Some(GetTransactionReceiptResult {
274            from: String::from("0x7eb4c9d6b763324eea4852f5d40985bbf0f29832"),
275            to: String::from("0x3c42649799074b438889b80312ea9f62bc798aa8"),
276
277            block_number: primitive_types::U256::from_str_radix("0xb", 16).unwrap(),
278            block_hash: vec![
279                198, 239, 47, 197, 66, 109, 106, 214, 253, 158, 42, 38, 171, 234, 176, 170, 36, 17,
280                183, 171, 23, 243, 10, 153, 211, 203, 150, 174, 209, 209, 5, 91,
281            ],
282
283            contract_address: None,
284
285            cumulative_gas_used: primitive_types::U256::from_str_radix("0x33bc", 16).unwrap(),
286            gas_used: primitive_types::U256::from_str_radix("0x4dc", 16).unwrap(),
287
288            transaction_index: primitive_types::U256::from_str_radix("0x1", 16).unwrap(),
289            transaction_hash: vec![
290                185, 3, 35, 159, 133, 67, 208, 75, 93, 193, 186, 101, 121, 19, 43, 20, 48, 135,
291                198, 141, 177, 178, 22, 135, 134, 64, 143, 203, 206, 86, 130, 56,
292            ],
293
294            status: primitive_types::U256::from_str_radix("0x1", 16).unwrap(),
295        }),
296    };
297    assert_eq!(resp, expected);
298}
299
300/// Response for "eth_sendRawTransaction".
301/// ref. <https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_signtransaction>
302/// ref. <https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendtransaction>
303/// ref. <https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendrawtransaction>
304#[serde_as]
305#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)]
306pub struct SendRawTransactionResponse {
307    pub jsonrpc: String,
308    pub id: u32,
309
310    /// Transaction hash.
311    #[serde_as(as = "Option<Hex0xH256>")]
312    pub result: Option<primitive_types::H256>,
313}
314
315/// RUST_LOG=debug cargo test --package avalanche-types --lib -- jsonrpc::evm::test_send_raw_transaction --exact --show-output
316#[test]
317fn test_send_raw_transaction() {
318    use std::str::FromStr;
319
320    let resp: SendRawTransactionResponse = serde_json::from_str(
321        "
322
323{
324    \"jsonrpc\": \"2.0\",
325    \"result\": \"0xe16906ec1c7049438bd642023ab15f8633e032940994e6940fff4ec0a2819eb6\",
326    \"id\": 1
327}
328
329",
330    )
331    .unwrap();
332    let expected = SendRawTransactionResponse {
333        jsonrpc: "2.0".to_string(),
334        id: 1,
335        result: Some(
336            primitive_types::H256::from_str(
337                "e16906ec1c7049438bd642023ab15f8633e032940994e6940fff4ec0a2819eb6",
338            )
339            .unwrap(),
340        ),
341    };
342    assert_eq!(resp, expected);
343}