Skip to content
Snippets Groups Projects
Commit 33329a2b authored by 邱昊's avatar 邱昊 Committed by Xiliang Chen
Browse files

feat: prices module (#23)

* feat: prices module

* fix: add check to avoid dividing by zero

* fix: delete num_traits dependency
parent 90b89dfc
No related branches found
No related tags found
No related merge requests found
...@@ -3,6 +3,7 @@ members = [ ...@@ -3,6 +3,7 @@ members = [
"oracle", "oracle",
"tokens", "tokens",
"traits", "traits",
"prices",
"utilities", "utilities",
"auction", "auction",
] ]
[package]
name = "orml-prices"
version = "0.1.0"
authors = ["Acala Developers"]
edition = "2018"
[dependencies]
serde = { version = "1.0", optional = true }
codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false }
sr-primitives = { git = "https://github.com/paritytech/substrate.git", default-features = false }
srml-support = { package = "srml-support", git = "https://github.com/paritytech/substrate.git", default-features = false }
srml-system = { package = "srml-system", git = "https://github.com/paritytech/substrate.git", default-features = false }
runtime_io = { package = "sr-io", git = "https://github.com/paritytech/substrate.git", default-features = false }
traits = { package = "orml-traits", path = "../traits", default-features = false }
utilities = { package = "orml-utilities", path = "../utilities", default-features = false }
[dev-dependencies]
primitives = { package = "substrate-primitives", git = "https://github.com/paritytech/substrate.git", default-features = false }
[features]
default = ["std"]
std = [
"serde",
"codec/std",
"sr-primitives/std",
"srml-support/std",
"srml-system/std",
"runtime_io/std",
"traits/std",
"utilities/std",
]
#![cfg_attr(not(feature = "std"), no_std)]
use sr_primitives::traits::{MaybeSerializeDeserialize, Member, SimpleArithmetic, Zero};
use srml_support::{decl_module, decl_storage, Parameter};
use srml_system as system;
use traits::{DataProvider, PriceProvider};
pub trait Trait: system::Trait {
type CurrencyId: Parameter + Member + Default + Copy + MaybeSerializeDeserialize;
type Price: Parameter + Member + Zero + SimpleArithmetic + Copy + Ord;
type Source: DataProvider<Self::CurrencyId, Self::Price>;
}
mod mock;
mod tests;
decl_storage! {
trait Store for Module<T: Trait> as Prices { }
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin { }
}
impl<T: Trait> Module<T> {}
impl<T: Trait> PriceProvider<T::CurrencyId, T::Price> for Module<T> {
fn get_price(base: T::CurrencyId, quote: T::CurrencyId) -> Option<T::Price> {
if let (Some(base_price), Some(quote_price)) = (T::Source::get(&base), (T::Source::get(&quote))) {
if !base_price.is_zero() {
return Some(quote_price / base_price);
}
}
None
}
}
//! Mocks for the prices module.
#![cfg(test)]
use primitives::H256;
use sr_primitives::{testing::Header, traits::IdentityLookup, Perbill};
use srml_support::{impl_outer_origin, parameter_types};
use super::*;
impl_outer_origin! {
pub enum Origin for Runtime {}
}
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Runtime;
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const MaximumBlockWeight: u32 = 1024;
pub const MaximumBlockLength: u32 = 2 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::one();
}
pub type AccountId = u64;
pub type BlockNumber = u64;
impl system::Trait for Runtime {
type Origin = Origin;
type Index = u64;
type BlockNumber = BlockNumber;
type Call = ();
type Hash = H256;
type Hashing = ::sr_primitives::traits::BlakeTwo256;
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = ();
type BlockHashCount = BlockHashCount;
type MaximumBlockWeight = MaximumBlockWeight;
type MaximumBlockLength = MaximumBlockLength;
type AvailableBlockRatio = AvailableBlockRatio;
type Version = ();
}
type Price = u32;
type CurrencyId = u32;
pub struct MockDataProvider;
impl DataProvider<CurrencyId, Price> for MockDataProvider {
fn get(currency: &CurrencyId) -> Option<Price> {
match currency {
0 => Some(0),
1 => Some(1),
2 => Some(2),
_ => None,
}
}
}
impl Trait for Runtime {
type CurrencyId = CurrencyId;
type Price = Price;
type Source = MockDataProvider;
}
pub type PricesModule = Module<Runtime>;
pub struct ExtBuilder;
impl Default for ExtBuilder {
fn default() -> Self {
ExtBuilder
}
}
impl ExtBuilder {
pub fn build(self) -> runtime_io::TestExternalities {
let t = system::GenesisConfig::default().build_storage::<Runtime>().unwrap();
t.into()
}
}
//! Unit tests for the prices module.
#![cfg(test)]
use super::*;
use mock::{ExtBuilder, PricesModule};
#[test]
fn get_price_should_work() {
ExtBuilder::default().build().execute_with(|| {
assert_eq!(PricesModule::get_price(1, 2), Some(2));
});
}
#[test]
fn price_is_none_should_not_panic() {
ExtBuilder::default().build().execute_with(|| {
assert_eq!(PricesModule::get_price(3, 3), None);
assert_eq!(PricesModule::get_price(3, 1), None);
assert_eq!(PricesModule::get_price(1, 3), None);
});
}
#[test]
fn price_is_zero_should_not_panic() {
ExtBuilder::default().build().execute_with(|| {
assert_eq!(PricesModule::get_price(0, 0), None);
assert_eq!(PricesModule::get_price(1, 0), Some(0));
});
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment