lightning_liquidity/lsps0/
client.rs1use crate::events::{Event, EventQueue};
8use crate::lsps0::event::LSPS0ClientEvent;
9use crate::lsps0::msgs::{
10 LSPS0Message, LSPS0Request, LSPS0Response, ListProtocolsRequest, ListProtocolsResponse,
11};
12use crate::lsps0::ser::{ProtocolMessageHandler, ResponseError};
13use crate::message_queue::MessageQueue;
14use crate::sync::Arc;
15use crate::utils;
16
17use lightning::ln::msgs::{ErrorAction, LightningError};
18use lightning::sign::EntropySource;
19use lightning::util::logger::Level;
20
21use bitcoin::secp256k1::PublicKey;
22
23use core::ops::Deref;
24
25pub struct LSPS0ClientHandler<ES: Deref>
27where
28 ES::Target: EntropySource,
29{
30 entropy_source: ES,
31 pending_messages: Arc<MessageQueue>,
32 pending_events: Arc<EventQueue>,
33}
34
35impl<ES: Deref> LSPS0ClientHandler<ES>
36where
37 ES::Target: EntropySource,
38{
39 pub(crate) fn new(
41 entropy_source: ES, pending_messages: Arc<MessageQueue>, pending_events: Arc<EventQueue>,
42 ) -> Self {
43 Self { entropy_source, pending_messages, pending_events }
44 }
45
46 pub fn list_protocols(&self, counterparty_node_id: &PublicKey) {
52 let msg = LSPS0Message::Request(
53 utils::generate_request_id(&self.entropy_source),
54 LSPS0Request::ListProtocols(ListProtocolsRequest {}),
55 );
56
57 self.pending_messages.enqueue(counterparty_node_id, msg.into());
58 }
59
60 fn handle_response(
61 &self, response: LSPS0Response, counterparty_node_id: &PublicKey,
62 ) -> Result<(), LightningError> {
63 match response {
64 LSPS0Response::ListProtocols(ListProtocolsResponse { protocols }) => {
65 self.pending_events.enqueue(Event::LSPS0Client(
66 LSPS0ClientEvent::ListProtocolsResponse {
67 counterparty_node_id: *counterparty_node_id,
68 protocols,
69 },
70 ));
71 Ok(())
72 },
73 LSPS0Response::ListProtocolsError(ResponseError { code, message, data, .. }) => {
74 Err(LightningError {
75 err: format!(
76 "ListProtocols error received. code = {}, message = {}, data = {:?}",
77 code, message, data
78 ),
79 action: ErrorAction::IgnoreAndLog(Level::Info),
80 })
81 },
82 }
83 }
84}
85
86impl<ES: Deref> ProtocolMessageHandler for LSPS0ClientHandler<ES>
87where
88 ES::Target: EntropySource,
89{
90 type ProtocolMessage = LSPS0Message;
91 const PROTOCOL_NUMBER: Option<u16> = None;
92
93 fn handle_message(
94 &self, message: Self::ProtocolMessage, counterparty_node_id: &PublicKey,
95 ) -> Result<(), LightningError> {
96 match message {
97 LSPS0Message::Response(_, response) => {
98 self.handle_response(response, counterparty_node_id)
99 },
100 LSPS0Message::Request(..) => {
101 debug_assert!(
102 false,
103 "Client handler received LSPS0 request message. This should never happen."
104 );
105 Err(LightningError { err: format!("Client handler received LSPS0 request message from node {:?}. This should never happen.", counterparty_node_id), action: ErrorAction::IgnoreAndLog(Level::Info)})
106 },
107 }
108 }
109}
110
111#[cfg(test)]
112mod tests {
113
114 use alloc::string::ToString;
115 use alloc::sync::Arc;
116
117 use crate::lsps0::ser::{LSPSMessage, RequestId};
118 use crate::tests::utils::{self, TestEntropy};
119
120 use super::*;
121
122 #[test]
123 fn test_list_protocols() {
124 let pending_messages = Arc::new(MessageQueue::new());
125 let entropy_source = Arc::new(TestEntropy {});
126 let event_queue = Arc::new(EventQueue::new());
127
128 let lsps0_handler = Arc::new(LSPS0ClientHandler::new(
129 entropy_source,
130 Arc::clone(&pending_messages),
131 event_queue,
132 ));
133
134 let counterparty_node_id = utils::parse_pubkey(
135 "027100442c3b79f606f80f322d98d499eefcb060599efc5d4ecb00209c2cb54190",
136 )
137 .unwrap();
138
139 lsps0_handler.list_protocols(&counterparty_node_id);
140 let pending_messages = pending_messages.get_and_clear_pending_msgs();
141
142 assert_eq!(pending_messages.len(), 1);
143
144 let (pubkey, message) = &pending_messages[0];
145
146 assert_eq!(*pubkey, counterparty_node_id);
147 assert_eq!(
148 *message,
149 LSPSMessage::LSPS0(LSPS0Message::Request(
150 RequestId("00000000000000000000000000000000".to_string()),
151 LSPS0Request::ListProtocols(ListProtocolsRequest {})
152 ))
153 );
154 }
155}