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