diff --git a/taptrade-cli-demo/coordinator/src/communication/api.rs b/taptrade-cli-demo/coordinator/src/communication/api.rs index 891bcff..902350b 100644 --- a/taptrade-cli-demo/coordinator/src/communication/api.rs +++ b/taptrade-cli-demo/coordinator/src/communication/api.rs @@ -71,7 +71,7 @@ pub struct OfferPsbtRequest { #[derive(Debug, Serialize, Deserialize)] pub struct OfferTakenRequest { pub robohash_hex: String, - pub order_id_hex: String, + pub offer_id_hex: String, } #[derive(Debug, Serialize, Deserialize)] @@ -80,3 +80,9 @@ pub struct PsbtSubmissionRequest { pub offer_id_hex: String, pub robohash_hex: String, } + +#[derive(Debug, Serialize, Deserialize)] +pub struct TradeObligationsUnsatisfied { + pub robohash_hex: String, + pub offer_id_hex: String, +} diff --git a/taptrade-cli-demo/coordinator/src/communication/mod.rs b/taptrade-cli-demo/coordinator/src/communication/mod.rs index 98dae77..53e1398 100755 --- a/taptrade-cli-demo/coordinator/src/communication/mod.rs +++ b/taptrade-cli-demo/coordinator/src/communication/mod.rs @@ -226,7 +226,7 @@ async fn submit_obligation_confirmation( return Ok(StatusCode::NOT_FOUND.into_response()); } database - .set_trader_happy_true(&payload.order_id_hex, &payload.robohash_hex) + .set_trader_happy_field(&payload.order_id_hex, &payload.robohash_hex, true) .await?; Ok(StatusCode::OK.into_response()) } @@ -237,10 +237,21 @@ async fn submit_obligation_confirmation( // before timeout ends async fn request_escrow( Extension(database): Extension>, - Extension(wallet): Extension>>, - Json(payload): Json, + Json(payload): Json, ) -> Result { - panic!("implement") + if !database + .is_valid_robohash_in_table(&payload.robohash_hex, &payload.offer_id_hex) + .await? || !database + .fetch_escrow_tx_confirmation_status(&payload.offer_id_hex) + .await? + { + return Ok(StatusCode::NOT_FOUND.into_response()); + } + database + .set_trader_happy_field(&payload.offer_id_hex, &payload.robohash_hex, false) + .await?; + + Ok(StatusCode::OK.into_response()) } /// Is supposed to get polled by the traders once they clicked on "i sent the fiat" or "i received the fiat". @@ -252,6 +263,22 @@ async fn poll_final_payout( Extension(wallet): Extension>>, Json(payload): Json, ) -> Result { + if !database + .is_valid_robohash_in_table(&payload.robohash_hex, &payload.offer_id_hex) + .await? || !database + .fetch_escrow_tx_confirmation_status(&payload.offer_id_hex) + .await? + { + return Ok(StatusCode::NOT_FOUND.into_response()); + } + // check if both traders are happy + // assemble payout psbt and return to them for signing + + // if one of them is not happy + // open escrow cli on coordinator to decide who will win (chat/dispute is out of scope for this demo) + // once decided who will win assemble the correct payout psbt and return it to the according trader + // the other trader gets a error code/ end of trade code + panic!("implement") } diff --git a/taptrade-cli-demo/coordinator/src/database/mod.rs b/taptrade-cli-demo/coordinator/src/database/mod.rs index 5770353..52638d2 100644 --- a/taptrade-cli-demo/coordinator/src/database/mod.rs +++ b/taptrade-cli-demo/coordinator/src/database/mod.rs @@ -125,7 +125,7 @@ impl CoordinatorDB { escrow_psbt_txid TEXT, escrow_psbt_is_confirmed INTEGER, maker_happy INTEGER, - taker_happy INTEGER + taker_happy INTEGER, )", // escrow_psbt_is_confirmed will be set 1 once the escrow psbt is confirmed onchain ) .execute(&db_pool) @@ -578,7 +578,12 @@ impl CoordinatorDB { Ok(status.get::("escrow_psbt_is_confirmed") == 1) } - pub async fn set_trader_happy_true(&self, offer_id: &String, robohash: &String) -> Result<()> { + pub async fn set_trader_happy_field( + &self, + offer_id: &String, + robohash: &String, + is_happy: bool, + ) -> Result<()> { let robohash_bytes = hex::decode(robohash)?; // First, check if the robohash matches the maker or taker @@ -597,12 +602,13 @@ impl CoordinatorDB { } let query = if is_maker { - "UPDATE taken_offers SET maker_happy = 1 WHERE offer_id = ?" + "UPDATE taken_offers SET maker_happy = ? WHERE offer_id = ?" } else { - "UPDATE taken_offers SET taker_happy = 1 WHERE offer_id = ?" + "UPDATE taken_offers SET taker_happy = ? WHERE offer_id = ?" }; sqlx::query(query) + .bind(bool_to_sql_int(is_happy)) .bind(offer_id) .execute(&*self.db_pool) .await?; diff --git a/taptrade-cli-demo/trader/src/communication/api.rs b/taptrade-cli-demo/trader/src/communication/api.rs index 17992bd..f6ce51f 100644 --- a/taptrade-cli-demo/trader/src/communication/api.rs +++ b/taptrade-cli-demo/trader/src/communication/api.rs @@ -107,3 +107,9 @@ pub struct TradeObligationsSatisfied { pub struct PayoutPsbtResponse { pub payout_psbt_hex: String, } + +#[derive(Debug, Serialize)] +pub struct TradeObligationsUnsatisfied { + pub robohash_hex: String, + pub offer_id_hex: String, +} diff --git a/taptrade-cli-demo/trader/src/communication/mod.rs b/taptrade-cli-demo/trader/src/communication/mod.rs index 8cab918..90ab1c2 100644 --- a/taptrade-cli-demo/trader/src/communication/mod.rs +++ b/taptrade-cli-demo/trader/src/communication/mod.rs @@ -278,3 +278,28 @@ impl IsOfferReadyRequest { Ok(Some(final_psbt)) } } + +impl TradeObligationsUnsatisfied { + pub fn request_escrow(offer_id_hex: &String, trader_config: &TraderSettings) -> Result<()> { + let request = TradeObligationsUnsatisfied { + robohash_hex: trader_config.robosats_robohash_hex.clone(), + offer_id_hex: offer_id_hex.clone(), + }; + + let client = reqwest::blocking::Client::new(); + let res = client + .post(format!( + "{}{}", + trader_config.coordinator_endpoint, "/request-escrow" + )) + .json(&request) + .send()?; + if res.status() != 200 { + return Err(anyhow!( + "Submitting trade obligations unsatisfied failed. Status: {}", + res.status() + )); + } + Ok(()) + } +} diff --git a/taptrade-cli-demo/trader/src/trading/mod.rs b/taptrade-cli-demo/trader/src/trading/mod.rs index dd7319b..3345e4f 100644 --- a/taptrade-cli-demo/trader/src/trading/mod.rs +++ b/taptrade-cli-demo/trader/src/trading/mod.rs @@ -9,7 +9,7 @@ use crate::{ communication::api::{ BondRequirementResponse, BondSubmissionRequest, IsOfferReadyRequest, OfferTakenRequest, OfferTakenResponse, PsbtSubmissionRequest, PublicOffer, PublicOffers, - TradeObligationsSatisfied, + TradeObligationsSatisfied, TradeObligationsUnsatisfied, }, wallet::{ bond::Bond, @@ -51,7 +51,8 @@ pub fn run_maker(maker_config: &TraderSettings) -> Result<()> { let payout_keyspend_psbt = IsOfferReadyRequest::poll_payout(maker_config, &offer)?; } else { error!("Trade failed. Initiating escrow mode."); - panic!("Escrow to be implemented!"); + TradeObligationsUnsatisfied::request_escrow(&offer.offer_id_hex, maker_config)?; + let escrow_payout_script_psbt = IsOfferReadyRequest::poll_payout(maker_config, &offer)?; } Ok(()) }