Browse Source

Revert "Db refactor"

refactor/no-log-handler
Thomas Eizinger 3 years ago
committed by GitHub
parent
commit
237f4c25bf
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      Cargo.lock
  2. 2
      daemon/Cargo.toml
  3. 28
      daemon/migrations/20210903050345_create_cfd_and_order_tables.sql
  4. 292
      daemon/sqlx-data.json
  5. 688
      daemon/src/db.rs
  6. 19
      daemon/src/model.rs
  7. 5
      daemon/src/model/cfd.rs

1
Cargo.lock

@ -2616,7 +2616,6 @@ dependencies = [
"thiserror", "thiserror",
"tokio-stream", "tokio-stream",
"url", "url",
"uuid",
"webpki", "webpki",
"webpki-roots 0.21.1", "webpki-roots 0.21.1",
"whoami", "whoami",

2
daemon/Cargo.toml

@ -32,7 +32,7 @@ serde_json = "1"
serde_plain = "1" serde_plain = "1"
serde_with = { version = "1", features = ["macros"] } serde_with = { version = "1", features = ["macros"] }
sha2 = "0.9" sha2 = "0.9"
sqlx = { version = "0.5", features = ["offline", "sqlite", "uuid"] } sqlx = { version = "0.5", features = ["offline"] }
thiserror = "1" thiserror = "1"
time = { version = "0.3", features = ["serde"] } time = { version = "0.3", features = ["serde"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "net"] } tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "net"] }

28
daemon/migrations/20210903050345_create_cfd_and_order_tables.sql

@ -1,21 +1,19 @@
-- todo: Decimal is had to deserialize as number so we use text -- todo: Decimal is had to deserialize as number so we use text
create table if not exists orders create table if not exists orders
( (
id integer primary key autoincrement, id integer primary key autoincrement,
uuid text unique not null, uuid text unique not null,
trading_pair text not null, trading_pair text not null,
position text not null, position text not null,
initial_price text not null, initial_price text not null,
min_quantity text not null, min_quantity text not null,
max_quantity text not null, max_quantity text not null,
leverage integer not null, leverage integer not null,
liquidation_price text not null, liquidation_price text not null,
creation_timestamp_seconds integer not null, creation_timestamp text not null,
creation_timestamp_nanoseconds integer not null, term text not null,
term_seconds integer not null, origin text not null,
term_nanoseconds integer not null, oracle_event_id text not null
origin text not null,
oracle_event_id text not null
); );
create unique index if not exists orders_uuid create unique index if not exists orders_uuid

292
daemon/sqlx-data.json

@ -1,92 +1,100 @@
{ {
"db": "SQLite", "db": "SQLite",
"0862abd1900c5c5ae4a145635c19aef1a563ea470530d83325839868ffacd7bf": { "50abbb297394739ec9d85917f8c32aa8bcfa0bfe140b24e9eeda4ce8d30d4f8d": {
"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 term_seconds as term_secs,\n term_nanoseconds as term_nanos,\n origin,\n oracle_event_id\n from orders\n ),\n\n cfd as (\n select\n id as cfd_id,\n order_id,\n quantity_usd\n from cfds\n ),\n\n tmp as (\n select\n id as state_id,\n cfd_id,\n state\n from cfd_states\n ),\n\n state as (\n select\n tmp.state,\n cfd.order_id,\n cfd.quantity_usd\n from tmp\n inner join cfd on tmp.cfd_id = cfd.cfd_id\n where tmp.state_id in (\n select max(state_id)\n from tmp\n group by state_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.term_secs as \"term_secs: i64\",\n ord.term_nanos as \"term_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 ", "query": "\n select\n state\n from cfd_states\n where cfd_id = ?\n order by id desc\n limit 1;\n ",
"describe": { "describe": {
"columns": [ "columns": [
{ {
"name": "uuid: crate::model::cfd::OrderId", "name": "state",
"ordinal": 0,
"type_info": "Text"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
}
},
"63c8fd1a1512b55c19feea463dbb6a0fdf98a325801ba8677e2a33fd3ee1ebb9": {
"query": "\n select\n orders.uuid as order_id,\n orders.initial_price as price,\n orders.min_quantity as min_quantity,\n orders.max_quantity as max_quantity,\n orders.leverage as leverage,\n orders.trading_pair as trading_pair,\n orders.position as position,\n orders.origin as origin,\n orders.liquidation_price as liquidation_price,\n orders.creation_timestamp as creation_timestamp,\n orders.term as term,\n orders.oracle_event_id,\n cfds.quantity_usd as quantity_usd,\n cfd_states.state as state\n from cfds as cfds\n inner join orders as orders on cfds.order_id = orders.id\n inner join cfd_states as cfd_states on cfd_states.cfd_id = cfds.id\n where cfd_states.state in (\n select\n state\n from cfd_states\n where cfd_id = cfds.id\n order by id desc\n limit 1\n )\n ",
"describe": {
"columns": [
{
"name": "order_id",
"ordinal": 0, "ordinal": 0,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "trading_pair: crate::model::TradingPair", "name": "price",
"ordinal": 1, "ordinal": 1,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "position: crate::model::Position", "name": "min_quantity",
"ordinal": 2, "ordinal": 2,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "initial_price", "name": "max_quantity",
"ordinal": 3, "ordinal": 3,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "min_quantity", "name": "leverage",
"ordinal": 4, "ordinal": 4,
"type_info": "Text" "type_info": "Int64"
}, },
{ {
"name": "max_quantity", "name": "trading_pair",
"ordinal": 5, "ordinal": 5,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "leverage: crate::model::Leverage", "name": "position",
"ordinal": 6, "ordinal": 6,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "liquidation_price", "name": "origin",
"ordinal": 7, "ordinal": 7,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "ts_secs: i64", "name": "liquidation_price",
"ordinal": 8, "ordinal": 8,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "ts_nanos: i32", "name": "creation_timestamp",
"ordinal": 9, "ordinal": 9,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "term_secs: i64", "name": "term",
"ordinal": 10, "ordinal": 10,
"type_info": "Int64"
},
{
"name": "term_nanos: i32",
"ordinal": 11,
"type_info": "Int64"
},
{
"name": "origin: crate::model::cfd::Origin",
"ordinal": 12,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "oracle_event_id", "name": "oracle_event_id",
"ordinal": 13, "ordinal": 11,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "quantity_usd", "name": "quantity_usd",
"ordinal": 14, "ordinal": 12,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "state", "name": "state",
"ordinal": 15, "ordinal": 13,
"type_info": "Text" "type_info": "Text"
} }
], ],
"parameters": { "parameters": {
"Right": 1 "Right": 0
}, },
"nullable": [ "nullable": [
false, false,
@ -102,112 +110,120 @@
false, false,
false, false,
false, false,
false,
false,
false false
] ]
} }
}, },
"221a6283db798bacaba99e7e85130f9a8bbea1299d8cb99d272b1d478dc19775": { "8e7571250da58b12f5884f17656e5966957c7798ea029c701a4fc43fd613f015": {
"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 select\n id\n from cfds\n where order_uuid = ?;\n ",
"describe": { "describe": {
"columns": [ "columns": [
{ {
"name": "state", "name": "id",
"ordinal": 0, "ordinal": 0,
"type_info": "Text" "type_info": "Int64"
} }
], ],
"parameters": { "parameters": {
"Right": 1 "Right": 1
}, },
"nullable": [ "nullable": [
false true
] ]
} }
}, },
"62c4b31272cc2c889ebc946f4eaa3160ef2cf8c272412a77e9339249468d14bf": { "a464a1feb12abadff8bfd5b2b3b7362f3846869c0702944b21737eff8f420be5": {
"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 term_seconds as term_secs,\n term_nanoseconds as term_nanos,\n origin,\n oracle_event_id\n from orders\n ),\n\n cfd as (\n select\n id as cfd_id,\n order_id,\n quantity_usd as quantity_usd\n from cfds\n ),\n\n tmp as (\n select\n id as state_id,\n cfd_id,\n state\n from cfd_states\n ),\n\n state as (\n select\n tmp.state,\n cfd.order_id,\n cfd.quantity_usd\n from tmp\n inner join cfd on tmp.cfd_id = cfd.cfd_id\n where tmp.state_id in (\n select max(state_id)\n from tmp\n group by state_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.term_secs as \"term_secs: i64\",\n ord.term_nanos as \"term_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 ", "query": "\n insert into cfd_states (\n cfd_id,\n state\n ) values (?, ?);\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
}
},
"a59cf0824b5e4191c94c229086ce464d1b8084f65a6fafb165d27ce6df5b815b": {
"query": "\n insert into orders (\n uuid,\n trading_pair,\n position,\n initial_price,\n min_quantity,\n max_quantity,\n leverage,\n liquidation_price,\n creation_timestamp,\n term,\n origin,\n oracle_event_id\n ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 12
},
"nullable": []
}
},
"e0d3fe192c419be4fa65199d1e024ce8794e19a847be53038b7a8a33afb36bd2": {
"query": "\n select\n orders.uuid as order_id,\n orders.initial_price as price,\n orders.min_quantity as min_quantity,\n orders.max_quantity as max_quantity,\n orders.leverage as leverage,\n orders.trading_pair as trading_pair,\n orders.position as position,\n orders.origin as origin,\n orders.liquidation_price as liquidation_price,\n orders.creation_timestamp as creation_timestamp,\n orders.term as term,\n orders.oracle_event_id,\n cfds.quantity_usd as quantity_usd,\n cfd_states.state as state\n from cfds as cfds\n inner join orders as orders on cfds.order_id = orders.id\n inner join cfd_states as cfd_states on cfd_states.cfd_id = cfds.id\n where cfd_states.state in (\n select\n state\n from cfd_states\n where cfd_id = cfds.id\n order by id desc\n limit 1\n )\n and orders.uuid = ?\n ",
"describe": { "describe": {
"columns": [ "columns": [
{ {
"name": "uuid: crate::model::cfd::OrderId", "name": "order_id",
"ordinal": 0, "ordinal": 0,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "trading_pair: crate::model::TradingPair", "name": "price",
"ordinal": 1, "ordinal": 1,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "position: crate::model::Position", "name": "min_quantity",
"ordinal": 2, "ordinal": 2,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "initial_price", "name": "max_quantity",
"ordinal": 3, "ordinal": 3,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "min_quantity", "name": "leverage",
"ordinal": 4, "ordinal": 4,
"type_info": "Text" "type_info": "Int64"
}, },
{ {
"name": "max_quantity", "name": "trading_pair",
"ordinal": 5, "ordinal": 5,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "leverage: crate::model::Leverage", "name": "position",
"ordinal": 6, "ordinal": 6,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "liquidation_price", "name": "origin",
"ordinal": 7, "ordinal": 7,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "ts_secs: i64", "name": "liquidation_price",
"ordinal": 8, "ordinal": 8,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "ts_nanos: i32", "name": "creation_timestamp",
"ordinal": 9, "ordinal": 9,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "term_secs: i64", "name": "term",
"ordinal": 10, "ordinal": 10,
"type_info": "Int64"
},
{
"name": "term_nanos: i32",
"ordinal": 11,
"type_info": "Int64"
},
{
"name": "origin: crate::model::cfd::Origin",
"ordinal": 12,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "oracle_event_id", "name": "oracle_event_id",
"ordinal": 13, "ordinal": 11,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "quantity_usd", "name": "quantity_usd",
"ordinal": 14, "ordinal": 12,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "state", "name": "state",
"ordinal": 15, "ordinal": 13,
"type_info": "Text" "type_info": "Text"
} }
], ],
@ -228,101 +244,81 @@
false, false,
false, false,
false, false,
false,
false,
false false
] ]
} }
}, },
"8cbe349911b35d8e79763d64b4f5813b4bd98f12e0bba5ada84d2cae8b08ef4f": { "e45a49eb1fb4cbddc046712d9e2df2db0c18c618f0fae2133e51d82eda6bec36": {
"query": "\n select\n id\n from cfds\n where order_uuid = $1;\n ", "query": "\n select\n orders.uuid as order_id,\n orders.initial_price as price,\n orders.min_quantity as min_quantity,\n orders.max_quantity as max_quantity,\n orders.leverage as leverage,\n orders.trading_pair as trading_pair,\n orders.position as position,\n orders.origin as origin,\n orders.liquidation_price as liquidation_price,\n orders.creation_timestamp as creation_timestamp,\n orders.term as term,\n orders.oracle_event_id,\n cfds.quantity_usd as quantity_usd,\n cfd_states.state as state\n from cfds as cfds\n inner join orders as orders on cfds.order_id = orders.id\n inner join cfd_states as cfd_states on cfd_states.cfd_id = cfds.id\n where cfd_states.state in (\n select\n state\n from cfd_states\n where cfd_id = cfds.id\n order by id desc\n limit 1\n )\n and orders.oracle_event_id = ?\n ",
"describe": { "describe": {
"columns": [ "columns": [
{ {
"name": "id", "name": "order_id",
"ordinal": 0,
"type_info": "Int64"
}
],
"parameters": {
"Right": 1
},
"nullable": [
true
]
}
},
"b708b7116aa14093e0e21ab8f87e52928a70649a62250902054ef6526f1d6f66": {
"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 term_seconds as \"term_secs: i64\",\n term_nanoseconds as \"term_nanos: i32\",\n origin as \"origin: crate::model::cfd::Origin\",\n oracle_event_id\n\n from orders\n where uuid = $1\n ",
"describe": {
"columns": [
{
"name": "uuid: crate::model::cfd::OrderId",
"ordinal": 0, "ordinal": 0,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "trading_pair: crate::model::TradingPair", "name": "price",
"ordinal": 1, "ordinal": 1,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "position: crate::model::Position", "name": "min_quantity",
"ordinal": 2, "ordinal": 2,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "initial_price", "name": "max_quantity",
"ordinal": 3, "ordinal": 3,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "min_quantity", "name": "leverage",
"ordinal": 4, "ordinal": 4,
"type_info": "Text" "type_info": "Int64"
}, },
{ {
"name": "max_quantity", "name": "trading_pair",
"ordinal": 5, "ordinal": 5,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "leverage: crate::model::Leverage", "name": "position",
"ordinal": 6, "ordinal": 6,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "liquidation_price", "name": "origin",
"ordinal": 7, "ordinal": 7,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "ts_secs: i64", "name": "liquidation_price",
"ordinal": 8, "ordinal": 8,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "ts_nanos: i32", "name": "creation_timestamp",
"ordinal": 9, "ordinal": 9,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "term_secs: i64", "name": "term",
"ordinal": 10, "ordinal": 10,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "term_nanos: i32", "name": "oracle_event_id",
"ordinal": 11, "ordinal": 11,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "origin: crate::model::cfd::Origin", "name": "quantity_usd",
"ordinal": 12, "ordinal": 12,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "oracle_event_id", "name": "state",
"ordinal": 13, "ordinal": 13,
"type_info": "Text" "type_info": "Text"
} }
@ -348,99 +344,81 @@
] ]
} }
}, },
"d8323d50427833c983088011597081023ac564d65bc459d26aa27549a49b1df8": { "f3dce76f316212c91cb3402b0cef00f1c9adbef8519c54e9bdbd373aab946209": {
"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 term_seconds as term_secs,\n term_nanoseconds as term_nanos,\n origin,\n oracle_event_id\n from orders\n ),\n\n cfd as (\n select\n id as cfd_id,\n order_id,\n quantity_usd as quantity_usd\n from cfds\n ),\n\n tmp as (\n select\n id as state_id,\n cfd_id,\n state\n from cfd_states\n ),\n\n state as (\n select\n tmp.state,\n cfd.order_id,\n cfd.quantity_usd\n from tmp\n inner join cfd on tmp.cfd_id = cfd.cfd_id\n where tmp.state_id in (\n select max(state_id)\n from tmp\n group by state_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.term_secs as \"term_secs: i64\",\n ord.term_nanos as \"term_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 ", "query": "\n select * from orders where uuid = ?;\n ",
"describe": { "describe": {
"columns": [ "columns": [
{ {
"name": "uuid: crate::model::cfd::OrderId", "name": "id",
"ordinal": 0, "ordinal": 0,
"type_info": "Text" "type_info": "Int64"
}, },
{ {
"name": "trading_pair: crate::model::TradingPair", "name": "uuid",
"ordinal": 1, "ordinal": 1,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "position: crate::model::Position", "name": "trading_pair",
"ordinal": 2, "ordinal": 2,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "initial_price", "name": "position",
"ordinal": 3, "ordinal": 3,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "min_quantity", "name": "initial_price",
"ordinal": 4, "ordinal": 4,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "max_quantity", "name": "min_quantity",
"ordinal": 5, "ordinal": 5,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "leverage: crate::model::Leverage", "name": "max_quantity",
"ordinal": 6, "ordinal": 6,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "liquidation_price", "name": "leverage",
"ordinal": 7, "ordinal": 7,
"type_info": "Text" "type_info": "Int64"
}, },
{ {
"name": "ts_secs: i64", "name": "liquidation_price",
"ordinal": 8, "ordinal": 8,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "ts_nanos: i32", "name": "creation_timestamp",
"ordinal": 9, "ordinal": 9,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "term_secs: i64", "name": "term",
"ordinal": 10, "ordinal": 10,
"type_info": "Int64" "type_info": "Text"
}, },
{ {
"name": "term_nanos: i32", "name": "origin",
"ordinal": 11, "ordinal": 11,
"type_info": "Int64"
},
{
"name": "origin: crate::model::cfd::Origin",
"ordinal": 12,
"type_info": "Text" "type_info": "Text"
}, },
{ {
"name": "oracle_event_id", "name": "oracle_event_id",
"ordinal": 13, "ordinal": 12,
"type_info": "Text"
},
{
"name": "quantity_usd",
"ordinal": 14,
"type_info": "Text"
},
{
"name": "state",
"ordinal": 15,
"type_info": "Text" "type_info": "Text"
} }
], ],
"parameters": { "parameters": {
"Right": 0 "Right": 1
}, },
"nullable": [ "nullable": [
false, true,
false,
false,
false,
false, false,
false, false,
false, false,
@ -456,22 +434,22 @@
] ]
} }
}, },
"dde58d2118537f05941a79896639efb2e64f2bb6cf76f14c6c2eec20ec253160": { "fac3d990211ef9e5fa8bcd6e1d6e0c8a81652b98fb11f2686affd1593fba75fd": {
"query": "\n insert into cfds (\n order_id,\n order_uuid,\n quantity_usd\n )\n select\n id as order_id,\n uuid as order_uuid,\n $2 as quantity_usd\n from orders\n where uuid = $1;\n\n insert into cfd_states (\n cfd_id,\n state\n )\n select\n id as cfd_id,\n $3 as state\n from cfds\n order by id desc limit 1;\n ", "query": "\n insert into cfd_states (\n cfd_id,\n state\n ) values (?, ?);\n ",
"describe": { "describe": {
"columns": [], "columns": [],
"parameters": { "parameters": {
"Right": 3 "Right": 2
}, },
"nullable": [] "nullable": []
} }
}, },
"faaf391b5dca70a87c5f8ac9346fd6d9dd1ae6b83d99a0311df463ecaaf8c301": { "fad32c267100e26f4fba80e4feb5ff45ee29c3a67bd378f6627b1f13ee45c573": {
"query": "\n insert into cfd_states (\n cfd_id,\n state\n ) values ($1, $2);\n ", "query": "\n insert into cfds (\n order_id,\n order_uuid,\n quantity_usd\n ) values (?, ?, ?);\n ",
"describe": { "describe": {
"columns": [], "columns": [],
"parameters": { "parameters": {
"Right": 2 "Right": 3
}, },
"nullable": [] "nullable": []
} }

688
daemon/src/db.rs

@ -1,14 +1,11 @@
use crate::model::cfd::{Cfd, CfdState, Order, OrderId}; use crate::model::cfd::{Cfd, CfdState, Order, OrderId, Origin};
use crate::model::{BitMexPriceEventId, Usd}; use crate::model::{BitMexPriceEventId, Leverage, Position};
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use rocket_db_pools::sqlx; use rocket_db_pools::sqlx;
use rust_decimal::Decimal;
use sqlx::pool::PoolConnection; use sqlx::pool::PoolConnection;
use sqlx::{Sqlite, SqlitePool}; use sqlx::{Acquire, Sqlite, SqlitePool};
use std::convert::TryInto;
use std::mem; use std::mem;
use std::str::FromStr;
use std::time::SystemTime;
use time::{Duration, OffsetDateTime};
pub async fn run_migrations(pool: &SqlitePool) -> anyhow::Result<()> { pub async fn run_migrations(pool: &SqlitePool) -> anyhow::Result<()> {
sqlx::migrate!("./migrations").run(pool).await?; sqlx::migrate!("./migrations").run(pool).await?;
@ -16,48 +13,49 @@ pub async fn run_migrations(pool: &SqlitePool) -> anyhow::Result<()> {
} }
pub async fn insert_order(order: &Order, conn: &mut PoolConnection<Sqlite>) -> anyhow::Result<()> { pub async fn insert_order(order: &Order, conn: &mut PoolConnection<Sqlite>) -> anyhow::Result<()> {
sqlx::query( let uuid = serde_json::to_string(&order.id).unwrap();
r#"insert into orders ( let trading_pair = serde_json::to_string(&order.trading_pair).unwrap();
uuid, let position = serde_json::to_string(&order.position).unwrap();
trading_pair, let initial_price = serde_json::to_string(&order.price).unwrap();
position, let min_quantity = serde_json::to_string(&order.min_quantity).unwrap();
initial_price, let max_quantity = serde_json::to_string(&order.max_quantity).unwrap();
min_quantity, let leverage = order.leverage.0;
max_quantity, let liquidation_price = serde_json::to_string(&order.liquidation_price).unwrap();
leverage, let creation_timestamp = serde_json::to_string(&order.creation_timestamp).unwrap();
liquidation_price, let term = serde_json::to_string(&order.term).unwrap();
creation_timestamp_seconds, let origin = serde_json::to_string(&order.origin).unwrap();
creation_timestamp_nanoseconds, let oracle_event_id = order.oracle_event_id.to_string();
term_seconds,
term_nanoseconds, sqlx::query!(
origin, r#"
oracle_event_id insert into orders (
) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)"#, uuid,
) trading_pair,
.bind(&order.id) position,
.bind(&order.trading_pair) initial_price,
.bind(&order.position) min_quantity,
.bind(&order.price.to_string()) max_quantity,
.bind(&order.min_quantity.to_string()) leverage,
.bind(&order.max_quantity.to_string()) liquidation_price,
.bind(order.leverage.0) creation_timestamp,
.bind(&order.liquidation_price.to_string()) term,
.bind( origin,
order oracle_event_id
.creation_timestamp ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
.duration_since(SystemTime::UNIX_EPOCH)? "#,
.as_secs() as i64, uuid,
) trading_pair,
.bind( position,
order initial_price,
.creation_timestamp min_quantity,
.duration_since(SystemTime::UNIX_EPOCH)? max_quantity,
.subsec_nanos() as i32, leverage,
liquidation_price,
creation_timestamp,
term,
origin,
oracle_event_id
) )
.bind(&order.term.whole_seconds())
.bind(&order.term.subsec_nanoseconds())
.bind(&order.origin)
.bind(&order.oracle_event_id.to_string())
.execute(conn) .execute(conn)
.await?; .await?;
@ -68,83 +66,97 @@ pub async fn load_order_by_id(
id: OrderId, id: OrderId,
conn: &mut PoolConnection<Sqlite>, conn: &mut PoolConnection<Sqlite>,
) -> anyhow::Result<Order> { ) -> anyhow::Result<Order> {
let uuid = serde_json::to_string(&id).unwrap();
let row = sqlx::query!( let row = sqlx::query!(
r#" r#"
select select * from orders where uuid = ?;
uuid as "uuid: crate::model::cfd::OrderId",
trading_pair as "trading_pair: crate::model::TradingPair",
position as "position: crate::model::Position",
initial_price,
min_quantity,
max_quantity,
leverage as "leverage: crate::model::Leverage",
liquidation_price,
creation_timestamp_seconds as "ts_secs: i64",
creation_timestamp_nanoseconds as "ts_nanos: i32",
term_seconds as "term_secs: i64",
term_nanoseconds as "term_nanos: i32",
origin as "origin: crate::model::cfd::Origin",
oracle_event_id
from orders
where uuid = $1
"#, "#,
id uuid
) )
.fetch_one(conn) .fetch_one(conn)
.await?; .await?;
let uuid = serde_json::from_str(row.uuid.as_str()).unwrap();
let trading_pair = serde_json::from_str(row.trading_pair.as_str()).unwrap();
let position = serde_json::from_str(row.position.as_str()).unwrap();
let initial_price = serde_json::from_str(row.initial_price.as_str()).unwrap();
let min_quantity = serde_json::from_str(row.min_quantity.as_str()).unwrap();
let max_quantity = serde_json::from_str(row.max_quantity.as_str()).unwrap();
let leverage = Leverage(row.leverage.try_into().unwrap());
let liquidation_price = serde_json::from_str(row.liquidation_price.as_str()).unwrap();
let creation_timestamp = serde_json::from_str(row.creation_timestamp.as_str()).unwrap();
let term = serde_json::from_str(row.term.as_str()).unwrap();
let origin = serde_json::from_str(row.origin.as_str()).unwrap();
Ok(Order { Ok(Order {
id: row.uuid, id: uuid,
trading_pair: row.trading_pair, trading_pair,
position: row.position, position,
price: Usd(Decimal::from_str(&row.initial_price)?), price: initial_price,
min_quantity: Usd(Decimal::from_str(&row.min_quantity)?), min_quantity,
max_quantity: Usd(Decimal::from_str(&row.max_quantity)?), max_quantity,
leverage: row.leverage, leverage,
liquidation_price: Usd(Decimal::from_str(&row.liquidation_price)?), liquidation_price,
creation_timestamp: convert_to_system_time(row.ts_secs, row.ts_nanos)?, creation_timestamp,
term: Duration::new(row.term_secs, row.term_nanos), term,
origin: row.origin, origin,
oracle_event_id: row.oracle_event_id.parse::<BitMexPriceEventId>()?, oracle_event_id: row.oracle_event_id.parse().unwrap(),
}) })
} }
pub async fn insert_cfd(cfd: Cfd, conn: &mut PoolConnection<Sqlite>) -> anyhow::Result<()> { pub async fn insert_cfd(cfd: Cfd, conn: &mut PoolConnection<Sqlite>) -> anyhow::Result<()> {
let order_uuid = &cfd.order.id; let mut tx = conn.begin().await?;
let quantity_usd = &cfd.quantity_usd.to_string();
let state = serde_json::to_string(&cfd.state)?;
sqlx::query!(
r#"
insert into cfds (
order_id,
order_uuid,
quantity_usd
)
select
id as order_id,
uuid as order_uuid,
$2 as quantity_usd
from orders
where uuid = $1;
insert into cfd_states ( let order_uuid = serde_json::to_string(&cfd.order.id)?;
cfd_id, let order_row = sqlx::query!(
state r#"
) select * from orders where uuid = ?;
select
id as cfd_id,
$3 as state
from cfds
order by id desc limit 1;
"#, "#,
order_uuid
)
.fetch_one(&mut tx)
.await?;
let order_id = order_row.id;
let quantity_usd = serde_json::to_string(&cfd.quantity_usd)?;
let cfd_state = serde_json::to_string(&cfd.state)?;
// save cfd + state in a transaction to make sure the state is only inserted if the cfd was
// inserted
let cfd_id = sqlx::query!(
r#"
insert into cfds (
order_id,
order_uuid,
quantity_usd
) values (?, ?, ?);
"#,
order_id,
order_uuid, order_uuid,
quantity_usd, quantity_usd,
state
) )
.execute(conn) .execute(&mut tx)
.await?
.last_insert_rowid();
sqlx::query!(
r#"
insert into cfd_states (
cfd_id,
state
) values (?, ?);
"#,
cfd_id,
cfd_state,
)
.execute(&mut tx)
.await?; .await?;
tx.commit().await?;
Ok(()) Ok(())
} }
@ -175,7 +187,7 @@ pub async fn insert_new_cfd_state_by_order_id(
insert into cfd_states ( insert into cfd_states (
cfd_id, cfd_id,
state state
) values ($1, $2); ) values (?, ?);
"#, "#,
cfd_id, cfd_id,
cfd_state, cfd_state,
@ -191,12 +203,14 @@ async fn load_cfd_id_by_order_uuid(
order_uuid: OrderId, order_uuid: OrderId,
conn: &mut PoolConnection<Sqlite>, conn: &mut PoolConnection<Sqlite>,
) -> anyhow::Result<i64> { ) -> anyhow::Result<i64> {
let order_uuid = serde_json::to_string(&order_uuid)?;
let cfd_id = sqlx::query!( let cfd_id = sqlx::query!(
r#" r#"
select select
id id
from cfds from cfds
where order_uuid = $1; where order_uuid = ?;
"#, "#,
order_uuid order_uuid
) )
@ -218,7 +232,7 @@ async fn load_latest_cfd_state(
select select
state state
from cfd_states from cfd_states
where cfd_id = $1 where cfd_id = ?
order by id desc order by id desc
limit 1; limit 1;
"#, "#,
@ -236,215 +250,159 @@ pub async fn load_cfd_by_order_id(
order_id: OrderId, order_id: OrderId,
conn: &mut PoolConnection<Sqlite>, conn: &mut PoolConnection<Sqlite>,
) -> Result<Cfd> { ) -> Result<Cfd> {
let order_uuid = serde_json::to_string(&order_id)?;
let row = sqlx::query!( let row = sqlx::query!(
r#" r#"
with ord as ( select
select orders.uuid as order_id,
id as order_id, orders.initial_price as price,
uuid, orders.min_quantity as min_quantity,
trading_pair, orders.max_quantity as max_quantity,
position, orders.leverage as leverage,
initial_price, orders.trading_pair as trading_pair,
min_quantity, orders.position as position,
max_quantity, orders.origin as origin,
leverage, orders.liquidation_price as liquidation_price,
liquidation_price, orders.creation_timestamp as creation_timestamp,
creation_timestamp_seconds as ts_secs, orders.term as term,
creation_timestamp_nanoseconds as ts_nanos, orders.oracle_event_id,
term_seconds as term_secs, cfds.quantity_usd as quantity_usd,
term_nanoseconds as term_nanos, cfd_states.state as state
origin, from cfds as cfds
oracle_event_id inner join orders as orders on cfds.order_id = orders.id
from orders inner join cfd_states as cfd_states on cfd_states.cfd_id = cfds.id
), where cfd_states.state in (
cfd as (
select
id as cfd_id,
order_id,
quantity_usd
from cfds
),
tmp as (
select
id as state_id,
cfd_id,
state
from cfd_states
),
state as (
select select
tmp.state, state
cfd.order_id, from cfd_states
cfd.quantity_usd where cfd_id = cfds.id
from tmp order by id desc
inner join cfd on tmp.cfd_id = cfd.cfd_id limit 1
where tmp.state_id in (
select max(state_id)
from tmp
group by state_id
)
) )
and orders.uuid = ?
select
ord.uuid as "uuid: crate::model::cfd::OrderId",
ord.trading_pair as "trading_pair: crate::model::TradingPair",
ord.position as "position: crate::model::Position",
ord.initial_price,
ord.min_quantity,
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.term_secs as "term_secs: i64",
ord.term_nanos as "term_nanos: i32",
ord.origin as "origin: crate::model::cfd::Origin",
ord.oracle_event_id,
state.quantity_usd,
state.state
from ord
inner join state on state.order_id = ord.order_id
where ord.uuid = $1
"#, "#,
order_id order_uuid
) )
.fetch_one(conn) .fetch_one(conn)
.await?; .await?;
let order_id = serde_json::from_str(row.order_id.as_str()).unwrap();
let trading_pair = serde_json::from_str(row.trading_pair.as_str()).unwrap();
let position: Position = serde_json::from_str(row.position.as_str()).unwrap();
let price = serde_json::from_str(row.price.as_str()).unwrap();
let min_quantity = serde_json::from_str(row.min_quantity.as_str()).unwrap();
let max_quantity = serde_json::from_str(row.max_quantity.as_str()).unwrap();
let leverage = Leverage(row.leverage.try_into().unwrap());
let liquidation_price = serde_json::from_str(row.liquidation_price.as_str()).unwrap();
let creation_timestamp = serde_json::from_str(row.creation_timestamp.as_str()).unwrap();
let term = serde_json::from_str(row.term.as_str()).unwrap();
let origin: Origin = serde_json::from_str(row.origin.as_str()).unwrap();
let oracle_event_id = row.oracle_event_id.parse().unwrap();
let quantity = serde_json::from_str(row.quantity_usd.as_str()).unwrap();
let latest_state = serde_json::from_str(row.state.as_str()).unwrap();
let order = Order { let order = Order {
id: row.uuid, id: order_id,
trading_pair: row.trading_pair, trading_pair,
position: row.position, position,
price: Usd(Decimal::from_str(&row.initial_price)?), price,
min_quantity: Usd(Decimal::from_str(&row.min_quantity)?), min_quantity,
max_quantity: Usd(Decimal::from_str(&row.max_quantity)?), max_quantity,
leverage: row.leverage, leverage,
liquidation_price: Usd(Decimal::from_str(&row.liquidation_price)?), liquidation_price,
creation_timestamp: convert_to_system_time(row.ts_secs, row.ts_nanos)?, creation_timestamp,
term: Duration::new(row.term_secs, row.term_nanos), term,
origin: row.origin, origin,
oracle_event_id: row.oracle_event_id.parse::<BitMexPriceEventId>()?, oracle_event_id,
}; };
// TODO:
// still have the use of serde_json::from_str() here, which will be dealt with
// via https://github.com/comit-network/hermes/issues/290
Ok(Cfd { Ok(Cfd {
order, order,
quantity_usd: Usd(Decimal::from_str(&row.quantity_usd)?), quantity_usd: quantity,
state: serde_json::from_str(row.state.as_str())?, state: latest_state,
}) })
} }
/// Loads all CFDs with the latest state as the CFD state /// Loads all CFDs with the latest state as the CFD state
pub async fn load_all_cfds(conn: &mut PoolConnection<Sqlite>) -> anyhow::Result<Vec<Cfd>> { pub async fn load_all_cfds(conn: &mut PoolConnection<Sqlite>) -> anyhow::Result<Vec<Cfd>> {
// TODO: Could be optimized with something like but not sure it's worth the complexity:
let rows = sqlx::query!( let rows = sqlx::query!(
r#" r#"
with ord as ( select
select orders.uuid as order_id,
id as order_id, orders.initial_price as price,
uuid, orders.min_quantity as min_quantity,
trading_pair, orders.max_quantity as max_quantity,
position, orders.leverage as leverage,
initial_price, orders.trading_pair as trading_pair,
min_quantity, orders.position as position,
max_quantity, orders.origin as origin,
leverage, orders.liquidation_price as liquidation_price,
liquidation_price, orders.creation_timestamp as creation_timestamp,
creation_timestamp_seconds as ts_secs, orders.term as term,
creation_timestamp_nanoseconds as ts_nanos, orders.oracle_event_id,
term_seconds as term_secs, cfds.quantity_usd as quantity_usd,
term_nanoseconds as term_nanos, cfd_states.state as state
origin, from cfds as cfds
oracle_event_id inner join orders as orders on cfds.order_id = orders.id
from orders inner join cfd_states as cfd_states on cfd_states.cfd_id = cfds.id
), where cfd_states.state in (
cfd as (
select
id as cfd_id,
order_id,
quantity_usd as quantity_usd
from cfds
),
tmp as (
select
id as state_id,
cfd_id,
state
from cfd_states
),
state as (
select select
tmp.state, state
cfd.order_id, from cfd_states
cfd.quantity_usd where cfd_id = cfds.id
from tmp order by id desc
inner join cfd on tmp.cfd_id = cfd.cfd_id limit 1
where tmp.state_id in (
select max(state_id)
from tmp
group by state_id
)
) )
select
ord.uuid as "uuid: crate::model::cfd::OrderId",
ord.trading_pair as "trading_pair: crate::model::TradingPair",
ord.position as "position: crate::model::Position",
ord.initial_price,
ord.min_quantity,
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.term_secs as "term_secs: i64",
ord.term_nanos as "term_nanos: i32",
ord.origin as "origin: crate::model::cfd::Origin",
ord.oracle_event_id,
state.quantity_usd,
state.state
from ord
inner join state on state.order_id = ord.order_id
"# "#
) )
.fetch_all(conn) .fetch_all(conn)
.await?; .await?;
let cfds = rows let cfds = rows
.into_iter() .iter()
.map(|row| { .map(|row| {
let order_id = serde_json::from_str(row.order_id.as_str()).unwrap();
let trading_pair = serde_json::from_str(row.trading_pair.as_str()).unwrap();
let position: Position = serde_json::from_str(row.position.as_str()).unwrap();
let price = serde_json::from_str(row.price.as_str()).unwrap();
let min_quantity = serde_json::from_str(row.min_quantity.as_str()).unwrap();
let max_quantity = serde_json::from_str(row.max_quantity.as_str()).unwrap();
let leverage = Leverage(row.leverage.try_into().unwrap());
let liquidation_price = serde_json::from_str(row.liquidation_price.as_str()).unwrap();
let creation_timestamp = serde_json::from_str(row.creation_timestamp.as_str()).unwrap();
let term = serde_json::from_str(row.term.as_str()).unwrap();
let origin: Origin = serde_json::from_str(row.origin.as_str()).unwrap();
let oracle_event_id = row.oracle_event_id.clone().parse().unwrap();
let quantity = serde_json::from_str(row.quantity_usd.as_str()).unwrap();
let latest_state = serde_json::from_str(row.state.as_str()).unwrap();
let order = Order { let order = Order {
id: row.uuid, id: order_id,
trading_pair: row.trading_pair, trading_pair,
position: row.position, position,
price: Usd(Decimal::from_str(&row.initial_price)?), price,
min_quantity: Usd(Decimal::from_str(&row.min_quantity)?), min_quantity,
max_quantity: Usd(Decimal::from_str(&row.max_quantity)?), max_quantity,
leverage: row.leverage, leverage,
liquidation_price: Usd(Decimal::from_str(&row.liquidation_price)?), liquidation_price,
creation_timestamp: convert_to_system_time(row.ts_secs, row.ts_nanos)?, creation_timestamp,
term: Duration::new(row.term_secs, row.term_nanos), term,
origin: row.origin, origin,
oracle_event_id: row.oracle_event_id.parse::<BitMexPriceEventId>()?, oracle_event_id,
}; };
Ok(Cfd { Cfd {
order, order,
quantity_usd: Usd(Decimal::from_str(&row.quantity_usd)?), quantity_usd: quantity,
state: serde_json::from_str(row.state.as_str())?, state: latest_state,
}) }
}) })
.collect::<Result<Vec<_>>>()?; .collect();
Ok(cfds) Ok(cfds)
} }
@ -454,124 +412,88 @@ pub async fn load_cfds_by_oracle_event_id(
oracle_event_id: BitMexPriceEventId, oracle_event_id: BitMexPriceEventId,
conn: &mut PoolConnection<Sqlite>, conn: &mut PoolConnection<Sqlite>,
) -> anyhow::Result<Vec<Cfd>> { ) -> anyhow::Result<Vec<Cfd>> {
let event_id = oracle_event_id.to_string(); let oracle_event_id = oracle_event_id.to_string();
let rows = sqlx::query!( let rows = sqlx::query!(
r#" r#"
with ord as ( select
select orders.uuid as order_id,
id as order_id, orders.initial_price as price,
uuid, orders.min_quantity as min_quantity,
trading_pair, orders.max_quantity as max_quantity,
position, orders.leverage as leverage,
initial_price, orders.trading_pair as trading_pair,
min_quantity, orders.position as position,
max_quantity, orders.origin as origin,
leverage, orders.liquidation_price as liquidation_price,
liquidation_price, orders.creation_timestamp as creation_timestamp,
creation_timestamp_seconds as ts_secs, orders.term as term,
creation_timestamp_nanoseconds as ts_nanos, orders.oracle_event_id,
term_seconds as term_secs, cfds.quantity_usd as quantity_usd,
term_nanoseconds as term_nanos, cfd_states.state as state
origin, from cfds as cfds
oracle_event_id inner join orders as orders on cfds.order_id = orders.id
from orders inner join cfd_states as cfd_states on cfd_states.cfd_id = cfds.id
), where cfd_states.state in (
cfd as (
select
id as cfd_id,
order_id,
quantity_usd as quantity_usd
from cfds
),
tmp as (
select
id as state_id,
cfd_id,
state
from cfd_states
),
state as (
select select
tmp.state, state
cfd.order_id, from cfd_states
cfd.quantity_usd where cfd_id = cfds.id
from tmp order by id desc
inner join cfd on tmp.cfd_id = cfd.cfd_id limit 1
where tmp.state_id in (
select max(state_id)
from tmp
group by state_id
)
) )
and orders.oracle_event_id = ?
select
ord.uuid as "uuid: crate::model::cfd::OrderId",
ord.trading_pair as "trading_pair: crate::model::TradingPair",
ord.position as "position: crate::model::Position",
ord.initial_price,
ord.min_quantity,
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.term_secs as "term_secs: i64",
ord.term_nanos as "term_nanos: i32",
ord.origin as "origin: crate::model::cfd::Origin",
ord.oracle_event_id,
state.quantity_usd,
state.state
from ord
inner join state on state.order_id = ord.order_id
where ord.oracle_event_id = $1
"#, "#,
event_id oracle_event_id
) )
.fetch_all(conn) .fetch_all(conn)
.await?; .await?;
let cfds = rows let cfds = rows
.into_iter() .iter()
.map(|row| { .map(|row| {
let order_id = serde_json::from_str(row.order_id.as_str()).unwrap();
let trading_pair = serde_json::from_str(row.trading_pair.as_str()).unwrap();
let position: Position = serde_json::from_str(row.position.as_str()).unwrap();
let price = serde_json::from_str(row.price.as_str()).unwrap();
let min_quantity = serde_json::from_str(row.min_quantity.as_str()).unwrap();
let max_quantity = serde_json::from_str(row.max_quantity.as_str()).unwrap();
let leverage = Leverage(row.leverage.try_into().unwrap());
let liquidation_price = serde_json::from_str(row.liquidation_price.as_str()).unwrap();
let creation_timestamp = serde_json::from_str(row.creation_timestamp.as_str()).unwrap();
let term = serde_json::from_str(row.term.as_str()).unwrap();
let origin: Origin = serde_json::from_str(row.origin.as_str()).unwrap();
let oracle_event_id = row.oracle_event_id.parse().unwrap();
let quantity = serde_json::from_str(row.quantity_usd.as_str()).unwrap();
let latest_state = serde_json::from_str(row.state.as_str()).unwrap();
let order = Order { let order = Order {
id: row.uuid, id: order_id,
trading_pair: row.trading_pair, trading_pair,
position: row.position, position,
price: Usd(Decimal::from_str(&row.initial_price)?), price,
min_quantity: Usd(Decimal::from_str(&row.min_quantity)?), min_quantity,
max_quantity: Usd(Decimal::from_str(&row.max_quantity)?), max_quantity,
leverage: row.leverage, leverage,
liquidation_price: Usd(Decimal::from_str(&row.liquidation_price)?), liquidation_price,
creation_timestamp: convert_to_system_time(row.ts_secs, row.ts_nanos)?, creation_timestamp,
term: Duration::new(row.term_secs, row.term_nanos), term,
origin: row.origin, origin,
oracle_event_id: row.oracle_event_id.parse::<BitMexPriceEventId>()?, oracle_event_id,
}; };
Ok(Cfd { Cfd {
order, order,
quantity_usd: Usd(Decimal::from_str(&row.quantity_usd)?), quantity_usd: quantity,
state: serde_json::from_str(row.state.as_str())?, state: latest_state,
}) }
}) })
.collect::<Result<Vec<_>>>()?; .collect();
Ok(cfds) 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)] #[cfg(test)]
mod tests { mod tests {
use std::fs::File; use std::fs::File;
@ -584,7 +506,7 @@ mod tests {
use time::OffsetDateTime; use time::OffsetDateTime;
use crate::db::insert_order; use crate::db::insert_order;
use crate::model::cfd::{Cfd, CfdState, CfdStateCommon, Order, Origin}; use crate::model::cfd::{Cfd, CfdState, CfdStateCommon, Order};
use crate::model::Usd; use crate::model::Usd;
use super::*; use super::*;
@ -720,7 +642,7 @@ mod tests {
.unwrap(); .unwrap();
let cfds_from_db = load_all_cfds(&mut conn).await.unwrap(); let cfds_from_db = load_all_cfds(&mut conn).await.unwrap();
let cfd_from_db = cfds_from_db.last().unwrap().clone(); let cfd_from_db = cfds_from_db.first().unwrap().clone();
assert_eq!(cfd, cfd_from_db) assert_eq!(cfd, cfd_from_db)
} }

19
daemon/src/model.rs

@ -72,16 +72,15 @@ impl From<Decimal> for Percent {
} }
} }
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, sqlx::Type)] #[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq)]
#[sqlx(transparent)]
pub struct Leverage(pub u8); pub struct Leverage(pub u8);
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, sqlx::Type)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum TradingPair { pub enum TradingPair {
BtcUsd, BtcUsd,
} }
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, sqlx::Type)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum Position { pub enum Position {
Buy, Buy,
Sell, Sell,
@ -110,17 +109,7 @@ pub struct WalletInfo {
} }
#[derive( #[derive(
Debug, Debug, Clone, Copy, SerializeDisplay, DeserializeFromStr, PartialEq, Eq, Hash, PartialOrd, Ord,
Clone,
Copy,
SerializeDisplay,
DeserializeFromStr,
PartialEq,
Eq,
Hash,
PartialOrd,
Ord,
sqlx::Type,
)] )]
pub struct BitMexPriceEventId { pub struct BitMexPriceEventId {
/// The timestamp this price event refers to. /// The timestamp this price event refers to.

5
daemon/src/model/cfd.rs

@ -19,8 +19,7 @@ use std::time::SystemTime;
use time::Duration; use time::Duration;
use uuid::Uuid; use uuid::Uuid;
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, sqlx::Type)] #[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[sqlx(transparent)]
pub struct OrderId(Uuid); pub struct OrderId(Uuid);
impl Default for OrderId { impl Default for OrderId {
@ -46,7 +45,7 @@ impl<'v> FromParam<'v> for OrderId {
// TODO: Could potentially remove this and use the Role in the Order instead // TODO: Could potentially remove this and use the Role in the Order instead
/// Origin of the order /// Origin of the order
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, sqlx::Type)] #[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq)]
pub enum Origin { pub enum Origin {
Ours, Ours,
Theirs, Theirs,

Loading…
Cancel
Save