Skip to content
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

LSPS1- Channel request #8

Merged
merged 4 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1,075 changes: 1,075 additions & 0 deletions src/channel_request/channel_manager.rs

Large diffs are not rendered by default.

59 changes: 59 additions & 0 deletions src/channel_request/event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#![allow(missing_docs)]

use bitcoin::secp256k1::PublicKey;

use super::msgs::{ChannelInfo, OptionsSupported, Order, OrderId, Payment};
use crate::transport::msgs::RequestId;

/// An "Event" which you should probably take some action in response to.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Event {
GetInfoResponse {
id: u128,
request_id: RequestId,
counterparty_node_id: PublicKey,
version: u16,
website: String,
options_supported: OptionsSupported,
},

CreateInvoice {
request_id: RequestId,
counterparty_node_id: PublicKey,
order: Order,
},

DisplayOrder {
id: u128,
counterparty_node_id: PublicKey,
order: Order,
payment: Payment,
channel: Option<ChannelInfo>,
},

PayforChannel {
request_id: RequestId,
counterparty_node_id: PublicKey,
order: Order,
payment: Payment,
channel: Option<ChannelInfo>,
},

CheckPaymentConfirmation {
request_id: RequestId,
counterparty_node_id: PublicKey,
order_id: OrderId,
},

OpenChannel {
request_id: RequestId,
counterparty_node_id: PublicKey,
order_id: OrderId,
},

Refund {
request_id: RequestId,
counterparty_node_id: PublicKey,
order_id: OrderId,
},
}
5 changes: 5 additions & 0 deletions src/channel_request/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@
// licenses.

//! Types and primitives that implement the LSPS1: Channel Request specification.
pub(crate) mod channel_manager;
pub(crate) mod event;
/// Message, request, and other primitive types used to implement LSPS2.
pub mod msgs;
pub(crate) mod utils;
187 changes: 187 additions & 0 deletions src/channel_request/msgs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
use chrono::Utc;
use std::convert::TryFrom;

use serde::{Deserialize, Serialize};

use crate::transport::msgs::{LSPSMessage, RequestId, ResponseError};

pub(crate) const LSPS1_GET_INFO_METHOD_NAME: &str = "lsps1.get_info";
pub(crate) const LSPS1_CREATE_ORDER_METHOD_NAME: &str = "lsps1.create_order";
pub(crate) const LSPS1_GET_ORDER_METHOD_NAME: &str = "lsps1.get_order";

pub(crate) const LSPS1_CREATE_ORDER_REQUEST_INVALID_PARAMS_ERROR_CODE: i32 = -32602;
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_ORDER_MISMATCH_ERROR_CODE: i32 = 1000;
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_CLIENT_REJECTED_ERROR_CODE: i32 = 1001;
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_INVALID_VERSION_ERROR_CODE: i32 = 1;
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_INVALID_TOKEN_ERROR_CODE: i32 = 2;

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Hash)]
pub struct OrderId(pub String);

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)]
#[serde(default)]
pub struct GetInfoRequest {}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct OptionsSupported {
pub minimum_channel_confirmations: u8,
pub minimum_onchain_payment_confirmations: u8,
pub supports_zero_channel_reserve: bool,
pub min_onchain_payment_size_sat: Option<u32>,
pub max_channel_expiry_blocks: u32,
pub min_initial_client_balance_sat: u64,
pub max_initial_client_balance_sat: u64,
pub min_initial_lsp_balance_sat: u64,
pub max_initial_lsp_balance_sat: u64,
pub min_channel_balance_sat: u64,
pub max_channel_balance_sat: u64,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct GetInfoResponse {
pub supported_versions: Vec<u16>,
pub website: String,
pub options: OptionsSupported,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct CreateOrderRequest {
pub version: u16,
pub order: Order,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct Order {
pub api_version: u16,
pub lsp_balance_sat: u64,
pub client_balance_sat: u64,
pub confirms_within_blocks: u32,
pub channel_expiry_blocks: u32,
pub token: String,
pub announce_channel: bool,
pub refund_onchain_address: Option<String>,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct CreateOrderResponse {
pub order_id: OrderId,
pub order: Order,
pub order_state: OrderState,
pub created_at: chrono::DateTime<Utc>,
pub expires_at: chrono::DateTime<Utc>,
pub payment: Payment,
pub channel: Option<ChannelInfo>,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum OrderState {
Requested,
Created,
Completed,
Failed,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct Payment {
pub state: PaymentState,
pub fee_total_sat: u64,
pub order_total_sat: u64,
pub onchain_address: String,
pub bolt11_invoice: String,
pub onchain_block_confirmations_required: u8,
pub minimum_fee_for_0conf: u8,
pub onchain_payment: OnchainPayment,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum PaymentState {
ExpectPayment,
Hold,
Paid,
Refunded,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct OnchainPayment {
pub outpoint: String,
pub sat: u64,
pub confirmed: bool,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct ChannelInfo {
pub state: ChannelStatus,
pub funded_at: String,
pub funding_outpoint: String,
pub scid: Option<String>,
pub expires_at: String,
pub closing_transaction: Option<String>,
pub closed_at: Option<String>,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum ChannelStatus {
Opening,
Opened,
Closed,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct GetOrderRequest {
pub order_id: OrderId,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct GetOrderResponse {
pub response: CreateOrderResponse,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum LSPS1Request {
GetInfo(GetInfoRequest),
CreateOrder(CreateOrderRequest),
GetOrder(GetOrderRequest),
}

impl LSPS1Request {
pub fn method(&self) -> &str {
match self {
LSPS1Request::GetInfo(_) => LSPS1_GET_INFO_METHOD_NAME,
LSPS1Request::CreateOrder(_) => LSPS1_CREATE_ORDER_METHOD_NAME,
LSPS1Request::GetOrder(_) => LSPS1_GET_ORDER_METHOD_NAME,
}
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum LSPS1Response {
GetInfo(GetInfoResponse),
CreateOrder(CreateOrderResponse),
CreateOrderError(ResponseError),
GetOrder(GetOrderResponse),
GetOrderError(ResponseError),
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum LSPS1Message {
Request(RequestId, LSPS1Request),
Response(RequestId, LSPS1Response),
}

impl TryFrom<LSPSMessage> for LSPS1Message {
type Error = ();

fn try_from(message: LSPSMessage) -> Result<Self, Self::Error> {
if let LSPSMessage::LSPS1(message) = message {
return Ok(message);
}

Err(())
}
}

impl From<LSPS1Message> for LSPSMessage {
fn from(message: LSPS1Message) -> Self {
LSPSMessage::LSPS1(message)
}
}
23 changes: 23 additions & 0 deletions src/channel_request/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use super::msgs::{OptionsSupported, Order};

pub fn check_range(min: u64, max: u64, value: u64) -> bool {
(value >= min) && (value <= max)
}

pub fn is_valid(order: &Order, options: &OptionsSupported) -> bool {
let bool = check_range(
options.min_initial_client_balance_sat,
options.max_initial_client_balance_sat,
order.client_balance_sat,
) && check_range(
options.min_initial_lsp_balance_sat,
options.max_initial_lsp_balance_sat,
order.lsp_balance_sat,
) && check_range(
1,
options.max_channel_expiry_blocks.into(),
order.channel_expiry_blocks.into(),
);

bool
}
4 changes: 4 additions & 0 deletions src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
//! [`LiquidityManager::get_and_clear_pending_events`] to receive events.
//!
//! [`LiquidityManager::get_and_clear_pending_events`]: crate::LiquidityManager::get_and_clear_pending_events
/// [`crate::LiquidityManager::get_and_clear_pending_events()`] to receive events.
use crate::channel_request;
use crate::jit_channel;
use std::collections::VecDeque;
use std::sync::{Condvar, Mutex};
Expand Down Expand Up @@ -60,4 +62,6 @@ impl EventQueue {
pub enum Event {
/// An LSPS2 (JIT Channel) protocol event.
LSPS2(jit_channel::LSPS2Event),
/// An LSPS1 protocol event.
LSPS1(channel_request::event::Event),
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub mod jit_channel;
mod transport;
mod utils;

pub use channel_request::event::Event as LSPS1Event;
pub use transport::message_handler::{
JITChannelsConfig, LiquidityManager, LiquidityProviderConfig,
};
Expand Down