Skip to main content

dpp/data_contract/associated_token/token_configuration_convention/
mod.rs

1use crate::data_contract::associated_token::token_configuration_convention::v0::TokenConfigurationConventionV0;
2#[cfg(feature = "json-conversion")]
3use crate::serialization::JsonConvertible;
4#[cfg(feature = "value-conversion")]
5use crate::serialization::ValueConvertible;
6use bincode::{Decode, Encode};
7use derive_more::From;
8use serde::{Deserialize, Serialize};
9use std::fmt;
10
11pub mod accessors;
12pub mod methods;
13pub mod v0;
14
15/// Versioned wrapper for token display conventions.
16///
17/// `TokenConfigurationConvention` provides a flexible, forward-compatible structure
18/// for representing human-readable metadata about a token, such as localized names
19/// and decimal formatting standards.
20///
21/// This enum enables evolution of the convention schema over time without breaking
22/// compatibility with older tokens. Each variant defines a specific format version.
23#[cfg_attr(feature = "json-conversion", derive(JsonConvertible))]
24#[derive(Serialize, Deserialize, Encode, Decode, Debug, Clone, PartialEq, Eq, PartialOrd, From)]
25#[cfg_attr(feature = "value-conversion", derive(ValueConvertible))]
26#[serde(tag = "$formatVersion")]
27pub enum TokenConfigurationConvention {
28    /// Version 0 of the token convention schema.
29    ///
30    /// Defines localized names (by ISO 639 language codes) and the number of decimal places
31    /// used for displaying token amounts.
32    #[serde(rename = "0")]
33    V0(TokenConfigurationConventionV0),
34}
35
36impl fmt::Display for TokenConfigurationConvention {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        match self {
39            TokenConfigurationConvention::V0(v0) => {
40                write!(f, "{}", v0) //just pass through
41            }
42        }
43    }
44}
45
46#[cfg(all(
47    test,
48    feature = "json-conversion",
49    feature = "value-conversion",
50    feature = "serde-conversion"
51))]
52mod json_convertible_tests {
53    use super::*;
54    use crate::data_contract::associated_token::token_configuration_convention::v0::TokenConfigurationConventionV0;
55    use crate::data_contract::associated_token::token_configuration_localization::v0::TokenConfigurationLocalizationV0;
56    use crate::data_contract::associated_token::token_configuration_localization::TokenConfigurationLocalization;
57    use std::collections::BTreeMap;
58
59    fn fixture() -> TokenConfigurationConvention {
60        let mut localizations = BTreeMap::new();
61        localizations.insert(
62            "en".to_string(),
63            TokenConfigurationLocalization::V0(TokenConfigurationLocalizationV0 {
64                should_capitalize: true,
65                singular_form: "Token".to_string(),
66                plural_form: "Tokens".to_string(),
67            }),
68        );
69        TokenConfigurationConvention::V0(TokenConfigurationConventionV0 {
70            localizations,
71            decimals: 8,
72        })
73    }
74
75    #[test]
76    fn json_round_trip_with_full_wire_shape() {
77        use crate::serialization::JsonConvertible;
78        use serde_json::json;
79        let original = fixture();
80        let json = original.to_json().expect("to_json");
81        // `decimals` is `u8`; JSON erases the size — value-path locks `8u8` below.
82        assert_eq!(
83            json,
84            json!({
85                "$formatVersion": "0",
86                "localizations": {
87                    "en": {
88                        "$formatVersion": "0",
89                        "shouldCapitalize": true,
90                        "singularForm": "Token",
91                        "pluralForm": "Tokens",
92                    }
93                },
94                "decimals": 8,
95            })
96        );
97        let recovered = TokenConfigurationConvention::from_json(json).expect("from_json");
98        assert_eq!(original, recovered);
99    }
100
101    #[test]
102    fn value_round_trip_with_full_wire_shape() {
103        use crate::serialization::ValueConvertible;
104        use platform_value::platform_value;
105        let original = fixture();
106        let value = original.to_object().expect("to_object");
107        // `decimals` is u8 → `Value::U8`.
108        assert_eq!(
109            value,
110            platform_value!({
111                "$formatVersion": "0",
112                "localizations": {
113                    "en": {
114                        "$formatVersion": "0",
115                        "shouldCapitalize": true,
116                        "singularForm": "Token",
117                        "pluralForm": "Tokens",
118                    }
119                },
120                "decimals": 8u8,
121            })
122        );
123        let recovered = TokenConfigurationConvention::from_object(value).expect("from_object");
124        assert_eq!(original, recovered);
125    }
126}