mostro_client/cli/
take_sell.rs

1use anyhow::Result;
2use lnurl::lightning_address::LightningAddress;
3use mostro_core::error::CantDoReason;
4use mostro_core::message::{Action, Message, Payload};
5use nostr_sdk::prelude::*;
6use std::str::FromStr;
7use uuid::Uuid;
8
9use crate::db::{connect, Order, User};
10use crate::lightning::is_valid_invoice;
11use crate::util::send_message_sync;
12
13#[allow(clippy::too_many_arguments)]
14pub async fn execute_take_sell(
15    order_id: &Uuid,
16    invoice: &Option<String>,
17    amount: Option<u32>,
18    identity_keys: &Keys,
19    trade_keys: &Keys,
20    trade_index: i64,
21    mostro_key: PublicKey,
22    client: &Client,
23) -> Result<()> {
24    println!(
25        "Request of take sell order {} from mostro pubId {}",
26        order_id,
27        mostro_key.clone()
28    );
29
30    let payload = match invoice {
31        Some(inv) => {
32            let initial_payload = match LightningAddress::from_str(&inv) {
33                Ok(_) => Payload::PaymentRequest(None, inv.to_string(), None),
34                Err(_) => match is_valid_invoice(&inv) {
35                    Ok(i) => Payload::PaymentRequest(None, i.to_string(), None),
36                    Err(e) => {
37                        println!("{}", e);
38                        Payload::PaymentRequest(None, inv.to_string(), None) // or handle error differently
39                    }
40                },
41            };
42
43            match amount {
44                Some(amt) => match initial_payload {
45                    Payload::PaymentRequest(a, b, _) => {
46                        Payload::PaymentRequest(a, b, Some(amt as i64))
47                    }
48                    payload => payload,
49                },
50                None => initial_payload,
51            }
52        }
53        None => amount
54            .map(|amt| Payload::Amount(amt.into()))
55            .unwrap_or(Payload::Amount(0)),
56    };
57
58    let request_id = Uuid::new_v4().as_u128() as u64;
59    // Create takesell message
60    let take_sell_message = Message::new_order(
61        Some(*order_id),
62        Some(request_id),
63        Some(trade_index),
64        Action::TakeSell,
65        Some(payload),
66    );
67
68    let dm = send_message_sync(
69        client,
70        Some(identity_keys),
71        trade_keys,
72        mostro_key,
73        take_sell_message,
74        true,
75        false,
76    )
77    .await?;
78    let pool = connect().await?;
79
80    let order = dm.iter().find_map(|el| {
81        let message = el.0.get_inner_message_kind();
82        if message.request_id == Some(request_id) {
83            match message.action {
84                Action::AddInvoice => {
85                    if let Some(Payload::Order(order)) = message.payload.as_ref() {
86                        println!(
87                            "Please add a lightning invoice with amount of {}",
88                            order.amount
89                        );
90                        return Some(order.clone());
91                    }
92                }
93                Action::CantDo => {
94                    if let Some(Payload::CantDo(Some(cant_do_reason))) = &message.payload {
95                        match cant_do_reason {
96                            CantDoReason::OutOfRangeFiatAmount | CantDoReason::OutOfRangeSatsAmount => {
97                                println!("Error: Amount is outside the allowed range. Please check the order's min/max limits.");
98                            }
99                            _ => {
100                                println!("Unknown reason: {:?}", message.payload);
101                            }
102                        }
103                    } else {
104                        println!("Unknown reason: {:?}", message.payload);
105                        return None;
106                    }
107                }
108                _ => {
109                    println!("Unknown action: {:?}", message.action);
110                    return None;
111                }
112            }
113        }
114        None
115    });
116    if let Some(o) = order {
117        if let Ok(order) = Order::new(&pool, o, trade_keys, Some(request_id as i64)).await {
118            if let Some(order_id) = order.id {
119                println!("Order {} created", order_id);
120            } else {
121                println!("Warning: The newly created order has no ID.");
122            }
123            // Update last trade index to be used in next trade
124            match User::get(&pool).await {
125                Ok(mut user) => {
126                    user.set_last_trade_index(trade_index);
127                    if let Err(e) = user.save(&pool).await {
128                        println!("Failed to update user: {}", e);
129                    }
130                }
131                Err(e) => println!("Failed to get user: {}", e),
132            }
133        }
134    }
135
136    Ok(())
137}