@ -11,21 +11,17 @@ use rocket::time::format_description::FormatItem;
use rocket ::time ::macros ::format_description ;
use rocket ::time ::{ Duration , OffsetDateTime , Time } ;
use serde ::{ Deserialize , Serialize } ;
use std ::collections ::HashSet ;
use std ::convert ::TryFrom ;
/// Where `olivia` is located.
const OLIVIA_URL : & str = "https://h00.ooo" ;
use std ::collections ::{ HashMap , HashSet } ;
const OLIVIA_EVENT_TIME_FORMAT : & [ FormatItem ] =
format_description ! ( "[year]-[month]-[day]T[hour]:[minute]:[second]" ) ;
pub struct Actor < CFD , M >
where
CFD : xtra ::Handler < Announcements > + xtra ::Handler < A ttestation > ,
CFD : xtra ::Handler < Attestation > ,
M : xtra ::Handler < Attestation > ,
{
latest_announcements : Option < [ Announcement ; 24 ] > ,
latest_announcements : HashMap < OracleEventId , Announcement > ,
pending_attestations : HashSet < OracleEventId > ,
cfd_actor_address : xtra ::Address < CFD > ,
monitor_actor_address : xtra ::Address < M > ,
@ -33,7 +29,7 @@ where
impl < CFD , M > Actor < CFD , M >
where
CFD : xtra ::Handler < Announcements > + xtra ::Handler < A ttestation > ,
CFD : xtra ::Handler < Attestation > ,
M : xtra ::Handler < Attestation > ,
{
pub fn new (
@ -69,7 +65,7 @@ where
}
Self {
latest_announcements : None ,
latest_announcements : HashMap ::new ( ) ,
pending_attestations ,
cfd_actor_address ,
monitor_actor_address ,
@ -88,36 +84,29 @@ where
}
async fn update_latest_announcements ( & mut self ) -> Result < ( ) > {
let new_announcements = next_url s ( )
let new_announcements = next_id s ( )
. into_iter ( )
. map ( | event_url | async move {
let response = reqwest ::get ( event_url . clone ( ) )
. map ( | event_id | async move {
let url = event_id . to_olivia_url ( ) ;
let response = reqwest ::get ( url . clone ( ) )
. await
. with_context ( | | format ! ( "Failed to GET {}" , event_ url) ) ? ;
. with_context ( | | format ! ( "Failed to GET {}" , url ) ) ? ;
if ! response . status ( ) . is_success ( ) {
anyhow ::bail ! ( "GET {} responded with {}" , event_ url, response . status ( ) ) ;
anyhow ::bail ! ( "GET {} responded with {}" , url , response . status ( ) ) ;
}
let announcement = response
. json ::< Announcement > ( )
. await
. context ( "Failed to deserialize as Announcement" ) ? ;
Result ::< _ , anyhow ::Error > ::Ok ( announcement )
Result ::< _ , anyhow ::Error > ::Ok ( ( event_id , announcement ) )
} )
. collect ::< FuturesOrdered < _ > > ( )
. try_collect ::< Vec < _ > > ( )
. try_collect ::< HashMap < OracleEventId , Announcement > > ( )
. await ? ;
let new_announcements = < [ Announcement ; 24 ] > ::try_from ( new_announcements )
. map_err ( | vec | anyhow ::anyhow ! ( "wrong number of announcements: {}" , vec . len ( ) ) ) ? ;
if self . latest_announcements . as_ref ( ) ! = Some ( & new_announcements ) {
self . latest_announcements = Some ( new_announcements . clone ( ) ) ;
self . cfd_actor_address
. do_send_async ( Announcements ( new_announcements ) )
. await ? ;
}
self . latest_announcements = new_announcements ;
Ok ( ( ) )
}
@ -126,7 +115,7 @@ where
let pending_attestations = self . pending_attestations . clone ( ) ;
for event_id in pending_attestations . into_iter ( ) {
{
let res = match reqwest ::get ( format ! ( "{}{}" , OLIVIA_URL , event_id ) ) . await {
let res = match reqwest ::get ( event_id . to_olivia_url ( ) ) . await {
Ok ( res ) if res . status ( ) . is_success ( ) = > res ,
Ok ( res ) if res . status ( ) = = StatusCode ::NOT_FOUND = > {
tracing ::trace ! ( "Attestation not ready yet" ) ;
@ -165,11 +154,15 @@ where
tracing ::trace ! ( "Event {} already being monitored" , event_id ) ;
}
}
pub fn handle_get_announcement ( & self , event_id : OracleEventId ) -> Option < Announcement > {
self . latest_announcements . get ( & event_id ) . cloned ( )
}
}
impl < CFD , M > xtra ::Actor for Actor < CFD , M >
where
CFD : xtra ::Handler < Announcements > + xtra ::Handler < A ttestation > ,
CFD : xtra ::Handler < Attestation > ,
M : xtra ::Handler < Attestation > ,
{
}
@ -183,7 +176,7 @@ impl xtra::Message for Sync {
#[ async_trait ]
impl < CFD , M > xtra ::Handler < Sync > for Actor < CFD , M >
where
CFD : xtra ::Handler < Announcements > + xtra ::Handler < A ttestation > ,
CFD : xtra ::Handler < Attestation > ,
M : xtra ::Handler < Attestation > ,
{
async fn handle ( & mut self , _ : Sync , _ctx : & mut xtra ::Context < Self > ) {
@ -202,7 +195,7 @@ impl xtra::Message for MonitorEvent {
#[ async_trait ]
impl < CFD , M > xtra ::Handler < MonitorEvent > for Actor < CFD , M >
where
CFD : xtra ::Handler < Announcements > + xtra ::Handler < A ttestation > ,
CFD : xtra ::Handler < Attestation > ,
M : xtra ::Handler < Attestation > ,
{
async fn handle ( & mut self , msg : MonitorEvent , _ctx : & mut xtra ::Context < Self > ) {
@ -210,12 +203,30 @@ where
}
}
#[ derive(Debug, Clone) ]
pub struct GetAnnouncement ( pub OracleEventId ) ;
#[ async_trait ]
impl < CFD , M > xtra ::Handler < GetAnnouncement > for Actor < CFD , M >
where
CFD : xtra ::Handler < Attestation > ,
M : xtra ::Handler < Attestation > ,
{
async fn handle (
& mut self ,
msg : GetAnnouncement ,
_ctx : & mut xtra ::Context < Self > ,
) -> Option < Announcement > {
self . handle_get_announcement ( msg . 0 )
}
}
/// Construct the URL of the next 24 `BitMEX/BXBT` hourly events
/// `olivia` will attest to.
fn next_urls ( ) -> Vec < String > {
fn next_id s ( ) -> Vec < OracleEventId > {
next_24_hours ( OffsetDateTime ::now_utc ( ) )
. into_iter ( )
. map ( event_url )
. map ( event_id )
. collect ( )
}
@ -224,14 +235,23 @@ fn next_24_hours(datetime: OffsetDateTime) -> Vec<OffsetDateTime> {
( 1 . . = 24 ) . map ( | i | adjusted + Duration ::hours ( i ) ) . collect ( )
}
#[ allow(dead_code) ]
pub fn next_announcement_after ( timestamp : OffsetDateTime ) -> OracleEventId {
// always ceil to next hour
let adjusted =
timestamp . replace_time ( Time ::from_hms ( timestamp . hour ( ) + 1 , 0 , 0 ) . expect ( "in_range" ) ) ;
event_id ( adjusted )
}
/// Construct the URL of `olivia`'s `BitMEX/BXBT` event to be attested
/// for at the time indicated by the argument `datetime`.
fn event_url ( datetime : OffsetDateTime ) -> String {
fn event_id ( datetime : OffsetDateTime ) -> OracleEventId {
let datetime = datetime
. format ( & OLIVIA_EVENT_TIME_FORMAT )
. expect ( "valid formatter for datetime" ) ;
format ! ( "{}/x/BitMEX/BXBT/{}.price[n:20]" , OLIVIA_URL , datetime )
OracleEventId ( format ! ( "/x/BitMEX/BXBT/{}.price?n=20" , datetime ) )
}
#[ derive(Debug, Clone, serde::Deserialize, PartialEq) ]
@ -255,9 +275,6 @@ impl From<Announcement> for cfd_protocol::Announcement {
}
}
#[ derive(Debug, Clone) ]
pub struct Announcements ( pub [ Announcement ; 24 ] ) ;
// TODO: Implement real deserialization once price attestation is
// implemented in `olivia`
#[ derive(Debug, Clone, Serialize, Deserialize, PartialEq) ]
@ -268,8 +285,8 @@ pub struct Attestation {
pub scalars : Vec < SecretKey > ,
}
impl xtra ::Message for Announcements {
type Result = ( ) ;
impl xtra ::Message for Get Announcement {
type Result = Option < Announcement > ;
}
impl xtra ::Message for Attestation {
@ -394,11 +411,11 @@ mod olivia_api {
#[ test ]
fn deserialize_announcement ( ) {
let json = r#"{"announcement":{"oracle_event":{"encoding":"json","data":"{\"id\":\"/x/BitMEX/BXBT/2021-10-04T22:00:00.price[n:20] \",\"expected-outcome-time\":\"2021-10-04T22:00:00\",\"descriptor\":{\"type\":\"digit-decomposition\",\"is_signed\":false,\"n_digits\":20,\"unit\":null},\"schemes\":{\"olivia-v1\":{\"nonces\":[\"8d72028eeaf4b85aec0f750f05a4a320cac193f5d8494bfe05cd4b29f3df4239\",\"77240f79a0042adae35ad24284b18b906f17a979fcec3c90d11ed682c6b9261e\",\"e42332407b58f7c6e860b886acfe8d19636fb21a1e20722522206b30a2424d89\",\"ce1158e02dc265751887edae9bdcf8d06ad40489c7643324ccb6a46e4e740f5a\",\"52a5751a43046217bcf009df917c24e400c6da645474a654a5f89499df7154d4\",\"e7b97360a952c2b239d1bfeaade73da4a38e83d20f5deb5b054bcbbc78c91e40\",\"612ce13fd61be10e8de77976c6d479865bc3d2ebdc212946f1e5d93e3f504d2e\",\"e40decd0ea27003b873dde9b6be02f1b344e7e74bc5299144fa0f37b1cf12e90\",\"281a829e05d5f8b96eaf620c7b26115bfb29013d503b6bb40068cdb413a87197\",\"3c87eed0a3852953b0f3ac8a47ff194de66c7229c42e6578e0f6464ba240f033\",\"29028525277cb39adab9ac145d6ce61f2e10306e7b6ce95970a22ea3b201a5d9\",\"20971b4d2069d8b9b5c5678290ab7624821cf32ffe32a20d58428ca90da02523\",\"667a9af33ed45bfb5c4fc7adacea15bbe26df90e0df7dd5b8235e14dfd0da38f\",\"224df2d2706b5c629173b84927e2b206dad7a72e132eb86912d9464dad4b41d1\",\"85296962b9d1f7699c248467ce94ce4aa6e00d26fe01af3a507bcd3a303855d4\",\"96813c9f4d136f0f64be79e73d657fecc43d8b6c463163913b4fa31f96b1ae6b\",\"9d5971aa596923560b12f367fb2f4e192d8906bf6ed3a58b093f50d3cad27493\",\"b7f2c135db80cee02b4436557c78dc1dd2343c1a3688ba736c6c40e9531547b6\",\"bd6236fc18f1dc96f9755cc5c435adaf3952ff810d3ad5b96a03464a61eecfde\",\"20b2922ce326e5e2f4ed683723a879e467edd1068bf5a3c4f331525216227abe\"]},\"ecdsa-v1\":{}}}"},"signature":"743ed9900aba5a1ba3ba9d862628cdc5cca27974c40c4ab64618709021b3fbb13216a3efc733be260025da487ae9b63a8290d555bdc8da6324deff149fc7b110"},"attestation":{"outcome":"48935","schemes":{"olivia-v1":{"scalars":["1327b3bd0f1faf45d6fed6c96d0c158da22a2033a6fed98bed036df0a4eef484","72659c6beebd45e299bc4260a1c1ffd708ed33771459563502f25fc4f537cef6","051eec45417e2493f36b13f4fdf83fb981be42901bf876e4ac594ff2daa4c30e","847d8c7204335b1dbc2078cfb56118b1977162e7b997f2029f490929bbd603c7","5b695846292b6d69d9beedcc7dd2b7e49fd49ec4fcf262d9357f52b049fa8998","368a1f2206fcedcde37381b272fa5a400f55ef720ee2b8fff558e3b0dce729ee","9e1c015c0e827037f18681937764f4973ef22d6fbbd82f6bde3bf5198f6b8999","fe9620c9ad9862b5615f8cf3e20e8d9f422e7410914ce8af2b8bad8937b75738","44297ae831898f8f5c7e57720f233a717e9034a5b41d6c89cce6d9058c4ee086","587fc9b71f1920df825138f00bc625e6610e61b1fec0a64e2800fc05b3a2e96d","010377f6b885ae48d62e7863c8038240aafe0a7fb97d58ac6173186c95335955","5243782226739f59b0ac01a56a63537289ffe81b87b33eca42f89f7848623520","06184cb8e46b5d520cd9b5829feeb73b688d61e5f37b91ff88d3f9b8664a5cdd","fe48f4b568bb501732c4e8f1919940c9bca0ad909f4624658b14664af823ccfe","0841f121e7a54f88a844227cd0ae62171b49d004120c16d1a1d619f0b76f7068","c4ac3c8751a63f7c40062b9b84f2bb953b0e6bd8f2cf3b2bcaf711321e92df8f","86a2b1a31bf80f17c00ab28420c636c1ed604d0b1f0a33adda99a0cf1e510269","fb892eba992b723a06bccad6a2a1bb875d548a275a987266fceed097b9fd88db","41991fb15fdb013ccab3e6674b91546a0e1e56a1e212c8795c76d0b43f4c884d","ab6a4368d2e5e7cea23fd648662769facc1c37f1d1613225e9010af07cd74711"]},"ecdsa-v1":{"signature":"1d9a5e2336883cc6b440ff40e16ee44f8af2ba9313e46f1e4cd417f7dba7686279b0216e4b0b5fcf0c650dbad98fdefcf5ef16b49d63651a87f80caddd472384"}},"time":"2021-10-04T22:00:15"}}"# ;
let json = r#"{"announcement":{"oracle_event":{"encoding":"json","data":"{\"id\":\"/x/BitMEX/BXBT/2021-10-04T22:00:00.price?n=20 \",\"expected-outcome-time\":\"2021-10-04T22:00:00\",\"descriptor\":{\"type\":\"digit-decomposition\",\"is_signed\":false,\"n_digits\":20,\"unit\":null},\"schemes\":{\"olivia-v1\":{\"nonces\":[\"8d72028eeaf4b85aec0f750f05a4a320cac193f5d8494bfe05cd4b29f3df4239\",\"77240f79a0042adae35ad24284b18b906f17a979fcec3c90d11ed682c6b9261e\",\"e42332407b58f7c6e860b886acfe8d19636fb21a1e20722522206b30a2424d89\",\"ce1158e02dc265751887edae9bdcf8d06ad40489c7643324ccb6a46e4e740f5a\",\"52a5751a43046217bcf009df917c24e400c6da645474a654a5f89499df7154d4\",\"e7b97360a952c2b239d1bfeaade73da4a38e83d20f5deb5b054bcbbc78c91e40\",\"612ce13fd61be10e8de77976c6d479865bc3d2ebdc212946f1e5d93e3f504d2e\",\"e40decd0ea27003b873dde9b6be02f1b344e7e74bc5299144fa0f37b1cf12e90\",\"281a829e05d5f8b96eaf620c7b26115bfb29013d503b6bb40068cdb413a87197\",\"3c87eed0a3852953b0f3ac8a47ff194de66c7229c42e6578e0f6464ba240f033\",\"29028525277cb39adab9ac145d6ce61f2e10306e7b6ce95970a22ea3b201a5d9\",\"20971b4d2069d8b9b5c5678290ab7624821cf32ffe32a20d58428ca90da02523\",\"667a9af33ed45bfb5c4fc7adacea15bbe26df90e0df7dd5b8235e14dfd0da38f\",\"224df2d2706b5c629173b84927e2b206dad7a72e132eb86912d9464dad4b41d1\",\"85296962b9d1f7699c248467ce94ce4aa6e00d26fe01af3a507bcd3a303855d4\",\"96813c9f4d136f0f64be79e73d657fecc43d8b6c463163913b4fa31f96b1ae6b\",\"9d5971aa596923560b12f367fb2f4e192d8906bf6ed3a58b093f50d3cad27493\",\"b7f2c135db80cee02b4436557c78dc1dd2343c1a3688ba736c6c40e9531547b6\",\"bd6236fc18f1dc96f9755cc5c435adaf3952ff810d3ad5b96a03464a61eecfde\",\"20b2922ce326e5e2f4ed683723a879e467edd1068bf5a3c4f331525216227abe\"]},\"ecdsa-v1\":{}}}"},"signature":"743ed9900aba5a1ba3ba9d862628cdc5cca27974c40c4ab64618709021b3fbb13216a3efc733be260025da487ae9b63a8290d555bdc8da6324deff149fc7b110"},"attestation":{"outcome":"48935","schemes":{"olivia-v1":{"scalars":["1327b3bd0f1faf45d6fed6c96d0c158da22a2033a6fed98bed036df0a4eef484","72659c6beebd45e299bc4260a1c1ffd708ed33771459563502f25fc4f537cef6","051eec45417e2493f36b13f4fdf83fb981be42901bf876e4ac594ff2daa4c30e","847d8c7204335b1dbc2078cfb56118b1977162e7b997f2029f490929bbd603c7","5b695846292b6d69d9beedcc7dd2b7e49fd49ec4fcf262d9357f52b049fa8998","368a1f2206fcedcde37381b272fa5a400f55ef720ee2b8fff558e3b0dce729ee","9e1c015c0e827037f18681937764f4973ef22d6fbbd82f6bde3bf5198f6b8999","fe9620c9ad9862b5615f8cf3e20e8d9f422e7410914ce8af2b8bad8937b75738","44297ae831898f8f5c7e57720f233a717e9034a5b41d6c89cce6d9058c4ee086","587fc9b71f1920df825138f00bc625e6610e61b1fec0a64e2800fc05b3a2e96d","010377f6b885ae48d62e7863c8038240aafe0a7fb97d58ac6173186c95335955","5243782226739f59b0ac01a56a63537289ffe81b87b33eca42f89f7848623520","06184cb8e46b5d520cd9b5829feeb73b688d61e5f37b91ff88d3f9b8664a5cdd","fe48f4b568bb501732c4e8f1919940c9bca0ad909f4624658b14664af823ccfe","0841f121e7a54f88a844227cd0ae62171b49d004120c16d1a1d619f0b76f7068","c4ac3c8751a63f7c40062b9b84f2bb953b0e6bd8f2cf3b2bcaf711321e92df8f","86a2b1a31bf80f17c00ab28420c636c1ed604d0b1f0a33adda99a0cf1e510269","fb892eba992b723a06bccad6a2a1bb875d548a275a987266fceed097b9fd88db","41991fb15fdb013ccab3e6674b91546a0e1e56a1e212c8795c76d0b43f4c884d","ab6a4368d2e5e7cea23fd648662769facc1c37f1d1613225e9010af07cd74711"]},"ecdsa-v1":{"signature":"1d9a5e2336883cc6b440ff40e16ee44f8af2ba9313e46f1e4cd417f7dba7686279b0216e4b0b5fcf0c650dbad98fdefcf5ef16b49d63651a87f80caddd472384"}},"time":"2021-10-04T22:00:15"}}"# ;
let deserialized = serde_json ::from_str ::< oracle ::Announcement > ( json ) . unwrap ( ) ;
let expected = oracle ::Announcement {
id : OracleEventId ( "/x/BitMEX/BXBT/2021-10-04T22:00:00.price[n:20] " . to_string ( ) ) ,
id : OracleEventId ( "/x/BitMEX/BXBT/2021-10-04T22:00:00.price?n=20 " . to_string ( ) ) ,
expected_outcome_time : datetime ! ( 2021 - 10 - 04 22 :00 :00 ) . assume_utc ( ) ,
nonce_pks : vec ! [
"8d72028eeaf4b85aec0f750f05a4a320cac193f5d8494bfe05cd4b29f3df4239"
@ -469,11 +486,11 @@ mod olivia_api {
#[ test ]
fn deserialize_attestation ( ) {
let json = r#"{"announcement":{"oracle_event":{"encoding":"json","data":"{\"id\":\"/x/BitMEX/BXBT/2021-10-04T22:00:00.price[n:20] \",\"expected-outcome-time\":\"2021-10-04T22:00:00\",\"descriptor\":{\"type\":\"digit-decomposition\",\"is_signed\":false,\"n_digits\":20,\"unit\":null},\"schemes\":{\"olivia-v1\":{\"nonces\":[\"8d72028eeaf4b85aec0f750f05a4a320cac193f5d8494bfe05cd4b29f3df4239\",\"77240f79a0042adae35ad24284b18b906f17a979fcec3c90d11ed682c6b9261e\",\"e42332407b58f7c6e860b886acfe8d19636fb21a1e20722522206b30a2424d89\",\"ce1158e02dc265751887edae9bdcf8d06ad40489c7643324ccb6a46e4e740f5a\",\"52a5751a43046217bcf009df917c24e400c6da645474a654a5f89499df7154d4\",\"e7b97360a952c2b239d1bfeaade73da4a38e83d20f5deb5b054bcbbc78c91e40\",\"612ce13fd61be10e8de77976c6d479865bc3d2ebdc212946f1e5d93e3f504d2e\",\"e40decd0ea27003b873dde9b6be02f1b344e7e74bc5299144fa0f37b1cf12e90\",\"281a829e05d5f8b96eaf620c7b26115bfb29013d503b6bb40068cdb413a87197\",\"3c87eed0a3852953b0f3ac8a47ff194de66c7229c42e6578e0f6464ba240f033\",\"29028525277cb39adab9ac145d6ce61f2e10306e7b6ce95970a22ea3b201a5d9\",\"20971b4d2069d8b9b5c5678290ab7624821cf32ffe32a20d58428ca90da02523\",\"667a9af33ed45bfb5c4fc7adacea15bbe26df90e0df7dd5b8235e14dfd0da38f\",\"224df2d2706b5c629173b84927e2b206dad7a72e132eb86912d9464dad4b41d1\",\"85296962b9d1f7699c248467ce94ce4aa6e00d26fe01af3a507bcd3a303855d4\",\"96813c9f4d136f0f64be79e73d657fecc43d8b6c463163913b4fa31f96b1ae6b\",\"9d5971aa596923560b12f367fb2f4e192d8906bf6ed3a58b093f50d3cad27493\",\"b7f2c135db80cee02b4436557c78dc1dd2343c1a3688ba736c6c40e9531547b6\",\"bd6236fc18f1dc96f9755cc5c435adaf3952ff810d3ad5b96a03464a61eecfde\",\"20b2922ce326e5e2f4ed683723a879e467edd1068bf5a3c4f331525216227abe\"]},\"ecdsa-v1\":{}}}"},"signature":"743ed9900aba5a1ba3ba9d862628cdc5cca27974c40c4ab64618709021b3fbb13216a3efc733be260025da487ae9b63a8290d555bdc8da6324deff149fc7b110"},"attestation":{"outcome":"48935","schemes":{"olivia-v1":{"scalars":["1327b3bd0f1faf45d6fed6c96d0c158da22a2033a6fed98bed036df0a4eef484","72659c6beebd45e299bc4260a1c1ffd708ed33771459563502f25fc4f537cef6","051eec45417e2493f36b13f4fdf83fb981be42901bf876e4ac594ff2daa4c30e","847d8c7204335b1dbc2078cfb56118b1977162e7b997f2029f490929bbd603c7","5b695846292b6d69d9beedcc7dd2b7e49fd49ec4fcf262d9357f52b049fa8998","368a1f2206fcedcde37381b272fa5a400f55ef720ee2b8fff558e3b0dce729ee","9e1c015c0e827037f18681937764f4973ef22d6fbbd82f6bde3bf5198f6b8999","fe9620c9ad9862b5615f8cf3e20e8d9f422e7410914ce8af2b8bad8937b75738","44297ae831898f8f5c7e57720f233a717e9034a5b41d6c89cce6d9058c4ee086","587fc9b71f1920df825138f00bc625e6610e61b1fec0a64e2800fc05b3a2e96d","010377f6b885ae48d62e7863c8038240aafe0a7fb97d58ac6173186c95335955","5243782226739f59b0ac01a56a63537289ffe81b87b33eca42f89f7848623520","06184cb8e46b5d520cd9b5829feeb73b688d61e5f37b91ff88d3f9b8664a5cdd","fe48f4b568bb501732c4e8f1919940c9bca0ad909f4624658b14664af823ccfe","0841f121e7a54f88a844227cd0ae62171b49d004120c16d1a1d619f0b76f7068","c4ac3c8751a63f7c40062b9b84f2bb953b0e6bd8f2cf3b2bcaf711321e92df8f","86a2b1a31bf80f17c00ab28420c636c1ed604d0b1f0a33adda99a0cf1e510269","fb892eba992b723a06bccad6a2a1bb875d548a275a987266fceed097b9fd88db","41991fb15fdb013ccab3e6674b91546a0e1e56a1e212c8795c76d0b43f4c884d","ab6a4368d2e5e7cea23fd648662769facc1c37f1d1613225e9010af07cd74711"]},"ecdsa-v1":{"signature":"1d9a5e2336883cc6b440ff40e16ee44f8af2ba9313e46f1e4cd417f7dba7686279b0216e4b0b5fcf0c650dbad98fdefcf5ef16b49d63651a87f80caddd472384"}},"time":"2021-10-04T22:00:15"}}"# ;
let json = r#"{"announcement":{"oracle_event":{"encoding":"json","data":"{\"id\":\"/x/BitMEX/BXBT/2021-10-04T22:00:00.price?n=20 \",\"expected-outcome-time\":\"2021-10-04T22:00:00\",\"descriptor\":{\"type\":\"digit-decomposition\",\"is_signed\":false,\"n_digits\":20,\"unit\":null},\"schemes\":{\"olivia-v1\":{\"nonces\":[\"8d72028eeaf4b85aec0f750f05a4a320cac193f5d8494bfe05cd4b29f3df4239\",\"77240f79a0042adae35ad24284b18b906f17a979fcec3c90d11ed682c6b9261e\",\"e42332407b58f7c6e860b886acfe8d19636fb21a1e20722522206b30a2424d89\",\"ce1158e02dc265751887edae9bdcf8d06ad40489c7643324ccb6a46e4e740f5a\",\"52a5751a43046217bcf009df917c24e400c6da645474a654a5f89499df7154d4\",\"e7b97360a952c2b239d1bfeaade73da4a38e83d20f5deb5b054bcbbc78c91e40\",\"612ce13fd61be10e8de77976c6d479865bc3d2ebdc212946f1e5d93e3f504d2e\",\"e40decd0ea27003b873dde9b6be02f1b344e7e74bc5299144fa0f37b1cf12e90\",\"281a829e05d5f8b96eaf620c7b26115bfb29013d503b6bb40068cdb413a87197\",\"3c87eed0a3852953b0f3ac8a47ff194de66c7229c42e6578e0f6464ba240f033\",\"29028525277cb39adab9ac145d6ce61f2e10306e7b6ce95970a22ea3b201a5d9\",\"20971b4d2069d8b9b5c5678290ab7624821cf32ffe32a20d58428ca90da02523\",\"667a9af33ed45bfb5c4fc7adacea15bbe26df90e0df7dd5b8235e14dfd0da38f\",\"224df2d2706b5c629173b84927e2b206dad7a72e132eb86912d9464dad4b41d1\",\"85296962b9d1f7699c248467ce94ce4aa6e00d26fe01af3a507bcd3a303855d4\",\"96813c9f4d136f0f64be79e73d657fecc43d8b6c463163913b4fa31f96b1ae6b\",\"9d5971aa596923560b12f367fb2f4e192d8906bf6ed3a58b093f50d3cad27493\",\"b7f2c135db80cee02b4436557c78dc1dd2343c1a3688ba736c6c40e9531547b6\",\"bd6236fc18f1dc96f9755cc5c435adaf3952ff810d3ad5b96a03464a61eecfde\",\"20b2922ce326e5e2f4ed683723a879e467edd1068bf5a3c4f331525216227abe\"]},\"ecdsa-v1\":{}}}"},"signature":"743ed9900aba5a1ba3ba9d862628cdc5cca27974c40c4ab64618709021b3fbb13216a3efc733be260025da487ae9b63a8290d555bdc8da6324deff149fc7b110"},"attestation":{"outcome":"48935","schemes":{"olivia-v1":{"scalars":["1327b3bd0f1faf45d6fed6c96d0c158da22a2033a6fed98bed036df0a4eef484","72659c6beebd45e299bc4260a1c1ffd708ed33771459563502f25fc4f537cef6","051eec45417e2493f36b13f4fdf83fb981be42901bf876e4ac594ff2daa4c30e","847d8c7204335b1dbc2078cfb56118b1977162e7b997f2029f490929bbd603c7","5b695846292b6d69d9beedcc7dd2b7e49fd49ec4fcf262d9357f52b049fa8998","368a1f2206fcedcde37381b272fa5a400f55ef720ee2b8fff558e3b0dce729ee","9e1c015c0e827037f18681937764f4973ef22d6fbbd82f6bde3bf5198f6b8999","fe9620c9ad9862b5615f8cf3e20e8d9f422e7410914ce8af2b8bad8937b75738","44297ae831898f8f5c7e57720f233a717e9034a5b41d6c89cce6d9058c4ee086","587fc9b71f1920df825138f00bc625e6610e61b1fec0a64e2800fc05b3a2e96d","010377f6b885ae48d62e7863c8038240aafe0a7fb97d58ac6173186c95335955","5243782226739f59b0ac01a56a63537289ffe81b87b33eca42f89f7848623520","06184cb8e46b5d520cd9b5829feeb73b688d61e5f37b91ff88d3f9b8664a5cdd","fe48f4b568bb501732c4e8f1919940c9bca0ad909f4624658b14664af823ccfe","0841f121e7a54f88a844227cd0ae62171b49d004120c16d1a1d619f0b76f7068","c4ac3c8751a63f7c40062b9b84f2bb953b0e6bd8f2cf3b2bcaf711321e92df8f","86a2b1a31bf80f17c00ab28420c636c1ed604d0b1f0a33adda99a0cf1e510269","fb892eba992b723a06bccad6a2a1bb875d548a275a987266fceed097b9fd88db","41991fb15fdb013ccab3e6674b91546a0e1e56a1e212c8795c76d0b43f4c884d","ab6a4368d2e5e7cea23fd648662769facc1c37f1d1613225e9010af07cd74711"]},"ecdsa-v1":{"signature":"1d9a5e2336883cc6b440ff40e16ee44f8af2ba9313e46f1e4cd417f7dba7686279b0216e4b0b5fcf0c650dbad98fdefcf5ef16b49d63651a87f80caddd472384"}},"time":"2021-10-04T22:00:15"}}"# ;
let deserialized = serde_json ::from_str ::< oracle ::Attestation > ( json ) . unwrap ( ) ;
let expected = oracle ::Attestation {
id : OracleEventId ( "/x/BitMEX/BXBT/2021-10-04T22:00:00.price[n:20] " . to_string ( ) ) ,
id : OracleEventId ( "/x/BitMEX/BXBT/2021-10-04T22:00:00.price?n=20 " . to_string ( ) ) ,
price : 48935 ,
scalars : vec ! [
"1327b3bd0f1faf45d6fed6c96d0c158da22a2033a6fed98bed036df0a4eef484"
@ -550,13 +567,17 @@ mod tests {
use time ::macros ::datetime ;
#[ test ]
fn next_event_url_is_correct ( ) {
let url = event_url ( datetime ! ( 2021 - 09 - 23 10 :00 :00 ) . assume_utc ( ) ) ;
fn next_event_id_is_correct ( ) {
let event_id = event_id ( datetime ! ( 2021 - 09 - 23 10 :00 :00 ) . assume_utc ( ) ) ;
assert_eq ! ( event_id . 0 , "/x/BitMEX/BXBT/2021-09-23T10:00:00.price?n=20" ) ;
}
#[ test ]
fn next_event_id_after_timestamp ( ) {
let event_id = next_announcement_after ( datetime ! ( 2021 - 09 - 23 10 :40 :00 ) . assume_utc ( ) ) ;
assert_eq ! (
url ,
"https://h00.ooo/x/BitMEX/BXBT/2021-09-23T10:00:00.price[n:20]"
) ;
assert_eq ! ( event_id . 0 , "/x/BitMEX/BXBT/2021-09-23T11:00:00.price?n=20" ) ;
}
#[ test ]