1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use crate::DataProvider;
use frame_support::Parameter;
use sp_runtime::traits::{CheckedDiv, MaybeSerializeDeserialize, Member};
use sp_std::marker::PhantomData;
pub trait PriceProvider<CurrencyId, Price> {
fn get_price(base: CurrencyId, quote: CurrencyId) -> Option<Price>;
}
pub struct DefaultPriceProvider<CurrencyId, Source>(PhantomData<(CurrencyId, Source)>);
impl<CurrencyId, Source, Price> PriceProvider<CurrencyId, Price> for DefaultPriceProvider<CurrencyId, Source>
where
CurrencyId: Parameter + Member + Copy + MaybeSerializeDeserialize,
Source: DataProvider<CurrencyId, Price>,
Price: CheckedDiv,
{
fn get_price(base_currency_id: CurrencyId, quote_currency_id: CurrencyId) -> Option<Price> {
let base_price = Source::get(&base_currency_id)?;
let quote_price = Source::get("e_currency_id)?;
base_price.checked_div("e_price)
}
}
#[cfg(test)]
mod test {
use super::*;
use sp_runtime::{FixedPointNumber, FixedU128};
type Price = FixedU128;
pub struct MockDataProvider;
impl DataProvider<u32, Price> for MockDataProvider {
fn get(currency: &u32) -> Option<Price> {
match currency {
0 => Some(Price::from_inner(0)),
1 => Some(Price::from_inner(1)),
2 => Some(Price::from_inner(2)),
_ => None,
}
}
}
type TestPriceProvider = DefaultPriceProvider<u32, MockDataProvider>;
#[test]
fn get_price_should_work() {
assert_eq!(
TestPriceProvider::get_price(1, 2),
Some(Price::saturating_from_rational(1, 2))
);
assert_eq!(
TestPriceProvider::get_price(2, 1),
Some(Price::saturating_from_rational(2, 1))
);
}
#[test]
fn price_is_none_should_not_panic() {
assert_eq!(TestPriceProvider::get_price(3, 3), None);
assert_eq!(TestPriceProvider::get_price(3, 1), None);
assert_eq!(TestPriceProvider::get_price(1, 3), None);
}
#[test]
fn price_is_zero_should_not_panic() {
assert_eq!(TestPriceProvider::get_price(0, 0), None);
assert_eq!(TestPriceProvider::get_price(1, 0), None);
assert_eq!(TestPriceProvider::get_price(0, 1), Some(Price::from_inner(0)));
}
}