diff --git a/coordinator/src/bin/coordinator.rs b/coordinator/src/bin/coordinator.rs index a2e290ad5..12c1a5b30 100644 --- a/coordinator/src/bin/coordinator.rs +++ b/coordinator/src/bin/coordinator.rs @@ -201,11 +201,20 @@ async fn main() -> Result<()> { let (_handle, notifier) = notification::start(tx_user_feed.clone()); - let (_handle, trading_sender) = - trading::start(pool.clone(), tx_price_feed.clone(), notifier.clone()); + let (_handle, trading_sender) = trading::start( + pool.clone(), + tx_price_feed.clone(), + notifier.clone(), + network, + ); - let _handle = async_match::monitor(pool.clone(), tx_user_feed.clone(), notifier.clone()); - let _handle = rollover::monitor(pool.clone(), tx_user_feed.clone(), notifier); + let _handle = async_match::monitor( + pool.clone(), + tx_user_feed.clone(), + notifier.clone(), + network, + ); + let _handle = rollover::monitor(pool.clone(), tx_user_feed.clone(), notifier, network); tokio::spawn({ let node = node.clone(); diff --git a/coordinator/src/node/rollover.rs b/coordinator/src/node/rollover.rs index 63a27a3ea..84ef211b3 100644 --- a/coordinator/src/node/rollover.rs +++ b/coordinator/src/node/rollover.rs @@ -8,6 +8,7 @@ use anyhow::Context; use anyhow::Result; use bitcoin::hashes::hex::ToHex; use bitcoin::secp256k1::PublicKey; +use bitcoin::Network; use bitcoin::XOnlyPublicKey; use diesel::r2d2::ConnectionManager; use diesel::r2d2::Pool; @@ -37,12 +38,14 @@ struct Rollover { contract_symbol: ContractSymbol, oracle_pk: XOnlyPublicKey, contract_tx_fee_rate: u64, + network: Network, } pub fn monitor( pool: Pool>, tx_user_feed: broadcast::Sender, notifier: mpsc::Sender, + network: Network, ) -> RemoteHandle> { let mut user_feed = tx_user_feed.subscribe(); let (fut, remote_handle) = async move { @@ -51,9 +54,13 @@ pub fn monitor( let mut conn = pool.get()?; let notifier = notifier.clone(); async move { - if let Err(e) = - check_if_eligible_for_rollover(&mut conn, notifier, new_user_msg.new_user) - .await + if let Err(e) = check_if_eligible_for_rollover( + &mut conn, + notifier, + new_user_msg.new_user, + network, + ) + .await { tracing::error!("Failed to check if eligible for rollover. Error: {e:#}"); } @@ -73,15 +80,17 @@ async fn check_if_eligible_for_rollover( conn: &mut PgConnection, notifier: mpsc::Sender, trader_id: PublicKey, + network: Network, ) -> Result<()> { tracing::debug!(%trader_id, "Checking if the users positions is eligible for rollover"); if let Some(position) = positions::Position::get_open_position_by_trader(conn, trader_id.to_string())? { - if coordinator_commons::is_in_rollover_weekend(OffsetDateTime::now_utc()) + if coordinator_commons::is_eligible_for_rollover(OffsetDateTime::now_utc(), network) && !position.is_expired() { - let next_expiry = coordinator_commons::calculate_next_expiry(OffsetDateTime::now_utc()); + let next_expiry = + coordinator_commons::calculate_next_expiry(OffsetDateTime::now_utc(), network); if position.expiry_timestamp == next_expiry { tracing::trace!(%trader_id, position_id=position.id, "Position has already been rolled over"); return Ok(()); @@ -103,7 +112,7 @@ async fn check_if_eligible_for_rollover( } impl Rollover { - pub fn new(contract: Contract) -> Result { + pub fn new(contract: Contract, network: Network) -> Result { let contract = match contract { Contract::Confirmed(contract) => contract, _ => bail!( @@ -145,6 +154,7 @@ impl Rollover { &oracle_announcement.oracle_event.event_id[..6], )?, contract_tx_fee_rate, + network, }) } @@ -155,15 +165,19 @@ impl Rollover { /// Calculates the maturity time based on the current expiry timestamp. pub fn maturity_time(&self) -> OffsetDateTime { - coordinator_commons::calculate_next_expiry(self.expiry_timestamp) + coordinator_commons::calculate_next_expiry(self.expiry_timestamp, self.network) } } impl Node { /// Initiates the rollover protocol with the app. - pub async fn propose_rollover(&self, dlc_channel_id: ChannelId) -> Result<()> { + pub async fn propose_rollover( + &self, + dlc_channel_id: ChannelId, + network: Network, + ) -> Result<()> { let contract = self.inner.get_contract_by_dlc_channel_id(dlc_channel_id)?; - let rollover = Rollover::new(contract)?; + let rollover = Rollover::new(contract, network)?; tracing::debug!(?rollover, "Rollover dlc channel"); @@ -245,7 +259,7 @@ pub mod tests { fn test_new_rollover_from_signed_contract() { let expiry_timestamp = OffsetDateTime::now_utc().unix_timestamp() + 10_000; let contract = dummy_signed_contract(200, 100, expiry_timestamp as u32); - let rollover = Rollover::new(Contract::Confirmed(contract)).unwrap(); + let rollover = Rollover::new(Contract::Confirmed(contract), Network::Bitcoin).unwrap(); assert_eq!(rollover.contract_symbol, ContractSymbol::BtcUsd); assert_eq!(rollover.margin_trader, 100); assert_eq!(rollover.margin_coordinator, 200); @@ -254,11 +268,10 @@ pub mod tests { #[test] fn test_new_rollover_from_other_contract() { let expiry_timestamp = OffsetDateTime::now_utc().unix_timestamp() + 10_000; - assert!(Rollover::new(Contract::Offered(dummy_offered_contract( - 200, - 100, - expiry_timestamp as u32 - ))) + assert!(Rollover::new( + Contract::Offered(dummy_offered_contract(200, 100, expiry_timestamp as u32)), + Network::Bitcoin + ) .is_err()) } @@ -275,6 +288,7 @@ pub mod tests { contract_symbol: ContractSymbol::BtcUsd, oracle_pk: XOnlyPublicKey::from(dummy_pubkey()), contract_tx_fee_rate: 1, + network: Network::Bitcoin, }; let event_id = rollover.event_id(); @@ -296,6 +310,7 @@ pub mod tests { contract_symbol: ContractSymbol::BtcUsd, oracle_pk: XOnlyPublicKey::from(dummy_pubkey()), contract_tx_fee_rate: 1, + network: Network::Bitcoin, }; let contract_input: ContractInput = rollover.into(); @@ -307,11 +322,10 @@ pub mod tests { #[test] fn test_rollover_expired_position() { let expiry_timestamp = OffsetDateTime::now_utc().unix_timestamp() - 10_000; - assert!(Rollover::new(Contract::Confirmed(dummy_signed_contract( - 200, - 100, - expiry_timestamp as u32 - ))) + assert!(Rollover::new( + Contract::Confirmed(dummy_signed_contract(200, 100, expiry_timestamp as u32)), + Network::Bitcoin + ) .is_err()) } diff --git a/coordinator/src/orderbook/async_match.rs b/coordinator/src/orderbook/async_match.rs index 9a04e1d54..0dd08a9bd 100644 --- a/coordinator/src/orderbook/async_match.rs +++ b/coordinator/src/orderbook/async_match.rs @@ -5,6 +5,7 @@ use crate::orderbook::db::orders; use anyhow::ensure; use anyhow::Result; use bitcoin::secp256k1::PublicKey; +use bitcoin::Network; use bitcoin::XOnlyPublicKey; use diesel::r2d2::ConnectionManager; use diesel::r2d2::Pool; @@ -26,6 +27,7 @@ pub fn monitor( pool: Pool>, tx_user_feed: broadcast::Sender, notifier: mpsc::Sender, + network: Network, ) -> RemoteHandle> { let mut user_feed = tx_user_feed.subscribe(); let (fut, remote_handle) = async move { @@ -35,7 +37,7 @@ pub fn monitor( let notifier = notifier.clone(); async move { tracing::debug!(trader_id=%new_user_msg.new_user, "Checking if the user needs to be notified about pending matches"); - if let Err(e) = process_pending_match(&mut conn, notifier, new_user_msg.new_user).await { + if let Err(e) = process_pending_match(&mut conn, notifier, new_user_msg.new_user, network).await { tracing::error!("Failed to process pending match. Error: {e:#}"); } } @@ -54,12 +56,13 @@ async fn process_pending_match( conn: &mut PgConnection, notifier: mpsc::Sender, trader_id: PublicKey, + network: Network, ) -> Result<()> { if let Some(order) = orders::get_by_trader_id_and_state(conn, trader_id, OrderState::Matched)? { tracing::debug!(%trader_id, order_id=%order.id, "Notifying trader about pending match"); let matches = matches::get_matches_by_order_id(conn, order.id)?; - let filled_with = get_filled_with_from_matches(matches)?; + let filled_with = get_filled_with_from_matches(matches, network)?; let message = match order.order_reason { OrderReason::Manual => Message::Match(filled_with), @@ -75,7 +78,7 @@ async fn process_pending_match( Ok(()) } -fn get_filled_with_from_matches(matches: Vec) -> Result { +fn get_filled_with_from_matches(matches: Vec, network: Network) -> Result { ensure!( !matches.is_empty(), "Need at least one matches record to construct a FilledWith" @@ -90,7 +93,8 @@ fn get_filled_with_from_matches(matches: Vec) -> Result { ) .expect("To be a valid pubkey"); - let expiry_timestamp = coordinator_commons::calculate_next_expiry(OffsetDateTime::now_utc()); + let expiry_timestamp = + coordinator_commons::calculate_next_expiry(OffsetDateTime::now_utc(), network); Ok(FilledWith { order_id, diff --git a/coordinator/src/orderbook/trading.rs b/coordinator/src/orderbook/trading.rs index 8d1f2cb35..ebf706dee 100644 --- a/coordinator/src/orderbook/trading.rs +++ b/coordinator/src/orderbook/trading.rs @@ -6,6 +6,7 @@ use anyhow::bail; use anyhow::Result; use autometrics::autometrics; use bitcoin::secp256k1::PublicKey; +use bitcoin::Network; use bitcoin::XOnlyPublicKey; use coordinator_commons::TradeParams; use diesel::r2d2::ConnectionManager; @@ -85,6 +86,7 @@ pub fn start( pool: Pool>, tx_price_feed: broadcast::Sender, notifier: mpsc::Sender, + network: Network, ) -> (RemoteHandle>, mpsc::Sender) { let (sender, mut receiver) = mpsc::channel::(NEW_ORDERS_BUFFER_SIZE); @@ -102,6 +104,7 @@ pub fn start( tx_price_feed, new_order, new_order_msg.order_reason, + network, ) .await; if let Err(e) = new_order_msg.sender.send(result).await { @@ -133,6 +136,7 @@ async fn process_new_order( tx_price_feed: broadcast::Sender, new_order: NewOrder, order_reason: OrderReason, + network: Network, ) -> Result { tracing::info!(trader_id=%new_order.trader_id, "Received a new {:?} order", new_order.order_type); @@ -173,7 +177,7 @@ async fn process_new_order( true, )?; - let matched_orders = match match_order(&order, opposite_direction_orders) { + let matched_orders = match match_order(&order, opposite_direction_orders, network) { Ok(Some(matched_orders)) => matched_orders, Ok(None) => { // TODO(holzeis): Currently we still respond to the user immediately if there @@ -259,6 +263,7 @@ async fn process_new_order( fn match_order( order: &Order, opposite_direction_orders: Vec, + network: Network, ) -> Result> { if order.order_type == OrderType::Limit { // we don't match limit and limit at the moment @@ -294,7 +299,8 @@ fn match_order( return Ok(None); } - let expiry_timestamp = coordinator_commons::calculate_next_expiry(OffsetDateTime::now_utc()); + let expiry_timestamp = + coordinator_commons::calculate_next_expiry(OffsetDateTime::now_utc(), network); // For now we hardcode the oracle pubkey here let oracle_pk = XOnlyPublicKey::from_str( @@ -384,6 +390,7 @@ pub mod tests { use crate::orderbook::trading::match_order; use crate::orderbook::trading::sort_orders; use bitcoin::secp256k1::PublicKey; + use bitcoin::Network; use orderbook_commons::Order; use orderbook_commons::OrderReason; use orderbook_commons::OrderState; @@ -561,7 +568,9 @@ pub mod tests { order_reason: OrderReason::Manual, }; - let matched_orders = match_order(&order, all_orders).unwrap().unwrap(); + let matched_orders = match_order(&order, all_orders, Network::Bitcoin) + .unwrap() + .unwrap(); assert_eq!(matched_orders.makers_matches.len(), 1); let maker_matches = matched_orders @@ -635,7 +644,7 @@ pub mod tests { order_reason: OrderReason::Manual, }; - assert!(match_order(&order, all_orders).is_err()); + assert!(match_order(&order, all_orders, Network::Bitcoin).is_err()); } #[test] @@ -685,7 +694,7 @@ pub mod tests { order_reason: OrderReason::Manual, }; - let matched_orders = match_order(&order, all_orders).unwrap(); + let matched_orders = match_order(&order, all_orders, Network::Bitcoin).unwrap(); assert!(matched_orders.is_none()); } diff --git a/coordinator/src/routes.rs b/coordinator/src/routes.rs index 5425c5537..9320f0164 100644 --- a/coordinator/src/routes.rs +++ b/coordinator/src/routes.rs @@ -274,7 +274,7 @@ pub async fn rollover( state .node - .propose_rollover(dlc_channel_id) + .propose_rollover(dlc_channel_id, state.node.inner.network) .await .map_err(|e| { AppError::InternalServerError(format!( diff --git a/crates/coordinator-commons/src/lib.rs b/crates/coordinator-commons/src/lib.rs index dd23d4e2b..c6a875204 100644 --- a/crates/coordinator-commons/src/lib.rs +++ b/crates/coordinator-commons/src/lib.rs @@ -1,4 +1,5 @@ use bdk::bitcoin::secp256k1::PublicKey; +use bdk::bitcoin::Network; use orderbook_commons::FilledWith; use rust_decimal::Decimal; use serde::Deserialize; @@ -83,88 +84,119 @@ pub struct TokenUpdateParams { pub fcm_token: String, } -/// Calculates the expiry timestamp at the next Sunday at 3 pm UTC from a given offset date time. -/// If the argument falls in between Friday, 3 pm UTC and Sunday, 3pm UTC, the expiry will be -/// calculated to next weeks Sunday at 3 pm -pub fn calculate_next_expiry(time: OffsetDateTime) -> OffsetDateTime { - let days = if is_in_rollover_weekend(time) || time.weekday() == Weekday::Sunday { - // if the provided time is in the rollover weekend or on a sunday, we expire the sunday the - // week after. - 7 - time.weekday().number_from_monday() + 7 - } else { - 7 - time.weekday().number_from_monday() - }; - let time = time.date().with_hms(15, 0, 0).expect("to fit into time"); - - (time + Duration::days(days as i64)).assume_utc() +/// Calculates the next expiry timestamp based on the given timestamp and the network. +pub fn calculate_next_expiry(timestamp: OffsetDateTime, network: Network) -> OffsetDateTime { + match network { + // Calculates the expiry timestamp at the next Sunday at 3 pm UTC from a given offset date + // time. If the argument falls in between Friday, 3 pm UTC and Sunday, 3pm UTC, the + // expiry will be calculated to next weeks Sunday at 3 pm + Network::Bitcoin => { + let days = if is_eligible_for_rollover(timestamp, network) + || timestamp.weekday() == Weekday::Sunday + { + // if the provided timestamp is in the rollover weekend or on a sunday, we expire + // the sunday the week after. + 7 - timestamp.weekday().number_from_monday() + 7 + } else { + 7 - timestamp.weekday().number_from_monday() + }; + let time = timestamp + .date() + .with_hms(15, 0, 0) + .expect("to fit into time"); + + (time + Duration::days(days as i64)).assume_utc() + } + // Calculates the expiry timestamp on the same day at midnight unless its already in + // rollover then the next day midnight. + _ => { + if is_eligible_for_rollover(timestamp, network) { + let after_tomorrow = timestamp.date() + Duration::days(2); + after_tomorrow.midnight().assume_utc() + } else { + let tomorrow = timestamp.date() + Duration::days(1); + tomorrow.midnight().assume_utc() + } + } + } } /// Checks whether the provided expiry date is eligible for a rollover -/// -/// Returns true if the given date falls in between friday 15 pm UTC and sunday 15 pm UTC -pub fn is_in_rollover_weekend(timestamp: OffsetDateTime) -> bool { - match timestamp.weekday() { - Weekday::Friday => timestamp.time() >= time!(15:00), - Weekday::Saturday => true, - Weekday::Sunday => timestamp.time() < time!(15:00), - _ => false, +pub fn is_eligible_for_rollover(timestamp: OffsetDateTime, network: Network) -> bool { + match network { + // Returns true if the given date falls in between Friday 15 pm UTC and Sunday 15 pm UTC + Network::Bitcoin => match timestamp.weekday() { + Weekday::Friday => timestamp.time() >= time!(15:00), + Weekday::Saturday => true, + Weekday::Sunday => timestamp.time() < time!(15:00), + _ => false, + }, + // Returns true if the timestamp is less than 8 hours from now + _ => { + let midnight = (OffsetDateTime::now_utc().date() + Duration::days(1)) + .midnight() + .assume_utc(); + (midnight - timestamp) < Duration::hours(8) + } } } #[cfg(test)] mod test { use crate::calculate_next_expiry; - use crate::is_in_rollover_weekend; + use crate::is_eligible_for_rollover; + use bdk::bitcoin::Network; + use time::Duration; use time::OffsetDateTime; #[test] - fn test_is_not_in_rollover_weekend() { + fn test_is_not_eligible_for_rollover() { // Wed Aug 09 2023 09:30:23 GMT+0000 let expiry = OffsetDateTime::from_unix_timestamp(1691573423).unwrap(); - assert!(!is_in_rollover_weekend(expiry)); + assert!(!is_eligible_for_rollover(expiry, Network::Bitcoin)); } #[test] - fn test_is_just_in_rollover_weekend_friday() { + fn test_is_just_eligible_for_rollover_friday() { // Fri Aug 11 2023 15:00:00 GMT+0000 let expiry = OffsetDateTime::from_unix_timestamp(1691766000).unwrap(); - assert!(is_in_rollover_weekend(expiry)); + assert!(is_eligible_for_rollover(expiry, Network::Bitcoin)); // Fri Aug 11 2023 15:00:01 GMT+0000 let expiry = OffsetDateTime::from_unix_timestamp(1691766001).unwrap(); - assert!(is_in_rollover_weekend(expiry)); + assert!(is_eligible_for_rollover(expiry, Network::Bitcoin)); } #[test] - fn test_is_in_rollover_weekend_saturday() { + fn test_is_eligible_for_rollover_saturday() { // Sat Aug 12 2023 16:00:00 GMT+0000 let expiry = OffsetDateTime::from_unix_timestamp(1691856000).unwrap(); - assert!(is_in_rollover_weekend(expiry)); + assert!(is_eligible_for_rollover(expiry, Network::Bitcoin)); } #[test] - fn test_is_just_in_rollover_weekend_sunday() { + fn test_is_just_eligible_for_rollover_sunday() { // Sun Aug 13 2023 14:59:59 GMT+0000 let expiry = OffsetDateTime::from_unix_timestamp(1691938799).unwrap(); - assert!(is_in_rollover_weekend(expiry)); + assert!(is_eligible_for_rollover(expiry, Network::Bitcoin)); } #[test] - fn test_is_just_not_in_rollover_weekend_sunday() { + fn test_is_just_not_eligible_for_rollover_sunday() { // Sun Aug 13 2023 15:00:00 GMT+0000 let expiry = OffsetDateTime::from_unix_timestamp(1691938800).unwrap(); - assert!(!is_in_rollover_weekend(expiry)); + assert!(!is_eligible_for_rollover(expiry, Network::Bitcoin)); // Sun Aug 13 2023 15:00:01 GMT+0000 let expiry = OffsetDateTime::from_unix_timestamp(1691938801).unwrap(); - assert!(!is_in_rollover_weekend(expiry)); + assert!(!is_eligible_for_rollover(expiry, Network::Bitcoin)); } #[test] fn test_expiry_timestamp_before_friday_15pm() { // Wed Aug 09 2023 09:30:23 GMT+0000 let from = OffsetDateTime::from_unix_timestamp(1691573423).unwrap(); - let expiry = calculate_next_expiry(from); + let expiry = calculate_next_expiry(from, Network::Bitcoin); // Sun Aug 13 2023 15:00:00 GMT+0000 assert_eq!(1691938800, expiry.unix_timestamp()); @@ -174,7 +206,7 @@ mod test { fn test_expiry_timestamp_just_before_friday_15pm() { // Fri Aug 11 2023 14:59:59 GMT+0000 let from = OffsetDateTime::from_unix_timestamp(1691765999).unwrap(); - let expiry = calculate_next_expiry(from); + let expiry = calculate_next_expiry(from, Network::Bitcoin); // Sun Aug 13 2023 15:00:00 GMT+0000 assert_eq!(1691938800, expiry.unix_timestamp()); @@ -184,7 +216,7 @@ mod test { fn test_expiry_timestamp_just_after_friday_15pm() { // Fri Aug 11 2023 15:00:01 GMT+0000 let from = OffsetDateTime::from_unix_timestamp(1691766001).unwrap(); - let expiry = calculate_next_expiry(from); + let expiry = calculate_next_expiry(from, Network::Bitcoin); // Sun Aug 20 2023 15:00:00 GMT+0000 assert_eq!(1692543600, expiry.unix_timestamp()); @@ -194,7 +226,7 @@ mod test { fn test_expiry_timestamp_at_friday_15pm() { // Fri Aug 11 2023 15:00:00 GMT+0000 let from = OffsetDateTime::from_unix_timestamp(1691766000).unwrap(); - let expiry = calculate_next_expiry(from); + let expiry = calculate_next_expiry(from, Network::Bitcoin); // Sun Aug 20 2023 15:00:00 GMT+0000 assert_eq!(1692543600, expiry.unix_timestamp()); @@ -204,7 +236,7 @@ mod test { fn test_expiry_timestamp_after_sunday_15pm() { // Sun Aug 06 2023 16:00:00 GMT+0000 let from = OffsetDateTime::from_unix_timestamp(1691337600).unwrap(); - let expiry = calculate_next_expiry(from); + let expiry = calculate_next_expiry(from, Network::Bitcoin); // Sun Aug 13 2023 15:00:00 GMT+0000 assert_eq!(1691938800, expiry.unix_timestamp()); @@ -212,11 +244,55 @@ mod test { #[test] fn test_expiry_timestamp_on_saturday() { - // // Sat Aug 12 2023 16:00:00 GMT+0000 + // Sat Aug 12 2023 16:00:00 GMT+0000 let from = OffsetDateTime::from_unix_timestamp(1691856000).unwrap(); - let expiry = calculate_next_expiry(from); + let expiry = calculate_next_expiry(from, Network::Bitcoin); // Sun Aug 20 2023 15:00:00 GMT+0000 assert_eq!(1692543600, expiry.unix_timestamp()); } + + #[test] + fn test_expiry_timestamp_regtest_midnight() { + // 12:00 on the current day + let timestamp = OffsetDateTime::now_utc().date().midnight() + Duration::hours(12); + let expiry = calculate_next_expiry(timestamp.assume_utc(), Network::Regtest); + + let midnight = (OffsetDateTime::now_utc().date() + Duration::days(1)) + .midnight() + .assume_utc(); + + assert_eq!(midnight, expiry); + } + + #[test] + fn test_expiry_timestamp_regtest_next_midnight() { + // 20:00 on the current day + let timestamp = OffsetDateTime::now_utc().date().midnight() + Duration::hours(20); + let expiry = calculate_next_expiry(timestamp.assume_utc(), Network::Regtest); + + let next_midnight = (timestamp.date() + Duration::days(2)) + .midnight() + .assume_utc(); + + assert_eq!(next_midnight, expiry); + } + + #[test] + fn test_is_not_eligable_for_rollover_regtest() { + let timestamp = OffsetDateTime::now_utc().date().midnight() + Duration::hours(16); + assert!(!is_eligible_for_rollover( + timestamp.assume_utc(), + Network::Regtest + )) + } + + #[test] + fn test_is_eligable_for_rollover_regtest() { + let timestamp = OffsetDateTime::now_utc().date().midnight() + Duration::hours(17); + assert!(is_eligible_for_rollover( + timestamp.assume_utc(), + Network::Regtest + )) + } } diff --git a/crates/tests-e2e/tests/rollover_position.rs b/crates/tests-e2e/tests/rollover_position.rs index 8e6af79dc..2a823c5a2 100644 --- a/crates/tests-e2e/tests/rollover_position.rs +++ b/crates/tests-e2e/tests/rollover_position.rs @@ -1,3 +1,4 @@ +use bitcoin::Network; use native::api; use native::trade::position; use position::PositionState; @@ -22,7 +23,7 @@ async fn can_rollover_position() { .unwrap(); let position = test.app.rx.position().expect("position to exist"); - let new_expiry = coordinator_commons::calculate_next_expiry(position.expiry); + let new_expiry = coordinator_commons::calculate_next_expiry(position.expiry, Network::Bitcoin); coordinator .rollover(&dlc_channel.dlc_channel_id.unwrap()) diff --git a/mobile/lib/features/trade/application/trade_values_service.dart b/mobile/lib/features/trade/application/trade_values_service.dart index b0897d425..0ed9ac2dc 100644 --- a/mobile/lib/features/trade/application/trade_values_service.dart +++ b/mobile/lib/features/trade/application/trade_values_service.dart @@ -41,6 +41,8 @@ class TradeValuesService { } DateTime getExpiryTimestamp() { - return DateTime.fromMillisecondsSinceEpoch(rust.api.getExpiryTimestamp() * 1000); + String network = const String.fromEnvironment('NETWORK', defaultValue: "regtest"); + return DateTime.fromMillisecondsSinceEpoch( + rust.api.getExpiryTimestamp(network: network) * 1000); } } diff --git a/mobile/lib/features/trade/domain/trade_values.dart b/mobile/lib/features/trade/domain/trade_values.dart index 5031fa132..b3f2ea073 100644 --- a/mobile/lib/features/trade/domain/trade_values.dart +++ b/mobile/lib/features/trade/domain/trade_values.dart @@ -109,7 +109,6 @@ class TradeValues { updatePriceAndQuantity(double? price) { this.price = price; - // _recalculateMargin(); _recalculateQuantity(); _recalculateLiquidationPrice(); _recalculateFee(); @@ -117,7 +116,6 @@ class TradeValues { updatePriceAndMargin(double? price) { this.price = price; - // _recalculateMargin(); _recalculateMargin(); _recalculateLiquidationPrice(); _recalculateFee(); diff --git a/mobile/native/src/api.rs b/mobile/native/src/api.rs index 0d049ee68..f462e9f57 100644 --- a/mobile/native/src/api.rs +++ b/mobile/native/src/api.rs @@ -396,8 +396,10 @@ pub fn get_channel_open_fee_estimate_sat() -> Result { Ok(estimate.ceil() as u64) } -pub fn get_expiry_timestamp() -> SyncReturn { +pub fn get_expiry_timestamp(network: String) -> SyncReturn { + let network = config::api::parse_network(&network); SyncReturn( - coordinator_commons::calculate_next_expiry(OffsetDateTime::now_utc()).unix_timestamp(), + coordinator_commons::calculate_next_expiry(OffsetDateTime::now_utc(), network) + .unix_timestamp(), ) } diff --git a/mobile/native/src/config/api.rs b/mobile/native/src/config/api.rs index 3a29b579d..08348ce1d 100644 --- a/mobile/native/src/config/api.rs +++ b/mobile/native/src/config/api.rs @@ -41,7 +41,7 @@ impl From for ConfigInternal { } } -fn parse_network(network: &str) -> Network { +pub fn parse_network(network: &str) -> Network { match network { "signet" => Network::Signet, "testnet" => Network::Testnet,