1use crate::{Error, env::EnvError};
4use candid::Principal;
5use thiserror::Error as ThisError;
6
7#[derive(Debug, ThisError)]
12pub enum SnsError {
13 #[error("invalid principal: {0} ({1})")]
14 InvalidPrincipal(String, String),
15}
16
17impl From<SnsError> for Error {
18 fn from(err: SnsError) -> Self {
19 EnvError::SnsError(err).into()
20 }
21}
22
23#[derive(Clone, Debug)]
28pub struct SnsCanisters {
29 pub root: Principal,
30 pub governance: Principal,
31 pub index: Principal,
32 pub ledger: Principal,
33}
34
35#[derive(Clone, Copy, Debug)]
40pub enum SnsRole {
41 Root,
42 Governance,
43 Index,
44 Ledger,
45}
46
47#[derive(Clone, Copy, Debug)]
52#[remain::sorted]
53pub enum SnsType {
54 Alice,
55 Catalyze,
56 DecideAi,
57 Dragginz,
58 GoldDao,
59 Kinic,
60 KongSwap,
61 Mimic,
62 Motoko,
63 Neutrinite,
64 Nuance,
65 OpenChat,
66 PokedBots,
67 Sneed,
68 Swampies,
69 TacoDao,
70 Tendies,
71 Trax,
72}
73
74fn parse_required(name: &str, text: &str) -> Result<Principal, SnsError> {
77 Principal::from_text(text)
78 .map_err(|_| SnsError::InvalidPrincipal(name.to_string(), text.to_string()))
79}
80
81fn bundle(root: &str, gov: &str, idx: &str, led: &str) -> Result<SnsCanisters, SnsError> {
82 Ok(SnsCanisters {
83 root: parse_required("root", root)?,
84 governance: parse_required("governance", gov)?,
85 index: parse_required("index", idx)?,
86 ledger: parse_required("ledger", led)?,
87 })
88}
89
90macro_rules! define_sns_table {
93 (
94 $(
95 $name:ident {
96 root: $root:expr,
97 governance: $gov:expr,
98 index: $idx:expr,
99 ledger: $led:expr $(,)?
100 }
101 ),+ $(,)?
102 ) => {
103 impl SnsType {
104 pub fn principal(self, role: SnsRole) -> Result<Principal, Error> {
105 let set = self.principals()?;
106 Ok(match role {
107 SnsRole::Root => set.root,
108 SnsRole::Governance => set.governance,
109 SnsRole::Index => set.index,
110 SnsRole::Ledger => set.ledger,
111 })
112 }
113
114 pub fn principals(self) -> Result<SnsCanisters, Error> {
115 match self {
116 $(
117 Self::$name => bundle($root, $gov, $idx, $led),
118 )+
119 }
120 .map_err(EnvError::from)
121 .map_err(Error::from)
122 }
123 }
124
125 #[cfg(test)]
127 mod __sns_parse_tests {
128 use super::*;
129 #[test]
130 fn all_configured_ids_parse() {
131 $(
132 if !($root.is_empty() || $gov.is_empty() || $idx.is_empty() || $led.is_empty()) {
134 let _ = SnsType::$name.principals().expect(concat!("failed for ", stringify!($name)));
135 }
136 )+
137 }
138 }
139 }
140}
141
142define_sns_table! {
145
146 Alice {
147 root: "oh4fn-kyaaa-aaaaq-aaega-cai",
148 governance: "oa5dz-haaaa-aaaaq-aaegq-cai",
149 index: "mtcaz-pyaaa-aaaaq-aaeia-cai",
150 ledger: "oj6if-riaaa-aaaaq-aaeha-cai",
151 },
152
153 Catalyze {
154 root: "uly3p-iqaaa-aaaaq-aabma-cai",
155 governance: "umz53-fiaaa-aaaaq-aabmq-cai",
156 index: "ux4b6-7qaaa-aaaaq-aaboa-cai",
157 ledger: "uf2wh-taaaa-aaaaq-aabna-cai",
158 },
159
160 DecideAi {
161 root: "x4kx5-ziaaa-aaaaq-aabeq-cai",
162 governance: "xvj4b-paaaa-aaaaq-aabfa-cai",
163 index: "xaonm-oiaaa-aaaaq-aabgq-cai",
164 ledger: "xsi2v-cyaaa-aaaaq-aabfq-cai",
165 },
166
167 Dragginz {
168 root: "zxeu2-7aaaa-aaaaq-aaafa-cai",
169 governance: "zqfso-syaaa-aaaaq-aaafq-cai",
170 index: "zlaol-iaaaa-aaaaq-aaaha-cai",
171 ledger: "zfcdd-tqaaa-aaaaq-aaaga-cai",
172 },
173
174 GoldDao {
175 root: "tw2vt-hqaaa-aaaaq-aab6a-cai",
176 governance: "tr3th-kiaaa-aaaaq-aab6q-cai",
177 index: "efv5g-kqaaa-aaaaq-aacaa-cai",
178 ledger: "tyyy3-4aaaa-aaaaq-aab7a-cai",
179 },
180
181 Kinic {
182 root: "7jkta-eyaaa-aaaaq-aaarq-cai",
183 governance: "74ncn-fqaaa-aaaaq-aaasa-cai",
184 index: "7vojr-tyaaa-aaaaq-aaatq-cai",
185 ledger: "73mez-iiaaa-aaaaq-aaasq-cai",
186 },
187
188 KongSwap {
189 root: "ormnc-tiaaa-aaaaq-aadyq-cai",
190 governance: "oypg6-faaaa-aaaaq-aadza-cai",
191 index: "onixt-eiaaa-aaaaq-aad2q-cai",
192 ledger: "o7oak-iyaaa-aaaaq-aadzq-cai",
193 },
194
195 Mimic {
196 root: "4m6il-zqaaa-aaaaq-aaa2a-cai",
197 governance: "4l7o7-uiaaa-aaaaq-aaa2q-cai",
198 index: "ks7eq-3yaaa-aaaaq-aaddq-cai",
199 ledger: "4c4fd-caaaa-aaaaq-aaa3a-cai",
200 },
201
202 Motoko {
203 root: "ko36b-myaaa-aaaaq-aadbq-cai",
204 governance: "k34pm-nqaaa-aaaaq-aadca-cai",
205 index: "5ithz-aqaaa-aaaaq-aaa4a-cai",
206 ledger: "k45jy-aiaaa-aaaaq-aadcq-cai",
207 },
208
209 Neutrinite {
210 root: "extk7-gaaaa-aaaaq-aacda-cai",
211 governance: "eqsml-lyaaa-aaaaq-aacdq-cai",
212 index: "ft6fn-7aaaa-aaaaq-aacfa-cai",
213 ledger: "f54if-eqaaa-aaaaq-aacea-cai",
214 },
215
216 Nuance {
217 root: "rzbmc-yiaaa-aaaaq-aabsq-cai",
218 governance: "rqch6-oaaaa-aaaaq-aabta-cai",
219 index: "q5mdq-biaaa-aaaaq-aabuq-cai",
220 ledger: "rxdbk-dyaaa-aaaaq-aabtq-cai",
221 },
222
223 OpenChat {
224 root: "3e3x2-xyaaa-aaaaq-aaalq-cai",
225 governance: "2jvtu-yqaaa-aaaaq-aaama-cai",
226 index: "2awyi-oyaaa-aaaaq-aaanq-cai",
227 ledger: "2ouva-viaaa-aaaaq-aaamq-cai",
228 },
229
230 PokedBots {
231 root: "nb7he-piaaa-aaaaq-aadqq-cai",
232 governance: "ni4my-zaaaa-aaaaq-aadra-cai",
233 index: "n535v-yiaaa-aaaaq-aadsq-cai",
234 ledger: "np5km-uyaaa-aaaaq-aadrq-cai",
235 },
236
237 Sneed {
238 root: "fp274-iaaaa-aaaaq-aacha-cai",
239 governance: "fi3zi-fyaaa-aaaaq-aachq-cai",
240 index: "h3e2i-naaaa-aaaaq-aacja-cai",
241 ledger: "hvgxa-wqaaa-aaaaq-aacia-cai",
242 },
243
244 Swampies {
245 root: "l7ra6-uqaaa-aaaaq-aadea-cai",
246 governance: "lyqgk-ziaaa-aaaaq-aadeq-cai",
247 index: "ldv2p-dqaaa-aaaaq-aadga-cai",
248 ledger: "lrtnw-paaaa-aaaaq-aadfa-cai",
249 },
250
251 TacoDao {
252 root: "lacdn-3iaaa-aaaaq-aae3a-cai",
253 governance: "lhdfz-wqaaa-aaaaq-aae3q-cai",
254 index: "kepm7-ciaaa-aaaaq-aae5a-cai",
255 ledger: "kknbx-zyaaa-aaaaq-aae4a-cai",
256 },
257
258 Tendies {
259 root: "kwj3g-oyaaa-aaaaq-aae6a-cai",
260 governance: "kri5s-daaaa-aaaaq-aae6q-cai",
261 index: "bb4ce-dyaaa-aaaaq-aafaa-cai",
262 ledger: "kylwo-viaaa-aaaaq-aae7a-cai",
263 },
264
265 Trax {
266 root: "ecu3s-hiaaa-aaaaq-aacaq-cai",
267 governance: "elxqo-raaaa-aaaaq-aacba-cai",
268 index: "e6qbd-qiaaa-aaaaq-aaccq-cai",
269 ledger: "emww2-4yaaa-aaaaq-aacbq-cai",
270 },
271}