Skip to main content

dpp/group/
mod.rs

1use crate::data_contract::group::{Group, GroupMemberPower};
2use crate::data_contract::GroupContractPosition;
3#[cfg(feature = "json-conversion")]
4use crate::serialization::json_safe_fields;
5use bincode::{Decode, Encode};
6use derive_more::Display;
7use platform_value::Identifier;
8#[cfg(feature = "serde-conversion")]
9use serde::{Deserialize, Serialize};
10
11pub mod action_event;
12pub mod action_taker;
13pub mod group_action;
14pub mod group_action_status;
15
16#[derive(Debug, Clone, Copy, Encode, Decode, PartialEq)]
17pub enum GroupStateTransitionInfoStatus {
18    GroupStateTransitionInfoProposer(GroupContractPosition),
19    GroupStateTransitionInfoOtherSigner(GroupStateTransitionInfo),
20}
21
22impl From<GroupStateTransitionInfoStatus> for GroupStateTransitionInfo {
23    fn from(value: GroupStateTransitionInfoStatus) -> Self {
24        match value {
25            GroupStateTransitionInfoStatus::GroupStateTransitionInfoProposer(
26                group_contract_position,
27            ) => GroupStateTransitionInfo {
28                group_contract_position,
29                action_id: Default::default(),
30                action_is_proposer: true,
31            },
32            GroupStateTransitionInfoStatus::GroupStateTransitionInfoOtherSigner(info) => info,
33        }
34    }
35}
36
37#[cfg_attr(feature = "json-conversion", json_safe_fields)]
38#[derive(Debug, Clone, Copy, Encode, Decode, Default, PartialEq, Display)]
39#[cfg_attr(
40    feature = "serde-conversion",
41    derive(Serialize, Deserialize),
42    serde(rename_all = "camelCase")
43)]
44#[display("ID: {}, Action ID: {}", "id", "action_id")]
45pub struct GroupStateTransitionInfo {
46    #[cfg_attr(feature = "serde-conversion", serde(rename = "$groupContractPosition"))]
47    pub group_contract_position: GroupContractPosition,
48    #[cfg_attr(feature = "serde-conversion", serde(rename = "$groupActionId"))]
49    pub action_id: Identifier,
50    /// This is true if we are the proposer, otherwise we are just voting on a previous action.
51    #[cfg_attr(feature = "serde-conversion", serde(rename = "$groupActionIsProposer"))]
52    pub action_is_proposer: bool,
53}
54
55#[cfg(all(feature = "json-conversion", feature = "serde-conversion"))]
56impl crate::serialization::JsonConvertible for GroupStateTransitionInfo {}
57
58#[cfg(all(feature = "value-conversion", feature = "serde-conversion"))]
59impl crate::serialization::ValueConvertible for GroupStateTransitionInfo {}
60
61#[derive(Debug, Clone, PartialEq)]
62pub struct GroupStateTransitionResolvedInfo {
63    pub group_contract_position: GroupContractPosition,
64    pub group: Group,
65    pub action_id: Identifier,
66    /// This is true if we are the proposer, otherwise we are just voting on a previous action.
67    pub action_is_proposer: bool,
68    pub signer_power: GroupMemberPower,
69}
70
71#[cfg(all(
72    test,
73    feature = "json-conversion",
74    feature = "value-conversion",
75    feature = "serde-conversion"
76))]
77mod json_convertible_tests_groupstatetransitioninfo {
78    use super::*;
79    use platform_value::platform_value;
80    use serde_json::json;
81
82    fn fixture() -> GroupStateTransitionInfo {
83        GroupStateTransitionInfo {
84            group_contract_position: 5,
85            action_id: Identifier::new([0x33; 32]),
86            action_is_proposer: true,
87        }
88    }
89
90    #[test]
91    fn json_round_trip_with_full_wire_shape() {
92        use crate::serialization::JsonConvertible;
93        let original = fixture();
94        let json = original.to_json().expect("to_json");
95        // Each field has an explicit `serde(rename = "$..." )` so the wire keys
96        // are `$groupContractPosition` / `$groupActionId` / `$groupActionIsProposer`.
97        // `group_contract_position` is `GroupContractPosition` (= u16), so JSON
98        // erases the size — the value-path assertion uses `5u16`.
99        // `action_id` is `Identifier` and serializes as base58 in JSON.
100        assert_eq!(
101            json,
102            json!({
103                "$groupContractPosition": 5,
104                "$groupActionId": "4Ss5JMkXAD9Z7cktFEdrqeMuT6jGMF1pVozTyPHZ6zT4",
105                "$groupActionIsProposer": true,
106            })
107        );
108        let recovered = GroupStateTransitionInfo::from_json(json).expect("from_json");
109        assert_eq!(original, recovered);
110    }
111
112    #[test]
113    fn value_round_trip_with_full_wire_shape() {
114        use crate::serialization::ValueConvertible;
115        let original = fixture();
116        let value = original.to_object().expect("to_object");
117        // `5u16` locks `Value::U16`. `Identifier` flows through as
118        // `Value::Identifier` when interpolated into `platform_value!`.
119        let action_id = Identifier::new([0x33; 32]);
120        assert_eq!(
121            value,
122            platform_value!({
123                "$groupContractPosition": 5u16,
124                "$groupActionId": action_id,
125                "$groupActionIsProposer": true,
126            })
127        );
128        let recovered = GroupStateTransitionInfo::from_object(value).expect("from_object");
129        assert_eq!(original, recovered);
130    }
131}