mirror of
https://github.com/RoboSats/taptrade-core.git
synced 2025-07-23 11:13:17 +00:00
complete more api endpoints
This commit is contained in:
@ -160,7 +160,7 @@ async fn request_offer_status_maker(
|
||||
Json(payload): Json<OfferTakenRequest>,
|
||||
) -> Result<Response, AppError> {
|
||||
let offer = database
|
||||
.fetch_taken_offer_maker(&payload.order_id_hex, &payload.robohash_hex)
|
||||
.fetch_taken_offer_maker(&payload.offer_id_hex, &payload.robohash_hex)
|
||||
.await?;
|
||||
match offer {
|
||||
Some(offer) => Ok(Json(OfferTakenResponse {
|
||||
@ -196,13 +196,13 @@ async fn poll_escrow_confirmation(
|
||||
Json(payload): Json<OfferTakenRequest>,
|
||||
) -> Result<Response, AppError> {
|
||||
if !database
|
||||
.is_valid_robohash_in_table(&payload.robohash_hex, &payload.order_id_hex)
|
||||
.is_valid_robohash_in_table(&payload.robohash_hex, &payload.offer_id_hex)
|
||||
.await?
|
||||
{
|
||||
return Ok(StatusCode::NOT_FOUND.into_response());
|
||||
}
|
||||
if database
|
||||
.fetch_escrow_tx_confirmation_status(&payload.order_id_hex)
|
||||
.fetch_escrow_tx_confirmation_status(&payload.offer_id_hex)
|
||||
.await?
|
||||
{
|
||||
return Ok(StatusCode::OK.into_response());
|
||||
@ -213,20 +213,19 @@ async fn poll_escrow_confirmation(
|
||||
|
||||
async fn submit_obligation_confirmation(
|
||||
Extension(database): Extension<Arc<CoordinatorDB>>,
|
||||
Extension(wallet): Extension<Arc<CoordinatorWallet<sled::Tree>>>,
|
||||
Json(payload): Json<OfferTakenRequest>,
|
||||
) -> Result<Response, AppError> {
|
||||
// sanity check if offer is in table and if the escrow tx is confirmed
|
||||
if !database
|
||||
.is_valid_robohash_in_table(&payload.robohash_hex, &payload.order_id_hex)
|
||||
.is_valid_robohash_in_table(&payload.robohash_hex, &payload.offer_id_hex)
|
||||
.await? || !database
|
||||
.fetch_escrow_tx_confirmation_status(&payload.order_id_hex)
|
||||
.fetch_escrow_tx_confirmation_status(&payload.offer_id_hex)
|
||||
.await?
|
||||
{
|
||||
return Ok(StatusCode::NOT_FOUND.into_response());
|
||||
}
|
||||
database
|
||||
.set_trader_happy_field(&payload.order_id_hex, &payload.robohash_hex, true)
|
||||
.set_trader_happy_field(&payload.offer_id_hex, &payload.robohash_hex, true)
|
||||
.await?;
|
||||
Ok(StatusCode::OK.into_response())
|
||||
}
|
||||
@ -271,15 +270,44 @@ async fn poll_final_payout(
|
||||
{
|
||||
return Ok(StatusCode::NOT_FOUND.into_response());
|
||||
}
|
||||
// check if both traders are happy
|
||||
// assemble payout psbt and return to them for signing
|
||||
|
||||
let trader_happiness = database
|
||||
.fetch_trader_happiness(&payload.offer_id_hex)
|
||||
.await?;
|
||||
if trader_happiness.maker_happy.is_some_and(|x| x == true)
|
||||
&& trader_happiness.taker_happy.is_some_and(|x| x == true)
|
||||
{
|
||||
panic!("Implement wallet.assemble_keyspend_payout_psbt()");
|
||||
// let payout_keyspend_psbt_hex = wallet
|
||||
// .assemble_keyspend_payout_psbt(&payload.offer_id_hex, &payload.robohash_hex)
|
||||
// .await
|
||||
// .context("Error assembling payout PSBT")?;
|
||||
// return Ok(String::from(payout_keyspend_psbt_hex).into_response());
|
||||
} else if (trader_happiness.maker_happy.is_none() || trader_happiness.taker_happy.is_none())
|
||||
&& !trader_happiness.escrow_ongoing
|
||||
{
|
||||
return Ok(StatusCode::ACCEPTED.into_response());
|
||||
}
|
||||
// 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")
|
||||
// escrow winner has to be set true with a cli input of the coordinator. This could be an api
|
||||
// endpoint for the admin UI frontend in the future
|
||||
if let Some(escrow_winner) = database.fetch_escrow_result(&payload.offer_id_hex).await? {
|
||||
if escrow_winner == payload.robohash_hex {
|
||||
panic!("Implement wallet.assemble_script_payout_psbt()");
|
||||
// let script_payout_psbt_hex = wallet
|
||||
// .assemble_script_payout_psbt(&payload.offer_id_hex, &payload.robohash_hex, is_maker_bool)
|
||||
// .await
|
||||
// .context("Error assembling payout PSBT")?;
|
||||
// return Ok(String::from(payout_keyspend_psbt_hex).into_response());
|
||||
} else {
|
||||
return Ok(StatusCode::GONE.into_response()); // this will be returned to the losing trader
|
||||
}
|
||||
} else {
|
||||
return Ok(StatusCode::PROCESSING.into_response()); // this will be returned if the coordinator hasn't decided yet
|
||||
}
|
||||
}
|
||||
|
||||
async fn test_api() -> &'static str {
|
||||
|
@ -40,6 +40,12 @@ struct AwaitingTakerOffer {
|
||||
musig_pubkey_hex_maker: String,
|
||||
}
|
||||
|
||||
pub struct TraderHappiness {
|
||||
pub maker_happy: Option<bool>,
|
||||
pub taker_happy: Option<bool>,
|
||||
pub escrow_ongoing: bool,
|
||||
}
|
||||
|
||||
fn bool_to_sql_int(flag: bool) -> Option<i64> {
|
||||
if flag {
|
||||
Some(1)
|
||||
@ -126,6 +132,8 @@ impl CoordinatorDB {
|
||||
escrow_psbt_is_confirmed INTEGER,
|
||||
maker_happy INTEGER,
|
||||
taker_happy INTEGER,
|
||||
escrow_ongoing INTEGER NOT NULL,
|
||||
escrow_winner_robohash TEXT
|
||||
)", // escrow_psbt_is_confirmed will be set 1 once the escrow psbt is confirmed onchain
|
||||
)
|
||||
.execute(&db_pool)
|
||||
@ -351,8 +359,8 @@ impl CoordinatorDB {
|
||||
"INSERT OR REPLACE INTO taken_offers (offer_id, robohash_maker, robohash_taker, is_buy_order, amount_sat,
|
||||
bond_ratio, offer_duration_ts, bond_address_maker, bond_address_taker, bond_amount_sat, bond_tx_hex_maker,
|
||||
bond_tx_hex_taker, payout_address_maker, payout_address_taker, musig_pub_nonce_hex_maker, musig_pubkey_hex_maker,
|
||||
musig_pub_nonce_hex_taker, musig_pubkey_hex_taker, escrow_psbt_hex_maker, escrow_psbt_hex_taker, escrow_psbt_txid, escrow_psbt_is_confirmed)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
musig_pub_nonce_hex_taker, musig_pubkey_hex_taker, escrow_psbt_hex_maker, escrow_psbt_hex_taker, escrow_psbt_txid, escrow_psbt_is_confirmed, escrow_ongoing)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
)
|
||||
.bind(public_offer.offer_id)
|
||||
.bind(public_offer.robohash_maker)
|
||||
@ -376,6 +384,7 @@ impl CoordinatorDB {
|
||||
.bind(trade_contract_psbt_taker.clone())
|
||||
.bind(trade_tx_txid)
|
||||
.bind(0)
|
||||
.bind(0)
|
||||
.execute(&*self.db_pool)
|
||||
.await?;
|
||||
|
||||
@ -613,6 +622,44 @@ impl CoordinatorDB {
|
||||
.execute(&*self.db_pool)
|
||||
.await?;
|
||||
|
||||
if !is_happy {
|
||||
sqlx::query("UPDATE taken_offers SET escrow_ongoing = 1 WHERE offer_id = ?")
|
||||
.bind(offer_id)
|
||||
.execute(&*self.db_pool)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn fetch_trader_happiness(&self, offer_id: &String) -> Result<TraderHappiness> {
|
||||
let row = sqlx::query(
|
||||
"SELECT maker_happy, taker_happy, escrow_ongoing FROM taken_offers WHERE offer_id = ?",
|
||||
)
|
||||
.bind(offer_id)
|
||||
.fetch_one(&*self.db_pool)
|
||||
.await?;
|
||||
|
||||
let maker_happy: Option<i64> = row.try_get::<Option<i64>, _>("maker_happy")?;
|
||||
let taker_happy: Option<i64> = row.try_get::<Option<i64>, _>("taker_happy")?;
|
||||
let escrow_ongoing: i64 = row.try_get::<i64, _>("escrow_ongoing")?;
|
||||
|
||||
Ok(TraderHappiness {
|
||||
maker_happy: maker_happy.map(|v| v != 0),
|
||||
taker_happy: taker_happy.map(|v| v != 0),
|
||||
escrow_ongoing: escrow_ongoing != 0,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn fetch_escrow_result(&self, offer_id: &String) -> Result<Option<String>> {
|
||||
let row = sqlx::query("SELECT escrow_winner_robohash FROM taken_offers WHERE offer_id = ?")
|
||||
.bind(offer_id)
|
||||
.fetch_one(&*self.db_pool)
|
||||
.await?;
|
||||
|
||||
let winner_robohash: Option<String> =
|
||||
row.try_get::<Option<String>, _>("escrow_winner_robohash")?;
|
||||
|
||||
Ok(winner_robohash)
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ use bdk::{
|
||||
wallet::AddressInfo,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{str::FromStr, thread::sleep, time::Duration};
|
||||
use std::{f32::consts::E, str::FromStr, thread::sleep, time::Duration};
|
||||
|
||||
impl BondRequirementResponse {
|
||||
fn _format_request(trader_setup: &TraderSettings) -> OrderRequest {
|
||||
@ -257,13 +257,20 @@ impl IsOfferReadyRequest {
|
||||
.send()?;
|
||||
if res.status() == 200 {
|
||||
// good case, psbt is returned
|
||||
debug!("Payout psbt received. Signing...");
|
||||
break;
|
||||
} else if res.status() == 204 {
|
||||
} else if res.status() == 202 {
|
||||
// still waiting, retry
|
||||
continue;
|
||||
} else if res.status() == 201 {
|
||||
} else if res.status() == 102 {
|
||||
// other party initiated escrow
|
||||
return Ok(None);
|
||||
debug!("Other party initiated escrow. Waiting for coordinator to finalize.");
|
||||
continue;
|
||||
} else if res.status() != 410 {
|
||||
return Err(anyhow!(
|
||||
"We lost the escrow, your bond is gone: {}",
|
||||
res.status()
|
||||
));
|
||||
} else {
|
||||
// unintended response
|
||||
return Err(anyhow!(
|
||||
|
Reference in New Issue
Block a user