use crate::{
error::SubmitError,
fabric::{
common::SignatureHeader,
protos::{
QueryPendingSnapshotsResponse, SignedSnapshotRequest, SnapshotQuery, SnapshotRequest,
},
protos::snapshot_client::SnapshotClient,
},
identity::Identity,
};
use prost::Message;
pub struct SnapshotRequestBuilder {
identity: Identity,
channel_id: Option<String>,
block_number: Option<u64>,
}
impl SnapshotRequestBuilder {
pub fn new(identity: Identity) -> Self {
Self {
identity,
channel_id: None,
block_number: None,
}
}
pub fn with_channel_id(mut self, channel_id: impl Into<String>) -> Result<Self, crate::error::BuilderError> {
let channel_id = channel_id.into().trim().to_string();
if channel_id.is_empty() {
return Err(crate::error::BuilderError::InvalidParameter(
"channel_id cannot be empty".into(),
));
}
self.channel_id = Some(channel_id);
Ok(self)
}
pub fn with_block_number(mut self, block_number: u64) -> Self {
self.block_number = Some(block_number);
self
}
pub fn build_signed_request(self) -> Result<SignedSnapshotRequest, crate::error::BuilderError> {
let channel_id = self
.channel_id
.ok_or_else(|| crate::error::BuilderError::MissingParameter("channel_id".into()))?;
let block_number = self
.block_number
.ok_or_else(|| crate::error::BuilderError::MissingParameter("block_number".into()))?;
let signature_header = SignatureHeader {
creator: self.identity.get_serialized_identity().encode_to_vec(),
nonce: vec![], };
let request = SnapshotRequest {
signature_header: Some(signature_header),
channel_id,
block_number,
};
let request_bytes = request.encode_to_vec();
let signature = self.identity.sign_message(&request_bytes);
Ok(SignedSnapshotRequest {
request: request_bytes,
signature,
})
}
}
pub struct SnapshotQueryBuilder {
identity: Identity,
channel_id: Option<String>,
}
impl SnapshotQueryBuilder {
pub fn new(identity: Identity) -> Self {
Self {
identity,
channel_id: None,
}
}
pub fn with_channel_id(mut self, channel_id: impl Into<String>) -> Result<Self, crate::error::BuilderError> {
let channel_id = channel_id.into().trim().to_string();
if channel_id.is_empty() {
return Err(crate::error::BuilderError::InvalidParameter(
"channel_id cannot be empty".into(),
));
}
self.channel_id = Some(channel_id);
Ok(self)
}
pub fn build_signed_query(self) -> Result<SignedSnapshotRequest, crate::error::BuilderError> {
let channel_id = self
.channel_id
.ok_or_else(|| crate::error::BuilderError::MissingParameter("channel_id".into()))?;
let signature_header = SignatureHeader {
creator: self.identity.get_serialized_identity().encode_to_vec(),
nonce: vec![], };
let query = SnapshotQuery {
signature_header: Some(signature_header),
channel_id,
};
let query_bytes = query.encode_to_vec();
let signature = self.identity.sign_message(&query_bytes);
Ok(SignedSnapshotRequest {
request: query_bytes,
signature,
})
}
}
pub struct SnapshotClientWrapper {
client: SnapshotClient<tonic::transport::Channel>,
}
impl SnapshotClientWrapper {
pub fn new(channel: tonic::transport::Channel) -> Self {
let client = SnapshotClient::new(channel);
Self { client }
}
pub async fn generate(
&mut self,
request: SignedSnapshotRequest,
) -> Result<(), SubmitError> {
let response = self.client.generate(request).await;
match response {
Ok(_) => Ok(()),
Err(err) => Err(SubmitError::NodeError(
String::from_utf8_lossy(err.details()).into_owned(),
)),
}
}
pub async fn cancel(
&mut self,
request: SignedSnapshotRequest,
) -> Result<(), SubmitError> {
let response = self.client.cancel(request).await;
match response {
Ok(_) => Ok(()),
Err(err) => Err(SubmitError::NodeError(
String::from_utf8_lossy(err.details()).into_owned(),
)),
}
}
pub async fn query_pendings(
&mut self,
request: SignedSnapshotRequest,
) -> Result<QueryPendingSnapshotsResponse, SubmitError> {
let response = self.client.query_pendings(request).await;
match response {
Ok(response) => Ok(response.into_inner()),
Err(err) => Err(SubmitError::NodeError(
String::from_utf8_lossy(err.details()).into_owned(),
)),
}
}
}