mostro_client/cli/
send_msg.rs

1use crate::cli::{Commands, Context};
2use crate::db::{Order, User};
3use crate::util::{print_dm_events, send_dm, wait_for_dm};
4
5use anyhow::Result;
6use mostro_core::prelude::*;
7use nostr_sdk::prelude::*;
8use uuid::Uuid;
9
10pub async fn execute_send_msg(
11    command: Commands,
12    order_id: Option<Uuid>,
13    ctx: &Context,
14    text: Option<&str>,
15) -> Result<()> {
16    // Map CLI command to action
17    let requested_action = match command {
18        Commands::FiatSent { .. } => Action::FiatSent,
19        Commands::Release { .. } => Action::Release,
20        Commands::Cancel { .. } => Action::Cancel,
21        Commands::Dispute { .. } => Action::Dispute,
22        Commands::AdmCancel { .. } => Action::AdminCancel,
23        Commands::AdmSettle { .. } => Action::AdminSettle,
24        Commands::AdmAddSolver { .. } => Action::AdminAddSolver,
25        _ => {
26            return Err(anyhow::anyhow!("Invalid command for send msg"));
27        }
28    };
29
30    // Printout command information
31    println!(
32        "Sending {} command for order {} to mostro pubId {}",
33        requested_action,
34        order_id.unwrap(),
35        ctx.mostro_pubkey
36    );
37
38    // Determine payload
39    let payload = match requested_action {
40        Action::FiatSent | Action::Release => create_next_trade_payload(ctx, &order_id).await?,
41        _ => text.map(|t| Payload::TextMessage(t.to_string())),
42    };
43    // Update last trade index if next trade payload
44    if let Some(Payload::NextTrade(_, trade_index)) = &payload {
45        // Update last trade index
46        match User::get(&ctx.pool).await {
47            Ok(mut user) => {
48                user.set_last_trade_index(*trade_index as i64);
49                if let Err(e) = user.save(&ctx.pool).await {
50                    println!("Failed to update user: {}", e);
51                }
52            }
53            Err(e) => println!("Failed to get user: {}", e),
54        }
55    }
56
57    // Create request id
58    let request_id = Uuid::new_v4().as_u128() as u64;
59
60    // Create and send the message
61    let message = Message::new_order(order_id, Some(request_id), None, requested_action, payload);
62
63    if let Some(order_id) = order_id {
64        let order = Order::get_by_id(&ctx.pool, &order_id.to_string()).await?;
65
66        if let Some(trade_keys_str) = order.trade_keys.clone() {
67            let trade_keys = Keys::parse(&trade_keys_str)?;
68
69            // Send DM
70            let message_json = message
71                .as_json()
72                .map_err(|e| anyhow::anyhow!("Failed to serialize message: {e}"))?;
73
74            // Send DM
75            let sent_message = send_dm(
76                &ctx.client,
77                Some(&ctx.identity_keys),
78                &trade_keys,
79                &ctx.mostro_pubkey,
80                message_json,
81                None,
82                false,
83            );
84
85            // Wait for incoming DM
86            let recv_event = wait_for_dm(ctx, Some(&trade_keys), sent_message).await?;
87
88            // Parse the incoming DM
89            print_dm_events(recv_event, request_id, ctx, Some(&trade_keys)).await?;
90        }
91    }
92    Ok(())
93}
94
95async fn create_next_trade_payload(
96    ctx: &Context,
97    order_id: &Option<Uuid>,
98) -> Result<Option<Payload>> {
99    if let Some(order_id) = order_id {
100        let order = Order::get_by_id(&ctx.pool, &order_id.to_string()).await?;
101
102        if let (Some(_), Some(min_amount), Some(max_amount)) =
103            (order.is_mine, order.min_amount, order.max_amount)
104        {
105            if max_amount - order.fiat_amount >= min_amount {
106                let (trade_keys, trade_index) = User::get_next_trade_keys(&ctx.pool).await?;
107                return Ok(Some(Payload::NextTrade(
108                    trade_keys.public_key().to_string(),
109                    trade_index.try_into()?,
110                )));
111            }
112        }
113    }
114    Ok(None)
115}