pallet_block_producer_fees/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
15#![deny(missing_docs)]
16
17pub mod benchmarking;
18
19#[cfg(test)]
20mod mock;
21#[cfg(test)]
22mod tests;
23pub mod weights;
24
25pub use pallet::*;
26pub use weights::WeightInfo;
27
28#[frame_support::pallet]
29pub mod pallet {
30 use super::*;
31 use frame_support::pallet_prelude::*;
32 use frame_system::pallet_prelude::*;
33 use sp_block_producer_fees::PerTenThousands;
34 use sp_std::collections::vec_deque::VecDeque;
35
36 pub const PALLET_VERSION: u32 = 1;
38
39 #[pallet::pallet]
40 pub struct Pallet<T>(_);
41
42 #[pallet::config]
43 pub trait Config: frame_system::Config {
44 #[pallet::constant]
46 type HistoricalChangesPerProducer: Get<u16>;
47
48 type WeightInfo: WeightInfo;
50
51 type Moment: Parameter + Default + MaxEncodedLen + PartialOrd;
53
54 fn current_moment() -> Self::Moment;
56
57 #[cfg(feature = "runtime-benchmarks")]
58 type BenchmarkHelper: benchmarking::BenchmarkHelper<Self::AccountId>;
60 }
61
62 type FeeChangeOf<T> = (<T as Config>::Moment, PerTenThousands);
63
64 #[pallet::storage]
66 #[pallet::unbounded]
67 pub type FeesChanges<T: Config> = StorageMap<
68 Hasher = Twox64Concat,
69 Key = T::AccountId,
70 Value = VecDeque<FeeChangeOf<T>>,
71 QueryKind = ValueQuery,
72 >;
73
74 #[pallet::call]
75 impl<T: Config> Pallet<T> {
76 #[pallet::call_index(0)]
78 #[pallet::weight((T::WeightInfo::set_fee(), DispatchClass::Normal))]
79 pub fn set_fee(origin: OriginFor<T>, fee_numerator: PerTenThousands) -> DispatchResult {
80 let account_id = ensure_signed(origin)?;
81 if fee_numerator > 10000 {
82 return Err(DispatchError::Other("fee numerator must be in range from 0 to 10000"));
83 }
84 FeesChanges::<T>::mutate(account_id, |fees_log| {
85 if fees_log.len() > T::HistoricalChangesPerProducer::get().into() {
86 let _ = fees_log.pop_back();
87 }
88 fees_log.push_front((T::current_moment(), fee_numerator));
89 });
90 Ok(())
91 }
92 }
93
94 impl<T: Config> Pallet<T> {
95 pub fn get_version() -> u32 {
97 PALLET_VERSION
98 }
99
100 pub fn get_all() -> impl Iterator<Item = (T::AccountId, VecDeque<FeeChangeOf<T>>)> {
102 FeesChanges::<T>::iter()
103 }
104
105 pub fn get_all_latest() -> impl Iterator<Item = (T::AccountId, FeeChangeOf<T>)> {
107 Self::get_all().map(|(account_id, changes)| {
108 (
109 account_id,
110 changes.front().expect("There are no empty collections in storage").clone(),
111 )
112 })
113 }
114
115 pub fn get(id: T::AccountId) -> VecDeque<FeeChangeOf<T>> {
118 FeesChanges::<T>::get(id)
119 }
120
121 pub fn get_latest(id: T::AccountId) -> Option<FeeChangeOf<T>> {
123 FeesChanges::<T>::get(id).front().cloned()
124 }
125 }
126}