mostro_client/cli/
add_invoice.rs1use crate::util::{send_dm, wait_for_dm};
2use crate::{cli::Context, db::Order, lightning::is_valid_invoice};
3use anyhow::Result;
4use lnurl::lightning_address::LightningAddress;
5use mostro_core::prelude::*;
6use nostr_sdk::prelude::*;
7use std::str::FromStr;
8use uuid::Uuid;
9
10pub async fn execute_add_invoice(order_id: &Uuid, invoice: &str, ctx: &Context) -> Result<()> {
11 let order = Order::get_by_id(&ctx.pool, &order_id.to_string()).await?;
12 let trade_keys = order
13 .trade_keys
14 .clone()
15 .ok_or(anyhow::anyhow!("Missing trade keys"))?;
16 let order_trade_keys = Keys::parse(&trade_keys)?;
17 println!(
18 "Order trade keys: {:?}",
19 order_trade_keys.public_key().to_hex()
20 );
21
22 println!(
23 "Sending a lightning invoice for order {} to mostro pubId {}",
24 order_id, ctx.mostro_pubkey
25 );
26 let ln_addr = LightningAddress::from_str(invoice);
28 let payload = if ln_addr.is_ok() {
29 Some(Payload::PaymentRequest(None, invoice.to_string(), None))
30 } else {
31 match is_valid_invoice(invoice) {
32 Ok(i) => Some(Payload::PaymentRequest(None, i.to_string(), None)),
33 Err(e) => {
34 return Err(anyhow::anyhow!("Invalid invoice: {}", e));
35 }
36 }
37 };
38
39 let request_id = Uuid::new_v4().as_u128() as u64;
41 let add_invoice_message = Message::new_order(
43 Some(*order_id),
44 Some(request_id),
45 None,
46 Action::AddInvoice,
47 payload,
48 );
49
50 let message_json = add_invoice_message
52 .as_json()
53 .map_err(|_| anyhow::anyhow!("Failed to serialize message"))?;
54
55 let subscription = Filter::new()
57 .pubkey(order_trade_keys.clone().public_key())
58 .kind(nostr_sdk::Kind::GiftWrap)
59 .limit(0);
60
61 let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::WaitForEvents(1));
62 ctx.client.subscribe(subscription, Some(opts)).await?;
63
64 let identity_keys_clone = ctx.identity_keys.clone();
66 let client_clone = ctx.client.clone();
67 let mostro_pubkey_clone = ctx.mostro_pubkey;
68 let order_trade_keys_clone = order_trade_keys.clone();
69
70 tokio::spawn(async move {
73 let _ = send_dm(
74 &client_clone,
75 Some(&identity_keys_clone),
76 &order_trade_keys,
77 &mostro_pubkey_clone,
78 message_json,
79 None,
80 false,
81 )
82 .await;
83 });
84
85 wait_for_dm(
87 &ctx.client,
88 &order_trade_keys_clone,
89 request_id,
90 None,
91 Some(order),
92 &ctx.pool,
93 )
94 .await?;
95 Ok(())
96}