use super::Client;
use crate::{Error, Result};
use sn_interface::{
messaging::{
data::{ClientMsg, DataCmd},
ClientAuth, WireMsg,
},
types::{PublicKey, Signature},
};
use bytes::Bytes;
use xor_name::XorName;
impl Client {
pub fn sign(&self, data: &[u8]) -> Signature {
self.keypair.sign(data)
}
pub async fn send_signed_cmd(
&self,
dst_address: XorName,
client_pk: PublicKey,
serialised_cmd: Bytes,
signature: Signature,
needs_super_majority: bool,
) -> Result<()> {
let auth = ClientAuth {
public_key: client_pk,
signature,
};
tokio::time::timeout(self.cmd_timeout, async {
self.session
.send_cmd(dst_address, auth, serialised_cmd, needs_super_majority)
.await
})
.await
.map_err(|_| Error::CmdAckValidationTimeout {
elapsed: self.cmd_timeout,
dst_address,
})?
}
#[instrument(skip_all, level = "debug", name = "client-api send cmd")]
pub async fn send_cmd(&self, cmd: DataCmd) -> Result<()> {
let client_pk = self.public_key();
let dst_name = cmd.dst_name();
let debug_cmd = format!("{:?}", cmd);
debug!("Attempting {debug_cmd}");
let needs_super_majority = matches!(cmd, DataCmd::Spentbook(_));
let serialised_cmd = {
let msg = ClientMsg::Cmd(cmd);
WireMsg::serialize_msg_payload(&msg)?
};
let signature = self.sign(&serialised_cmd);
let res = self
.send_signed_cmd(
dst_name,
client_pk,
serialised_cmd,
signature,
needs_super_majority,
)
.await;
if res.is_ok() {
debug!("{debug_cmd} sent okay: {res:?}");
} else {
trace!("Failed response on {debug_cmd}, response: {:?}", res);
}
res
}
}