Skip to main content

dpp/tokens/
gas_fees_paid_by.rs

1use crate::consensus::basic::data_contract::UnknownGasFeesPaidByError;
2use crate::consensus::basic::BasicError;
3use crate::consensus::ConsensusError;
4use crate::ProtocolError;
5use bincode::{Decode, Encode};
6use derive_more::Display;
7#[cfg(feature = "serde-conversion")]
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, Copy, Encode, Decode, Default, PartialEq, Display)]
11#[cfg_attr(feature = "serde-conversion", derive(Serialize, Deserialize))]
12pub enum GasFeesPaidBy {
13    /// The user pays the gas fees
14    #[default]
15    DocumentOwner = 0,
16    /// The contract owner pays the gas fees
17    ContractOwner = 1,
18    /// The user is stating his willingness to pay the gas fee if the Contract owner's balance is
19    /// insufficient.
20    PreferContractOwner = 2,
21}
22
23#[cfg(all(feature = "json-conversion", feature = "serde-conversion"))]
24impl crate::serialization::JsonConvertible for GasFeesPaidBy {}
25
26#[cfg(all(feature = "value-conversion", feature = "serde-conversion"))]
27impl crate::serialization::ValueConvertible for GasFeesPaidBy {}
28
29impl From<GasFeesPaidBy> for u8 {
30    fn from(value: GasFeesPaidBy) -> Self {
31        match value {
32            GasFeesPaidBy::DocumentOwner => 0,
33            GasFeesPaidBy::ContractOwner => 1,
34            GasFeesPaidBy::PreferContractOwner => 2,
35        }
36    }
37}
38
39impl TryFrom<u8> for GasFeesPaidBy {
40    type Error = ProtocolError;
41
42    fn try_from(value: u8) -> Result<Self, Self::Error> {
43        match value {
44            0 => Ok(GasFeesPaidBy::DocumentOwner),
45            1 => Ok(GasFeesPaidBy::ContractOwner),
46            2 => Ok(GasFeesPaidBy::PreferContractOwner),
47            value => Err(ProtocolError::ConsensusError(
48                ConsensusError::BasicError(BasicError::UnknownGasFeesPaidByError(
49                    UnknownGasFeesPaidByError::new(vec![0, 1, 2], value as u64),
50                ))
51                .into(),
52            )),
53        }
54    }
55}
56
57impl TryFrom<u64> for GasFeesPaidBy {
58    type Error = ProtocolError;
59
60    fn try_from(value: u64) -> Result<Self, Self::Error> {
61        u8::try_from(value)
62            .map_err(|_| {
63                ProtocolError::ConsensusError(
64                    ConsensusError::BasicError(BasicError::UnknownGasFeesPaidByError(
65                        UnknownGasFeesPaidByError::new(vec![0, 1, 2], value),
66                    ))
67                    .into(),
68                )
69            })?
70            .try_into()
71    }
72}
73
74#[cfg(all(
75    test,
76    feature = "json-conversion",
77    feature = "value-conversion",
78    feature = "serde-conversion"
79))]
80mod json_convertible_tests {
81    use super::*;
82    use platform_value::platform_value;
83    use serde_json::json;
84
85    // `GasFeesPaidBy` is a unit-only enum without `rename_all`, so each variant
86    // (de)serializes as its PascalCase Rust name in both JSON and platform_value.
87
88    #[test]
89    fn json_round_trip_document_owner() {
90        use crate::serialization::JsonConvertible;
91        let original = GasFeesPaidBy::DocumentOwner;
92        let json = original.to_json().expect("to_json");
93        assert_eq!(json, json!("DocumentOwner"));
94        let recovered = GasFeesPaidBy::from_json(json).expect("from_json");
95        assert_eq!(original, recovered);
96    }
97
98    #[test]
99    fn json_round_trip_contract_owner() {
100        use crate::serialization::JsonConvertible;
101        let original = GasFeesPaidBy::ContractOwner;
102        let json = original.to_json().expect("to_json");
103        assert_eq!(json, json!("ContractOwner"));
104        let recovered = GasFeesPaidBy::from_json(json).expect("from_json");
105        assert_eq!(original, recovered);
106    }
107
108    #[test]
109    fn json_round_trip_prefer_contract_owner() {
110        use crate::serialization::JsonConvertible;
111        let original = GasFeesPaidBy::PreferContractOwner;
112        let json = original.to_json().expect("to_json");
113        assert_eq!(json, json!("PreferContractOwner"));
114        let recovered = GasFeesPaidBy::from_json(json).expect("from_json");
115        assert_eq!(original, recovered);
116    }
117
118    #[test]
119    fn value_round_trip_document_owner() {
120        use crate::serialization::ValueConvertible;
121        let original = GasFeesPaidBy::DocumentOwner;
122        let value = original.to_object().expect("to_object");
123        assert_eq!(value, platform_value!("DocumentOwner"));
124        let recovered = GasFeesPaidBy::from_object(value).expect("from_object");
125        assert_eq!(original, recovered);
126    }
127
128    #[test]
129    fn value_round_trip_contract_owner() {
130        use crate::serialization::ValueConvertible;
131        let original = GasFeesPaidBy::ContractOwner;
132        let value = original.to_object().expect("to_object");
133        assert_eq!(value, platform_value!("ContractOwner"));
134        let recovered = GasFeesPaidBy::from_object(value).expect("from_object");
135        assert_eq!(original, recovered);
136    }
137
138    #[test]
139    fn value_round_trip_prefer_contract_owner() {
140        use crate::serialization::ValueConvertible;
141        let original = GasFeesPaidBy::PreferContractOwner;
142        let value = original.to_object().expect("to_object");
143        assert_eq!(value, platform_value!("PreferContractOwner"));
144        let recovered = GasFeesPaidBy::from_object(value).expect("from_object");
145        assert_eq!(original, recovered);
146    }
147}