dpp/tokens/token_payment_info/
mod.rs1use crate::balances::credits::TokenAmount;
46use crate::data_contract::TokenContractPosition;
47use crate::tokens::gas_fees_paid_by::GasFeesPaidBy;
48use crate::tokens::token_payment_info::methods::v0::TokenPaymentInfoMethodsV0;
49use crate::tokens::token_payment_info::v0::v0_accessors::TokenPaymentInfoAccessorsV0;
50use crate::tokens::token_payment_info::v0::TokenPaymentInfoV0;
51use crate::ProtocolError;
52use bincode::{Decode, DecodeUntrusted, Encode};
53use derive_more::{Display, From};
54use platform_serialization_derive::{
55 PlatformDeserializeTrusted, PlatformDeserializeUntrusted, PlatformSerialize,
56};
57use platform_value::btreemap_extensions::BTreeValueMapHelper;
58#[cfg(feature = "value-conversion")]
59use platform_value::Error;
60use platform_value::{Identifier, Value};
61#[cfg(feature = "serde-conversion")]
62use serde::{Deserialize, Serialize};
63use std::collections::BTreeMap;
64
65pub mod methods;
66pub mod v0;
67
68#[derive(
69 Debug,
70 Clone,
71 Copy,
72 Encode,
73 Decode,
74 PlatformDeserializeTrusted,
75 PlatformDeserializeUntrusted,
76 PlatformSerialize,
77 PartialEq,
78 Display,
79 From,
80 DecodeUntrusted,
81)]
82#[cfg_attr(
83 feature = "serde-conversion",
84 derive(Serialize, Deserialize),
85 serde(tag = "$formatVersion")
86)]
87pub enum TokenPaymentInfo {
97 #[display("V0({})", "_0")]
98 #[cfg_attr(feature = "serde-conversion", serde(rename = "0"))]
99 V0(TokenPaymentInfoV0),
100}
101
102#[cfg(all(feature = "json-conversion", feature = "serde-conversion"))]
103impl crate::serialization::JsonConvertible for TokenPaymentInfo {}
104
105#[cfg(all(feature = "value-conversion", feature = "serde-conversion"))]
106impl crate::serialization::ValueConvertible for TokenPaymentInfo {}
107
108impl TokenPaymentInfoMethodsV0 for TokenPaymentInfo {}
109
110impl TokenPaymentInfoAccessorsV0 for TokenPaymentInfo {
111 fn payment_token_contract_id(&self) -> Option<Identifier> {
113 match self {
114 TokenPaymentInfo::V0(v0) => v0.payment_token_contract_id(),
115 }
116 }
117
118 fn payment_token_contract_id_ref(&self) -> &Option<Identifier> {
119 match self {
120 TokenPaymentInfo::V0(v0) => v0.payment_token_contract_id_ref(),
121 }
122 }
123
124 fn token_contract_position(&self) -> TokenContractPosition {
125 match self {
126 TokenPaymentInfo::V0(v0) => v0.token_contract_position(),
127 }
128 }
129
130 fn minimum_token_cost(&self) -> Option<TokenAmount> {
131 match self {
132 TokenPaymentInfo::V0(v0) => v0.minimum_token_cost(),
133 }
134 }
135
136 fn maximum_token_cost(&self) -> Option<TokenAmount> {
137 match self {
138 TokenPaymentInfo::V0(v0) => v0.maximum_token_cost(),
139 }
140 }
141
142 fn gas_fees_paid_by(&self) -> GasFeesPaidBy {
143 match self {
144 TokenPaymentInfo::V0(v0) => v0.gas_fees_paid_by(),
145 }
146 }
147
148 fn set_payment_token_contract_id(&mut self, id: Option<Identifier>) {
150 match self {
151 TokenPaymentInfo::V0(v0) => v0.set_payment_token_contract_id(id),
152 }
153 }
154
155 fn set_token_contract_position(&mut self, position: TokenContractPosition) {
156 match self {
157 TokenPaymentInfo::V0(v0) => v0.set_token_contract_position(position),
158 }
159 }
160
161 fn set_minimum_token_cost(&mut self, cost: Option<TokenAmount>) {
162 match self {
163 TokenPaymentInfo::V0(v0) => v0.set_minimum_token_cost(cost),
164 }
165 }
166
167 fn set_maximum_token_cost(&mut self, cost: Option<TokenAmount>) {
168 match self {
169 TokenPaymentInfo::V0(v0) => v0.set_maximum_token_cost(cost),
170 }
171 }
172
173 fn set_gas_fees_paid_by(&mut self, payer: GasFeesPaidBy) {
174 match self {
175 TokenPaymentInfo::V0(v0) => v0.set_gas_fees_paid_by(payer),
176 }
177 }
178}
179
180impl TryFrom<BTreeMap<String, Value>> for TokenPaymentInfo {
181 type Error = ProtocolError;
182
183 fn try_from(map: BTreeMap<String, Value>) -> Result<Self, Self::Error> {
184 let format_version = map.get_str("$formatVersion")?;
188 match format_version {
189 "0" => {
190 let token_payment_info: TokenPaymentInfoV0 = map.try_into()?;
191
192 Ok(token_payment_info.into())
193 }
194 version => Err(ProtocolError::UnknownVersionMismatch {
195 method: "TokenPaymentInfo::from_value".to_string(),
196 known_versions: vec![0],
197 received: version
198 .parse()
199 .map_err(|_| ProtocolError::Generic("Conversion error".to_string()))?,
200 }),
201 }
202 }
203}
204
205#[cfg(feature = "value-conversion")]
206impl TryFrom<TokenPaymentInfo> for Value {
207 type Error = Error;
208 fn try_from(value: TokenPaymentInfo) -> Result<Self, Self::Error> {
213 platform_value::to_value(value)
214 }
215}
216
217#[cfg(all(
218 test,
219 feature = "json-conversion",
220 feature = "value-conversion",
221 feature = "serde-conversion"
222))]
223mod json_convertible_tests {
224 use super::*;
225 use platform_value::platform_value;
226 use serde_json::json;
227
228 fn fixture() -> TokenPaymentInfo {
229 TokenPaymentInfo::V0(TokenPaymentInfoV0 {
230 payment_token_contract_id: Some(Identifier::new([0x99; 32])),
231 token_contract_position: 3,
232 minimum_token_cost: Some(100),
233 maximum_token_cost: Some(1_000),
234 gas_fees_paid_by: GasFeesPaidBy::ContractOwner,
235 })
236 }
237
238 #[test]
239 fn json_round_trip_with_full_wire_shape() {
240 use crate::serialization::JsonConvertible;
241 let original = fixture();
242 let json = original.to_json().expect("to_json");
243 assert_eq!(
251 json,
252 json!({
253 "$formatVersion": "0",
254 "paymentTokenContractId": "BLbDu5FZUdSfLrGejhuaWw5iMJBo3j3TVRyPv9rfJyMA",
255 "tokenContractPosition": 3,
256 "minimumTokenCost": 100,
257 "maximumTokenCost": 1_000,
258 "gasFeesPaidBy": "ContractOwner",
259 })
260 );
261 let recovered = TokenPaymentInfo::from_json(json).expect("from_json");
262 assert_eq!(original, recovered);
263 }
264
265 #[test]
266 fn value_round_trip_with_full_wire_shape() {
267 use crate::serialization::ValueConvertible;
268 let original = fixture();
269 let value = original.to_object().expect("to_object");
270 let payment_token_contract_id = Identifier::new([0x99; 32]);
273 assert_eq!(
274 value,
275 platform_value!({
276 "$formatVersion": "0",
277 "paymentTokenContractId": payment_token_contract_id,
278 "tokenContractPosition": 3u16,
279 "minimumTokenCost": 100u64,
280 "maximumTokenCost": 1_000u64,
281 "gasFeesPaidBy": "ContractOwner",
282 })
283 );
284 let recovered = TokenPaymentInfo::from_object(value).expect("from_object");
285 assert_eq!(original, recovered);
286 }
287}