@ -1,4 +1,4 @@
use crate ::model ::cfd ::{ Cfd , CfdOffer , Cfd Offe rI d, CfdState } ;
use crate ::model ::cfd ::{ Cfd , CfdState , Order , OrderId } ;
use crate ::model ::{ Leverage , Position } ;
use anyhow ::Context ;
use rocket_db_pools ::sqlx ;
@ -9,9 +9,9 @@ use std::convert::TryInto;
use std ::mem ;
#[ derive(Debug, Clone, Serialize, Deserialize, PartialEq) ]
pub enum OfferO rigin {
Mine ,
Othe rs,
pub enum Origin {
Ours ,
Thei rs,
}
pub async fn run_migrations ( pool : & SqlitePool ) -> anyhow ::Result < ( ) > {
@ -19,26 +19,26 @@ pub async fn run_migrations(pool: &SqlitePool) -> anyhow::Result<()> {
Ok ( ( ) )
}
pub async fn insert_cfd_off er (
cfd_offer : & CfdOff er,
pub async fn insert_ord er (
order : & Ord er,
conn : & mut PoolConnection < Sqlite > ,
origin : OfferO rigin ,
origin : Origin ,
) -> anyhow ::Result < ( ) > {
let uuid = serde_json ::to_string ( & cfd_off er. id ) . unwrap ( ) ;
let trading_pair = serde_json ::to_string ( & cfd_off er. trading_pair ) . unwrap ( ) ;
let position = serde_json ::to_string ( & cfd_off er. position ) . unwrap ( ) ;
let initial_price = serde_json ::to_string ( & cfd_off er. price ) . unwrap ( ) ;
let min_quantity = serde_json ::to_string ( & cfd_off er. min_quantity ) . unwrap ( ) ;
let max_quantity = serde_json ::to_string ( & cfd_off er. max_quantity ) . unwrap ( ) ;
let leverage = cfd_off er. leverage . 0 ;
let liquidation_price = serde_json ::to_string ( & cfd_off er. liquidation_price ) . unwrap ( ) ;
let creation_timestamp = serde_json ::to_string ( & cfd_off er. creation_timestamp ) . unwrap ( ) ;
let term = serde_json ::to_string ( & cfd_off er. term ) . unwrap ( ) ;
let uuid = serde_json ::to_string ( & ord er. id ) . unwrap ( ) ;
let trading_pair = serde_json ::to_string ( & ord er. trading_pair ) . unwrap ( ) ;
let position = serde_json ::to_string ( & ord er. position ) . unwrap ( ) ;
let initial_price = serde_json ::to_string ( & ord er. price ) . unwrap ( ) ;
let min_quantity = serde_json ::to_string ( & ord er. min_quantity ) . unwrap ( ) ;
let max_quantity = serde_json ::to_string ( & ord er. max_quantity ) . unwrap ( ) ;
let leverage = ord er. leverage . 0 ;
let liquidation_price = serde_json ::to_string ( & ord er. liquidation_price ) . unwrap ( ) ;
let creation_timestamp = serde_json ::to_string ( & ord er. creation_timestamp ) . unwrap ( ) ;
let term = serde_json ::to_string ( & ord er. term ) . unwrap ( ) ;
let origin = serde_json ::to_string ( & origin ) . unwrap ( ) ;
sqlx ::query ! (
r # "
insert into off ers (
insert into ord ers (
uuid ,
trading_pair ,
position ,
@ -70,15 +70,15 @@ pub async fn insert_cfd_offer(
Ok ( ( ) )
}
pub async fn load_off er_by_id (
id : CfdOff erId,
pub async fn load_ord er_by_id (
id : Ord erId,
conn : & mut PoolConnection < Sqlite > ,
) -> anyhow ::Result < CfdOff er> {
) -> anyhow ::Result < Ord er> {
let uuid = serde_json ::to_string ( & id ) . unwrap ( ) ;
let row = sqlx ::query ! (
r # "
select * from off ers where uuid = ? ;
select * from ord ers where uuid = ? ;
" # ,
uuid
)
@ -96,7 +96,7 @@ pub async fn load_offer_by_id(
let creation_timestamp = serde_json ::from_str ( row . creation_timestamp . as_str ( ) ) . unwrap ( ) ;
let term = serde_json ::from_str ( row . term . as_str ( ) ) . unwrap ( ) ;
Ok ( CfdOff er {
Ok ( Ord er {
id : uuid ,
trading_pair ,
position ,
@ -113,17 +113,17 @@ pub async fn load_offer_by_id(
pub async fn insert_cfd ( cfd : Cfd , conn : & mut PoolConnection < Sqlite > ) -> anyhow ::Result < ( ) > {
let mut tx = conn . begin ( ) . await ? ;
let off er_uuid = serde_json ::to_string ( & cfd . off er_id ) ? ;
let off er_row = sqlx ::query ! (
let ord er_uuid = serde_json ::to_string ( & cfd . ord er_id ) ? ;
let ord er_row = sqlx ::query ! (
r # "
select * from off ers where uuid = ? ;
select * from ord ers where uuid = ? ;
" # ,
off er_uuid
ord er_uuid
)
. fetch_one ( & mut tx )
. await ? ;
let off er_id = off er_row . id ;
let ord er_id = ord er_row . id ;
let quantity_usd = serde_json ::to_string ( & cfd . quantity_usd ) ? ;
let cfd_state = serde_json ::to_string ( & cfd . state ) ? ;
@ -134,13 +134,13 @@ pub async fn insert_cfd(cfd: Cfd, conn: &mut PoolConnection<Sqlite>) -> anyhow::
let cfd_id = sqlx ::query ! (
r # "
insert into cfds (
off er_id ,
off er_uuid ,
ord er_id ,
ord er_uuid ,
quantity_usd
) values ( ? , ? , ? ) ;
" # ,
off er_id ,
off er_uuid ,
ord er_id ,
ord er_uuid ,
quantity_usd ,
)
. execute ( & mut tx )
@ -166,12 +166,12 @@ pub async fn insert_cfd(cfd: Cfd, conn: &mut PoolConnection<Sqlite>) -> anyhow::
}
#[ allow(dead_code) ]
pub async fn insert_new_cfd_state_by_off er_id (
offer_id : CfdOff erId ,
pub async fn insert_new_cfd_state_by_ord er_id (
order_id : Ord erId ,
new_state : CfdState ,
conn : & mut PoolConnection < Sqlite > ,
) -> anyhow ::Result < ( ) > {
let cfd_id = load_cfd_id_by_offer_uuid ( off er_id , conn ) . await ? ;
let cfd_id = load_cfd_id_by_order_uuid ( ord er_id , conn ) . await ? ;
let latest_cfd_state_in_db = load_latest_cfd_state ( cfd_id , conn )
. await
. context ( "loading latest state failed" ) ? ;
@ -179,7 +179,7 @@ pub async fn insert_new_cfd_state_by_offer_id(
// make sure that the new state is different than the current one to avoid that we save the same
// state twice
if mem ::discriminant ( & latest_cfd_state_in_db ) = = mem ::discriminant ( & new_state ) {
anyhow ::bail ! ( "Cannot insert new state {} for cfd with order_id {} because it currently already is in state {}" , new_state , off er_id , latest_cfd_state_in_db ) ;
anyhow ::bail ! ( "Cannot insert new state {} for cfd with order_id {} because it currently already is in state {}" , new_state , ord er_id , latest_cfd_state_in_db ) ;
}
let cfd_state = serde_json ::to_string ( & new_state ) ? ;
@ -201,20 +201,20 @@ pub async fn insert_new_cfd_state_by_offer_id(
}
#[ allow(dead_code) ]
async fn load_cfd_id_by_off er_uuid (
offer_uuid : CfdOff erId ,
async fn load_cfd_id_by_ord er_uuid (
order_uuid : Ord erId ,
conn : & mut PoolConnection < Sqlite > ,
) -> anyhow ::Result < i64 > {
let off er_uuid = serde_json ::to_string ( & off er_uuid ) ? ;
let ord er_uuid = serde_json ::to_string ( & ord er_uuid ) ? ;
let cfd_id = sqlx ::query ! (
r # "
select
id
from cfds
where off er_uuid = ? ;
where ord er_uuid = ? ;
" # ,
off er_uuid
ord er_uuid
)
. fetch_one ( conn )
. await ? ;
@ -257,17 +257,17 @@ pub async fn load_all_cfds(conn: &mut PoolConnection<Sqlite>) -> anyhow::Result<
r # "
select
cfds . id as cfd_id ,
off ers . uuid as off er_id ,
off ers . initial_price as initial_price ,
off ers . leverage as leverage ,
off ers . trading_pair as trading_pair ,
off ers . position as position ,
off ers . origin as origin ,
off ers . liquidation_price as liquidation_price ,
ord ers . uuid as ord er_id ,
ord ers . initial_price as initial_price ,
ord ers . leverage as leverage ,
ord ers . trading_pair as trading_pair ,
ord ers . position as position ,
ord ers . origin as origin ,
ord ers . liquidation_price as liquidation_price ,
cfds . quantity_usd as quantity_usd ,
cfd_states . state as state
from cfds as cfds
inner join off ers as off ers on cfds . off er_id = off ers . id
inner join ord ers as ord ers on cfds . ord er_id = ord ers . id
inner join cfd_states as cfd_states on cfd_states . cfd_id = cfds . id
where cfd_states . state in (
select
@ -285,7 +285,7 @@ pub async fn load_all_cfds(conn: &mut PoolConnection<Sqlite>) -> anyhow::Result<
let cfds = rows
. iter ( )
. map ( | row | {
let off er_id = serde_json ::from_str ( row . off er_id . as_str ( ) ) . unwrap ( ) ;
let ord er_id = serde_json ::from_str ( row . ord er_id . as_str ( ) ) . unwrap ( ) ;
let initial_price = serde_json ::from_str ( row . initial_price . as_str ( ) ) . unwrap ( ) ;
let leverage = Leverage ( row . leverage . try_into ( ) . unwrap ( ) ) ;
let trading_pair = serde_json ::from_str ( row . trading_pair . as_str ( ) ) . unwrap ( ) ;
@ -293,16 +293,16 @@ pub async fn load_all_cfds(conn: &mut PoolConnection<Sqlite>) -> anyhow::Result<
let quantity = serde_json ::from_str ( row . quantity_usd . as_str ( ) ) . unwrap ( ) ;
let latest_state = serde_json ::from_str ( row . state . as_str ( ) ) . unwrap ( ) ;
let origin : OfferO rigin = serde_json ::from_str ( row . origin . as_str ( ) ) . unwrap ( ) ;
let origin : Origin = serde_json ::from_str ( row . origin . as_str ( ) ) . unwrap ( ) ;
let position : Position = serde_json ::from_str ( row . position . as_str ( ) ) . unwrap ( ) ;
let position = match origin {
OfferOrigin ::Mine = > position ,
OfferOrigin ::Othe rs = > position . counter_position ( ) ,
Origin ::Ours = > position ,
Origin ::Thei rs = > position . counter_position ( ) ,
} ;
Cfd {
off er_id ,
ord er_id ,
initial_price ,
leverage ,
trading_pair ,
@ -326,25 +326,25 @@ mod tests {
use sqlx ::SqlitePool ;
use tempfile ::tempdir ;
use crate ::db ::insert_cfd_off er ;
use crate ::model ::cfd ::{ Cfd , CfdOffer , Cfd State , CfdStateCommon } ;
use crate ::db ::insert_ord er ;
use crate ::model ::cfd ::{ Cfd , CfdState , CfdStateCommon , Order } ;
use crate ::model ::Usd ;
use super ::* ;
#[ tokio::test ]
async fn test_insert_and_load_off er ( ) {
async fn test_insert_and_load_ord er ( ) {
let pool = setup_test_db ( ) . await ;
let mut conn = pool . acquire ( ) . await . unwrap ( ) ;
let cfd_offer = CfdOff er ::from_default_with_price ( Usd ( dec ! ( 10000 ) ) ) . unwrap ( ) ;
insert_cfd_offer ( & cfd_off er , & mut conn , OfferOrigin ::Othe rs )
let order = Ord er ::from_default_with_price ( Usd ( dec ! ( 10000 ) ) ) . unwrap ( ) ;
insert_order ( & ord er , & mut conn , Origin ::Thei rs )
. await
. unwrap ( ) ;
let cfd_off er_loaded = load_offer_by_id ( cfd_off er . id , & mut conn ) . await . unwrap ( ) ;
let ord er_loaded = load_order_by_id ( ord er . id , & mut conn ) . await . unwrap ( ) ;
assert_eq ! ( cfd_offer , cfd_off er_loaded) ;
assert_eq ! ( order , ord er_loaded) ;
}
#[ tokio::test ]
@ -352,9 +352,9 @@ mod tests {
let pool = setup_test_db ( ) . await ;
let mut conn = pool . acquire ( ) . await . unwrap ( ) ;
let cfd_offer = CfdOff er ::from_default_with_price ( Usd ( dec ! ( 10000 ) ) ) . unwrap ( ) ;
let order = Ord er ::from_default_with_price ( Usd ( dec ! ( 10000 ) ) ) . unwrap ( ) ;
let cfd = Cfd ::new (
cfd_off er. clone ( ) ,
ord er. clone ( ) ,
Usd ( dec ! ( 1000 ) ) ,
CfdState ::PendingTakeRequest {
common : CfdStateCommon {
@ -365,7 +365,7 @@ mod tests {
) ;
// the order ahs to exist in the db in order to be able to insert the cfd
insert_cfd_offer ( & cfd_off er , & mut conn , OfferOrigin ::Othe rs )
insert_order ( & ord er , & mut conn , Origin ::Thei rs )
. await
. unwrap ( ) ;
insert_cfd ( cfd . clone ( ) , & mut conn ) . await . unwrap ( ) ;
@ -380,9 +380,9 @@ mod tests {
let pool = setup_test_db ( ) . await ;
let mut conn = pool . acquire ( ) . await . unwrap ( ) ;
let cfd_offer = CfdOff er ::from_default_with_price ( Usd ( dec ! ( 10000 ) ) ) . unwrap ( ) ;
let order = Ord er ::from_default_with_price ( Usd ( dec ! ( 10000 ) ) ) . unwrap ( ) ;
let mut cfd = Cfd ::new (
cfd_off er. clone ( ) ,
ord er. clone ( ) ,
Usd ( dec ! ( 1000 ) ) ,
CfdState ::PendingTakeRequest {
common : CfdStateCommon {
@ -393,7 +393,7 @@ mod tests {
) ;
// the order ahs to exist in the db in order to be able to insert the cfd
insert_cfd_offer ( & cfd_off er , & mut conn , OfferOrigin ::Othe rs )
insert_order ( & ord er , & mut conn , Origin ::Thei rs )
. await
. unwrap ( ) ;
insert_cfd ( cfd . clone ( ) , & mut conn ) . await . unwrap ( ) ;
@ -403,7 +403,7 @@ mod tests {
transition_timestamp : SystemTime ::now ( ) ,
} ,
} ;
insert_new_cfd_state_by_off er_id ( cfd . off er_id , cfd . state , & mut conn )
insert_new_cfd_state_by_ord er_id ( cfd . ord er_id , cfd . state , & mut conn )
. await
. unwrap ( ) ;