Skip to main content

drive/state_transition_action/contract/data_contract_create/
mod.rs

1/// transformer
2pub mod transformer;
3/// v0
4pub mod v0;
5/// v1
6pub mod v1;
7
8use crate::state_transition_action::contract::data_contract_create::v0::DataContractCreateTransitionActionV0;
9use crate::state_transition_action::contract::data_contract_create::v1::DataContractCreateTransitionActionV1;
10use derive_more::From;
11use dpp::contract_group::{ContractGroupInfo, ContractGroupMembership};
12use dpp::data_contract::DataContract;
13use dpp::identifier::Identifier;
14use dpp::prelude::{IdentityNonce, UserFeeIncrease};
15
16/// data contract create transition action
17#[derive(Debug, Clone, From)]
18pub enum DataContractCreateTransitionAction {
19    /// v0
20    V0(DataContractCreateTransitionActionV0),
21    /// v1: adds contract groups
22    V1(DataContractCreateTransitionActionV1),
23}
24
25impl DataContractCreateTransitionAction {
26    /// data contract
27    pub fn data_contract(self) -> DataContract {
28        match self {
29            DataContractCreateTransitionAction::V0(transition) => transition.data_contract,
30            DataContractCreateTransitionAction::V1(transition) => transition.data_contract,
31        }
32    }
33    /// data contract ref
34    pub fn data_contract_ref(&self) -> &DataContract {
35        match self {
36            DataContractCreateTransitionAction::V0(transition) => &transition.data_contract,
37            DataContractCreateTransitionAction::V1(transition) => &transition.data_contract,
38        }
39    }
40
41    /// identity nonce
42    pub fn identity_nonce(&self) -> IdentityNonce {
43        match self {
44            DataContractCreateTransitionAction::V0(transition) => transition.identity_nonce,
45            DataContractCreateTransitionAction::V1(transition) => transition.identity_nonce,
46        }
47    }
48
49    /// fee multiplier
50    pub fn user_fee_increase(&self) -> UserFeeIncrease {
51        match self {
52            DataContractCreateTransitionAction::V0(transition) => transition.user_fee_increase,
53            DataContractCreateTransitionAction::V1(transition) => transition.user_fee_increase,
54        }
55    }
56
57    /// The contract group the transition registers, with its derived id, if any.
58    pub fn contract_group(&self) -> Option<&(Identifier, ContractGroupInfo)> {
59        match self {
60            DataContractCreateTransitionAction::V0(_) => None,
61            DataContractCreateTransitionAction::V1(transition) => {
62                transition.contract_group.as_ref()
63            }
64        }
65    }
66
67    /// The contract group memberships the created contract declares.
68    pub fn contract_group_memberships(&self) -> &[ContractGroupMembership] {
69        match self {
70            DataContractCreateTransitionAction::V0(_) => &[],
71            DataContractCreateTransitionAction::V1(transition) => {
72                transition.contract_group_memberships.as_slice()
73            }
74        }
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81    use dpp::data_contract::accessors::v0::DataContractV0Getters;
82    use dpp::tests::fixtures::get_data_contract_fixture;
83    use platform_version::version::PlatformVersion;
84
85    fn make_action() -> DataContractCreateTransitionAction {
86        let fixture =
87            get_data_contract_fixture(None, 0, PlatformVersion::latest().protocol_version);
88        let dc = fixture.data_contract_owned();
89        let v0 = DataContractCreateTransitionActionV0 {
90            data_contract: dc,
91            identity_nonce: 42,
92            user_fee_increase: 7,
93        };
94        DataContractCreateTransitionAction::from(v0)
95    }
96
97    /// The expected document type names produced by `get_data_contract_fixture`.
98    const EXPECTED_DOC_TYPES: [&str; 7] = [
99        "indexedDocument",
100        "niceDocument",
101        "noTimeDocument",
102        "optionalUniqueIndexedDocument",
103        "prettyDocument",
104        "uniqueDates",
105        "withByteArrays",
106    ];
107
108    #[test]
109    fn test_from_v0() {
110        let action = make_action();
111        assert!(matches!(action, DataContractCreateTransitionAction::V0(_)));
112        // Verify the fixture values are accessible through the enum wrapper.
113        assert_eq!(action.identity_nonce(), 42);
114        assert_eq!(action.user_fee_increase(), 7);
115        assert_eq!(action.data_contract_ref().version(), 1);
116    }
117
118    #[test]
119    fn test_data_contract_ref() {
120        let action = make_action();
121        let dc_ref = action.data_contract_ref();
122        // Verify the contract has the expected version and document types.
123        assert_eq!(dc_ref.version(), 1);
124        let doc_types = dc_ref.document_types();
125        assert_eq!(doc_types.len(), EXPECTED_DOC_TYPES.len());
126        for name in &EXPECTED_DOC_TYPES {
127            assert!(
128                dc_ref.has_document_type_for_name(name),
129                "expected document type '{}' not found",
130                name
131            );
132        }
133    }
134
135    #[test]
136    fn test_data_contract_owned() {
137        let action = make_action();
138        let original_id = action.data_contract_ref().id();
139        let original_owner = action.data_contract_ref().owner_id();
140        let dc = action.data_contract();
141        assert_eq!(dc.id(), original_id);
142        assert_eq!(dc.owner_id(), original_owner);
143        assert_eq!(dc.version(), 1);
144        assert_eq!(dc.document_types().len(), EXPECTED_DOC_TYPES.len());
145    }
146
147    #[test]
148    fn test_identity_nonce() {
149        let action = make_action();
150        assert_eq!(action.identity_nonce(), 42);
151    }
152
153    #[test]
154    fn test_user_fee_increase() {
155        let action = make_action();
156        assert_eq!(action.user_fee_increase(), 7);
157    }
158
159    #[test]
160    fn test_clone() {
161        let action = make_action();
162        let cloned = action.clone();
163        assert_eq!(cloned.identity_nonce(), 42);
164        assert_eq!(cloned.user_fee_increase(), 7);
165        // Verify the cloned contract preserves identity and structure.
166        assert_eq!(
167            cloned.data_contract_ref().id(),
168            action.data_contract_ref().id()
169        );
170        assert_eq!(
171            cloned.data_contract_ref().owner_id(),
172            action.data_contract_ref().owner_id()
173        );
174        assert_eq!(cloned.data_contract_ref().version(), 1);
175        assert_eq!(
176            cloned.data_contract_ref().document_types().len(),
177            EXPECTED_DOC_TYPES.len()
178        );
179    }
180
181    #[test]
182    fn test_debug() {
183        let action = make_action();
184        let debug_str = format!("{:?}", action);
185        assert!(debug_str.contains("V0"));
186    }
187}