New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: price-oracle pallet #112
Conversation
Codecov Report
@@ Coverage Diff @@
## master #112 +/- ##
==========================================
+ Coverage 85.22% 85.26% +0.04%
==========================================
Files 21 24 +3
Lines 2132 2362 +230
==========================================
+ Hits 1817 2014 +197
- Misses 315 348 +33
Continue to review full report at Codecov.
|
Our use case is to allow another pallets to call @jak-pan @lumir-mrkva @apopiak your expertise would be greatly appreciated. |
polkadotJS types definition seems to be missing |
} | ||
|
||
impl BucketQueue { | ||
// make sure that BUCKET_SIZE != 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did you? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any idea how this can be done?
} | ||
} | ||
|
||
pub const BUCKET_SIZE: u32 = 10; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably going to be configured from time to time so might be better as a pallet const
Also - maybe NonZeroU32 type can be used instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't use NonZeroU32 because its constructor is not const
. The same problem applies also for pallet config parameters.
afaik rule of thumb is keep the load on on_finalize minimized, so all the heavier operations should always be processed in on_inialize |
Did this change? We were told the exact opposite before when we were doing exchange. The only thing you need to make sure is to reserve weight in on-initialize -> That's why the exchange order matching is done in on-finalize. (The data structures can be still cleaned for that block so we don't need to save unnecessary data to blockchain) |
The most important thing is to make sure that the weight used is predictable. As long as all weight consumed in the hooks is tracked it does not matter whether you execute in |
This line makes me uncomfortable xD |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few more comments. I haven't got through it all yet.
impl<T: Config> Pallet<T> { | ||
pub fn on_create_pool(asset_pair: AssetPair) { | ||
let data = PriceDataTen::<T>::get(); | ||
if !data.iter().any(|bucket_tuple| bucket_tuple.0 == asset_pair.name()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the iteration necessary ? I am not sure how many there can be but i'd rather try to avoid.
Perhaps different storage ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it is necessary. We need to check the existence of an asset pair and increase the asset_count if the asset pair exists because it is used in weigh calculation here
fn on_initialize_one_entry_multiple_tokens(t: u32, ) -> Weight { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, i know it is necessary now. I really meant if this could not be done in a way where there is no need to iterate over it just to find the pair
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not aware of a better solution. We need to use an iteration because we use a vector. The reason behind this is that we need to iterate over all values at the end of each block, and because it is advised to use vectors over maps (faster iterations). https://substrate.dev/docs/en/knowledgebase/runtime/storage#iterating-over-storage-maps
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not to just use a map where the check for existence could be O(1) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I stated above, we use a vector because we iterate over all values at the end of each block. For me, it makes sense to prioritize iterations, because a lookup is a "one time thing" (occurs only when a new pool is created), but iterating takes place at the end of each block. There's a plan to modify the algorithm for price calculations, so this implementation might change in the future.
Description
Implement on-chain oracles providing price estimates for asset pairs based on previous trading data.
Aggregate data of different length periods( e.g. 1, 10, 100 and 1000 blocks ) and calculate average prices.
Values tracked: trading prices and volumes, total pool liquidity.
Related Issue
Fixes: #106