docs/src/proposals/rust-clients.md
High-level tests, such as bench-tps, are written in terms of the Client
trait. When we execute these tests as part of the test suite, we use the
low-level BankClient implementation. When we need to run the same test
against a cluster, we use the ThinClient implementation. The problem with
that approach is that it means the trait will continually expand to include new
utility functions and all implementations of it need to add the new
functionality. By separating the user-facing object from the trait that abstracts
the network interface, we can expand the user-facing object to include all sorts
of useful functionality, such as the "spinner" from RpcClient, without concern
for needing to extend the trait and its implementations.
Instead of implementing the Client trait, ThinClient should be constructed
with an implementation of it. That way, all utility functions currently in the
Client trait can move into ThinClient. ThinClient could then move into
solana-sdk since all its network dependencies would be in the implementation
of Client. We would then add a new implementation of Client, called
ClusterClient, and that would live in the solana-client crate, where
ThinClient currently resides.
After this reorg, any code needing a client would be written in terms of
ThinClient. In unit tests, the functionality would be invoked with
ThinClient<BankClient>, whereas main() functions, benchmarks and
integration tests would invoke it with ThinClient<ClusterClient>.
If higher-level components require more functionality than what could be
implemented by BankClient, it should be implemented by a second object
that implements a second trait, following the same pattern described here.
The Client should use the existing TransportError enum for errors, except
that the Custom(String) field should be changed to Custom(Box<dyn Error>).
solana-sdk, RpcClientTng, where the Tng suffix is
temporary and stands for "The Next Generation"RpcClientTng with a SyncClient implementation.solana-sdk, ThinClientTng; initialize it with
RpcClientTng and an AsyncClient implementationBankClient to ThinClientTng<BankClient>ClusterClientThinClient users to ThinClientTng<ClusterClient>ThinClient and rename ThinClientTng to ThinClientRpcClient users to new ThinClient<ClusterClient>RpcClient and rename RpcClientTng to RpcClient