42
42
#![ cfg_attr( not( feature = "std" ) , no_std) ]
43
43
44
44
use frame_system:: {
45
- self as system,
46
- ensure_signed,
47
- ensure_none,
48
45
offchain:: {
49
46
AppCrypto , CreateSignedTransaction , SendUnsignedTransaction , SendSignedTransaction ,
50
47
SignedPayload , SigningTypes , Signer , SubmitTransaction ,
51
48
}
52
49
} ;
53
- use frame_support:: {
54
- debug,
55
- dispatch:: DispatchResult , decl_module, decl_storage, decl_event,
56
- traits:: Get ,
57
- } ;
50
+ use frame_support:: { debug, storage:: StorageValue , traits:: Get } ;
58
51
use sp_core:: crypto:: KeyTypeId ;
59
52
use sp_runtime:: {
60
53
RuntimeDebug ,
61
54
offchain:: { http, Duration , storage:: StorageValueRef } ,
62
55
traits:: Zero ,
63
56
transaction_validity:: {
64
57
InvalidTransaction , ValidTransaction , TransactionValidity , TransactionSource ,
65
- TransactionPriority ,
66
58
} ,
67
59
} ;
68
60
use codec:: { Encode , Decode } ;
@@ -101,37 +93,6 @@ pub mod crypto {
101
93
}
102
94
}
103
95
104
- /// This pallet's configuration trait
105
- pub trait Trait : CreateSignedTransaction < Call < Self > > {
106
- /// The identifier type for an offchain worker.
107
- type AuthorityId : AppCrypto < Self :: Public , Self :: Signature > ;
108
-
109
- /// The overarching event type.
110
- type Event : From < Event < Self > > + Into < <Self as frame_system:: Trait >:: Event > ;
111
- /// The overarching dispatch call type.
112
- type Call : From < Call < Self > > ;
113
-
114
- // Configuration parameters
115
-
116
- /// A grace period after we send transaction.
117
- ///
118
- /// To avoid sending too many transactions, we only attempt to send one
119
- /// every `GRACE_PERIOD` blocks. We use Local Storage to coordinate
120
- /// sending between distinct runs of this offchain worker.
121
- type GracePeriod : Get < Self :: BlockNumber > ;
122
-
123
- /// Number of blocks of cooldown after unsigned transaction is included.
124
- ///
125
- /// This ensures that we only accept unsigned transactions once, every `UnsignedInterval` blocks.
126
- type UnsignedInterval : Get < Self :: BlockNumber > ;
127
-
128
- /// A configuration for base priority of unsigned transactions.
129
- ///
130
- /// This is exposed so that it can be tuned for particular runtime, when
131
- /// multiple pallets send unsigned transactions.
132
- type UnsignedPriority : Get < TransactionPriority > ;
133
- }
134
-
135
96
/// Payload used by this example crate to hold price
136
97
/// data required to submit a transaction.
137
98
#[ derive( Encode , Decode , Clone , PartialEq , Eq , RuntimeDebug ) ]
@@ -147,35 +108,131 @@ impl<T: SigningTypes> SignedPayload<T> for PricePayload<T::Public, T::BlockNumbe
147
108
}
148
109
}
149
110
150
- decl_storage ! {
151
- trait Store for Module <T : Trait > as ExampleOffchainWorker {
152
- /// A vector of recently submitted prices.
111
+ pub use pallet:: * ;
112
+ #[ frame_support:: pallet( ExampleOffchainWorker ) ]
113
+ mod pallet {
114
+ use super :: { CreateSignedTransaction , AppCrypto , PricePayload , TransactionType } ;
115
+ use frame_support:: { pallet_prelude:: * , debug} ;
116
+ use frame_system:: pallet_prelude:: * ;
117
+
118
+ /// This pallet's configuration trait
119
+ #[ pallet:: trait_]
120
+ pub trait Trait : CreateSignedTransaction < Call < Self > > + frame_system:: Trait {
121
+ /// The identifier type for an offchain worker.
122
+ type AuthorityId : AppCrypto < Self :: Public , Self :: Signature > ;
123
+
124
+ /// The overarching event type.
125
+ type Event : From < Event < Self > > + IsType < <Self as frame_system:: Trait >:: Event > ;
126
+ /// The overarching dispatch call type.
127
+ type Call : From < Call < Self > > ;
128
+
129
+ // Configuration parameters
130
+
131
+ /// A grace period after we send transaction.
153
132
///
154
- /// This is used to calculate average price, should have bounded size.
155
- Prices get( fn prices) : Vec <u32 >;
156
- /// Defines the block when next unsigned transaction will be accepted.
133
+ /// To avoid sending too many transactions, we only attempt to send one
134
+ /// every `GRACE_PERIOD` blocks. We use Local Storage to coordinate
135
+ /// sending between distinct runs of this offchain worker.
136
+ type GracePeriod : Get < Self :: BlockNumber > ;
137
+
138
+ /// Number of blocks of cooldown after unsigned transaction is included.
157
139
///
158
- /// To prevent spam of unsigned (and unpayed!) transactions on the network,
159
- /// we only allow one transaction every `T::UnsignedInterval` blocks.
160
- /// This storage entry defines when new transaction is going to be accepted.
161
- NextUnsignedAt get( fn next_unsigned_at) : T :: BlockNumber ;
140
+ /// This ensures that we only accept unsigned transactions once, every `UnsignedInterval`
141
+ /// blocks.
142
+ type UnsignedInterval : Get < Self :: BlockNumber > ;
143
+
144
+ /// A configuration for base priority of unsigned transactions.
145
+ ///
146
+ /// This is exposed so that it can be tuned for particular runtime, when
147
+ /// multiple pallets send unsigned transactions.
148
+ type UnsignedPriority : Get < TransactionPriority > ;
162
149
}
163
- }
164
150
165
- decl_event ! (
151
+ /// A vector of recently submitted prices.
152
+ ///
153
+ /// This is used to calculate average price, should have bounded size.
154
+ #[ pallet:: storage]
155
+ #[ pallet:: generate_getter( fn prices) ]
156
+ pub ( crate ) type Prices = StorageValueType < _ , Vec < u32 > , ValueQuery > ;
157
+
158
+ /// Defines the block when next unsigned transaction will be accepted.
159
+ ///
160
+ /// To prevent spam of unsigned (and unpayed!) transactions on the network,
161
+ /// we only allow one transaction every `T::UnsignedInterval` blocks.
162
+ /// This storage entry defines when new transaction is going to be accepted.
163
+ #[ pallet:: storage]
164
+ #[ pallet:: generate_getter( fn next_unsigned_at) ]
165
+ pub ( crate ) type NextUnsignedAt < T : Trait > = StorageValueType < _ , T :: BlockNumber , ValueQuery > ;
166
+
166
167
/// Events generated by the module.
167
- pub enum Event <T > where AccountId = <T as frame_system:: Trait >:: AccountId {
168
- /// Event generated when new price is accepted to contribute to the average.
168
+ #[ pallet:: event]
169
+ #[ pallet:: metadata( <T as frame_system:: Trait >:: AccountId = AccountId ) ]
170
+ pub enum Event < T : Trait > {
171
+ /// Event generated when new price is accepted to contribute to the average.
169
172
/// [price, who]
170
- NewPrice ( u32 , AccountId ) ,
173
+ NewPrice ( u32 , < T as frame_system :: Trait > :: AccountId ) ,
171
174
}
172
- ) ;
173
175
174
- decl_module ! {
175
- /// A public part of the pallet.
176
- pub struct Module <T : Trait > for enum Call where origin: T :: Origin {
177
- fn deposit_event( ) = default ;
176
+ #[ pallet:: module]
177
+ #[ pallet:: generate( fn deposit_event) ]
178
+ pub struct Module < T > ( PhantomData < T > ) ;
179
+
180
+ #[ pallet:: module_interface]
181
+ impl < T : Trait > ModuleInterface < BlockNumberFor < T > > for Module < T > {
182
+ /// Offchain Worker entry point.
183
+ ///
184
+ /// By implementing `fn offchain_worker` within `decl_module!` you declare a new offchain
185
+ /// worker.
186
+ /// This function will be called when the node is fully synced and a new best block is
187
+ /// succesfuly imported.
188
+ /// Note that it's not guaranteed for offchain workers to run on EVERY block, there might
189
+ /// be cases where some blocks are skipped, or for some the worker runs twice (re-orgs),
190
+ /// so the code should be able to handle that.
191
+ /// You can use `Local Storage` API to coordinate runs of the worker.
192
+ fn offchain_worker ( block_number : T :: BlockNumber ) {
193
+ // It's a good idea to add logs to your offchain workers.
194
+ // Using the `frame_support::debug` module you have access to the same API exposed by
195
+ // the `log` crate.
196
+ // Note that having logs compiled to WASM may cause the size of the blob to increase
197
+ // significantly. You can use `RuntimeDebug` custom derive to hide details of the types
198
+ // in WASM or use `debug::native` namespace to produce logs only when the worker is
199
+ // running natively.
200
+ debug:: native:: info!( "Hello World from offchain workers!" ) ;
201
+
202
+ // Since off-chain workers are just part of the runtime code, they have direct access
203
+ // to the storage and other included pallets.
204
+ //
205
+ // We can easily import `frame_system` and retrieve a block hash of the parent block.
206
+ let parent_hash = <frame_system:: Module < T > >:: block_hash ( block_number - 1 . into ( ) ) ;
207
+ debug:: debug!( "Current block: {:?} (parent hash: {:?})" , block_number, parent_hash) ;
208
+
209
+ // It's a good practice to keep `fn offchain_worker()` function minimal, and move most
210
+ // of the code to separate `impl` block.
211
+ // Here we call a helper function to calculate current average price.
212
+ // This function reads storage entries of the current state.
213
+ let average: Option < u32 > = Self :: average_price ( ) ;
214
+ debug:: debug!( "Current price: {:?}" , average) ;
215
+
216
+ // For this example we are going to send both signed and unsigned transactions
217
+ // depending on the block number.
218
+ // Usually it's enough to choose one or the other.
219
+ let should_send = Self :: choose_transaction_type ( block_number) ;
220
+ let res = match should_send {
221
+ TransactionType :: Signed => Self :: fetch_price_and_send_signed ( ) ,
222
+ TransactionType :: UnsignedForAny => Self :: fetch_price_and_send_unsigned_for_any_account ( block_number) ,
223
+ TransactionType :: UnsignedForAll => Self :: fetch_price_and_send_unsigned_for_all_accounts ( block_number) ,
224
+ TransactionType :: Raw => Self :: fetch_price_and_send_raw_unsigned ( block_number) ,
225
+ TransactionType :: None => Ok ( ( ) ) ,
226
+ } ;
227
+ if let Err ( e) = res {
228
+ debug:: error!( "Error: {}" , e) ;
229
+ }
230
+ }
231
+ }
178
232
233
+ /// A public part of the pallet.
234
+ #[ pallet:: call]
235
+ impl < T : Trait > Call for Module < T > {
179
236
/// Submit new price to the list.
180
237
///
181
238
/// This method is a public function of the module and can be called from within
@@ -190,13 +247,13 @@ decl_module! {
190
247
/// working and receives (and provides) meaningful data.
191
248
/// This example is not focused on correctness of the oracle itself, but rather its
192
249
/// purpose is to showcase offchain worker capabilities.
193
- #[ weight = 0 ]
194
- pub fn submit_price( origin, price: u32 ) -> DispatchResult {
250
+ #[ pallet :: weight( 0 ) ]
251
+ pub fn submit_price ( origin : OriginFor < T > , price : u32 ) -> DispatchResultWithPostInfo {
195
252
// Retrieve sender of the transaction.
196
253
let who = ensure_signed ( origin) ?;
197
254
// Add the price to the on-chain list.
198
255
Self :: add_price ( who, price) ;
199
- Ok ( ( ) )
256
+ Ok ( ( ) . into ( ) )
200
257
}
201
258
202
259
/// Submit new price to the list via unsigned transaction.
@@ -215,84 +272,37 @@ decl_module! {
215
272
///
216
273
/// This example is not focused on correctness of the oracle itself, but rather its
217
274
/// purpose is to showcase offchain worker capabilities.
218
- #[ weight = 0 ]
219
- pub fn submit_price_unsigned( origin, _block_number: T :: BlockNumber , price: u32 )
220
- -> DispatchResult
275
+ #[ pallet:: weight( 0 ) ]
276
+ pub fn submit_price_unsigned (
277
+ origin : OriginFor < T > ,
278
+ _block_number : T :: BlockNumber ,
279
+ price : u32
280
+ ) -> DispatchResultWithPostInfo
221
281
{
222
282
// This ensures that the function can only be called via unsigned transaction.
223
283
ensure_none ( origin) ?;
224
284
// Add the price to the on-chain list, but mark it as coming from an empty address.
225
285
Self :: add_price ( Default :: default ( ) , price) ;
226
286
// now increment the block number at which we expect next unsigned transaction.
227
- let current_block = <system :: Module <T >>:: block_number( ) ;
287
+ let current_block = <frame_system :: Module < T > >:: block_number ( ) ;
228
288
<NextUnsignedAt < T > >:: put ( current_block + T :: UnsignedInterval :: get ( ) ) ;
229
- Ok ( ( ) )
289
+ Ok ( ( ) . into ( ) )
230
290
}
231
291
232
- #[ weight = 0 ]
292
+ #[ pallet :: weight( 0 ) ]
233
293
pub fn submit_price_unsigned_with_signed_payload (
234
- origin,
294
+ origin : OriginFor < T > ,
235
295
price_payload : PricePayload < T :: Public , T :: BlockNumber > ,
236
296
_signature : T :: Signature ,
237
- ) -> DispatchResult {
297
+ ) -> DispatchResultWithPostInfo {
238
298
// This ensures that the function can only be called via unsigned transaction.
239
299
ensure_none ( origin) ?;
240
300
// Add the price to the on-chain list, but mark it as coming from an empty address.
241
301
Self :: add_price ( Default :: default ( ) , price_payload. price ) ;
242
302
// now increment the block number at which we expect next unsigned transaction.
243
- let current_block = <system :: Module <T >>:: block_number( ) ;
303
+ let current_block = <frame_system :: Module < T > >:: block_number ( ) ;
244
304
<NextUnsignedAt < T > >:: put ( current_block + T :: UnsignedInterval :: get ( ) ) ;
245
- Ok ( ( ) )
246
- }
247
-
248
- /// Offchain Worker entry point.
249
- ///
250
- /// By implementing `fn offchain_worker` within `decl_module!` you declare a new offchain
251
- /// worker.
252
- /// This function will be called when the node is fully synced and a new best block is
253
- /// succesfuly imported.
254
- /// Note that it's not guaranteed for offchain workers to run on EVERY block, there might
255
- /// be cases where some blocks are skipped, or for some the worker runs twice (re-orgs),
256
- /// so the code should be able to handle that.
257
- /// You can use `Local Storage` API to coordinate runs of the worker.
258
- fn offchain_worker( block_number: T :: BlockNumber ) {
259
- // It's a good idea to add logs to your offchain workers.
260
- // Using the `frame_support::debug` module you have access to the same API exposed by
261
- // the `log` crate.
262
- // Note that having logs compiled to WASM may cause the size of the blob to increase
263
- // significantly. You can use `RuntimeDebug` custom derive to hide details of the types
264
- // in WASM or use `debug::native` namespace to produce logs only when the worker is
265
- // running natively.
266
- debug:: native:: info!( "Hello World from offchain workers!" ) ;
267
-
268
- // Since off-chain workers are just part of the runtime code, they have direct access
269
- // to the storage and other included pallets.
270
- //
271
- // We can easily import `frame_system` and retrieve a block hash of the parent block.
272
- let parent_hash = <system:: Module <T >>:: block_hash( block_number - 1 . into( ) ) ;
273
- debug:: debug!( "Current block: {:?} (parent hash: {:?})" , block_number, parent_hash) ;
274
-
275
- // It's a good practice to keep `fn offchain_worker()` function minimal, and move most
276
- // of the code to separate `impl` block.
277
- // Here we call a helper function to calculate current average price.
278
- // This function reads storage entries of the current state.
279
- let average: Option <u32 > = Self :: average_price( ) ;
280
- debug:: debug!( "Current price: {:?}" , average) ;
281
-
282
- // For this example we are going to send both signed and unsigned transactions
283
- // depending on the block number.
284
- // Usually it's enough to choose one or the other.
285
- let should_send = Self :: choose_transaction_type( block_number) ;
286
- let res = match should_send {
287
- TransactionType :: Signed => Self :: fetch_price_and_send_signed( ) ,
288
- TransactionType :: UnsignedForAny => Self :: fetch_price_and_send_unsigned_for_any_account( block_number) ,
289
- TransactionType :: UnsignedForAll => Self :: fetch_price_and_send_unsigned_for_all_accounts( block_number) ,
290
- TransactionType :: Raw => Self :: fetch_price_and_send_raw_unsigned( block_number) ,
291
- TransactionType :: None => Ok ( ( ) ) ,
292
- } ;
293
- if let Err ( e) = res {
294
- debug:: error!( "Error: {}" , e) ;
295
- }
305
+ Ok ( ( ) . into ( ) )
296
306
}
297
307
}
298
308
}
@@ -631,7 +641,7 @@ impl<T: Trait> Module<T> {
631
641
. expect ( "The average is not empty, because it was just mutated; qed" ) ;
632
642
debug:: info!( "Current average price is: {}" , average) ;
633
643
// here we are raising the NewPrice event
634
- Self :: deposit_event ( RawEvent :: NewPrice ( price, who) ) ;
644
+ Self :: deposit_event ( Event :: NewPrice ( price, who) ) ;
635
645
}
636
646
637
647
/// Calculate current average price.
@@ -654,7 +664,7 @@ impl<T: Trait> Module<T> {
654
664
return InvalidTransaction :: Stale . into ( ) ;
655
665
}
656
666
// Let's make sure to reject transactions from the future.
657
- let current_block = <system :: Module < T > >:: block_number ( ) ;
667
+ let current_block = <frame_system :: Module < T > >:: block_number ( ) ;
658
668
if & current_block < block_number {
659
669
return InvalidTransaction :: Future . into ( ) ;
660
670
}
0 commit comments