mostro_client/cli/
new_order.rs1use crate::cli::Context;
2use crate::parser::orders::print_order_preview;
3use crate::util::{print_dm_events, send_dm, uppercase_first, wait_for_dm};
4use anyhow::Result;
5use mostro_core::prelude::*;
6use std::collections::HashMap;
7use std::io::{stdin, stdout, BufRead, Write};
8use std::process;
9use std::str::FromStr;
10use uuid::Uuid;
11
12pub type FiatNames = HashMap<String, String>;
13
14#[allow(clippy::too_many_arguments)]
15pub async fn execute_new_order(
16 kind: &str,
17 fiat_code: &str,
18 fiat_amount: &(i64, Option<i64>),
19 amount: &i64,
20 payment_method: &str,
21 premium: &i64,
22 invoice: &Option<String>,
23 ctx: &Context,
24 expiration_days: &i64,
25) -> Result<()> {
26 let fiat_code = fiat_code.to_uppercase();
28 if *amount == 0 {
31 let api_req_string = "https://api.yadio.io/currencies".to_string();
33 let fiat_list_check = reqwest::get(api_req_string)
34 .await?
35 .json::<FiatNames>()
36 .await?
37 .contains_key(&fiat_code);
38 if !fiat_list_check {
39 println!("{} is not present in the fiat market, please specify an amount with -a flag to fix the rate", fiat_code);
40 process::exit(0);
41 }
42 }
43 let kind = uppercase_first(kind);
44 let kind_checked = mostro_core::order::Kind::from_str(&kind)
46 .map_err(|_| anyhow::anyhow!("Invalid order kind"))?;
47 let expires_at = match *expiration_days {
48 0 => None,
49 _ => {
50 let now = chrono::Utc::now();
51 let expires_at = now + chrono::Duration::days(*expiration_days);
52 Some(expires_at.timestamp())
53 }
54 };
55
56 let amt = if fiat_amount.1.is_some() {
60 (0, Some(fiat_amount.0), fiat_amount.1)
61 } else {
62 (fiat_amount.0, None, None)
63 };
64
65 let small_order = SmallOrder::new(
66 None,
67 Some(kind_checked),
68 Some(Status::Pending),
69 *amount,
70 fiat_code.clone(),
71 amt.1,
72 amt.2,
73 amt.0,
74 payment_method.to_owned(),
75 *premium,
76 None,
77 None,
78 invoice.as_ref().to_owned().cloned(),
79 Some(0),
80 expires_at,
81 );
82
83 let order_content = Payload::Order(small_order.clone());
85
86 let ord_preview = print_order_preview(order_content.clone())
88 .map_err(|e| anyhow::anyhow!("Failed to generate order preview: {}", e))?;
89 println!("{ord_preview}");
90 let mut user_input = String::new();
91 let _input = stdin();
92 print!("Check your order! Is it correct? (Y/n) > ");
93 stdout().flush()?;
94
95 let mut answer = stdin().lock();
96 answer.read_line(&mut user_input)?;
97
98 match user_input.to_lowercase().as_str().trim_end() {
99 "y" | "" => {}
100 "n" => {
101 println!("Ok you have cancelled the order, create another one please");
102 process::exit(0);
103 }
104 &_ => {
105 println!("Can't get what you're sayin!");
106 process::exit(0);
107 }
108 };
109 let request_id = Uuid::new_v4().as_u128() as u64;
110 let message = Message::new_order(
112 None,
113 Some(request_id),
114 Some(ctx.trade_index),
115 Action::NewOrder,
116 Some(order_content),
117 );
118
119 println!(
121 "SENDING DM with trade index: {} and trade keys: {:?}",
122 ctx.trade_index,
123 ctx.trade_keys.public_key().to_hex()
124 );
125
126 let message_json = message
128 .as_json()
129 .map_err(|_| anyhow::anyhow!("Failed to serialize message"))?;
130
131 let sent_message = send_dm(
133 &ctx.client,
134 Some(&ctx.identity_keys),
135 &ctx.trade_keys,
136 &ctx.mostro_pubkey,
137 message_json,
138 None,
139 false,
140 );
141
142 let recv_event = wait_for_dm(ctx, None, sent_message).await?;
144
145 print_dm_events(recv_event, request_id, ctx, None).await?;
147
148 Ok(())
149}