diff --git a/.gitignore b/.gitignore index cc4d016..b7347ec 100755 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ ./taptrade-cli-demo/target taptrade-cli-demo/target taptrade-cli-demo/coordinator/target -taptrade-cli-demo/trader/target \ No newline at end of file +taptrade-cli-demo/coordinator/dbs/* +taptrade-cli-demo/trader/target diff --git a/taptrade-cli-demo/coordinator/src/communication/mod.rs b/taptrade-cli-demo/coordinator/src/communication/mod.rs index 1ed81ed..b6d76b2 100755 --- a/taptrade-cli-demo/coordinator/src/communication/mod.rs +++ b/taptrade-cli-demo/coordinator/src/communication/mod.rs @@ -1,6 +1,8 @@ pub mod api; +mod utils; use self::api::*; +use self::utils::*; use super::*; use axum::{ http::StatusCode, @@ -19,6 +21,9 @@ async fn receive_order( Extension(wallet): Extension, Json(order): Json, ) -> Result, AppError> { + if order.sanity_check().is_err() { + return Err(AppError(anyhow!("Invalid order request"))); + } let bond_requirements = BondRequirementResponse { bond_address: wallet.get_new_address().await?, locking_amount_sat: order.amount_satoshi * order.bond_ratio as u64 / 100, @@ -31,20 +36,37 @@ async fn receive_order( Ok(Json(bond_requirements)) } +// BondSubmissionRequest { +// pub robohash_hex: String, +// pub signed_bond_hex: String, // signed bond transaction, hex encoded +// pub payout_address: String, +// pub musig_pub_nonce_hex: String, +// pub musig_pubkey_hex: String, async fn submit_maker_bond( Extension(database): Extension, Extension(wallet): Extension, Json(payload): Json, ) -> Result, AppError> { - // Process the payload + let bond_requirements = database.fetch_maker_request(&payload.robohash_hex).await?; + + // validate bond (check amounts, valid inputs, correct addresses, valid signature, feerate) + wallet + .validate_bond_tx_hex(&payload.signed_bond_hex) + .await?; + + // insert bond into sql database + + // begin monitoring bond + + // move trade to orderbook + // For now, we'll just return a dummy success response let response = OrderActivatedResponse { bond_locked_until_timestamp: 0 as u128, order_id_hex: "Bond submitted successfully".to_string(), }; - // Create the JSON response - Json(response) + Ok(Json(response)) } pub async fn api_server(database: CoordinatorDB, wallet: CoordinatorWallet) -> Result<()> { diff --git a/taptrade-cli-demo/coordinator/src/communication/utils.rs b/taptrade-cli-demo/coordinator/src/communication/utils.rs new file mode 100644 index 0000000..cf7eff9 --- /dev/null +++ b/taptrade-cli-demo/coordinator/src/communication/utils.rs @@ -0,0 +1,31 @@ +use anyhow::Context; + +use super::*; + +impl OrderRequest { + pub fn sanity_check(&self) -> Result<()> { + // Get the current time + let now = SystemTime::now(); + // Convert the current time to a UNIX timestamp + let unix_timestamp = now + .duration_since(UNIX_EPOCH) + .context("Time went backwards")? + .as_secs(); + if self.amount_satoshi < 10000 { + return Err(anyhow!("Amount too low")); + } + if self.amount_satoshi > 20000000 { + return Err(anyhow!("Amount too high")); + } + if self.bond_ratio < 2 || self.bond_ratio > 50 { + return Err(anyhow!("Bond ratio out of bounds")); + } + if self.offer_duration_ts < unix_timestamp + 10800 { + return Err(anyhow!("Offer duration too short")); + } + if self.offer_duration_ts > unix_timestamp + 604800 { + return Err(anyhow!("Offer duration too long")); + } + Ok(()) + } +} diff --git a/taptrade-cli-demo/coordinator/src/coordinator/verify_bond.rs b/taptrade-cli-demo/coordinator/src/coordinator/verify_bond.rs index e78619e..eaf6370 100644 --- a/taptrade-cli-demo/coordinator/src/coordinator/verify_bond.rs +++ b/taptrade-cli-demo/coordinator/src/coordinator/verify_bond.rs @@ -16,7 +16,7 @@ pub fn verify_and_respond( wallet: &Wallet, ) -> Result { // Deserialize the signed bond hex - let tx: Transaction = deserialize(hex::decode(bond_submission.signed_bond_hex)?.as_slice())?; + let tx: Transaction = deserialize(&hex::decode(&bond_submission.signed_bond_hex)?)?; // Verify the transaction (this example assumes you've implemented your own verification logic) let is_valid = verify_psbt(&tx, &wallet, &bond_submission)?; diff --git a/taptrade-cli-demo/coordinator/src/database/mod.rs b/taptrade-cli-demo/coordinator/src/database/mod.rs index 62c4958..b2b25d8 100644 --- a/taptrade-cli-demo/coordinator/src/database/mod.rs +++ b/taptrade-cli-demo/coordinator/src/database/mod.rs @@ -1,7 +1,7 @@ use anyhow::Context; use super::*; -use sqlx::{sqlite::SqlitePoolOptions, Pool, Sqlite}; +use sqlx::{sqlite::SqlitePoolOptions, Pool, Row, Sqlite}; #[derive(Clone, Debug)] pub struct CoordinatorDB { @@ -70,4 +70,18 @@ impl CoordinatorDB { Ok(()) } + + pub async fn fetch_maker_request(&self, robohash: &String) -> Result { + let maker_request = sqlx::query( + "SELECT bond_address, bond_amount_sat FROM maker_requests WHERE robohash = ?", + ) + .bind(hex::decode(robohash)?) + .fetch_one(&*self.db_pool) + .await?; + + Ok(BondRequirementResponse { + bond_address: maker_request.try_get("bond_address")?, + locking_amount_sat: maker_request.try_get::("bond_amount_sat")? as u64, + }) + } } diff --git a/taptrade-cli-demo/coordinator/src/main.rs b/taptrade-cli-demo/coordinator/src/main.rs index 70e36c3..b6f5e17 100755 --- a/taptrade-cli-demo/coordinator/src/main.rs +++ b/taptrade-cli-demo/coordinator/src/main.rs @@ -1,5 +1,5 @@ mod communication; -// mod coordinator; +mod coordinator; mod database; mod wallet; @@ -7,6 +7,7 @@ use anyhow::{anyhow, Result}; use communication::{api::*, api_server}; use database::CoordinatorDB; use dotenv::dotenv; +use std::time::{SystemTime, UNIX_EPOCH}; use std::{env, sync::Arc}; use tokio::sync::Mutex; use wallet::CoordinatorWallet; diff --git a/taptrade-cli-demo/coordinator/src/wallet/mod.rs b/taptrade-cli-demo/coordinator/src/wallet/mod.rs index 877326a..a65d466 100644 --- a/taptrade-cli-demo/coordinator/src/wallet/mod.rs +++ b/taptrade-cli-demo/coordinator/src/wallet/mod.rs @@ -1,7 +1,7 @@ use super::*; use anyhow::Context; use bdk::{ - bitcoin::{self, bip32::ExtendedPrivKey}, + bitcoin::{self, bip32::ExtendedPrivKey, consensus::encode::deserialize, Transaction}, blockchain::ElectrumBlockchain, electrum_client::Client, sled::{self, Tree}, @@ -46,4 +46,11 @@ impl CoordinatorWallet { let address = wallet.get_address(bdk::wallet::AddressIndex::New)?; Ok(address.address.to_string()) } + + // validate bond (check amounts, valid inputs, correct addresses, valid signature, feerate) + pub async fn validate_bond_tx_hex(&self, bond: &String) -> Result { + let tx: Transaction = deserialize(&hex::decode(bond)?)?; + + Ok(true) + } }