Browse Source

Nanoseconds begone!

Created new Timestamp struct that only uses seconds (as i64 in order
to play nice with both sqlx and chrono) and removed use of SytemTime::now()
throughout in the process.

This PR addresses #352 but also had the effect of doing a better job of
addressing #434, making #435 pointless.
burn-down-handle
DelicioiusHair 3 years ago
parent
commit
6bd7fe2d78
  1. 2
      Cargo.lock
  2. 1
      daemon/Cargo.toml
  3. 5
      daemon/migrations/20211025050345_rename_term_to_settlement_time_interval.sql
  4. 188
      daemon/sqlx-data.json
  5. 9
      daemon/src/bitmex_price_feed.rs
  6. 79
      daemon/src/db.rs
  7. 7
      daemon/src/maker_cfd.rs
  8. 54
      daemon/src/model.rs
  9. 61
      daemon/src/model/cfd.rs
  10. 7
      daemon/src/taker_cfd.rs
  11. 35
      daemon/src/to_sse_event.rs
  12. 5
      daemon/src/wallet.rs
  13. 7
      daemon/src/wire.rs
  14. 6
      daemon/tests/happy_path.rs

2
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",

1
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"

5
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;

188
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
]
}
}
}

9
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<Output = ()>, watch::Receiver<Quote>)>
#[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(&quote.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)
}
}

79
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<Sqlite>) -> 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<Sqlite>) -> 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::<Usd>()?,
leverage: row.leverage,
liquidation_price: row.liquidation_price.parse::<Price>()?,
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::<BitMexPriceEventId>()?,
})
@ -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::<Usd>()?,
leverage: row.leverage,
liquidation_price: row.liquidation_price.parse::<Price>()?,
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::<BitMexPriceEventId>()?,
};
@ -358,9 +331,7 @@ pub async fn load_all_cfds(conn: &mut PoolConnection<Sqlite>) -> 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<Sqlite>) -> 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<Sqlite>) -> anyhow::Result<
max_quantity: row.max_quantity.parse::<Usd>()?,
leverage: row.leverage,
liquidation_price: row.liquidation_price.parse::<Price>()?,
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::<BitMexPriceEventId>()?,
};
@ -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::<Usd>()?,
leverage: row.leverage,
liquidation_price: row.liquidation_price.parse::<Price>()?,
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::<BitMexPriceEventId>()?,
};
@ -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<SystemTime> {
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;

7
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?;

54
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<Self> {
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<Self> {
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<u64> {
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);
}
}

61
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<Self> {
// 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 {

7
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?;

35
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<CfdAction>,
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<model::cfd::Order> {
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<TxUrl> {
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(&quote).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<CfdAction> {
match (state, role) {
(CfdState::IncomingOrderRequest { .. }, Role::Maker) => {

5
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)

7
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),

6
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<PartiallySignedTransaction> {

Loading…
Cancel
Save