referrerpolicy=no-referrer-when-downgrade

pallet_oracle/
default_combine_data.rs

1// This file is part of Substrate.
2
3// Copyright (C) 2020-2025 Acala Foundation.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use crate::{CombineData, Config, MomentOf, TimestampedValueOf};
19use frame_support::traits::{Get, Time};
20use sp_runtime::traits::Saturating;
21use sp_std::{marker, prelude::*};
22
23/// Sort by value and returns median timestamped value.
24/// Returns prev_value if not enough valid values.
25pub struct DefaultCombineData<T, MinimumCount, ExpiresIn, I = ()>(
26	marker::PhantomData<(T, I, MinimumCount, ExpiresIn)>,
27);
28
29impl<T, I, MinimumCount, ExpiresIn>
30	CombineData<<T as Config<I>>::OracleKey, TimestampedValueOf<T, I>>
31	for DefaultCombineData<T, MinimumCount, ExpiresIn, I>
32where
33	T: Config<I>,
34	I: 'static,
35	MinimumCount: Get<u32>,
36	ExpiresIn: Get<MomentOf<T, I>>,
37{
38	fn combine_data(
39		_key: &<T as Config<I>>::OracleKey,
40		mut values: Vec<TimestampedValueOf<T, I>>,
41		prev_value: Option<TimestampedValueOf<T, I>>,
42	) -> Option<TimestampedValueOf<T, I>> {
43		let expires_in = ExpiresIn::get();
44		let now = T::Time::now();
45
46		values.retain(|x| x.timestamp.saturating_add(expires_in) > now);
47
48		let count = values.len() as u32;
49		let minimum_count = MinimumCount::get();
50		if count < minimum_count || count == 0 {
51			return prev_value;
52		}
53
54		let mid_index = count / 2;
55		// Won't panic as `values` ensured not empty.
56		let (_, value, _) =
57			values.select_nth_unstable_by(mid_index as usize, |a, b| a.value.cmp(&b.value));
58		Some(value.clone())
59	}
60}