Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 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
@@ -1,6 +1,6 @@
[package]
name = "mostro-cli"
version = "0.10.5"
version = "0.10.6"
edition = "2021"
license = "MIT"
authors = [
Expand Down Expand Up @@ -39,7 +39,7 @@ uuid = { version = "1.3.0", features = [
dotenvy = "0.15.6"
lightning-invoice = "0.23.0"
reqwest = { version = "0.12.4", features = ["json"] }
mostro-core = "0.6.16"
mostro-core = "0.6.17"
bitcoin_hashes = "0.15.0"
lnurl-rs = "0.9.0"
pretty_env_logger = "0.5.0"
Expand Down
4 changes: 1 addition & 3 deletions src/cli/add_invoice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@ pub async fn execute_add_invoice(
}
// Create AddInvoice message
let add_invoice_message =
Message::new_order(Some(*order_id), None, None, Action::AddInvoice, payload)
.as_json()
.unwrap();
Message::new_order(Some(*order_id), None, None, Action::AddInvoice, payload);

send_message_sync(
client,
Expand Down
27 changes: 22 additions & 5 deletions src/cli/new_order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,19 +121,17 @@ pub async fn execute_new_order(
Some(trade_index),
Action::NewOrder,
Some(order_content),
)
.as_json()
.unwrap();
);
// Create order in db
let pool = connect().await?;
Order::new(&pool, small_order, trade_keys, Some(request_id as i64))
let db_order = Order::new(&pool, small_order, trade_keys, Some(request_id as i64))
.await
.unwrap();
// Update last trade index
let mut user = User::get(&pool).await.unwrap();
user.set_last_trade_index(trade_index);
user.save(&pool).await.unwrap();
send_message_sync(
let dm = send_message_sync(
client,
Some(identity_keys),
trade_keys,
Expand All @@ -143,5 +141,24 @@ pub async fn execute_new_order(
false,
)
.await?;
let order_id = dm.iter()
.find_map(|el| {
let message = el.0.get_inner_message_kind();
message.request_id
.filter(|&id| id == request_id)
.and_then(|_| message.payload.as_ref())
.and_then(|payload| {
if let Payload::Order(order) = payload {
order.id
} else {
None
}
})
})
.ok_or_else(|| anyhow::anyhow!("No matching order found in response"))?;

println!("Order id {} created", order_id);
Order::save_new_id(&pool, db_order.id.clone().ok_or_else(|| anyhow::anyhow!("Missing order id"))?, order_id.to_string())
.await?;
Ok(())
}
4 changes: 1 addition & 3 deletions src/cli/rate_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ pub async fn execute_rate_user(
None,
Action::RateUser,
Some(rating_content),
)
.as_json()
.unwrap();
);

send_message_sync(
client,
Expand Down
16 changes: 7 additions & 9 deletions src/cli/send_dm.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::util::send_message_sync;
use anyhow::Result;
use mostro_core::message::{Action, Message, Payload};
use nostr_sdk::prelude::*;

pub async fn execute_send_dm(
Expand All @@ -8,16 +9,13 @@ pub async fn execute_send_dm(
client: &Client,
message: &str,
) -> Result<()> {
send_message_sync(
client,
let message = Message::new_dm(
None,
trade_keys,
receiver,
message.to_string(),
true,
true,
)
.await?;
None,
Action::SendDm,
Some(Payload::TextMessage(message.to_string())),
);
send_message_sync(client, None, trade_keys, receiver, message, true, true).await?;

Ok(())
}
4 changes: 1 addition & 3 deletions src/cli/send_msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ pub async fn execute_send_msg(
}

// Create message
let message = Message::new_order(order_id, None, None, requested_action, payload)
.as_json()
.unwrap();
let message = Message::new_order(order_id, None, None, requested_action, payload);
info!("Sending message: {:#?}", message);

let pool = connect().await?;
Expand Down
4 changes: 1 addition & 3 deletions src/cli/take_buy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ pub async fn execute_take_buy(
Some(trade_index),
Action::TakeBuy,
payload,
)
.as_json()
.unwrap();
);

send_message_sync(
client,
Expand Down
4 changes: 1 addition & 3 deletions src/cli/take_dispute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ pub async fn execute_take_dispute(
None,
Action::AdminTakeDispute,
None,
)
.as_json()
.unwrap();
);

send_message_sync(
client,
Expand Down
4 changes: 1 addition & 3 deletions src/cli/take_sell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,7 @@ pub async fn execute_take_sell(
Some(trade_index),
Action::TakeSell,
payload,
)
.as_json()
.unwrap();
);

send_message_sync(
client,
Expand Down
21 changes: 21 additions & 0 deletions src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,27 @@ impl Order {
Ok(())
}

pub async fn save_new_id(
pool: &SqlitePool,
id: String,
new_id: String,
) -> anyhow::Result<bool> {
let rows_affected = sqlx::query(
r#"
UPDATE orders
SET id = ?
WHERE id = ?
"#,
)
.bind(&new_id)
.bind(&id)
.execute(pool)
.await?
.rows_affected();

Ok(rows_affected > 0)
}

pub async fn get_by_id(
pool: &SqlitePool,
id: &str,
Expand Down
65 changes: 27 additions & 38 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use mostro_core::order::{SmallOrder, Status};
use mostro_core::NOSTR_REPLACEABLE_EVENT_KIND;
use nip44::v2::{decrypt_to_bytes, encrypt_to_bytes, ConversationKey};
use nostr_sdk::prelude::*;
use std::thread::sleep;
use std::time::Duration;
use std::{fs, path::Path};
use tokio::time::timeout;
Expand Down Expand Up @@ -80,58 +81,46 @@ pub async fn send_message_sync(
identity_keys: Option<&Keys>,
trade_keys: &Keys,
receiver_pubkey: PublicKey,
message: String,
message: Message,
wait_for_dm_ans: bool,
to_user: bool,
) -> Result<()> {
) -> Result<Vec<(Message, u64)>> {
let mut dm: Vec<(Message, u64)> = Vec::new();
let message_json = message.as_json()?;
// Send dm to receiver pubkey
println!(
"SENDING DM with trade keys: {:?}",
trade_keys.public_key().to_hex()
);
send_dm(
client,
identity_keys,
trade_keys,
&receiver_pubkey,
message,
message_json,
to_user,
)
.await?;

let mut notifications = client.notifications();
while let Ok(notification) = notifications.recv().await {
if wait_for_dm_ans {
let dm = get_direct_messages(client, trade_keys, 1, to_user).await;
println!("DM: {:#?}", dm);
for el in dm.iter() {
if let Some(Payload::PaymentRequest(ord, inv, _)) =
&el.0.get_inner_message_kind().payload
{
println!("NEW MESSAGE:");
println!(
"Mostro sent you this hold invoice for order id: {}",
ord.as_ref().unwrap().id.unwrap()
);
println!();
println!("Pay this invoice to continue --> {}", inv);
println!();
}
sleep(Duration::from_secs(1));

if wait_for_dm_ans {
dm = get_direct_messages(client, trade_keys, 1, to_user).await;
for el in dm.iter() {
if let Some(Payload::PaymentRequest(ord, inv, _)) =
&el.0.get_inner_message_kind().payload
{
println!("NEW MESSAGE:");
println!(
"Mostro sent you this hold invoice for order id: {}",
ord.as_ref().unwrap().id.unwrap()
);
println!();
println!("Pay this invoice to continue --> {}", inv);
println!();
}
break;
} else if let RelayPoolNotification::Message {
message:
RelayMessage::Ok {
event_id: _,
status: _,
message: _,
},
..
} = notification
{
println!(
"Message correctly sent to Mostro! Check messages with getdm or listorders command"
);
break;
}
}
Comment on lines +106 to 122

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider improving error handling and async operations

The current implementation has several areas for improvement:

  1. The message processing loop could benefit from error handling
  2. Using synchronous sleep in an async function can block the executor

Consider this improved implementation:

     if wait_for_dm_ans {
-        dm = get_direct_messages(client, trade_keys, 1, to_user).await;
-        for el in dm.iter() {
+        match get_direct_messages(client, trade_keys, 1, to_user).await {
+            messages => {
+                dm = messages;
+                for el in dm.iter() {
                     if let Some(Payload::PaymentRequest(ord, inv, _)) =
                         &el.0.get_inner_message_kind().payload
                     {
-                        println!("NEW MESSAGE:");
-                        println!(
-                            "Mostro sent you this hold invoice for order id: {}",
-                            ord.as_ref().unwrap().id.unwrap()
-                        );
-                        println!();
-                        println!("Pay this invoice to continue -->  {}", inv);
-                        println!();
+                        if let Some(order) = ord.as_ref() {
+                            if let Some(order_id) = order.id {
+                                println!("NEW MESSAGE:");
+                                println!(
+                                    "Mostro sent you this hold invoice for order id: {}",
+                                    order_id
+                                );
+                                println!();
+                                println!("Pay this invoice to continue -->  {}", inv);
+                                println!();
+                            }
+                        }
                     }
+                }
             }
         }
     }

Also, consider using tokio::time::sleep instead of std::thread::sleep to avoid blocking:

- use std::thread::sleep;
+ use tokio::time::sleep;

Committable suggestion skipped: line range outside the PR's diff.

Ok(())
Ok(dm)
Comment on lines 83 to +123

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Update required: Inconsistent handling of return values

Based on the verification results, there are issues with how the return value is handled across different callers:

  • In src/cli/new_order.rs: Correctly assigns the return value to dm variable
  • In src/cli/send_dm.rs: Ignores the return value and returns Ok(())
  • Other callers (take_sell, take_dispute, rate_user, send_msg, take_buy, add_invoice) don't handle the return value properly

The change from Result<()> to Result<Vec<(Message, u64)>> requires updates in all calling functions to properly handle the returned messages.

🔗 Analysis chain

Verify updates in all caller functions

The change in return type from Result<()> to Result<Vec<(Message, u64)>> requires verification of all calling functions.


Let me analyze the callers to verify if they handle the return value correctly.


Let me try a different approach to check the usage patterns.


Let me try one more search to see how the function calls are handled in other files.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all calls to send_message_sync
rg "send_message_sync\(" --type rust -A 5 -B 5

Length of output: 4340


Script:

#!/bin/bash
# Check how callers handle the return value
ast-grep --pattern 'send_message_sync($$$).await$_'

Length of output: 53


Script:

#!/bin/bash
# Search for await patterns with send_message_sync
rg "send_message_sync\(.*\)\.await" --type rust -A 2 -B 2

Length of output: 317


Script:

#!/bin/bash
# Search for let patterns with send_message_sync to see variable assignments
rg "let.*=.*send_message_sync\(" --type rust -A 2 -B 2

Length of output: 319

}

pub async fn requests_relay(
Expand Down