at main 4.9 kB view raw
1pub use common::message::{PlcOperation, SignedPlcOperation}; 2use common::message::{Request, Response}; 3use sdk::vanadium_client::{VAppClient, VAppExecutionError}; 4 5use sdk::comm::SendMessageError; 6 7pub use sdk::{transport, vanadium_client}; 8 9#[derive(Debug)] 10pub enum AtprotoAppClientError { 11 VAppExecutionError(VAppExecutionError), 12 SendMessageError(SendMessageError), 13 InvalidResponse(&'static str), 14 GenericError(&'static str), 15} 16 17impl From<VAppExecutionError> for AtprotoAppClientError { 18 fn from(e: VAppExecutionError) -> Self { 19 Self::VAppExecutionError(e) 20 } 21} 22 23impl From<SendMessageError> for AtprotoAppClientError { 24 fn from(e: SendMessageError) -> Self { 25 Self::SendMessageError(e) 26 } 27} 28 29impl From<&'static str> for AtprotoAppClientError { 30 fn from(e: &'static str) -> Self { 31 Self::GenericError(e) 32 } 33} 34 35impl std::fmt::Display for AtprotoAppClientError { 36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 37 match self { 38 AtprotoAppClientError::VAppExecutionError(e) => write!(f, "VAppExecutionError: {}", e), 39 AtprotoAppClientError::SendMessageError(e) => write!(f, "SendMessageError: {}", e), 40 AtprotoAppClientError::InvalidResponse(e) => write!(f, "InvalidResponse: {}", e), 41 AtprotoAppClientError::GenericError(e) => write!(f, "GenericError: {}", e), 42 } 43 } 44} 45 46impl std::error::Error for AtprotoAppClientError { 47 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 48 match self { 49 AtprotoAppClientError::VAppExecutionError(e) => Some(e), 50 AtprotoAppClientError::SendMessageError(e) => Some(e), 51 AtprotoAppClientError::InvalidResponse(_) => None, 52 AtprotoAppClientError::GenericError(_) => None, 53 } 54 } 55} 56 57pub struct AtprotoAppClient { 58 app_client: Box<dyn VAppClient + Send + Sync>, 59} 60 61impl<'a> AtprotoAppClient { 62 pub fn new(app_client: Box<dyn VAppClient + Send + Sync>) -> Self { 63 Self { app_client } 64 } 65 66 async fn send_message(&mut self, out: &[u8]) -> Result<Vec<u8>, AtprotoAppClientError> { 67 sdk::comm::send_message(&mut self.app_client, out) 68 .await 69 .map_err(AtprotoAppClientError::from) 70 } 71 72 async fn parse_response(response_raw: &'a [u8]) -> Result<Response, AtprotoAppClientError> { 73 let resp: Response = postcard::from_bytes(response_raw) 74 .map_err(|_| AtprotoAppClientError::GenericError("Failed to parse response"))?; 75 Ok(resp) 76 } 77 78 pub async fn get_did_key( 79 &mut self, 80 index: u32, 81 display: bool, 82 ) -> Result<Vec<u8>, AtprotoAppClientError> { 83 let msg = postcard::to_allocvec(&Request::GetDidKey { index, display }) 84 .map_err(|_| AtprotoAppClientError::GenericError("Failed to serialize Exit request"))?; 85 86 let response_raw = self.send_message(&msg).await?; 87 match Self::parse_response(&response_raw).await? { 88 Response::DidKey(key) => Ok(key), 89 _ => Err(AtprotoAppClientError::InvalidResponse("Invalid response")), 90 } 91 } 92 93 pub async fn sign_plc_operation( 94 &mut self, 95 key_index: u32, 96 operation: PlcOperation, 97 previous: Option<SignedPlcOperation>, 98 ) -> Result<Vec<u8>, AtprotoAppClientError> { 99 let msg = postcard::to_allocvec(&Request::SignPlcOperation { 100 key_index, 101 previous, 102 operation, 103 }) 104 .map_err(|e| { 105 eprintln!("{:?}", e); 106 AtprotoAppClientError::GenericError("Failed to serialize SignPlcOperation request") 107 })?; 108 109 let response_raw = self.send_message(&msg).await?; 110 match Self::parse_response(&response_raw).await? { 111 Response::Signature(sig) => Ok(sig), 112 _ => Err(AtprotoAppClientError::InvalidResponse("Invalid response")), 113 } 114 } 115 116 pub async fn exit(&mut self) -> Result<i32, AtprotoAppClientError> { 117 let msg = postcard::to_allocvec(&Request::Exit) 118 .map_err(|_| AtprotoAppClientError::GenericError("Failed to serialize Exit request"))?; 119 let response_raw = self.send_message(&msg).await?; 120 121 match Self::parse_response(&response_raw).await { 122 Ok(_) => Err(AtprotoAppClientError::InvalidResponse( 123 "Exit message shouldn't return!", 124 )), 125 Err(e) => match e { 126 AtprotoAppClientError::VAppExecutionError(VAppExecutionError::AppExited( 127 status, 128 )) => Ok(status), 129 e => { 130 println!("Unexpected error on exit: {:?}", e); 131 Err(AtprotoAppClientError::InvalidResponse( 132 "Unexpected error on exit", 133 )) 134 } 135 }, 136 } 137 } 138}