1use serde::{Deserialize, Serialize};
2use serde_json::{json, Value};
3
4#[derive(Debug, Serialize, Deserialize)]
5pub struct SnapPackage {
6 pub name: String,
7 pub icon: String,
8 pub description: String,
9 pub registry: String,
10}
11
12#[derive(Debug, Serialize, Deserialize)]
13#[serde(rename_all = "lowercase")]
14pub enum Curve {
15 Secp256k1,
16 Ed25519,
17}
18
19#[derive(Debug, Serialize, Deserialize)]
20pub struct Bip32 {
21 pub path: String,
22 pub curve: Curve,
23}
24
25impl Bip32 {
26 pub fn to_json(&self) -> Value {
27 let s: Vec<String> = self.path.split('/').map(String::from).collect();
28
29 json!({ "path": s, "curve": self.curve })
30 }
31}
32
33#[derive(Debug, Serialize, Deserialize)]
34pub struct Bip44 {
35 pub coin_type: u64,
36}
37
38impl Bip44 {
39 pub fn to_json(&self) -> Value {
40 json!({
41 "coinType": self.coin_type
42 })
43 }
44}
45
46#[derive(Debug, Serialize, Deserialize)]
47pub struct CronjobRequest {
48 pub method: String,
49 pub params: toml::Value,
50}
51
52#[derive(Debug, Serialize, Deserialize)]
53pub struct Cronjob {
54 pub expression: String,
55 pub request: CronjobRequest,
56}
57
58impl Cronjob {
59 pub fn to_json(&self) -> Value {
60 json!({
61 "expression": self.expression,
62 "request": {
63 "method": self.request.method,
64 "params": self.request.params
65 }
66 })
67 }
68}
69
70#[derive(Debug, Serialize, Deserialize)]
71pub struct RPC {
72 pub dapps: bool,
73 pub snaps: bool,
74}
75
76#[derive(Debug, Serialize, Deserialize)]
77pub struct TransactionInsight {
78 pub allow_transaction_origin: bool,
79}
80
81#[derive(Debug, Serialize, Deserialize)]
82pub struct Empty {}
83
84#[derive(Debug, Serialize, Deserialize)]
85pub struct SnapPermissions {
86 pub dialog: Option<Empty>,
87 pub bip32_entropy: Option<Vec<Bip32>>,
88 pub bip32_public_key: Option<Vec<Bip32>>,
89 pub bip44_entropy: Option<Vec<Bip44>>,
90 pub entropy: Option<Empty>,
91 pub manage_accounts: Option<Empty>,
92 pub manage_state: Option<Empty>,
93 pub notify: Option<Empty>,
94 pub cronjob: Option<Vec<Cronjob>>,
95 pub ethereum_provider: Option<Empty>,
96 pub network_access: Option<Empty>,
97 pub rpc: Option<RPC>,
98 pub transaction_insight: Option<TransactionInsight>,
99}
100
101impl SnapPermissions {
102 pub fn build_json(&self, v: &mut Value) {
103 if self.dialog.is_some() {
104 v["snap_dialog"] = json!({});
105 }
106
107 if let Some(vs) = &self.bip32_entropy {
108 let vs: Vec<Value> = vs.iter().map(Bip32::to_json).collect();
109 v["snap_getBip32Entropy"] = Value::Array(vs);
110 }
111
112 if let Some(vs) = &self.bip32_public_key {
113 let vs: Vec<Value> = vs.iter().map(Bip32::to_json).collect();
114 v["snap_getBip32PublicKey"] = Value::Array(vs);
115 }
116
117 if let Some(vs) = &self.bip44_entropy {
118 let vs: Vec<Value> = vs.iter().map(Bip44::to_json).collect();
119 v["snap_getBip44Entropy"] = Value::Array(vs);
120 }
121
122 if self.entropy.is_some() {
123 v["snap_getEntropy"] = json!({});
124 }
125
126 if self.manage_accounts.is_some() {
127 v["snap_manageAccounts"] = json!({});
128 }
129
130 if self.manage_state.is_some() {
131 v["snap_manageState"] = json!({});
132 }
133
134 if self.notify.is_some() {
135 v["snap_notify"] = json!({});
136 }
137
138 if let Some(vs) = &self.cronjob {
139 let vs: Vec<Value> = vs.iter().map(Cronjob::to_json).collect();
140 v["endowment:cronjob"] = json!({ "jobs": vs });
141 }
142
143 if self.ethereum_provider.is_some() {
144 v["endowment:ethereum-provider"] = json!({});
145 }
146
147 if self.network_access.is_some() {
148 v["endowment:network-access"] = json!({});
149 }
150
151 if let Some(rpc) = &self.rpc {
152 v["endowment:rpc"] = json!({
153 "dapps": rpc.dapps,
154 "snaps": rpc.snaps
155 });
156 }
157
158 if let Some(e) = &self.transaction_insight {
159 v["endowment:transaction-insight"] = json!({
160 "allowTransactionOrigin": e.allow_transaction_origin
161 });
162 }
163 }
164}
165
166#[derive(Debug, Serialize, Deserialize)]
167pub struct SnapConfig {
168 pub snap: SnapPackage,
169 pub permissions: Option<SnapPermissions>,
170}
171
172#[cfg(test)]
173mod tests {
174 use crate::SnapConfig;
175
176 #[test]
177 fn test_config() {
178 let s = include_str!("../assets/Snap.toml");
179
180 let o: SnapConfig = toml::from_str(s).unwrap();
181
182 println!("{:#?}", o);
183 }
184}