diff --git a/Cargo.toml b/Cargo.toml index 95da6c82..63aafab0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ uuid = { version = "1.3.0", features = [ "serde", ] } reqwest = { version = "0.11", features = ["json"] } -mostro-core = "0.3.2" +mostro-core = "0.3.3" tokio-cron-scheduler = "*" tracing = "0.1.37" tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } diff --git a/src/app/dispute.rs b/src/app/dispute.rs index d719cda8..b45cda40 100644 --- a/src/app/dispute.rs +++ b/src/app/dispute.rs @@ -74,5 +74,23 @@ pub async fn dispute_action( }; add_dispute(&dispute, pool).await?; + // We create a Message for the initiator + let message = Message::new(0, Some(order.id), None, Action::DisputeInitiatedByYou, None); + let message = message.as_json()?; + let initiator_pubkey = XOnlyPublicKey::from_bech32(message_sender)?; + send_dm(client, my_keys, &initiator_pubkey, message).await?; + + // We create a Message for the counterpart + let message = Message::new( + 0, + Some(order.id), + None, + Action::DisputeInitiatedByPeer, + None, + ); + let message = message.as_json()?; + let counterpart_pubkey = XOnlyPublicKey::from_bech32(counterpart)?; + send_dm(client, my_keys, &counterpart_pubkey, message).await?; + Ok(()) } diff --git a/src/main.rs b/src/main.rs index 3d249b19..f73a042c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ pub mod flow; pub mod lightning; pub mod messages; pub mod models; +pub mod nip33; pub mod scheduler; pub mod util; diff --git a/src/nip33.rs b/src/nip33.rs new file mode 100644 index 00000000..905a19e6 --- /dev/null +++ b/src/nip33.rs @@ -0,0 +1,45 @@ +use mostro_core::NOSTR_REPLACEABLE_EVENT_KIND; +use nostr::event::builder::Error; +use nostr_sdk::prelude::*; + +/// Creates a new mostro nip33 event +/// +/// # Arguments +/// +/// * `keys` - The keys used to sign the event +/// * `content` - The content of the event +/// * `d_str` - The nip33 d tag used to replaced the event with a new one +/// * `k_str` - The nip33 k tag used to subscribe to sell/buy order type notifications +/// * `f_str` - The nip33 f tag used to subscribe to fiat currency code type notifications +/// * `s_str` - The nip33 s tag used to subscribe to order status type notifications +pub fn new_event( + keys: &Keys, + content: String, + d_str: String, + k_str: Option, + f_str: Option, + s_str: Option, +) -> Result { + // This tag (nip33) allows us to change this event in particular in the future + let d_tag = Tag::Generic(TagKind::Custom("d".to_string()), vec![d_str]); + let mut tags = vec![d_tag]; + if let Some(k) = k_str { + // This tag helps client to subscribe to sell/buy order type notifications + let k_tag = Tag::Generic(TagKind::Custom("k".to_string()), vec![k]); + tags.push(k_tag); + } + + if let Some(f) = f_str { + // This tag helps client to subscribe to fiat(shit) coin name + let f_tag = Tag::Generic(TagKind::Custom("f".to_string()), vec![f]); + tags.push(f_tag); + } + + if let Some(s) = s_str { + // This tag helps client to subscribe to order status + let s_tag = Tag::Generic(TagKind::Custom("s".to_string()), vec![s]); + tags.push(s_tag); + } + + EventBuilder::new(Kind::Custom(NOSTR_REPLACEABLE_EVENT_KIND), content, &tags).to_event(keys) +} diff --git a/src/util.rs b/src/util.rs index 2a1a6a6c..2fdf3dac 100644 --- a/src/util.rs +++ b/src/util.rs @@ -4,12 +4,13 @@ use crate::lightning; use crate::lightning::LndConnector; use crate::messages; use crate::models::Yadio; +use crate::nip33::new_event; use crate::{db, flow}; use anyhow::{Context, Result}; use log::{error, info}; use mostro_core::order::{Kind as OrderKind, NewOrder, Order, SmallOrder, Status}; -use mostro_core::{Action, Content, Message, NOSTR_REPLACEABLE_EVENT_KIND}; +use mostro_core::{Action, Content, Message}; use nostr_sdk::prelude::*; use sqlx::SqlitePool; use sqlx::{Pool, Sqlite}; @@ -107,25 +108,16 @@ pub async fn publish_order( let order_string = order.as_json().unwrap(); info!("serialized order: {order_string}"); - // This tag (nip33) allows us to change this event in particular in the future - let d_tag = Tag::Generic(TagKind::Custom("d".to_string()), vec![order_id.to_string()]); - // This tag helps client to subscribe to sell/buy order type notifications - let k_tag = Tag::Generic( - TagKind::Custom("k".to_string()), - vec![order.kind.to_string()], - ); - // This tag helps client to subscribe to fiat(shit) coin name - let f_tag = Tag::Generic( - TagKind::Custom("f".to_string()), - vec![order.fiat_code.clone()], - ); - let event = EventBuilder::new( - Kind::Custom(NOSTR_REPLACEABLE_EVENT_KIND), - &order_string, - &[d_tag, k_tag, f_tag], - ) - .to_event(keys) - .unwrap(); + // nip33 kind with d, k, f, s tags + let event = new_event( + keys, + order_string, + order_id.to_string(), + Some(order.kind.to_string()), + Some(order.fiat_code.clone()), + Some(order.status.to_string()), + )?; + info!("Event to be published: {event:#?}"); let event_id = event.id.to_string(); info!("Publishing Event Id: {event_id} for Order Id: {order_id}"); // We update the order id with the new event_id @@ -192,15 +184,8 @@ pub async fn update_user_rating_event( pool: &SqlitePool, rate_list: Arc>>, ) -> Result<()> { - // let reputation = reput // nip33 kind and d tag - let d_tag = Tag::Generic(TagKind::Custom("d".to_string()), vec![user.to_string()]); - let event = EventBuilder::new( - Kind::Custom(NOSTR_REPLACEABLE_EVENT_KIND), - reputation, - &[d_tag], - ) - .to_event(keys)?; + let event = new_event(keys, reputation, user.to_string(), None, None, None)?; info!("Sending replaceable event: {event:#?}"); // We update the order vote status if buyer_sent_rate { @@ -240,15 +225,10 @@ pub async fn update_order_event( None, Some(order.created_at), ); - let order_string = publish_order.as_json()?; + let order_content = publish_order.as_json()?; // nip33 kind and d tag - let d_tag = Tag::Generic(TagKind::Custom("d".to_string()), vec![order.id.to_string()]); - let event = EventBuilder::new( - Kind::Custom(NOSTR_REPLACEABLE_EVENT_KIND), - &order_string, - &[d_tag], - ) - .to_event(keys)?; + // FIXME: check if we need to send k, f and s tags here too + let event = new_event(keys, order_content, order.id.to_string(), None, None, None)?; let event_id = event.id.to_string(); let status_str = status.to_string(); info!("Sending replaceable event: {event:#?}");