1use crate::cli::Context;
2use crate::parser::common::{
3 create_emoji_field_row, create_field_value_header, create_standard_table,
4};
5use crate::parser::orders::print_order_preview;
6use crate::util::{print_dm_events, send_dm, uppercase_first, wait_for_dm};
7use anyhow::Result;
8use mostro_core::prelude::*;
9use std::collections::HashMap;
10use std::io::{stdin, stdout, BufRead, Write};
11use std::process;
12use std::str::FromStr;
13use uuid::Uuid;
14
15pub type FiatNames = HashMap<String, String>;
16
17#[allow(clippy::too_many_arguments)]
18pub async fn execute_new_order(
19 kind: &str,
20 fiat_code: &str,
21 fiat_amount: &(i64, Option<i64>),
22 amount: &i64,
23 payment_method: &str,
24 premium: &i64,
25 invoice: &Option<String>,
26 ctx: &Context,
27 expiration_days: &i64,
28) -> Result<()> {
29 let fiat_code = fiat_code.to_uppercase();
31 if *amount == 0 {
34 let api_req_string = "https://api.yadio.io/currencies".to_string();
36 let fiat_list_check = reqwest::get(api_req_string)
37 .await?
38 .json::<FiatNames>()
39 .await?
40 .contains_key(&fiat_code);
41 if !fiat_list_check {
42 println!("{} is not present in the fiat market, please specify an amount with -a flag to fix the rate", fiat_code);
43 process::exit(0);
44 }
45 }
46 let kind = uppercase_first(kind);
47 let kind_checked = mostro_core::order::Kind::from_str(&kind)
49 .map_err(|_| anyhow::anyhow!("Invalid order kind"))?;
50 let expires_at = match *expiration_days {
51 0 => None,
52 _ => {
53 let now = chrono::Utc::now();
54 let expires_at = now + chrono::Duration::days(*expiration_days);
55 Some(expires_at.timestamp())
56 }
57 };
58
59 let amt = if fiat_amount.1.is_some() {
63 (0, Some(fiat_amount.0), fiat_amount.1)
64 } else {
65 (fiat_amount.0, None, None)
66 };
67
68 let small_order = SmallOrder::new(
69 None,
70 Some(kind_checked),
71 Some(Status::Pending),
72 *amount,
73 fiat_code.clone(),
74 amt.1,
75 amt.2,
76 amt.0,
77 payment_method.to_owned(),
78 *premium,
79 None,
80 None,
81 invoice.as_ref().to_owned().cloned(),
82 Some(0),
83 expires_at,
84 );
85
86 let order_content = Payload::Order(small_order.clone());
88
89 let ord_preview = print_order_preview(order_content.clone())
91 .map_err(|e| anyhow::anyhow!("Failed to generate order preview: {}", e))?;
92 println!("{ord_preview}");
93 let mut user_input = String::new();
94 let _input = stdin();
95 stdout().flush()?;
96
97 let mut answer = stdin().lock();
98 answer.read_line(&mut user_input)?;
99
100 match user_input.to_lowercase().as_str().trim_end() {
101 "y" | "" => {}
102 "n" => {
103 println!("Ok you have cancelled the order, create another one please");
104 process::exit(0);
105 }
106 &_ => {
107 println!("Can't get what you're sayin!");
108 process::exit(0);
109 }
110 };
111 let request_id = Uuid::new_v4().as_u128() as u64;
112 let message = Message::new_order(
114 None,
115 Some(request_id),
116 Some(ctx.trade_index),
117 Action::NewOrder,
118 Some(order_content),
119 );
120
121 println!("š Create New Order");
123 println!("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
124
125 let mut table = create_standard_table();
126 table.set_header(create_field_value_header());
127
128 table.add_row(create_emoji_field_row("š ", "Order Type", &kind));
129 table.add_row(create_emoji_field_row("š± ", "Fiat Code", &fiat_code));
130 table.add_row(create_emoji_field_row(
131 "š° ",
132 "Amount (sats)",
133 &amount.to_string(),
134 ));
135
136 if let Some(max) = fiat_amount.1 {
137 table.add_row(create_emoji_field_row(
138 "š ",
139 "Fiat Range",
140 &format!("{}-{}", fiat_amount.0, max),
141 ));
142 } else {
143 table.add_row(create_emoji_field_row(
144 "šµ ",
145 "Fiat Amount",
146 &fiat_amount.0.to_string(),
147 ));
148 }
149
150 table.add_row(create_emoji_field_row(
151 "š³ ",
152 "Payment Method",
153 payment_method,
154 ));
155 table.add_row(create_emoji_field_row(
156 "š ",
157 "Premium (%)",
158 &premium.to_string(),
159 ));
160 table.add_row(create_emoji_field_row(
161 "š¢ ",
162 "Trade Index",
163 &ctx.trade_index.to_string(),
164 ));
165 table.add_row(create_emoji_field_row(
166 "š ",
167 "Trade Key",
168 &ctx.trade_keys.public_key.to_hex(),
169 ));
170 table.add_row(create_emoji_field_row(
171 "šÆ ",
172 "Target",
173 &ctx.mostro_pubkey.to_string(),
174 ));
175 println!("{}", table);
176 println!("\nš” Sending new order to Mostro...\n");
177
178 let message_json = message
180 .as_json()
181 .map_err(|_| anyhow::anyhow!("Failed to serialize message"))?;
182
183 let sent_message = send_dm(
185 &ctx.client,
186 Some(&ctx.identity_keys),
187 &ctx.trade_keys,
188 &ctx.mostro_pubkey,
189 message_json,
190 None,
191 false,
192 );
193
194 let recv_event = wait_for_dm(ctx, None, sent_message).await?;
196
197 print_dm_events(recv_event, request_id, ctx, None).await?;
199
200 Ok(())
201}