Browse Source

Merge #687

687: Implement sqlx::Type for more datatypes r=da-kami a=thomaseizinger

This maker our DB code slightly simpler because we can directly use
our newtypes in the query and they are also constructed right away
by sqlx.

`@da-kami` `@klochowicz` Could one of you run `./prepare-db.sh` locally? It doesn't work on my machine for some reason ...

Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
debug-collab-settlement
bors[bot] 3 years ago
committed by GitHub
parent
commit
ad2ceda3da
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 138
      daemon/sqlx-data.json
  2. 117
      daemon/src/db.rs
  3. 2
      daemon/src/lib.rs
  4. 11
      daemon/src/model.rs
  5. 2
      daemon/src/model/cfd.rs
  6. 30
      daemon/src/sqlx_ext.rs

138
daemon/sqlx-data.json

@ -1,7 +1,25 @@
{ {
"db": "SQLite", "db": "SQLite",
"04399897350d026ee0830ccaba3638f8aa8f4ef9694d59286f32b9e2449a99fa": { "221a6283db798bacaba99e7e85130f9a8bbea1299d8cb99d272b1d478dc19775": {
"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 ", "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
]
}
},
"3d41b8a81df84252dae228d8512b7491416520a6ad89561f67cdfb673f864a5a": {
"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 as \"initial_price: crate::model::Price\",\n ord.min_quantity as \"min_quantity: crate::model::Usd\",\n ord.max_quantity as \"max_quantity: crate::model::Usd\",\n ord.leverage as \"leverage: crate::model::Leverage\",\n ord.liquidation_price as \"liquidation_price: crate::model::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 as \"oracle_event_id: crate::model::BitMexPriceEventId\",\n state.quantity_usd as \"quantity_usd: crate::model::Usd\",\n state.state\n\n from ord\n inner join state on state.order_id = ord.order_id\n ",
"describe": { "describe": {
"columns": [ "columns": [
{ {
@ -20,17 +38,17 @@
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "initial_price", "name": "initial_price: crate::model::Price",
"ordinal": 3, "ordinal": 3,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "min_quantity", "name": "min_quantity: crate::model::Usd",
"ordinal": 4, "ordinal": 4,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "max_quantity", "name": "max_quantity: crate::model::Usd",
"ordinal": 5, "ordinal": 5,
"type_info": "Text" "type_info": "Text"
}, },
@ -40,7 +58,7 @@
"type_info": "Int64" "type_info": "Int64"
}, },
{ {
"name": "liquidation_price", "name": "liquidation_price: crate::model::Price",
"ordinal": 7, "ordinal": 7,
"type_info": "Text" "type_info": "Text"
}, },
@ -60,12 +78,12 @@
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "oracle_event_id", "name": "oracle_event_id: crate::model::BitMexPriceEventId",
"ordinal": 11, "ordinal": 11,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "quantity_usd", "name": "quantity_usd: crate::model::Usd",
"ordinal": 12, "ordinal": 12,
"type_info": "Text" "type_info": "Text"
}, },
@ -76,7 +94,7 @@
} }
], ],
"parameters": { "parameters": {
"Right": 1 "Right": 0
}, },
"nullable": [ "nullable": [
false, false,
@ -96,26 +114,8 @@
] ]
} }
}, },
"221a6283db798bacaba99e7e85130f9a8bbea1299d8cb99d272b1d478dc19775": { "414ecf7f0cfce0a1a482b1b430d960867df835aae7fe1b306aa7f22353795dcf": {
"query": "\n select\n state\n from cfd_states\n where cfd_id = $1\n order by id desc\n limit 1;\n ", "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 as \"initial_price: crate::model::Price\",\n ord.min_quantity as \"min_quantity: crate::model::Usd\",\n ord.max_quantity as \"max_quantity: crate::model::Usd\",\n ord.leverage as \"leverage: crate::model::Leverage\",\n ord.liquidation_price as \"liquidation_price: crate::model::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 as \"oracle_event_id: crate::model::BitMexPriceEventId\",\n state.quantity_usd as \"quantity_usd: crate::model::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": [
{
"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": { "describe": {
"columns": [ "columns": [
{ {
@ -134,17 +134,17 @@
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "initial_price", "name": "initial_price: crate::model::Price",
"ordinal": 3, "ordinal": 3,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "min_quantity", "name": "min_quantity: crate::model::Usd",
"ordinal": 4, "ordinal": 4,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "max_quantity", "name": "max_quantity: crate::model::Usd",
"ordinal": 5, "ordinal": 5,
"type_info": "Text" "type_info": "Text"
}, },
@ -154,7 +154,7 @@
"type_info": "Int64" "type_info": "Int64"
}, },
{ {
"name": "liquidation_price", "name": "liquidation_price: crate::model::Price",
"ordinal": 7, "ordinal": 7,
"type_info": "Text" "type_info": "Text"
}, },
@ -174,12 +174,12 @@
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "oracle_event_id", "name": "oracle_event_id: crate::model::BitMexPriceEventId",
"ordinal": 11, "ordinal": 11,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "quantity_usd", "name": "quantity_usd: crate::model::Usd",
"ordinal": 12, "ordinal": 12,
"type_info": "Text" "type_info": "Text"
}, },
@ -190,7 +190,7 @@
} }
], ],
"parameters": { "parameters": {
"Right": 0 "Right": 1
}, },
"nullable": [ "nullable": [
false, false,
@ -210,8 +210,8 @@
] ]
} }
}, },
"4bb5424ebcd683a149f15df5560fdea6727174f4cd6e0709e526ac3a690e2e5e": { "5569292de42c8ce5cff83beb43af1f8e6c3c12b17e740550c1303a1a6d151100": {
"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 ", "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 as \"initial_price: crate::model::Price\",\n min_quantity as \"min_quantity: crate::model::Usd\",\n max_quantity as \"max_quantity: crate::model::Usd\",\n leverage as \"leverage: crate::model::Leverage\",\n liquidation_price as \"liquidation_price: crate::model::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 as \"oracle_event_id: crate::model::BitMexPriceEventId\"\n from\n orders\n where\n uuid = $1\n ",
"describe": { "describe": {
"columns": [ "columns": [
{ {
@ -230,17 +230,17 @@
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "initial_price", "name": "initial_price: crate::model::Price",
"ordinal": 3, "ordinal": 3,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "min_quantity", "name": "min_quantity: crate::model::Usd",
"ordinal": 4, "ordinal": 4,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "max_quantity", "name": "max_quantity: crate::model::Usd",
"ordinal": 5, "ordinal": 5,
"type_info": "Text" "type_info": "Text"
}, },
@ -250,7 +250,7 @@
"type_info": "Int64" "type_info": "Int64"
}, },
{ {
"name": "liquidation_price", "name": "liquidation_price: crate::model::Price",
"ordinal": 7, "ordinal": 7,
"type_info": "Text" "type_info": "Text"
}, },
@ -270,7 +270,7 @@
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "oracle_event_id", "name": "oracle_event_id: crate::model::BitMexPriceEventId",
"ordinal": 11, "ordinal": 11,
"type_info": "Text" "type_info": "Text"
} }
@ -294,8 +294,26 @@
] ]
} }
}, },
"6dbd14a613a982521b4cc9179fd6f6b0298c0a4475508536379e9b82c9f2d0a0": { "8cbe349911b35d8e79763d64b4f5813b4bd98f12e0bba5ada84d2cae8b08ef4f": {
"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 ", "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
]
}
},
"f822252e3d3eb70a03300529d8de8f553e8d97b1aac72fb964cbde49d65fe153": {
"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 as \"initial_price: crate::model::Price\",\n ord.min_quantity as \"min_quantity: crate::model::Usd\",\n ord.max_quantity as \"max_quantity: crate::model::Usd\",\n ord.leverage as \"leverage: crate::model::Leverage\",\n ord.liquidation_price as \"liquidation_price: crate::model::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 as \"oracle_event_id: crate::model::BitMexPriceEventId\",\n state.quantity_usd as \"quantity_usd: crate::model::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": { "describe": {
"columns": [ "columns": [
{ {
@ -314,17 +332,17 @@
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "initial_price", "name": "initial_price: crate::model::Price",
"ordinal": 3, "ordinal": 3,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "min_quantity", "name": "min_quantity: crate::model::Usd",
"ordinal": 4, "ordinal": 4,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "max_quantity", "name": "max_quantity: crate::model::Usd",
"ordinal": 5, "ordinal": 5,
"type_info": "Text" "type_info": "Text"
}, },
@ -334,7 +352,7 @@
"type_info": "Int64" "type_info": "Int64"
}, },
{ {
"name": "liquidation_price", "name": "liquidation_price: crate::model::Price",
"ordinal": 7, "ordinal": 7,
"type_info": "Text" "type_info": "Text"
}, },
@ -354,12 +372,12 @@
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "oracle_event_id", "name": "oracle_event_id: crate::model::BitMexPriceEventId",
"ordinal": 11, "ordinal": 11,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "quantity_usd", "name": "quantity_usd: crate::model::Usd",
"ordinal": 12, "ordinal": 12,
"type_info": "Text" "type_info": "Text"
}, },
@ -389,23 +407,5 @@
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
]
}
} }
} }

117
daemon/src/db.rs

@ -1,11 +1,9 @@
use crate::model::cfd::{Cfd, CfdState, Order, OrderId}; use crate::model::cfd::{Cfd, CfdState, Order, OrderId};
use crate::model::{BitMexPriceEventId, Usd}; use crate::model::BitMexPriceEventId;
use anyhow::{bail, Context, Result}; use anyhow::{bail, Context, Result};
use rust_decimal::Decimal;
use sqlx::pool::PoolConnection; use sqlx::pool::PoolConnection;
use sqlx::{Sqlite, SqlitePool}; use sqlx::{Sqlite, SqlitePool};
use std::mem; use std::mem;
use std::str::FromStr;
use time::Duration; use time::Duration;
pub async fn run_migrations(pool: &SqlitePool) -> anyhow::Result<()> { pub async fn run_migrations(pool: &SqlitePool) -> anyhow::Result<()> {
@ -33,15 +31,15 @@ pub async fn insert_order(order: &Order, conn: &mut PoolConnection<Sqlite>) -> a
.bind(&order.id) .bind(&order.id)
.bind(&order.trading_pair) .bind(&order.trading_pair)
.bind(&order.position) .bind(&order.position)
.bind(&order.price.to_string()) .bind(&order.price)
.bind(&order.min_quantity.to_string()) .bind(&order.min_quantity)
.bind(&order.max_quantity.to_string()) .bind(&order.max_quantity)
.bind(order.leverage.get()) .bind(&order.leverage)
.bind(&order.liquidation_price.to_string()) .bind(&order.liquidation_price)
.bind(&order.creation_timestamp.seconds()) .bind(&order.creation_timestamp.seconds())
.bind(&order.settlement_interval.whole_seconds()) .bind(&order.settlement_interval.whole_seconds())
.bind(&order.origin) .bind(&order.origin)
.bind(&order.oracle_event_id.to_string()) .bind(&order.oracle_event_id)
.execute(conn) .execute(conn)
.await?; .await?;
@ -62,18 +60,19 @@ pub async fn load_order_by_id(
uuid as "uuid: crate::model::cfd::OrderId", uuid as "uuid: crate::model::cfd::OrderId",
trading_pair as "trading_pair: crate::model::TradingPair", trading_pair as "trading_pair: crate::model::TradingPair",
position as "position: crate::model::Position", position as "position: crate::model::Position",
initial_price, initial_price as "initial_price: crate::model::Price",
min_quantity, min_quantity as "min_quantity: crate::model::Usd",
max_quantity, max_quantity as "max_quantity: crate::model::Usd",
leverage as "leverage: crate::model::Leverage", leverage as "leverage: crate::model::Leverage",
liquidation_price, liquidation_price as "liquidation_price: crate::model::Price",
creation_timestamp_seconds as "ts_secs: crate::model::Timestamp", creation_timestamp_seconds as "ts_secs: crate::model::Timestamp",
settlement_time_interval_seconds as "settlement_time_interval_secs: i64", settlement_time_interval_seconds as "settlement_time_interval_secs: i64",
origin as "origin: crate::model::cfd::Origin", origin as "origin: crate::model::cfd::Origin",
oracle_event_id oracle_event_id as "oracle_event_id: crate::model::BitMexPriceEventId"
from
from orders orders
where uuid = $1 where
uuid = $1
"#, "#,
id id
) )
@ -84,15 +83,15 @@ pub async fn load_order_by_id(
id: row.uuid, id: row.uuid,
trading_pair: row.trading_pair, trading_pair: row.trading_pair,
position: row.position, position: row.position,
price: row.initial_price.parse()?, price: row.initial_price,
min_quantity: row.min_quantity.parse()?, min_quantity: row.min_quantity,
max_quantity: row.max_quantity.parse()?, max_quantity: row.max_quantity,
leverage: row.leverage, leverage: row.leverage,
liquidation_price: row.liquidation_price.parse()?, liquidation_price: row.liquidation_price,
creation_timestamp: row.ts_secs, creation_timestamp: row.ts_secs,
settlement_interval: Duration::new(row.settlement_time_interval_secs, 0), settlement_interval: Duration::new(row.settlement_time_interval_secs, 0),
origin: row.origin, origin: row.origin,
oracle_event_id: row.oracle_event_id.parse()?, oracle_event_id: row.oracle_event_id,
}) })
} }
@ -131,7 +130,7 @@ pub async fn insert_cfd(cfd: &Cfd, conn: &mut PoolConnection<Sqlite>) -> anyhow:
"#, "#,
) )
.bind(&cfd.order.id) .bind(&cfd.order.id)
.bind(&cfd.quantity_usd.to_string()) .bind(&cfd.quantity_usd)
.bind(state) .bind(state)
.execute(conn) .execute(conn)
.await?; .await?;
@ -275,16 +274,16 @@ pub async fn load_cfd_by_order_id(
ord.uuid as "uuid: crate::model::cfd::OrderId", ord.uuid as "uuid: crate::model::cfd::OrderId",
ord.trading_pair as "trading_pair: crate::model::TradingPair", ord.trading_pair as "trading_pair: crate::model::TradingPair",
ord.position as "position: crate::model::Position", ord.position as "position: crate::model::Position",
ord.initial_price, ord.initial_price as "initial_price: crate::model::Price",
ord.min_quantity, ord.min_quantity as "min_quantity: crate::model::Usd",
ord.max_quantity, ord.max_quantity as "max_quantity: crate::model::Usd",
ord.leverage as "leverage: crate::model::Leverage", ord.leverage as "leverage: crate::model::Leverage",
ord.liquidation_price, ord.liquidation_price as "liquidation_price: crate::model::Price",
ord.ts_secs as "ts_secs: crate::model::Timestamp", ord.ts_secs as "ts_secs: crate::model::Timestamp",
ord.settlement_time_interval_secs as "settlement_time_interval_secs: i64", ord.settlement_time_interval_secs as "settlement_time_interval_secs: i64",
ord.origin as "origin: crate::model::cfd::Origin", ord.origin as "origin: crate::model::cfd::Origin",
ord.oracle_event_id, ord.oracle_event_id as "oracle_event_id: crate::model::BitMexPriceEventId",
state.quantity_usd, state.quantity_usd as "quantity_usd: crate::model::Usd",
state.state state.state
from ord from ord
@ -301,15 +300,15 @@ pub async fn load_cfd_by_order_id(
id: row.uuid, id: row.uuid,
trading_pair: row.trading_pair, trading_pair: row.trading_pair,
position: row.position, position: row.position,
price: row.initial_price.parse()?, price: row.initial_price,
min_quantity: row.min_quantity.parse()?, min_quantity: row.min_quantity,
max_quantity: row.max_quantity.parse()?, max_quantity: row.max_quantity,
leverage: row.leverage, leverage: row.leverage,
liquidation_price: row.liquidation_price.parse()?, liquidation_price: row.liquidation_price,
creation_timestamp: row.ts_secs, creation_timestamp: row.ts_secs,
settlement_interval: Duration::new(row.settlement_time_interval_secs, 0), settlement_interval: Duration::new(row.settlement_time_interval_secs, 0),
origin: row.origin, origin: row.origin,
oracle_event_id: row.oracle_event_id.parse()?, oracle_event_id: row.oracle_event_id,
}; };
// TODO: // TODO:
@ -317,7 +316,7 @@ pub async fn load_cfd_by_order_id(
// via https://github.com/comit-network/hermes/issues/290 // via https://github.com/comit-network/hermes/issues/290
Ok(Cfd { Ok(Cfd {
order, order,
quantity_usd: Usd::new(Decimal::from_str(&row.quantity_usd)?), quantity_usd: row.quantity_usd,
state: serde_json::from_str(row.state.as_str())?, state: serde_json::from_str(row.state.as_str())?,
}) })
} }
@ -373,16 +372,16 @@ pub async fn load_all_cfds(conn: &mut PoolConnection<Sqlite>) -> anyhow::Result<
ord.uuid as "uuid: crate::model::cfd::OrderId", ord.uuid as "uuid: crate::model::cfd::OrderId",
ord.trading_pair as "trading_pair: crate::model::TradingPair", ord.trading_pair as "trading_pair: crate::model::TradingPair",
ord.position as "position: crate::model::Position", ord.position as "position: crate::model::Position",
ord.initial_price, ord.initial_price as "initial_price: crate::model::Price",
ord.min_quantity, ord.min_quantity as "min_quantity: crate::model::Usd",
ord.max_quantity, ord.max_quantity as "max_quantity: crate::model::Usd",
ord.leverage as "leverage: crate::model::Leverage", ord.leverage as "leverage: crate::model::Leverage",
ord.liquidation_price, ord.liquidation_price as "liquidation_price: crate::model::Price",
ord.ts_secs as "ts_secs: crate::model::Timestamp", ord.ts_secs as "ts_secs: crate::model::Timestamp",
ord.settlement_time_interval_secs as "settlement_time_interval_secs: i64", ord.settlement_time_interval_secs as "settlement_time_interval_secs: i64",
ord.origin as "origin: crate::model::cfd::Origin", ord.origin as "origin: crate::model::cfd::Origin",
ord.oracle_event_id, ord.oracle_event_id as "oracle_event_id: crate::model::BitMexPriceEventId",
state.quantity_usd, state.quantity_usd as "quantity_usd: crate::model::Usd",
state.state state.state
from ord from ord
@ -399,20 +398,20 @@ pub async fn load_all_cfds(conn: &mut PoolConnection<Sqlite>) -> anyhow::Result<
id: row.uuid, id: row.uuid,
trading_pair: row.trading_pair, trading_pair: row.trading_pair,
position: row.position, position: row.position,
price: row.initial_price.parse()?, price: row.initial_price,
min_quantity: row.min_quantity.parse()?, min_quantity: row.min_quantity,
max_quantity: row.max_quantity.parse()?, max_quantity: row.max_quantity,
leverage: row.leverage, leverage: row.leverage,
liquidation_price: row.liquidation_price.parse()?, liquidation_price: row.liquidation_price,
creation_timestamp: row.ts_secs, creation_timestamp: row.ts_secs,
settlement_interval: Duration::new(row.settlement_time_interval_secs, 0), settlement_interval: Duration::new(row.settlement_time_interval_secs, 0),
origin: row.origin, origin: row.origin,
oracle_event_id: row.oracle_event_id.parse()?, oracle_event_id: row.oracle_event_id,
}; };
Ok(Cfd { Ok(Cfd {
order, order,
quantity_usd: Usd::new(Decimal::from_str(&row.quantity_usd)?), quantity_usd: row.quantity_usd,
state: serde_json::from_str(row.state.as_str())?, state: serde_json::from_str(row.state.as_str())?,
}) })
}) })
@ -476,16 +475,16 @@ pub async fn load_cfds_by_oracle_event_id(
ord.uuid as "uuid: crate::model::cfd::OrderId", ord.uuid as "uuid: crate::model::cfd::OrderId",
ord.trading_pair as "trading_pair: crate::model::TradingPair", ord.trading_pair as "trading_pair: crate::model::TradingPair",
ord.position as "position: crate::model::Position", ord.position as "position: crate::model::Position",
ord.initial_price, ord.initial_price as "initial_price: crate::model::Price",
ord.min_quantity, ord.min_quantity as "min_quantity: crate::model::Usd",
ord.max_quantity, ord.max_quantity as "max_quantity: crate::model::Usd",
ord.leverage as "leverage: crate::model::Leverage", ord.leverage as "leverage: crate::model::Leverage",
ord.liquidation_price, ord.liquidation_price as "liquidation_price: crate::model::Price",
ord.ts_secs as "ts_secs: crate::model::Timestamp", ord.ts_secs as "ts_secs: crate::model::Timestamp",
ord.settlement_time_interval_secs as "settlement_time_interval_secs: i64", ord.settlement_time_interval_secs as "settlement_time_interval_secs: i64",
ord.origin as "origin: crate::model::cfd::Origin", ord.origin as "origin: crate::model::cfd::Origin",
ord.oracle_event_id, ord.oracle_event_id as "oracle_event_id: crate::model::BitMexPriceEventId",
state.quantity_usd, state.quantity_usd as "quantity_usd: crate::model::Usd",
state.state state.state
from ord from ord
@ -505,20 +504,20 @@ pub async fn load_cfds_by_oracle_event_id(
id: row.uuid, id: row.uuid,
trading_pair: row.trading_pair, trading_pair: row.trading_pair,
position: row.position, position: row.position,
price: row.initial_price.parse()?, price: row.initial_price,
min_quantity: row.min_quantity.parse()?, min_quantity: row.min_quantity,
max_quantity: row.max_quantity.parse()?, max_quantity: row.max_quantity,
leverage: row.leverage, leverage: row.leverage,
liquidation_price: row.liquidation_price.parse()?, liquidation_price: row.liquidation_price,
creation_timestamp: row.ts_secs, creation_timestamp: row.ts_secs,
settlement_interval: Duration::new(row.settlement_time_interval_secs, 0), settlement_interval: Duration::new(row.settlement_time_interval_secs, 0),
origin: row.origin, origin: row.origin,
oracle_event_id: row.oracle_event_id.parse()?, oracle_event_id: row.oracle_event_id,
}; };
Ok(Cfd { Ok(Cfd {
order, order,
quantity_usd: row.quantity_usd.parse()?, quantity_usd: row.quantity_usd,
state: serde_json::from_str(row.state.as_str())?, state: serde_json::from_str(row.state.as_str())?,
}) })
}) })

2
daemon/src/lib.rs

@ -16,6 +16,8 @@ use tokio::sync::watch;
use xtra::message_channel::{MessageChannel, StrongMessageChannel}; use xtra::message_channel::{MessageChannel, StrongMessageChannel};
use xtra::{Actor, Address}; use xtra::{Actor, Address};
pub mod sqlx_ext; // Must come first because it is a macro.
pub mod actors; pub mod actors;
pub mod auth; pub mod auth;
pub mod bitmex_price_feed; pub mod bitmex_price_feed;

11
daemon/src/model.rs

@ -1,4 +1,4 @@
use crate::olivia; use crate::{impl_sqlx_type_display_from_str, olivia};
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use bdk::bitcoin::{Address, Amount, Denomination}; use bdk::bitcoin::{Address, Amount, Denomination};
use chrono::DateTime; use chrono::DateTime;
@ -62,9 +62,13 @@ impl str::FromStr for Usd {
} }
} }
impl_sqlx_type_display_from_str!(Usd);
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Serialize, Deserialize)] #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Price(Decimal); pub struct Price(Decimal);
impl_sqlx_type_display_from_str!(Price);
impl Price { impl Price {
pub fn new(value: Decimal) -> Result<Self, Error> { pub fn new(value: Decimal) -> Result<Self, Error> {
if value == Decimal::ZERO { if value == Decimal::ZERO {
@ -133,6 +137,7 @@ impl InversePrice {
} }
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, sqlx::Type)] #[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, sqlx::Type)]
#[sqlx(transparent)]
pub struct Leverage(u8); pub struct Leverage(u8);
impl Leverage { impl Leverage {
@ -377,7 +382,7 @@ pub enum TradingPair {
BtcUsd, BtcUsd,
} }
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, sqlx::Type)] #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, sqlx::Type)]
pub enum Position { pub enum Position {
Long, Long,
Short, Short,
@ -507,6 +512,8 @@ impl str::FromStr for BitMexPriceEventId {
} }
} }
impl_sqlx_type_display_from_str!(BitMexPriceEventId);
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, sqlx::Type)] #[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, sqlx::Type)]
pub struct Timestamp(i64); pub struct Timestamp(i64);

2
daemon/src/model/cfd.rs

@ -660,7 +660,7 @@ impl Cfd {
pub fn position(&self) -> Position { pub fn position(&self) -> Position {
match self.order.origin { match self.order.origin {
Origin::Ours => self.order.position.clone(), Origin::Ours => self.order.position,
// If the order is not our own we take the counter-position in the CFD // If the order is not our own we take the counter-position in the CFD
Origin::Theirs => match self.order.position { Origin::Theirs => match self.order.position {

30
daemon/src/sqlx_ext.rs

@ -0,0 +1,30 @@
#[macro_export]
macro_rules! impl_sqlx_type_display_from_str {
($ty:ty) => {
impl sqlx::Type<sqlx::Sqlite> for $ty {
fn type_info() -> sqlx::sqlite::SqliteTypeInfo {
String::type_info()
}
}
impl<'q> sqlx::Encode<'q, sqlx::Sqlite> for $ty {
fn encode_by_ref(
&self,
args: &mut Vec<sqlx::sqlite::SqliteArgumentValue<'q>>,
) -> sqlx::encode::IsNull {
self.to_string().encode_by_ref(args)
}
}
impl<'r> sqlx::Decode<'r, sqlx::Sqlite> for $ty {
fn decode(
value: sqlx::sqlite::SqliteValueRef<'r>,
) -> Result<Self, sqlx::error::BoxDynError> {
let string = String::decode(value)?;
let value = string.parse()?;
Ok(value)
}
}
};
}
Loading…
Cancel
Save