1use serde::{Deserialize, Serialize};
8
9pub(in crate::nns) const NNS_PROPOSAL_SORT_API_LABEL: &str = "api";
10pub(in crate::nns) const NNS_PROPOSAL_SORT_ID_LABEL: &str = "id";
11pub(in crate::nns) const NNS_PROPOSAL_SORT_STATUS_LABEL: &str = "status";
12pub(in crate::nns) const NNS_PROPOSAL_SORT_REWARD_STATUS_LABEL: &str = "reward-status";
13pub(in crate::nns) const NNS_PROPOSAL_SORT_TOPIC_LABEL: &str = "topic";
14pub(in crate::nns) const NNS_PROPOSAL_SORT_PROPOSER_LABEL: &str = "proposer";
15pub(in crate::nns) const NNS_PROPOSAL_SORT_TITLE_LABEL: &str = "title";
16pub(in crate::nns) const NNS_PROPOSAL_SORT_ACTION_LABEL: &str = "action";
17pub(in crate::nns) const NNS_PROPOSAL_SORT_YES_LABEL: &str = "yes";
18pub(in crate::nns) const NNS_PROPOSAL_SORT_NO_LABEL: &str = "no";
19pub(in crate::nns) const NNS_PROPOSAL_SORT_TOTAL_VOTES_LABEL: &str = "total-votes";
20pub(in crate::nns) const NNS_PROPOSAL_SORT_TALLY_TIME_LABEL: &str = "tally-time";
21pub(in crate::nns) const NNS_PROPOSAL_SORT_VOTING_POWER_LABEL: &str = "voting-power";
22pub(in crate::nns) const NNS_PROPOSAL_SORT_BALLOTS_LABEL: &str = "ballots";
23pub(in crate::nns) const NNS_PROPOSAL_SORT_REJECT_COST_LABEL: &str = "reject-cost";
24pub(in crate::nns) const NNS_PROPOSAL_SORT_REWARD_ROUND_LABEL: &str = "reward-round";
25pub(in crate::nns) const NNS_PROPOSAL_SORT_PROPOSED_LABEL: &str = "proposed";
26pub(in crate::nns) const NNS_PROPOSAL_SORT_DEADLINE_LABEL: &str = "deadline";
27pub(in crate::nns) const NNS_PROPOSAL_SORT_DECIDED_LABEL: &str = "decided";
28pub(in crate::nns) const NNS_PROPOSAL_SORT_EXECUTED_LABEL: &str = "executed";
29pub(in crate::nns) const NNS_PROPOSAL_SORT_FAILED_LABEL: &str = "failed";
30pub(in crate::nns) const NNS_PROPOSAL_SORT_ASC_LABEL: &str = "asc";
31pub(in crate::nns) const NNS_PROPOSAL_SORT_DESC_LABEL: &str = "desc";
32pub(in crate::nns) const NNS_PROPOSAL_SORT_NONE_LABEL: &str = "none";
33
34#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
41#[serde(rename_all = "kebab-case")]
42pub enum NnsProposalStatus {
43 Unspecified,
45 Open,
47 Rejected,
49 Adopted,
51 Executed,
53 Failed,
55}
56
57impl NnsProposalStatus {
58 #[must_use]
60 pub const fn from_code(code: i32) -> Self {
61 match code {
62 1 => Self::Open,
63 2 => Self::Rejected,
64 3 => Self::Adopted,
65 4 => Self::Executed,
66 5 => Self::Failed,
67 _ => Self::Unspecified,
68 }
69 }
70
71 #[must_use]
73 pub const fn code(self) -> i32 {
74 match self {
75 Self::Unspecified => 0,
76 Self::Open => 1,
77 Self::Rejected => 2,
78 Self::Adopted => 3,
79 Self::Executed => 4,
80 Self::Failed => 5,
81 }
82 }
83
84 #[must_use]
86 pub const fn as_str(self) -> &'static str {
87 match self {
88 Self::Unspecified => "unspecified",
89 Self::Open => "open",
90 Self::Rejected => "rejected",
91 Self::Adopted => "adopted",
92 Self::Executed => "executed",
93 Self::Failed => "failed",
94 }
95 }
96}
97
98#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
105#[serde(rename_all = "kebab-case")]
106pub enum NnsProposalRewardStatus {
107 Unspecified,
109 AcceptVotes,
111 ReadyToSettle,
113 Settled,
115 Ineligible,
117}
118
119impl NnsProposalRewardStatus {
120 #[must_use]
122 pub const fn from_code(code: i32) -> Self {
123 match code {
124 1 => Self::AcceptVotes,
125 2 => Self::ReadyToSettle,
126 3 => Self::Settled,
127 4 => Self::Ineligible,
128 _ => Self::Unspecified,
129 }
130 }
131
132 #[must_use]
134 pub const fn code(self) -> i32 {
135 match self {
136 Self::Unspecified => 0,
137 Self::AcceptVotes => 1,
138 Self::ReadyToSettle => 2,
139 Self::Settled => 3,
140 Self::Ineligible => 4,
141 }
142 }
143
144 #[must_use]
146 pub const fn as_str(self) -> &'static str {
147 match self {
148 Self::Unspecified => "unspecified",
149 Self::AcceptVotes => "accept-votes",
150 Self::ReadyToSettle => "ready-to-settle",
151 Self::Settled => "settled",
152 Self::Ineligible => "ineligible",
153 }
154 }
155}
156
157#[cfg(feature = "host")]
158pub(in crate::nns) const NNS_PROPOSAL_VOTE_UNSPECIFIED_LABEL: &str = "unspecified";
159#[cfg(feature = "host")]
160pub(in crate::nns) const NNS_PROPOSAL_VOTE_YES_LABEL: &str = "yes";
161#[cfg(feature = "host")]
162pub(in crate::nns) const NNS_PROPOSAL_VOTE_NO_LABEL: &str = "no";
163#[cfg(feature = "host")]
164pub(in crate::nns) const NNS_PROPOSAL_VOTE_YES_CODE: i32 = 1;
165#[cfg(feature = "host")]
166pub(in crate::nns) const NNS_PROPOSAL_VOTE_NO_CODE: i32 = 2;
167
168pub(in crate::nns) const NNS_PROPOSAL_TOPIC_ANY_LABEL: &str = "any";
169pub(in crate::nns) const NNS_PROPOSAL_TOPIC_NEURON_MANAGEMENT_LABEL: &str = "neuron-management";
170pub(in crate::nns) const NNS_PROPOSAL_TOPIC_EXCHANGE_RATE_LABEL: &str = "exchange-rate";
171pub(in crate::nns) const NNS_PROPOSAL_TOPIC_NETWORK_ECONOMICS_LABEL: &str = "network-economics";
172pub(in crate::nns) const NNS_PROPOSAL_TOPIC_GOVERNANCE_LABEL: &str = "governance";
173pub(in crate::nns) const NNS_PROPOSAL_TOPIC_NODE_ADMIN_LABEL: &str = "node-admin";
174pub(in crate::nns) const NNS_PROPOSAL_TOPIC_PARTICIPANT_MANAGEMENT_LABEL: &str =
175 "participant-management";
176pub(in crate::nns) const NNS_PROPOSAL_TOPIC_SUBNET_MANAGEMENT_LABEL: &str = "subnet-management";
177pub(in crate::nns) const NNS_PROPOSAL_TOPIC_NETWORK_CANISTER_MANAGEMENT_LABEL: &str =
178 "network-canister-management";
179pub(in crate::nns) const NNS_PROPOSAL_TOPIC_KYC_LABEL: &str = "kyc";
180pub(in crate::nns) const NNS_PROPOSAL_TOPIC_NODE_PROVIDER_REWARDS_LABEL: &str =
181 "node-provider-rewards";
182pub(in crate::nns) const NNS_PROPOSAL_TOPIC_IC_OS_VERSION_DEPLOYMENT_LABEL: &str =
183 "ic-os-version-deployment";
184pub(in crate::nns) const NNS_PROPOSAL_TOPIC_IC_OS_VERSION_ELECTION_LABEL: &str =
185 "ic-os-version-election";
186pub(in crate::nns) const NNS_PROPOSAL_TOPIC_SNS_AND_COMMUNITY_FUND_LABEL: &str =
187 "sns-and-community-fund";
188pub(in crate::nns) const NNS_PROPOSAL_TOPIC_API_BOUNDARY_NODE_MANAGEMENT_LABEL: &str =
189 "api-boundary-node-management";
190pub(in crate::nns) const NNS_PROPOSAL_TOPIC_SUBNET_RENTAL_LABEL: &str = "subnet-rental";
191pub(in crate::nns) const NNS_PROPOSAL_TOPIC_APPLICATION_CANISTER_MANAGEMENT_LABEL: &str =
192 "application-canister-management";
193pub(in crate::nns) const NNS_PROPOSAL_TOPIC_PROTOCOL_CANISTER_MANAGEMENT_LABEL: &str =
194 "protocol-canister-management";
195#[cfg(feature = "host")]
196pub(in crate::nns) const NNS_PROPOSAL_TOPIC_UNSPECIFIED_LABEL: &str = "unspecified";
197#[cfg(feature = "host")]
198pub(in crate::nns) const NNS_PROPOSAL_TOPIC_NEURON_MANAGEMENT_CODE: i32 = 1;
199#[cfg(feature = "host")]
200pub(in crate::nns) const NNS_PROPOSAL_TOPIC_EXCHANGE_RATE_CODE: i32 = 2;
201#[cfg(feature = "host")]
202pub(in crate::nns) const NNS_PROPOSAL_TOPIC_NETWORK_ECONOMICS_CODE: i32 = 3;
203#[cfg(feature = "host")]
204pub(in crate::nns) const NNS_PROPOSAL_TOPIC_GOVERNANCE_CODE: i32 = 4;
205#[cfg(feature = "host")]
206pub(in crate::nns) const NNS_PROPOSAL_TOPIC_NODE_ADMIN_CODE: i32 = 5;
207#[cfg(feature = "host")]
208pub(in crate::nns) const NNS_PROPOSAL_TOPIC_PARTICIPANT_MANAGEMENT_CODE: i32 = 6;
209#[cfg(feature = "host")]
210pub(in crate::nns) const NNS_PROPOSAL_TOPIC_SUBNET_MANAGEMENT_CODE: i32 = 7;
211#[cfg(feature = "host")]
212pub(in crate::nns) const NNS_PROPOSAL_TOPIC_NETWORK_CANISTER_MANAGEMENT_CODE: i32 = 8;
213#[cfg(feature = "host")]
214pub(in crate::nns) const NNS_PROPOSAL_TOPIC_KYC_CODE: i32 = 9;
215#[cfg(feature = "host")]
216pub(in crate::nns) const NNS_PROPOSAL_TOPIC_NODE_PROVIDER_REWARDS_CODE: i32 = 10;
217#[cfg(feature = "host")]
218pub(in crate::nns) const NNS_PROPOSAL_TOPIC_IC_OS_VERSION_DEPLOYMENT_CODE: i32 = 12;
219#[cfg(feature = "host")]
220pub(in crate::nns) const NNS_PROPOSAL_TOPIC_IC_OS_VERSION_ELECTION_CODE: i32 = 13;
221#[cfg(feature = "host")]
222pub(in crate::nns) const NNS_PROPOSAL_TOPIC_SNS_AND_COMMUNITY_FUND_CODE: i32 = 14;
223#[cfg(feature = "host")]
224pub(in crate::nns) const NNS_PROPOSAL_TOPIC_API_BOUNDARY_NODE_MANAGEMENT_CODE: i32 = 15;
225#[cfg(feature = "host")]
226pub(in crate::nns) const NNS_PROPOSAL_TOPIC_SUBNET_RENTAL_CODE: i32 = 16;
227#[cfg(feature = "host")]
228pub(in crate::nns) const NNS_PROPOSAL_TOPIC_APPLICATION_CANISTER_MANAGEMENT_CODE: i32 = 17;
229#[cfg(feature = "host")]
230pub(in crate::nns) const NNS_PROPOSAL_TOPIC_PROTOCOL_CANISTER_MANAGEMENT_CODE: i32 = 18;
231
232#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
239pub enum NnsProposalListSort {
240 #[default]
241 Api,
242 Id,
243 Status,
244 RewardStatus,
245 Topic,
246 Proposer,
247 Title,
248 Action,
249 Yes,
250 No,
251 TotalVotes,
252 TallyTime,
253 VotingPower,
254 Ballots,
255 RejectCost,
256 RewardRound,
257 Proposed,
258 Deadline,
259 Decided,
260 Executed,
261 Failed,
262}
263
264impl NnsProposalListSort {
265 #[must_use]
266 pub const fn as_str(self) -> &'static str {
267 match self {
268 Self::Api => NNS_PROPOSAL_SORT_API_LABEL,
269 Self::Id => NNS_PROPOSAL_SORT_ID_LABEL,
270 Self::Status => NNS_PROPOSAL_SORT_STATUS_LABEL,
271 Self::RewardStatus => NNS_PROPOSAL_SORT_REWARD_STATUS_LABEL,
272 Self::Topic => NNS_PROPOSAL_SORT_TOPIC_LABEL,
273 Self::Proposer => NNS_PROPOSAL_SORT_PROPOSER_LABEL,
274 Self::Title => NNS_PROPOSAL_SORT_TITLE_LABEL,
275 Self::Action => NNS_PROPOSAL_SORT_ACTION_LABEL,
276 Self::Yes => NNS_PROPOSAL_SORT_YES_LABEL,
277 Self::No => NNS_PROPOSAL_SORT_NO_LABEL,
278 Self::TotalVotes => NNS_PROPOSAL_SORT_TOTAL_VOTES_LABEL,
279 Self::TallyTime => NNS_PROPOSAL_SORT_TALLY_TIME_LABEL,
280 Self::VotingPower => NNS_PROPOSAL_SORT_VOTING_POWER_LABEL,
281 Self::Ballots => NNS_PROPOSAL_SORT_BALLOTS_LABEL,
282 Self::RejectCost => NNS_PROPOSAL_SORT_REJECT_COST_LABEL,
283 Self::RewardRound => NNS_PROPOSAL_SORT_REWARD_ROUND_LABEL,
284 Self::Proposed => NNS_PROPOSAL_SORT_PROPOSED_LABEL,
285 Self::Deadline => NNS_PROPOSAL_SORT_DEADLINE_LABEL,
286 Self::Decided => NNS_PROPOSAL_SORT_DECIDED_LABEL,
287 Self::Executed => NNS_PROPOSAL_SORT_EXECUTED_LABEL,
288 Self::Failed => NNS_PROPOSAL_SORT_FAILED_LABEL,
289 }
290 }
291
292 #[must_use]
293 pub const fn default_direction(self) -> NnsProposalSortDirection {
294 match self {
295 Self::Status
296 | Self::RewardStatus
297 | Self::Topic
298 | Self::Proposer
299 | Self::Title
300 | Self::Action => NnsProposalSortDirection::Asc,
301 _ => NnsProposalSortDirection::Desc,
302 }
303 }
304
305 #[must_use]
306 pub const fn uses_local_direction(self) -> bool {
307 !matches!(self, Self::Api)
308 }
309
310 #[must_use]
311 pub const fn direction_label(self, direction: NnsProposalSortDirection) -> &'static str {
312 match self {
313 Self::Api => NNS_PROPOSAL_SORT_NONE_LABEL,
314 _ => direction.as_str(),
315 }
316 }
317}
318
319#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
326pub enum NnsProposalSortDirection {
327 Asc,
328 #[default]
329 Desc,
330}
331
332impl NnsProposalSortDirection {
333 #[must_use]
334 pub const fn as_str(self) -> &'static str {
335 match self {
336 Self::Asc => NNS_PROPOSAL_SORT_ASC_LABEL,
337 Self::Desc => NNS_PROPOSAL_SORT_DESC_LABEL,
338 }
339 }
340}
341
342#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
349pub enum NnsProposalStatusFilter {
350 #[default]
351 Any,
352 Open,
353 Rejected,
354 Adopted,
355 Executed,
356 Failed,
357}
358
359#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
366pub enum NnsProposalRewardStatusFilter {
367 #[default]
368 Any,
369 AcceptVotes,
370 ReadyToSettle,
371 Settled,
372 Ineligible,
373}
374
375impl NnsProposalRewardStatusFilter {
376 #[must_use]
377 pub const fn as_str(self) -> &'static str {
378 match self {
379 Self::Any => "any",
380 Self::AcceptVotes => NnsProposalRewardStatus::AcceptVotes.as_str(),
381 Self::ReadyToSettle => NnsProposalRewardStatus::ReadyToSettle.as_str(),
382 Self::Settled => NnsProposalRewardStatus::Settled.as_str(),
383 Self::Ineligible => NnsProposalRewardStatus::Ineligible.as_str(),
384 }
385 }
386
387 #[cfg(feature = "host")]
388 pub(in crate::nns) const fn governance_reward_status_code(self) -> Option<i32> {
389 match self {
390 Self::Any => None,
391 Self::AcceptVotes => Some(NnsProposalRewardStatus::AcceptVotes.code()),
392 Self::ReadyToSettle => Some(NnsProposalRewardStatus::ReadyToSettle.code()),
393 Self::Settled => Some(NnsProposalRewardStatus::Settled.code()),
394 Self::Ineligible => Some(NnsProposalRewardStatus::Ineligible.code()),
395 }
396 }
397}
398
399impl NnsProposalStatusFilter {
400 #[must_use]
401 pub const fn as_str(self) -> &'static str {
402 match self {
403 Self::Any => "any",
404 Self::Open => NnsProposalStatus::Open.as_str(),
405 Self::Rejected => NnsProposalStatus::Rejected.as_str(),
406 Self::Adopted => NnsProposalStatus::Adopted.as_str(),
407 Self::Executed => NnsProposalStatus::Executed.as_str(),
408 Self::Failed => NnsProposalStatus::Failed.as_str(),
409 }
410 }
411
412 #[cfg(feature = "host")]
413 pub(in crate::nns) const fn governance_status_code(self) -> Option<i32> {
414 match self {
415 Self::Any => None,
416 Self::Open => Some(NnsProposalStatus::Open.code()),
417 Self::Rejected => Some(NnsProposalStatus::Rejected.code()),
418 Self::Adopted => Some(NnsProposalStatus::Adopted.code()),
419 Self::Executed => Some(NnsProposalStatus::Executed.code()),
420 Self::Failed => Some(NnsProposalStatus::Failed.code()),
421 }
422 }
423}
424
425#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
432pub enum NnsProposalTopicFilter {
433 #[default]
434 Any,
435 NeuronManagement,
436 ExchangeRate,
437 NetworkEconomics,
438 Governance,
439 NodeAdmin,
440 ParticipantManagement,
441 SubnetManagement,
442 NetworkCanisterManagement,
443 Kyc,
444 NodeProviderRewards,
445 IcOsVersionDeployment,
446 IcOsVersionElection,
447 SnsAndCommunityFund,
448 ApiBoundaryNodeManagement,
449 SubnetRental,
450 ApplicationCanisterManagement,
451 ProtocolCanisterManagement,
452}
453
454impl NnsProposalTopicFilter {
455 #[must_use]
456 pub const fn as_str(self) -> &'static str {
457 match self {
458 Self::Any => NNS_PROPOSAL_TOPIC_ANY_LABEL,
459 Self::NeuronManagement => NNS_PROPOSAL_TOPIC_NEURON_MANAGEMENT_LABEL,
460 Self::ExchangeRate => NNS_PROPOSAL_TOPIC_EXCHANGE_RATE_LABEL,
461 Self::NetworkEconomics => NNS_PROPOSAL_TOPIC_NETWORK_ECONOMICS_LABEL,
462 Self::Governance => NNS_PROPOSAL_TOPIC_GOVERNANCE_LABEL,
463 Self::NodeAdmin => NNS_PROPOSAL_TOPIC_NODE_ADMIN_LABEL,
464 Self::ParticipantManagement => NNS_PROPOSAL_TOPIC_PARTICIPANT_MANAGEMENT_LABEL,
465 Self::SubnetManagement => NNS_PROPOSAL_TOPIC_SUBNET_MANAGEMENT_LABEL,
466 Self::NetworkCanisterManagement => NNS_PROPOSAL_TOPIC_NETWORK_CANISTER_MANAGEMENT_LABEL,
467 Self::Kyc => NNS_PROPOSAL_TOPIC_KYC_LABEL,
468 Self::NodeProviderRewards => NNS_PROPOSAL_TOPIC_NODE_PROVIDER_REWARDS_LABEL,
469 Self::IcOsVersionDeployment => NNS_PROPOSAL_TOPIC_IC_OS_VERSION_DEPLOYMENT_LABEL,
470 Self::IcOsVersionElection => NNS_PROPOSAL_TOPIC_IC_OS_VERSION_ELECTION_LABEL,
471 Self::SnsAndCommunityFund => NNS_PROPOSAL_TOPIC_SNS_AND_COMMUNITY_FUND_LABEL,
472 Self::ApiBoundaryNodeManagement => {
473 NNS_PROPOSAL_TOPIC_API_BOUNDARY_NODE_MANAGEMENT_LABEL
474 }
475 Self::SubnetRental => NNS_PROPOSAL_TOPIC_SUBNET_RENTAL_LABEL,
476 Self::ApplicationCanisterManagement => {
477 NNS_PROPOSAL_TOPIC_APPLICATION_CANISTER_MANAGEMENT_LABEL
478 }
479 Self::ProtocolCanisterManagement => {
480 NNS_PROPOSAL_TOPIC_PROTOCOL_CANISTER_MANAGEMENT_LABEL
481 }
482 }
483 }
484
485 #[cfg(feature = "host")]
486 pub(in crate::nns) const fn topic_code(self) -> Option<i32> {
487 match self {
488 Self::Any => None,
489 Self::NeuronManagement => Some(NNS_PROPOSAL_TOPIC_NEURON_MANAGEMENT_CODE),
490 Self::ExchangeRate => Some(NNS_PROPOSAL_TOPIC_EXCHANGE_RATE_CODE),
491 Self::NetworkEconomics => Some(NNS_PROPOSAL_TOPIC_NETWORK_ECONOMICS_CODE),
492 Self::Governance => Some(NNS_PROPOSAL_TOPIC_GOVERNANCE_CODE),
493 Self::NodeAdmin => Some(NNS_PROPOSAL_TOPIC_NODE_ADMIN_CODE),
494 Self::ParticipantManagement => Some(NNS_PROPOSAL_TOPIC_PARTICIPANT_MANAGEMENT_CODE),
495 Self::SubnetManagement => Some(NNS_PROPOSAL_TOPIC_SUBNET_MANAGEMENT_CODE),
496 Self::NetworkCanisterManagement => {
497 Some(NNS_PROPOSAL_TOPIC_NETWORK_CANISTER_MANAGEMENT_CODE)
498 }
499 Self::Kyc => Some(NNS_PROPOSAL_TOPIC_KYC_CODE),
500 Self::NodeProviderRewards => Some(NNS_PROPOSAL_TOPIC_NODE_PROVIDER_REWARDS_CODE),
501 Self::IcOsVersionDeployment => Some(NNS_PROPOSAL_TOPIC_IC_OS_VERSION_DEPLOYMENT_CODE),
502 Self::IcOsVersionElection => Some(NNS_PROPOSAL_TOPIC_IC_OS_VERSION_ELECTION_CODE),
503 Self::SnsAndCommunityFund => Some(NNS_PROPOSAL_TOPIC_SNS_AND_COMMUNITY_FUND_CODE),
504 Self::ApiBoundaryNodeManagement => {
505 Some(NNS_PROPOSAL_TOPIC_API_BOUNDARY_NODE_MANAGEMENT_CODE)
506 }
507 Self::SubnetRental => Some(NNS_PROPOSAL_TOPIC_SUBNET_RENTAL_CODE),
508 Self::ApplicationCanisterManagement => {
509 Some(NNS_PROPOSAL_TOPIC_APPLICATION_CANISTER_MANAGEMENT_CODE)
510 }
511 Self::ProtocolCanisterManagement => {
512 Some(NNS_PROPOSAL_TOPIC_PROTOCOL_CANISTER_MANAGEMENT_CODE)
513 }
514 }
515 }
516}
517
518#[cfg(test)]
519mod tests {
520 use super::*;
521
522 #[test]
523 fn proposal_status_codes_and_labels_round_trip() {
524 for (status, code, label) in [
525 (NnsProposalStatus::Unspecified, 0, "unspecified"),
526 (NnsProposalStatus::Open, 1, "open"),
527 (NnsProposalStatus::Rejected, 2, "rejected"),
528 (NnsProposalStatus::Adopted, 3, "adopted"),
529 (NnsProposalStatus::Executed, 4, "executed"),
530 (NnsProposalStatus::Failed, 5, "failed"),
531 ] {
532 assert_eq!(status.code(), code);
533 assert_eq!(NnsProposalStatus::from_code(code), status);
534 assert_json_label(status, label);
535 }
536 assert_eq!(
537 NnsProposalStatus::from_code(99),
538 NnsProposalStatus::Unspecified
539 );
540 }
541
542 #[test]
543 fn proposal_reward_status_codes_and_labels_round_trip() {
544 for (status, code, label) in [
545 (NnsProposalRewardStatus::Unspecified, 0, "unspecified"),
546 (NnsProposalRewardStatus::AcceptVotes, 1, "accept-votes"),
547 (NnsProposalRewardStatus::ReadyToSettle, 2, "ready-to-settle"),
548 (NnsProposalRewardStatus::Settled, 3, "settled"),
549 (NnsProposalRewardStatus::Ineligible, 4, "ineligible"),
550 ] {
551 assert_eq!(status.code(), code);
552 assert_eq!(NnsProposalRewardStatus::from_code(code), status);
553 assert_json_label(status, label);
554 }
555 assert_eq!(
556 NnsProposalRewardStatus::from_code(99),
557 NnsProposalRewardStatus::Unspecified
558 );
559 }
560
561 fn assert_json_label<T>(value: T, label: &str)
562 where
563 T: Copy + std::fmt::Debug + Eq + Serialize + serde::de::DeserializeOwned,
564 {
565 assert_eq!(
566 serde_json::to_string(&value).unwrap(),
567 format!("\"{label}\"")
568 );
569 assert_eq!(
570 serde_json::from_str::<T>(&format!("\"{label}\"")).unwrap(),
571 value
572 );
573 }
574}