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