diff --git a/taptrade-cli-demo/trader/src/communication/api.rs b/taptrade-cli-demo/trader/src/communication/api.rs index 3ad90da..d89ffca 100644 --- a/taptrade-cli-demo/trader/src/communication/api.rs +++ b/taptrade-cli-demo/trader/src/communication/api.rs @@ -15,7 +15,7 @@ pub struct OrderRequest { // direct Json answer to step 1 (same request) #[derive(Debug, Deserialize)] pub struct OfferCreationResponse { - pub bond_address: String, // address the bond has to be locked to + pub bond_address: String, // address the bond ha/workspaces/taptrade-core/taptrade-cli-demo/trader/src/communications to be locked to pub locking_amount_sat: u64, // min amount of the bond output in sat } @@ -36,3 +36,14 @@ pub struct OrderActivatedResponse { pub order_id_hex: String, pub bond_locked_until_timestamp: u128, // unix timestamp. Do not touch bond till then unless offer gets taken. } + +#[derive(Debug, Serialize)] +pub struct OfferTakenRequest { + pub robohash_hex: String, + pub order_id_hex: String, +} + +#[derive(Debug, Deserialize)] +pub struct OfferTakenResponse { + pub trade_psbt_hex_to_sign: String, +} diff --git a/taptrade-cli-demo/trader/src/communication/mod.rs b/taptrade-cli-demo/trader/src/communication/mod.rs index 627f00e..6b58920 100644 --- a/taptrade-cli-demo/trader/src/communication/mod.rs +++ b/taptrade-cli-demo/trader/src/communication/mod.rs @@ -2,10 +2,14 @@ pub mod api; use crate::{ cli::{OfferType, TraderSettings}, + trading::maker_utils::ActiveOffer, wallet::{bond::Bond, musig2::MuSigData}, }; -use anyhow::Result; -use api::{BondSubmissionRequest, OfferCreationResponse, OrderActivatedResponse, OrderRequest}; +use anyhow::{anyhow, Result}; +use api::{ + BondSubmissionRequest, OfferCreationResponse, OfferTakenRequest, OfferTakenResponse, + OrderActivatedResponse, OrderRequest, +}; use bdk::bitcoin::consensus::encode::serialize_hex; use bdk::{ bitcoin::{consensus::Encodable, psbt::PartiallySignedTransaction}, @@ -81,3 +85,33 @@ impl BondSubmissionRequest { Ok(res) } } + +impl OfferTakenResponse { + // posts offer to coordinator to check if it has been taken, if not taken + // returns status code 204 No Content + pub fn check( + offer: &ActiveOffer, + trader_setup: &TraderSettings, + ) -> Result> { + let request = OfferTakenRequest { + // maybe can be made a bit more efficient (less clone) + robohash_hex: trader_setup.robosats_robohash_hex.clone(), + order_id_hex: offer.order_id_hex.clone(), + }; + let client = reqwest::blocking::Client::new(); + let res = client + .post(format!( + "{}{}", + trader_setup.coordinator_endpoint, "/request-trade-status" + )) + .json(&request) + .send()?; + if res.status() == 200 { + Ok(Some(res.json::()?)) + } else if res.status() == 204 { + Ok(None) + } else { + Err(anyhow!("Offer status polling returned: {}", res.status())) + } + } +} diff --git a/taptrade-cli-demo/trader/src/trading/maker_utils.rs b/taptrade-cli-demo/trader/src/trading/maker_utils.rs index 11d92d4..6b43737 100644 --- a/taptrade-cli-demo/trader/src/trading/maker_utils.rs +++ b/taptrade-cli-demo/trader/src/trading/maker_utils.rs @@ -1,14 +1,18 @@ use crate::cli::TraderSettings; -use crate::communication::api::{BondSubmissionRequest, OfferCreationResponse}; +use crate::communication::api::{ + BondSubmissionRequest, OfferCreationResponse, OfferTakenRequest, OfferTakenResponse, +}; use crate::wallet::{ bond::Bond, musig2::{MuSigData, MusigNonce}, TradingWallet, }; use anyhow::Result; +use bdk::bitcoin::amount::serde::as_btc::deserialize; use bdk::{ bitcoin::psbt::PartiallySignedTransaction, database::MemoryDatabase, wallet::AddressInfo, }; +use std::{thread, time::Duration}; #[derive(Debug)] pub struct ActiveOffer { @@ -52,4 +56,20 @@ impl ActiveOffer { expected_payout_address: payout_address, }) } + + // polling until offer is taken, in production a more efficient way would make sense + // returns the PSBT of the escrow trade transaction we have to validate, sign and return + pub fn wait_until_taken( + self, + trader_config: &TraderSettings, + ) -> Result { + loop { + thread::sleep(Duration::from_secs(10)); + if let Some(offer_taken_response) = OfferTakenResponse::check(&self, trader_config)? { + let psbt_bytes = hex::decode(offer_taken_response.trade_psbt_hex_to_sign)?; + let psbt = PartiallySignedTransaction::deserialize(&psbt_bytes)?; + return Ok(psbt); + } + } + } } diff --git a/taptrade-cli-demo/trader/src/trading/mod.rs b/taptrade-cli-demo/trader/src/trading/mod.rs index 38d92f0..7b928df 100644 --- a/taptrade-cli-demo/trader/src/trading/mod.rs +++ b/taptrade-cli-demo/trader/src/trading/mod.rs @@ -1,4 +1,4 @@ -mod maker_utils; +pub mod maker_utils; use self::maker_utils::ActiveOffer; use crate::cli::TraderSettings; @@ -10,6 +10,8 @@ pub fn run_maker(maker_config: &TraderSettings) -> Result<()> { let offer = ActiveOffer::create(&wallet, maker_config)?; dbg!(&offer); + let trade_psbt = offer.wait_until_taken(maker_config)?; + Ok(()) }