pallet_transaction_payment/
types.rs1use codec::{Decode, Encode};
21#[cfg(feature = "std")]
22use serde::{Deserialize, Serialize};
23
24use scale_info::TypeInfo;
25
26use sp_runtime::traits::{AtLeast32BitUnsigned, Zero};
27
28use frame_support::dispatch::DispatchClass;
29
30#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
32#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
33#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
34pub struct InclusionFee<Balance> {
35 pub base_fee: Balance,
38 pub len_fee: Balance,
40 pub adjusted_weight_fee: Balance,
48}
49
50impl<Balance: AtLeast32BitUnsigned + Copy> InclusionFee<Balance> {
51 pub fn inclusion_fee(&self) -> Balance {
57 self.base_fee
58 .saturating_add(self.len_fee)
59 .saturating_add(self.adjusted_weight_fee)
60 }
61}
62
63#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
68#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
69#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
70pub struct FeeDetails<Balance> {
71 pub inclusion_fee: Option<InclusionFee<Balance>>,
73 #[cfg_attr(feature = "std", serde(skip))]
75 pub tip: Balance,
76}
77
78impl<Balance: AtLeast32BitUnsigned + Copy> FeeDetails<Balance> {
79 pub fn final_fee(&self) -> Balance {
85 self.inclusion_fee
86 .as_ref()
87 .map(|i| i.inclusion_fee())
88 .unwrap_or_else(|| Zero::zero())
89 .saturating_add(self.tip)
90 }
91}
92
93#[derive(Eq, PartialEq, Encode, Decode, Default, TypeInfo)]
96#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize, Clone))]
97#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
98#[cfg_attr(
99 feature = "std",
100 serde(bound(serialize = "Balance: std::fmt::Display, Weight: Serialize"))
101)]
102#[cfg_attr(
103 feature = "std",
104 serde(bound(deserialize = "Balance: std::str::FromStr, Weight: Deserialize<'de>"))
105)]
106pub struct RuntimeDispatchInfo<Balance, Weight = frame_support::weights::Weight> {
107 pub weight: Weight,
109 pub class: DispatchClass,
111 #[cfg_attr(feature = "std", serde(with = "serde_balance"))]
116 pub partial_fee: Balance,
117}
118
119#[cfg(feature = "std")]
120mod serde_balance {
121 use serde::{Deserialize, Deserializer, Serializer};
122
123 pub fn serialize<S: Serializer, T: std::fmt::Display>(
124 t: &T,
125 serializer: S,
126 ) -> Result<S::Ok, S::Error> {
127 serializer.serialize_str(&t.to_string())
128 }
129
130 pub fn deserialize<'de, D: Deserializer<'de>, T: std::str::FromStr>(
131 deserializer: D,
132 ) -> Result<T, D::Error> {
133 let s = String::deserialize(deserializer)?;
134 s.parse::<T>().map_err(|_| serde::de::Error::custom("Parse from string failed"))
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141 use frame_support::weights::Weight;
142
143 #[test]
144 fn should_serialize_and_deserialize_properly_with_string() {
145 let info = RuntimeDispatchInfo {
146 weight: Weight::from_parts(5, 0),
147 class: DispatchClass::Normal,
148 partial_fee: 1_000_000_u64,
149 };
150
151 let json_str =
152 r#"{"weight":{"ref_time":5,"proof_size":0},"class":"normal","partialFee":"1000000"}"#;
153
154 assert_eq!(serde_json::to_string(&info).unwrap(), json_str);
155 assert_eq!(serde_json::from_str::<RuntimeDispatchInfo<u64>>(json_str).unwrap(), info);
156
157 serde_json::to_value(&info).unwrap();
159 }
160
161 #[test]
162 fn should_serialize_and_deserialize_properly_large_value() {
163 let info = RuntimeDispatchInfo {
164 weight: Weight::from_parts(5, 0),
165 class: DispatchClass::Normal,
166 partial_fee: u128::max_value(),
167 };
168
169 let json_str = r#"{"weight":{"ref_time":5,"proof_size":0},"class":"normal","partialFee":"340282366920938463463374607431768211455"}"#;
170
171 assert_eq!(serde_json::to_string(&info).unwrap(), json_str);
172 assert_eq!(serde_json::from_str::<RuntimeDispatchInfo<u128>>(json_str).unwrap(), info);
173
174 serde_json::to_value(&info).unwrap();
176 }
177}