-
Notifications
You must be signed in to change notification settings - Fork 400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LSPS5 implementation #3662
base: main
Are you sure you want to change the base?
LSPS5 implementation #3662
Changes from all commits
5f46222
0450594
3b34619
0bd470e
a60eeff
71f0e61
d78c28b
51c9324
a4abf32
42fd719
330e052
3d8ce58
a26d4d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
martinsaposnic marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,14 +21,21 @@ use crate::lsps1::msgs::{ | |
use crate::lsps2::msgs::{ | ||
LSPS2Message, LSPS2Request, LSPS2Response, LSPS2_BUY_METHOD_NAME, LSPS2_GET_INFO_METHOD_NAME, | ||
}; | ||
use crate::lsps5::msgs::{ | ||
LSPS5Message, LSPS5Request, LSPS5Response, LSPS5_LIST_WEBHOOKS_METHOD_NAME, | ||
LSPS5_REMOVE_WEBHOOK_METHOD_NAME, LSPS5_SET_WEBHOOK_METHOD_NAME, | ||
}; | ||
|
||
use crate::prelude::HashMap; | ||
|
||
use chrono::DateTime; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: I think importing this is fine (although not doing so was a choice before), but now we started, let's drop the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I prefer the style used before. Deleting the import... |
||
use lightning::ln::msgs::{DecodeError, LightningError}; | ||
use lightning::ln::wire; | ||
use lightning::util::ser::{LengthLimitedRead, LengthReadable, WithoutLength}; | ||
|
||
use bitcoin::secp256k1::PublicKey; | ||
|
||
use core::time::Duration; | ||
#[cfg(feature = "std")] | ||
tnull marked this conversation as resolved.
Show resolved
Hide resolved
|
||
use std::time::{SystemTime, UNIX_EPOCH}; | ||
|
||
|
@@ -60,6 +67,9 @@ pub(crate) enum LSPSMethod { | |
LSPS1CreateOrder, | ||
LSPS2GetInfo, | ||
LSPS2Buy, | ||
LSPS5SetWebhook, | ||
LSPS5ListWebhooks, | ||
LSPS5RemoveWebhook, | ||
} | ||
|
||
impl LSPSMethod { | ||
|
@@ -71,6 +81,9 @@ impl LSPSMethod { | |
Self::LSPS1GetOrder => LSPS1_GET_ORDER_METHOD_NAME, | ||
Self::LSPS2GetInfo => LSPS2_GET_INFO_METHOD_NAME, | ||
Self::LSPS2Buy => LSPS2_BUY_METHOD_NAME, | ||
Self::LSPS5SetWebhook => LSPS5_SET_WEBHOOK_METHOD_NAME, | ||
Self::LSPS5ListWebhooks => LSPS5_LIST_WEBHOOKS_METHOD_NAME, | ||
Self::LSPS5RemoveWebhook => LSPS5_REMOVE_WEBHOOK_METHOD_NAME, | ||
} | ||
} | ||
} | ||
|
@@ -85,6 +98,9 @@ impl FromStr for LSPSMethod { | |
LSPS1_GET_ORDER_METHOD_NAME => Ok(Self::LSPS1GetOrder), | ||
LSPS2_GET_INFO_METHOD_NAME => Ok(Self::LSPS2GetInfo), | ||
LSPS2_BUY_METHOD_NAME => Ok(Self::LSPS2Buy), | ||
LSPS5_SET_WEBHOOK_METHOD_NAME => Ok(Self::LSPS5SetWebhook), | ||
LSPS5_LIST_WEBHOOKS_METHOD_NAME => Ok(Self::LSPS5ListWebhooks), | ||
LSPS5_REMOVE_WEBHOOK_METHOD_NAME => Ok(Self::LSPS5RemoveWebhook), | ||
_ => Err(&"Unknown method name"), | ||
} | ||
} | ||
|
@@ -117,6 +133,16 @@ impl From<&LSPS2Request> for LSPSMethod { | |
} | ||
} | ||
|
||
impl From<&LSPS5Request> for LSPSMethod { | ||
fn from(value: &LSPS5Request) -> Self { | ||
match value { | ||
LSPS5Request::SetWebhook(_) => Self::LSPS5SetWebhook, | ||
LSPS5Request::ListWebhooks(_) => Self::LSPS5ListWebhooks, | ||
LSPS5Request::RemoveWebhook(_) => Self::LSPS5RemoveWebhook, | ||
} | ||
} | ||
} | ||
|
||
impl<'de> Deserialize<'de> for LSPSMethod { | ||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
where | ||
|
@@ -214,6 +240,16 @@ impl LSPSDateTime { | |
self.0.timestamp().try_into().expect("expiration to be ahead of unix epoch"); | ||
now_seconds_since_epoch > datetime_seconds_since_epoch | ||
} | ||
|
||
/// Returns the time in seconds since the unix epoch. | ||
pub fn abs_diff(&self, other: &Self) -> u64 { | ||
self.0.timestamp().abs_diff(other.0.timestamp()) | ||
} | ||
|
||
/// Returns the time in seconds since the unix epoch. | ||
pub fn new_from_duration_since_epoch(duration: Duration) -> Self { | ||
Self(DateTime::UNIX_EPOCH + duration) | ||
} | ||
} | ||
|
||
impl FromStr for LSPSDateTime { | ||
|
@@ -255,6 +291,8 @@ pub enum LSPSMessage { | |
LSPS1(LSPS1Message), | ||
/// An LSPS2 message. | ||
LSPS2(LSPS2Message), | ||
/// An LSPS5 message. | ||
LSPS5(LSPS5Message), | ||
} | ||
|
||
impl LSPSMessage { | ||
|
@@ -282,6 +320,10 @@ impl LSPSMessage { | |
LSPSMessage::LSPS2(LSPS2Message::Request(request_id, request)) => { | ||
Some((LSPSRequestId(request_id.0.clone()), request.into())) | ||
}, | ||
// Add LSPS5 | ||
LSPSMessage::LSPS5(LSPS5Message::Request(request_id, request)) => { | ||
Some((LSPSRequestId(request_id.0.clone()), request.into())) | ||
}, | ||
_ => None, | ||
} | ||
} | ||
|
@@ -398,6 +440,47 @@ impl Serialize for LSPSMessage { | |
jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &serde_json::Value::Null)?; | ||
jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, &error)?; | ||
}, | ||
LSPSMessage::LSPS5(LSPS5Message::Request(request_id, request)) => { | ||
jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?; | ||
jsonrpc_object | ||
.serialize_field(JSONRPC_METHOD_FIELD_KEY, &LSPSMethod::from(request))?; | ||
|
||
match request { | ||
LSPS5Request::SetWebhook(params) => { | ||
jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)? | ||
}, | ||
LSPS5Request::ListWebhooks(params) => { | ||
jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)? | ||
}, | ||
LSPS5Request::RemoveWebhook(params) => { | ||
jsonrpc_object.serialize_field(JSONRPC_PARAMS_FIELD_KEY, params)? | ||
}, | ||
} | ||
}, | ||
LSPSMessage::LSPS5(LSPS5Message::Response(request_id, response)) => { | ||
jsonrpc_object.serialize_field(JSONRPC_ID_FIELD_KEY, &request_id.0)?; | ||
|
||
match response { | ||
LSPS5Response::SetWebhook(result) => { | ||
jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)? | ||
}, | ||
LSPS5Response::SetWebhookError(error) => { | ||
jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)? | ||
}, | ||
LSPS5Response::ListWebhooks(result) => { | ||
jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)? | ||
}, | ||
LSPS5Response::ListWebhooksError(error) => { | ||
jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)? | ||
}, | ||
LSPS5Response::RemoveWebhook(result) => { | ||
jsonrpc_object.serialize_field(JSONRPC_RESULT_FIELD_KEY, result)? | ||
}, | ||
LSPS5Response::RemoveWebhookError(error) => { | ||
jsonrpc_object.serialize_field(JSONRPC_ERROR_FIELD_KEY, error)? | ||
}, | ||
} | ||
}, | ||
} | ||
|
||
jsonrpc_object.end() | ||
|
@@ -511,6 +594,31 @@ impl<'de, 'a> Visitor<'de> for LSPSMessageVisitor<'a> { | |
.map_err(de::Error::custom)?; | ||
Ok(LSPSMessage::LSPS2(LSPS2Message::Request(id, LSPS2Request::Buy(request)))) | ||
}, | ||
// Add LSPS5 methods | ||
LSPSMethod::LSPS5SetWebhook => { | ||
let request = serde_json::from_value(params.unwrap_or(json!({}))) | ||
.map_err(de::Error::custom)?; | ||
Ok(LSPSMessage::LSPS5(LSPS5Message::Request( | ||
id, | ||
LSPS5Request::SetWebhook(request), | ||
))) | ||
}, | ||
LSPSMethod::LSPS5ListWebhooks => { | ||
let request = serde_json::from_value(params.unwrap_or(json!({}))) | ||
.map_err(de::Error::custom)?; | ||
Ok(LSPSMessage::LSPS5(LSPS5Message::Request( | ||
id, | ||
LSPS5Request::ListWebhooks(request), | ||
))) | ||
}, | ||
LSPSMethod::LSPS5RemoveWebhook => { | ||
let request = serde_json::from_value(params.unwrap_or(json!({}))) | ||
.map_err(de::Error::custom)?; | ||
Ok(LSPSMessage::LSPS5(LSPS5Message::Request( | ||
id, | ||
LSPS5Request::RemoveWebhook(request), | ||
))) | ||
}, | ||
}, | ||
None => match self.request_id_to_method_map.remove(&id) { | ||
Some(method) => match method { | ||
|
@@ -616,6 +724,58 @@ impl<'de, 'a> Visitor<'de> for LSPSMessageVisitor<'a> { | |
Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required")) | ||
} | ||
}, | ||
// Add LSPS5 methods | ||
LSPSMethod::LSPS5SetWebhook => { | ||
if let Some(error) = error { | ||
Ok(LSPSMessage::LSPS5(LSPS5Message::Response( | ||
id, | ||
LSPS5Response::SetWebhookError(error), | ||
))) | ||
} else if let Some(result) = result { | ||
let response = | ||
serde_json::from_value(result).map_err(de::Error::custom)?; | ||
Ok(LSPSMessage::LSPS5(LSPS5Message::Response( | ||
id, | ||
LSPS5Response::SetWebhook(response), | ||
))) | ||
} else { | ||
Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required")) | ||
} | ||
}, | ||
LSPSMethod::LSPS5ListWebhooks => { | ||
if let Some(error) = error { | ||
Ok(LSPSMessage::LSPS5(LSPS5Message::Response( | ||
id, | ||
LSPS5Response::ListWebhooksError(error), | ||
))) | ||
} else if let Some(result) = result { | ||
let response = | ||
serde_json::from_value(result).map_err(de::Error::custom)?; | ||
Ok(LSPSMessage::LSPS5(LSPS5Message::Response( | ||
id, | ||
LSPS5Response::ListWebhooks(response), | ||
))) | ||
} else { | ||
Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required")) | ||
} | ||
}, | ||
LSPSMethod::LSPS5RemoveWebhook => { | ||
if let Some(error) = error { | ||
Ok(LSPSMessage::LSPS5(LSPS5Message::Response( | ||
id, | ||
LSPS5Response::RemoveWebhookError(error), | ||
))) | ||
} else if let Some(result) = result { | ||
let response = | ||
serde_json::from_value(result).map_err(de::Error::custom)?; | ||
Ok(LSPSMessage::LSPS5(LSPS5Message::Response( | ||
id, | ||
LSPS5Response::RemoveWebhook(response), | ||
))) | ||
} else { | ||
Err(de::Error::custom("Received invalid JSON-RPC object: one of method, result, or error required")) | ||
} | ||
}, | ||
}, | ||
None => Err(de::Error::custom(format!( | ||
"Received response for unknown request id: {}", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Let's keep this whitespace line.