From 4887e94908fd3e7b6e6f5c955f9fc0f8e8020bdd Mon Sep 17 00:00:00 2001 From: Lucas Soriano del Pino Date: Wed, 10 Apr 2024 12:28:35 +1000 Subject: [PATCH 1/2] chore(coordinator): Add trader_pnl to trade_params table Instead of allowing to insert trades early into the database (via the `is_complete` column, which is now gone). --- .../down.sql | 5 ++ .../up.sql | 5 ++ coordinator/src/db/trade_params.rs | 3 + coordinator/src/db/trades.rs | 24 ------ coordinator/src/dlc_protocol.rs | 79 +++++++++++-------- coordinator/src/schema.rs | 2 +- coordinator/src/trade/mod.rs | 17 +--- coordinator/src/trade/models.rs | 2 - 8 files changed, 64 insertions(+), 73 deletions(-) create mode 100644 coordinator/migrations/2024-04-10-015155_move_pnl_to_trade_params/down.sql create mode 100644 coordinator/migrations/2024-04-10-015155_move_pnl_to_trade_params/up.sql diff --git a/coordinator/migrations/2024-04-10-015155_move_pnl_to_trade_params/down.sql b/coordinator/migrations/2024-04-10-015155_move_pnl_to_trade_params/down.sql new file mode 100644 index 000000000..2029677fe --- /dev/null +++ b/coordinator/migrations/2024-04-10-015155_move_pnl_to_trade_params/down.sql @@ -0,0 +1,5 @@ +ALTER TABLE trades + ADD COLUMN is_complete BOOLEAN NOT NULL DEFAULT true; + +ALTER TABLE trade_params + DROP COLUMN IF EXISTS trader_pnl_sat; diff --git a/coordinator/migrations/2024-04-10-015155_move_pnl_to_trade_params/up.sql b/coordinator/migrations/2024-04-10-015155_move_pnl_to_trade_params/up.sql new file mode 100644 index 000000000..6fd80da47 --- /dev/null +++ b/coordinator/migrations/2024-04-10-015155_move_pnl_to_trade_params/up.sql @@ -0,0 +1,5 @@ +ALTER TABLE trades + DROP COLUMN IF EXISTS "is_complete"; + +ALTER TABLE trade_params + ADD COLUMN trader_pnl_sat BIGINT; diff --git a/coordinator/src/db/trade_params.rs b/coordinator/src/db/trade_params.rs index ac120a11d..2462f32af 100644 --- a/coordinator/src/db/trade_params.rs +++ b/coordinator/src/db/trade_params.rs @@ -4,6 +4,7 @@ use crate::orderbook::db::custom_types::Direction; use crate::schema::trade_params; use bitcoin::secp256k1::PublicKey; use bitcoin::Amount; +use bitcoin::SignedAmount; use diesel::ExpressionMethods; use diesel::PgConnection; use diesel::QueryDsl; @@ -25,6 +26,7 @@ pub(crate) struct TradeParams { pub average_price: f32, pub direction: Direction, pub matching_fee: i64, + pub trader_pnl: Option, } pub(crate) fn insert( @@ -71,6 +73,7 @@ impl From for dlc_protocol::TradeParams { average_price: value.average_price, direction: trade::Direction::from(value.direction), matching_fee: Amount::from_sat(value.matching_fee as u64), + trader_pnl: value.trader_pnl.map(SignedAmount::from_sat), } } } diff --git a/coordinator/src/db/trades.rs b/coordinator/src/db/trades.rs index fcf02d018..856d83ad1 100644 --- a/coordinator/src/db/trades.rs +++ b/coordinator/src/db/trades.rs @@ -22,7 +22,6 @@ struct Trade { timestamp: OffsetDateTime, order_matching_fee_sat: i64, trader_realized_pnl_sat: Option, - is_complete: bool, } #[derive(Insertable, Debug, Clone)] @@ -37,7 +36,6 @@ struct NewTrade { average_price: f32, order_matching_fee_sat: i64, trader_realized_pnl_sat: Option, - is_complete: bool, } pub fn insert( @@ -51,26 +49,6 @@ pub fn insert( Ok(trade.into()) } -pub fn mark_as_completed(conn: &mut PgConnection, position_id: i32) -> QueryResult<()> { - let trade = trades::table - .filter(trades::position_id.eq(position_id)) - .order_by(trades::id.desc()) - .first::(conn) - .optional()? - .ok_or(diesel::result::Error::NotFound)?; - - let affected_rows = diesel::update(trades::table) - .filter(trades::id.eq(trade.id)) - .set(trades::is_complete.eq(true)) - .execute(conn)?; - - if affected_rows == 0 { - return Err(diesel::result::Error::NotFound); - } - - Ok(()) -} - pub fn get_latest_for_position( conn: &mut PgConnection, position_id: i32, @@ -112,7 +90,6 @@ impl From for NewTrade { average_price: value.average_price, order_matching_fee_sat: value.order_matching_fee.to_sat() as i64, trader_realized_pnl_sat: value.trader_realized_pnl_sat, - is_complete: value.is_complete, } } } @@ -132,7 +109,6 @@ impl From for crate::trade::models::Trade { timestamp: value.timestamp, order_matching_fee: Amount::from_sat(value.order_matching_fee_sat as u64), trader_realized_pnl_sat: value.trader_realized_pnl_sat, - is_complete: value.is_complete, } } } diff --git a/coordinator/src/dlc_protocol.rs b/coordinator/src/dlc_protocol.rs index 33668f58d..9db821931 100644 --- a/coordinator/src/dlc_protocol.rs +++ b/coordinator/src/dlc_protocol.rs @@ -6,6 +6,7 @@ use anyhow::Context; use anyhow::Result; use bitcoin::secp256k1::PublicKey; use bitcoin::Amount; +use bitcoin::SignedAmount; use diesel::r2d2::ConnectionManager; use diesel::r2d2::Pool; use diesel::result::Error::RollbackTransaction; @@ -119,10 +120,15 @@ pub struct TradeParams { pub average_price: f32, pub direction: Direction, pub matching_fee: Amount, + pub trader_pnl: Option, } -impl From<(ProtocolId, &commons::TradeParams)> for TradeParams { - fn from((protocol_id, trade_params): (ProtocolId, &commons::TradeParams)) -> Self { +impl TradeParams { + fn new( + trade_params: &commons::TradeParams, + protocol_id: ProtocolId, + trader_pnl: Option, + ) -> Self { Self { protocol_id, trader: trade_params.pubkey, @@ -131,9 +137,10 @@ impl From<(ProtocolId, &commons::TradeParams)> for TradeParams { average_price: trade_params .average_execution_price() .to_f32() - .expect("to fit into f32"), + .expect("to fit"), direction: trade_params.direction, matching_fee: trade_params.order_matching_fee(), + trader_pnl, } } } @@ -154,6 +161,30 @@ pub enum DlcProtocolType { Rollover { trader: PublicKey }, } +impl DlcProtocolType { + pub fn open(trade_params: &commons::TradeParams, protocol_id: ProtocolId) -> Self { + Self::Open { + trade_params: TradeParams::new(trade_params, protocol_id, None), + } + } + + pub fn renew( + trade_params: &commons::TradeParams, + protocol_id: ProtocolId, + trader_pnl: Option, + ) -> Self { + Self::Renew { + trade_params: TradeParams::new(trade_params, protocol_id, trader_pnl), + } + } + + pub fn settle(trade_params: &commons::TradeParams, protocol_id: ProtocolId) -> Self { + Self::Settle { + trade_params: TradeParams::new(trade_params, protocol_id, None), + } + } +} + impl DlcProtocolType { pub fn get_trader_pubkey(&self) -> &PublicKey { match self { @@ -403,7 +434,6 @@ impl DlcProtocolExecutor { average_price: trade_params.average_price, order_matching_fee, trader_realized_pnl_sat: Some(trader_realized_pnl_sat), - is_complete: true, }; db::trades::insert(conn, new_trade)?; @@ -433,14 +463,6 @@ impl DlcProtocolExecutor { channel_id, )?; - let original = db::positions::Position::get_position_by_trader( - conn, - trade_params.trader, - vec![PositionState::Proposed, PositionState::Resizing], - )? - .context("Can't finish open or resize protocol without position") - .map_err(|_| RollbackTransaction)?; - // TODO(holzeis): We are still updating the position based on the position state. This // will change once we only have a single position per user and representing // the position only as view on multiple trades. @@ -453,29 +475,20 @@ impl DlcProtocolExecutor { let order_matching_fee = trade_params.matching_fee; - if matches!(original.position_state, PositionState::Resizing) { - // A resizing protocol may generate PNL, but here we are not able to calculate it, so - // the `Trade` has to be inserted before it is complete. So here we just have to mark - // the `Trade` as complete. - - db::trades::mark_as_completed(conn, position.id)?; - } else { - let new_trade = NewTrade { - position_id: position.id, - contract_symbol: position.contract_symbol, - trader_pubkey: trade_params.trader, - quantity: trade_params.quantity, - trader_leverage: trade_params.leverage, - trader_direction: trade_params.direction, - average_price: trade_params.average_price, - order_matching_fee, - trader_realized_pnl_sat: None, - is_complete: true, - }; - - db::trades::insert(conn, new_trade)?; + let new_trade = NewTrade { + position_id: position.id, + contract_symbol: position.contract_symbol, + trader_pubkey: trade_params.trader, + quantity: trade_params.quantity, + trader_leverage: trade_params.leverage, + trader_direction: trade_params.direction, + average_price: trade_params.average_price, + order_matching_fee, + trader_realized_pnl_sat: trade_params.trader_pnl.map(|pnl| pnl.to_sat()), }; + db::trades::insert(conn, new_trade)?; + Ok(()) } diff --git a/coordinator/src/schema.rs b/coordinator/src/schema.rs index c94c38c87..edf922a9f 100644 --- a/coordinator/src/schema.rs +++ b/coordinator/src/schema.rs @@ -416,6 +416,7 @@ diesel::table! { average_price -> Float4, direction -> DirectionType, matching_fee -> Int8, + trader_pnl_sat -> Nullable, } } @@ -436,7 +437,6 @@ diesel::table! { timestamp -> Timestamptz, order_matching_fee_sat -> Int8, trader_realized_pnl_sat -> Nullable, - is_complete -> Bool, } } diff --git a/coordinator/src/trade/mod.rs b/coordinator/src/trade/mod.rs index 73153d061..1bc864e2d 100644 --- a/coordinator/src/trade/mod.rs +++ b/coordinator/src/trade/mod.rs @@ -374,9 +374,7 @@ impl TradeExecutor { None, &temporary_contract_id, &temporary_channel_id, - DlcProtocolType::Open { - trade_params: (protocol_id, trade_params).into(), - }, + DlcProtocolType::open(trade_params, protocol_id), )?; // After the DLC channel has been proposed the position can be created. This fixes @@ -550,9 +548,7 @@ impl TradeExecutor { previous_id, &temporary_contract_id, &channel.get_id(), - DlcProtocolType::Renew { - trade_params: (protocol_id, trade_params).into(), - }, + DlcProtocolType::renew(trade_params, protocol_id, None), )?; // TODO(holzeis): The position should only get created after the dlc protocol has finished @@ -720,9 +716,7 @@ impl TradeExecutor { previous_id, &temporary_contract_id, &channel.get_id(), - DlcProtocolType::Renew { - trade_params: (protocol_id, trade_params).into(), - }, + DlcProtocolType::renew(trade_params, protocol_id, realized_pnl), )?; db::positions::Position::set_position_to_resizing( @@ -758,7 +752,6 @@ impl TradeExecutor { .expect("to fit"), order_matching_fee, trader_realized_pnl_sat: realized_pnl.map(SignedAmount::to_sat), - is_complete: false, }, )?; @@ -896,9 +889,7 @@ impl TradeExecutor { previous_id, &contract_id, &channel.get_id(), - DlcProtocolType::Settle { - trade_params: (protocol_id, trade_params).into(), - }, + DlcProtocolType::settle(trade_params, protocol_id), )?; db::positions::Position::set_open_position_to_closing( diff --git a/coordinator/src/trade/models.rs b/coordinator/src/trade/models.rs index 87047bd1b..180c9358f 100644 --- a/coordinator/src/trade/models.rs +++ b/coordinator/src/trade/models.rs @@ -15,7 +15,6 @@ pub struct NewTrade { pub average_price: f32, pub order_matching_fee: Amount, pub trader_realized_pnl_sat: Option, - pub is_complete: bool, } #[derive(Debug)] @@ -31,5 +30,4 @@ pub struct Trade { pub timestamp: OffsetDateTime, pub order_matching_fee: Amount, pub trader_realized_pnl_sat: Option, - pub is_complete: bool, } From 16d51500ddcbf35a028406ddc5f32bdbdba8e8dc Mon Sep 17 00:00:00 2001 From: Lucas Soriano del Pino Date: Wed, 10 Apr 2024 13:00:51 +1000 Subject: [PATCH 2/2] chore(coordinator): Enrich DlcProtocolType model We can now differentiate between opening a channel, opening a position and resizing a position. --- .../down.sql | 5 + .../up.sql | 9 ++ coordinator/src/db/custom_types.rs | 10 +- coordinator/src/db/dlc_channels.rs | 2 +- coordinator/src/db/dlc_protocols.rs | 22 ++- coordinator/src/dlc_protocol.rs | 139 ++++++++++++++---- coordinator/src/node/channel.rs | 9 +- coordinator/src/trade/mod.rs | 6 +- 8 files changed, 156 insertions(+), 46 deletions(-) create mode 100644 coordinator/migrations/2024-04-10-023033_add_resize_dlc_protocol_type/down.sql create mode 100644 coordinator/migrations/2024-04-10-023033_add_resize_dlc_protocol_type/up.sql diff --git a/coordinator/migrations/2024-04-10-023033_add_resize_dlc_protocol_type/down.sql b/coordinator/migrations/2024-04-10-023033_add_resize_dlc_protocol_type/down.sql new file mode 100644 index 000000000..6d9f7d62f --- /dev/null +++ b/coordinator/migrations/2024-04-10-023033_add_resize_dlc_protocol_type/down.sql @@ -0,0 +1,5 @@ +ALTER TYPE "Protocol_Type_Type" + RENAME VALUE 'open-channel' TO 'open'; + +ALTER TYPE "Protocol_Type_Type" + RENAME VALUE 'open-position' TO 'renew'; diff --git a/coordinator/migrations/2024-04-10-023033_add_resize_dlc_protocol_type/up.sql b/coordinator/migrations/2024-04-10-023033_add_resize_dlc_protocol_type/up.sql new file mode 100644 index 000000000..b7d5e0119 --- /dev/null +++ b/coordinator/migrations/2024-04-10-023033_add_resize_dlc_protocol_type/up.sql @@ -0,0 +1,9 @@ +-- Must use `IF NOT EXISTS` because enum values cannot be removed on "down" migrations. +ALTER TYPE "Protocol_Type_Type" + ADD VALUE IF NOT EXISTS 'resize-position'; + +ALTER TYPE "Protocol_Type_Type" + RENAME VALUE 'open' TO 'open-channel'; + +ALTER TYPE "Protocol_Type_Type" + RENAME VALUE 'renew' TO 'open-position'; diff --git a/coordinator/src/db/custom_types.rs b/coordinator/src/db/custom_types.rs index f4aa478a1..f7d5a46ba 100644 --- a/coordinator/src/db/custom_types.rs +++ b/coordinator/src/db/custom_types.rs @@ -181,12 +181,13 @@ impl FromSql for DlcProtocolState { impl ToSql for DlcProtocolType { fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result { match *self { - DlcProtocolType::Open => out.write_all(b"open")?, + DlcProtocolType::OpenChannel => out.write_all(b"open-channel")?, DlcProtocolType::Settle => out.write_all(b"settle")?, - DlcProtocolType::Renew => out.write_all(b"renew")?, + DlcProtocolType::OpenPosition => out.write_all(b"open-position")?, DlcProtocolType::Rollover => out.write_all(b"rollover")?, DlcProtocolType::Close => out.write_all(b"close")?, DlcProtocolType::ForceClose => out.write_all(b"force-close")?, + DlcProtocolType::ResizePosition => out.write_all(b"resize-position")?, } Ok(IsNull::No) } @@ -195,12 +196,13 @@ impl ToSql for DlcProtocolType { impl FromSql for DlcProtocolType { fn from_sql(bytes: PgValue<'_>) -> deserialize::Result { match bytes.as_bytes() { - b"open" => Ok(DlcProtocolType::Open), + b"open-channel" => Ok(DlcProtocolType::OpenChannel), b"settle" => Ok(DlcProtocolType::Settle), - b"renew" => Ok(DlcProtocolType::Renew), + b"open-position" => Ok(DlcProtocolType::OpenPosition), b"rollover" => Ok(DlcProtocolType::Rollover), b"close" => Ok(DlcProtocolType::Close), b"force-close" => Ok(DlcProtocolType::ForceClose), + b"resize-position" => Ok(DlcProtocolType::ResizePosition), _ => Err("Unrecognized enum variant for ProtocolTypeType".into()), } } diff --git a/coordinator/src/db/dlc_channels.rs b/coordinator/src/db/dlc_channels.rs index c34850c17..c07a969d7 100644 --- a/coordinator/src/db/dlc_channels.rs +++ b/coordinator/src/db/dlc_channels.rs @@ -113,7 +113,7 @@ pub(crate) fn set_dlc_channel_open( .execute(conn) } -pub(crate) fn update_channel_on_renew( +pub(crate) fn update_channel( conn: &mut PgConnection, channel_id: &DlcChannelId, coordinator_reserve: Amount, diff --git a/coordinator/src/db/dlc_protocols.rs b/coordinator/src/db/dlc_protocols.rs index 474bb7487..799f17fa7 100644 --- a/coordinator/src/db/dlc_protocols.rs +++ b/coordinator/src/db/dlc_protocols.rs @@ -42,12 +42,13 @@ impl QueryId for ProtocolStateType { #[derive(Debug, Clone, Copy, PartialEq, FromSqlRow, AsExpression, Eq, Hash)] #[diesel(sql_type = ProtocolTypeType)] pub(crate) enum DlcProtocolType { - Open, - Renew, + OpenChannel, + OpenPosition, Settle, Close, ForceClose, Rollover, + ResizePosition, } impl QueryId for ProtocolTypeType { @@ -83,13 +84,13 @@ pub(crate) fn get_dlc_protocol( .first(conn)?; let protocol_type = match dlc_protocol.protocol_type { - DlcProtocolType::Open => { + DlcProtocolType::OpenChannel => { let trade_params = db::trade_params::get(conn, protocol_id)?; - dlc_protocol::DlcProtocolType::Open { trade_params } + dlc_protocol::DlcProtocolType::OpenChannel { trade_params } } - DlcProtocolType::Renew => { + DlcProtocolType::OpenPosition => { let trade_params = db::trade_params::get(conn, protocol_id)?; - dlc_protocol::DlcProtocolType::Renew { trade_params } + dlc_protocol::DlcProtocolType::OpenPosition { trade_params } } DlcProtocolType::Settle => { let trade_params = db::trade_params::get(conn, protocol_id)?; @@ -104,6 +105,10 @@ pub(crate) fn get_dlc_protocol( DlcProtocolType::Rollover => dlc_protocol::DlcProtocolType::Rollover { trader: PublicKey::from_str(&dlc_protocol.trader_pubkey).expect("valid public key"), }, + DlcProtocolType::ResizePosition => { + let trade_params = db::trade_params::get(conn, protocol_id)?; + dlc_protocol::DlcProtocolType::ResizePosition { trade_params } + } }; let protocol = dlc_protocol::DlcProtocol { @@ -209,12 +214,13 @@ impl From for dlc_protocol::DlcProtocolState { impl From for DlcProtocolType { fn from(value: dlc_protocol::DlcProtocolType) -> Self { match value { - dlc_protocol::DlcProtocolType::Open { .. } => DlcProtocolType::Open, - dlc_protocol::DlcProtocolType::Renew { .. } => DlcProtocolType::Renew, + dlc_protocol::DlcProtocolType::OpenChannel { .. } => DlcProtocolType::OpenChannel, + dlc_protocol::DlcProtocolType::OpenPosition { .. } => DlcProtocolType::OpenPosition, dlc_protocol::DlcProtocolType::Settle { .. } => DlcProtocolType::Settle, dlc_protocol::DlcProtocolType::Close { .. } => DlcProtocolType::Close, dlc_protocol::DlcProtocolType::ForceClose { .. } => DlcProtocolType::ForceClose, dlc_protocol::DlcProtocolType::Rollover { .. } => DlcProtocolType::Rollover, + dlc_protocol::DlcProtocolType::ResizePosition { .. } => DlcProtocolType::ResizePosition, } } } diff --git a/coordinator/src/dlc_protocol.rs b/coordinator/src/dlc_protocol.rs index 9db821931..2d4c867a8 100644 --- a/coordinator/src/dlc_protocol.rs +++ b/coordinator/src/dlc_protocol.rs @@ -153,27 +153,49 @@ pub enum DlcProtocolState { #[derive(Clone, Debug)] pub enum DlcProtocolType { - Open { trade_params: TradeParams }, - Renew { trade_params: TradeParams }, - Settle { trade_params: TradeParams }, - Close { trader: PublicKey }, - ForceClose { trader: PublicKey }, - Rollover { trader: PublicKey }, + /// Opening a channel also opens a position. + OpenChannel { + trade_params: TradeParams, + }, + OpenPosition { + trade_params: TradeParams, + }, + ResizePosition { + trade_params: TradeParams, + }, + Rollover { + trader: PublicKey, + }, + Settle { + trade_params: TradeParams, + }, + Close { + trader: PublicKey, + }, + ForceClose { + trader: PublicKey, + }, } impl DlcProtocolType { - pub fn open(trade_params: &commons::TradeParams, protocol_id: ProtocolId) -> Self { - Self::Open { + pub fn open_channel(trade_params: &commons::TradeParams, protocol_id: ProtocolId) -> Self { + Self::OpenChannel { trade_params: TradeParams::new(trade_params, protocol_id, None), } } - pub fn renew( + pub fn open_position(trade_params: &commons::TradeParams, protocol_id: ProtocolId) -> Self { + Self::OpenPosition { + trade_params: TradeParams::new(trade_params, protocol_id, None), + } + } + + pub fn resize_position( trade_params: &commons::TradeParams, protocol_id: ProtocolId, trader_pnl: Option, ) -> Self { - Self::Renew { + Self::ResizePosition { trade_params: TradeParams::new(trade_params, protocol_id, trader_pnl), } } @@ -188,10 +210,13 @@ impl DlcProtocolType { impl DlcProtocolType { pub fn get_trader_pubkey(&self) -> &PublicKey { match self { - DlcProtocolType::Open { + DlcProtocolType::OpenChannel { trade_params: TradeParams { trader, .. }, } => trader, - DlcProtocolType::Renew { + DlcProtocolType::OpenPosition { + trade_params: TradeParams { trader, .. }, + } => trader, + DlcProtocolType::ResizePosition { trade_params: TradeParams { trader, .. }, } => trader, DlcProtocolType::Settle { @@ -238,8 +263,9 @@ impl DlcProtocolExecutor { )?; match protocol_type { - DlcProtocolType::Open { trade_params } - | DlcProtocolType::Renew { trade_params } + DlcProtocolType::OpenChannel { trade_params } + | DlcProtocolType::OpenPosition { trade_params } + | DlcProtocolType::ResizePosition { trade_params } | DlcProtocolType::Settle { trade_params } => { db::trade_params::insert(conn, protocol_id, &trade_params)?; } @@ -272,12 +298,24 @@ impl DlcProtocolExecutor { let dlc_protocol = db::dlc_protocols::get_dlc_protocol(&mut conn, protocol_id)?; conn.transaction(|conn| { match &dlc_protocol.protocol_type { - DlcProtocolType::Open { trade_params } - | DlcProtocolType::Renew { trade_params } => { + DlcProtocolType::OpenChannel { trade_params } + | DlcProtocolType::OpenPosition { trade_params } => { let contract_id = contract_id .context("missing contract id") .map_err(|_| RollbackTransaction)?; - self.finish_open_or_resize_trade_dlc_protocol( + self.finish_open_position_dlc_protocol( + conn, + trade_params, + protocol_id, + &contract_id, + channel_id, + ) + } + DlcProtocolType::ResizePosition { trade_params } => { + let contract_id = contract_id + .context("missing contract id") + .map_err(|_| RollbackTransaction)?; + self.finish_resize_position_dlc_protocol( conn, trade_params, protocol_id, @@ -318,8 +356,9 @@ impl DlcProtocolExecutor { })?; match &dlc_protocol.protocol_type { - DlcProtocolType::Open { trade_params } - | DlcProtocolType::Renew { trade_params } + DlcProtocolType::OpenChannel { trade_params } + | DlcProtocolType::OpenPosition { trade_params } + | DlcProtocolType::ResizePosition { trade_params } | DlcProtocolType::Settle { trade_params } => { if let Err(e) = { tx_position_feed.send(InternalPositionUpdateMessage::NewTrade { @@ -336,7 +375,8 @@ impl DlcProtocolExecutor { } } _ => { - // a trade only happens in Open, Renew and Settle + // A trade only happens in `OpenChannel`, `OpenPosition`, `ResizePosition` and + // `Settle`. } } @@ -441,14 +481,61 @@ impl DlcProtocolExecutor { Ok(()) } - /// Complete an open or resize trade DLC protocol as successful and update the 10101 metadata - /// accordingly, in a single database transaction. + /// Complete a DLC protocol that opens a position, by updating several database tables in a + /// single transaction. + /// + /// Specifically, we: /// /// - Set DLC protocol to success. - /// - Update the [`PositionState::Proposed`] or [`PositionState::Resizing`] position state to - /// [`PositionState::Open`]. + /// - Update the position state to [`PositionState::Open`]. /// - Create and insert the new trade. - fn finish_open_or_resize_trade_dlc_protocol( + fn finish_open_position_dlc_protocol( + &self, + conn: &mut PgConnection, + trade_params: &TradeParams, + protocol_id: ProtocolId, + contract_id: &ContractId, + channel_id: &DlcChannelId, + ) -> QueryResult<()> { + db::dlc_protocols::set_dlc_protocol_state_to_success( + conn, + protocol_id, + contract_id, + channel_id, + )?; + + // TODO(holzeis): We are still updating the position based on the position state. This + // will change once we only have a single position per user and representing + // the position only as view on multiple trades. + let position = db::positions::Position::update_position_state( + conn, + trade_params.trader.to_string(), + vec![PositionState::Proposed], + PositionState::Open, + )?; + + let order_matching_fee = trade_params.matching_fee; + + let new_trade = NewTrade { + position_id: position.id, + contract_symbol: position.contract_symbol, + trader_pubkey: trade_params.trader, + quantity: trade_params.quantity, + trader_leverage: trade_params.leverage, + trader_direction: trade_params.direction, + average_price: trade_params.average_price, + order_matching_fee, + trader_realized_pnl_sat: None, + }; + + db::trades::insert(conn, new_trade)?; + + Ok(()) + } + + /// Complete a DLC protocol that resizes a position, by updating several database tables in a + /// single transaction. + fn finish_resize_position_dlc_protocol( &self, conn: &mut PgConnection, trade_params: &TradeParams, @@ -469,7 +556,7 @@ impl DlcProtocolExecutor { let position = db::positions::Position::update_position_state( conn, trade_params.trader.to_string(), - vec![PositionState::Proposed, PositionState::Resizing], + vec![PositionState::Resizing], PositionState::Open, )?; diff --git a/coordinator/src/node/channel.rs b/coordinator/src/node/channel.rs index 2e4d3667d..db64ebd01 100644 --- a/coordinator/src/node/channel.rs +++ b/coordinator/src/node/channel.rs @@ -135,7 +135,7 @@ impl Node { let dlc_protocol = db::dlc_protocols::get_dlc_protocol(&mut conn, protocol_id)?; match dlc_protocol.protocol_type { - DlcProtocolType::Open { .. } => { + DlcProtocolType::OpenChannel { .. } => { db::dlc_channels::set_dlc_channel_open( &mut conn, &protocol_id, @@ -147,10 +147,11 @@ impl Node { trader_funding, )?; } - DlcProtocolType::Renew { .. } + DlcProtocolType::OpenPosition { .. } | DlcProtocolType::Settle { .. } - | DlcProtocolType::Rollover { .. } => { - db::dlc_channels::update_channel_on_renew( + | DlcProtocolType::Rollover { .. } + | DlcProtocolType::ResizePosition { .. } => { + db::dlc_channels::update_channel( &mut conn, &channel.get_id(), coordinator_reserve, diff --git a/coordinator/src/trade/mod.rs b/coordinator/src/trade/mod.rs index 1bc864e2d..2f07604ee 100644 --- a/coordinator/src/trade/mod.rs +++ b/coordinator/src/trade/mod.rs @@ -374,7 +374,7 @@ impl TradeExecutor { None, &temporary_contract_id, &temporary_channel_id, - DlcProtocolType::open(trade_params, protocol_id), + DlcProtocolType::open_channel(trade_params, protocol_id), )?; // After the DLC channel has been proposed the position can be created. This fixes @@ -548,7 +548,7 @@ impl TradeExecutor { previous_id, &temporary_contract_id, &channel.get_id(), - DlcProtocolType::renew(trade_params, protocol_id, None), + DlcProtocolType::open_position(trade_params, protocol_id), )?; // TODO(holzeis): The position should only get created after the dlc protocol has finished @@ -716,7 +716,7 @@ impl TradeExecutor { previous_id, &temporary_contract_id, &channel.get_id(), - DlcProtocolType::renew(trade_params, protocol_id, realized_pnl), + DlcProtocolType::resize_position(trade_params, protocol_id, realized_pnl), )?; db::positions::Position::set_position_to_resizing(