1pub mod dispute;
2pub mod error;
3pub mod message;
4pub mod order;
5pub mod rating;
6pub mod user;
7
8pub const NOSTR_REPLACEABLE_EVENT_KIND: u16 = 38383;
11pub const PROTOCOL_VER: u8 = 1;
12
13#[cfg(test)]
14mod test {
15 use crate::error::CantDoReason;
16 use crate::message::{Action, Message, MessageKind, Payload, Peer};
17 use crate::order::{Kind, SmallOrder, Status};
18 use nostr_sdk::Keys;
19 use uuid::uuid;
20
21 #[test]
22 fn test_status_string() {
23 assert_eq!(Status::Active.to_string(), "active");
24 assert_eq!(Status::CompletedByAdmin.to_string(), "completed-by-admin");
25 assert_eq!(Status::FiatSent.to_string(), "fiat-sent");
26 assert_ne!(Status::Pending.to_string(), "Pending");
27 }
28
29 #[test]
30 fn test_kind_string() {
31 assert_ne!(Kind::Sell.to_string(), "active");
32 assert_eq!(Kind::Sell.to_string(), "sell");
33 assert_eq!(Kind::Buy.to_string(), "buy");
34 assert_ne!(Kind::Buy.to_string(), "active");
35 }
36
37 #[test]
38 fn test_order_message() {
39 let uuid = uuid!("308e1272-d5f4-47e6-bd97-3504baea9c23");
40 let payload = Payload::Order(SmallOrder::new(
41 Some(uuid),
42 Some(Kind::Sell),
43 Some(Status::Pending),
44 100,
45 "eur".to_string(),
46 None,
47 None,
48 100,
49 "SEPA".to_string(),
50 1,
51 None,
52 None,
53 None,
54 Some(1627371434),
55 None,
56 None,
57 None,
58 ));
59
60 let test_message = Message::Order(MessageKind::new(
61 Some(uuid),
62 Some(1),
63 Some(2),
64 Action::NewOrder,
65 Some(payload),
66 ));
67 let test_message_json = test_message.as_json().unwrap();
68 let sample_message = r#"{"order":{"version":1,"id":"308e1272-d5f4-47e6-bd97-3504baea9c23","request_id":1,"trade_index":2,"action":"new-order","payload":{"order":{"id":"308e1272-d5f4-47e6-bd97-3504baea9c23","kind":"sell","status":"pending","amount":100,"fiat_code":"eur","fiat_amount":100,"payment_method":"SEPA","premium":1,"created_at":1627371434}}}}"#;
69 let message = Message::from_json(sample_message).unwrap();
70 assert!(message.verify());
71 let message_json = message.as_json().unwrap();
72 assert_eq!(message_json, test_message_json);
73 }
74
75 #[test]
76 fn test_payment_request_payload_message() {
77 let uuid = uuid!("308e1272-d5f4-47e6-bd97-3504baea9c23");
78 let test_message = Message::Order(MessageKind::new(
79 Some(uuid),
80 Some(1),
81 Some(3),
82 Action::PayInvoice,
83 Some(Payload::PaymentRequest(
84 Some(SmallOrder::new(
85 Some(uuid),
86 Some(Kind::Sell),
87 Some(Status::WaitingPayment),
88 100,
89 "eur".to_string(),
90 None,
91 None,
92 100,
93 "SEPA".to_string(),
94 1,
95 None,
96 None,
97 None,
98 Some(1627371434),
99 None,
100 None,
101 None,
102 )),
103 "lnbcrt78510n1pj59wmepp50677g8tffdqa2p8882y0x6newny5vtz0hjuyngdwv226nanv4uzsdqqcqzzsxqyz5vqsp5skn973360gp4yhlpmefwvul5hs58lkkl3u3ujvt57elmp4zugp4q9qyyssqw4nzlr72w28k4waycf27qvgzc9sp79sqlw83j56txltz4va44j7jda23ydcujj9y5k6k0rn5ms84w8wmcmcyk5g3mhpqepf7envhdccp72nz6e".to_string(),
104 None,
105 )),
106 ));
107 let sample_message = r#"{"order":{"version":1,"id":"308e1272-d5f4-47e6-bd97-3504baea9c23","request_id":1,"trade_index":3,"action":"pay-invoice","payload":{"payment_request":[{"id":"308e1272-d5f4-47e6-bd97-3504baea9c23","kind":"sell","status":"waiting-payment","amount":100,"fiat_code":"eur","fiat_amount":100,"payment_method":"SEPA","premium":1,"created_at":1627371434},"lnbcrt78510n1pj59wmepp50677g8tffdqa2p8882y0x6newny5vtz0hjuyngdwv226nanv4uzsdqqcqzzsxqyz5vqsp5skn973360gp4yhlpmefwvul5hs58lkkl3u3ujvt57elmp4zugp4q9qyyssqw4nzlr72w28k4waycf27qvgzc9sp79sqlw83j56txltz4va44j7jda23ydcujj9y5k6k0rn5ms84w8wmcmcyk5g3mhpqepf7envhdccp72nz6e",null]}}}"#;
108 let message = Message::from_json(sample_message).unwrap();
109 assert!(message.verify());
110 let message_json = message.as_json().unwrap();
111 let test_message_json = test_message.as_json().unwrap();
112 assert_eq!(message_json, test_message_json);
113 }
114
115 #[test]
116 fn test_message_payload_signature() {
117 let uuid = uuid!("308e1272-d5f4-47e6-bd97-3504baea9c23");
118 let peer = Peer::new(
119 "npub1testjsf0runcqdht5apkfcalajxkf8txdxqqk5kgm0agc38ke4vsfsgzf8".to_string(),
120 None,
121 );
122 let payload = Payload::Peer(peer);
123 let test_message = Message::Order(MessageKind::new(
124 Some(uuid),
125 Some(1),
126 Some(2),
127 Action::FiatSentOk,
128 Some(payload),
129 ));
130 assert!(test_message.verify());
131 let test_message_json = test_message.as_json().unwrap();
132 let trade_keys =
134 Keys::parse("110e43647eae221ab1da33ddc17fd6ff423f2b2f49d809b9ffa40794a2ab996c")
135 .unwrap();
136 let sig = Message::sign(test_message_json.clone(), &trade_keys);
137
138 assert!(Message::verify_signature(
139 test_message_json,
140 trade_keys.public_key(),
141 sig
142 ));
143 }
144
145 #[test]
146 fn test_cant_do_message_serialization() {
147 let reasons = vec![
149 CantDoReason::InvalidSignature,
150 CantDoReason::InvalidTradeIndex,
151 CantDoReason::InvalidAmount,
152 CantDoReason::InvalidInvoice,
153 CantDoReason::InvalidPaymentRequest,
154 CantDoReason::InvalidPeer,
155 CantDoReason::InvalidRating,
156 CantDoReason::InvalidTextMessage,
157 CantDoReason::InvalidOrderStatus,
158 CantDoReason::InvalidPubkey,
159 CantDoReason::InvalidParameters,
160 CantDoReason::OrderAlreadyCanceled,
161 CantDoReason::CantCreateUser,
162 CantDoReason::IsNotYourOrder,
163 CantDoReason::NotAllowedByStatus,
164 CantDoReason::OutOfRangeFiatAmount,
165 CantDoReason::OutOfRangeSatsAmount,
166 CantDoReason::IsNotYourDispute,
167 CantDoReason::NotFound,
168 ];
169
170 for reason in reasons {
171 let cant_do = Message::CantDo(MessageKind::new(
172 None,
173 None,
174 None,
175 Action::CantDo,
176 Some(Payload::CantDo(Some(reason.clone()))),
177 ));
178 let message = Message::from_json(&cant_do.as_json().unwrap()).unwrap();
179 assert!(message.verify());
180 assert_eq!(message.as_json().unwrap(), cant_do.as_json().unwrap());
181 }
182
183 let cant_do = Message::CantDo(MessageKind::new(
185 None,
186 None,
187 None,
188 Action::CantDo,
189 Some(Payload::CantDo(None)),
190 ));
191 let message = Message::from_json(&cant_do.as_json().unwrap()).unwrap();
192 assert!(message.verify());
193 assert_eq!(message.as_json().unwrap(), cant_do.as_json().unwrap());
194 }
195}