orml_oracle/
default_combine_data.rs

1use crate::{Config, MomentOf, TimestampedValueOf};
2use frame_support::traits::{Get, Time};
3use orml_traits::CombineData;
4use sp_runtime::traits::Saturating;
5use sp_std::{marker, prelude::*};
6
7/// Sort by value and returns median timestamped value.
8/// Returns prev_value if not enough valid values.
9pub struct DefaultCombineData<T, MinimumCount, ExpiresIn, I = ()>(marker::PhantomData<(T, I, MinimumCount, ExpiresIn)>);
10
11impl<T, I, MinimumCount, ExpiresIn> CombineData<<T as Config<I>>::OracleKey, TimestampedValueOf<T, I>>
12	for DefaultCombineData<T, MinimumCount, ExpiresIn, I>
13where
14	T: Config<I>,
15	I: 'static,
16	MinimumCount: Get<u32>,
17	ExpiresIn: Get<MomentOf<T, I>>,
18{
19	fn combine_data(
20		_key: &<T as Config<I>>::OracleKey,
21		mut values: Vec<TimestampedValueOf<T, I>>,
22		prev_value: Option<TimestampedValueOf<T, I>>,
23	) -> Option<TimestampedValueOf<T, I>> {
24		let expires_in = ExpiresIn::get();
25		let now = T::Time::now();
26
27		values.retain(|x| x.timestamp.saturating_add(expires_in) > now);
28
29		let count = values.len() as u32;
30		let minimum_count = MinimumCount::get();
31		if count < minimum_count || count == 0 {
32			return prev_value;
33		}
34
35		let mid_index = count / 2;
36		// Won't panic as `values` ensured not empty.
37		let (_, value, _) = values.select_nth_unstable_by(mid_index as usize, |a, b| a.value.cmp(&b.value));
38		Some(value.clone())
39	}
40}