Skip to main content

gm_lib/tui/app/pages/
sign_message.rs

1use std::sync::{atomic::AtomicBool, mpsc, Arc};
2
3use alloy::signers::SignerSync;
4use ratatui::{buffer::Buffer, layout::Rect};
5use strum::EnumIter;
6
7use crate::{
8    tui::{
9        app::{
10            widgets::form::{Form, FormItemIndex, FormWidget},
11            SharedState,
12        },
13        events::Event,
14        traits::{Component, HandleResult},
15    },
16    utils::account::AccountManager,
17};
18
19#[derive(EnumIter, PartialEq)]
20pub enum FormItem {
21    Heading,
22    Message,
23    SignMessageButton,
24    Signature,
25}
26
27pub struct SignMessagePage {
28    form: Form<FormItem>,
29}
30impl FormItemIndex for FormItem {
31    fn index(self) -> usize {
32        self as usize
33    }
34}
35impl TryFrom<FormItem> for FormWidget {
36    type Error = crate::Error;
37    fn try_from(value: FormItem) -> crate::Result<Self> {
38        let widget = match value {
39            FormItem::Heading => FormWidget::Heading("Sign a Message"),
40            FormItem::Message => FormWidget::InputBox {
41                label: "Message",
42                text: String::new(),
43                empty_text: Some("Type message to sign"),
44                currency: None,
45            },
46            FormItem::SignMessageButton => FormWidget::Button {
47                label: "Sign Message",
48            },
49            FormItem::Signature => FormWidget::DisplayText(String::new()),
50        };
51        Ok(widget)
52    }
53}
54
55impl SignMessagePage {
56    pub fn new() -> crate::Result<Self> {
57        Ok(Self {
58            form: Form::init(|_| Ok(()))?,
59        })
60    }
61}
62
63impl Component for SignMessagePage {
64    fn set_focus(&mut self, focus: bool) {
65        self.form.set_form_focus(focus);
66    }
67
68    fn handle_event(
69        &mut self,
70        event: &Event,
71        _area: Rect,
72        _transmitter: &mpsc::Sender<Event>,
73        _shutdown_signal: &Arc<AtomicBool>,
74        shared_state: &SharedState,
75    ) -> crate::Result<HandleResult> {
76        self.form.handle_event(
77            event,
78            |_, _| Ok(()),
79            |item, form| {
80                if item == FormItem::SignMessageButton
81                    && form.get_text(FormItem::Signature).is_empty()
82                {
83                    let message = form.get_text(FormItem::Message);
84
85                    let wallet_address = shared_state.try_current_account()?;
86                    let wallet = AccountManager::load_wallet(&wallet_address)?;
87                    let signature = wallet.sign_message_sync(message.as_bytes())?;
88                    *form.get_text_mut(FormItem::Signature) = format!("Signature:\n{signature}");
89                }
90                Ok(())
91            },
92        )?;
93        Ok(HandleResult::default())
94    }
95
96    fn render_component(&self, area: Rect, buf: &mut Buffer, ss: &SharedState) -> Rect
97    where
98        Self: Sized,
99    {
100        self.form.render(area, buf, &ss.theme);
101
102        area
103    }
104}