|
|
|
@ -28,6 +28,9 @@ use {
|
|
|
|
|
PriceInfo,
|
|
|
|
|
PythDataSource,
|
|
|
|
|
},
|
|
|
|
|
Price,
|
|
|
|
|
PriceFeed,
|
|
|
|
|
PriceIdentifier,
|
|
|
|
|
},
|
|
|
|
|
cosmwasm_std::{
|
|
|
|
|
coin,
|
|
|
|
@ -51,12 +54,10 @@ use {
|
|
|
|
|
WasmMsg,
|
|
|
|
|
WasmQuery,
|
|
|
|
|
},
|
|
|
|
|
p2w_sdk::BatchPriceAttestation,
|
|
|
|
|
pyth_sdk_cw::{
|
|
|
|
|
PriceFeed,
|
|
|
|
|
PriceIdentifier,
|
|
|
|
|
p2w_sdk::{
|
|
|
|
|
BatchPriceAttestation,
|
|
|
|
|
PriceAttestation,
|
|
|
|
|
PriceStatus,
|
|
|
|
|
ProductIdentifier,
|
|
|
|
|
},
|
|
|
|
|
std::{
|
|
|
|
|
collections::HashSet,
|
|
|
|
@ -348,22 +349,7 @@ fn process_batch_attestation(
|
|
|
|
|
|
|
|
|
|
// Update prices
|
|
|
|
|
for price_attestation in batch_attestation.price_attestations.iter() {
|
|
|
|
|
let price_feed = PriceFeed::new(
|
|
|
|
|
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 price_feed = create_price_feed_from_price_attestation(price_attestation);
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
///
|
|
|
|
|
/// 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)]
|
|
|
|
|
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
|
|
|
|
|
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
|
|
|
|
|
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::GetValidTimePeriod => to_binary(&get_valid_time_period(&deps)?),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn query_price_feed(deps: &Deps, env: Env, address: &[u8]) -> StdResult<PriceFeedResponse> {
|
|
|
|
|
let config = config_read(deps.storage).load()?;
|
|
|
|
|
pub fn query_price_feed(deps: &Deps, address: &[u8]) -> StdResult<PriceFeedResponse> {
|
|
|
|
|
match price_info_read(deps.storage).load(address) {
|
|
|
|
|
Ok(mut price_info) => {
|
|
|
|
|
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 {
|
|
|
|
|
Ok(price_info) => Ok(PriceFeedResponse {
|
|
|
|
|
price_feed: price_info.price_feed,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
Err(_) => Err(PythContractError::PriceFeedNotFound)?,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -489,10 +487,13 @@ pub fn get_valid_time_period(deps: &Deps) -> StdResult<Duration> {
|
|
|
|
|
mod test {
|
|
|
|
|
use {
|
|
|
|
|
super::*,
|
|
|
|
|
crate::governance::GovernanceModule::{
|
|
|
|
|
crate::{
|
|
|
|
|
governance::GovernanceModule::{
|
|
|
|
|
Executor,
|
|
|
|
|
Target,
|
|
|
|
|
},
|
|
|
|
|
PriceIdentifier,
|
|
|
|
|
},
|
|
|
|
|
cosmwasm_std::{
|
|
|
|
|
coins,
|
|
|
|
|
from_binary,
|
|
|
|
@ -512,6 +513,7 @@ mod test {
|
|
|
|
|
SystemResult,
|
|
|
|
|
Uint128,
|
|
|
|
|
},
|
|
|
|
|
p2w_sdk::PriceAttestation,
|
|
|
|
|
std::time::Duration,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -635,9 +637,17 @@ mod test {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn create_price_feed(expo: i32) -> PriceFeed {
|
|
|
|
|
let mut price_feed = PriceFeed::default();
|
|
|
|
|
price_feed.expo = expo;
|
|
|
|
|
price_feed
|
|
|
|
|
PriceFeed::new(
|
|
|
|
|
PriceIdentifier::new([0u8; 32]),
|
|
|
|
|
Price {
|
|
|
|
|
expo,
|
|
|
|
|
..Default::default()
|
|
|
|
|
},
|
|
|
|
|
Price {
|
|
|
|
|
expo,
|
|
|
|
|
..Default::default()
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn create_data_sources(
|
|
|
|
@ -681,6 +691,210 @@ mod test {
|
|
|
|
|
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]
|
|
|
|
|
fn test_verify_vaa_sender_ok() {
|
|
|
|
|
let result = apply_price_update(
|
|
|
|
@ -828,102 +1042,47 @@ mod test {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_query_price_info_ok_trading() {
|
|
|
|
|
let (mut deps, mut env) = setup_test();
|
|
|
|
|
fn test_query_price_info_ok() {
|
|
|
|
|
let (mut deps, _env) = setup_test();
|
|
|
|
|
|
|
|
|
|
let address = b"123".as_ref();
|
|
|
|
|
|
|
|
|
|
let mut dummy_price_info = PriceInfo::default();
|
|
|
|
|
dummy_price_info.price_feed.publish_time = 80;
|
|
|
|
|
dummy_price_info.price_feed.status = PriceStatus::Trading;
|
|
|
|
|
let dummy_price_info = PriceInfo {
|
|
|
|
|
price_feed: PriceFeed::new(
|
|
|
|
|
PriceIdentifier::new([0u8; 32]),
|
|
|
|
|
Price {
|
|
|
|
|
price: 300,
|
|
|
|
|
conf: 301,
|
|
|
|
|
expo: 302,
|
|
|
|
|
publish_time: 303,
|
|
|
|
|
},
|
|
|
|
|
Price {
|
|
|
|
|
..Default::default()
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
..Default::default()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
price_info(&mut deps.storage)
|
|
|
|
|
.save(address, &dummy_price_info)
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
env.block.time = Timestamp::from_seconds(80 + VALID_TIME_PERIOD.as_secs());
|
|
|
|
|
|
|
|
|
|
let price_feed = query_price_feed(&deps.as_ref(), env, address)
|
|
|
|
|
let price_feed = query_price_feed(&deps.as_ref(), address)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.price_feed;
|
|
|
|
|
|
|
|
|
|
assert_eq!(price_feed.status, PriceStatus::Trading);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
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);
|
|
|
|
|
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);
|
|
|
|
|
assert_eq!(price_feed.get_price_unchecked().publish_time, 303);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_query_price_info_err_not_found() {
|
|
|
|
|
let (deps, env) = setup_test();
|
|
|
|
|
let deps = setup_test().0;
|
|
|
|
|
|
|
|
|
|
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())
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|