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