@@ -73,7 +73,28 @@ impl ProcessBlockValues for AverageBlockValue {
73
73
}
74
74
}
75
75
76
- const LOG_TARGET : & str = "price-aggregator" ;
76
+ /// Used to calculate the median of the accumulated values.
77
+ pub struct MedianBlockValue ;
78
+ impl ProcessBlockValues for MedianBlockValue {
79
+ fn process ( values : & [ CurrencyAmount ] ) -> Result < CurrencyAmount , & ' static str > {
80
+ if values. is_empty ( ) {
81
+ return Err ( "No values exist for the current block." ) ;
82
+ }
83
+
84
+ let mut sorted_values = values. to_vec ( ) ;
85
+ sorted_values. sort_unstable ( ) ;
86
+
87
+ let mid = sorted_values. len ( ) / 2 ;
88
+
89
+ if sorted_values. len ( ) % 2 == 0 {
90
+ Ok ( sorted_values[ mid. saturating_sub ( 1 ) ]
91
+ . saturating_add ( sorted_values[ mid] )
92
+ . saturating_mul ( CurrencyAmount :: from_rational ( 1 , 2 ) ) )
93
+ } else {
94
+ Ok ( sorted_values[ mid] )
95
+ }
96
+ }
97
+ }
77
98
78
99
/// Used to aggregate the accumulated values over some time period.
79
100
///
@@ -199,6 +220,8 @@ impl<L: Get<u32>> CircularBuffer<L> {
199
220
}
200
221
}
201
222
223
+ const LOG_TARGET : & str = "price-aggregator" ;
224
+
202
225
#[ frame_support:: pallet]
203
226
pub mod pallet {
204
227
use super :: * ;
@@ -274,12 +297,16 @@ pub mod pallet {
274
297
Self :: process_block_aggregated_values ( ) ;
275
298
276
299
// 2. Check if we need to push the average aggregated value to the storage.
277
- if IntermediateValueAggregator :: < T > :: get ( ) . limit_block > = now. saturated_into ( ) {
300
+ if IntermediateValueAggregator :: < T > :: get ( ) . limit_block < = now. saturated_into ( ) {
278
301
Self :: process_intermediate_aggregated_values ( now) ;
279
302
}
280
303
}
281
304
282
- // TODO: integration tests!
305
+ fn integrity_test ( ) {
306
+ assert ! ( T :: MaxValuesPerBlock :: get( ) > 0 ) ;
307
+ assert ! ( T :: CircularBufferLength :: get( ) > 0 ) ;
308
+ assert ! ( !T :: AggregationDuration :: get( ) . is_zero( ) ) ;
309
+ }
283
310
}
284
311
285
312
impl < T : Config > Pallet < T > {
@@ -297,7 +324,7 @@ pub mod pallet {
297
324
) {
298
325
Ok ( value) => value,
299
326
Err ( message) => {
300
- log:: error !(
327
+ log:: trace !(
301
328
target: LOG_TARGET ,
302
329
"Failed to process the accumulated native currency values in the current block. \
303
330
Reason: {:?}",
@@ -309,22 +336,22 @@ pub mod pallet {
309
336
}
310
337
} ;
311
338
312
- // TODO: is it ok to ignore this? A bit confused what happens actually in the closure.
313
339
// 3. Attempt to store the processed value.
314
- let _ignore = IntermediateValueAggregator :: < T > :: try_mutate (
315
- |aggregator| match aggregator. try_add ( processed_value) {
316
- Ok ( new_aggregator) => Ok ( new_aggregator) ,
317
- Err ( message) => {
318
- log:: error!(
319
- target: LOG_TARGET ,
320
- "Failed to add the processed native currency value to the intermediate storage. \
321
- Reason: {:?}",
322
- message
323
- ) ;
324
- Err ( ( ) )
325
- }
326
- } ,
327
- ) ;
340
+ // This operation is practically infallible, but we check the results for the additional safety.
341
+ let intermediate_value = IntermediateValueAggregator :: < T > :: get ( ) ;
342
+ match intermediate_value. try_add ( processed_value) {
343
+ Ok ( new_aggregator) => {
344
+ IntermediateValueAggregator :: < T > :: put ( new_aggregator) ;
345
+ }
346
+ Err ( message) => {
347
+ log:: error!(
348
+ target: LOG_TARGET ,
349
+ "Failed to add the processed native currency value to the intermediate storage. \
350
+ Reason: {:?}",
351
+ message
352
+ ) ;
353
+ }
354
+ }
328
355
}
329
356
330
357
/// Used to process the intermediate aggregated values, and push them to the moving average storage.
0 commit comments