Skip to content

Commit

Permalink
Range order fixes (#286)
Browse files Browse the repository at this point in the history
* mostro range order first release

* fix cargo.lock

* fix cargo.toml

* Only show fiat amount range in pending orders

* Reset order amount after child order creation

* Fix takebuy without amount

---------

Co-authored-by: Lucio Pinese <[email protected]>
  • Loading branch information
grunch and Lucio Pinese authored May 21, 2024
1 parent 0f79b5a commit fd3e8c4
Show file tree
Hide file tree
Showing 13 changed files with 206 additions and 42 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ uuid = { version = "1.8.0", features = [
"serde",
] }
reqwest = { version = "0.12.1", features = ["json"] }
mostro-core = { version = "0.5.8", features = ["sqlx"] }
mostro-core = { version = "0.5.13", features = ["sqlx"] }
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
config = "0.14.0"
clap = { version = "4.5.3", features = ["derive"] }
lnurl-rs = "0.5.0"
openssl = { version = "0.10", features = ["vendored"] }
openssl = { version = "0.10", features = ["vendored"] }
5 changes: 3 additions & 2 deletions src/app/add_invoice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,7 @@ pub async fn add_invoice_action(
Some(order.id),
Some(format!(
"You are not allowed to add an invoice because order Id {} status is {}",
order_status.to_string(),
order.id
order_status, order.id
)),
&buyer_pubkey,
)
Expand All @@ -134,6 +133,8 @@ pub async fn add_invoice_action(
Some(Status::Active),
order.amount,
order.fiat_code.clone(),
order.min_amount,
order.max_amount,
order.fiat_amount,
order.payment_method.clone(),
order.premium,
Expand Down
2 changes: 1 addition & 1 deletion src/app/admin_cancel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub async fn admin_cancel_action(
if order.status != Status::Dispute.to_string() {
let error = format!(
"Can't settle an order with status different than {}!",
Status::Dispute.to_string()
Status::Dispute
);
send_cant_do_msg(Some(order.id), Some(error), &event.pubkey).await;

Expand Down
2 changes: 1 addition & 1 deletion src/app/admin_settle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub async fn admin_settle_action(
if order.status != Status::Dispute.to_string() {
let error = format!(
"Can't settle an order with status different than {}!",
Status::Dispute.to_string()
Status::Dispute
);
send_cant_do_msg(Some(order.id), Some(error), &event.pubkey).await;

Expand Down
8 changes: 6 additions & 2 deletions src/app/admin_take_dispute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,12 @@ pub async fn admin_take_dispute_action(
};

let mut new_order = order.as_new_order();
new_order.master_buyer_pubkey = order.master_buyer_pubkey.clone();
new_order.master_seller_pubkey = order.master_seller_pubkey.clone();
new_order
.master_buyer_pubkey
.clone_from(&order.master_buyer_pubkey);
new_order
.master_seller_pubkey
.clone_from(&order.master_seller_pubkey);

// Update dispute fields
dispute.status = Status::InProgress.to_string();
Expand Down
51 changes: 32 additions & 19 deletions src/app/order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,28 @@ pub async fn order_action(
}
}

let quote = match order.amount {
0 => match get_market_quote(&order.fiat_amount, &order.fiat_code, 0).await {
Ok(amount) => amount,
Err(e) => {
error!("{:?}", e.to_string());
return Ok(());
}
},
_ => order.amount,
};
// Default case single amount
let mut amount_vec = vec![order.fiat_amount];

// Get max and and min amount in case of range order
// in case of single order do like usual
if let (Some(min), Some(max)) = (order.min_amount, order.max_amount) {
amount_vec.clear();
amount_vec.push(min);
amount_vec.push(max);
}

for fiat_amount in amount_vec {
let quote = match order.amount {
0 => match get_market_quote(&fiat_amount, &order.fiat_code, 0).await {
Ok(amount) => amount,
Err(e) => {
error!("{:?}", e.to_string());
return Ok(());
}
},
_ => order.amount,
};

// Check amount is positive - extra safety check
if quote < 0 {
Expand All @@ -50,15 +62,16 @@ pub async fn order_action(
return Ok(());
}

if quote > mostro_settings.max_order_amount as i64
|| quote < mostro_settings.min_payment_amount as i64
{
let msg = format!(
"Quote is out of sats boundaries min is {} max is {}",
mostro_settings.min_payment_amount, mostro_settings.max_order_amount
);
send_cant_do_msg(order.id, Some(msg), &event.pubkey).await;
return Ok(());
if quote > mostro_settings.max_order_amount as i64
|| quote < mostro_settings.min_payment_amount as i64
{
let msg = format!(
"Quote is out of sats boundaries min is {} max is {}",
mostro_settings.min_payment_amount, mostro_settings.max_order_amount
);
send_cant_do_msg(order.id, Some(msg), &event.pubkey).await;
return Ok(());
}
}

let initiator_ephemeral_pubkey = event.pubkey.to_string();
Expand Down
85 changes: 80 additions & 5 deletions src/app/release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::util::{
get_keys, rate_counterpart, send_cant_do_msg, send_new_order_msg, settle_seller_hold_invoice,
update_order_event,
};
use crate::NOSTR_CLIENT;

use anyhow::{Error, Result};
use lnurl::lightning_address::LightningAddress;
Expand All @@ -14,6 +15,7 @@ use mostro_core::order::{Order, Status};
use nostr_sdk::prelude::*;
use sqlx::{Pool, Sqlite};
use sqlx_crud::Crud;
use std::cmp::Ordering;
use std::str::FromStr;
use tokio::sync::mpsc::channel;
use tonic_openssl_lnd::lnrpc::payment::PaymentStatus;
Expand Down Expand Up @@ -131,7 +133,7 @@ pub async fn release_action(
Ok(())
}

pub async fn do_payment(order: Order) -> Result<()> {
pub async fn do_payment(mut order: Order) -> Result<()> {
// Finally we try to pay buyer's invoice
let payment_request = match order.buyer_invoice.as_ref() {
Some(req) => req.to_string(),
Expand Down Expand Up @@ -182,9 +184,13 @@ pub async fn do_payment(order: Order) -> Result<()> {
"Order Id {}: Invoice with hash: {} paid!",
order.id, msg.payment.payment_hash
);
let _ =
payment_success(&order, &buyer_pubkey, &seller_pubkey, &my_keys)
.await;
let _ = payment_success(
&mut order,
&buyer_pubkey,
&seller_pubkey,
&my_keys,
)
.await;
}
PaymentStatus::Failed => {
info!(
Expand All @@ -211,7 +217,7 @@ pub async fn do_payment(order: Order) -> Result<()> {
}

async fn payment_success(
order: &Order,
order: &mut Order,
buyer_pubkey: &PublicKey,
seller_pubkey: &PublicKey,
my_keys: &Keys,
Expand All @@ -225,6 +231,75 @@ async fn payment_success(
)
.await;

// Check if order is range type
// Add parent range id and update max amount
if order.max_amount.is_some() && order.min_amount.is_some() {
if let Some(max) = order.max_amount {
if let Some(new_max) = max.checked_sub(order.fiat_amount) {
match new_max.cmp(&order.min_amount.unwrap()) {
Ordering::Equal => {
// Update order in case max == min
let pool = db::connect().await?;
let mut new_order = order.clone();
new_order.max_amount = None;
new_order.min_amount = None;
new_order.amount = 0;
new_order.fiat_amount = new_max;
new_order.status = Status::Pending.to_string();
new_order.id = uuid::Uuid::new_v4();
new_order.status = Status::Pending.to_string();
// CRUD order creation
new_order.clone().create(&pool).await?;
// We transform the order fields to tags to use in the event
let tags = crate::nip33::order_to_tags(&new_order);

info!("range order tags to be republished: {:#?}", tags);
// nip33 kind with order fields as tags and order id as identifier
let event =
crate::nip33::new_event(my_keys, "", new_order.id.to_string(), tags)?;

let _ = NOSTR_CLIENT
.get()
.unwrap()
.send_event(event)
.await
.map(|_s| ())
.map_err(|err| err.to_string());
}
Ordering::Greater => {
// Update order in case new max is still greater the min amount
let pool = db::connect().await?;
let mut new_order = order.clone();
new_order.max_amount = Some(new_max);
new_order.range_parent_id = Some(order.id);
new_order.amount = 0;
new_order.id = uuid::Uuid::new_v4();
new_order.status = Status::Pending.to_string();
// CRUD order creation
new_order.clone().create(&pool).await?;
// We transform the order fields to tags to use in the event
let tags = crate::nip33::order_to_tags(&new_order);

info!("range order tags to be republished: {:#?}", tags);
// nip33 kind with order fields as tags and order id as identifier
let event =
crate::nip33::new_event(my_keys, "", new_order.id.to_string(), tags)?;

let _ = NOSTR_CLIENT
.get()
.unwrap()
.send_event(event)
.await
.map(|_s| ())
.map_err(|err| err.to_string());
}
// Update order status in case new max is smaller the min amount
Ordering::Less => {}
}
}
}
}

// Let's wait 5 secs before publish this new event
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
// We publish a new replaceable kind nostr event with the status updated
Expand Down
19 changes: 17 additions & 2 deletions src/app/take_buy.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::util::{
get_market_amount_and_fee, send_cant_do_msg, send_new_order_msg, show_hold_invoice,
get_fiat_amount_requested, get_market_amount_and_fee, send_cant_do_msg, send_new_order_msg,
show_hold_invoice,
};

use anyhow::{Error, Result};
Expand Down Expand Up @@ -48,6 +49,18 @@ pub async fn take_buy_action(
return Ok(());
}

// Get amount request if user requested one for range order - fiat amount will be used below
if let Some(am) = get_fiat_amount_requested(&order, &msg) {
order.fiat_amount = am;
} else {
let error = format!(
"Amount requested is not correct, probably out of range min {:#?} - max {:#?}",
order.min_amount, order.max_amount
);
send_cant_do_msg(Some(order.id), Some(error), &event.pubkey).await;
return Ok(());
}

let order_status = match Status::from_str(&order.status) {
Ok(s) => s,
Err(e) => {
Expand All @@ -67,7 +80,9 @@ pub async fn take_buy_action(
return Ok(());
}
// We update the master pubkey
order.master_seller_pubkey = msg.get_inner_message_kind().pubkey.clone();
order
.master_seller_pubkey
.clone_from(&msg.get_inner_message_kind().pubkey);

let seller_pubkey = event.pubkey;
// Seller can take pending orders only
Expand Down
20 changes: 17 additions & 3 deletions src/app/take_sell.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::lightning::invoice::is_valid_invoice;
use crate::util::{
get_market_amount_and_fee, send_cant_do_msg, send_dm, set_waiting_invoice_status,
show_hold_invoice, update_order_event,
get_fiat_amount_requested, get_market_amount_and_fee, send_cant_do_msg, send_dm,
set_waiting_invoice_status, show_hold_invoice, update_order_event,
};

use anyhow::{Error, Result};
Expand Down Expand Up @@ -32,6 +32,18 @@ pub async fn take_sell_action(
return Ok(());
}
};

// Get amount request if user requested one for range order - fiat amount will be used below
if let Some(am) = get_fiat_amount_requested(&order, &msg) {
order.fiat_amount = am;
} else {
let error = format!(
"Amount requested is not correct, probably out of range min {:#?} - max {:#?}",
order.min_amount, order.max_amount
);
send_cant_do_msg(Some(order.id), Some(error), &event.pubkey).await;
}

// Maker can't take own order
if order.creator_pubkey == event.pubkey.to_hex() {
send_cant_do_msg(Some(order.id), None, &event.pubkey).await;
Expand Down Expand Up @@ -99,7 +111,9 @@ pub async fn take_sell_action(
}

// We update the master pubkey
order.master_buyer_pubkey = msg.get_inner_message_kind().pubkey.clone();
order
.master_buyer_pubkey
.clone_from(&msg.get_inner_message_kind().pubkey);
// Add buyer pubkey to order
order.buyer_pubkey = Some(buyer_pubkey.to_string());
// Timestamp take order time
Expand Down
2 changes: 2 additions & 0 deletions src/flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ pub async fn hold_invoice_paid(hash: &str) -> Result<()> {
None,
order.amount,
order.fiat_code.clone(),
order.min_amount,
order.max_amount,
order.fiat_amount,
order.payment_method.clone(),
order.premium,
Expand Down
Loading

0 comments on commit fd3e8c4

Please sign in to comment.