Skip to main content

dpp/data_contract/associated_token/token_distribution_rules/
mod.rs

1#[cfg(feature = "json-conversion")]
2use crate::serialization::JsonConvertible;
3#[cfg(feature = "value-conversion")]
4use crate::serialization::ValueConvertible;
5use bincode::{Decode, Encode};
6use derive_more::From;
7use serde::{Deserialize, Serialize};
8
9pub mod accessors;
10pub mod v0;
11
12#[cfg_attr(feature = "json-conversion", derive(JsonConvertible))]
13#[cfg_attr(feature = "value-conversion", derive(ValueConvertible))]
14#[derive(Serialize, Deserialize, Encode, Decode, Debug, Clone, PartialEq, Eq, From)]
15#[serde(tag = "$formatVersion")]
16pub enum TokenDistributionRules {
17    #[serde(rename = "0")]
18    V0(TokenDistributionRulesV0),
19}
20
21use crate::data_contract::associated_token::token_distribution_rules::v0::TokenDistributionRulesV0;
22use std::fmt;
23
24impl fmt::Display for TokenDistributionRules {
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        match self {
27            TokenDistributionRules::V0(v0) => {
28                write!(f, "{}", v0) //just pass through
29            }
30        }
31    }
32}
33
34#[cfg(all(
35    test,
36    feature = "json-conversion",
37    feature = "value-conversion",
38    feature = "serde-conversion"
39))]
40mod json_convertible_tests {
41    use super::*;
42    use crate::data_contract::associated_token::token_distribution_rules::v0::TokenDistributionRulesV0;
43    use crate::data_contract::change_control_rules::v0::ChangeControlRulesV0;
44    use crate::data_contract::change_control_rules::ChangeControlRules;
45    use platform_value::{platform_value, Identifier, Value};
46    use serde_json::json;
47
48    /// Non-default values per inner field (set destination_identity to a
49    /// specific identifier and `minting_allow_choosing_destination` to true)
50    /// so the wire-shape assertion catches silent zero-out / flip on round-trip.
51    fn fixture() -> TokenDistributionRules {
52        let ccr = || ChangeControlRules::V0(ChangeControlRulesV0::default());
53        TokenDistributionRules::V0(TokenDistributionRulesV0 {
54            perpetual_distribution: None,
55            perpetual_distribution_rules: ccr(),
56            pre_programmed_distribution: None,
57            new_tokens_destination_identity: Some(Identifier::new([0x42; 32])),
58            new_tokens_destination_identity_rules: ccr(),
59            minting_allow_choosing_destination: true,
60            minting_allow_choosing_destination_rules: ccr(),
61            change_direct_purchase_pricing_rules: ccr(),
62        })
63    }
64
65    fn default_ccr_json() -> serde_json::Value {
66        json!({
67            "$formatVersion": "0",
68            "authorizedToMakeChange": {"$type": "noOne"},
69            "adminActionTakers": {"$type": "noOne"},
70            "changingAuthorizedActionTakersToNoOneAllowed": false,
71            "changingAdminActionTakersToNoOneAllowed": false,
72            "selfChangingAdminActionTakersAllowed": false,
73        })
74    }
75
76    fn default_ccr_value() -> Value {
77        platform_value!({
78            "$formatVersion": "0",
79            "authorizedToMakeChange": {"$type": "noOne"},
80            "adminActionTakers": {"$type": "noOne"},
81            "changingAuthorizedActionTakersToNoOneAllowed": false,
82            "changingAdminActionTakersToNoOneAllowed": false,
83            "selfChangingAdminActionTakersAllowed": false,
84        })
85    }
86
87    #[test]
88    fn json_round_trip_with_full_wire_shape() {
89        use crate::serialization::JsonConvertible;
90        let original = fixture();
91        let json = original.to_json().expect("to_json");
92        // `Identifier` renders as base58 string in JSON. None Options become
93        // `null`. Inner `ChangeControlRules` round-trips its own envelope.
94        // No sized integers in this fixture.
95        assert_eq!(
96            json,
97            json!({
98                "$formatVersion": "0",
99                "perpetualDistribution": null,
100                "perpetualDistributionRules": default_ccr_json(),
101                "preProgrammedDistribution": null,
102                "newTokensDestinationIdentity": "5TeWSsjg2gbxCyWVniXeCmwM7UtHTCK7svzJr5xYJzHf",
103                "newTokensDestinationIdentityRules": default_ccr_json(),
104                "mintingAllowChoosingDestination": true,
105                "mintingAllowChoosingDestinationRules": default_ccr_json(),
106                "changeDirectPurchasePricingRules": default_ccr_json(),
107            })
108        );
109        let recovered = TokenDistributionRules::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        // `Identifier`'s Serialize emits `Value::Identifier`; interpolating the
119        // Identifier through `platform_value!{...}` runs Serialize and produces
120        // the typed variant. None becomes `Value::Null`.
121        let id = Identifier::new([0x42; 32]);
122        assert_eq!(
123            value,
124            platform_value!({
125                "$formatVersion": "0",
126                "perpetualDistribution": Value::Null,
127                "perpetualDistributionRules": default_ccr_value(),
128                "preProgrammedDistribution": Value::Null,
129                "newTokensDestinationIdentity": id,
130                "newTokensDestinationIdentityRules": default_ccr_value(),
131                "mintingAllowChoosingDestination": true,
132                "mintingAllowChoosingDestinationRules": default_ccr_value(),
133                "changeDirectPurchasePricingRules": default_ccr_value(),
134            })
135        );
136        let recovered = TokenDistributionRules::from_object(value).expect("from_object");
137        assert_eq!(original, recovered);
138    }
139}