diff --git a/Cargo.lock b/Cargo.lock index 9b155cb..a220558 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -357,6 +357,7 @@ dependencies = [ "libc", "num-integer", "num-traits", + "serde", "time 0.1.43", "winapi 0.3.9", ] @@ -521,6 +522,7 @@ dependencies = [ "bdk", "bytes", "cfd_protocol", + "chrono", "clap", "futures", "hex", diff --git a/daemon/Cargo.toml b/daemon/Cargo.toml index b7a007d..56ed3c8 100644 --- a/daemon/Cargo.toml +++ b/daemon/Cargo.toml @@ -10,6 +10,7 @@ atty = "0.2" bdk = { version = "0.12", default-features = false, features = ["sqlite", "electrum"] } bytes = "1" cfd_protocol = { path = "../cfd_protocol" } +chrono = { version = "0.4", features = ["serde"] } clap = "3.0.0-beta.4" futures = { version = "0.3", default-features = false } hex = "0.4" diff --git a/daemon/migrations/20211025050345_rename_term_to_settlement_time_interval.sql b/daemon/migrations/20211025050345_rename_term_to_settlement_time_interval.sql index 15481a2..d0eadac 100644 --- a/daemon/migrations/20211025050345_rename_term_to_settlement_time_interval.sql +++ b/daemon/migrations/20211025050345_rename_term_to_settlement_time_interval.sql @@ -2,4 +2,7 @@ alter table orders rename column term_seconds to settlement_time_interval_seconds; alter table orders -rename column term_nanoseconds to settlement_time_interval_nanoseconds; +drop column creation_timestamp_nanoseconds; + +alter table orders +drop column term_nanoseconds; diff --git a/daemon/sqlx-data.json b/daemon/sqlx-data.json index 903ba03..6722eb5 100644 --- a/daemon/sqlx-data.json +++ b/daemon/sqlx-data.json @@ -1,7 +1,7 @@ { "db": "SQLite", - "07b8db7d3a709a7f06a20251d5b7251c2a3428ec73c6710a83048d6c8e974958": { - "query": "\n select\n uuid as \"uuid: crate::model::cfd::OrderId\",\n trading_pair as \"trading_pair: crate::model::TradingPair\",\n position as \"position: crate::model::Position\",\n initial_price,\n min_quantity,\n max_quantity,\n leverage as \"leverage: crate::model::Leverage\",\n liquidation_price,\n creation_timestamp_seconds as \"ts_secs: i64\",\n creation_timestamp_nanoseconds as \"ts_nanos: i32\",\n settlement_time_interval_seconds as \"settlement_time_interval_secs: i64\",\n settlement_time_interval_nanoseconds as \"settlement_time_interval_nanos: i32\",\n origin as \"origin: crate::model::cfd::Origin\",\n oracle_event_id\n\n from orders\n where uuid = $1\n ", + "04399897350d026ee0830ccaba3638f8aa8f4ef9694d59286f32b9e2449a99fa": { + "query": "\n with ord as (\n select\n id as order_id,\n uuid,\n trading_pair,\n position,\n initial_price,\n min_quantity,\n max_quantity,\n leverage,\n liquidation_price,\n creation_timestamp_seconds as ts_secs,\n settlement_time_interval_seconds as settlement_time_interval_secs,\n origin,\n oracle_event_id\n from orders\n ),\n\n cfd as (\n select\n ord.order_id,\n id as cfd_id,\n quantity_usd\n from cfds\n inner join ord on ord.order_id = cfds.order_id\n ),\n\n state as (\n select\n id as state_id,\n cfd.order_id,\n cfd.quantity_usd,\n state\n from cfd_states\n inner join cfd on cfd.cfd_id = cfd_states.cfd_id\n where id in (\n select\n max(id) as id\n from cfd_states\n group by (cfd_id)\n )\n )\n\n select\n ord.uuid as \"uuid: crate::model::cfd::OrderId\",\n ord.trading_pair as \"trading_pair: crate::model::TradingPair\",\n ord.position as \"position: crate::model::Position\",\n ord.initial_price,\n ord.min_quantity,\n ord.max_quantity,\n ord.leverage as \"leverage: crate::model::Leverage\",\n ord.liquidation_price,\n ord.ts_secs as \"ts_secs: crate::model::Timestamp\",\n ord.settlement_time_interval_secs as \"settlement_time_interval_secs: i64\",\n ord.origin as \"origin: crate::model::cfd::Origin\",\n ord.oracle_event_id,\n state.quantity_usd,\n state.state\n\n from ord\n inner join state on state.order_id = ord.order_id\n\n where ord.uuid = $1\n ", "describe": { "columns": [ { @@ -45,32 +45,32 @@ "type_info": "Text" }, { - "name": "ts_secs: i64", + "name": "ts_secs: crate::model::Timestamp", "ordinal": 8, "type_info": "Int64" }, { - "name": "ts_nanos: i32", + "name": "settlement_time_interval_secs: i64", "ordinal": 9, "type_info": "Int64" }, { - "name": "settlement_time_interval_secs: i64", + "name": "origin: crate::model::cfd::Origin", "ordinal": 10, - "type_info": "Int64" + "type_info": "Text" }, { - "name": "settlement_time_interval_nanos: i32", + "name": "oracle_event_id", "ordinal": 11, - "type_info": "Int64" + "type_info": "Text" }, { - "name": "origin: crate::model::cfd::Origin", + "name": "quantity_usd", "ordinal": 12, "type_info": "Text" }, { - "name": "oracle_event_id", + "name": "state", "ordinal": 13, "type_info": "Text" } @@ -96,8 +96,26 @@ ] } }, - "1ea6916f2e25bdd8f4761f0810178ed3b5e52817e6440b54d2bf4e13fb786405": { - "query": "\n with ord as (\n select\n id as order_id,\n uuid,\n trading_pair,\n position,\n initial_price,\n min_quantity,\n max_quantity,\n leverage,\n liquidation_price,\n creation_timestamp_seconds as ts_secs,\n creation_timestamp_nanoseconds as ts_nanos,\n settlement_time_interval_seconds as settlement_time_interval_secs,\n settlement_time_interval_nanoseconds as settlement_time_interval_nanos,\n origin,\n oracle_event_id\n from orders\n ),\n\n cfd as (\n select\n ord.order_id,\n id as cfd_id,\n quantity_usd\n from cfds\n inner join ord on ord.order_id = cfds.order_id\n ),\n\n state as (\n select\n id as state_id,\n cfd.order_id,\n cfd.quantity_usd,\n state\n from cfd_states\n inner join cfd on cfd.cfd_id = cfd_states.cfd_id\n where id in (\n select\n max(id) as id\n from cfd_states\n group by (cfd_id)\n )\n )\n\n select\n ord.uuid as \"uuid: crate::model::cfd::OrderId\",\n ord.trading_pair as \"trading_pair: crate::model::TradingPair\",\n ord.position as \"position: crate::model::Position\",\n ord.initial_price,\n ord.min_quantity,\n ord.max_quantity,\n ord.leverage as \"leverage: crate::model::Leverage\",\n ord.liquidation_price,\n ord.ts_secs as \"ts_secs: i64\",\n ord.ts_nanos as \"ts_nanos: i32\",\n ord.settlement_time_interval_secs as \"settlement_time_interval_secs: i64\",\n ord.settlement_time_interval_nanos as \"settlement_time_interval_nanos: i32\",\n ord.origin as \"origin: crate::model::cfd::Origin\",\n ord.oracle_event_id,\n state.quantity_usd,\n state.state\n\n from ord\n inner join state on state.order_id = ord.order_id\n\n where ord.uuid = $1\n ", + "221a6283db798bacaba99e7e85130f9a8bbea1299d8cb99d272b1d478dc19775": { + "query": "\n select\n state\n from cfd_states\n where cfd_id = $1\n order by id desc\n limit 1;\n ", + "describe": { + "columns": [ + { + "name": "state", + "ordinal": 0, + "type_info": "Text" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + } + }, + "22aae04782d6d9d6fa025e7606e3dcce91bfb9aca4aef9089a9ff9407c9f2715": { + "query": "\n with ord as (\n select\n id as order_id,\n uuid,\n trading_pair,\n position,\n initial_price,\n min_quantity,\n max_quantity,\n leverage,\n liquidation_price,\n creation_timestamp_seconds as ts_secs,\n settlement_time_interval_seconds as settlement_time_interval_secs,\n origin,\n oracle_event_id\n from orders\n ),\n\n cfd as (\n select\n ord.order_id,\n id as cfd_id,\n quantity_usd\n from cfds\n inner join ord on ord.order_id = cfds.order_id\n ),\n\n state as (\n select\n id as state_id,\n cfd.order_id,\n cfd.quantity_usd,\n state\n from cfd_states\n inner join cfd on cfd.cfd_id = cfd_states.cfd_id\n where id in (\n select\n max(id) as id\n from cfd_states\n group by (cfd_id)\n )\n )\n\n select\n ord.uuid as \"uuid: crate::model::cfd::OrderId\",\n ord.trading_pair as \"trading_pair: crate::model::TradingPair\",\n ord.position as \"position: crate::model::Position\",\n ord.initial_price,\n ord.min_quantity,\n ord.max_quantity,\n ord.leverage as \"leverage: crate::model::Leverage\",\n ord.liquidation_price,\n ord.ts_secs as \"ts_secs: crate::model::Timestamp\",\n ord.settlement_time_interval_secs as \"settlement_time_interval_secs: i64\",\n ord.origin as \"origin: crate::model::cfd::Origin\",\n ord.oracle_event_id,\n state.quantity_usd,\n state.state\n\n from ord\n inner join state on state.order_id = ord.order_id\n ", "describe": { "columns": [ { @@ -141,48 +159,38 @@ "type_info": "Text" }, { - "name": "ts_secs: i64", + "name": "ts_secs: crate::model::Timestamp", "ordinal": 8, "type_info": "Int64" }, - { - "name": "ts_nanos: i32", - "ordinal": 9, - "type_info": "Int64" - }, { "name": "settlement_time_interval_secs: i64", - "ordinal": 10, - "type_info": "Int64" - }, - { - "name": "settlement_time_interval_nanos: i32", - "ordinal": 11, + "ordinal": 9, "type_info": "Int64" }, { "name": "origin: crate::model::cfd::Origin", - "ordinal": 12, + "ordinal": 10, "type_info": "Text" }, { "name": "oracle_event_id", - "ordinal": 13, + "ordinal": 11, "type_info": "Text" }, { "name": "quantity_usd", - "ordinal": 14, + "ordinal": 12, "type_info": "Text" }, { "name": "state", - "ordinal": 15, + "ordinal": 13, "type_info": "Text" } ], "parameters": { - "Right": 1 + "Right": 0 }, "nullable": [ false, @@ -198,32 +206,12 @@ false, false, false, - false, - false, false ] } }, - "221a6283db798bacaba99e7e85130f9a8bbea1299d8cb99d272b1d478dc19775": { - "query": "\n select\n state\n from cfd_states\n where cfd_id = $1\n order by id desc\n limit 1;\n ", - "describe": { - "columns": [ - { - "name": "state", - "ordinal": 0, - "type_info": "Text" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false - ] - } - }, - "571575003ef3ad8ad627213f11c9080c25a29bb665077ada9047630acfe4465c": { - "query": "\n with ord as (\n select\n id as order_id,\n uuid,\n trading_pair,\n position,\n initial_price,\n min_quantity,\n max_quantity,\n leverage,\n liquidation_price,\n creation_timestamp_seconds as ts_secs,\n creation_timestamp_nanoseconds as ts_nanos,\n settlement_time_interval_seconds as settlement_time_interval_secs,\n settlement_time_interval_nanoseconds as settlement_time_interval_nanos,\n origin,\n oracle_event_id\n from orders\n ),\n\n cfd as (\n select\n ord.order_id,\n id as cfd_id,\n quantity_usd\n from cfds\n inner join ord on ord.order_id = cfds.order_id\n ),\n\n state as (\n select\n id as state_id,\n cfd.order_id,\n cfd.quantity_usd,\n state\n from cfd_states\n inner join cfd on cfd.cfd_id = cfd_states.cfd_id\n where id in (\n select\n max(id) as id\n from cfd_states\n group by (cfd_id)\n )\n )\n\n select\n ord.uuid as \"uuid: crate::model::cfd::OrderId\",\n ord.trading_pair as \"trading_pair: crate::model::TradingPair\",\n ord.position as \"position: crate::model::Position\",\n ord.initial_price,\n ord.min_quantity,\n ord.max_quantity,\n ord.leverage as \"leverage: crate::model::Leverage\",\n ord.liquidation_price,\n ord.ts_secs as \"ts_secs: i64\",\n ord.ts_nanos as \"ts_nanos: i32\",\n ord.settlement_time_interval_secs as \"settlement_time_interval_secs: i64\",\n ord.settlement_time_interval_nanos as \"settlement_time_interval_nanos: i32\",\n ord.origin as \"origin: crate::model::cfd::Origin\",\n ord.oracle_event_id,\n state.quantity_usd,\n state.state\n\n from ord\n inner join state on state.order_id = ord.order_id\n\n where ord.oracle_event_id = $1\n ", + "4bb5424ebcd683a149f15df5560fdea6727174f4cd6e0709e526ac3a690e2e5e": { + "query": "\n select\n uuid as \"uuid: crate::model::cfd::OrderId\",\n trading_pair as \"trading_pair: crate::model::TradingPair\",\n position as \"position: crate::model::Position\",\n initial_price,\n min_quantity,\n max_quantity,\n leverage as \"leverage: crate::model::Leverage\",\n liquidation_price,\n creation_timestamp_seconds as \"ts_secs: crate::model::Timestamp\",\n settlement_time_interval_seconds as \"settlement_time_interval_secs: i64\",\n origin as \"origin: crate::model::cfd::Origin\",\n oracle_event_id\n\n from orders\n where uuid = $1\n ", "describe": { "columns": [ { @@ -267,43 +255,23 @@ "type_info": "Text" }, { - "name": "ts_secs: i64", + "name": "ts_secs: crate::model::Timestamp", "ordinal": 8, "type_info": "Int64" }, - { - "name": "ts_nanos: i32", - "ordinal": 9, - "type_info": "Int64" - }, { "name": "settlement_time_interval_secs: i64", - "ordinal": 10, - "type_info": "Int64" - }, - { - "name": "settlement_time_interval_nanos: i32", - "ordinal": 11, + "ordinal": 9, "type_info": "Int64" }, { "name": "origin: crate::model::cfd::Origin", - "ordinal": 12, + "ordinal": 10, "type_info": "Text" }, { "name": "oracle_event_id", - "ordinal": 13, - "type_info": "Text" - }, - { - "name": "quantity_usd", - "ordinal": 14, - "type_info": "Text" - }, - { - "name": "state", - "ordinal": 15, + "ordinal": 11, "type_info": "Text" } ], @@ -322,34 +290,12 @@ false, false, false, - false, - false, - false, - false, false ] } }, - "8cbe349911b35d8e79763d64b4f5813b4bd98f12e0bba5ada84d2cae8b08ef4f": { - "query": "\n select\n id\n from cfds\n where order_uuid = $1;\n ", - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int64" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - true - ] - } - }, - "b5a6bcafbfa745d147c30410e0acf8ee6c7733cc3e550a2db0c7860737c756dd": { - "query": "\n with ord as (\n select\n id as order_id,\n uuid,\n trading_pair,\n position,\n initial_price,\n min_quantity,\n max_quantity,\n leverage,\n liquidation_price,\n creation_timestamp_seconds as ts_secs,\n creation_timestamp_nanoseconds as ts_nanos,\n settlement_time_interval_seconds as settlement_time_interval_secs,\n settlement_time_interval_nanoseconds as settlement_time_interval_nanos,\n origin,\n oracle_event_id\n from orders\n ),\n\n cfd as (\n select\n ord.order_id,\n id as cfd_id,\n quantity_usd\n from cfds\n inner join ord on ord.order_id = cfds.order_id\n ),\n\n state as (\n select\n id as state_id,\n cfd.order_id,\n cfd.quantity_usd,\n state\n from cfd_states\n inner join cfd on cfd.cfd_id = cfd_states.cfd_id\n where id in (\n select\n max(id) as id\n from cfd_states\n group by (cfd_id)\n )\n )\n\n select\n ord.uuid as \"uuid: crate::model::cfd::OrderId\",\n ord.trading_pair as \"trading_pair: crate::model::TradingPair\",\n ord.position as \"position: crate::model::Position\",\n ord.initial_price,\n ord.min_quantity,\n ord.max_quantity,\n ord.leverage as \"leverage: crate::model::Leverage\",\n ord.liquidation_price,\n ord.ts_secs as \"ts_secs: i64\",\n ord.ts_nanos as \"ts_nanos: i32\",\n ord.settlement_time_interval_secs as \"settlement_time_interval_secs: i64\",\n ord.settlement_time_interval_nanos as \"settlement_time_interval_nanos: i32\",\n ord.origin as \"origin: crate::model::cfd::Origin\",\n ord.oracle_event_id,\n state.quantity_usd,\n state.state\n\n from ord\n inner join state on state.order_id = ord.order_id\n ", + "6dbd14a613a982521b4cc9179fd6f6b0298c0a4475508536379e9b82c9f2d0a0": { + "query": "\n with ord as (\n select\n id as order_id,\n uuid,\n trading_pair,\n position,\n initial_price,\n min_quantity,\n max_quantity,\n leverage,\n liquidation_price,\n creation_timestamp_seconds as ts_secs,\n settlement_time_interval_seconds as settlement_time_interval_secs,\n origin,\n oracle_event_id\n from orders\n ),\n\n cfd as (\n select\n ord.order_id,\n id as cfd_id,\n quantity_usd\n from cfds\n inner join ord on ord.order_id = cfds.order_id\n ),\n\n state as (\n select\n id as state_id,\n cfd.order_id,\n cfd.quantity_usd,\n state\n from cfd_states\n inner join cfd on cfd.cfd_id = cfd_states.cfd_id\n where id in (\n select\n max(id) as id\n from cfd_states\n group by (cfd_id)\n )\n )\n\n select\n ord.uuid as \"uuid: crate::model::cfd::OrderId\",\n ord.trading_pair as \"trading_pair: crate::model::TradingPair\",\n ord.position as \"position: crate::model::Position\",\n ord.initial_price,\n ord.min_quantity,\n ord.max_quantity,\n ord.leverage as \"leverage: crate::model::Leverage\",\n ord.liquidation_price,\n ord.ts_secs as \"ts_secs: crate::model::Timestamp\",\n ord.settlement_time_interval_secs as \"settlement_time_interval_secs: i64\",\n ord.origin as \"origin: crate::model::cfd::Origin\",\n ord.oracle_event_id,\n state.quantity_usd,\n state.state\n\n from ord\n inner join state on state.order_id = ord.order_id\n\n where ord.oracle_event_id = $1\n ", "describe": { "columns": [ { @@ -393,48 +339,38 @@ "type_info": "Text" }, { - "name": "ts_secs: i64", + "name": "ts_secs: crate::model::Timestamp", "ordinal": 8, "type_info": "Int64" }, - { - "name": "ts_nanos: i32", - "ordinal": 9, - "type_info": "Int64" - }, { "name": "settlement_time_interval_secs: i64", - "ordinal": 10, - "type_info": "Int64" - }, - { - "name": "settlement_time_interval_nanos: i32", - "ordinal": 11, + "ordinal": 9, "type_info": "Int64" }, { "name": "origin: crate::model::cfd::Origin", - "ordinal": 12, + "ordinal": 10, "type_info": "Text" }, { "name": "oracle_event_id", - "ordinal": 13, + "ordinal": 11, "type_info": "Text" }, { "name": "quantity_usd", - "ordinal": 14, + "ordinal": 12, "type_info": "Text" }, { "name": "state", - "ordinal": 15, + "ordinal": 13, "type_info": "Text" } ], "parameters": { - "Right": 0 + "Right": 1 }, "nullable": [ false, @@ -450,10 +386,26 @@ false, false, false, - false, - false, false ] } + }, + "8cbe349911b35d8e79763d64b4f5813b4bd98f12e0bba5ada84d2cae8b08ef4f": { + "query": "\n select\n id\n from cfds\n where order_uuid = $1;\n ", + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int64" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + true + ] + } } } \ No newline at end of file diff --git a/daemon/src/bitmex_price_feed.rs b/daemon/src/bitmex_price_feed.rs index 96ee267..d0adce6 100644 --- a/daemon/src/bitmex_price_feed.rs +++ b/daemon/src/bitmex_price_feed.rs @@ -1,10 +1,9 @@ -use crate::model::Price; +use crate::model::{Price, Timestamp}; use anyhow::Result; use futures::{StreamExt, TryStreamExt}; use rust_decimal::Decimal; use std::convert::TryFrom; use std::future::Future; -use std::time::SystemTime; use tokio::sync::watch; use tokio_tungstenite::tungstenite; @@ -42,7 +41,7 @@ pub async fn new() -> Result<(impl Future, watch::Receiver)> #[derive(Clone, Debug)] pub struct Quote { - pub timestamp: SystemTime, + pub timestamp: Timestamp, pub bid: Price, pub ask: Price, } @@ -62,7 +61,7 @@ impl Quote { let [quote] = table_message.data; Ok(Some(Self { - timestamp: SystemTime::now(), + timestamp: Timestamp::parse_from_rfc3339("e.timestamp)?, bid: Price::new(Decimal::try_from(quote.bid_price)?)?, ask: Price::new(Decimal::try_from(quote.ask_price)?)?, })) @@ -100,6 +99,7 @@ mod wire { pub bid_price: f64, pub ask_price: f64, pub symbol: String, + pub timestamp: String, } } @@ -116,5 +116,6 @@ mod tests { assert_eq!(quote.bid, Price::new(dec!(42640.5)).unwrap()); assert_eq!(quote.ask, Price::new(dec!(42641)).unwrap()); + assert_eq!(quote.timestamp.seconds(), 1632192000) } } diff --git a/daemon/src/db.rs b/daemon/src/db.rs index 66a02e8..5f6ce31 100644 --- a/daemon/src/db.rs +++ b/daemon/src/db.rs @@ -6,8 +6,7 @@ use sqlx::pool::PoolConnection; use sqlx::{Sqlite, SqlitePool}; use std::mem; use std::str::FromStr; -use std::time::SystemTime; -use time::{Duration, OffsetDateTime}; +use time::Duration; pub async fn run_migrations(pool: &SqlitePool) -> anyhow::Result<()> { sqlx::migrate!("./migrations").run(pool).await?; @@ -26,12 +25,10 @@ pub async fn insert_order(order: &Order, conn: &mut PoolConnection) -> a leverage, liquidation_price, creation_timestamp_seconds, - creation_timestamp_nanoseconds, settlement_time_interval_seconds, - settlement_time_interval_nanoseconds, origin, oracle_event_id - ) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)"#, + ) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)"#, ) .bind(&order.id) .bind(&order.trading_pair) @@ -41,20 +38,8 @@ pub async fn insert_order(order: &Order, conn: &mut PoolConnection) -> a .bind(&order.max_quantity.to_string()) .bind(order.leverage.get()) .bind(&order.liquidation_price.to_string()) - .bind( - order - .creation_timestamp - .duration_since(SystemTime::UNIX_EPOCH)? - .as_secs() as i64, - ) - .bind( - order - .creation_timestamp - .duration_since(SystemTime::UNIX_EPOCH)? - .subsec_nanos() as i32, - ) + .bind(&order.creation_timestamp.seconds()) .bind(&order.settlement_time_interval_hours.whole_seconds()) - .bind(&order.settlement_time_interval_hours.subsec_nanoseconds()) .bind(&order.origin) .bind(&order.oracle_event_id.to_string()) .execute(conn) @@ -82,10 +67,8 @@ pub async fn load_order_by_id( max_quantity, leverage as "leverage: crate::model::Leverage", liquidation_price, - creation_timestamp_seconds as "ts_secs: i64", - creation_timestamp_nanoseconds as "ts_nanos: i32", + creation_timestamp_seconds as "ts_secs: crate::model::Timestamp", settlement_time_interval_seconds as "settlement_time_interval_secs: i64", - settlement_time_interval_nanoseconds as "settlement_time_interval_nanos: i32", origin as "origin: crate::model::cfd::Origin", oracle_event_id @@ -106,11 +89,8 @@ pub async fn load_order_by_id( max_quantity: row.max_quantity.parse::()?, leverage: row.leverage, liquidation_price: row.liquidation_price.parse::()?, - creation_timestamp: convert_to_system_time(row.ts_secs, row.ts_nanos)?, - settlement_time_interval_hours: Duration::new( - row.settlement_time_interval_secs, - row.settlement_time_interval_nanos, - ), + creation_timestamp: row.ts_secs, + settlement_time_interval_hours: Duration::new(row.settlement_time_interval_secs, 0), origin: row.origin, oracle_event_id: row.oracle_event_id.parse::()?, }) @@ -253,9 +233,7 @@ pub async fn load_cfd_by_order_id( leverage, liquidation_price, creation_timestamp_seconds as ts_secs, - creation_timestamp_nanoseconds as ts_nanos, settlement_time_interval_seconds as settlement_time_interval_secs, - settlement_time_interval_nanoseconds as settlement_time_interval_nanos, origin, oracle_event_id from orders @@ -295,10 +273,8 @@ pub async fn load_cfd_by_order_id( ord.max_quantity, ord.leverage as "leverage: crate::model::Leverage", ord.liquidation_price, - ord.ts_secs as "ts_secs: i64", - ord.ts_nanos as "ts_nanos: i32", + ord.ts_secs as "ts_secs: crate::model::Timestamp", ord.settlement_time_interval_secs as "settlement_time_interval_secs: i64", - ord.settlement_time_interval_nanos as "settlement_time_interval_nanos: i32", ord.origin as "origin: crate::model::cfd::Origin", ord.oracle_event_id, state.quantity_usd, @@ -323,11 +299,8 @@ pub async fn load_cfd_by_order_id( max_quantity: row.max_quantity.parse::()?, leverage: row.leverage, liquidation_price: row.liquidation_price.parse::()?, - creation_timestamp: convert_to_system_time(row.ts_secs, row.ts_nanos)?, - settlement_time_interval_hours: Duration::new( - row.settlement_time_interval_secs, - row.settlement_time_interval_nanos, - ), + creation_timestamp: row.ts_secs, + settlement_time_interval_hours: Duration::new(row.settlement_time_interval_secs, 0), origin: row.origin, oracle_event_id: row.oracle_event_id.parse::()?, }; @@ -358,9 +331,7 @@ pub async fn load_all_cfds(conn: &mut PoolConnection) -> anyhow::Result< leverage, liquidation_price, creation_timestamp_seconds as ts_secs, - creation_timestamp_nanoseconds as ts_nanos, settlement_time_interval_seconds as settlement_time_interval_secs, - settlement_time_interval_nanoseconds as settlement_time_interval_nanos, origin, oracle_event_id from orders @@ -400,10 +371,8 @@ pub async fn load_all_cfds(conn: &mut PoolConnection) -> anyhow::Result< ord.max_quantity, ord.leverage as "leverage: crate::model::Leverage", ord.liquidation_price, - ord.ts_secs as "ts_secs: i64", - ord.ts_nanos as "ts_nanos: i32", + ord.ts_secs as "ts_secs: crate::model::Timestamp", ord.settlement_time_interval_secs as "settlement_time_interval_secs: i64", - ord.settlement_time_interval_nanos as "settlement_time_interval_nanos: i32", ord.origin as "origin: crate::model::cfd::Origin", ord.oracle_event_id, state.quantity_usd, @@ -428,11 +397,8 @@ pub async fn load_all_cfds(conn: &mut PoolConnection) -> anyhow::Result< max_quantity: row.max_quantity.parse::()?, leverage: row.leverage, liquidation_price: row.liquidation_price.parse::()?, - creation_timestamp: convert_to_system_time(row.ts_secs, row.ts_nanos)?, - settlement_time_interval_hours: Duration::new( - row.settlement_time_interval_secs, - row.settlement_time_interval_nanos, - ), + creation_timestamp: row.ts_secs, + settlement_time_interval_hours: Duration::new(row.settlement_time_interval_secs, 0), origin: row.origin, oracle_event_id: row.oracle_event_id.parse::()?, }; @@ -468,9 +434,7 @@ pub async fn load_cfds_by_oracle_event_id( leverage, liquidation_price, creation_timestamp_seconds as ts_secs, - creation_timestamp_nanoseconds as ts_nanos, settlement_time_interval_seconds as settlement_time_interval_secs, - settlement_time_interval_nanoseconds as settlement_time_interval_nanos, origin, oracle_event_id from orders @@ -510,10 +474,8 @@ pub async fn load_cfds_by_oracle_event_id( ord.max_quantity, ord.leverage as "leverage: crate::model::Leverage", ord.liquidation_price, - ord.ts_secs as "ts_secs: i64", - ord.ts_nanos as "ts_nanos: i32", + ord.ts_secs as "ts_secs: crate::model::Timestamp", ord.settlement_time_interval_secs as "settlement_time_interval_secs: i64", - ord.settlement_time_interval_nanos as "settlement_time_interval_nanos: i32", ord.origin as "origin: crate::model::cfd::Origin", ord.oracle_event_id, state.quantity_usd, @@ -541,11 +503,8 @@ pub async fn load_cfds_by_oracle_event_id( max_quantity: row.max_quantity.parse::()?, leverage: row.leverage, liquidation_price: row.liquidation_price.parse::()?, - creation_timestamp: convert_to_system_time(row.ts_secs, row.ts_nanos)?, - settlement_time_interval_hours: Duration::new( - row.settlement_time_interval_secs, - row.settlement_time_interval_nanos, - ), + creation_timestamp: row.ts_secs, + settlement_time_interval_hours: Duration::new(row.settlement_time_interval_secs, 0), origin: row.origin, oracle_event_id: row.oracle_event_id.parse::()?, }; @@ -561,14 +520,6 @@ pub async fn load_cfds_by_oracle_event_id( Ok(cfds) } -fn convert_to_system_time(row_secs: i64, row_nanos: i32) -> Result { - let secs = row_secs as i128; - let nanos = row_nanos as i128; - let offset_dt = OffsetDateTime::from_unix_timestamp_nanos(secs * 1_000_000_000 + nanos)?; - - Ok(SystemTime::from(offset_dt)) -} - #[cfg(test)] mod tests { use crate::cfd_actors; diff --git a/daemon/src/maker_cfd.rs b/daemon/src/maker_cfd.rs index e514d39..767718b 100644 --- a/daemon/src/maker_cfd.rs +++ b/daemon/src/maker_cfd.rs @@ -6,7 +6,7 @@ use crate::model::cfd::{ OrderId, Origin, Role, RollOverProposal, SettlementKind, SettlementProposal, UpdateCfdProposal, UpdateCfdProposals, }; -use crate::model::{Price, TakerId, Usd}; +use crate::model::{Price, TakerId, Timestamp, Usd}; use crate::monitor::MonitorParams; use crate::{log_error, maker_inc_connections, monitor, oracle, setup_contract, wallet, wire}; use anyhow::{Context as _, Result}; @@ -18,7 +18,6 @@ use futures::{future, SinkExt}; use sqlx::pool::PoolConnection; use sqlx::Sqlite; use std::collections::HashMap; -use std::time::SystemTime; use time::Duration; use tokio::sync::watch; use xtra::prelude::*; @@ -449,7 +448,7 @@ where quantity, CfdState::IncomingOrderRequest { common: CfdStateCommon { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now()?, }, taker_id, }, @@ -885,7 +884,7 @@ where let own_script_pubkey = dlc.script_pubkey_for(cfd.role()); cfd.handle(CfdStateChangeEvent::ProposalSigned( - CollaborativeSettlement::new(tx.clone(), own_script_pubkey.clone(), proposal.price), + CollaborativeSettlement::new(tx.clone(), own_script_pubkey.clone(), proposal.price)?, ))?; append_cfd_state(&cfd, &mut conn, &self.cfd_feed_actor_inbox).await?; diff --git a/daemon/src/model.rs b/daemon/src/model.rs index da603b9..b59efb8 100644 --- a/daemon/src/model.rs +++ b/daemon/src/model.rs @@ -1,15 +1,16 @@ use crate::olivia; - use anyhow::{Context, Result}; use bdk::bitcoin::{Address, Amount, Denomination}; +use chrono::DateTime; use reqwest::Url; use rust_decimal::prelude::ToPrimitive; use rust_decimal::Decimal; use serde::{Deserialize, Serialize}; use serde_with::{DeserializeFromStr, SerializeDisplay}; +use std::convert::TryInto; use std::num::NonZeroU8; use std::ops::{Add, Div, Mul, Sub}; -use std::time::SystemTime; +use std::time::{SystemTime, UNIX_EPOCH}; use std::{fmt, str}; use time::{OffsetDateTime, PrimitiveDateTime, Time}; use uuid::Uuid; @@ -464,7 +465,7 @@ impl fmt::Display for TakerId { pub struct WalletInfo { pub balance: Amount, pub address: Address, - pub last_updated_at: SystemTime, + pub last_updated_at: Timestamp, } #[derive( @@ -546,6 +547,43 @@ impl str::FromStr for BitMexPriceEventId { } } +#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, sqlx::Type)] +pub struct Timestamp(i64); + +impl Timestamp { + pub fn new(seconds: i64) -> Self { + Self(seconds) + } + + pub fn now() -> Result { + let seconds: i64 = SystemTime::now() + .duration_since(UNIX_EPOCH) + .context("time has gone backwards!")? + .as_secs() + .try_into() + .context("Unable to convert u64 to i64")?; + + Ok(Self(seconds)) + } + + pub fn parse_from_rfc3339(datetime_str: &str) -> Result { + let datetime = DateTime::parse_from_rfc3339(datetime_str) + .context("Unable to parse datetime as RFC3339")?; + let seconds = datetime.timestamp(); + + Ok(Self(seconds)) + } + + pub fn seconds(&self) -> i64 { + self.0 + } + + pub fn seconds_u64(&self) -> Result { + let out = self.0.try_into().context("Unable to convert i64 to u64")?; + Ok(out) + } +} + #[cfg(test)] mod tests { use rust_decimal_macros::dec; @@ -662,4 +700,14 @@ mod tests { assert_eq!(long_buyin, expected_buyin); assert_eq!(long_payout, Amount::ZERO); } + + #[test] + fn test_timestamp() { + let datetime_str_a = "1999-12-31T23:59:00.00Z"; + let datetime_str_b = "1999-12-31T23:59:00.00+10:00"; + let ts_a = Timestamp::parse_from_rfc3339(datetime_str_a).unwrap(); + let ts_b = Timestamp::parse_from_rfc3339(datetime_str_b).unwrap(); + + assert_eq!(ts_b.seconds() - ts_a.seconds(), -36000); + } } diff --git a/daemon/src/model/cfd.rs b/daemon/src/model/cfd.rs index 6e049c9..d6bb1f8 100644 --- a/daemon/src/model/cfd.rs +++ b/daemon/src/model/cfd.rs @@ -1,4 +1,7 @@ -use crate::model::{BitMexPriceEventId, Leverage, Percent, Position, TakerId, TradingPair, Usd}; +use crate::model::{ + BitMexPriceEventId, InversePrice, Leverage, Percent, Position, Price, TakerId, Timestamp, + TradingPair, Usd, +}; use crate::{monitor, oracle, payout_curve}; use anyhow::{bail, Context, Result}; use bdk::bitcoin::secp256k1::{SecretKey, Signature}; @@ -7,7 +10,6 @@ use bdk::descriptor::Descriptor; use bdk::miniscript::DescriptorTrait; use cfd_protocol::secp256k1_zkp::{self, EcdsaAdaptorSignature, SECP256K1}; use cfd_protocol::{finalize_spend_transaction, spending_tx_sighash, TransactionExt}; - use rocket::request::FromParam; use rust_decimal::prelude::FromPrimitive; use rust_decimal::Decimal; @@ -16,13 +18,10 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fmt; use std::ops::RangeInclusive; -use std::time::SystemTime; use time::{Duration, OffsetDateTime}; use uuid::adapter::Hyphenated; use uuid::Uuid; -use super::{InversePrice, Price}; - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, sqlx::Type)] #[sqlx(transparent)] pub struct OrderId(Hyphenated); @@ -113,7 +112,7 @@ pub struct Order { pub leverage: Leverage, pub liquidation_price: Price, - pub creation_timestamp: SystemTime, + pub creation_timestamp: Timestamp, /// The duration that will be used for calculating the settlement timestamp pub settlement_time_interval_hours: Duration, @@ -147,7 +146,7 @@ impl Order { trading_pair: TradingPair::BtcUsd, liquidation_price, position: Position::Short, - creation_timestamp: SystemTime::now(), + creation_timestamp: Timestamp::now()?, settlement_time_interval_hours, origin, oracle_event_id, @@ -168,13 +167,13 @@ pub struct CfdStateError { #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)] pub struct CfdStateCommon { - pub transition_timestamp: SystemTime, + pub transition_timestamp: Timestamp, } impl Default for CfdStateCommon { fn default() -> Self { Self { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now().expect("Unable to get current time"), } } } @@ -467,7 +466,7 @@ impl CfdState { *common } - pub fn get_transition_timestamp(&self) -> SystemTime { + pub fn get_transition_timestamp(&self) -> Timestamp { self.get_common().transition_timestamp } @@ -547,7 +546,7 @@ pub enum UpdateCfdProposal { #[derive(Debug, Clone)] pub struct SettlementProposal { pub order_id: OrderId, - pub timestamp: SystemTime, + pub timestamp: Timestamp, pub taker: Amount, pub maker: Amount, pub price: Price, @@ -557,7 +556,7 @@ pub struct SettlementProposal { #[derive(Debug, Clone)] pub struct RollOverProposal { pub order_id: OrderId, - pub timestamp: SystemTime, + pub timestamp: Timestamp, } #[derive(Debug, Clone)] @@ -642,7 +641,7 @@ impl Cfd { let settlement = SettlementProposal { order_id: self.order.id, - timestamp: SystemTime::now(), + timestamp: Timestamp::now()?, taker: *payout.taker_amount(), maker: *payout.maker_amount(), price: current_price, @@ -715,7 +714,7 @@ impl Cfd { if let PendingOpen { dlc, .. } = self.state.clone() { CfdState::Open { common: CfdStateCommon { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now()?, }, dlc, attestation: None, @@ -730,7 +729,7 @@ impl Cfd { { CfdState::Open { common: CfdStateCommon { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now()?, }, dlc, attestation, @@ -767,7 +766,7 @@ impl Cfd { OpenCommitted { common: CfdStateCommon { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now()?, }, dlc, cet_status: if let Some(attestation) = attestation { @@ -790,7 +789,7 @@ impl Cfd { .. } => CfdState::OpenCommitted { common: CfdStateCommon { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now()?, }, dlc, cet_status: CetStatus::TimelockExpired, @@ -801,7 +800,7 @@ impl Cfd { .. } => CfdState::OpenCommitted { common: CfdStateCommon { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now()?, }, dlc, cet_status: CetStatus::Ready(attestation), @@ -818,7 +817,7 @@ impl Cfd { tracing::debug!(%order_id, "Was in unexpected state {}, jumping ahead to OpenCommitted", self.state); CfdState::OpenCommitted { common: CfdStateCommon { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now()?, }, dlc, cet_status: match attestation { @@ -885,7 +884,7 @@ impl Cfd { PendingCommit { common: CfdStateCommon { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now()?, }, dlc, attestation, @@ -894,14 +893,14 @@ impl Cfd { CfdStateChangeEvent::OracleAttestation(attestation) => match self.state.clone() { CfdState::PendingOpen { dlc, .. } => CfdState::PendingOpen { common: CfdStateCommon { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now()?, }, dlc, attestation: Some(attestation), }, CfdState::Open { dlc, .. } => CfdState::Open { common: CfdStateCommon { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now()?, }, dlc, attestation: Some(attestation), @@ -912,7 +911,7 @@ impl Cfd { .. } => CfdState::PendingCommit { common: CfdStateCommon { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now()?, }, dlc, attestation: Some(attestation), @@ -923,7 +922,7 @@ impl Cfd { .. } => CfdState::OpenCommitted { common: CfdStateCommon { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now()?, }, dlc, cet_status: CetStatus::OracleSigned(attestation), @@ -934,7 +933,7 @@ impl Cfd { .. } => CfdState::OpenCommitted { common: CfdStateCommon { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now()?, }, dlc, cet_status: CetStatus::Ready(attestation), @@ -952,7 +951,7 @@ impl Cfd { CfdState::PendingCet { common: CfdStateCommon { - transition_timestamp: SystemTime::now(), + transition_timestamp: Timestamp::now()?, }, dlc, attestation, @@ -1798,14 +1797,14 @@ pub struct RevokedCommit { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct CollaborativeSettlement { pub tx: Transaction, - pub timestamp: SystemTime, + pub timestamp: Timestamp, #[serde(with = "::bdk::bitcoin::util::amount::serde::as_sat")] payout: Amount, price: Price, } impl CollaborativeSettlement { - pub fn new(tx: Transaction, own_script_pubkey: Script, price: Price) -> Self { + pub fn new(tx: Transaction, own_script_pubkey: Script, price: Price) -> Result { // Falls back to Amount::ZERO in case we don't find an output that matches out script pubkey // The assumption is, that this can happen for cases where we were liuqidated let payout = match tx @@ -1823,12 +1822,12 @@ impl CollaborativeSettlement { } }; - Self { + Ok(Self { tx, - timestamp: SystemTime::now(), + timestamp: Timestamp::now().context("Unable to get current time")?, payout, price, - } + }) } pub fn payout(&self) -> Amount { diff --git a/daemon/src/taker_cfd.rs b/daemon/src/taker_cfd.rs index 33c9c4d..89f94cc 100644 --- a/daemon/src/taker_cfd.rs +++ b/daemon/src/taker_cfd.rs @@ -5,7 +5,7 @@ use crate::model::cfd::{ OrderId, Origin, Role, RollOverProposal, SettlementKind, SettlementProposal, UpdateCfdProposal, UpdateCfdProposals, }; -use crate::model::{BitMexPriceEventId, Price, Usd}; +use crate::model::{BitMexPriceEventId, Price, Timestamp, Usd}; use crate::monitor::{self, MonitorParams}; use crate::wire::{MakerToTaker, RollOverMsg, SetupMsg}; use crate::{log_error, oracle, setup_contract, wallet, wire}; @@ -15,7 +15,6 @@ use bdk::bitcoin::secp256k1::schnorrsig; use futures::channel::mpsc; use futures::{future, SinkExt}; use std::collections::HashMap; -use std::time::SystemTime; use tokio::sync::watch; use xtra::prelude::*; use xtra::KeepRunning; @@ -357,7 +356,7 @@ where let proposal = RollOverProposal { order_id, - timestamp: SystemTime::now(), + timestamp: Timestamp::now()?, }; self.current_pending_proposals.insert( @@ -634,7 +633,7 @@ where tx.clone(), dlc.script_pubkey_for(cfd.role()), proposal.price, - ), + )?, ))?; append_cfd_state(&cfd, &mut conn, &self.cfd_feed_actor_inbox).await?; diff --git a/daemon/src/to_sse_event.rs b/daemon/src/to_sse_event.rs index 7c4e333..d323e56 100644 --- a/daemon/src/to_sse_event.rs +++ b/daemon/src/to_sse_event.rs @@ -1,7 +1,7 @@ use crate::model::cfd::{ Dlc, OrderId, Payout, Role, SettlementKind, UpdateCfdProposal, UpdateCfdProposals, }; -use crate::model::{Leverage, Position, Price, TradingPair, Usd}; +use crate::model::{Leverage, Position, Price, Timestamp, TradingPair, Usd}; use crate::{bitmex_price_feed, model}; use bdk::bitcoin::{Amount, Network, SignedAmount, Txid}; use rocket::request::FromParam; @@ -9,7 +9,6 @@ use rocket::response::stream::Event; use rust_decimal::Decimal; use serde::{Deserialize, Serialize}; use std::convert::TryInto; -use std::time::{SystemTime, UNIX_EPOCH}; use time::OffsetDateTime; use tokio::sync::watch; @@ -36,7 +35,7 @@ pub struct Cfd { pub state: CfdState, pub actions: Vec, - pub state_transition_timestamp: u64, + pub state_transition_timestamp: i64, pub details: CfdDetails, @@ -171,7 +170,7 @@ pub struct CfdOrder { pub leverage: Leverage, pub liquidation_price: Price, - pub creation_timestamp: u64, + pub creation_timestamp: Timestamp, pub settlement_time_interval_in_secs: u64, } @@ -253,12 +252,7 @@ impl ToSseEvent for CfdsWithAuxData { profit_in_percent: profit_in_percent.to_string(), state: state.clone(), actions: available_actions(state, cfd.role()), - state_transition_timestamp: cfd - .state - .get_transition_timestamp() - .duration_since(UNIX_EPOCH) - .expect("timestamp to be convertable to duration since epoch") - .as_secs(), + state_transition_timestamp: cfd.state.get_transition_timestamp().seconds(), // TODO: Depending on the state the margin might be set (i.e. in Open we save it // in the DB internally) and does not have to be calculated @@ -285,11 +279,7 @@ impl ToSseEvent for Option { max_quantity: order.max_quantity, leverage: order.leverage, liquidation_price: order.liquidation_price, - creation_timestamp: order - .creation_timestamp - .duration_since(UNIX_EPOCH) - .expect("timestamp to be convertible to duration since epoch") - .as_secs(), + creation_timestamp: order.creation_timestamp, settlement_time_interval_in_secs: order .settlement_time_interval_hours .whole_seconds() @@ -306,7 +296,7 @@ pub struct WalletInfo { #[serde(with = "::bdk::bitcoin::util::amount::serde::as_btc")] balance: Amount, address: String, - last_updated_at: u64, + last_updated_at: Timestamp, } impl ToSseEvent for model::WalletInfo { @@ -314,7 +304,7 @@ impl ToSseEvent for model::WalletInfo { let wallet_info = WalletInfo { balance: self.balance, address: self.address.to_string(), - last_updated_at: into_unix_secs(self.last_updated_at), + last_updated_at: self.last_updated_at, }; Event::json(&wallet_info).event("wallet") @@ -421,7 +411,7 @@ fn to_tx_url_list(state: model::cfd::CfdState, network: Network) -> Vec { pub struct Quote { bid: Price, ask: Price, - last_updated_at: u64, + last_updated_at: Timestamp, } impl ToSseEvent for bitmex_price_feed::Quote { @@ -429,19 +419,12 @@ impl ToSseEvent for bitmex_price_feed::Quote { let quote = Quote { bid: self.bid, ask: self.ask, - last_updated_at: into_unix_secs(self.timestamp), + last_updated_at: self.timestamp, }; Event::json("e).event("quote") } } -/// Convert to the format expected by the frontend -fn into_unix_secs(time: SystemTime) -> u64 { - time.duration_since(UNIX_EPOCH) - .expect("timestamp to be convertible to duration since epoch") - .as_secs() -} - fn available_actions(state: CfdState, role: Role) -> Vec { match (state, role) { (CfdState::IncomingOrderRequest { .. }, Role::Maker) => { diff --git a/daemon/src/wallet.rs b/daemon/src/wallet.rs index 47119e9..567f39a 100644 --- a/daemon/src/wallet.rs +++ b/daemon/src/wallet.rs @@ -1,4 +1,4 @@ -use crate::model::WalletInfo; +use crate::model::{Timestamp, WalletInfo}; use anyhow::{Context, Result}; use bdk::bitcoin::consensus::encode::serialize_hex; use bdk::bitcoin::util::bip32::ExtendedPrivKey; @@ -11,7 +11,6 @@ use cfd_protocol::{PartyParams, WalletExt}; use rocket::serde::json::Value; use std::path::Path; use std::sync::Arc; -use std::time::SystemTime; use tokio::sync::Mutex; use xtra_productivity::xtra_productivity; @@ -64,7 +63,7 @@ impl Actor { let wallet_info = WalletInfo { balance: Amount::from_sat(balance), address, - last_updated_at: SystemTime::now(), + last_updated_at: Timestamp::now()?, }; Ok(wallet_info) diff --git a/daemon/src/wire.rs b/daemon/src/wire.rs index 3d89e2f..a833cee 100644 --- a/daemon/src/wire.rs +++ b/daemon/src/wire.rs @@ -1,5 +1,5 @@ use crate::model::cfd::{Order, OrderId}; -use crate::model::{BitMexPriceEventId, Price, Usd}; +use crate::model::{BitMexPriceEventId, Price, Timestamp, Usd}; use anyhow::{bail, Result}; use bdk::bitcoin::secp256k1::Signature; use bdk::bitcoin::util::psbt::PartiallySignedTransaction; @@ -13,7 +13,6 @@ use std::collections::HashMap; use std::fmt; use std::marker::PhantomData; use std::ops::RangeInclusive; -use std::time::SystemTime; use tokio_util::codec::{Decoder, Encoder, LengthDelimitedCodec}; #[derive(Debug, Serialize, Deserialize)] @@ -26,7 +25,7 @@ pub enum TakerToMaker { }, ProposeSettlement { order_id: OrderId, - timestamp: SystemTime, + timestamp: Timestamp, #[serde(with = "::bdk::bitcoin::util::amount::serde::as_btc")] taker: Amount, #[serde(with = "::bdk::bitcoin::util::amount::serde::as_btc")] @@ -39,7 +38,7 @@ pub enum TakerToMaker { }, ProposeRollOver { order_id: OrderId, - timestamp: SystemTime, + timestamp: Timestamp, }, Protocol(SetupMsg), RollOverProtocol(RollOverMsg), diff --git a/daemon/tests/happy_path.rs b/daemon/tests/happy_path.rs index a989fc3..483c222 100644 --- a/daemon/tests/happy_path.rs +++ b/daemon/tests/happy_path.rs @@ -5,7 +5,7 @@ use cfd_protocol::secp256k1_zkp::{schnorrsig, Secp256k1}; use cfd_protocol::PartyParams; use daemon::maker_cfd::CfdAction; use daemon::model::cfd::{Cfd, CfdState, Order}; -use daemon::model::{Price, Usd, WalletInfo}; +use daemon::model::{Price, Timestamp, Usd, WalletInfo}; use daemon::tokio_ext::FutureExt; use daemon::{ connection, db, maker_cfd, maker_inc_connections, monitor, oracle, taker_cfd, wallet, @@ -16,7 +16,7 @@ use sqlx::SqlitePool; use std::net::SocketAddr; use std::str::FromStr; use std::task::Poll; -use std::time::{Duration, SystemTime}; +use std::time::Duration; use tokio::sync::watch; use tracing::subscriber::DefaultGuard; use tracing_subscriber::filter::LevelFilter; @@ -233,7 +233,7 @@ impl Wallet { Ok(WalletInfo { balance: bdk::bitcoin::Amount::ONE_BTC, address, - last_updated_at: SystemTime::now(), + last_updated_at: Timestamp::now()?, }) } async fn handle(&mut self, _msg: wallet::Sign) -> Result {