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, DecodeUntrusted, 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(
25    Serialize,
26    Deserialize,
27    Encode,
28    Decode,
29    Debug,
30    Clone,
31    PartialEq,
32    Eq,
33    PartialOrd,
34    From,
35    DecodeUntrusted,
36)]
37#[cfg_attr(feature = "value-conversion", derive(ValueConvertible))]
38#[serde(tag = "$formatVersion")]
39pub enum TokenConfigurationConvention {
40    /// Version 0 of the token convention schema.
41    ///
42    /// Defines localized names (by ISO 639 language codes) and the number of decimal places
43    /// used for displaying token amounts.
44    #[serde(rename = "0")]
45    V0(TokenConfigurationConventionV0),
46}
47
48impl fmt::Display for TokenConfigurationConvention {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        match self {
51            TokenConfigurationConvention::V0(v0) => {
52                write!(f, "{}", v0) //just pass through
53            }
54        }
55    }
56}
57
58#[cfg(all(
59    test,
60    feature = "json-conversion",
61    feature = "value-conversion",
62    feature = "serde-conversion"
63))]
64mod json_convertible_tests {
65    use super::*;
66    use crate::data_contract::associated_token::token_configuration_convention::v0::TokenConfigurationConventionV0;
67    use crate::data_contract::associated_token::token_configuration_localization::v0::TokenConfigurationLocalizationV0;
68    use crate::data_contract::associated_token::token_configuration_localization::TokenConfigurationLocalization;
69    use std::collections::BTreeMap;
70
71    fn fixture() -> TokenConfigurationConvention {
72        let mut localizations = BTreeMap::new();
73        localizations.insert(
74            "en".to_string(),
75            TokenConfigurationLocalization::V0(TokenConfigurationLocalizationV0 {
76                should_capitalize: true,
77                singular_form: "Token".to_string(),
78                plural_form: "Tokens".to_string(),
79            }),
80        );
81        TokenConfigurationConvention::V0(TokenConfigurationConventionV0 {
82            localizations,
83            decimals: 8,
84        })
85    }
86
87    #[test]
88    fn json_round_trip_with_full_wire_shape() {
89        use crate::serialization::JsonConvertible;
90        use serde_json::json;
91        let original = fixture();
92        let json = original.to_json().expect("to_json");
93        // `decimals` is `u8`; JSON erases the size — value-path locks `8u8` below.
94        assert_eq!(
95            json,
96            json!({
97                "$formatVersion": "0",
98                "localizations": {
99                    "en": {
100                        "$formatVersion": "0",
101                        "shouldCapitalize": true,
102                        "singularForm": "Token",
103                        "pluralForm": "Tokens",
104                    }
105                },
106                "decimals": 8,
107            })
108        );
109        let recovered = TokenConfigurationConvention::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        use platform_value::platform_value;
117        let original = fixture();
118        let value = original.to_object().expect("to_object");
119        // `decimals` is u8 → `Value::U8`.
120        assert_eq!(
121            value,
122            platform_value!({
123                "$formatVersion": "0",
124                "localizations": {
125                    "en": {
126                        "$formatVersion": "0",
127                        "shouldCapitalize": true,
128                        "singularForm": "Token",
129                        "pluralForm": "Tokens",
130                    }
131                },
132                "decimals": 8u8,
133            })
134        );
135        let recovered = TokenConfigurationConvention::from_object(value).expect("from_object");
136        assert_eq!(original, recovered);
137    }
138}