5
5
/// https://substrate.dev/docs/en/knowledgebase/runtime/frame
6
6
use frame_support:: { dispatch:: DispatchResultWithPostInfo , weights:: Pays } ;
7
7
use frame_system:: offchain:: { SendSignedTransaction , Signer } ;
8
- use lite_json:: json:: JsonValue ;
9
8
use log;
10
9
use sp_runtime:: offchain:: { http, Duration } ;
11
10
use sp_runtime:: traits:: SaturatedConversion ;
@@ -26,6 +25,9 @@ const DST_ISSUER: &str = "GBOVQKJYHXRR3DX6NOX2RRYFRCUMSADGDESTDNBDS6CDVLGVESRTAC
26
25
const DST_CODE : & str = "TFT" ;
27
26
const DST_AMOUNT : u32 = 100 ;
28
27
28
+ #[ cfg( test) ]
29
+ mod mock;
30
+
29
31
#[ cfg( test) ]
30
32
mod tests;
31
33
@@ -91,6 +93,8 @@ pub mod pallet {
91
93
PriceStored ( u32 ) ,
92
94
OffchainWorkerExecuted ( T :: AccountId ) ,
93
95
AveragePriceStored ( u32 ) ,
96
+ AveragePriceIsAboveMaxPrice ( u32 , u32 ) ,
97
+ AveragePriceIsBelowMinPrice ( u32 , u32 ) ,
94
98
}
95
99
96
100
#[ pallet:: error]
@@ -99,6 +103,8 @@ pub mod pallet {
99
103
OffchainSignedTxError ,
100
104
NoLocalAcctForSigning ,
101
105
AccountUnauthorizedToSetPrice ,
106
+ MaxPriceBelowMinPriceError ,
107
+ MinPriceAboveMaxPriceError ,
102
108
}
103
109
104
110
#[ pallet:: pallet]
@@ -130,6 +136,14 @@ pub mod pallet {
130
136
#[ pallet:: getter( fn allowed_origin) ]
131
137
pub type AllowedOrigin < T : Config > = StorageValue < _ , T :: AccountId , OptionQuery > ;
132
138
139
+ #[ pallet:: storage]
140
+ #[ pallet:: getter( fn min_tft_price) ]
141
+ pub type MinTftPrice < T > = StorageValue < _ , u32 , ValueQuery > ;
142
+
143
+ #[ pallet:: storage]
144
+ #[ pallet:: getter( fn max_tft_price) ]
145
+ pub type MaxTftPrice < T > = StorageValue < _ , u32 , ValueQuery > ;
146
+
133
147
#[ pallet:: call]
134
148
impl < T : Config > Pallet < T > {
135
149
#[ pallet:: weight( 100_000_000 + T :: DbWeight :: get( ) . writes( 1 ) + T :: DbWeight :: get( ) . reads( 1 ) ) ]
@@ -158,6 +172,28 @@ pub mod pallet {
158
172
AllowedOrigin :: < T > :: set ( Some ( target) ) ;
159
173
Ok ( ( ) . into ( ) )
160
174
}
175
+
176
+ #[ pallet:: weight( 100_000_000 + T :: DbWeight :: get( ) . writes( 1 ) + T :: DbWeight :: get( ) . reads( 1 ) ) ]
177
+ pub fn set_min_tft_price ( origin : OriginFor < T > , price : u32 ) -> DispatchResultWithPostInfo {
178
+ T :: RestrictedOrigin :: ensure_origin ( origin) ?;
179
+ ensure ! (
180
+ price < MaxTftPrice :: <T >:: get( ) ,
181
+ Error :: <T >:: MinPriceAboveMaxPriceError
182
+ ) ;
183
+ MinTftPrice :: < T > :: put ( price) ;
184
+ Ok ( ( ) . into ( ) )
185
+ }
186
+
187
+ #[ pallet:: weight( 100_000_000 + T :: DbWeight :: get( ) . writes( 1 ) + T :: DbWeight :: get( ) . reads( 1 ) ) ]
188
+ pub fn set_max_tft_price ( origin : OriginFor < T > , price : u32 ) -> DispatchResultWithPostInfo {
189
+ T :: RestrictedOrigin :: ensure_origin ( origin) ?;
190
+ ensure ! (
191
+ price > MinTftPrice :: <T >:: get( ) ,
192
+ Error :: <T >:: MaxPriceBelowMinPriceError
193
+ ) ;
194
+ MaxTftPrice :: < T > :: put ( price) ;
195
+ Ok ( ( ) . into ( ) )
196
+ }
161
197
}
162
198
163
199
#[ pallet:: hooks]
@@ -173,13 +209,17 @@ pub mod pallet {
173
209
#[ pallet:: genesis_config]
174
210
pub struct GenesisConfig < T : Config > {
175
211
pub allowed_origin : Option < T :: AccountId > ,
212
+ pub min_tft_price : u32 ,
213
+ pub max_tft_price : u32 ,
176
214
}
177
215
178
216
#[ cfg( feature = "std" ) ]
179
217
impl < T : Config > Default for GenesisConfig < T > {
180
218
fn default ( ) -> Self {
181
219
Self {
182
220
allowed_origin : None ,
221
+ min_tft_price : 10 ,
222
+ max_tft_price : 1000 ,
183
223
}
184
224
}
185
225
}
@@ -188,6 +228,8 @@ pub mod pallet {
188
228
impl < T : Config > GenesisBuild < T > for GenesisConfig < T > {
189
229
fn build ( & self ) {
190
230
AllowedOrigin :: < T > :: set ( self . allowed_origin . clone ( ) ) ;
231
+ MinTftPrice :: < T > :: put ( self . min_tft_price ) ;
232
+ MaxTftPrice :: < T > :: put ( self . max_tft_price ) ;
191
233
}
192
234
}
193
235
}
@@ -212,6 +254,18 @@ impl<T: Config> Pallet<T> {
212
254
AverageTftPrice :: < T > :: put ( average) ;
213
255
Self :: deposit_event ( Event :: AveragePriceStored ( average) ) ;
214
256
257
+ let min = Self :: min_tft_price ( ) ;
258
+ if average < min {
259
+ log:: info!( "average price {:?} is below min price {:?} !" , average, min) ;
260
+ Self :: deposit_event ( Event :: AveragePriceIsBelowMinPrice ( average, min) ) ;
261
+ }
262
+
263
+ let max = Self :: max_tft_price ( ) ;
264
+ if average > max {
265
+ log:: info!( "average price {:?} is above max price {:?} !" , average, max) ;
266
+ Self :: deposit_event ( Event :: AveragePriceIsAboveMaxPrice ( average, max) ) ;
267
+ }
268
+
215
269
Ok ( Pays :: No . into ( ) )
216
270
}
217
271
@@ -305,28 +359,6 @@ impl<T: Config> Pallet<T> {
305
359
return Err ( <Error < T > >:: OffchainSignedTxError ) ;
306
360
}
307
361
308
- /// Parse the price from the given JSON string using `lite-json`.
309
- ///
310
- /// Returns `None` when parsing failed or `Some(price in mUSD)` when parsing is successful.
311
- pub fn parse_price ( price_str : & str ) -> Option < u32 > {
312
- let val = lite_json:: parse_json ( price_str) ;
313
- let price = match val. ok ( ) ? {
314
- JsonValue :: Object ( obj) => {
315
- let ( _, v) = obj
316
- . into_iter ( )
317
- . find ( |( k, _) | k. iter ( ) . copied ( ) . eq ( "USD" . chars ( ) ) ) ?;
318
- match v {
319
- JsonValue :: Number ( number) => number,
320
- _ => return None ,
321
- }
322
- }
323
- _ => return None ,
324
- } ;
325
-
326
- let exp = price. fraction_length . saturating_sub ( 3 ) ;
327
- Some ( price. integer as u32 * 1000 + ( price. fraction / 10_u64 . pow ( exp) ) as u32 )
328
- }
329
-
330
362
/// Parse the lowest price from the given JSON string using `serde_json`.
331
363
///
332
364
/// Returns `None` when parsing failed or `Some(price in mUSD)` when parsing is successful.
@@ -366,8 +398,9 @@ impl<T: Config> Pallet<T> {
366
398
}
367
399
368
400
fn calc_avg ( ) -> u32 {
369
- let queue = Self :: queue_transient ( ) ;
370
- let items = queue. get_all_values ( ) ;
401
+ let items: Vec < u32 > = TftPriceHistory :: < T > :: iter_values ( )
402
+ . filter ( |val| val > & 0_u32 )
403
+ . collect ( ) ;
371
404
items. iter ( ) . fold ( 0_u32 , |a, b| a. saturating_add ( * b) ) / items. len ( ) as u32
372
405
}
373
406
}
0 commit comments