foundry_wallets/wallet_browser/
state.rs

1use std::sync::Arc;
2
3use tokio::sync::{Mutex, RwLock};
4use uuid::Uuid;
5
6use crate::wallet_browser::{
7    queue::RequestQueue,
8    types::{
9        BrowserSignRequest, BrowserSignResponse, BrowserTransactionRequest,
10        BrowserTransactionResponse, Connection,
11    },
12};
13
14#[derive(Debug, Clone)]
15pub(crate) struct BrowserWalletState {
16    /// Current information about the wallet connection.
17    connection: Arc<RwLock<Option<Connection>>>,
18    /// Request/response queue for transactions.
19    transactions: Arc<Mutex<RequestQueue<BrowserTransactionRequest, BrowserTransactionResponse>>>,
20    /// Request/response queue for signings.
21    signings: Arc<Mutex<RequestQueue<BrowserSignRequest, BrowserSignResponse>>>,
22    /// Unique session token for the wallet browser instance.
23    /// The CSP on the served page prevents this token from being loaded by other origins.
24    session_token: String,
25    /// If true, the server is running in development mode.
26    /// This relaxes certain security restrictions for local development.
27    ///
28    /// **WARNING**: This should only be used in a development environment.
29    development: bool,
30}
31
32impl BrowserWalletState {
33    /// Create a new browser wallet state.
34    pub fn new(session_token: String, development: bool) -> Self {
35        Self {
36            connection: Arc::new(RwLock::new(None)),
37            transactions: Arc::new(Mutex::new(RequestQueue::new())),
38            signings: Arc::new(Mutex::new(RequestQueue::new())),
39            session_token,
40            development,
41        }
42    }
43
44    /// Get the session token.
45    pub fn session_token(&self) -> &str {
46        &self.session_token
47    }
48
49    /// Check if in development mode.
50    /// This relaxes certain security restrictions for local development.
51    ///
52    /// **WARNING**: This should only be used in a development environment.
53    pub fn is_development(&self) -> bool {
54        self.development
55    }
56
57    /// Check if wallet is connected.
58    pub async fn is_connected(&self) -> bool {
59        self.connection.read().await.is_some()
60    }
61
62    /// Get current connection information.
63    pub async fn get_connection(&self) -> Option<Connection> {
64        *self.connection.read().await
65    }
66
67    /// Set connection information.
68    pub async fn set_connection(&self, connection: Option<Connection>) {
69        *self.connection.write().await = connection;
70    }
71
72    /// Add a transaction request.
73    pub async fn add_transaction_request(&self, request: BrowserTransactionRequest) {
74        self.transactions.lock().await.add_request(request);
75    }
76
77    /// Check if a transaction request exists.
78    pub async fn has_transaction_request(&self, id: &Uuid) -> bool {
79        self.transactions.lock().await.has_request(id)
80    }
81
82    /// Read the next transaction request.
83    pub async fn read_next_transaction_request(&self) -> Option<BrowserTransactionRequest> {
84        self.transactions.lock().await.read_request().cloned()
85    }
86
87    // Remove a transaction request.
88    pub async fn remove_transaction_request(&self, id: &Uuid) {
89        self.transactions.lock().await.remove_request(id);
90    }
91
92    /// Add transaction response.
93    pub async fn add_transaction_response(&self, response: BrowserTransactionResponse) {
94        let id = response.id;
95        let mut transactions = self.transactions.lock().await;
96        transactions.add_response(id, response);
97        transactions.remove_request(&id);
98    }
99
100    /// Get transaction response, removing it from the queue.
101    pub async fn get_transaction_response(&self, id: &Uuid) -> Option<BrowserTransactionResponse> {
102        self.transactions.lock().await.get_response(id)
103    }
104
105    /// Add a signing request.
106    pub async fn add_signing_request(&self, request: BrowserSignRequest) {
107        self.signings.lock().await.add_request(request);
108    }
109
110    /// Check if a signing request exists.
111    pub async fn has_signing_request(&self, id: &Uuid) -> bool {
112        self.signings.lock().await.has_request(id)
113    }
114
115    /// Read the next signing request.
116    pub async fn read_next_signing_request(&self) -> Option<BrowserSignRequest> {
117        self.signings.lock().await.read_request().cloned()
118    }
119
120    /// Remove a signing request.
121    pub async fn remove_signing_request(&self, id: &Uuid) {
122        self.signings.lock().await.remove_request(id);
123    }
124
125    /// Add signing response.
126    pub async fn add_signing_response(&self, response: BrowserSignResponse) {
127        let id = response.id;
128        let mut signings = self.signings.lock().await;
129        signings.add_response(id, response);
130        signings.remove_request(&id);
131    }
132
133    /// Get signing response, removing it from the queue.
134    pub async fn get_signing_response(&self, id: &Uuid) -> Option<BrowserSignResponse> {
135        self.signings.lock().await.get_response(id)
136    }
137}