rusnap_api/
dialog.rs

1use serde::{Deserialize, Serialize};
2
3use crate::Result;
4
5use super::request;
6
7/// Snap custom UI Component.
8///
9/// Snap Document: [Components](https://docs.metamask.io/snaps/how-to/use-custom-ui/#components)
10#[derive(Debug, Serialize, Deserialize)]
11#[serde(tag = "type")]
12#[serde(rename_all = "lowercase")]
13pub enum UiComponent {
14    Panel { children: Vec<UiComponent> },
15    Copyable { value: String },
16    Divider,
17    Heading { value: String },
18    Spinner,
19    Text { value: String },
20}
21
22/// Helper function to create `UiComponent`.
23pub mod ui {
24    use super::UiComponent;
25
26    /// A panel, which can be used as a container for other components.
27    ///
28    /// Snap Document: [panel](https://docs.metamask.io/snaps/how-to/use-custom-ui/#panel)
29    pub fn panel<T>(children: T) -> UiComponent
30    where
31        T: Into<Vec<UiComponent>>,
32    {
33        UiComponent::Panel {
34            children: children.into(),
35        }
36    }
37
38    /// A read-only text field with a copy-to-clipboard shortcut.
39    ///
40    /// Snap Document: [copyable](https://docs.metamask.io/snaps/how-to/use-custom-ui/#copyable)
41    pub fn copyable<T>(value: T) -> UiComponent
42    where
43        T: Into<String>,
44    {
45        UiComponent::Copyable {
46            value: value.into(),
47        }
48    }
49
50    /// A horizontal divider.
51    ///
52    /// Snap Document: [divider](https://docs.metamask.io/snaps/how-to/use-custom-ui/#divider)
53    pub fn divider() -> UiComponent {
54        UiComponent::Divider
55    }
56
57    /// A heading.
58    ///
59    /// Snap Document: [heading](https://docs.metamask.io/snaps/how-to/use-custom-ui/#heading)
60    pub fn heading<T>(value: T) -> UiComponent
61    where
62        T: Into<String>,
63    {
64        UiComponent::Heading {
65            value: value.into(),
66        }
67    }
68
69    /// A loading indicator.
70    ///
71    /// Snap Document: [spinner](https://docs.metamask.io/snaps/how-to/use-custom-ui/#spinner)
72    pub fn spinner() -> UiComponent {
73        UiComponent::Spinner
74    }
75
76    /// Text
77    ///
78    /// Snap Document: [text](https://docs.metamask.io/snaps/how-to/use-custom-ui/#text)
79    pub fn text<T>(value: T) -> UiComponent
80    where
81        T: Into<String>,
82    {
83        UiComponent::Text {
84            value: value.into(),
85        }
86    }
87}
88
89#[derive(Debug, Serialize, Deserialize)]
90struct DialogParams {
91    #[serde(rename = "type")]
92    ty: &'static str,
93    content: UiComponent,
94    #[serde(skip_serializing_if = "Option::is_none")]
95    placeholder: Option<String>,
96}
97
98/// Create an alert dialog.
99///
100/// Snap Document: [Alert dialog](https://docs.metamask.io/snaps/reference/rpc-api/#alert-dialog)
101pub async fn alert(content: UiComponent) -> Result<()> {
102    let req = DialogParams {
103        ty: "alert",
104        content,
105        placeholder: None,
106    };
107
108    request("snap_dialog", req).await?;
109
110    Ok(())
111}
112
113/// Create a confirmation dialog.
114///
115/// Snap Document: [Confirmation dialog](https://docs.metamask.io/snaps/reference/rpc-api/#confirmation-dialog)
116pub async fn confirm(content: UiComponent) -> Result<bool> {
117    let req = DialogParams {
118        ty: "confirmation",
119        content,
120        placeholder: None,
121    };
122
123    Ok(request("snap_dialog", req).await?)
124}
125
126/// Create a prompt dialog
127///
128/// Snap Document: [Prompt dialog](https://docs.metamask.io/snaps/reference/rpc-api/#prompt-dialog)
129pub async fn prompt(content: UiComponent, placeholder: &str) -> Result<Option<String>> {
130    let req = DialogParams {
131        ty: "prompt",
132        content,
133        placeholder: Some(String::from(placeholder)),
134    };
135
136    Ok(request("snap_dialog", req).await?)
137}