wip
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}