use std::net::{TcpStream, ToSocketAddrs};
use tendermint_proto::v0_38::abci::{
request, response, Request, RequestApplySnapshotChunk, RequestCheckTx, RequestCommit,
RequestEcho, RequestExtendVote, RequestFinalizeBlock, RequestFlush, RequestInfo,
RequestInitChain, RequestListSnapshots, RequestLoadSnapshotChunk, RequestOfferSnapshot,
RequestQuery, RequestVerifyVoteExtension, ResponseApplySnapshotChunk, ResponseCheckTx,
ResponseCommit, ResponseEcho, ResponseExtendVote, ResponseFinalizeBlock, ResponseFlush,
ResponseInfo, ResponseInitChain, ResponseListSnapshots, ResponseLoadSnapshotChunk,
ResponseOfferSnapshot, ResponseQuery, ResponseVerifyVoteExtension,
};
use crate::{codec::ClientCodec, Error};
pub const DEFAULT_CLIENT_READ_BUF_SIZE: usize = 1024;
pub struct ClientBuilder {
read_buf_size: usize,
}
impl ClientBuilder {
pub fn new(read_buf_size: usize) -> Self {
Self { read_buf_size }
}
pub fn connect<A: ToSocketAddrs>(self, addr: A) -> Result<Client, Error> {
let stream = TcpStream::connect(addr).map_err(Error::io)?;
Ok(Client {
codec: ClientCodec::new(stream, self.read_buf_size),
})
}
}
impl Default for ClientBuilder {
fn default() -> Self {
Self {
read_buf_size: DEFAULT_CLIENT_READ_BUF_SIZE,
}
}
}
pub struct Client {
codec: ClientCodec<TcpStream>,
}
macro_rules! perform {
($self:expr, $type:ident, $req:expr) => {
match $self.perform(request::Value::$type($req))? {
response::Value::$type(r) => Ok(r),
r => {
Err(Error::unexpected_server_response_type(stringify!($type).to_string(), r).into())
},
}
};
}
impl Client {
pub fn echo(&mut self, req: RequestEcho) -> Result<ResponseEcho, Error> {
perform!(self, Echo, req)
}
pub fn info(&mut self, req: RequestInfo) -> Result<ResponseInfo, Error> {
perform!(self, Info, req)
}
pub fn init_chain(&mut self, req: RequestInitChain) -> Result<ResponseInitChain, Error> {
perform!(self, InitChain, req)
}
pub fn query(&mut self, req: RequestQuery) -> Result<ResponseQuery, Error> {
perform!(self, Query, req)
}
pub fn check_tx(&mut self, req: RequestCheckTx) -> Result<ResponseCheckTx, Error> {
perform!(self, CheckTx, req)
}
pub fn flush(&mut self) -> Result<ResponseFlush, Error> {
perform!(self, Flush, RequestFlush {})
}
pub fn commit(&mut self) -> Result<ResponseCommit, Error> {
perform!(self, Commit, RequestCommit {})
}
pub fn list_snapshots(&mut self) -> Result<ResponseListSnapshots, Error> {
perform!(self, ListSnapshots, RequestListSnapshots {})
}
pub fn offer_snapshot(
&mut self,
req: RequestOfferSnapshot,
) -> Result<ResponseOfferSnapshot, Error> {
perform!(self, OfferSnapshot, req)
}
pub fn load_snapshot_chunk(
&mut self,
req: RequestLoadSnapshotChunk,
) -> Result<ResponseLoadSnapshotChunk, Error> {
perform!(self, LoadSnapshotChunk, req)
}
pub fn apply_snapshot_chunk(
&mut self,
req: RequestApplySnapshotChunk,
) -> Result<ResponseApplySnapshotChunk, Error> {
perform!(self, ApplySnapshotChunk, req)
}
pub fn extend_vote(&mut self, req: RequestExtendVote) -> Result<ResponseExtendVote, Error> {
perform!(self, ExtendVote, req)
}
pub fn verify_vote_extension(
&mut self,
req: RequestVerifyVoteExtension,
) -> Result<ResponseVerifyVoteExtension, Error> {
perform!(self, VerifyVoteExtension, req)
}
pub fn finalize_block(
&mut self,
req: RequestFinalizeBlock,
) -> Result<ResponseFinalizeBlock, Error> {
perform!(self, FinalizeBlock, req)
}
fn perform(&mut self, req: request::Value) -> Result<response::Value, Error> {
self.codec.send(Request { value: Some(req) })?;
let res = self
.codec
.next()
.ok_or_else(Error::server_connection_terminated)??;
res.value.ok_or_else(Error::malformed_server_response)
}
}