use crate::codec::ClientCodec;
use crate::{Error, Result};
use std::net::{TcpStream, ToSocketAddrs};
use tendermint_proto::abci::{
request, response, RequestApplySnapshotChunk, RequestBeginBlock, RequestCheckTx, RequestCommit,
RequestDeliverTx, RequestEndBlock, RequestFlush, RequestInfo, RequestInitChain,
RequestListSnapshots, RequestLoadSnapshotChunk, RequestOfferSnapshot, RequestQuery,
RequestSetOption, ResponseApplySnapshotChunk, ResponseBeginBlock, ResponseCheckTx,
ResponseCommit, ResponseDeliverTx, ResponseEndBlock, ResponseFlush, ResponseInfo,
ResponseInitChain, ResponseListSnapshots, ResponseLoadSnapshotChunk, ResponseOfferSnapshot,
ResponseQuery, ResponseSetOption,
};
use tendermint_proto::abci::{Request, RequestEcho, ResponseEcho};
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> {
let stream = TcpStream::connect(addr)?;
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::UnexpectedServerResponseType(stringify!($type).to_string(), r).into()),
}
};
}
impl Client {
pub fn echo(&mut self, req: RequestEcho) -> Result<ResponseEcho> {
perform!(self, Echo, req)
}
pub fn info(&mut self, req: RequestInfo) -> Result<ResponseInfo> {
perform!(self, Info, req)
}
pub fn init_chain(&mut self, req: RequestInitChain) -> Result<ResponseInitChain> {
perform!(self, InitChain, req)
}
pub fn query(&mut self, req: RequestQuery) -> Result<ResponseQuery> {
perform!(self, Query, req)
}
pub fn check_tx(&mut self, req: RequestCheckTx) -> Result<ResponseCheckTx> {
perform!(self, CheckTx, req)
}
pub fn begin_block(&mut self, req: RequestBeginBlock) -> Result<ResponseBeginBlock> {
perform!(self, BeginBlock, req)
}
pub fn deliver_tx(&mut self, req: RequestDeliverTx) -> Result<ResponseDeliverTx> {
perform!(self, DeliverTx, req)
}
pub fn end_block(&mut self, req: RequestEndBlock) -> Result<ResponseEndBlock> {
perform!(self, EndBlock, req)
}
pub fn flush(&mut self) -> Result<ResponseFlush> {
perform!(self, Flush, RequestFlush {})
}
pub fn commit(&mut self) -> Result<ResponseCommit> {
perform!(self, Commit, RequestCommit {})
}
pub fn set_option(&mut self, req: RequestSetOption) -> Result<ResponseSetOption> {
perform!(self, SetOption, req)
}
pub fn list_snapshots(&mut self) -> Result<ResponseListSnapshots> {
perform!(self, ListSnapshots, RequestListSnapshots {})
}
pub fn offer_snapshot(&mut self, req: RequestOfferSnapshot) -> Result<ResponseOfferSnapshot> {
perform!(self, OfferSnapshot, req)
}
pub fn load_snapshot_chunk(
&mut self,
req: RequestLoadSnapshotChunk,
) -> Result<ResponseLoadSnapshotChunk> {
perform!(self, LoadSnapshotChunk, req)
}
pub fn apply_snapshot_chunk(
&mut self,
req: RequestApplySnapshotChunk,
) -> Result<ResponseApplySnapshotChunk> {
perform!(self, ApplySnapshotChunk, req)
}
fn perform(&mut self, req: request::Value) -> Result<response::Value> {
self.codec.send(Request { value: Some(req) })?;
let res = self
.codec
.next()
.ok_or(Error::ServerConnectionTerminated)??;
match res.value {
Some(value) => Ok(value),
None => Err(Error::MalformedServerResponse.into()),
}
}
}