penumbra_sdk_custody/
terminal.rs1use anyhow::Result;
2use penumbra_sdk_governance::ValidatorVoteBody;
3use penumbra_sdk_proto::DomainType;
4use penumbra_sdk_stake::validator::Validator;
5use penumbra_sdk_transaction::TransactionPlan;
6use serde::de::DeserializeOwned;
7use tonic::async_trait;
8
9#[derive(Debug, Clone)]
10pub enum SigningRequest {
11 TransactionPlan(TransactionPlan),
12 ValidatorDefinition(Validator),
13 ValidatorVote(ValidatorVoteBody),
14}
15#[async_trait]
20pub trait Terminal: Sync {
21 async fn confirm_request(&self, request: &SigningRequest) -> Result<bool>;
27
28 fn explain(&self, msg: &str) -> Result<()>;
35
36 async fn broadcast(&self, data: &str) -> Result<()>;
38
39 async fn next_response<D>(&self) -> Result<D>
42 where
43 D: DomainType,
44 anyhow::Error: From<<D as TryFrom<<D as DomainType>::Proto>>::Error>,
45 <D as DomainType>::Proto: DeserializeOwned,
46 {
47 loop {
48 let line = self.read_line_raw().await?;
50
51 let proto = match serde_json::from_str::<<D as DomainType>::Proto>(&line) {
52 Ok(proto) => proto,
53 Err(e) => {
54 self.explain(&format!("Error parsing response: {:#}", e))?;
55 self.explain("Please try again:")?;
56 continue;
57 }
58 };
59
60 let message = match D::try_from(proto) {
61 Ok(message) => message,
62 Err(e) => {
63 let e: anyhow::Error = e.into();
64 self.explain(&format!("Error parsing response: {:#}", e))?;
65 self.explain("Please try again:")?;
66 continue;
67 }
68 };
69
70 return Ok(message);
71 }
72 }
73
74 async fn read_line_raw(&self) -> Result<String>;
76
77 async fn get_password(&self) -> Result<String>;
79}