From 06dedd1b955849f1d0d579fa7283ec456d55f8f4 Mon Sep 17 00:00:00 2001 From: f321x Date: Mon, 8 Jul 2024 12:27:29 +0000 Subject: [PATCH] testing and fixing api communication [coordinator & maker] --- taptrade-cli-demo/coordinator/.env | 1 + .../coordinator/src/communication/mod.rs | 67 ++++++++++++------- .../coordinator/src/coordinator/mod.rs | 2 +- .../coordinator/src/database/db_tests.rs | 1 + taptrade-cli-demo/trader/maker.env | 2 +- .../trader/src/communication/api.rs | 2 +- .../trader/src/communication/mod.rs | 37 +++++++--- .../trader/src/trading/maker_utils.rs | 2 +- taptrade-cli-demo/trader/taker.env | 2 +- 9 files changed, 78 insertions(+), 38 deletions(-) diff --git a/taptrade-cli-demo/coordinator/.env b/taptrade-cli-demo/coordinator/.env index 470bf9e..fc882e3 100644 --- a/taptrade-cli-demo/coordinator/.env +++ b/taptrade-cli-demo/coordinator/.env @@ -4,3 +4,4 @@ DATABASE_PATH="./dbs/trades.db" # path to the coordinator sqlite database stori BDK_DB_PATH="./dbs/bdk-wallet" # Path to the BDK Sled database (no .db postfix) WALLET_XPRV="tprv8ZgxMBicQKsPdHuCSjhQuSZP1h6ZTeiRqREYS5guGPdtL7D1uNLpnJmb2oJep99Esq1NbNZKVJBNnD2ZhuXSK7G5eFmmcx73gsoa65e2U32" PUNISHMENT_ENABLED=1 # enable punishment for misbehaving traders +PORT=9999 # port for the coordinator to listen on diff --git a/taptrade-cli-demo/coordinator/src/communication/mod.rs b/taptrade-cli-demo/coordinator/src/communication/mod.rs index c1d5d0a..003d715 100755 --- a/taptrade-cli-demo/coordinator/src/communication/mod.rs +++ b/taptrade-cli-demo/coordinator/src/communication/mod.rs @@ -5,10 +5,11 @@ use self::api::*; use self::utils::*; use super::*; use crate::wallet::*; +use anyhow::Context; use axum::{ http::StatusCode, response::{IntoResponse, Response}, - routing::post, + routing::{get, post}, Extension, Json, Router, }; use rand::Rng; @@ -21,10 +22,11 @@ use tokio::net::TcpListener; // /// Handler function to process the received data async fn receive_order( - Extension(database): Extension, - Extension(wallet): Extension, + Extension(database): Extension>, + Extension(wallet): Extension>, Json(order): Json, ) -> Result, AppError> { + dbg!(&order); if order.sanity_check().is_err() { return Err(AppError(anyhow!("Invalid order request"))); } @@ -42,10 +44,11 @@ async fn receive_order( /// receives the maker bond, verifies it and moves to offer to the active table (orderbook) async fn submit_maker_bond( - Extension(database): Extension, - Extension(wallet): Extension, + Extension(database): Extension>, + Extension(wallet): Extension>, Json(payload): Json, ) -> Result { + println!("\n\nReceived maker bond: {:?}", payload); let bond_requirements = if let Ok(requirements) = database .fetch_bond_requirements(&payload.robohash_hex) .await @@ -65,13 +68,24 @@ async fn submit_maker_bond( return Ok(StatusCode::NOT_ACCEPTABLE.into_response()); } } + println!("\nBond validation successful"); let offer_id_hex: String = generate_random_order_id(16); // 16 bytes random offer id, maybe a different system makes more sense later on? (uuid or increasing counter...) // create address for taker bond - let new_taker_bond_address = wallet.get_new_address().await?; + let new_taker_bond_address = wallet.get_new_address().await.context(format!( + "Error generating taker bond address for offer id: {}", + offer_id_hex + ))?; // insert bond into sql database and move offer to different table - let bond_locked_until_timestamp = database + let bond_locked_until_timestamp = match database .move_offer_to_active(&payload, &offer_id_hex, new_taker_bond_address) - .await?; + .await + { + Ok(timestamp) => timestamp, + Err(e) => { + dbg!("Error in validate_bond_tx_hex: {}", e); + return Ok(StatusCode::INTERNAL_SERVER_ERROR.into_response()); + } + }; // Create the JSON response Ok(Json(OrderActivatedResponse { @@ -83,7 +97,7 @@ async fn submit_maker_bond( /// returns available offers from the active table (orderbook) async fn fetch_available_offers( - Extension(database): Extension, + Extension(database): Extension>, Json(payload): Json, ) -> Result, AppError> { let offers: Option> = database.fetch_suitable_offers(&payload).await?; @@ -94,8 +108,8 @@ async fn fetch_available_offers( /// receives the taker bond for a given offer, verifies it, creates escrow transaction psbt /// and moves the offer to the taken table. Will return the trade contract psbt for the taker to sign. async fn submit_taker_bond( - Extension(database): Extension, - Extension(wallet): Extension, + Extension(database): Extension>, + Extension(wallet): Extension>, Json(payload): Json, ) -> Result { let bond_requirements = database @@ -133,7 +147,7 @@ async fn submit_taker_bond( /// gets polled by the maker and returns the escrow psbt in case the offer has been taken async fn request_offer_status_maker( - Extension(database): Extension, + Extension(database): Extension>, Json(payload): Json, ) -> Result { let offer = database @@ -153,8 +167,8 @@ async fn request_offer_status_maker( /// coordinator then has to check if their signatures are valid and everything else is according to the agreed upon contract. /// Once the coordinator has received both partitial signed PSBTs he can assemble them together to a transaction and publish it to the bitcoin network. async fn submit_escrow_psbt( - Extension(database): Extension, - Extension(wallet): Extension, + Extension(database): Extension>, + Extension(wallet): Extension>, Json(payload): Json, ) -> Result { panic!("implement") @@ -166,16 +180,16 @@ async fn submit_escrow_psbt( /// In theory this polling mechanism could also be replaced by the traders scanning the blockchain themself so they could also see once the tx is confirmed. /// We have to see what makes more sense later, but maybe this would be more elegant. TBD. async fn poll_escrow_confirmation( - Extension(database): Extension, - Extension(wallet): Extension, + Extension(database): Extension>, + Extension(wallet): Extension>, Json(payload): Json, ) -> Result { panic!("implement") } async fn submit_obligation_confirmation( - Extension(database): Extension, - Extension(wallet): Extension, + Extension(database): Extension>, + Extension(wallet): Extension>, Json(payload): Json, ) -> Result { panic!("implement") @@ -186,18 +200,23 @@ async fn submit_obligation_confirmation( /// If one of them is not happy and initiating escrow (e.g. claiming they didn't receive the fiat) then this /// endpoint can return 201 and the escrow mediation logic will get executed (tbd). async fn poll_final_payout( - Extension(database): Extension, - Extension(wallet): Extension, + Extension(database): Extension>, + Extension(wallet): Extension>, Json(payload): Json, ) -> Result { panic!("implement") } +async fn test_api() -> &'static str { + "Hello, World!" +} + pub async fn api_server(coordinator: Arc) -> Result<()> { let database = Arc::clone(&coordinator.coordinator_db); let wallet = Arc::clone(&coordinator.coordinator_wallet); let app = Router::new() + .route("/test", get(test_api)) .route("/create-offer", post(receive_order)) .route("/submit-maker-bond", post(submit_maker_bond)) .route("/fetch-available-offers", post(fetch_available_offers)) @@ -214,11 +233,13 @@ pub async fn api_server(coordinator: Arc) -> Result<()> { .layer(Extension(wallet)); // add other routes here - // Run the server on localhost:9999 - let addr = SocketAddr::from(([127, 0, 0, 1], 9999)); + let port: u16 = env::var("PORT") + .unwrap_or_else(|_| "9999".to_string()) + .parse()?; + println!("Listening on {}", port); + let addr = SocketAddr::from(([127, 0, 0, 1], port)); let tcp = TcpListener::bind(&addr).await.unwrap(); axum::serve(tcp, app).await?; - println!("Listening on {}", addr); Ok(()) } diff --git a/taptrade-cli-demo/coordinator/src/coordinator/mod.rs b/taptrade-cli-demo/coordinator/src/coordinator/mod.rs index 3398fe2..ab90781 100755 --- a/taptrade-cli-demo/coordinator/src/coordinator/mod.rs +++ b/taptrade-cli-demo/coordinator/src/coordinator/mod.rs @@ -1,4 +1,4 @@ pub mod monitoring; -pub mod create_taproot; +// pub mod create_taproot; // commented out for testing use super::*; diff --git a/taptrade-cli-demo/coordinator/src/database/db_tests.rs b/taptrade-cli-demo/coordinator/src/database/db_tests.rs index ef7ed74..da88a12 100644 --- a/taptrade-cli-demo/coordinator/src/database/db_tests.rs +++ b/taptrade-cli-demo/coordinator/src/database/db_tests.rs @@ -1,6 +1,7 @@ use super::*; #[cfg(test)] use anyhow::Ok; + async fn create_coordinator() -> Result { // Set up the in-memory database env::set_var("DATABASE_PATH", ":memory:"); diff --git a/taptrade-cli-demo/trader/maker.env b/taptrade-cli-demo/trader/maker.env index 46f9141..4979e18 100644 --- a/taptrade-cli-demo/trader/maker.env +++ b/taptrade-cli-demo/trader/maker.env @@ -1,5 +1,5 @@ ELECTRUM_ENDPOINT="ssl://mempool.space:40002" # testnet 4 electrum server -COORDINATOR_ENDPOINT="http://127.0.0.1:3000" +COORDINATOR_ENDPOINT="http://127.0.0.1:9999" ROBOHASH_HEX="26ee3dee4815655d223c3505162fd4610294a9542f89bb3d3e9748f534ac10ae" # sha256 of "robot21" TRADE_TYPE="buy" PAYOUT_ADDRESS="tb1p45daj2eaza6drcd85c3wvn0zrpqxuduk3rzcmla4eu7a02cep9kqjzkc64" diff --git a/taptrade-cli-demo/trader/src/communication/api.rs b/taptrade-cli-demo/trader/src/communication/api.rs index c2434cc..17992bd 100644 --- a/taptrade-cli-demo/trader/src/communication/api.rs +++ b/taptrade-cli-demo/trader/src/communication/api.rs @@ -33,7 +33,7 @@ pub struct BondSubmissionRequest { // Response after step2 if offer creation was successful and the offer is now online in the orderbook #[derive(Debug, Deserialize)] pub struct OrderActivatedResponse { - pub order_id_hex: String, + pub offer_id_hex: String, pub bond_locked_until_timestamp: u64, // unix timestamp. Do not touch bond till then unless offer gets taken. } diff --git a/taptrade-cli-demo/trader/src/communication/mod.rs b/taptrade-cli-demo/trader/src/communication/mod.rs index 50b14a0..88728b9 100644 --- a/taptrade-cli-demo/trader/src/communication/mod.rs +++ b/taptrade-cli-demo/trader/src/communication/mod.rs @@ -41,15 +41,20 @@ impl BondRequirementResponse { pub fn fetch(trader_setup: &TraderSettings) -> Result { let client = reqwest::blocking::Client::new(); + let endpoint = format!("{}{}", trader_setup.coordinator_endpoint, "/create-offer"); let res = client - .post(format!( - "{}{}", - trader_setup.coordinator_endpoint, "/create-offer" - )) + .post(endpoint) .json(&Self::_format_request(trader_setup)) - .send()? - .json::()?; - Ok(res) + .send()?; + let status_code = res.status(); + match res.json::() { + Ok(response) => Ok(response), + Err(e) => Err(anyhow!( + "Error fetching bond requirements: {}. Status code: {}", + e, + status_code + )), + } } } @@ -89,9 +94,21 @@ impl BondSubmissionRequest { trader_setup.coordinator_endpoint, "/submit-maker-bond" )) .json(&request) - .send()? - .json::()?; - Ok(res) + .send(); + match res { + Ok(res) => { + let status_code = res.status(); + match res.json::() { + Ok(response) => Ok(response), + Err(e) => Err(anyhow!( + "Error submitting maker bond: {}. Status code: {}", + e, + status_code + )), + } + } + Err(e) => Err(anyhow!("Error submitting maker bond: {}", e)), + } } } diff --git a/taptrade-cli-demo/trader/src/trading/maker_utils.rs b/taptrade-cli-demo/trader/src/trading/maker_utils.rs index 31a755d..41dba3e 100644 --- a/taptrade-cli-demo/trader/src/trading/maker_utils.rs +++ b/taptrade-cli-demo/trader/src/trading/maker_utils.rs @@ -24,7 +24,7 @@ impl ActiveOffer { maker_config, )?; Ok(ActiveOffer { - offer_id_hex: submission_result.order_id_hex, + offer_id_hex: submission_result.offer_id_hex, used_musig_config: musig_data, used_bond: bond, expected_payout_address: payout_address, diff --git a/taptrade-cli-demo/trader/taker.env b/taptrade-cli-demo/trader/taker.env index d15ed00..2c3f756 100644 --- a/taptrade-cli-demo/trader/taker.env +++ b/taptrade-cli-demo/trader/taker.env @@ -1,5 +1,5 @@ ELECTRUM_ENDPOINT="ssl://mempool.space:40002" # testnet 4 electrum server -COORDINATOR_ENDPOINT="http://127.0.0.1:3000" +COORDINATOR_ENDPOINT="http://127.0.0.1:9999" ROBOHASH_HEX="169b6049cf865eba7d01e1ad26975f1d5ff29d570297ff18d40a53c8281dff5d" # sha256 of "robot22" TRADE_TYPE="sell" PAYOUT_ADDRESS="tb1p37qg73t5y0l4un3q5dknzl8fgfhemghaap67wns45pzgrw2tasrq6kesxm"