[cosmwasm] update contract (#509)
* contract updated * add tests for the logic
This commit is contained in:
parent
f3f28b4214
commit
5d0acc1a76
|
@ -1136,7 +1136,7 @@ name = "p2w-sdk"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hex",
|
"hex",
|
||||||
"pyth-sdk",
|
"pyth-sdk 0.5.0",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1248,7 +1248,7 @@ dependencies = [
|
||||||
"k256 0.9.6",
|
"k256 0.9.6",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"p2w-sdk",
|
"p2w-sdk",
|
||||||
"pyth-sdk-cw",
|
"pyth-sdk 0.7.0",
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
|
@ -1273,14 +1273,14 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyth-sdk-cw"
|
name = "pyth-sdk"
|
||||||
version = "0.2.0"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4f1575db8f501031a810aa5fe5da8ac3868bfcee7ce3deb27d6354c81a5833cb"
|
checksum = "00bf2540203ca3c7a5712fdb8b5897534b7f6a0b6e7b0923ff00466c5f9efcb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cosmwasm-std",
|
"borsh",
|
||||||
"cosmwasm-storage",
|
"borsh-derive",
|
||||||
"pyth-sdk",
|
"hex",
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
|
@ -29,7 +29,7 @@ hex = "0.4.2"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
bigint = "4"
|
bigint = "4"
|
||||||
p2w-sdk = { path = "../../../../third_party/pyth/p2w-sdk/rust" }
|
p2w-sdk = { path = "../../../../third_party/pyth/p2w-sdk/rust" }
|
||||||
pyth-sdk-cw = "0.2.0"
|
pyth-sdk = "0.7.0"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -28,6 +28,9 @@ use {
|
||||||
PriceInfo,
|
PriceInfo,
|
||||||
PythDataSource,
|
PythDataSource,
|
||||||
},
|
},
|
||||||
|
Price,
|
||||||
|
PriceFeed,
|
||||||
|
PriceIdentifier,
|
||||||
},
|
},
|
||||||
cosmwasm_std::{
|
cosmwasm_std::{
|
||||||
coin,
|
coin,
|
||||||
|
@ -51,12 +54,10 @@ use {
|
||||||
WasmMsg,
|
WasmMsg,
|
||||||
WasmQuery,
|
WasmQuery,
|
||||||
},
|
},
|
||||||
p2w_sdk::BatchPriceAttestation,
|
p2w_sdk::{
|
||||||
pyth_sdk_cw::{
|
BatchPriceAttestation,
|
||||||
PriceFeed,
|
PriceAttestation,
|
||||||
PriceIdentifier,
|
|
||||||
PriceStatus,
|
PriceStatus,
|
||||||
ProductIdentifier,
|
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
|
@ -348,22 +349,7 @@ fn process_batch_attestation(
|
||||||
|
|
||||||
// Update prices
|
// Update prices
|
||||||
for price_attestation in batch_attestation.price_attestations.iter() {
|
for price_attestation in batch_attestation.price_attestations.iter() {
|
||||||
let price_feed = PriceFeed::new(
|
let price_feed = create_price_feed_from_price_attestation(price_attestation);
|
||||||
PriceIdentifier::new(price_attestation.price_id.to_bytes()),
|
|
||||||
price_attestation.status,
|
|
||||||
price_attestation.publish_time,
|
|
||||||
price_attestation.expo,
|
|
||||||
price_attestation.max_num_publishers,
|
|
||||||
price_attestation.num_publishers,
|
|
||||||
ProductIdentifier::new(price_attestation.product_id.to_bytes()),
|
|
||||||
price_attestation.price,
|
|
||||||
price_attestation.conf,
|
|
||||||
price_attestation.ema_price,
|
|
||||||
price_attestation.ema_conf,
|
|
||||||
price_attestation.prev_price,
|
|
||||||
price_attestation.prev_conf,
|
|
||||||
price_attestation.prev_publish_time,
|
|
||||||
);
|
|
||||||
|
|
||||||
let attestation_time = Timestamp::from_seconds(price_attestation.attestation_time as u64);
|
let attestation_time = Timestamp::from_seconds(price_attestation.attestation_time as u64);
|
||||||
|
|
||||||
|
@ -378,6 +364,41 @@ fn process_batch_attestation(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_price_feed_from_price_attestation(price_attestation: &PriceAttestation) -> PriceFeed {
|
||||||
|
match price_attestation.status {
|
||||||
|
PriceStatus::Trading => PriceFeed::new(
|
||||||
|
PriceIdentifier::new(price_attestation.price_id.to_bytes()),
|
||||||
|
Price {
|
||||||
|
price: price_attestation.price,
|
||||||
|
conf: price_attestation.conf,
|
||||||
|
expo: price_attestation.expo,
|
||||||
|
publish_time: price_attestation.publish_time,
|
||||||
|
},
|
||||||
|
Price {
|
||||||
|
price: price_attestation.ema_price,
|
||||||
|
conf: price_attestation.ema_conf,
|
||||||
|
expo: price_attestation.expo,
|
||||||
|
publish_time: price_attestation.publish_time,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
_ => PriceFeed::new(
|
||||||
|
PriceIdentifier::new(price_attestation.price_id.to_bytes()),
|
||||||
|
Price {
|
||||||
|
price: price_attestation.prev_price,
|
||||||
|
conf: price_attestation.prev_conf,
|
||||||
|
expo: price_attestation.expo,
|
||||||
|
publish_time: price_attestation.prev_publish_time,
|
||||||
|
},
|
||||||
|
Price {
|
||||||
|
price: price_attestation.ema_price,
|
||||||
|
conf: price_attestation.ema_conf,
|
||||||
|
expo: price_attestation.expo,
|
||||||
|
publish_time: price_attestation.prev_publish_time,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if the price_feed is newer than the stored one.
|
/// Returns true if the price_feed is newer than the stored one.
|
||||||
///
|
///
|
||||||
/// This function returns error only if there be issues in ser/de when it reads from the bucket.
|
/// This function returns error only if there be issues in ser/de when it reads from the bucket.
|
||||||
|
@ -423,42 +444,19 @@ fn update_price_feed_if_new(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(not(feature = "library"), entry_point)]
|
#[cfg_attr(not(feature = "library"), entry_point)]
|
||||||
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
|
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
|
||||||
match msg {
|
match msg {
|
||||||
QueryMsg::PriceFeed { id } => to_binary(&query_price_feed(&deps, env, id.as_ref())?),
|
QueryMsg::PriceFeed { id } => to_binary(&query_price_feed(&deps, id.as_ref())?),
|
||||||
QueryMsg::GetUpdateFee { vaas } => to_binary(&get_update_fee(&deps, &vaas)?),
|
QueryMsg::GetUpdateFee { vaas } => to_binary(&get_update_fee(&deps, &vaas)?),
|
||||||
QueryMsg::GetValidTimePeriod => to_binary(&get_valid_time_period(&deps)?),
|
QueryMsg::GetValidTimePeriod => to_binary(&get_valid_time_period(&deps)?),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn query_price_feed(deps: &Deps, env: Env, address: &[u8]) -> StdResult<PriceFeedResponse> {
|
pub fn query_price_feed(deps: &Deps, address: &[u8]) -> StdResult<PriceFeedResponse> {
|
||||||
let config = config_read(deps.storage).load()?;
|
|
||||||
match price_info_read(deps.storage).load(address) {
|
match price_info_read(deps.storage).load(address) {
|
||||||
Ok(mut price_info) => {
|
Ok(price_info) => Ok(PriceFeedResponse {
|
||||||
let env_time_sec = env.block.time.seconds();
|
|
||||||
let price_pub_time_sec = price_info.price_feed.publish_time as u64;
|
|
||||||
|
|
||||||
// Cases that it will cover:
|
|
||||||
// - This will ensure to set status unknown if the price has become very old and hasn't
|
|
||||||
// updated yet.
|
|
||||||
// - If a price has arrived very late to this chain it will set the status to unknown.
|
|
||||||
// - If a price is coming from future it's tolerated up to VALID_TIME_PERIOD seconds
|
|
||||||
// (using abs diff) but more than that is set to unknown, the reason could be the
|
|
||||||
// clock time drift between the source and target chains.
|
|
||||||
let time_abs_diff = if env_time_sec > price_pub_time_sec {
|
|
||||||
env_time_sec - price_pub_time_sec
|
|
||||||
} else {
|
|
||||||
price_pub_time_sec - env_time_sec
|
|
||||||
};
|
|
||||||
|
|
||||||
if time_abs_diff > config.valid_time_period.as_secs() {
|
|
||||||
price_info.price_feed.status = PriceStatus::Unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(PriceFeedResponse {
|
|
||||||
price_feed: price_info.price_feed,
|
price_feed: price_info.price_feed,
|
||||||
})
|
}),
|
||||||
}
|
|
||||||
Err(_) => Err(PythContractError::PriceFeedNotFound)?,
|
Err(_) => Err(PythContractError::PriceFeedNotFound)?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -489,10 +487,13 @@ pub fn get_valid_time_period(deps: &Deps) -> StdResult<Duration> {
|
||||||
mod test {
|
mod test {
|
||||||
use {
|
use {
|
||||||
super::*,
|
super::*,
|
||||||
crate::governance::GovernanceModule::{
|
crate::{
|
||||||
|
governance::GovernanceModule::{
|
||||||
Executor,
|
Executor,
|
||||||
Target,
|
Target,
|
||||||
},
|
},
|
||||||
|
PriceIdentifier,
|
||||||
|
},
|
||||||
cosmwasm_std::{
|
cosmwasm_std::{
|
||||||
coins,
|
coins,
|
||||||
from_binary,
|
from_binary,
|
||||||
|
@ -512,6 +513,7 @@ mod test {
|
||||||
SystemResult,
|
SystemResult,
|
||||||
Uint128,
|
Uint128,
|
||||||
},
|
},
|
||||||
|
p2w_sdk::PriceAttestation,
|
||||||
std::time::Duration,
|
std::time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -635,9 +637,17 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_price_feed(expo: i32) -> PriceFeed {
|
fn create_price_feed(expo: i32) -> PriceFeed {
|
||||||
let mut price_feed = PriceFeed::default();
|
PriceFeed::new(
|
||||||
price_feed.expo = expo;
|
PriceIdentifier::new([0u8; 32]),
|
||||||
price_feed
|
Price {
|
||||||
|
expo,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Price {
|
||||||
|
expo,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_data_sources(
|
fn create_data_sources(
|
||||||
|
@ -681,6 +691,210 @@ mod test {
|
||||||
update_price_feeds(deps.as_mut(), env, info, &[msg])
|
update_price_feeds(deps.as_mut(), env, info, &[msg])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_process_batch_attestation_empty_array() {
|
||||||
|
let (mut deps, env) = setup_test();
|
||||||
|
let attestations = BatchPriceAttestation {
|
||||||
|
price_attestations: vec![],
|
||||||
|
};
|
||||||
|
let (total_attestations, new_attestations) =
|
||||||
|
process_batch_attestation(&mut deps.as_mut(), &env, &attestations).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(total_attestations, 0);
|
||||||
|
assert_eq!(new_attestations, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_price_feed_from_price_attestation_status_trading() {
|
||||||
|
let price_attestation = PriceAttestation {
|
||||||
|
price_id: p2w_sdk::Identifier::new([0u8; 32]),
|
||||||
|
price: 100,
|
||||||
|
conf: 100,
|
||||||
|
expo: 100,
|
||||||
|
ema_price: 100,
|
||||||
|
ema_conf: 100,
|
||||||
|
status: PriceStatus::Trading,
|
||||||
|
attestation_time: 100,
|
||||||
|
publish_time: 100,
|
||||||
|
prev_publish_time: 99,
|
||||||
|
prev_price: 99,
|
||||||
|
prev_conf: 99,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let price_feed = create_price_feed_from_price_attestation(&price_attestation);
|
||||||
|
let price = price_feed.get_price_unchecked();
|
||||||
|
let ema_price = price_feed.get_ema_price_unchecked();
|
||||||
|
|
||||||
|
// for price
|
||||||
|
assert_eq!(price.price, 100);
|
||||||
|
assert_eq!(price.conf, 100);
|
||||||
|
assert_eq!(price.expo, 100);
|
||||||
|
assert_eq!(price.publish_time, 100);
|
||||||
|
|
||||||
|
// for ema
|
||||||
|
assert_eq!(ema_price.price, 100);
|
||||||
|
assert_eq!(ema_price.conf, 100);
|
||||||
|
assert_eq!(ema_price.expo, 100);
|
||||||
|
assert_eq!(ema_price.publish_time, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_price_feed_from_price_attestation_status_unknown() {
|
||||||
|
test_create_price_feed_from_price_attestation_not_trading(PriceStatus::Unknown)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_price_feed_from_price_attestation_status_halted() {
|
||||||
|
test_create_price_feed_from_price_attestation_not_trading(PriceStatus::Halted)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_price_feed_from_price_attestation_status_auction() {
|
||||||
|
test_create_price_feed_from_price_attestation_not_trading(PriceStatus::Auction)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_create_price_feed_from_price_attestation_not_trading(status: PriceStatus) {
|
||||||
|
let price_attestation = PriceAttestation {
|
||||||
|
price_id: p2w_sdk::Identifier::new([0u8; 32]),
|
||||||
|
price: 100,
|
||||||
|
conf: 100,
|
||||||
|
expo: 100,
|
||||||
|
ema_price: 100,
|
||||||
|
ema_conf: 100,
|
||||||
|
status,
|
||||||
|
attestation_time: 100,
|
||||||
|
publish_time: 100,
|
||||||
|
prev_publish_time: 99,
|
||||||
|
prev_price: 99,
|
||||||
|
prev_conf: 99,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let price_feed = create_price_feed_from_price_attestation(&price_attestation);
|
||||||
|
|
||||||
|
let price = price_feed.get_price_unchecked();
|
||||||
|
let ema_price = price_feed.get_ema_price_unchecked();
|
||||||
|
|
||||||
|
// for price
|
||||||
|
assert_eq!(price.price, 99);
|
||||||
|
assert_eq!(price.conf, 99);
|
||||||
|
assert_eq!(price.expo, 100);
|
||||||
|
assert_eq!(price.publish_time, 99);
|
||||||
|
|
||||||
|
// for ema
|
||||||
|
assert_eq!(ema_price.price, 100);
|
||||||
|
assert_eq!(ema_price.conf, 100);
|
||||||
|
assert_eq!(ema_price.expo, 100);
|
||||||
|
assert_eq!(ema_price.publish_time, 99);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is testing the function process_batch_attestation
|
||||||
|
// process_batch_attestation is calling update_price_feed_if_new
|
||||||
|
// changes to update_price_feed_if_new might cause this test
|
||||||
|
#[test]
|
||||||
|
fn test_process_batch_attestation_status_not_trading() {
|
||||||
|
let (mut deps, env) = setup_test();
|
||||||
|
|
||||||
|
let price_attestation = PriceAttestation {
|
||||||
|
price_id: p2w_sdk::Identifier::new([0u8; 32]),
|
||||||
|
price: 100,
|
||||||
|
conf: 100,
|
||||||
|
expo: 100,
|
||||||
|
ema_price: 100,
|
||||||
|
ema_conf: 100,
|
||||||
|
status: PriceStatus::Auction,
|
||||||
|
attestation_time: 100,
|
||||||
|
publish_time: 100,
|
||||||
|
prev_publish_time: 99,
|
||||||
|
prev_price: 99,
|
||||||
|
prev_conf: 99,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let attestations = BatchPriceAttestation {
|
||||||
|
price_attestations: vec![price_attestation],
|
||||||
|
};
|
||||||
|
let (total_attestations, new_attestations) =
|
||||||
|
process_batch_attestation(&mut deps.as_mut(), &env, &attestations).unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
let stored_price_feed = price_info_read(&deps.storage)
|
||||||
|
.load(&[0u8; 32])
|
||||||
|
.unwrap()
|
||||||
|
.price_feed;
|
||||||
|
let price = stored_price_feed.get_price_unchecked();
|
||||||
|
let ema_price = stored_price_feed.get_ema_price_unchecked();
|
||||||
|
|
||||||
|
assert_eq!(total_attestations, 1);
|
||||||
|
assert_eq!(new_attestations, 1);
|
||||||
|
|
||||||
|
// for price
|
||||||
|
assert_eq!(price.price, 99);
|
||||||
|
assert_eq!(price.conf, 99);
|
||||||
|
assert_eq!(price.expo, 100);
|
||||||
|
assert_eq!(price.publish_time, 99);
|
||||||
|
|
||||||
|
// for ema
|
||||||
|
assert_eq!(ema_price.price, 100);
|
||||||
|
assert_eq!(ema_price.conf, 100);
|
||||||
|
assert_eq!(ema_price.expo, 100);
|
||||||
|
assert_eq!(ema_price.publish_time, 99);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is testing the function process_batch_attestation
|
||||||
|
// process_batch_attestation is calling update_price_feed_if_new
|
||||||
|
// changes to update_price_feed_if_new might affect this test
|
||||||
|
#[test]
|
||||||
|
fn test_process_batch_attestation_status_trading() {
|
||||||
|
let (mut deps, env) = setup_test();
|
||||||
|
|
||||||
|
let price_attestation = PriceAttestation {
|
||||||
|
price_id: p2w_sdk::Identifier::new([0u8; 32]),
|
||||||
|
price: 100,
|
||||||
|
conf: 100,
|
||||||
|
expo: 100,
|
||||||
|
ema_price: 100,
|
||||||
|
ema_conf: 100,
|
||||||
|
status: PriceStatus::Trading,
|
||||||
|
attestation_time: 100,
|
||||||
|
publish_time: 100,
|
||||||
|
prev_publish_time: 99,
|
||||||
|
prev_price: 99,
|
||||||
|
prev_conf: 99,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let attestations = BatchPriceAttestation {
|
||||||
|
price_attestations: vec![price_attestation],
|
||||||
|
};
|
||||||
|
let (total_attestations, new_attestations) =
|
||||||
|
process_batch_attestation(&mut deps.as_mut(), &env, &attestations).unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
let stored_price_feed = price_info_read(&deps.storage)
|
||||||
|
.load(&[0u8; 32])
|
||||||
|
.unwrap()
|
||||||
|
.price_feed;
|
||||||
|
let price = stored_price_feed.get_price_unchecked();
|
||||||
|
let ema_price = stored_price_feed.get_ema_price_unchecked();
|
||||||
|
|
||||||
|
assert_eq!(total_attestations, 1);
|
||||||
|
assert_eq!(new_attestations, 1);
|
||||||
|
|
||||||
|
// for price
|
||||||
|
assert_eq!(price.price, 100);
|
||||||
|
assert_eq!(price.conf, 100);
|
||||||
|
assert_eq!(price.expo, 100);
|
||||||
|
assert_eq!(price.publish_time, 100);
|
||||||
|
|
||||||
|
// for ema
|
||||||
|
assert_eq!(ema_price.price, 100);
|
||||||
|
assert_eq!(ema_price.conf, 100);
|
||||||
|
assert_eq!(ema_price.expo, 100);
|
||||||
|
assert_eq!(ema_price.publish_time, 100);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_verify_vaa_sender_ok() {
|
fn test_verify_vaa_sender_ok() {
|
||||||
let result = apply_price_update(
|
let result = apply_price_update(
|
||||||
|
@ -828,102 +1042,47 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_price_info_ok_trading() {
|
fn test_query_price_info_ok() {
|
||||||
let (mut deps, mut env) = setup_test();
|
let (mut deps, _env) = setup_test();
|
||||||
|
|
||||||
let address = b"123".as_ref();
|
let address = b"123".as_ref();
|
||||||
|
|
||||||
let mut dummy_price_info = PriceInfo::default();
|
let dummy_price_info = PriceInfo {
|
||||||
dummy_price_info.price_feed.publish_time = 80;
|
price_feed: PriceFeed::new(
|
||||||
dummy_price_info.price_feed.status = PriceStatus::Trading;
|
PriceIdentifier::new([0u8; 32]),
|
||||||
|
Price {
|
||||||
|
price: 300,
|
||||||
|
conf: 301,
|
||||||
|
expo: 302,
|
||||||
|
publish_time: 303,
|
||||||
|
},
|
||||||
|
Price {
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
price_info(&mut deps.storage)
|
price_info(&mut deps.storage)
|
||||||
.save(address, &dummy_price_info)
|
.save(address, &dummy_price_info)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
env.block.time = Timestamp::from_seconds(80 + VALID_TIME_PERIOD.as_secs());
|
let price_feed = query_price_feed(&deps.as_ref(), address)
|
||||||
|
|
||||||
let price_feed = query_price_feed(&deps.as_ref(), env, address)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.price_feed;
|
.price_feed;
|
||||||
|
|
||||||
assert_eq!(price_feed.status, PriceStatus::Trading);
|
assert_eq!(price_feed.get_price_unchecked().price, 300);
|
||||||
}
|
assert_eq!(price_feed.get_price_unchecked().conf, 301);
|
||||||
|
assert_eq!(price_feed.get_price_unchecked().expo, 302);
|
||||||
#[test]
|
assert_eq!(price_feed.get_price_unchecked().publish_time, 303);
|
||||||
fn test_query_price_info_ok_stale_past() {
|
|
||||||
let (mut deps, mut env) = setup_test();
|
|
||||||
let address = b"123".as_ref();
|
|
||||||
|
|
||||||
let mut dummy_price_info = PriceInfo::default();
|
|
||||||
dummy_price_info.price_feed.publish_time = 500;
|
|
||||||
dummy_price_info.price_feed.status = PriceStatus::Trading;
|
|
||||||
|
|
||||||
price_info(&mut deps.storage)
|
|
||||||
.save(address, &dummy_price_info)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
env.block.time = Timestamp::from_seconds(500 + VALID_TIME_PERIOD.as_secs() + 1);
|
|
||||||
|
|
||||||
let price_feed = query_price_feed(&deps.as_ref(), env, address)
|
|
||||||
.unwrap()
|
|
||||||
.price_feed;
|
|
||||||
|
|
||||||
assert_eq!(price_feed.status, PriceStatus::Unknown);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_query_price_info_ok_trading_future() {
|
|
||||||
let (mut deps, mut env) = setup_test();
|
|
||||||
|
|
||||||
let address = b"123".as_ref();
|
|
||||||
|
|
||||||
let mut dummy_price_info = PriceInfo::default();
|
|
||||||
dummy_price_info.price_feed.publish_time = 500;
|
|
||||||
dummy_price_info.price_feed.status = PriceStatus::Trading;
|
|
||||||
|
|
||||||
price_info(&mut deps.storage)
|
|
||||||
.save(address, &dummy_price_info)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
env.block.time = Timestamp::from_seconds(500 - VALID_TIME_PERIOD.as_secs());
|
|
||||||
|
|
||||||
let price_feed = query_price_feed(&deps.as_ref(), env, address)
|
|
||||||
.unwrap()
|
|
||||||
.price_feed;
|
|
||||||
|
|
||||||
assert_eq!(price_feed.status, PriceStatus::Trading);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_query_price_info_ok_stale_future() {
|
|
||||||
let (mut deps, mut env) = setup_test();
|
|
||||||
|
|
||||||
let address = b"123".as_ref();
|
|
||||||
|
|
||||||
let mut dummy_price_info = PriceInfo::default();
|
|
||||||
dummy_price_info.price_feed.publish_time = 500;
|
|
||||||
dummy_price_info.price_feed.status = PriceStatus::Trading;
|
|
||||||
|
|
||||||
price_info(&mut deps.storage)
|
|
||||||
.save(address, &dummy_price_info)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
env.block.time = Timestamp::from_seconds(500 - VALID_TIME_PERIOD.as_secs() - 1);
|
|
||||||
|
|
||||||
let price_feed = query_price_feed(&deps.as_ref(), env, address)
|
|
||||||
.unwrap()
|
|
||||||
.price_feed;
|
|
||||||
|
|
||||||
assert_eq!(price_feed.status, PriceStatus::Unknown);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_price_info_err_not_found() {
|
fn test_query_price_info_err_not_found() {
|
||||||
let (deps, env) = setup_test();
|
let deps = setup_test().0;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
query_price_feed(&deps.as_ref(), env, b"123".as_ref()),
|
query_price_feed(&deps.as_ref(), b"123".as_ref()),
|
||||||
Err(PythContractError::PriceFeedNotFound.into())
|
Err(PythContractError::PriceFeedNotFound.into())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,3 +6,10 @@ pub mod error;
|
||||||
pub mod governance;
|
pub mod governance;
|
||||||
pub mod msg;
|
pub mod msg;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
|
|
||||||
|
pub use pyth_sdk::{
|
||||||
|
Price,
|
||||||
|
PriceFeed,
|
||||||
|
PriceIdentifier,
|
||||||
|
ProductIdentifier,
|
||||||
|
};
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use {
|
use {
|
||||||
crate::state::PythDataSource,
|
crate::{
|
||||||
|
state::PythDataSource,
|
||||||
|
PriceFeed,
|
||||||
|
PriceIdentifier,
|
||||||
|
},
|
||||||
cosmwasm_std::{
|
cosmwasm_std::{
|
||||||
Binary,
|
Binary,
|
||||||
Coin,
|
Coin,
|
||||||
},
|
},
|
||||||
pyth_sdk_cw::{
|
|
||||||
PriceFeed,
|
|
||||||
PriceIdentifier,
|
|
||||||
},
|
|
||||||
schemars::JsonSchema,
|
schemars::JsonSchema,
|
||||||
serde::{
|
serde::{
|
||||||
Deserialize,
|
Deserialize,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use {
|
use {
|
||||||
|
crate::PriceFeed,
|
||||||
cosmwasm_std::{
|
cosmwasm_std::{
|
||||||
Addr,
|
Addr,
|
||||||
Binary,
|
Binary,
|
||||||
|
@ -16,7 +17,6 @@ use {
|
||||||
ReadonlySingleton,
|
ReadonlySingleton,
|
||||||
Singleton,
|
Singleton,
|
||||||
},
|
},
|
||||||
pyth_sdk_cw::PriceFeed,
|
|
||||||
schemars::JsonSchema,
|
schemars::JsonSchema,
|
||||||
serde::{
|
serde::{
|
||||||
Deserialize,
|
Deserialize,
|
||||||
|
|
Loading…
Reference in New Issue