diff --git a/Cargo.lock b/Cargo.lock index b02841020cc..49f083223dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2954,11 +2954,9 @@ name = "near-jsonrpc-adversarial-primitives" version = "0.0.0" dependencies = [ "deepsize", - "near-jsonrpc-primitives", "near-network-primitives", "near-primitives", "serde", - "serde_json", ] [[package]] diff --git a/chain/jsonrpc-adversarial-primitives/Cargo.toml b/chain/jsonrpc-adversarial-primitives/Cargo.toml index 813be117da7..1310e68825a 100644 --- a/chain/jsonrpc-adversarial-primitives/Cargo.toml +++ b/chain/jsonrpc-adversarial-primitives/Cargo.toml @@ -9,10 +9,8 @@ edition = "2021" [dependencies] serde = { version = "1", features = ["derive"] } -serde_json = "1" near-primitives = { path = "../../core/primitives" } -near-jsonrpc-primitives = { path = "../jsonrpc-primitives" } near-network-primitives = { path = "../network-primitives" } deepsize = { version = "0.2.0", optional = true } diff --git a/chain/jsonrpc-adversarial-primitives/src/lib.rs b/chain/jsonrpc-adversarial-primitives/src/lib.rs index f8910be397e..d77d9b14ebf 100644 --- a/chain/jsonrpc-adversarial-primitives/src/lib.rs +++ b/chain/jsonrpc-adversarial-primitives/src/lib.rs @@ -10,23 +10,6 @@ pub struct SetRoutingTableRequest { pub prune_edges: Option, } -#[cfg(feature = "test_features")] -impl SetRoutingTableRequest { - pub fn parse( - value: Option, - ) -> Result { - if let Some(value) = value { - serde_json::from_value(value).map_err(|err| { - near_jsonrpc_primitives::errors::RpcError::parse_error(format!("Error {:?}", err)) - }) - } else { - Err(near_jsonrpc_primitives::errors::RpcError::parse_error( - "Require at least one parameter".to_owned(), - )) - } - } -} - #[derive(Deserialize)] pub struct SetAdvOptionsRequest { pub disable_edge_signature_verification: Option, diff --git a/chain/jsonrpc-primitives/src/lib.rs b/chain/jsonrpc-primitives/src/lib.rs index 3cfd6d57947..3a19a40ab60 100644 --- a/chain/jsonrpc-primitives/src/lib.rs +++ b/chain/jsonrpc-primitives/src/lib.rs @@ -2,4 +2,3 @@ pub mod errors; pub mod message; pub(crate) mod metrics; pub mod types; -pub(crate) mod utils; diff --git a/chain/jsonrpc-primitives/src/types/blocks.rs b/chain/jsonrpc-primitives/src/types/blocks.rs index 06b92bbacb2..328e34da3ba 100644 --- a/chain/jsonrpc-primitives/src/types/blocks.rs +++ b/chain/jsonrpc-primitives/src/types/blocks.rs @@ -82,16 +82,3 @@ impl From for crate::errors::RpcError { Self::new_internal_or_handler_error(error_data, error_data_value) } } - -impl RpcBlockRequest { - pub fn parse(value: Option) -> Result { - let block_reference = if let Ok((block_id,)) = - crate::utils::parse_params::<(near_primitives::types::BlockId,)>(value.clone()) - { - near_primitives::types::BlockReference::BlockId(block_id) - } else { - crate::utils::parse_params::(value)? - }; - Ok(RpcBlockRequest { block_reference }) - } -} diff --git a/chain/jsonrpc-primitives/src/types/changes.rs b/chain/jsonrpc-primitives/src/types/changes.rs index d215d17c17f..62292f66239 100644 --- a/chain/jsonrpc-primitives/src/types/changes.rs +++ b/chain/jsonrpc-primitives/src/types/changes.rs @@ -1,5 +1,4 @@ use serde::{Deserialize, Serialize}; -use serde_json::Value; #[derive(Debug, Serialize, Deserialize)] pub struct RpcStateChangesInBlockRequest { @@ -41,18 +40,6 @@ pub enum RpcStateChangesError { InternalError { error_message: String }, } -impl RpcStateChangesInBlockRequest { - pub fn parse(value: Option) -> Result { - Ok(crate::utils::parse_params::(value)?) - } -} - -impl RpcStateChangesInBlockByTypeRequest { - pub fn parse(value: Option) -> Result { - Ok(crate::utils::parse_params::(value)?) - } -} - impl From for RpcStateChangesError { fn from(error: near_client_primitives::types::GetBlockError) -> Self { match error { diff --git a/chain/jsonrpc-primitives/src/types/chunks.rs b/chain/jsonrpc-primitives/src/types/chunks.rs index eda4827af9d..3a19c8d46b6 100644 --- a/chain/jsonrpc-primitives/src/types/chunks.rs +++ b/chain/jsonrpc-primitives/src/types/chunks.rs @@ -55,26 +55,6 @@ impl From for near_client_primitives::types::GetChunk { } } -impl RpcChunkRequest { - pub fn parse(value: Option) -> Result { - // Try to parse legacy positioned args and if it fails parse newer named args - let chunk_reference = if let Ok((chunk_id,)) = - crate::utils::parse_params::<(near_primitives::hash::CryptoHash,)>(value.clone()) - { - ChunkReference::ChunkHash { chunk_id } - } else if let Ok(((block_id, shard_id),)) = crate::utils::parse_params::<(( - near_primitives::types::BlockId, - near_primitives::types::ShardId, - ),)>(value.clone()) - { - ChunkReference::BlockShardId { block_id, shard_id } - } else { - crate::utils::parse_params::(value)? - }; - Ok(Self { chunk_reference }) - } -} - impl From for RpcChunkError { fn from(error: near_client_primitives::types::GetChunkError) -> Self { match error { diff --git a/chain/jsonrpc-primitives/src/types/config.rs b/chain/jsonrpc-primitives/src/types/config.rs index 73f06e9fb5f..ec158558a10 100644 --- a/chain/jsonrpc-primitives/src/types/config.rs +++ b/chain/jsonrpc-primitives/src/types/config.rs @@ -7,15 +7,6 @@ pub struct RpcProtocolConfigRequest { pub block_reference: near_primitives::types::BlockReference, } -impl RpcProtocolConfigRequest { - pub fn parse( - value: Option, - ) -> Result { - crate::utils::parse_params::(value) - .map(|block_reference| RpcProtocolConfigRequest { block_reference }) - } -} - #[derive(Serialize, Deserialize, Debug)] pub struct RpcProtocolConfigResponse { #[serde(flatten)] diff --git a/chain/jsonrpc-primitives/src/types/gas_price.rs b/chain/jsonrpc-primitives/src/types/gas_price.rs index 5afc5e47fdd..70c87700842 100644 --- a/chain/jsonrpc-primitives/src/types/gas_price.rs +++ b/chain/jsonrpc-primitives/src/types/gas_price.rs @@ -75,10 +75,3 @@ impl From for crate::errors::RpcError { Self::new_internal_or_handler_error(error_data, error_data_value) } } - -impl RpcGasPriceRequest { - pub fn parse(value: Option) -> Result { - crate::utils::parse_params::<(MaybeBlockId,)>(value) - .map(|(block_id,)| RpcGasPriceRequest { block_id }) - } -} diff --git a/chain/jsonrpc-primitives/src/types/light_client.rs b/chain/jsonrpc-primitives/src/types/light_client.rs index 47403e0c3f7..73b63d1b8de 100644 --- a/chain/jsonrpc-primitives/src/types/light_client.rs +++ b/chain/jsonrpc-primitives/src/types/light_client.rs @@ -67,24 +67,6 @@ pub enum RpcLightClientNextBlockError { EpochOutOfBounds { epoch_id: near_primitives::types::EpochId }, } -impl RpcLightClientExecutionProofRequest { - pub fn parse(value: Option) -> Result { - Ok(crate::utils::parse_params::(value)?) - } -} - -impl RpcLightClientNextBlockRequest { - pub fn parse(value: Option) -> Result { - if let Ok((last_block_hash,)) = - crate::utils::parse_params::<(near_primitives::hash::CryptoHash,)>(value.clone()) - { - Ok(Self { last_block_hash }) - } else { - Ok(crate::utils::parse_params::(value)?) - } - } -} - impl From> for RpcLightClientNextBlockResponse { diff --git a/chain/jsonrpc-primitives/src/types/query.rs b/chain/jsonrpc-primitives/src/types/query.rs index 46a545fb443..26e6c12ef4d 100644 --- a/chain/jsonrpc-primitives/src/types/query.rs +++ b/chain/jsonrpc-primitives/src/types/query.rs @@ -1,8 +1,4 @@ use serde::{Deserialize, Serialize}; -use serde_json::Value; - -/// Max size of the query path (soft-deprecated) -const QUERY_DATA_MAX_SIZE: usize = 10 * 1024; #[derive(Serialize, Deserialize, Debug)] pub struct RpcQueryRequest { @@ -89,83 +85,6 @@ pub enum QueryResponseKind { AccessKeyList(near_primitives::views::AccessKeyList), } -impl RpcQueryRequest { - pub fn parse(value: Option) -> Result { - let query_request = if let Ok((path, data)) = - crate::utils::parse_params::<(String, String)>(value.clone()) - { - // Handle a soft-deprecated version of the query API, which is based on - // positional arguments with a "path"-style first argument. - // - // This whole block can be removed one day, when the new API is 100% adopted. - let data = near_primitives_core::serialize::from_base(&data) - .map_err(|err| crate::errors::RpcParseError(err.to_string()))?; - let query_data_size = path.len() + data.len(); - if query_data_size > QUERY_DATA_MAX_SIZE { - return Err(crate::errors::RpcParseError(format!( - "Query data size {} is too large", - query_data_size - ))); - } - - let mut path_parts = path.splitn(3, '/'); - let make_err = - || crate::errors::RpcParseError("Not enough query parameters provided".to_string()); - let query_command = path_parts.next().ok_or_else(make_err)?; - let account_id = path_parts - .next() - .ok_or_else(make_err)? - .parse() - .map_err(|err| crate::errors::RpcParseError(format!("{}", err)))?; - let maybe_extra_arg = path_parts.next(); - - let request = match query_command { - "account" => near_primitives::views::QueryRequest::ViewAccount { account_id }, - "access_key" => match maybe_extra_arg { - None => near_primitives::views::QueryRequest::ViewAccessKeyList { account_id }, - Some(pk) => near_primitives::views::QueryRequest::ViewAccessKey { - account_id, - public_key: pk.parse().map_err(|_| { - crate::errors::RpcParseError("Invalid public key".to_string()) - })?, - }, - }, - "code" => near_primitives::views::QueryRequest::ViewCode { account_id }, - "contract" => near_primitives::views::QueryRequest::ViewState { - account_id, - prefix: data.into(), - }, - "call" => match maybe_extra_arg { - Some(method_name) => near_primitives::views::QueryRequest::CallFunction { - account_id, - method_name: method_name.to_string(), - args: data.into(), - }, - None => { - return Err(crate::errors::RpcParseError( - "Method name is missing".to_string(), - )) - } - }, - _ => { - return Err(crate::errors::RpcParseError(format!( - "Unknown path {}", - query_command - ))) - } - }; - // Use Finality::None here to make backward compatibility tests work - RpcQueryRequest { - request, - block_reference: near_primitives::types::BlockReference::latest(), - } - } else { - crate::utils::parse_params::(value)? - }; - Ok(query_request) - } -} - impl From for RpcQueryError { fn from(error: near_client_primitives::types::QueryError) -> Self { match error { diff --git a/chain/jsonrpc-primitives/src/types/receipts.rs b/chain/jsonrpc-primitives/src/types/receipts.rs index 1065674c1d1..31466478a92 100644 --- a/chain/jsonrpc-primitives/src/types/receipts.rs +++ b/chain/jsonrpc-primitives/src/types/receipts.rs @@ -1,5 +1,4 @@ use serde::{Deserialize, Serialize}; -use serde_json::Value; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ReceiptReference { @@ -33,13 +32,6 @@ impl From for near_client_primitives::types::GetReceipt { } } -impl RpcReceiptRequest { - pub fn parse(value: Option) -> Result { - let receipt_reference = crate::utils::parse_params::(value)?; - Ok(Self { receipt_reference }) - } -} - impl From for RpcReceiptError { fn from(error: near_client_primitives::types::GetReceiptError) -> Self { match error { diff --git a/chain/jsonrpc-primitives/src/types/sandbox.rs b/chain/jsonrpc-primitives/src/types/sandbox.rs index d5d149e5cbd..5cd3b5351df 100644 --- a/chain/jsonrpc-primitives/src/types/sandbox.rs +++ b/chain/jsonrpc-primitives/src/types/sandbox.rs @@ -1,19 +1,12 @@ use near_primitives::state_record::StateRecord; use near_primitives::types::BlockHeightDelta; use serde::{Deserialize, Serialize}; -use serde_json::Value; #[derive(Deserialize, Serialize, Debug)] pub struct RpcSandboxPatchStateRequest { pub records: Vec, } -impl RpcSandboxPatchStateRequest { - pub fn parse(value: Option) -> Result { - Ok(crate::utils::parse_params::(value)?) - } -} - #[derive(Deserialize, Serialize, Debug)] pub struct RpcSandboxPatchStateResponse {} @@ -50,12 +43,6 @@ pub struct RpcSandboxFastForwardRequest { pub delta_height: BlockHeightDelta, } -impl RpcSandboxFastForwardRequest { - pub fn parse(value: Option) -> Result { - Ok(crate::utils::parse_params::(value)?) - } -} - #[derive(Deserialize, Serialize)] pub struct RpcSandboxFastForwardResponse {} diff --git a/chain/jsonrpc-primitives/src/types/transactions.rs b/chain/jsonrpc-primitives/src/types/transactions.rs index f5f948e6f64..3cd3bd2ebda 100644 --- a/chain/jsonrpc-primitives/src/types/transactions.rs +++ b/chain/jsonrpc-primitives/src/types/transactions.rs @@ -1,8 +1,6 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; -use near_primitives::types::AccountId; - #[derive(Debug, Clone)] pub struct RpcBroadcastTransactionRequest { pub signed_transaction: near_primitives::transaction::SignedTransaction, @@ -53,30 +51,6 @@ pub struct RpcBroadcastTxSyncResponse { pub transaction_hash: near_primitives::hash::CryptoHash, } -impl RpcBroadcastTransactionRequest { - pub fn parse(value: Option) -> Result { - let signed_transaction = crate::utils::parse_signed_transaction(value)?; - Ok(Self { signed_transaction }) - } -} - -impl RpcTransactionStatusCommonRequest { - pub fn parse(value: Option) -> Result { - if let Ok((hash, account_id)) = crate::utils::parse_params::<( - near_primitives::hash::CryptoHash, - AccountId, - )>(value.clone()) - { - let transaction_info = TransactionInfo::TransactionId { hash, account_id }; - Ok(Self { transaction_info }) - } else { - let signed_transaction = crate::utils::parse_signed_transaction(value)?; - let transaction_info = TransactionInfo::Transaction(signed_transaction); - Ok(Self { transaction_info }) - } - } -} - impl From for RpcTransactionError { fn from(error: near_client_primitives::types::TxStatusError) -> Self { match error { diff --git a/chain/jsonrpc-primitives/src/types/validator.rs b/chain/jsonrpc-primitives/src/types/validator.rs index 14b64fcf050..10e89e46d5d 100644 --- a/chain/jsonrpc-primitives/src/types/validator.rs +++ b/chain/jsonrpc-primitives/src/types/validator.rs @@ -63,28 +63,6 @@ impl From for RpcValidatorError { } } -impl RpcValidatorRequest { - pub fn parse(value: Option) -> Result { - let epoch_reference = if let Ok((block_id,)) = - crate::utils::parse_params::<(near_primitives::types::MaybeBlockId,)>(value.clone()) - { - match block_id { - Some(id) => near_primitives::types::EpochReference::BlockId(id), - None => near_primitives::types::EpochReference::Latest, - } - } else { - crate::utils::parse_params::(value)? - }; - Ok(Self { epoch_reference }) - } -} - -impl RpcValidatorsOrderedRequest { - pub fn parse(value: Option) -> Result { - Ok(crate::utils::parse_params::(value)?) - } -} - impl From for crate::errors::RpcError { fn from(error: RpcValidatorError) -> Self { let error_data = match &error { diff --git a/chain/jsonrpc-primitives/src/utils.rs b/chain/jsonrpc-primitives/src/utils.rs deleted file mode 100644 index f19b03e4715..00000000000 --- a/chain/jsonrpc-primitives/src/utils.rs +++ /dev/null @@ -1,26 +0,0 @@ -use serde::de::DeserializeOwned; -use serde_json::Value; - -use near_primitives::borsh::BorshDeserialize; - -pub(crate) fn parse_params( - value: Option, -) -> Result { - if let Some(value) = value { - serde_json::from_value(value) - .map_err(|err| crate::errors::RpcParseError(format!("Failed parsing args: {}", err))) - } else { - Err(crate::errors::RpcParseError("Require at least one parameter".to_owned())) - } -} - -pub(crate) fn parse_signed_transaction( - value: Option, -) -> Result { - let (encoded,) = crate::utils::parse_params::<(String,)>(value.clone())?; - let bytes = near_primitives_core::serialize::from_base64(&encoded) - .map_err(|err| crate::errors::RpcParseError(err.to_string()))?; - Ok(near_primitives::transaction::SignedTransaction::try_from_slice(&bytes).map_err(|err| { - crate::errors::RpcParseError(format!("Failed to decode transaction: {}", err)) - })?) -} diff --git a/chain/jsonrpc/src/lib.rs b/chain/jsonrpc/src/lib.rs index 9167ab40cf8..0a348895235 100644 --- a/chain/jsonrpc/src/lib.rs +++ b/chain/jsonrpc/src/lib.rs @@ -33,6 +33,9 @@ use near_primitives::types::AccountId; use near_primitives::views::FinalExecutionOutcomeViewEnum; mod metrics; +mod parser; + +use parser::RpcRequest; #[derive(Serialize, Deserialize, Clone, Copy, Debug)] pub struct RpcPollingConfig { diff --git a/chain/jsonrpc/src/parser.rs b/chain/jsonrpc/src/parser.rs new file mode 100644 index 00000000000..3b9167051f1 --- /dev/null +++ b/chain/jsonrpc/src/parser.rs @@ -0,0 +1,259 @@ +use serde::de::DeserializeOwned; +use serde_json::Value; + +use near_jsonrpc_primitives::errors::RpcParseError; +use near_primitives::borsh::BorshDeserialize; + +pub(crate) trait RpcRequest: Sized { + fn parse(value: Option) -> Result; +} + +fn parse_params(value: Option) -> Result { + if let Some(value) = value { + serde_json::from_value(value) + .map_err(|err| RpcParseError(format!("Failed parsing args: {}", err))) + } else { + Err(RpcParseError("Require at least one parameter".to_owned())) + } +} + +fn parse_signed_transaction( + value: Option, +) -> Result { + let (encoded,) = parse_params::<(String,)>(value)?; + let bytes = near_primitives::serialize::from_base64(&encoded) + .map_err(|err| RpcParseError(err.to_string()))?; + Ok(near_primitives::transaction::SignedTransaction::try_from_slice(&bytes) + .map_err(|err| RpcParseError(format!("Failed to decode transaction: {}", err)))?) +} + +impl RpcRequest for near_jsonrpc_primitives::types::blocks::RpcBlockRequest { + fn parse(value: Option) -> Result { + let block_reference = if let Ok((block_id,)) = + parse_params::<(near_primitives::types::BlockId,)>(value.clone()) + { + near_primitives::types::BlockReference::BlockId(block_id) + } else { + parse_params::(value)? + }; + Ok(Self { block_reference }) + } +} + +impl RpcRequest for near_jsonrpc_primitives::types::changes::RpcStateChangesInBlockRequest { + fn parse(value: Option) -> Result { + parse_params::(value) + } +} + +impl RpcRequest for near_jsonrpc_primitives::types::changes::RpcStateChangesInBlockByTypeRequest { + fn parse(value: Option) -> Result { + parse_params::(value) + } +} + +impl RpcRequest for near_jsonrpc_primitives::types::chunks::RpcChunkRequest { + fn parse(value: Option) -> Result { + // Try to parse legacy positioned args and if it fails parse newer named args + let chunk_reference = if let Ok((chunk_id,)) = + parse_params::<(near_primitives::hash::CryptoHash,)>(value.clone()) + { + near_jsonrpc_primitives::types::chunks::ChunkReference::ChunkHash { chunk_id } + } else if let Ok(((block_id, shard_id),)) = parse_params::<(( + near_primitives::types::BlockId, + near_primitives::types::ShardId, + ),)>(value.clone()) + { + near_jsonrpc_primitives::types::chunks::ChunkReference::BlockShardId { + block_id, + shard_id, + } + } else { + parse_params::(value)? + }; + Ok(Self { chunk_reference }) + } +} + +impl RpcRequest for near_jsonrpc_primitives::types::config::RpcProtocolConfigRequest { + fn parse(value: Option) -> Result { + parse_params::(value) + .map(|block_reference| Self { block_reference }) + } +} + +impl RpcRequest for near_jsonrpc_primitives::types::gas_price::RpcGasPriceRequest { + fn parse(value: Option) -> Result { + parse_params::<(near_primitives::types::MaybeBlockId,)>(value) + .map(|(block_id,)| Self { block_id }) + } +} + +impl RpcRequest + for near_jsonrpc_primitives::types::light_client::RpcLightClientExecutionProofRequest +{ + fn parse(value: Option) -> Result { + Ok(parse_params::(value)?) + } +} + +impl RpcRequest for near_jsonrpc_primitives::types::light_client::RpcLightClientNextBlockRequest { + fn parse(value: Option) -> Result { + if let Ok((last_block_hash,)) = + parse_params::<(near_primitives::hash::CryptoHash,)>(value.clone()) + { + Ok(Self { last_block_hash }) + } else { + Ok(parse_params::(value)?) + } + } +} + +/// Max size of the query path (soft-deprecated) +const QUERY_DATA_MAX_SIZE: usize = 10 * 1024; + +impl RpcRequest for near_jsonrpc_primitives::types::query::RpcQueryRequest { + fn parse(value: Option) -> Result { + let query_request = if let Ok((path, data)) = + parse_params::<(String, String)>(value.clone()) + { + // Handle a soft-deprecated version of the query API, which is based on + // positional arguments with a "path"-style first argument. + // + // This whole block can be removed one day, when the new API is 100% adopted. + let data = near_primitives::serialize::from_base(&data) + .map_err(|err| RpcParseError(err.to_string()))?; + let query_data_size = path.len() + data.len(); + if query_data_size > QUERY_DATA_MAX_SIZE { + return Err(RpcParseError(format!( + "Query data size {} is too large", + query_data_size + ))); + } + + let mut path_parts = path.splitn(3, '/'); + let make_err = || RpcParseError("Not enough query parameters provided".to_string()); + let query_command = path_parts.next().ok_or_else(make_err)?; + let account_id = path_parts + .next() + .ok_or_else(make_err)? + .parse() + .map_err(|err| RpcParseError(format!("{}", err)))?; + let maybe_extra_arg = path_parts.next(); + + let request = match query_command { + "account" => near_primitives::views::QueryRequest::ViewAccount { account_id }, + "access_key" => match maybe_extra_arg { + None => near_primitives::views::QueryRequest::ViewAccessKeyList { account_id }, + Some(pk) => near_primitives::views::QueryRequest::ViewAccessKey { + account_id, + public_key: pk + .parse() + .map_err(|_| RpcParseError("Invalid public key".to_string()))?, + }, + }, + "code" => near_primitives::views::QueryRequest::ViewCode { account_id }, + "contract" => near_primitives::views::QueryRequest::ViewState { + account_id, + prefix: data.into(), + }, + "call" => match maybe_extra_arg { + Some(method_name) => near_primitives::views::QueryRequest::CallFunction { + account_id, + method_name: method_name.to_string(), + args: data.into(), + }, + None => return Err(RpcParseError("Method name is missing".to_string())), + }, + _ => return Err(RpcParseError(format!("Unknown path {}", query_command))), + }; + // Use Finality::None here to make backward compatibility tests work + Self { request, block_reference: near_primitives::types::BlockReference::latest() } + } else { + parse_params::(value)? + }; + Ok(query_request) + } +} + +impl RpcRequest for near_jsonrpc_primitives::types::receipts::RpcReceiptRequest { + fn parse(value: Option) -> Result { + let receipt_reference = + parse_params::(value)?; + Ok(Self { receipt_reference }) + } +} + +impl RpcRequest for near_jsonrpc_primitives::types::sandbox::RpcSandboxPatchStateRequest { + fn parse(value: Option) -> Result { + parse_params::(value) + } +} + +impl RpcRequest for near_jsonrpc_primitives::types::sandbox::RpcSandboxFastForwardRequest { + fn parse(value: Option) -> Result { + parse_params::(value) + } +} + +impl RpcRequest for near_jsonrpc_primitives::types::transactions::RpcBroadcastTransactionRequest { + fn parse(value: Option) -> Result { + let signed_transaction = parse_signed_transaction(value)?; + Ok(Self { signed_transaction }) + } +} + +impl RpcRequest + for near_jsonrpc_primitives::types::transactions::RpcTransactionStatusCommonRequest +{ + fn parse(value: Option) -> Result { + if let Ok((hash, account_id)) = parse_params::<( + near_primitives::hash::CryptoHash, + near_primitives::types::AccountId, + )>(value.clone()) + { + let transaction_info = + near_jsonrpc_primitives::types::transactions::TransactionInfo::TransactionId { + hash, + account_id, + }; + Ok(Self { transaction_info }) + } else { + let signed_transaction = parse_signed_transaction(value)?; + let transaction_info = + near_jsonrpc_primitives::types::transactions::TransactionInfo::Transaction( + signed_transaction, + ); + Ok(Self { transaction_info }) + } + } +} + +impl RpcRequest for near_jsonrpc_primitives::types::validator::RpcValidatorRequest { + fn parse(value: Option) -> Result { + let epoch_reference = if let Ok((block_id,)) = + parse_params::<(near_primitives::types::MaybeBlockId,)>(value.clone()) + { + match block_id { + Some(id) => near_primitives::types::EpochReference::BlockId(id), + None => near_primitives::types::EpochReference::Latest, + } + } else { + parse_params::(value)? + }; + Ok(Self { epoch_reference }) + } +} + +impl RpcRequest for near_jsonrpc_primitives::types::validator::RpcValidatorsOrderedRequest { + fn parse(value: Option) -> Result { + parse_params::(value) + } +} + +#[cfg(feature = "test_features")] +impl RpcRequest for near_jsonrpc_adversarial_primitives::SetRoutingTableRequest { + fn parse(value: Option) -> Result { + parse_params::(value) + } +}