Skip to content

Commit 91f8db2

Browse files
authored
Merge pull request #89 from 0xripleys/0xripleys_stale_price_fn
PriceAccount::get_price_no_older_than impl + happy case test
2 parents 47f8bca + 221a474 commit 91f8db2

File tree

1 file changed

+152
-0
lines changed

1 file changed

+152
-0
lines changed

Diff for: pyth-sdk-solana/src/state.rs

+152
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use pyth_sdk::{
1616
PriceIdentifier,
1717
UnixTimestamp,
1818
};
19+
use solana_program::clock::Clock;
1920
use solana_program::pubkey::Pubkey;
2021
use std::mem::size_of;
2122

@@ -354,6 +355,32 @@ impl PriceAccount {
354355
}
355356
}
356357

358+
/// Get the last valid price as long as it was updated within `slot_threshold` slots of the
359+
/// current slot.
360+
pub fn get_price_no_older_than(&self, clock: &Clock, slot_threshold: u64) -> Option<Price> {
361+
if self.agg.status == PriceStatus::Trading
362+
&& self.agg.pub_slot >= clock.slot - slot_threshold
363+
{
364+
return Some(Price {
365+
conf: self.agg.conf,
366+
expo: self.expo,
367+
price: self.agg.price,
368+
publish_time: self.timestamp,
369+
});
370+
}
371+
372+
if self.prev_slot >= clock.slot - slot_threshold {
373+
return Some(Price {
374+
conf: self.prev_conf,
375+
expo: self.expo,
376+
price: self.prev_price,
377+
publish_time: self.prev_timestamp,
378+
});
379+
}
380+
381+
None
382+
}
383+
357384
pub fn to_price_feed(&self, price_key: &Pubkey) -> PriceFeed {
358385
let status = self.agg.status;
359386

@@ -480,6 +507,7 @@ mod test {
480507
Price,
481508
PriceFeed,
482509
};
510+
use solana_program::clock::Clock;
483511
use solana_program::pubkey::Pubkey;
484512

485513
use super::{
@@ -585,4 +613,128 @@ mod test {
585613
)
586614
);
587615
}
616+
617+
#[test]
618+
fn test_happy_use_latest_price_in_price_no_older_than() {
619+
let price_account = PriceAccount {
620+
expo: 5,
621+
agg: PriceInfo {
622+
price: 10,
623+
conf: 20,
624+
status: PriceStatus::Trading,
625+
pub_slot: 1,
626+
..Default::default()
627+
},
628+
timestamp: 200,
629+
prev_timestamp: 100,
630+
prev_price: 60,
631+
prev_conf: 70,
632+
..Default::default()
633+
};
634+
635+
let clock = Clock {
636+
slot: 5,
637+
..Default::default()
638+
};
639+
640+
assert_eq!(
641+
price_account.get_price_no_older_than(&clock, 4),
642+
Some(Price {
643+
conf: 20,
644+
expo: 5,
645+
price: 10,
646+
publish_time: 200,
647+
})
648+
);
649+
}
650+
651+
#[test]
652+
fn test_happy_use_prev_price_in_price_no_older_than() {
653+
let price_account = PriceAccount {
654+
expo: 5,
655+
agg: PriceInfo {
656+
price: 10,
657+
conf: 20,
658+
status: PriceStatus::Unknown,
659+
pub_slot: 3,
660+
..Default::default()
661+
},
662+
timestamp: 200,
663+
prev_timestamp: 100,
664+
prev_price: 60,
665+
prev_conf: 70,
666+
prev_slot: 1,
667+
..Default::default()
668+
};
669+
670+
let clock = Clock {
671+
slot: 5,
672+
..Default::default()
673+
};
674+
675+
assert_eq!(
676+
price_account.get_price_no_older_than(&clock, 4),
677+
Some(Price {
678+
conf: 70,
679+
expo: 5,
680+
price: 60,
681+
publish_time: 100,
682+
})
683+
);
684+
}
685+
686+
#[test]
687+
fn test_sad_cur_price_unknown_in_price_no_older_than() {
688+
let price_account = PriceAccount {
689+
expo: 5,
690+
agg: PriceInfo {
691+
price: 10,
692+
conf: 20,
693+
status: PriceStatus::Unknown,
694+
pub_slot: 3,
695+
..Default::default()
696+
},
697+
timestamp: 200,
698+
prev_timestamp: 100,
699+
prev_price: 60,
700+
prev_conf: 70,
701+
prev_slot: 1,
702+
..Default::default()
703+
};
704+
705+
let clock = Clock {
706+
slot: 5,
707+
..Default::default()
708+
};
709+
710+
// current price is unknown, prev price is too stale
711+
assert_eq!(price_account.get_price_no_older_than(&clock, 3), None);
712+
}
713+
714+
#[test]
715+
fn test_sad_cur_price_stale_in_price_no_older_than() {
716+
let price_account = PriceAccount {
717+
expo: 5,
718+
agg: PriceInfo {
719+
price: 10,
720+
conf: 20,
721+
status: PriceStatus::Trading,
722+
pub_slot: 3,
723+
..Default::default()
724+
},
725+
timestamp: 200,
726+
prev_timestamp: 100,
727+
prev_price: 60,
728+
prev_conf: 70,
729+
prev_slot: 1,
730+
..Default::default()
731+
};
732+
733+
let clock = Clock {
734+
slot: 5,
735+
..Default::default()
736+
};
737+
738+
assert_eq!(price_account.get_price_no_older_than(&clock, 1), None);
739+
}
588740
}

0 commit comments

Comments
 (0)