eth_jsonrpc_lib/rpc_complete/
complete.rs1use crate::rpc_request::{
16 eth_accountsParams, eth_blockNumberParams, eth_callParams, eth_chainIdParams,
17 eth_estimateGasParams, eth_gasPriceParams, eth_getBalanceParams, eth_getBlockByHashParams,
18 eth_getBlockByNumberParams, eth_getBlockTransactionCountByHashParams,
19 eth_getBlockTransactionCountByNumberParams, eth_getCodeParams, eth_getLogsParams,
20 eth_getStorageAtParams, eth_getTransactionByBlockHashAndIndexParams,
21 eth_getTransactionByBlockNumberAndIndexParams, eth_getTransactionByHashParams,
22 eth_getTransactionCountParams, eth_getTransactionReceiptParams, eth_maxPriorityFeePerGasParams,
23 eth_sendRawTransactionParams, eth_sendTransactionParams, eth_syncingParams, net_versionParams,
24 BlockNumberParams, CallParams, EstimateQuotaParams, GetAbiParams, GetBalanceParams,
25 GetBlockByHashParams, GetBlockByNumberParams, GetBlockHeaderParams, GetCensoredAddrsParams,
26 GetCodeParams, GetFilterChangesParams, GetFilterLogsParams, GetLogsParams, GetMetaDataParams,
27 GetPoolTxNumParams, GetStateProofParams, GetStorageKeyParams, GetTransactionCountParams,
28 GetTransactionParams, GetTransactionProofParams, GetTransactionReceiptParams, GetVersionParams,
29 LicenseInfoParams, NewBlockFilterParams, NewFilterParams, OpCensoredAddressParams,
30 PeerCountParams, PeersInfoParams, SendRawTransactionParams, SendTransactionParams,
31 UninstallFilterParams,
32};
33use crate::rpc_request::{Call, JsonRpcRequest, PartialCall, PartialRequest, Request};
34use crate::{impl_for_each_jsonrpc_requests, rpc_types::Params as PartialParams, Error};
35use serde_json;
36
37pub trait Complete {
38 type Output;
39 type Error;
40
41 fn complete(self) -> Result<Self::Output, Self::Error>;
42}
43
44impl Complete for PartialRequest {
45 type Output = Request;
46 type Error = Error;
47
48 fn complete(self) -> Result<Self::Output, Self::Error> {
49 let PartialRequest { jsonrpc, id, call } = self;
50 if let Some(part_call) = call {
51 part_call
52 .complete()
53 .map(|full_call| Request::new(jsonrpc, id, full_call))
54 } else {
55 Err(Error::method_not_found())
56 }
57 }
58}
59
60macro_rules! partial_call_complete {
61 ($( ($enum_name:ident, $params_name:ident: $params_list:expr, $result_type:ident) ),+ ,) => {
62 partial_call_complete!($( ($enum_name, $params_name) ),+);
63 };
64 ($( ($enum_name:ident, $params_name:ident) ),+) => {
65 impl Complete for PartialCall {
66 type Output = Call;
67 type Error = Error;
68
69 fn complete(self) -> Result<Self::Output, Self::Error> {
70 match self {
71 $(
72 PartialCall::$enum_name { params } => {
73 if let Some(params) = params {
74 let pparams: PartialParams = serde_json::from_value(params.clone())?;
75 if pparams.len() < $params_name::required_len()
76 && pparams.len() > $params_name::valid_len() {
77 Err(Error::invalid_params_len())
78 } else {
79 Ok(Call::$enum_name{ params: serde_json::from_value(params)? })
80 }
81 } else {
82 if $params_name::required_len() == 0 {
83 Ok(Call::$enum_name{
84 params: serde_json::from_value(
85 serde_json::Value::Array(Vec::new()))?})
86 } else {
87 Err(Error::invalid_params("params is requeired"))
88 }
89 }
90 },
91 )+
92 }
93 }
94 }
95 }
96}
97
98impl_for_each_jsonrpc_requests!(partial_call_complete);
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103 use ethereum_types::H256;
104
105 #[test]
106 fn test_get_transaction_receipt_params_complete() {
107 let params = GetTransactionReceiptParams::new(H256::from(10).into());
108 let full_req = params.into_request(1);
109
110 let req_str = r#"{
111 "jsonrpc": "2.0",
112 "id": 1,
113 "method": "getTransactionReceipt",
114 "params": ["0x000000000000000000000000000000000000000000000000000000000000000a"]
115 }"#;
116 let part_req = serde_json::from_str::<PartialRequest>(&req_str).unwrap();
117 assert_eq!(part_req.complete().unwrap(), full_req);
118 }
119
120 #[test]
121 fn test_get_transaction_receipt_params_complete_error() {
122 let req_str = r#"{
123 "jsonrpc": "2.0",
124 "id": null,
125 "method": "getTransactionReceipt"
126 }"#;
127 let part_req = serde_json::from_str::<PartialRequest>(&req_str).unwrap();
128
129 assert_eq!(
130 part_req.complete().err().unwrap(),
131 Error::invalid_params("params is requeired")
132 );
133
134 let req_str = r#"{
135 "jsonrpc": "2.0",
136 "id": null,
137 "method": "getTransactionReceipt",
138 "params": [1, 2]
139 }"#;
140 let part_req = serde_json::from_str::<PartialRequest>(&req_str).unwrap();
141 assert_eq!(
142 part_req.complete().err().unwrap(),
143 Error::invalid_params_len()
144 );
145 }
146
147 #[test]
148 fn test_block_number_params_complete() {
149 let params = eth_blockNumberParams::new();
150 let full_req = params.into_request(2);
151
152 let req_str = r#"{
153 "jsonrpc": "2.0",
154 "id": 2,
155 "method": "blockNumber"
156 }"#;
157 let part_req = serde_json::from_str::<PartialRequest>(&req_str).unwrap();
158 assert_eq!(part_req.complete().unwrap(), full_req);
159 }
160
161 #[test]
162 fn test_method_not_found_complete_error() {
163 let req_str = r#"{
164 "jsonrpc": "2.0",
165 "id": null,
166 "params": ["0x000000000000000000000000000000000000000000000000000000000000000a"]
167 }"#;
168 let part_req = serde_json::from_str::<PartialRequest>(&req_str).unwrap();
169
170 assert_eq!(
171 part_req.complete().err().unwrap(),
172 Error::method_not_found()
173 );
174
175 let req_str = r#"{
176 "jsonrpc": "2.0",
177 "id": null,
178 "method": "notAMethod",
179 "params": ["0x000000000000000000000000000000000000000000000000000000000000000a"]
180 }"#;
181 let part_req = serde_json::from_str::<PartialRequest>(&req_str).unwrap();
182 assert_eq!(
183 part_req.complete().err().unwrap(),
184 Error::method_not_found()
185 );
186 }
187}