add offer polling

This commit is contained in:
Felix
2024-06-13 15:18:34 +00:00
parent 401ee7149c
commit 871ab78062
4 changed files with 72 additions and 5 deletions

View File

@ -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,
}

View File

@ -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<Option<OfferTakenResponse>> {
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::<OfferTakenResponse>()?))
} else if res.status() == 204 {
Ok(None)
} else {
Err(anyhow!("Offer status polling returned: {}", res.status()))
}
}
}

View File

@ -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<PartiallySignedTransaction> {
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);
}
}
}
}

View File

@ -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(())
}