Skip to main content

dpp/voting/votes/resource_vote/
mod.rs

1#[cfg(feature = "json-conversion")]
2use crate::serialization::JsonConvertible;
3#[cfg(feature = "value-conversion")]
4use crate::serialization::ValueConvertible;
5use crate::voting::votes::resource_vote::v0::ResourceVoteV0;
6use crate::ProtocolError;
7use bincode::{Decode, Encode};
8use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize};
9#[cfg(feature = "serde-conversion")]
10use serde::{Deserialize, Serialize};
11
12pub mod accessors;
13pub mod v0;
14
15#[cfg_attr(
16    all(feature = "json-conversion", feature = "serde-conversion"),
17    derive(JsonConvertible)
18)]
19#[derive(Debug, Clone, Encode, Decode, PlatformSerialize, PlatformDeserialize, PartialEq)]
20#[cfg_attr(
21    feature = "serde-conversion",
22    derive(Serialize, Deserialize),
23    serde(tag = "$formatVersion")
24)]
25#[cfg_attr(feature = "value-conversion", derive(ValueConvertible))]
26#[platform_serialize(limit = 15000, unversioned)]
27pub enum ResourceVote {
28    #[cfg_attr(feature = "serde-conversion", serde(rename = "0"))]
29    V0(ResourceVoteV0),
30}
31
32impl Default for ResourceVote {
33    fn default() -> Self {
34        Self::V0(ResourceVoteV0::default())
35    }
36}
37
38#[cfg(all(
39    test,
40    feature = "json-conversion",
41    feature = "value-conversion",
42    feature = "serde-conversion"
43))]
44mod json_convertible_tests_resource_vote {
45    use super::*;
46    use crate::voting::vote_choices::resource_vote_choice::ResourceVoteChoice;
47    use crate::voting::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll;
48    use crate::voting::vote_polls::VotePoll;
49    use platform_value::{platform_value, Identifier, Value};
50    use serde_json::json;
51
52    /// Non-default values per inner field (named contract / index / values
53    /// inside the poll, plus a `TowardsIdentity` choice with non-zero
54    /// identifier) so the wire-shape assertion catches silent zero-out /
55    /// variant flip on round-trip.
56    fn fixture() -> ResourceVote {
57        ResourceVote::V0(ResourceVoteV0 {
58            vote_poll: VotePoll::ContestedDocumentResourceVotePoll(
59                ContestedDocumentResourceVotePoll {
60                    contract_id: Identifier::new([0xc1; 32]),
61                    document_type_name: "preorder".to_string(),
62                    index_name: "parentNameAndLabel".to_string(),
63                    index_values: vec![Value::Text("dash".to_string())],
64                },
65            ),
66            resource_vote_choice: ResourceVoteChoice::TowardsIdentity(Identifier::new([0xab; 32])),
67        })
68    }
69
70    #[test]
71    fn json_round_trip_with_full_wire_shape() {
72        use crate::serialization::JsonConvertible;
73        let original = fixture();
74        let json = original.to_json().expect("to_json");
75        // `VotePoll` uses internal tagging (`tag = "$type"`), so its variant
76        // body fields are flattened next to the `$type` discriminator.
77        // `ResourceVoteChoice` uses a custom Serialize/Deserialize that
78        // emits `{"$type": "towardsIdentity", "identity": <id>}` for the
79        // newtype variant. Identifiers render as base58 strings in JSON.
80        assert_eq!(
81            json,
82            json!({
83                "$formatVersion": "0",
84                "votePoll": {
85                    "$type": "contestedDocumentResourceVotePoll",
86                    "contractId": "E3M3d7sy8ZKivUGxBexL9wxE7ebqzGWFqkdeFMedCJFS",
87                    "documentTypeName": "preorder",
88                    "indexName": "parentNameAndLabel",
89                    "indexValues": ["dash"],
90                },
91                "resourceVoteChoice": {
92                    "$type": "towardsIdentity",
93                    "identity": "CZ8YUVdk7znjrUmnb5n7kgySk9yRAsQDYmyCxzfSky9t",
94                },
95            })
96        );
97        let recovered = ResourceVote::from_json(json).expect("from_json");
98        assert_eq!(original, recovered);
99    }
100
101    #[test]
102    fn value_round_trip_with_full_wire_shape() {
103        use crate::serialization::ValueConvertible;
104        let original = fixture();
105        let value = original.to_object().expect("to_object");
106        // platform_value preserves typed `Identifier` variants. Interpolate
107        // through the macro so Serialize emits `Value::Identifier`.
108        let contract_id = Identifier::new([0xc1; 32]);
109        let voter_id = Identifier::new([0xab; 32]);
110        assert_eq!(
111            value,
112            platform_value!({
113                "$formatVersion": "0",
114                "votePoll": {
115                    "$type": "contestedDocumentResourceVotePoll",
116                    "contractId": contract_id,
117                    "documentTypeName": "preorder",
118                    "indexName": "parentNameAndLabel",
119                    "indexValues": ["dash"],
120                },
121                "resourceVoteChoice": {
122                    "$type": "towardsIdentity",
123                    "identity": voter_id,
124                },
125            })
126        );
127        let recovered = ResourceVote::from_object(value).expect("from_object");
128        assert_eq!(original, recovered);
129    }
130}