Browse Source

Merge #666

666: Fixed settlement interval r=da-kami a=da-kami

This work was done as pre-work for #627 which is currently blocked by the model refactor. 

I think we should still get these changes in!

Co-authored-by: Daniel Karzel <daniel@comit.network>
debug-collab-settlement
bors[bot] 3 years ago
committed by GitHub
parent
commit
1fc9ab742e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      daemon/src/db.rs
  2. 16
      daemon/src/lib.rs
  3. 12
      daemon/src/maker.rs
  4. 12
      daemon/src/maker_cfd.rs
  5. 368
      daemon/src/model/cfd.rs
  6. 4
      daemon/src/taker.rs
  7. 55
      daemon/src/taker_cfd.rs
  8. 2
      daemon/src/to_sse_event.rs
  9. 4
      daemon/tests/harness/mod.rs

10
daemon/src/db.rs

@ -39,7 +39,7 @@ pub async fn insert_order(order: &Order, conn: &mut PoolConnection<Sqlite>) -> a
.bind(order.leverage.get())
.bind(&order.liquidation_price.to_string())
.bind(&order.creation_timestamp.seconds())
.bind(&order.settlement_time_interval_hours.whole_seconds())
.bind(&order.settlement_interval.whole_seconds())
.bind(&order.origin)
.bind(&order.oracle_event_id.to_string())
.execute(conn)
@ -90,7 +90,7 @@ pub async fn load_order_by_id(
leverage: row.leverage,
liquidation_price: row.liquidation_price.parse()?,
creation_timestamp: row.ts_secs,
settlement_time_interval_hours: Duration::new(row.settlement_time_interval_secs, 0),
settlement_interval: Duration::new(row.settlement_time_interval_secs, 0),
origin: row.origin,
oracle_event_id: row.oracle_event_id.parse()?,
})
@ -307,7 +307,7 @@ pub async fn load_cfd_by_order_id(
leverage: row.leverage,
liquidation_price: row.liquidation_price.parse()?,
creation_timestamp: row.ts_secs,
settlement_time_interval_hours: Duration::new(row.settlement_time_interval_secs, 0),
settlement_interval: Duration::new(row.settlement_time_interval_secs, 0),
origin: row.origin,
oracle_event_id: row.oracle_event_id.parse()?,
};
@ -405,7 +405,7 @@ pub async fn load_all_cfds(conn: &mut PoolConnection<Sqlite>) -> anyhow::Result<
leverage: row.leverage,
liquidation_price: row.liquidation_price.parse()?,
creation_timestamp: row.ts_secs,
settlement_time_interval_hours: Duration::new(row.settlement_time_interval_secs, 0),
settlement_interval: Duration::new(row.settlement_time_interval_secs, 0),
origin: row.origin,
oracle_event_id: row.oracle_event_id.parse()?,
};
@ -511,7 +511,7 @@ pub async fn load_cfds_by_oracle_event_id(
leverage: row.leverage,
liquidation_price: row.liquidation_price.parse()?,
creation_timestamp: row.ts_secs,
settlement_time_interval_hours: Duration::new(row.settlement_time_interval_secs, 0),
settlement_interval: Duration::new(row.settlement_time_interval_secs, 0),
origin: row.origin,
oracle_event_id: row.oracle_event_id.parse()?,
};

16
daemon/src/lib.rs

@ -52,6 +52,18 @@ pub const HEARTBEAT_INTERVAL: std::time::Duration = Duration::from_secs(5);
pub const N_PAYOUTS: usize = 200;
/// The interval until the cfd gets settled, i.e. the attestation happens
///
/// This variable defines at what point in time the oracle event id will be chose to settle the cfd.
/// Hence, this constant defines how long a cfd is open (until it gets either settled or rolled
/// over).
///
/// Multiple code parts align on this constant:
/// - How the oracle event id is chosen when creating an order (maker)
/// - The sliding window of cached oracle announcements (maker, taker)
/// - The auto-rollover time-window (taker)
pub const SETTLEMENT_INTERVAL: time::Duration = time::Duration::hours(24);
/// Struct controlling the lifetime of the async tasks,
/// such as running actors and periodic notifications.
/// If it gets dropped, all tasks are cancelled.
@ -106,7 +118,7 @@ where
Box<dyn MessageChannel<NewTakerOnline>>,
Box<dyn MessageChannel<FromTaker>>,
) -> T,
settlement_time_interval_hours: time::Duration,
settlement_interval: time::Duration,
n_payouts: usize,
projection_actor: Address<projection::Actor>,
) -> Result<Self>
@ -126,7 +138,7 @@ where
let (cfd_actor_addr, cfd_actor_fut) = maker_cfd::Actor::new(
db,
wallet_addr,
settlement_time_interval_hours,
settlement_interval,
oracle_pk,
projection_actor,
inc_conn_addr.clone(),

12
daemon/src/maker.rs

@ -13,6 +13,7 @@ use daemon::tokio_ext::FutureExt;
use daemon::{
bitmex_price_feed, db, housekeeping, logger, maker_cfd, maker_inc_connections, monitor, oracle,
projection, wallet, wallet_sync, MakerActorSystem, Tasks, HEARTBEAT_INTERVAL, N_PAYOUTS,
SETTLEMENT_INTERVAL,
};
use sqlx::sqlite::SqliteConnectOptions;
use sqlx::SqlitePool;
@ -51,10 +52,6 @@ struct Opts {
#[clap(short, long, default_value = "Debug")]
log_level: LevelFilter,
/// The time interval until potential settlement of each CFD in hours
#[clap(long, default_value = "24")]
settlement_time_interval_hours: u8,
#[clap(subcommand)]
network: Network,
}
@ -247,9 +244,6 @@ async fn main() -> Result<()> {
housekeeping::transition_non_continue_cfds_to_setup_failed(&mut conn).await?;
housekeeping::rebroadcast_transactions(&mut conn, &wallet).await?;
let settlement_time_interval_hours =
time::Duration::hours(opts.settlement_time_interval_hours as i64);
let (projection_actor, projection_context) = xtra::Context::new(None);
let MakerActorSystem {
@ -260,7 +254,7 @@ async fn main() -> Result<()> {
db.clone(),
wallet.clone(),
oracle,
|cfds, channel| oracle::Actor::new(cfds, channel, settlement_time_interval_hours),
|cfds, channel| oracle::Actor::new(cfds, channel, SETTLEMENT_INTERVAL),
{
|channel, cfds| {
let electrum = opts.network.electrum().to_string();
@ -270,7 +264,7 @@ async fn main() -> Result<()> {
|channel0, channel1| {
maker_inc_connections::Actor::new(channel0, channel1, identity_sk, HEARTBEAT_INTERVAL)
},
time::Duration::hours(opts.settlement_time_interval_hours as i64),
SETTLEMENT_INTERVAL,
N_PAYOUTS,
projection_actor.clone(),
)

12
daemon/src/maker_cfd.rs

@ -62,7 +62,7 @@ pub struct FromTaker {
pub struct Actor<O, M, T, W> {
db: sqlx::SqlitePool,
wallet: Address<W>,
settlement_time_interval_hours: Duration,
settlement_interval: Duration,
oracle_pk: schnorrsig::PublicKey,
projection_actor: Address<projection::Actor>,
takers: Address<T>,
@ -100,7 +100,7 @@ impl<O, M, T, W> Actor<O, M, T, W> {
pub fn new(
db: sqlx::SqlitePool,
wallet: Address<W>,
settlement_time_interval_hours: Duration,
settlement_interval: Duration,
oracle_pk: schnorrsig::PublicKey,
projection_actor: Address<projection::Actor>,
takers: Address<T>,
@ -111,7 +111,7 @@ impl<O, M, T, W> Actor<O, M, T, W> {
Self {
db,
wallet,
settlement_time_interval_hours,
settlement_interval,
oracle_pk,
projection_actor,
takers,
@ -736,7 +736,7 @@ where
let dlc = cfd.open_dlc().context("CFD was in wrong state")?;
let oracle_event_id = oracle::next_announcement_after(
time::OffsetDateTime::now_utc() + cfd.order.settlement_time_interval_hours,
time::OffsetDateTime::now_utc() + cfd.order.settlement_interval,
)?;
let announcement = self
.oracle_actor
@ -951,7 +951,7 @@ where
} = msg;
let oracle_event_id = oracle::next_announcement_after(
time::OffsetDateTime::now_utc() + self.settlement_time_interval_hours,
time::OffsetDateTime::now_utc() + self.settlement_interval,
)?;
let order = Order::new(
@ -960,7 +960,7 @@ where
max_quantity,
Origin::Ours,
oracle_event_id,
self.settlement_time_interval_hours,
self.settlement_interval,
)?;
// 1. Save to DB

368
daemon/src/model/cfd.rs

@ -115,7 +115,7 @@ pub struct Order {
pub creation_timestamp: Timestamp,
/// The duration that will be used for calculating the settlement timestamp
pub settlement_time_interval_hours: Duration,
pub settlement_interval: Duration,
pub origin: Origin,
@ -132,7 +132,7 @@ impl Order {
max_quantity: Usd,
origin: Origin,
oracle_event_id: BitMexPriceEventId,
settlement_time_interval_hours: Duration,
settlement_interval: Duration,
) -> Result<Self> {
let leverage = Leverage::new(2)?;
let liquidation_price = calculate_long_liquidation_price(leverage, price);
@ -147,7 +147,7 @@ impl Order {
liquidation_price,
position: Position::Short,
creation_timestamp: Timestamp::now(),
settlement_time_interval_hours,
settlement_interval,
origin,
oracle_event_id,
})
@ -671,7 +671,7 @@ impl Cfd {
}
pub fn refund_timelock_in_blocks(&self) -> u32 {
(self.order.settlement_time_interval_hours * Cfd::REFUND_THRESHOLD)
(self.order.settlement_interval * Cfd::REFUND_THRESHOLD)
.as_blocks()
.ceil() as u32
}
@ -680,20 +680,20 @@ impl Cfd {
self.order.oracle_event_id.timestamp()
}
/// A factor to be added to the CFD order settlement_time_interval_hours for calculating the
/// A factor to be added to the CFD order settlement_interval for calculating the
/// refund timelock.
///
/// The refund timelock is important in case the oracle disappears or never publishes a
/// signature. Ideally, both users collaboratively settle in the refund scenario. This
/// factor is important if the users do not settle collaboratively.
/// `1.5` times the settlement_time_interval_hours as defined in CFD order should be safe in the
/// `1.5` times the settlement_interval as defined in CFD order should be safe in the
/// extreme case where a user publishes the commit transaction right after the contract was
/// initialized. In this case, the oracle still has `1.0 *
/// cfdorder.settlement_time_interval_hours` time to attest and no one can publish the refund
/// cfdorder.settlement_interval` time to attest and no one can publish the refund
/// transaction.
/// The downside is that if the oracle disappears: the users would only notice at the end
/// of the cfd settlement_time_interval_hours. In this case the users has to wait for another
/// `1.5` times of the settlement_time_interval_hours to get his funds back.
/// of the cfd settlement_interval. In this case the users has to wait for another
/// `1.5` times of the settlement_interval to get his funds back.
const REFUND_THRESHOLD: f32 = 1.5;
pub const CET_TIMELOCK: u32 = 12;
@ -1464,6 +1464,181 @@ fn calculate_profit(
Ok((profit, Percent(percent)))
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Cet {
pub tx: Transaction,
pub adaptor_sig: EcdsaAdaptorSignature,
// TODO: Range + number of digits (usize) could be represented as Digits similar to what we do
// in the protocol lib
pub range: RangeInclusive<u64>,
pub n_bits: usize,
}
/// Contains all data we've assembled about the CFD through the setup protocol.
///
/// All contained signatures are the signatures of THE OTHER PARTY.
/// To use any of these transactions, we need to re-sign them with the correct secret key.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Dlc {
pub identity: SecretKey,
pub identity_counterparty: PublicKey,
pub revocation: SecretKey,
pub revocation_pk_counterparty: PublicKey,
pub publish: SecretKey,
pub publish_pk_counterparty: PublicKey,
pub maker_address: Address,
pub taker_address: Address,
/// The fully signed lock transaction ready to be published on chain
pub lock: (Transaction, Descriptor<PublicKey>),
pub commit: (Transaction, EcdsaAdaptorSignature, Descriptor<PublicKey>),
pub cets: HashMap<BitMexPriceEventId, Vec<Cet>>,
pub refund: (Transaction, Signature),
#[serde(with = "::bdk::bitcoin::util::amount::serde::as_sat")]
pub maker_lock_amount: Amount,
#[serde(with = "::bdk::bitcoin::util::amount::serde::as_sat")]
pub taker_lock_amount: Amount,
pub revoked_commit: Vec<RevokedCommit>,
}
impl Dlc {
/// Create a close transaction based on the current contract and a settlement proposals
pub fn close_transaction(
&self,
proposal: &crate::model::cfd::SettlementProposal,
) -> Result<(Transaction, Signature)> {
let (lock_tx, lock_desc) = &self.lock;
let (lock_outpoint, lock_amount) = {
let outpoint = lock_tx
.outpoint(&lock_desc.script_pubkey())
.expect("lock script to be in lock tx");
let amount = Amount::from_sat(lock_tx.output[outpoint.vout as usize].value);
(outpoint, amount)
};
let (tx, sighash) = maia::close_transaction(
lock_desc,
lock_outpoint,
lock_amount,
(&self.maker_address, proposal.maker),
(&self.taker_address, proposal.taker),
)
.context("Unable to collaborative close transaction")?;
let sig = SECP256K1.sign(&sighash, &self.identity);
Ok((tx, sig))
}
pub fn finalize_spend_transaction(
&self,
(close_tx, own_sig): (Transaction, Signature),
counterparty_sig: Signature,
) -> Result<Transaction> {
let own_pk = PublicKey::new(secp256k1_zkp::PublicKey::from_secret_key(
SECP256K1,
&self.identity,
));
let (_, lock_desc) = &self.lock;
let spend_tx = maia::finalize_spend_transaction(
close_tx,
lock_desc,
(own_pk, own_sig),
(self.identity_counterparty, counterparty_sig),
)?;
Ok(spend_tx)
}
pub fn refund_amount(&self, role: Role) -> Amount {
let our_script_pubkey = match role {
Role::Taker => self.taker_address.script_pubkey(),
Role::Maker => self.maker_address.script_pubkey(),
};
self.refund
.0
.output
.iter()
.find(|output| output.script_pubkey == our_script_pubkey)
.map(|output| Amount::from_sat(output.value))
.unwrap_or_default()
}
pub fn script_pubkey_for(&self, role: Role) -> Script {
match role {
Role::Maker => self.maker_address.script_pubkey(),
Role::Taker => self.taker_address.script_pubkey(),
}
}
}
/// Information which we need to remember in order to construct a
/// punishment transaction in case the counterparty publishes a
/// revoked commit transaction.
///
/// It also includes the information needed to monitor for the
/// publication of the revoked commit transaction.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct RevokedCommit {
// To build punish transaction
pub encsig_ours: EcdsaAdaptorSignature,
pub revocation_sk_theirs: SecretKey,
pub publication_pk_theirs: PublicKey,
// To monitor revoked commit transaction
pub txid: Txid,
pub script_pubkey: Script,
}
/// Used when transactions (e.g. collaborative close) are recorded as a part of
/// CfdState in the cases when we can't solely rely on state transition
/// timestamp as it could have occured for different reasons (like a new
/// attestation in Open state)
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct CollaborativeSettlement {
pub tx: Transaction,
pub timestamp: Timestamp,
#[serde(with = "::bdk::bitcoin::util::amount::serde::as_sat")]
payout: Amount,
price: Price,
}
impl CollaborativeSettlement {
pub fn new(tx: Transaction, own_script_pubkey: Script, price: Price) -> Result<Self> {
// Falls back to Amount::ZERO in case we don't find an output that matches out script pubkey
// The assumption is, that this can happen for cases where we were liuqidated
let payout = match tx
.output
.iter()
.find(|output| output.script_pubkey == own_script_pubkey)
.map(|output| Amount::from_sat(output.value))
{
Some(payout) => payout,
None => {
tracing::error!(
"Collaborative settlement with a zero amount, this should really not happen!"
);
Amount::ZERO
}
};
Ok(Self {
tx,
timestamp: Timestamp::now(),
payout,
price,
})
}
pub fn payout(&self) -> Amount {
self.payout
}
}
#[cfg(test)]
mod tests {
use super::*;
@ -1715,178 +1890,3 @@ mod tests {
assert_eq!(id, deserialized);
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Cet {
pub tx: Transaction,
pub adaptor_sig: EcdsaAdaptorSignature,
// TODO: Range + number of digits (usize) could be represented as Digits similar to what we do
// in the protocol lib
pub range: RangeInclusive<u64>,
pub n_bits: usize,
}
/// Contains all data we've assembled about the CFD through the setup protocol.
///
/// All contained signatures are the signatures of THE OTHER PARTY.
/// To use any of these transactions, we need to re-sign them with the correct secret key.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Dlc {
pub identity: SecretKey,
pub identity_counterparty: PublicKey,
pub revocation: SecretKey,
pub revocation_pk_counterparty: PublicKey,
pub publish: SecretKey,
pub publish_pk_counterparty: PublicKey,
pub maker_address: Address,
pub taker_address: Address,
/// The fully signed lock transaction ready to be published on chain
pub lock: (Transaction, Descriptor<PublicKey>),
pub commit: (Transaction, EcdsaAdaptorSignature, Descriptor<PublicKey>),
pub cets: HashMap<BitMexPriceEventId, Vec<Cet>>,
pub refund: (Transaction, Signature),
#[serde(with = "::bdk::bitcoin::util::amount::serde::as_sat")]
pub maker_lock_amount: Amount,
#[serde(with = "::bdk::bitcoin::util::amount::serde::as_sat")]
pub taker_lock_amount: Amount,
pub revoked_commit: Vec<RevokedCommit>,
}
impl Dlc {
/// Create a close transaction based on the current contract and a settlement proposals
pub fn close_transaction(
&self,
proposal: &crate::model::cfd::SettlementProposal,
) -> Result<(Transaction, Signature)> {
let (lock_tx, lock_desc) = &self.lock;
let (lock_outpoint, lock_amount) = {
let outpoint = lock_tx
.outpoint(&lock_desc.script_pubkey())
.expect("lock script to be in lock tx");
let amount = Amount::from_sat(lock_tx.output[outpoint.vout as usize].value);
(outpoint, amount)
};
let (tx, sighash) = maia::close_transaction(
lock_desc,
lock_outpoint,
lock_amount,
(&self.maker_address, proposal.maker),
(&self.taker_address, proposal.taker),
)
.context("Unable to collaborative close transaction")?;
let sig = SECP256K1.sign(&sighash, &self.identity);
Ok((tx, sig))
}
pub fn finalize_spend_transaction(
&self,
(close_tx, own_sig): (Transaction, Signature),
counterparty_sig: Signature,
) -> Result<Transaction> {
let own_pk = PublicKey::new(secp256k1_zkp::PublicKey::from_secret_key(
SECP256K1,
&self.identity,
));
let (_, lock_desc) = &self.lock;
let spend_tx = maia::finalize_spend_transaction(
close_tx,
lock_desc,
(own_pk, own_sig),
(self.identity_counterparty, counterparty_sig),
)?;
Ok(spend_tx)
}
pub fn refund_amount(&self, role: Role) -> Amount {
let our_script_pubkey = match role {
Role::Taker => self.taker_address.script_pubkey(),
Role::Maker => self.maker_address.script_pubkey(),
};
self.refund
.0
.output
.iter()
.find(|output| output.script_pubkey == our_script_pubkey)
.map(|output| Amount::from_sat(output.value))
.unwrap_or_default()
}
pub fn script_pubkey_for(&self, role: Role) -> Script {
match role {
Role::Maker => self.maker_address.script_pubkey(),
Role::Taker => self.taker_address.script_pubkey(),
}
}
}
/// Information which we need to remember in order to construct a
/// punishment transaction in case the counterparty publishes a
/// revoked commit transaction.
///
/// It also includes the information needed to monitor for the
/// publication of the revoked commit transaction.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct RevokedCommit {
// To build punish transaction
pub encsig_ours: EcdsaAdaptorSignature,
pub revocation_sk_theirs: SecretKey,
pub publication_pk_theirs: PublicKey,
// To monitor revoked commit transaction
pub txid: Txid,
pub script_pubkey: Script,
}
/// Used when transactions (e.g. collaborative close) are recorded as a part of
/// CfdState in the cases when we can't solely rely on state transition
/// timestamp as it could have occured for different reasons (like a new
/// attestation in Open state)
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct CollaborativeSettlement {
pub tx: Transaction,
pub timestamp: Timestamp,
#[serde(with = "::bdk::bitcoin::util::amount::serde::as_sat")]
payout: Amount,
price: Price,
}
impl CollaborativeSettlement {
pub fn new(tx: Transaction, own_script_pubkey: Script, price: Price) -> Result<Self> {
// Falls back to Amount::ZERO in case we don't find an output that matches out script pubkey
// The assumption is, that this can happen for cases where we were liuqidated
let payout = match tx
.output
.iter()
.find(|output| output.script_pubkey == own_script_pubkey)
.map(|output| Amount::from_sat(output.value))
{
Some(payout) => payout,
None => {
tracing::error!(
"Collaborative settlement with a zero amount, this should really not happen!"
);
Amount::ZERO
}
};
Ok(Self {
tx,
timestamp: Timestamp::now(),
payout,
price,
})
}
pub fn payout(&self) -> Amount {
self.payout
}
}

4
daemon/src/taker.rs

@ -13,6 +13,7 @@ use daemon::tokio_ext::FutureExt;
use daemon::{
bitmex_price_feed, connection, db, housekeeping, logger, monitor, oracle, projection,
taker_cfd, wallet, wallet_sync, TakerActorSystem, Tasks, HEARTBEAT_INTERVAL, N_PAYOUTS,
SETTLEMENT_INTERVAL,
};
use sqlx::sqlite::SqliteConnectOptions;
use sqlx::SqlitePool;
@ -30,7 +31,6 @@ use xtra::Actor;
mod routes_taker;
pub const ANNOUNCEMENT_LOOKAHEAD: time::Duration = time::Duration::hours(24);
const CONNECTION_RETRY_INTERVAL: Duration = Duration::from_secs(5);
#[derive(Parser)]
@ -247,7 +247,7 @@ async fn main() -> Result<()> {
wallet.clone(),
oracle,
identity_sk,
|cfds, channel| oracle::Actor::new(cfds, channel, ANNOUNCEMENT_LOOKAHEAD),
|cfds, channel| oracle::Actor::new(cfds, channel, SETTLEMENT_INTERVAL),
{
|channel, cfds| {
let electrum = opts.network.electrum().to_string();

55
daemon/src/taker_cfd.rs

@ -319,36 +319,7 @@ impl<O, M, W> Actor<O, M, W> {
}
Ok(())
}
}
impl<O, M, W> Actor<O, M, W>
where
W: xtra::Handler<wallet::TryBroadcastTransaction>,
{
async fn handle_oracle_attestation(&mut self, attestation: oracle::Attestation) -> Result<()> {
let mut conn = self.db.acquire().await?;
cfd_actors::handle_oracle_attestation(
attestation,
&mut conn,
&self.wallet,
&self.projection_actor,
)
.await?;
Ok(())
}
async fn handle_monitoring_event(&mut self, event: monitor::Event) -> Result<()> {
let mut conn = self.db.acquire().await?;
cfd_actors::handle_monitoring_event(event, &mut conn, &self.wallet, &self.projection_actor)
.await?;
Ok(())
}
}
impl<O, M, W> Actor<O, M, W>
where
W: xtra::Handler<wallet::TryBroadcastTransaction>,
{
async fn handle_propose_roll_over(&mut self, order_id: OrderId) -> Result<()> {
if self.current_pending_proposals.contains_key(&order_id) {
anyhow::bail!("An update for order id {} is already in progress", order_id)
@ -377,11 +348,29 @@ where
Ok(())
}
}
impl<O, M, W> Actor<O, M, W> where
W: xtra::Handler<wallet::TryBroadcastTransaction>
+ xtra::Handler<wallet::Sign>
+ xtra::Handler<wallet::BuildPartyParams>
impl<O, M, W> Actor<O, M, W>
where
W: xtra::Handler<wallet::TryBroadcastTransaction>,
{
async fn handle_oracle_attestation(&mut self, attestation: oracle::Attestation) -> Result<()> {
let mut conn = self.db.acquire().await?;
cfd_actors::handle_oracle_attestation(
attestation,
&mut conn,
&self.wallet,
&self.projection_actor,
)
.await?;
Ok(())
}
async fn handle_monitoring_event(&mut self, event: monitor::Event) -> Result<()> {
let mut conn = self.db.acquire().await?;
cfd_actors::handle_monitoring_event(event, &mut conn, &self.wallet, &self.projection_actor)
.await?;
Ok(())
}
}
impl<O, M, W> Actor<O, M, W>

2
daemon/src/to_sse_event.rs

@ -339,7 +339,7 @@ impl ToSseEvent for Option<model::cfd::Order> {
liquidation_price: order.liquidation_price.into(),
creation_timestamp: order.creation_timestamp,
settlement_time_interval_in_secs: order
.settlement_time_interval_hours
.settlement_interval
.whole_seconds()
.try_into()
.expect("settlement_time_interval_hours is always positive number"),

4
daemon/tests/harness/mod.rs

@ -77,7 +77,7 @@ impl Maker {
let (wallet_addr, wallet_fut) = wallet.create(None).run();
tasks.add(wallet_fut);
let settlement_time_interval_hours = time::Duration::hours(24);
let settlement_interval = time::Duration::hours(24);
let seed = Seed::default();
let (identity_pk, identity_sk) = seed.derive_identity();
@ -100,7 +100,7 @@ impl Maker {
HEARTBEAT_INTERVAL_FOR_TEST,
)
},
settlement_time_interval_hours,
settlement_interval,
N_PAYOUTS_FOR_TEST,
projection_actor.clone(),
)

Loading…
Cancel
Save