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