mirror of
https://github.com/RoboSats/taptrade-core.git
synced 2025-08-01 23:51:40 +00:00
add sanity checks to coordinator endpoint
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
./taptrade-cli-demo/target
|
||||
taptrade-cli-demo/target
|
||||
taptrade-cli-demo/coordinator/target
|
||||
taptrade-cli-demo/trader/target
|
||||
taptrade-cli-demo/coordinator/dbs/*
|
||||
taptrade-cli-demo/trader/target
|
||||
|
@ -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<CoordinatorWallet>,
|
||||
Json(order): Json<OrderRequest>,
|
||||
) -> Result<Json<BondRequirementResponse>, 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<CoordinatorDB>,
|
||||
Extension(wallet): Extension<CoordinatorWallet>,
|
||||
Json(payload): Json<BondSubmissionRequest>,
|
||||
) -> Result<Json<OrderActivatedResponse>, 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<()> {
|
||||
|
31
taptrade-cli-demo/coordinator/src/communication/utils.rs
Normal file
31
taptrade-cli-demo/coordinator/src/communication/utils.rs
Normal file
@ -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(())
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ pub fn verify_and_respond(
|
||||
wallet: &Wallet<MemoryDatabase>,
|
||||
) -> Result<OrderActivatedResponse> {
|
||||
// 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)?;
|
||||
|
@ -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<BondRequirementResponse> {
|
||||
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::<i64, _>("bond_amount_sat")? as u64,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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<bool> {
|
||||
let tx: Transaction = deserialize(&hex::decode(bond)?)?;
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user