From 3b32edeed93a1644f97939ba4e90b8dfcabd82f0 Mon Sep 17 00:00:00 2001 From: arkanoider Date: Fri, 20 Dec 2024 16:12:23 +0100 Subject: [PATCH 01/11] Fix: takesell now saves on db new order taken from buyer --- Cargo.lock | 8 ++++---- src/cli/get_dm.rs | 1 + src/cli/new_order.rs | 34 ++++++++++++++++++++++------------ src/cli/take_sell.rs | 10 ++++++++++ src/util.rs | 37 +++++++++++++++++++++++++------------ 5 files changed, 62 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0cec74a..7e8095c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -1126,11 +1126,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/src/cli/get_dm.rs b/src/cli/get_dm.rs index ed2c898..9f310a0 100644 --- a/src/cli/get_dm.rs +++ b/src/cli/get_dm.rs @@ -33,6 +33,7 @@ pub async fn execute_get_dm( for keys in final_trade_keys.iter() { let trade_keys = Keys::parse(keys).map_err(|e| anyhow::anyhow!("Failed to parse trade keys: {}", e))?; + println!("Getting messages for trade keys: {}", keys); let dm_temp = get_direct_messages(client, &trade_keys, *since, from_user).await; dm.extend(dm_temp); } diff --git a/src/cli/new_order.rs b/src/cli/new_order.rs index 1a0dd2f..d7ec31e 100644 --- a/src/cli/new_order.rs +++ b/src/cli/new_order.rs @@ -141,25 +141,35 @@ pub async fn execute_new_order( false, ) .await?; + let order_id = dm + .iter() let order_id = dm .iter() .find_map(|el| { let message = el.0.get_inner_message_kind(); - if message.request_id == Some(request_id) { - if let Some(Payload::Order(order)) = message.payload.as_ref() { - return order.id; - } - } - None + message + .request_id + .filter(|&id| id == request_id) + .and_then(|_| message.payload.as_ref()) + .and_then(|payload| { + if let Payload::Order(order) = payload { + order.id + } else { + None + } + }) }) .ok_or_else(|| anyhow::anyhow!("No matching order found in response"))?; println!("Order id {} created", order_id); - let db_order_id = db_order - .id - .clone() - .ok_or(anyhow::anyhow!("Missing order id"))?; - Order::save_new_id(&pool, db_order_id, order_id.to_string()).await?; - + Order::save_new_id( + &pool, + db_order + .id + .clone() + .ok_or_else(|| anyhow::anyhow!("Missing order id"))?, + order_id.to_string(), + ) + .await?; Ok(()) } diff --git a/src/cli/take_sell.rs b/src/cli/take_sell.rs index de24167..88c603b 100644 --- a/src/cli/take_sell.rs +++ b/src/cli/take_sell.rs @@ -97,5 +97,15 @@ pub async fn execute_take_sell( user.set_last_trade_index(trade_index); user.save(&pool).await.unwrap(); + for el in dm.iter() { + let payload = el.0.get_inner_message_kind().payload.clone(); + if let Some(Payload::Order(order)) = &payload { + println!("Order id {} created", order.id.unwrap()); + let _db_order = Order::new(&pool, order.clone(), trade_keys, None) + .await + .unwrap(); + } + } + Ok(()) } diff --git a/src/util.rs b/src/util.rs index f2d4123..be54371 100644 --- a/src/util.rs +++ b/src/util.rs @@ -129,6 +129,7 @@ pub async fn requests_relay( if m.is_empty() { info!("No requested events found on relay {}", relay.0.to_string()); } + println!("Received events: {:?}", res); res = m } Err(_e) => println!("Error"), @@ -183,6 +184,7 @@ pub async fn get_events_of_mostro( // Send msg to relay relay.send_msg(msg.clone())?; + println!("Message sent to relay {:?}", relay.url()); // Wait notification from relays let mut notifications = client.notifications(); @@ -196,10 +198,12 @@ pub async fn get_events_of_mostro( } => { if subscription_id == id { events.push(event.as_ref().clone()); + println!("Received event: {:?}", event); } } RelayMessage::EndOfStoredEvents(subscription_id) => { if subscription_id == id { + println!("End of stored events relay {:?}", relay.url()); break; } } @@ -247,17 +251,24 @@ pub async fn get_direct_messages( info!("Request events with event kind : {:?} ", filters.kinds); - // Send all requests to relays - let mostro_req = send_relays_requests(client, filters).await; - - // Buffer vector for direct messages let mut direct_messages: Vec<(Message, u64)> = Vec::new(); - // Vector for single order id check - maybe multiple relay could send the same order id? Check unique one... - let mut id_list = Vec::::new(); + // Send all requests to relays + //let mostro_req = send_relays_requests(client, filters).await; + let relays = client.pool().relays().await; + for r in relays.into_iter() { + let _ = client.add_relay(r.0).await; + } + + if let Ok(mostro_req) = client + .fetch_events(vec![filters], Some(Duration::from_secs(15))) + .await + { + // Buffer vector for direct messages + // Vector for single order id check - maybe multiple relay could send the same order id? Check unique one... + let mut id_list = Vec::::new(); - for dms in mostro_req.iter() { - for dm in dms { + for dm in mostro_req.iter() { if !id_list.contains(&dm.id) { id_list.push(dm.id); let created_at: Timestamp; @@ -281,6 +292,7 @@ pub async fn get_direct_messages( let unwrapped_gift = match unwrap_gift_wrap(Some(my_key), None, None, dm) { Ok(u) => u, Err(_) => { + println!("Error unwrapping gift"); continue; } }; @@ -290,6 +302,7 @@ pub async fn get_direct_messages( .get_inner_message_kind() .verify_signature(unwrapped_gift.rumor.pubkey, sig) { + println!("Signature verification failed"); continue; } message = mmessage; @@ -297,19 +310,19 @@ pub async fn get_direct_messages( } // Here we discard messages older than the real since parameter let since_time = chrono::Utc::now() - .checked_sub_signed(chrono::Duration::minutes(since)) + .checked_sub_signed(chrono::Duration::minutes(30)) .unwrap() .timestamp() as u64; if created_at.as_u64() < since_time { + println!("Discarding message older than since parameter"); continue; } - direct_messages.push((message, created_at.as_u64())); } } + // Return element sorted by second tuple element ( Timestamp ) + direct_messages.sort_by(|a, b| a.1.cmp(&b.1)); } - // Return element sorted by second tuple element ( Timestamp ) - direct_messages.sort_by(|a, b| a.1.cmp(&b.1)); direct_messages } From 68465dd141f03746f988b6f00d8dd458468c2b5b Mon Sep 17 00:00:00 2001 From: arkanoider Date: Fri, 20 Dec 2024 16:12:23 +0100 Subject: [PATCH 02/11] Remove logic had written for events fetching and switched to functions to sdk ones --- src/cli/new_order.rs | 5 +- src/util.rs | 143 +++++-------------------------------------- 2 files changed, 18 insertions(+), 130 deletions(-) diff --git a/src/cli/new_order.rs b/src/cli/new_order.rs index d7ec31e..829548b 100644 --- a/src/cli/new_order.rs +++ b/src/cli/new_order.rs @@ -141,8 +141,7 @@ pub async fn execute_new_order( false, ) .await?; - let order_id = dm - .iter() + let order_id = dm .iter() .find_map(|el| { @@ -150,7 +149,7 @@ pub async fn execute_new_order( message .request_id .filter(|&id| id == request_id) - .and_then(|_| message.payload.as_ref()) + .and(message.payload.as_ref()) .and_then(|payload| { if let Payload::Order(order) = payload { order.id diff --git a/src/util.rs b/src/util.rs index be54371..7232564 100644 --- a/src/util.rs +++ b/src/util.rs @@ -16,8 +16,6 @@ use nostr_sdk::prelude::*; use std::thread::sleep; use std::time::Duration; use std::{fs, path::Path}; -use tokio::time::timeout; -use uuid::Uuid; pub async fn send_dm( client: &Client, @@ -112,112 +110,6 @@ pub async fn send_message_sync( Ok(dm) } -pub async fn requests_relay( - client: Client, - relay: (RelayUrl, Relay), - filters: Filter, -) -> Vec { - let relrequest = get_events_of_mostro(&relay.1, vec![filters.clone()], client); - - // Buffer vector - let mut res: Vec = Vec::new(); - - // Using a timeout of 3 seconds to avoid unresponsive relays to block the loop forever. - if let Ok(rx) = timeout(Duration::from_secs(3), relrequest).await { - match rx { - Ok(m) => { - if m.is_empty() { - info!("No requested events found on relay {}", relay.0.to_string()); - } - println!("Received events: {:?}", res); - res = m - } - Err(_e) => println!("Error"), - } - } - - res -} - -pub async fn send_relays_requests(client: &Client, filters: Filter) -> Vec> { - let relays = client.relays().await; - - let relays_requests = relays.len(); - let mut requests: Vec>> = - Vec::with_capacity(relays_requests); - let mut answers_requests = Vec::with_capacity(relays_requests); - - for relay in relays.into_iter() { - info!("Requesting to relay : {}", relay.0.as_str()); - // Spawn futures and join them at the end - requests.push(tokio::spawn(requests_relay( - client.clone(), - relay.clone(), - filters.clone(), - ))); - } - - // Get answers from relay - for req in requests { - answers_requests.push(req.await.unwrap()); - } - - answers_requests -} - -pub async fn get_events_of_mostro( - relay: &Relay, - filters: Vec, - client: Client, -) -> Result, Error> { - let mut events: Vec = Vec::new(); - - // Subscribe - info!( - "Subscribing for all mostro orders to relay : {}", - relay.url().to_string() - ); - let id = SubscriptionId::new(Uuid::new_v4().to_string()); - let msg = ClientMessage::req(id.clone(), filters.clone()); - - info!("Message sent : {:?}", msg); - - // Send msg to relay - relay.send_msg(msg.clone())?; - println!("Message sent to relay {:?}", relay.url()); - - // Wait notification from relays - let mut notifications = client.notifications(); - - while let Ok(notification) = notifications.recv().await { - if let RelayPoolNotification::Message { message, .. } = notification { - match message { - RelayMessage::Event { - subscription_id, - event, - } => { - if subscription_id == id { - events.push(event.as_ref().clone()); - println!("Received event: {:?}", event); - } - } - RelayMessage::EndOfStoredEvents(subscription_id) => { - if subscription_id == id { - println!("End of stored events relay {:?}", relay.url()); - break; - } - } - _ => (), - }; - } - } - - // Unsubscribe - relay.send_msg(ClientMessage::close(id))?; - - Ok(events) -} - pub async fn get_direct_messages( client: &Client, my_key: &Keys, @@ -253,13 +145,6 @@ pub async fn get_direct_messages( let mut direct_messages: Vec<(Message, u64)> = Vec::new(); - // Send all requests to relays - //let mostro_req = send_relays_requests(client, filters).await; - let relays = client.pool().relays().await; - for r in relays.into_iter() { - let _ = client.add_relay(r.0).await; - } - if let Ok(mostro_req) = client .fetch_events(vec![filters], Some(Duration::from_secs(15))) .await @@ -341,7 +226,7 @@ pub async fn get_orders_list( let timestamp = Timestamp::from(since_time); - let filter = Filter::new() + let filters = Filter::new() .author(pubkey) .limit(50) .since(timestamp) @@ -350,7 +235,7 @@ pub async fn get_orders_list( info!( "Request to mostro id : {:?} with event kind : {:?} ", - filter.authors, filter.kinds + filters.authors, filters.kinds ); // Extracted Orders List @@ -358,11 +243,13 @@ pub async fn get_orders_list( let mut requested_orders_list = Vec::::new(); // Send all requests to relays - let mostro_req = send_relays_requests(client, filter).await; - // Scan events to extract all orders - for orders_row in mostro_req.iter() { - for ord in orders_row { - let order = order_from_tags(ord.tags.clone()); + if let Ok(mostro_req) = client + .fetch_events(vec![filters], Some(Duration::from_secs(15))) + .await + { + // Scan events to extract all orders + for el in mostro_req.iter() { + let order = order_from_tags(el.tags.clone()); if order.is_err() { error!("{order:?}"); @@ -388,7 +275,7 @@ pub async fn get_orders_list( } // Get created at field from Nostr event - order.created_at = Some(ord.created_at.as_u64() as i64); + order.created_at = Some(el.created_at.as_u64() as i64); complete_events_list.push(order.clone()); @@ -444,10 +331,12 @@ pub async fn get_disputes_list(pubkey: PublicKey, client: &Client) -> Result::new(); // Send all requests to relays - let mostro_req = send_relays_requests(client, filter).await; - // Scan events to extract all disputes - for disputes_row in mostro_req.iter() { - for d in disputes_row { + if let Ok(mostro_req) = client + .fetch_events(vec![filter], Some(Duration::from_secs(15))) + .await + { + // Scan events to extract all disputes + for d in mostro_req.iter() { let dispute = dispute_from_tags(d.tags.clone()); if dispute.is_err() { From b63417f4a3d0109b90d2fbbee2b9c49e55759a41 Mon Sep 17 00:00:00 2001 From: arkanoider Date: Fri, 20 Dec 2024 16:12:23 +0100 Subject: [PATCH 03/11] changed nip59 custom code with nostr-sdk - To be tested --- src/nip59.rs | 55 ---------------------------------------------------- src/util.rs | 37 ++++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 66 deletions(-) diff --git a/src/nip59.rs b/src/nip59.rs index 8a42e6e..67cec94 100644 --- a/src/nip59.rs +++ b/src/nip59.rs @@ -1,63 +1,8 @@ use base64::engine::{general_purpose, Engine}; -use mostro_core::message::Message; use nip44::v2::{decrypt_to_bytes, encrypt_to_bytes, ConversationKey}; use nostr_sdk::event::builder::Error as BuilderError; use nostr_sdk::prelude::*; -/// Creates a new nip59 event -/// -/// # Arguments -/// -/// * `identity_keys` - Keys of the sender used to identify the sender by Mostrod -/// * `trade_keys` - The keys of the sender used to trade -/// * `receiver` - The public key of the receiver -/// * `payload` - The message -/// * `expiration` - Time of the expiration of the event -/// -/// # Returns -/// Returns a gift wrap event -/// -pub fn gift_wrap( - identity_keys: &Keys, - trade_keys: &Keys, - receiver: PublicKey, - payload: String, - expiration: Option, - pow: u8, -) -> Result { - // We convert back the string to a message - let message = Message::from_json(&payload).unwrap(); - // We sign the message - let sig = message.get_inner_message_kind().sign(trade_keys); - // We compose the content - let content = (message, sig); - let content = serde_json::to_string(&content).unwrap(); - // We create the rumor - let rumor: UnsignedEvent = EventBuilder::text_note(content).build(trade_keys.public_key()); - // We seal the rumor - let seal: Event = seal(identity_keys, &receiver, rumor)?; - gift_wrap_from_seal(&receiver, &seal, expiration, pow) -} - -pub fn seal( - sender_keys: &Keys, - receiver_pubkey: &PublicKey, - rumor: UnsignedEvent, -) -> Result { - let sender_private_key = sender_keys.secret_key(); - // Derive conversation key - let ck = ConversationKey::derive(sender_private_key, receiver_pubkey); - // Encrypt payload - let encrypted_content = encrypt_to_bytes(&ck, rumor.as_json())?; - // Encode with base64 - let b64decoded_content = general_purpose::STANDARD.encode(encrypted_content); - // Compose builder - let event = EventBuilder::new(Kind::Seal, b64decoded_content) - .custom_created_at(Timestamp::tweaked(nip59::RANGE_RANDOM_TIMESTAMP_TWEAK)) - .build(sender_keys.public_key()) - .sign_with_keys(sender_keys)?; - Ok(event) -} pub fn gift_wrap_from_seal( receiver: &PublicKey, diff --git a/src/util.rs b/src/util.rs index 7232564..9bc8b97 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,5 +1,5 @@ use crate::nip33::{dispute_from_tags, order_from_tags}; -use crate::nip59::{gift_wrap, unwrap_gift_wrap}; + use anyhow::{Error, Result}; use base64::engine::general_purpose; @@ -23,6 +23,8 @@ pub async fn send_dm( trade_keys: &Keys, receiver_pubkey: &PublicKey, payload: String, + expiration: Option, + pow: u8, to_user: bool, ) -> Result<()> { let pow: u8 = var("POW").unwrap_or('0'.to_string()).parse().unwrap(); @@ -41,14 +43,25 @@ pub async fn send_dm( } else { let identity_keys = identity_keys .ok_or_else(|| Error::msg("identity_keys required when to_user is false"))?; - gift_wrap( - identity_keys, - trade_keys, - *receiver_pubkey, - payload, - None, - pow, - )? + + let message = Message::from_json(&payload).unwrap(); + // We sign the message + let sig = message.get_inner_message_kind().sign(trade_keys); + // We compose the content + let content = (message, sig); + let content = serde_json::to_string(&content).unwrap(); + // We create the rumor + let rumor = EventBuilder::text_note(content).pow(difficulty); + let mut tags: Vec = Vec::with_capacity(1 + usize::from(expiration.is_some())); + tags.push(Tag::public_key(*receiver_pubkey)); + + if let Some(timestamp) = expiration { + tags.push(Tag::expiration(timestamp)); + } + let tags = Tags::new(tags); + + EventBuilder::gift_wrap(identity_keys, receiver_pubkey, rumor, tags).await?; + }; info!("Sending event: {event:#?}"); @@ -95,7 +108,9 @@ pub async fn send_message_sync( trade_keys, &receiver_pubkey, message_json, - to_user, + None, + pow, + to_user ) .await?; // FIXME: This is a hack to wait for the DM to be sent @@ -174,7 +189,7 @@ pub async fn get_direct_messages( message = Message::from_json(&message_str).unwrap(); created_at = dm.created_at; } else { - let unwrapped_gift = match unwrap_gift_wrap(Some(my_key), None, None, dm) { + let unwrapped_gift = match nip59::extract_rumor(my_key, dm).await { Ok(u) => u, Err(_) => { println!("Error unwrapping gift"); From e399ccd7865b84f9936f0dbb53e934a48e3fa11d Mon Sep 17 00:00:00 2001 From: arkanoider Date: Fri, 20 Dec 2024 16:12:23 +0100 Subject: [PATCH 04/11] Pow fix --- src/util.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/util.rs b/src/util.rs index 9bc8b97..50f435e 100644 --- a/src/util.rs +++ b/src/util.rs @@ -24,7 +24,6 @@ pub async fn send_dm( receiver_pubkey: &PublicKey, payload: String, expiration: Option, - pow: u8, to_user: bool, ) -> Result<()> { let pow: u8 = var("POW").unwrap_or('0'.to_string()).parse().unwrap(); @@ -51,7 +50,7 @@ pub async fn send_dm( let content = (message, sig); let content = serde_json::to_string(&content).unwrap(); // We create the rumor - let rumor = EventBuilder::text_note(content).pow(difficulty); + let rumor = EventBuilder::text_note(content).pow(pow); let mut tags: Vec = Vec::with_capacity(1 + usize::from(expiration.is_some())); tags.push(Tag::public_key(*receiver_pubkey)); @@ -60,8 +59,7 @@ pub async fn send_dm( } let tags = Tags::new(tags); - EventBuilder::gift_wrap(identity_keys, receiver_pubkey, rumor, tags).await?; - + EventBuilder::gift_wrap(identity_keys, receiver_pubkey, rumor, tags).await? }; info!("Sending event: {event:#?}"); @@ -109,7 +107,6 @@ pub async fn send_message_sync( &receiver_pubkey, message_json, None, - pow, to_user ) .await?; From 95670241102be2879f5da3b3e3fbdd6ec34296b4 Mon Sep 17 00:00:00 2001 From: arkanoider Date: Fri, 20 Dec 2024 17:38:36 +0100 Subject: [PATCH 05/11] commit for comparing --- Cargo.lock | 53 +++++++++++------------------------------- Cargo.toml | 8 +++++-- src/cli/add_invoice.rs | 2 +- src/cli/send_msg.rs | 2 +- src/nip59.rs | 36 +++------------------------- src/util.rs | 12 +++++----- 6 files changed, 30 insertions(+), 83 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e8095c..b5a2f1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "async-utility" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a349201d80b4aa18d17a34a182bdd7f8ddf845e9e57d2ea130a12e10ef1e3a47" +checksum = "a34a3b57207a7a1007832416c3e4862378c8451b4e8e093e436f48c2d3d2c151" dependencies = [ "futures-util", "gloo-timers", @@ -166,15 +166,13 @@ dependencies = [ [[package]] name = "async-wsocket" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a107e3bdbe61e8e1e1341c57241b4b2d50501127b44bd2eff13b4635ab42d35a" +version = "0.11.0" +source = "git+https://github.com/yukibtc/async-wsocket?rev=259c0bc372e7d60d94827b484178bf995afdcbe6#259c0bc372e7d60d94827b484178bf995afdcbe6" dependencies = [ "async-utility", "futures", "futures-util", "js-sys", - "thiserror", "tokio", "tokio-rustls", "tokio-socks", @@ -195,12 +193,9 @@ dependencies = [ [[package]] name = "atomic-destructor" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d919cb60ba95c87ba42777e9e246c4e8d658057299b437b7512531ce0a09a23" -dependencies = [ - "tracing", -] +checksum = "ef49f5882e4b6afaac09ad239a4f8c70a24b8f2b0897edb1f706008efd109cf4" [[package]] name = "atomic-waker" @@ -1004,9 +999,9 @@ checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" [[package]] name = "gloo-timers" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" dependencies = [ "futures-channel", "futures-core", @@ -1462,15 +1457,6 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" -[[package]] -name = "lru" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" -dependencies = [ - "hashbrown", -] - [[package]] name = "md-5" version = "0.10.6" @@ -1550,9 +1536,7 @@ dependencies = [ [[package]] name = "mostro-core" -version = "0.6.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2707fa1318b15013af06d2314f073353977e56935bb697cb2e462d1cfcade66" +version = "0.6.18" dependencies = [ "anyhow", "bitcoin 0.32.5", @@ -1607,8 +1591,7 @@ dependencies = [ [[package]] name = "nostr" version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8aad4b767bbed24ac5eb4465bfb83bc1210522eb99d67cf4e547ec2ec7e47786" +source = "git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625#70db575d51965240aab1e1b3f1edab782c0ef625" dependencies = [ "async-trait", "base64 0.22.1", @@ -1633,22 +1616,17 @@ dependencies = [ [[package]] name = "nostr-database" version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23696338d51e45cd44e061823847f4b0d1d362eca80d5033facf9c184149f72f" +source = "git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625#70db575d51965240aab1e1b3f1edab782c0ef625" dependencies = [ "async-trait", - "lru", "nostr", - "thiserror", "tokio", - "tracing", ] [[package]] name = "nostr-relay-pool" version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15fcc6e3f0ca54d0fc779009bc5f2684cea9147be3b6aa68a7d301ea590f95f5" +source = "git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625#70db575d51965240aab1e1b3f1edab782c0ef625" dependencies = [ "async-utility", "async-wsocket", @@ -1657,24 +1635,19 @@ dependencies = [ "negentropy 0.4.3", "nostr", "nostr-database", - "thiserror", "tokio", - "tokio-stream", "tracing", ] [[package]] name = "nostr-sdk" version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "491221fc89b1aa189a0de640127127d68b4e7c5c1d44371b04d9a6d10694b5af" +source = "git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625#70db575d51965240aab1e1b3f1edab782c0ef625" dependencies = [ "async-utility", - "atomic-destructor", "nostr", "nostr-database", "nostr-relay-pool", - "thiserror", "tokio", "tracing", ] diff --git a/Cargo.toml b/Cargo.toml index 3be54f7..cb72764 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,8 @@ path = "src/main.rs" [dependencies] anyhow = "1.0.68" clap = { version = "4.0.32", features = ["derive"] } -nostr-sdk = { version = "0.37.0", features = ["nip06", "nip44", "nip59"] } +nostr-sdk = { git = "https://github.com/rust-nostr/nostr", features = ["nip06", "nip44", "nip59"], rev ="70db575d51965240aab1e1b3f1edab782c0ef625"} +# nostr-sdk = { version = "0.37.0", features = ["nip06", "nip44", "nip59"] } serde = "1.0.215" serde_json = "1.0.91" tokio = { version = "1.23.0", features = ["full"] } @@ -39,7 +40,7 @@ uuid = { version = "1.3.0", features = [ dotenvy = "0.15.6" lightning-invoice = "0.23.0" reqwest = { version = "0.12.4", features = ["json"] } -mostro-core = "0.6.17" +mostro-core = "0.6.18" bitcoin_hashes = "0.15.0" lnurl-rs = "0.9.0" pretty_env_logger = "0.5.0" @@ -47,3 +48,6 @@ openssl = { version = "0.10.68", features = ["vendored"] } sqlx = { version = "0.8.2", features = ["sqlite", "runtime-tokio-native-tls"] } bip39 = { version = "2.1.0", features = ["rand"] } dirs = "5.0.1" + +[patch.crates-io] +mostro-core = { path = "../mostro-core" } \ No newline at end of file diff --git a/src/cli/add_invoice.rs b/src/cli/add_invoice.rs index c58613a..f0bd1e3 100644 --- a/src/cli/add_invoice.rs +++ b/src/cli/add_invoice.rs @@ -21,7 +21,7 @@ pub async fn execute_add_invoice( .await .unwrap(); let trade_keys = order.trade_keys.clone().unwrap(); - let trade_keys = Keys::parse(trade_keys).unwrap(); + let trade_keys = Keys::parse(&trade_keys).unwrap(); println!( "Sending a lightning invoice {} to mostro pubId {}", diff --git a/src/cli/send_msg.rs b/src/cli/send_msg.rs index f29551a..a628cd3 100644 --- a/src/cli/send_msg.rs +++ b/src/cli/send_msg.rs @@ -52,7 +52,7 @@ pub async fn execute_send_msg( match order { Ok(order) => { if let Some(trade_keys_str) = order.trade_keys { - let trade_keys = Keys::parse(trade_keys_str)?; + let trade_keys = Keys::parse(&trade_keys_str)?; send_message_sync( client, identity_keys, diff --git a/src/nip59.rs b/src/nip59.rs index 67cec94..2f57297 100644 --- a/src/nip59.rs +++ b/src/nip59.rs @@ -1,39 +1,9 @@ use base64::engine::{general_purpose, Engine}; -use nip44::v2::{decrypt_to_bytes, encrypt_to_bytes, ConversationKey}; +use nip44::v2::{decrypt_to_bytes, ConversationKey}; use nostr_sdk::event::builder::Error as BuilderError; use nostr_sdk::prelude::*; -pub fn gift_wrap_from_seal( - receiver: &PublicKey, - seal: &Event, - expiration: Option, - pow: u8, -) -> Result { - let ephemeral_keys: Keys = Keys::generate(); - // Derive conversation key - let ck = ConversationKey::derive(ephemeral_keys.secret_key(), receiver); - // Encrypt payload - let encrypted_content = encrypt_to_bytes(&ck, seal.as_json())?; - let mut tags: Vec = Vec::with_capacity(1 + usize::from(expiration.is_some())); - tags.push(Tag::public_key(*receiver)); - - if let Some(timestamp) = expiration { - tags.push(Tag::expiration(timestamp)); - } - let tags = Tags::new(tags); - // Encode with base64 - let b64decoded_content = general_purpose::STANDARD.encode(encrypted_content); - let event = EventBuilder::new(Kind::GiftWrap, b64decoded_content) - .tags(tags) - .custom_created_at(Timestamp::tweaked(nip59::RANGE_RANDOM_TIMESTAMP_TWEAK)) - .pow(pow) - .build(ephemeral_keys.public_key()) - .sign_with_keys(&ephemeral_keys)?; - - Ok(event) -} - pub fn unwrap_gift_wrap( keys: Option<&Keys>, gw_ck: Option, @@ -62,7 +32,7 @@ pub fn unwrap_gift_wrap( } }; // Decrypt and verify seal - let seal = decrypt_to_bytes(&gw_ck, b64decoded_content)?; + let seal = decrypt_to_bytes(&gw_ck, &b64decoded_content)?; let seal = String::from_utf8(seal).expect("Found invalid UTF-8"); let seal = match Event::from_json(seal) { Ok(seal) => seal, @@ -95,7 +65,7 @@ pub fn unwrap_gift_wrap( } }; // Decrypt rumor - let rumor = decrypt_to_bytes(&seal_ck, b64decoded_content)?; + let rumor = decrypt_to_bytes(&seal_ck, &b64decoded_content)?; let rumor = String::from_utf8(rumor).expect("Found invalid UTF-8"); Ok(UnwrappedGift { diff --git a/src/util.rs b/src/util.rs index 50f435e..2c00dcc 100644 --- a/src/util.rs +++ b/src/util.rs @@ -31,7 +31,7 @@ pub async fn send_dm( // Derive conversation key let ck = ConversationKey::derive(trade_keys.secret_key(), receiver_pubkey); // Encrypt payload - let encrypted_content = encrypt_to_bytes(&ck, payload)?; + let encrypted_content = encrypt_to_bytes(&ck, payload.as_bytes())?; // Encode with base64 let b64decoded_content = general_purpose::STANDARD.encode(encrypted_content); // Compose builder @@ -50,7 +50,7 @@ pub async fn send_dm( let content = (message, sig); let content = serde_json::to_string(&content).unwrap(); // We create the rumor - let rumor = EventBuilder::text_note(content).pow(pow); + let rumor = EventBuilder::text_note(content).pow(pow).build(trade_keys.public_key()); let mut tags: Vec = Vec::with_capacity(1 + usize::from(expiration.is_some())); tags.push(Tag::public_key(*receiver_pubkey)); @@ -158,7 +158,7 @@ pub async fn get_direct_messages( let mut direct_messages: Vec<(Message, u64)> = Vec::new(); if let Ok(mostro_req) = client - .fetch_events(vec![filters], Some(Duration::from_secs(15))) + .fetch_events(vec![filters], Duration::from_secs(15)) .await { // Buffer vector for direct messages @@ -180,7 +180,7 @@ pub async fn get_direct_messages( } }; // Decrypt - let unencrypted_content = decrypt_to_bytes(&ck, b64decoded_content).unwrap(); + let unencrypted_content = decrypt_to_bytes(&ck, &b64decoded_content).unwrap(); let message_str = String::from_utf8(unencrypted_content).expect("Found invalid UTF-8"); message = Message::from_json(&message_str).unwrap(); @@ -256,7 +256,7 @@ pub async fn get_orders_list( // Send all requests to relays if let Ok(mostro_req) = client - .fetch_events(vec![filters], Some(Duration::from_secs(15))) + .fetch_events(vec![filters], Duration::from_secs(15)) .await { // Scan events to extract all orders @@ -344,7 +344,7 @@ pub async fn get_disputes_list(pubkey: PublicKey, client: &Client) -> Result Date: Fri, 20 Dec 2024 17:52:51 +0100 Subject: [PATCH 06/11] Remove of nip59 mod - Tested a full cycle with specific commit of Yuki, need to check if I can manage also user messages. Removed lot of code also for events fetching --- src/cli/get_dm.rs | 1 - src/cli/new_order.rs | 33 +++++++------------ src/cli/take_sell.rs | 10 ------ src/lib.rs | 1 - src/nip59.rs | 75 -------------------------------------------- src/util.rs | 11 ++++--- 6 files changed, 18 insertions(+), 113 deletions(-) delete mode 100644 src/nip59.rs diff --git a/src/cli/get_dm.rs b/src/cli/get_dm.rs index 9f310a0..ed2c898 100644 --- a/src/cli/get_dm.rs +++ b/src/cli/get_dm.rs @@ -33,7 +33,6 @@ pub async fn execute_get_dm( for keys in final_trade_keys.iter() { let trade_keys = Keys::parse(keys).map_err(|e| anyhow::anyhow!("Failed to parse trade keys: {}", e))?; - println!("Getting messages for trade keys: {}", keys); let dm_temp = get_direct_messages(client, &trade_keys, *since, from_user).await; dm.extend(dm_temp); } diff --git a/src/cli/new_order.rs b/src/cli/new_order.rs index 829548b..1a0dd2f 100644 --- a/src/cli/new_order.rs +++ b/src/cli/new_order.rs @@ -141,34 +141,25 @@ pub async fn execute_new_order( false, ) .await?; - let order_id = dm .iter() .find_map(|el| { let message = el.0.get_inner_message_kind(); - message - .request_id - .filter(|&id| id == request_id) - .and(message.payload.as_ref()) - .and_then(|payload| { - if let Payload::Order(order) = payload { - order.id - } else { - None - } - }) + if message.request_id == Some(request_id) { + if let Some(Payload::Order(order)) = message.payload.as_ref() { + return order.id; + } + } + None }) .ok_or_else(|| anyhow::anyhow!("No matching order found in response"))?; println!("Order id {} created", order_id); - Order::save_new_id( - &pool, - db_order - .id - .clone() - .ok_or_else(|| anyhow::anyhow!("Missing order id"))?, - order_id.to_string(), - ) - .await?; + let db_order_id = db_order + .id + .clone() + .ok_or(anyhow::anyhow!("Missing order id"))?; + Order::save_new_id(&pool, db_order_id, order_id.to_string()).await?; + Ok(()) } diff --git a/src/cli/take_sell.rs b/src/cli/take_sell.rs index 88c603b..de24167 100644 --- a/src/cli/take_sell.rs +++ b/src/cli/take_sell.rs @@ -97,15 +97,5 @@ pub async fn execute_take_sell( user.set_last_trade_index(trade_index); user.save(&pool).await.unwrap(); - for el in dm.iter() { - let payload = el.0.get_inner_message_kind().payload.clone(); - if let Some(Payload::Order(order)) = &payload { - println!("Order id {} created", order.id.unwrap()); - let _db_order = Order::new(&pool, order.clone(), trade_keys, None) - .await - .unwrap(); - } - } - Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index 1cbc0b8..ce39579 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,5 @@ pub mod db; pub mod error; pub mod lightning; pub mod nip33; -pub mod nip59; pub mod pretty_table; pub mod util; diff --git a/src/nip59.rs b/src/nip59.rs deleted file mode 100644 index 2f57297..0000000 --- a/src/nip59.rs +++ /dev/null @@ -1,75 +0,0 @@ -use base64::engine::{general_purpose, Engine}; -use nip44::v2::{decrypt_to_bytes, ConversationKey}; -use nostr_sdk::event::builder::Error as BuilderError; -use nostr_sdk::prelude::*; - - -pub fn unwrap_gift_wrap( - keys: Option<&Keys>, - gw_ck: Option, - seal_ck: Option, - gift_wrap: &Event, -) -> Result { - let gw_ck = match keys { - Some(keys) => ConversationKey::derive(keys.secret_key(), &gift_wrap.pubkey), - None => match gw_ck { - Some(ck) => ck, - None => { - return Err(BuilderError::NIP44( - nostr_sdk::nips::nip44::Error::NotFound( - "No keys or conversation key".to_string(), - ), - )) - } - }, - }; - let b64decoded_content = match general_purpose::STANDARD.decode(gift_wrap.content.as_bytes()) { - Ok(b64decoded_content) => b64decoded_content, - Err(e) => { - return Err(BuilderError::NIP44( - nostr_sdk::nips::nip44::Error::NotFound(e.to_string()), - )); - } - }; - // Decrypt and verify seal - let seal = decrypt_to_bytes(&gw_ck, &b64decoded_content)?; - let seal = String::from_utf8(seal).expect("Found invalid UTF-8"); - let seal = match Event::from_json(seal) { - Ok(seal) => seal, - Err(e) => { - println!("Error: {:#?}", e); - return Err(BuilderError::NIP44( - nostr_sdk::nips::nip44::Error::NotFound(e.to_string()), - )); - } - }; - let seal_ck = match keys { - Some(keys) => ConversationKey::derive(keys.secret_key(), &seal.pubkey), - None => match seal_ck { - Some(ck) => ck, - None => { - return Err(BuilderError::NIP44( - nostr_sdk::nips::nip44::Error::NotFound( - "No keys or conversation key".to_string(), - ), - )) - } - }, - }; - let b64decoded_content = match general_purpose::STANDARD.decode(seal.content.as_bytes()) { - Ok(b64decoded_content) => b64decoded_content, - Err(e) => { - return Err(BuilderError::NIP44( - nostr_sdk::nips::nip44::Error::NotFound(e.to_string()), - )) - } - }; - // Decrypt rumor - let rumor = decrypt_to_bytes(&seal_ck, &b64decoded_content)?; - let rumor = String::from_utf8(rumor).expect("Found invalid UTF-8"); - - Ok(UnwrappedGift { - sender: seal.pubkey, - rumor: UnsignedEvent::from_json(rumor)?, - }) -} diff --git a/src/util.rs b/src/util.rs index 2c00dcc..06a2b05 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,6 +1,5 @@ use crate::nip33::{dispute_from_tags, order_from_tags}; - use anyhow::{Error, Result}; use base64::engine::general_purpose; use base64::Engine; @@ -50,15 +49,17 @@ pub async fn send_dm( let content = (message, sig); let content = serde_json::to_string(&content).unwrap(); // We create the rumor - let rumor = EventBuilder::text_note(content).pow(pow).build(trade_keys.public_key()); + let rumor = EventBuilder::text_note(content) + .pow(pow) + .build(trade_keys.public_key()); let mut tags: Vec = Vec::with_capacity(1 + usize::from(expiration.is_some())); tags.push(Tag::public_key(*receiver_pubkey)); - + if let Some(timestamp) = expiration { tags.push(Tag::expiration(timestamp)); } let tags = Tags::new(tags); - + EventBuilder::gift_wrap(identity_keys, receiver_pubkey, rumor, tags).await? }; @@ -107,7 +108,7 @@ pub async fn send_message_sync( &receiver_pubkey, message_json, None, - to_user + to_user, ) .await?; // FIXME: This is a hack to wait for the DM to be sent From 6c9c4f3ec7d7110e8676354754db1944a00aafe3 Mon Sep 17 00:00:00 2001 From: arkanoider Date: Fri, 20 Dec 2024 18:01:59 +0100 Subject: [PATCH 07/11] removed override in cargo.toml --- Cargo.toml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cb72764..23ce64a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,4 @@ pretty_env_logger = "0.5.0" openssl = { version = "0.10.68", features = ["vendored"] } sqlx = { version = "0.8.2", features = ["sqlite", "runtime-tokio-native-tls"] } bip39 = { version = "2.1.0", features = ["rand"] } -dirs = "5.0.1" - -[patch.crates-io] -mostro-core = { path = "../mostro-core" } \ No newline at end of file +dirs = "5.0.1" \ No newline at end of file From 787c8150f370d0a2d0d36dbed17285344171dddb Mon Sep 17 00:00:00 2001 From: arkanoider Date: Sat, 21 Dec 2024 14:23:51 +0100 Subject: [PATCH 08/11] Rate-user management of command - get the trade keys for the order from db --- Cargo.lock | 46 +++++++++++++++++++++++++++++--------------- src/cli.rs | 10 +--------- src/cli/rate_user.rs | 14 +++++++++++--- src/db.rs | 39 +++++++++++++++---------------------- 4 files changed, 59 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0cec74a..14ad93c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -166,15 +166,14 @@ dependencies = [ [[package]] name = "async-wsocket" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a107e3bdbe61e8e1e1341c57241b4b2d50501127b44bd2eff13b4635ab42d35a" +checksum = "8d50cb541e6d09e119e717c64c46ed33f49be7fa592fa805d56c11d6a7ff093c" dependencies = [ "async-utility", "futures", "futures-util", "js-sys", - "thiserror", "tokio", "tokio-rustls", "tokio-socks", @@ -849,6 +848,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + [[package]] name = "foreign-types" version = "0.3.2" @@ -1043,13 +1048,24 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "hashlink" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -1126,11 +1142,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1292,7 +1308,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -1464,11 +1480,11 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown", + "hashbrown 0.15.2", ] [[package]] @@ -1550,9 +1566,9 @@ dependencies = [ [[package]] name = "mostro-core" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2707fa1318b15013af06d2314f073353977e56935bb697cb2e462d1cfcade66" +checksum = "365f4109979a283c0f198befaa9a518edb346873ead95fca742fb7cc5eb65c81" dependencies = [ "anyhow", "bitcoin 0.32.5", @@ -2537,7 +2553,7 @@ dependencies = [ "futures-intrusive", "futures-io", "futures-util", - "hashbrown", + "hashbrown 0.14.5", "hashlink", "hex", "indexmap", diff --git a/src/cli.rs b/src/cli.rs index ad668c7..bb7607b 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -410,15 +410,7 @@ pub async fn run() -> Result<()> { .await? } Commands::Rate { order_id, rating } => { - execute_rate_user( - order_id, - rating, - &identity_keys, - &trade_keys, - mostro_key, - &client, - ) - .await?; + execute_rate_user(order_id, rating, &identity_keys, mostro_key, &client).await?; } Commands::AdmTakeDispute { dispute_id } => { execute_take_dispute(dispute_id, &identity_keys, &trade_keys, mostro_key, &client) diff --git a/src/cli/rate_user.rs b/src/cli/rate_user.rs index 7625991..07bfca6 100644 --- a/src/cli/rate_user.rs +++ b/src/cli/rate_user.rs @@ -3,13 +3,15 @@ use mostro_core::message::{Action, Message, Payload}; use nostr_sdk::prelude::*; use uuid::Uuid; -use crate::util::send_message_sync; +use crate::{ + db::{connect, Order}, + util::send_message_sync, +}; pub async fn execute_rate_user( order_id: &Uuid, rating: &u8, identity_keys: &Keys, - trade_keys: &Keys, mostro_key: PublicKey, client: &Client, ) -> Result<()> { @@ -24,6 +26,12 @@ pub async fn execute_rate_user( std::process::exit(0); } + let pool = connect().await?; + + // Get trade key for order + let order_to_vote = Order::get_by_id(&pool, &order_id.to_string()).await?; + let trade_keys = Keys::parse(&order_to_vote.trade_keys.unwrap()).unwrap(); + // Create rating message of counterpart let rate_message = Message::new_order( Some(*order_id), @@ -36,7 +44,7 @@ pub async fn execute_rate_user( send_message_sync( client, Some(identity_keys), - trade_keys, + &trade_keys, mostro_key, rate_message, true, diff --git a/src/db.rs b/src/db.rs index 2c1437a..a9ada61 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,4 +1,5 @@ use crate::util::get_mcli_path; +use anyhow::Result; use mostro_core::order::SmallOrder; use mostro_core::NOSTR_REPLACEABLE_EVENT_KIND; use nip06::FromMnemonic; @@ -9,7 +10,7 @@ use sqlx::SqlitePool; use std::fs::File; use std::path::Path; -pub async fn connect() -> Result, sqlx::Error> { +pub async fn connect() -> Result> { let mcli_dir = get_mcli_path(); let mcli_db_path = format!("{}/mcli.db", mcli_dir); let db_url = format!("sqlite://{}", mcli_db_path); @@ -17,7 +18,7 @@ pub async fn connect() -> Result, sqlx::Error> { if !Path::exists(Path::new(&mcli_db_path)) { if let Err(res) = File::create(&mcli_db_path) { println!("Error in creating db file: {}", res); - return Err(sqlx::Error::Io(res)); + return Err(res.into()); } pool = SqlitePool::connect(&db_url).await?; println!("Creating database file with orders table..."); @@ -59,10 +60,10 @@ pub async fn connect() -> Result, sqlx::Error> { Ok(m) => m.to_string(), Err(e) => { println!("Error generating mnemonic: {}", e); - return Err(sqlx::Error::Decode(Box::new(e))); + return Err(e.into()); } }; - let user = User::new(mnemonic, &pool).await.unwrap(); + let user = User::new(mnemonic, &pool).await?; println!("User created with pubkey: {}", user.i0_pubkey); } else { pool = SqlitePool::connect(&db_url).await?; @@ -81,10 +82,7 @@ pub struct User { } impl User { - pub async fn new( - mnemonic: String, - pool: &SqlitePool, - ) -> Result> { + pub async fn new(mnemonic: String, pool: &SqlitePool) -> Result { let mut user = User::default(); let account = NOSTR_REPLACEABLE_EVENT_KIND as u32; let i0_keys = @@ -118,7 +116,7 @@ impl User { } // Applying changes to the database - pub async fn save(&self, pool: &SqlitePool) -> Result<(), Box> { + pub async fn save(&self, pool: &SqlitePool) -> Result<()> { sqlx::query( r#" UPDATE users @@ -140,7 +138,7 @@ impl User { Ok(()) } - pub async fn get(pool: &SqlitePool) -> Result> { + pub async fn get(pool: &SqlitePool) -> Result { let user = sqlx::query_as::<_, User>( r#" SELECT i0_pubkey, mnemonic, last_trade_index, created_at @@ -154,7 +152,7 @@ impl User { Ok(user) } - pub async fn get_next_trade_index(pool: SqlitePool) -> Result> { + pub async fn get_next_trade_index(pool: SqlitePool) -> Result { let user = User::get(&pool).await?; match user.last_trade_index { Some(index) => Ok(index + 1), @@ -162,7 +160,7 @@ impl User { } } - pub async fn get_identity_keys(pool: &SqlitePool) -> Result> { + pub async fn get_identity_keys(pool: &SqlitePool) -> Result { let user = User::get(pool).await?; let account = NOSTR_REPLACEABLE_EVENT_KIND as u32; let keys = @@ -171,9 +169,7 @@ impl User { Ok(keys) } - pub async fn get_next_trade_keys( - pool: &SqlitePool, - ) -> Result<(Keys, i64), Box> { + pub async fn get_next_trade_keys(pool: &SqlitePool) -> Result<(Keys, i64)> { let trade_index = User::get_next_trade_index(pool.clone()).await?; let user = User::get(pool).await?; let account = NOSTR_REPLACEABLE_EVENT_KIND as u32; @@ -225,7 +221,7 @@ impl Order { order: SmallOrder, trade_keys: &Keys, request_id: Option, - ) -> Result> { + ) -> Result { let trade_keys_hex = trade_keys.secret_key().to_secret_hex(); let id = match order.id { Some(id) => id.to_string(), @@ -349,7 +345,7 @@ impl Order { } // Applying changes to the database - pub async fn save(&self, pool: &SqlitePool) -> Result<(), Box> { + pub async fn save(&self, pool: &SqlitePool) -> Result<()> { // Validation if an identity document is present if let Some(ref id) = self.id { sqlx::query( @@ -385,7 +381,7 @@ impl Order { println!("Order with id {} updated in the database.", id); } else { - return Err("Order must have an ID to be updated.".into()); + return Err(anyhow::anyhow!("Order must have an ID to be updated.")); } Ok(()) @@ -412,10 +408,7 @@ impl Order { Ok(rows_affected > 0) } - pub async fn get_by_id( - pool: &SqlitePool, - id: &str, - ) -> Result> { + pub async fn get_by_id(pool: &SqlitePool, id: &str) -> Result { let order = sqlx::query_as::<_, Order>( r#" SELECT * FROM orders WHERE id = ? @@ -429,7 +422,7 @@ impl Order { Ok(order) } - pub async fn get_all(pool: &SqlitePool) -> Result, Box> { + pub async fn get_all(pool: &SqlitePool) -> Result> { let orders = sqlx::query_as::<_, Order>(r#"SELECT * FROM orders"#) .fetch_all(pool) .await?; From f5b27e0e4d541eefbc94a039cd16930b2e929709 Mon Sep 17 00:00:00 2001 From: arkanoider Date: Mon, 23 Dec 2024 11:20:16 +0100 Subject: [PATCH 09/11] add rust-toolchain.toml --- rust-toolchain.toml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 rust-toolchain.toml diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..1173a45 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,5 @@ +[toolchain] +channel = "1.82.0" +profile = "minimal" +components = ["clippy", "rust-docs", "rustfmt"] +targets = ["wasm32-unknown-unknown"] \ No newline at end of file From 7b2b2681bb63cf15285ddd576c5fa22d1331f779 Mon Sep 17 00:00:00 2001 From: arkanoider Date: Tue, 24 Dec 2024 09:47:02 +0100 Subject: [PATCH 10/11] Fix: Improved error message if rating a not taken order --- src/cli/rate_user.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/cli/rate_user.rs b/src/cli/rate_user.rs index a546299..146040f 100644 --- a/src/cli/rate_user.rs +++ b/src/cli/rate_user.rs @@ -28,13 +28,17 @@ pub async fn execute_rate_user( let pool = connect().await?; - let order_to_vote = Order::get_by_id(&pool, &order_id.to_string()).await?; - let trade_keys = match order_to_vote.trade_keys.as_ref() { - Some(trade_keys) => Keys::parse(trade_keys)?, - None => { - println!("key parse error"); - std::process::exit(0); + let trade_keys = if let Ok(order_to_vote) = Order::get_by_id(&pool, &order_id.to_string()).await + { + match order_to_vote.trade_keys.as_ref() { + Some(trade_keys) => Keys::parse(trade_keys)?, + None => { + anyhow::bail!("No trade_keys found for this order"); + } } + } else { + println!("order {} not found", order_id); + std::process::exit(0) }; // Create rating message of counterpart From 2053f6a6e87fa15eb8094fce434d00fa5983658d Mon Sep 17 00:00:00 2001 From: arkanoider Date: Thu, 26 Dec 2024 16:10:50 +0100 Subject: [PATCH 11/11] Fix: senddm improve trade key for message sending --- src/cli.rs | 7 +++++-- src/cli/send_dm.rs | 24 +++++++++++++++++++++--- src/db.rs | 4 +++- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index bb7607b..70d2e6a 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -159,6 +159,9 @@ pub enum Commands { /// Pubkey of the counterpart #[arg(short, long)] pubkey: String, + /// Order id + #[arg(short, long)] + order_id: Uuid, /// Message to send #[arg(short, long)] message: String, @@ -417,9 +420,9 @@ pub async fn run() -> Result<()> { .await? } Commands::AdmListDisputes {} => execute_list_disputes(mostro_key, &client).await?, - Commands::SendDm { pubkey, message } => { + Commands::SendDm { pubkey, order_id, message } => { let pubkey = PublicKey::from_str(pubkey)?; - execute_send_dm(&trade_keys, pubkey, &client, message).await? + execute_send_dm(pubkey, &client, order_id, message).await? } }; } diff --git a/src/cli/send_dm.rs b/src/cli/send_dm.rs index 9c9482d..645e304 100644 --- a/src/cli/send_dm.rs +++ b/src/cli/send_dm.rs @@ -1,12 +1,13 @@ -use crate::util::send_message_sync; +use crate::{db::Order, util::send_message_sync}; use anyhow::Result; use mostro_core::message::{Action, Message, Payload}; use nostr_sdk::prelude::*; +use uuid::Uuid; pub async fn execute_send_dm( - trade_keys: &Keys, receiver: PublicKey, client: &Client, + order_id: &Uuid, message: &str, ) -> Result<()> { let message = Message::new_dm( @@ -15,7 +16,24 @@ pub async fn execute_send_dm( Action::SendDm, Some(Payload::TextMessage(message.to_string())), ); - send_message_sync(client, None, trade_keys, receiver, message, true, true).await?; + + let pool = crate::db::connect().await?; + + let trade_keys = if let Ok(order_to_vote) = Order::get_by_id(&pool, &order_id.to_string()).await + { + match order_to_vote.trade_keys.as_ref() { + Some(trade_keys) => Keys::parse(trade_keys)?, + None => { + anyhow::bail!("No trade_keys found for this order"); + } + } + } else { + println!("order {} not found", order_id); + std::process::exit(0) + }; + + + send_message_sync(client, None, &trade_keys, receiver, message, true, true).await?; Ok(()) } diff --git a/src/db.rs b/src/db.rs index a9ada61..1519d12 100644 --- a/src/db.rs +++ b/src/db.rs @@ -170,7 +170,9 @@ impl User { } pub async fn get_next_trade_keys(pool: &SqlitePool) -> Result<(Keys, i64)> { - let trade_index = User::get_next_trade_index(pool.clone()).await?; + let mut trade_index = User::get_next_trade_index(pool.clone()).await?; + trade_index = trade_index - 1; + let user = User::get(pool).await?; let account = NOSTR_REPLACEABLE_EVENT_KIND as u32; match trade_index.try_into() {