diff --git a/client/src/nonblocking/rpc_client.rs b/client/src/nonblocking/rpc_client.rs index 9cbef3f24..bdb01d75d 100644 --- a/client/src/nonblocking/rpc_client.rs +++ b/client/src/nonblocking/rpc_client.rs @@ -6,6 +6,7 @@ //! //! [JSON-RPC]: https://www.jsonrpc.org/specification +pub use crate::mock_sender::Mocks; #[allow(deprecated)] use crate::rpc_deprecated_config::{ RpcConfirmedBlockConfig, RpcConfirmedTransactionConfig, @@ -15,7 +16,7 @@ use { crate::{ client_error::{ClientError, ClientErrorKind, Result as ClientResult}, http_sender::HttpSender, - mock_sender::{MockSender, Mocks}, + mock_sender::MockSender, rpc_client::{GetConfirmedSignaturesForAddress2Config, RpcClientConfig}, rpc_config::{RpcAccountInfoConfig, *}, rpc_request::{RpcError, RpcRequest, RpcResponseErrorData, TokenAccountsFilter}, @@ -146,8 +147,8 @@ impl RpcClient { /// /// This is the basic constructor, allowing construction with any type of /// `RpcSender`. Most applications should use one of the other constructors, - /// such as [`new`] and [`new_mock`], which create an `RpcClient` - /// encapsulating an [`HttpSender`] and [`MockSender`] respectively. + /// such as [`RpcClient::new`], [`RpcClient::new_with_commitment`] or + /// [`RpcClient::new_with_timeout`]. pub fn new_sender( sender: T, config: RpcClientConfig, @@ -314,8 +315,34 @@ impl RpcClient { /// Create a mock `RpcClient`. /// - /// See the [`MockSender`] documentation for an explanation of - /// how it treats the `url` argument. + /// A mock `RpcClient` contains an implementation of [`RpcSender`] that does + /// not use the network, and instead returns synthetic responses, for use in + /// tests. + /// + /// It is primarily for internal use, with limited customizability, and + /// behaviors determined by internal Solana test cases. New users should + /// consider implementing `RpcSender` themselves and constructing + /// `RpcClient` with [`RpcClient::new_sender`] to get mock behavior. + /// + /// Unless directed otherwise, a mock `RpcClient` will generally return a + /// reasonable default response to any request, at least for [`RpcRequest`] + /// values for which responses have been implemented. + /// + /// This mock can be customized by changing the `url` argument, which is not + /// actually a URL, but a simple string directive that changes the mock + /// behavior in specific scenarios: + /// + /// - It is customary to set the `url` to "succeeds" for mocks that should + /// return sucessfully, though this value is not actually interpreted. + /// + /// - If `url` is "fails" then any call to `send` will return `Ok(Value::Null)`. + /// + /// - Other possible values of `url` are specific to different `RpcRequest` + /// values. Read the implementation of (non-public) `MockSender` for + /// details. + /// + /// The [`RpcClient::new_mock_with_mocks`] function offers further + /// customization options. /// /// # Examples /// @@ -341,8 +368,43 @@ impl RpcClient { /// Create a mock `RpcClient`. /// - /// See the [`MockSender`] documentation for an explanation of how it treats - /// the `url` argument. + /// A mock `RpcClient` contains an implementation of [`RpcSender`] that does + /// not use the network, and instead returns synthetic responses, for use in + /// tests. + /// + /// It is primarily for internal use, with limited customizability, and + /// behaviors determined by internal Solana test cases. New users should + /// consider implementing `RpcSender` themselves and constructing + /// `RpcClient` with [`RpcClient::new_sender`] to get mock behavior. + /// + /// Unless directed otherwise, a mock `RpcClient` will generally return a + /// reasonable default response to any request, at least for [`RpcRequest`] + /// values for which responses have been implemented. + /// + /// This mock can be customized in two ways: + /// + /// 1) By changing the `url` argument, which is not actually a URL, but a + /// simple string directive that changes the mock behavior in specific + /// scenarios. + /// + /// It is customary to set the `url` to "succeeds" for mocks that should + /// return sucessfully, though this value is not actually interpreted. + /// + /// If `url` is "fails" then any call to `send` will return `Ok(Value::Null)`. + /// + /// Other possible values of `url` are specific to different `RpcRequest` + /// values. Read the implementation of `MockSender` (which is non-public) + /// for details. + /// + /// 2) Custom responses can be configured by providing [`Mocks`]. This type + /// is a [`HashMap`] from [`RpcRequest`] to a JSON [`Value`] response, + /// Any entries in this map override the default behavior for the given + /// request. + /// + /// The [`RpcClient::new_mock_with_mocks`] function offers further + /// customization options. + /// + /// [`HashMap`]: std::collections::HashMap /// /// # Examples /// diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index 79b013578..8978b35ad 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -6,13 +6,14 @@ //! //! [JSON-RPC]: https://www.jsonrpc.org/specification +pub use crate::mock_sender::Mocks; #[allow(deprecated)] use crate::rpc_deprecated_config::{RpcConfirmedBlockConfig, RpcConfirmedTransactionConfig}; use { crate::{ client_error::Result as ClientResult, http_sender::HttpSender, - mock_sender::{MockSender, Mocks}, + mock_sender::MockSender, nonblocking::{self, rpc_client::get_rpc_request_str}, rpc_config::{RpcAccountInfoConfig, *}, rpc_request::{RpcRequest, TokenAccountsFilter}, @@ -103,8 +104,8 @@ pub struct GetConfirmedSignaturesForAddress2Config { /// [`Processed`] commitment level. These exceptions are noted in the method /// documentation. /// -/// [`Finalized`]: CommitmentLevel::Finalized -/// [`Processed`]: CommitmentLevel::Processed +/// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized +/// [`Processed`]: solana_sdk::commitment_config::CommitmentLevel::Processed /// [jsonprot]: https://docs.solana.com/developing/clients/jsonrpc-api /// [JSON-RPC]: https://www.jsonrpc.org/specification /// [slots]: https://docs.solana.com/terminology#slot @@ -145,6 +146,10 @@ pub struct GetConfirmedSignaturesForAddress2Config { /// [`is_timeout`](crate::client_error::reqwest::Error::is_timeout) method /// returns `true`. The default timeout is 30 seconds, and may be changed by /// calling an appropriate constructor with a `timeout` parameter. +/// +/// [`ClientError`]: crate::client_error::ClientError +/// [`ClientErrorKind`]: crate::client_error::ClientErrorKind +/// [`ClientErrorKind::Reqwest`]: crate::client_error::ClientErrorKind::Reqwest pub struct RpcClient { rpc_client: nonblocking::rpc_client::RpcClient, runtime: Option, @@ -161,8 +166,8 @@ impl RpcClient { /// /// This is the basic constructor, allowing construction with any type of /// `RpcSender`. Most applications should use one of the other constructors, - /// such as [`new`] and [`new_mock`], which create an `RpcClient` - /// encapsulating an [`HttpSender`] and [`MockSender`] respectively. + /// such as [`RpcClient::new`], [`RpcClient::new_with_commitment`] or + /// [`RpcClient::new_with_timeout`]. pub fn new_sender( sender: T, config: RpcClientConfig, @@ -186,9 +191,10 @@ impl RpcClient { /// "http://localhost:8899". /// /// The client has a default timeout of 30 seconds, and a default [commitment - /// level][cl] of [`Finalized`](CommitmentLevel::Finalized). + /// level][cl] of [`Finalized`]. /// /// [cl]: https://docs.solana.com/developing/clients/jsonrpc-api#configuring-state-commitment + /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// /// # Examples /// @@ -211,6 +217,8 @@ impl RpcClient { /// The client has a default timeout of 30 seconds, and a user-specified /// [`CommitmentLevel`] via [`CommitmentConfig`]. /// + /// [`CommitmentLevel`]: solana_sdk::commitment_config::CommitmentLevel + /// /// # Examples /// /// ``` @@ -233,9 +241,10 @@ impl RpcClient { /// "http://localhost:8899". /// /// The client has and a default [commitment level][cl] of - /// [`Finalized`](CommitmentLevel::Finalized). + /// [`Finalized`]. /// /// [cl]: https://docs.solana.com/developing/clients/jsonrpc-api#configuring-state-commitment + /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// /// # Examples /// @@ -335,8 +344,34 @@ impl RpcClient { /// Create a mock `RpcClient`. /// - /// See the [`MockSender`] documentation for an explanation of - /// how it treats the `url` argument. + /// A mock `RpcClient` contains an implementation of [`RpcSender`] that does + /// not use the network, and instead returns synthetic responses, for use in + /// tests. + /// + /// It is primarily for internal use, with limited customizability, and + /// behaviors determined by internal Solana test cases. New users should + /// consider implementing `RpcSender` themselves and constructing + /// `RpcClient` with [`RpcClient::new_sender`] to get mock behavior. + /// + /// Unless directed otherwise, a mock `RpcClient` will generally return a + /// reasonable default response to any request, at least for [`RpcRequest`] + /// values for which responses have been implemented. + /// + /// This mock can be customized by changing the `url` argument, which is not + /// actually a URL, but a simple string directive that changes the mock + /// behavior in specific scenarios: + /// + /// - It is customary to set the `url` to "succeeds" for mocks that should + /// return sucessfully, though this value is not actually interpreted. + /// + /// - If `url` is "fails" then any call to `send` will return `Ok(Value::Null)`. + /// + /// - Other possible values of `url` are specific to different `RpcRequest` + /// values. Read the implementation of (non-public) `MockSender` for + /// details. + /// + /// The [`RpcClient::new_mock_with_mocks`] function offers further + /// customization options. /// /// # Examples /// @@ -362,8 +397,43 @@ impl RpcClient { /// Create a mock `RpcClient`. /// - /// See the [`MockSender`] documentation for an explanation of how it treats - /// the `url` argument. + /// A mock `RpcClient` contains an implementation of [`RpcSender`] that does + /// not use the network, and instead returns synthetic responses, for use in + /// tests. + /// + /// It is primarily for internal use, with limited customizability, and + /// behaviors determined by internal Solana test cases. New users should + /// consider implementing `RpcSender` themselves and constructing + /// `RpcClient` with [`RpcClient::new_sender`] to get mock behavior. + /// + /// Unless directed otherwise, a mock `RpcClient` will generally return a + /// reasonable default response to any request, at least for [`RpcRequest`] + /// values for which responses have been implemented. + /// + /// This mock can be customized in two ways: + /// + /// 1) By changing the `url` argument, which is not actually a URL, but a + /// simple string directive that changes the mock behavior in specific + /// scenarios. + /// + /// It is customary to set the `url` to "succeeds" for mocks that should + /// return sucessfully, though this value is not actually interpreted. + /// + /// If `url` is "fails" then any call to `send` will return `Ok(Value::Null)`. + /// + /// Other possible values of `url` are specific to different `RpcRequest` + /// values. Read the implementation of `MockSender` (which is non-public) + /// for details. + /// + /// 2) Custom responses can be configured by providing [`Mocks`]. This type + /// is a [`HashMap`] from [`RpcRequest`] to a JSON [`Value`] response, + /// Any entries in this map override the default behavior for the given + /// request. + /// + /// The [`RpcClient::new_mock_with_mocks`] function offers further + /// customization options. + /// + /// [`HashMap`]: std::collections::HashMap /// /// # Examples /// @@ -397,9 +467,10 @@ impl RpcClient { /// Create an HTTP `RpcClient` from a [`SocketAddr`]. /// /// The client has a default timeout of 30 seconds, and a default [commitment - /// level][cl] of [`Finalized`](CommitmentLevel::Finalized). + /// level][cl] of [`Finalized`]. /// /// [cl]: https://docs.solana.com/developing/clients/jsonrpc-api#configuring-state-commitment + /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// /// # Examples /// @@ -420,6 +491,8 @@ impl RpcClient { /// The client has a default timeout of 30 seconds, and a user-specified /// [`CommitmentLevel`] via [`CommitmentConfig`]. /// + /// [`CommitmentLevel`]: solana_sdk::commitment_config::CommitmentLevel + /// /// # Examples /// /// ``` @@ -442,9 +515,10 @@ impl RpcClient { /// Create an HTTP `RpcClient` from a [`SocketAddr`] with specified timeout. /// - /// The client has a default [commitment level][cl] of [`Finalized`](CommitmentLevel::Finalized). + /// The client has a default [commitment level][cl] of [`Finalized`]. /// /// [cl]: https://docs.solana.com/developing/clients/jsonrpc-api#configuring-state-commitment + /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// /// # Examples /// @@ -469,7 +543,9 @@ impl RpcClient { /// determines how thoroughly committed a transaction must be when waiting /// for its confirmation or otherwise checking for confirmation. If not /// specified, the default commitment level is - /// [`Finalized`](CommitmentLevel::Finalized). + /// [`Finalized`]. + /// + /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// /// The default commitment level is overridden when calling methods that /// explicitly provide a [`CommitmentConfig`], like @@ -503,7 +579,8 @@ impl RpcClient { /// containing an [`RpcResponseError`] with `code` set to /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]. /// - /// [`RpcResponseError`]: RpcError::RpcResponseError + /// [`RpcError`]: crate::rpc_request::RpcError + /// [`RpcResponseError`]: crate::rpc_request::RpcError::RpcResponseError /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE /// [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY @@ -616,7 +693,8 @@ impl RpcClient { /// containing an [`RpcResponseError`] with `code` set to /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]. /// - /// [`RpcResponseError`]: RpcError::RpcResponseError + /// [`RpcError`]: crate::rpc_request::RpcError + /// [`RpcResponseError`]: crate::rpc_request::RpcError::RpcResponseError /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE /// [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY @@ -690,7 +768,8 @@ impl RpcClient { /// containing an [`RpcResponseError`] with `code` set to /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]. /// - /// [`RpcResponseError`]: RpcError::RpcResponseError + /// [`RpcError`]: crate::rpc_request::RpcError + /// [`RpcResponseError`]: crate::rpc_request::RpcError::RpcResponseError /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE /// [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY @@ -2102,7 +2181,7 @@ impl RpcClient { /// /// This method uses the [`Finalized`] [commitment level][cl]. /// - /// [`Finalized`]: CommitmentLevel::Finalized + /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// [`get_blocks_with_limit`]: RpcClient::get_blocks_with_limit. /// [cl]: https://docs.solana.com/developing/clients/jsonrpc-api#configuring-state-commitment /// @@ -2161,7 +2240,7 @@ impl RpcClient { /// This method returns an error if the given commitment level is below /// [`Confirmed`]. /// - /// [`Confirmed`]: CommitmentLevel::Confirmed + /// [`Confirmed`]: solana_sdk::commitment_config::CommitmentLevel::Confirmed /// /// # RPC Reference /// @@ -2254,7 +2333,7 @@ impl RpcClient { /// [`Confirmed`]. /// /// [cl]: https://docs.solana.com/developing/clients/jsonrpc-api#configuring-state-commitment - /// [`Confirmed`]: CommitmentLevel::Confirmed + /// [`Confirmed`]: solana_sdk::commitment_config::CommitmentLevel::Confirmed /// /// # RPC Reference /// @@ -2415,7 +2494,7 @@ impl RpcClient { /// [`Confirmed`]. /// /// [cl]: https://docs.solana.com/developing/clients/jsonrpc-api#configuring-state-commitment - /// [`Confirmed`]: CommitmentLevel::Confirmed + /// [`Confirmed`]: solana_sdk::commitment_config::CommitmentLevel::Confirmed /// /// # RPC Reference /// @@ -2505,7 +2584,7 @@ impl RpcClient { /// /// This method uses the [`Finalized`] [commitment level][cl]. /// - /// [`Finalized`]: CommitmentLevel::Finalized + /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// [cl]: https://docs.solana.com/developing/clients/jsonrpc-api#configuring-state-commitment /// /// # RPC Reference @@ -2560,7 +2639,7 @@ impl RpcClient { /// [`Confirmed`]. /// /// [cl]: https://docs.solana.com/developing/clients/jsonrpc-api#configuring-state-commitment - /// [`Confirmed`]: CommitmentLevel::Confirmed + /// [`Confirmed`]: solana_sdk::commitment_config::CommitmentLevel::Confirmed /// /// # RPC Reference /// @@ -2926,7 +3005,7 @@ impl RpcClient { /// /// This method uses the [`Finalized`] [commitment level][cl]. /// - /// [`Finalized`]: CommitmentLevel::Finalized + /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// [cl]: https://docs.solana.com/developing/clients/jsonrpc-api#configuring-state-commitment /// /// # RPC Reference @@ -3084,6 +3163,7 @@ impl RpcClient { /// [`RpcError::ForUser`]. This is unlike [`get_account_with_commitment`], /// which returns `Ok(None)` if the account does not exist. /// + /// [`RpcError::ForUser`]: crate::rpc_request::RpcError::ForUser /// [`get_account_with_commitment`]: RpcClient::get_account_with_commitment /// /// # RPC Reference diff --git a/client/src/rpc_sender.rs b/client/src/rpc_sender.rs index 68b71dc2e..10b3dbe7b 100644 --- a/client/src/rpc_sender.rs +++ b/client/src/rpc_sender.rs @@ -23,11 +23,7 @@ pub struct RpcTransportStats { /// `RpcSender` implements the underlying transport of requests to, and /// responses from, a Solana node, and is used primarily by [`RpcClient`]. /// -/// It is typically implemented by [`HttpSender`] in production, and -/// [`MockSender`] in unit tests. -/// -/// [`HttpSender`]: crate::http_sender::HttpSender -/// [`MockSender`]: crate::mock_sender::MockSender +/// [`RpcClient`]: crate::rpc_client::RpcClient #[async_trait] pub trait RpcSender { async fn send(