@ -1,7 +1,7 @@
use crate ::model ::cfd ::{
use crate ::model ::cfd ::{
Dlc , OrderId , Payout , Role , SettlementKind , UpdateCfdProposal , UpdateCfdProposals ,
Dlc , OrderId , Payout , Role , SettlementKind , UpdateCfdProposal , UpdateCfdProposals ,
} ;
} ;
use crate ::model ::{ Leverage , Position , Price , Timestamp , TradingPair , Usd } ;
use crate ::model ::{ Leverage , Position , Timestamp , TradingPair } ;
use crate ::{ bitmex_price_feed , model } ;
use crate ::{ bitmex_price_feed , model } ;
use bdk ::bitcoin ::{ Amount , Network , SignedAmount , Txid } ;
use bdk ::bitcoin ::{ Amount , Network , SignedAmount , Txid } ;
use rocket ::request ::FromParam ;
use rocket ::request ::FromParam ;
@ -12,6 +12,64 @@ use std::convert::TryInto;
use time ::OffsetDateTime ;
use time ::OffsetDateTime ;
use tokio ::sync ::watch ;
use tokio ::sync ::watch ;
#[ derive(Debug, Clone) ]
pub struct Usd {
inner : model ::Usd ,
}
impl Usd {
fn new ( usd : model ::Usd ) -> Self {
Self {
inner : model ::Usd ::new ( usd . into_decimal ( ) . round_dp ( 2 ) ) ,
}
}
}
impl From < model ::Usd > for Usd {
fn from ( usd : model ::Usd ) -> Self {
Self ::new ( usd )
}
}
impl Serialize for Usd {
fn serialize < S > ( & self , serializer : S ) -> Result < S ::Ok , S ::Error >
where
S : serde ::Serializer ,
{
< Decimal as Serialize > ::serialize ( & self . inner . into_decimal ( ) , serializer )
}
}
#[ derive(Debug, Clone) ]
pub struct Price {
inner : model ::Price ,
}
impl Price {
fn new ( price : model ::Price ) -> Self {
Self {
inner : model ::Price ::new ( price . into_decimal ( ) . round_dp ( 2 ) ) . expect (
"rounding a valid price to 2 decimal places should still result in a valid price" ,
) ,
}
}
}
impl From < model ::Price > for Price {
fn from ( price : model ::Price ) -> Self {
Self ::new ( price )
}
}
impl Serialize for Price {
fn serialize < S > ( & self , serializer : S ) -> Result < S ::Ok , S ::Error >
where
S : serde ::Serializer ,
{
< Decimal as Serialize > ::serialize ( & self . inner . into_decimal ( ) , serializer )
}
}
#[ derive(Debug, Clone, Serialize) ]
#[ derive(Debug, Clone, Serialize) ]
pub struct Cfd {
pub struct Cfd {
pub order_id : OrderId ,
pub order_id : OrderId ,
@ -183,7 +241,7 @@ pub trait ToSseEvent {
/// by UI
/// by UI
pub struct CfdsWithAuxData {
pub struct CfdsWithAuxData {
pub cfds : Vec < model ::cfd ::Cfd > ,
pub cfds : Vec < model ::cfd ::Cfd > ,
pub current_price : Price ,
pub current_price : model ::Price ,
pub pending_proposals : UpdateCfdProposals ,
pub pending_proposals : UpdateCfdProposals ,
pub network : Network ,
pub network : Network ,
}
}
@ -242,14 +300,14 @@ impl ToSseEvent for CfdsWithAuxData {
Cfd {
Cfd {
order_id : cfd . order . id ,
order_id : cfd . order . id ,
initial_price : cfd . order . price ,
initial_price : cfd . order . price . into ( ) ,
leverage : cfd . order . leverage ,
leverage : cfd . order . leverage ,
trading_pair : cfd . order . trading_pair . clone ( ) ,
trading_pair : cfd . order . trading_pair . clone ( ) ,
position : cfd . position ( ) ,
position : cfd . position ( ) ,
liquidation_price : cfd . order . liquidation_price ,
liquidation_price : cfd . order . liquidation_price . into ( ) ,
quantity_usd : cfd . quantity_usd ,
quantity_usd : cfd . quantity_usd . into ( ) ,
profit_btc ,
profit_btc ,
profit_in_percent : profit_in_percent . to_string ( ) ,
profit_in_percent : profit_in_percent . round_dp ( 1 ) . to_string ( ) ,
state : state . clone ( ) ,
state : state . clone ( ) ,
actions : available_actions ( state , cfd . role ( ) ) ,
actions : available_actions ( state , cfd . role ( ) ) ,
state_transition_timestamp : cfd . state . get_transition_timestamp ( ) . seconds ( ) ,
state_transition_timestamp : cfd . state . get_transition_timestamp ( ) . seconds ( ) ,
@ -274,11 +332,11 @@ impl ToSseEvent for Option<model::cfd::Order> {
id : order . id ,
id : order . id ,
trading_pair : order . trading_pair ,
trading_pair : order . trading_pair ,
position : order . position ,
position : order . position ,
price : order . price ,
price : order . price . into ( ) ,
min_quantity : order . min_quantity ,
min_quantity : order . min_quantity . into ( ) ,
max_quantity : order . max_quantity ,
max_quantity : order . max_quantity . into ( ) ,
leverage : order . leverage ,
leverage : order . leverage ,
liquidation_price : order . liquidation_price ,
liquidation_price : order . liquidation_price . into ( ) ,
creation_timestamp : order . creation_timestamp ,
creation_timestamp : order . creation_timestamp ,
settlement_time_interval_in_secs : order
settlement_time_interval_in_secs : order
. settlement_time_interval_hours
. settlement_time_interval_hours
@ -417,8 +475,8 @@ pub struct Quote {
impl ToSseEvent for bitmex_price_feed ::Quote {
impl ToSseEvent for bitmex_price_feed ::Quote {
fn to_sse_event ( & self ) -> Event {
fn to_sse_event ( & self ) -> Event {
let quote = Quote {
let quote = Quote {
bid : self . bid ,
bid : self . bid . into ( ) ,
ask : self . ask ,
ask : self . ask . into ( ) ,
last_updated_at : self . timestamp ,
last_updated_at : self . timestamp ,
} ;
} ;
Event ::json ( & quote ) . event ( "quote" )
Event ::json ( & quote ) . event ( "quote" )
@ -457,6 +515,9 @@ fn available_actions(state: CfdState, role: Role) -> Vec<CfdAction> {
mod tests {
mod tests {
use super ::* ;
use super ::* ;
use rust_decimal_macros ::dec ;
use serde_test ::{ assert_ser_tokens , Token } ;
#[ test ]
#[ test ]
fn state_snapshot_test ( ) {
fn state_snapshot_test ( ) {
// Make sure to update the UI after changing this test!
// Make sure to update the UI after changing this test!
@ -484,4 +545,18 @@ mod tests {
let json = serde_json ::to_string ( & CfdState ::SetupFailed ) . unwrap ( ) ;
let json = serde_json ::to_string ( & CfdState ::SetupFailed ) . unwrap ( ) ;
assert_eq ! ( json , "\"SetupFailed\"" ) ;
assert_eq ! ( json , "\"SetupFailed\"" ) ;
}
}
#[ test ]
fn usd_serializes_with_only_cents ( ) {
let usd = Usd ::new ( model ::Usd ::new ( dec ! ( 1000.12345 ) ) ) ;
assert_ser_tokens ( & usd , & [ Token ::Str ( "1000.12" ) ] ) ;
}
#[ test ]
fn price_serializes_with_only_cents ( ) {
let price = Price ::new ( model ::Price ::new ( dec ! ( 1000.12345 ) ) . unwrap ( ) ) ;
assert_ser_tokens ( & price , & [ Token ::Str ( "1000.12" ) ] ) ;
}
}
}