Skip to main content

dpp/data_contract/associated_token/token_perpetual_distribution/
mod.rs

1use crate::data_contract::associated_token::token_perpetual_distribution::v0::TokenPerpetualDistributionV0;
2use crate::errors::ProtocolError;
3#[cfg(feature = "json-conversion")]
4use crate::serialization::JsonConvertible;
5#[cfg(feature = "value-conversion")]
6use crate::serialization::ValueConvertible;
7use bincode::{Decode, Encode};
8use derive_more::From;
9use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize};
10use serde::{Deserialize, Serialize};
11use std::fmt;
12
13pub mod distribution_function;
14pub mod distribution_recipient;
15pub mod methods;
16pub mod reward_distribution_moment;
17pub mod reward_distribution_type;
18pub mod v0;
19
20#[cfg_attr(feature = "json-conversion", derive(JsonConvertible))]
21#[cfg_attr(feature = "value-conversion", derive(ValueConvertible))]
22#[derive(
23    Serialize,
24    Deserialize,
25    Encode,
26    Decode,
27    PlatformSerialize,
28    PlatformDeserialize,
29    Debug,
30    Clone,
31    PartialEq,
32    Eq,
33    PartialOrd,
34    From,
35)]
36#[serde(tag = "$formatVersion")]
37#[platform_serialize(unversioned)]
38pub enum TokenPerpetualDistribution {
39    #[serde(rename = "0")]
40    V0(TokenPerpetualDistributionV0),
41}
42
43impl fmt::Display for TokenPerpetualDistribution {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        match self {
46            TokenPerpetualDistribution::V0(v0) => {
47                write!(f, "{}", v0) //just pass through
48            }
49        }
50    }
51}
52
53#[cfg(all(
54    test,
55    feature = "json-conversion",
56    feature = "value-conversion",
57    feature = "serde-conversion"
58))]
59mod json_convertible_tests {
60    use super::*;
61    use crate::data_contract::associated_token::token_perpetual_distribution::distribution_function::DistributionFunction;
62    use crate::data_contract::associated_token::token_perpetual_distribution::distribution_recipient::TokenDistributionRecipient;
63    use crate::data_contract::associated_token::token_perpetual_distribution::reward_distribution_type::RewardDistributionType;
64    use crate::data_contract::associated_token::token_perpetual_distribution::v0::TokenPerpetualDistributionV0;
65    use platform_value::platform_value;
66    use serde_json::json;
67
68    /// Non-default values (interval=1000, amount=100, ContractOwner) so the
69    /// wire-shape assertion catches any silent zero-out / variant flip.
70    fn fixture() -> TokenPerpetualDistribution {
71        TokenPerpetualDistribution::V0(TokenPerpetualDistributionV0 {
72            distribution_type: RewardDistributionType::BlockBasedDistribution {
73                interval: 1000,
74                function: DistributionFunction::FixedAmount { amount: 100 },
75            },
76            distribution_recipient: TokenDistributionRecipient::ContractOwner,
77        })
78    }
79
80    #[test]
81    fn json_round_trip_with_full_wire_shape() {
82        use crate::serialization::JsonConvertible;
83        let original = fixture();
84        let json = original.to_json().expect("to_json");
85        // `RewardDistributionType` and `DistributionFunction` are externally
86        // tagged enums (no `#[serde(tag = "...")]`), so struct variants
87        // serialize as `{ "VariantName": { ...fields... } }`. `interval` is
88        // `u64` (BlockHeightInterval); `amount` is `u64` (TokenAmount); JSON
89        // erases the size — the value-path assertion below uses `1000u64` /
90        // `100u64` to lock in `Value::U64`.
91        assert_eq!(
92            json,
93            json!({
94                "$formatVersion": "0",
95                "distributionType": {
96                    "$type": "blockBasedDistribution",
97                    "interval": 1000,
98                    "function": { "$type": "fixedAmount", "amount": 100 },
99                },
100                "distributionRecipient": {"$type": "contractOwner"},
101            })
102        );
103        let recovered = TokenPerpetualDistribution::from_json(json).expect("from_json");
104        assert_eq!(original, recovered);
105    }
106
107    #[test]
108    fn value_round_trip_with_full_wire_shape() {
109        use crate::serialization::ValueConvertible;
110        let original = fixture();
111        let value = original.to_object().expect("to_object");
112        // `1000u64` / `100u64`: explicit suffix forces `Value::U64`, matching
113        // the `BlockHeightInterval` / `TokenAmount` aliases (both u64).
114        assert_eq!(
115            value,
116            platform_value!({
117                "$formatVersion": "0",
118                "distributionType": {
119                    "$type": "blockBasedDistribution",
120                    "interval": 1000u64,
121                    "function": { "$type": "fixedAmount", "amount": 100u64 },
122                },
123                "distributionRecipient": {"$type": "contractOwner"},
124            })
125        );
126        let recovered = TokenPerpetualDistribution::from_object(value).expect("from_object");
127        assert_eq!(original, recovered);
128    }
129}