Browse Source
322: Cleanup in Cfd actors r=klochowicz a=klochowicz I started out trying to fix a common gotcha (forgetting to refresh Cfd feed), and then realised that I was not far off of addressing a bunch of TODOs in the code Co-authored-by: Mariusz Klochowicz <mariusz@klochowicz.com>refactor/no-log-handler
committed by
GitHub
6 changed files with 229 additions and 277 deletions
@ -0,0 +1,149 @@ |
|||||
|
use crate::model::cfd::{Attestation, Cfd, CfdState, CfdStateChangeEvent, OrderId}; |
||||
|
use crate::wallet::Wallet; |
||||
|
use crate::{db, monitor, oracle}; |
||||
|
use anyhow::{bail, Result}; |
||||
|
use sqlx::pool::PoolConnection; |
||||
|
use sqlx::Sqlite; |
||||
|
use tokio::sync::watch; |
||||
|
|
||||
|
pub async fn insert_cfd( |
||||
|
cfd: Cfd, |
||||
|
conn: &mut PoolConnection<Sqlite>, |
||||
|
update_sender: &watch::Sender<Vec<Cfd>>, |
||||
|
) -> Result<()> { |
||||
|
db::insert_cfd(cfd, conn).await?; |
||||
|
update_sender.send(db::load_all_cfds(conn).await?)?; |
||||
|
Ok(()) |
||||
|
} |
||||
|
|
||||
|
pub async fn insert_new_cfd_state_by_order_id( |
||||
|
order_id: OrderId, |
||||
|
new_state: &CfdState, |
||||
|
conn: &mut PoolConnection<Sqlite>, |
||||
|
update_sender: &watch::Sender<Vec<Cfd>>, |
||||
|
) -> Result<()> { |
||||
|
db::insert_new_cfd_state_by_order_id(order_id, new_state, conn).await?; |
||||
|
update_sender.send(db::load_all_cfds(conn).await?)?; |
||||
|
Ok(()) |
||||
|
} |
||||
|
|
||||
|
pub async fn try_cet_publication( |
||||
|
cfd: &mut Cfd, |
||||
|
conn: &mut PoolConnection<Sqlite>, |
||||
|
wallet: &Wallet, |
||||
|
update_sender: &watch::Sender<Vec<Cfd>>, |
||||
|
) -> Result<()> { |
||||
|
match cfd.cet()? { |
||||
|
Ok(cet) => { |
||||
|
let txid = wallet.try_broadcast_transaction(cet).await?; |
||||
|
tracing::info!("CET published with txid {}", txid); |
||||
|
|
||||
|
if cfd.handle(CfdStateChangeEvent::CetSent)?.is_none() { |
||||
|
bail!("If we can get the CET we should be able to transition") |
||||
|
} |
||||
|
|
||||
|
insert_new_cfd_state_by_order_id(cfd.order.id, &cfd.state, conn, update_sender).await?; |
||||
|
} |
||||
|
Err(not_ready_yet) => { |
||||
|
tracing::debug!("{:#}", not_ready_yet); |
||||
|
return Ok(()); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
Ok(()) |
||||
|
} |
||||
|
|
||||
|
pub async fn handle_monitoring_event( |
||||
|
event: monitor::Event, |
||||
|
conn: &mut PoolConnection<Sqlite>, |
||||
|
wallet: &Wallet, |
||||
|
update_sender: &watch::Sender<Vec<Cfd>>, |
||||
|
) -> Result<()> { |
||||
|
let order_id = event.order_id(); |
||||
|
|
||||
|
let mut cfd = db::load_cfd_by_order_id(order_id, conn).await?; |
||||
|
|
||||
|
if cfd.handle(CfdStateChangeEvent::Monitor(event))?.is_none() { |
||||
|
// early exit if there was not state change
|
||||
|
// this is for cases where we are already in a final state
|
||||
|
return Ok(()); |
||||
|
} |
||||
|
|
||||
|
insert_new_cfd_state_by_order_id(order_id, &cfd.state, conn, update_sender).await?; |
||||
|
|
||||
|
if let CfdState::OpenCommitted { .. } = cfd.state { |
||||
|
try_cet_publication(&mut cfd, conn, wallet, update_sender).await?; |
||||
|
} else if let CfdState::MustRefund { .. } = cfd.state { |
||||
|
let signed_refund_tx = cfd.refund_tx()?; |
||||
|
let txid = wallet.try_broadcast_transaction(signed_refund_tx).await?; |
||||
|
|
||||
|
tracing::info!("Refund transaction published on chain: {}", txid); |
||||
|
} |
||||
|
Ok(()) |
||||
|
} |
||||
|
|
||||
|
pub async fn handle_commit( |
||||
|
order_id: OrderId, |
||||
|
conn: &mut PoolConnection<Sqlite>, |
||||
|
wallet: &Wallet, |
||||
|
update_sender: &watch::Sender<Vec<Cfd>>, |
||||
|
) -> Result<()> { |
||||
|
let mut cfd = db::load_cfd_by_order_id(order_id, conn).await?; |
||||
|
|
||||
|
let signed_commit_tx = cfd.commit_tx()?; |
||||
|
|
||||
|
let txid = wallet.try_broadcast_transaction(signed_commit_tx).await?; |
||||
|
|
||||
|
if cfd.handle(CfdStateChangeEvent::CommitTxSent)?.is_none() { |
||||
|
bail!("If we can get the commit tx we should be able to transition") |
||||
|
} |
||||
|
|
||||
|
insert_new_cfd_state_by_order_id(cfd.order.id, &cfd.state, conn, update_sender).await?; |
||||
|
tracing::info!("Commit transaction published on chain: {}", txid); |
||||
|
|
||||
|
Ok(()) |
||||
|
} |
||||
|
|
||||
|
pub async fn handle_oracle_attestation( |
||||
|
attestation: oracle::Attestation, |
||||
|
conn: &mut PoolConnection<Sqlite>, |
||||
|
wallet: &Wallet, |
||||
|
update_sender: &watch::Sender<Vec<Cfd>>, |
||||
|
) -> Result<()> { |
||||
|
tracing::debug!( |
||||
|
"Learnt latest oracle attestation for event: {}", |
||||
|
attestation.id |
||||
|
); |
||||
|
|
||||
|
let mut cfds = db::load_cfds_by_oracle_event_id(attestation.id, conn).await?; |
||||
|
|
||||
|
for (cfd, dlc) in cfds |
||||
|
.iter_mut() |
||||
|
.filter_map(|cfd| cfd.dlc().map(|dlc| (cfd, dlc))) |
||||
|
{ |
||||
|
if cfd |
||||
|
.handle(CfdStateChangeEvent::OracleAttestation(Attestation::new( |
||||
|
attestation.id, |
||||
|
attestation.price, |
||||
|
attestation.scalars.clone(), |
||||
|
dlc, |
||||
|
cfd.role(), |
||||
|
)?))? |
||||
|
.is_none() |
||||
|
{ |
||||
|
// if we don't transition to a new state after oracle attestation we ignore the cfd
|
||||
|
// this is for cases where we cannot handle the attestation which should be in a
|
||||
|
// final state
|
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
insert_new_cfd_state_by_order_id(cfd.order.id, &cfd.state, conn, update_sender).await?; |
||||
|
|
||||
|
if let Err(e) = try_cet_publication(cfd, conn, wallet, update_sender).await { |
||||
|
tracing::error!("Error when trying to publish CET: {:#}", e); |
||||
|
continue; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Ok(()) |
||||
|
} |
Loading…
Reference in new issue