Skip to content

Instantly share code, notes, and snippets.

@johncantrell97
Created February 6, 2024 15:01
Show Gist options
  • Select an option

  • Save johncantrell97/dc682d2d75a0331fa83cb10a54f62b74 to your computer and use it in GitHub Desktop.

Select an option

Save johncantrell97/dc682d2d75a0331fa83cb10a54f62b74 to your computer and use it in GitHub Desktop.
lightning-liquidity LSP Server Example
// **************************************
// STEP 1: Initialize liquidity manager *
// **************************************
// Create a service config for LSPS2
let liquidity_service_config = LiquidityServiceConfig {
lsps2_service_config: Some(LSPS2ServiceConfig {
// Used to verify the fee parameters you give out
promise_secret: [0; 32],
min_payment_size_msat: 10_000_000,
max_payment_size_msat: 1_000_000_000,
})
};
// Create a liquidity manager which acts as a custom message handler
let liquidity_manager = new LiquidityManager(
keys_manager,
channel_manager,
None,
None,
Some(liquidity_service_config),
None
);
// Provide the liquidity manager as the custom message handler
let lightning_msg_handler = MessageHandler {
chan_handler,
route_handler,
onion_message_handler,
custom_message_handler: liquidity_manager,
};
// Use the message handler when creating your peer manager
let peer_manager = PeerManager::new(
lightning_msg_handler,
...
);
// *******************************************
// STEP 2: Handle lightning-liquidity events *
// *******************************************
// `lightning-liquidity` event handling
tokio::spawn(async move {
let mut interval = tokio::time::interval(Duration::from_secs(1));
loop {
interval.tick().await;
for event in liquidity_manager.get_and_clear_pending_events() {
match event {
LSPSEvent::LSPS2Service(event) => match event {
// A client is asking for our fee information
LSPS2ServiceEvent::GetInfo { request_id, counterparty_node_id, token } => {
// (optional) Check if token is valid and requires custom fees or parameters
// determine fee rate you want to charge
let opening_fee_params_menu = vec![
RawOpeningFeeParams {
min_fee_msat: 5000_000,
proportional_fee: 10_000,
// The parameters are valid for the next 10 minutes
valid_until: Utc::now() + Duration::minutes(10),
// How many blocks we guarantee the channel will remain open for
min_lifetime: 4320,
// The maximum number of blocks we will allow the client to lock our funds up for
// if we need to force close the channel
max_client_to_self_delay: 432
}
];
// Provide the information to lightning-liquidity so it can handle the response
let lsps2_service_handler = liquidity_manager.lsps2_service_handler().unwrap();
lsps2_service_handler.opening_fee_params_generated(&counterparty_node_id, request_id, opening_fee_params_menu).unwrap();
}
// A client is asking to purchase a channel given one of the fee options we provided during a previous GetInfo request
LSPS2ServiceEvent::BuyRequest { request_id, counterparty_node_id, opening_fee_params, payment_size_msat } => {
// (optional) Create an identifier to track this channel request
let user_channel_id = 0;
// Have LDK provide an scid we can use to intercept the payment's HTLC(s)
let intercept_scid = channel_manager.get_intercept_scid();
let cltv_expiry_delta = 72;
let client_trusts_lsp = true;
// Provide the invoice parameters to lightning-liquidity so it can handle the response
let lsps2_service_handler = liquidity_manager.lsps2_service_handler().unwrap();
lsps2_service_handler.invoice_parameters_generated(
&counterparty_node_id,
request_id,
intercept_scid,
client_trusts_lsp,
user_channel_id,
).unwrap();
}
// The payment has been intercepted, it's time to open the channel
LSPS2ServiceEvent::OpenChannel { user_channel_id, their_network_key, amt_to_forward_msat, opening_fee_msat, .. } => {
// Decide on a channel size based on the amount to forward
let channel_value_sats = amt_to_forward_msat * 2;
let push_msats = 0;
// Create the channel with the user
channel_manager.create_channel(
their_network_key,
channel_value_sats,
push_msats,
user_channel_id,
None,
).unwrap();
}
}
}
}
}
})
/// ***********************************
/// STEP3: Augment LDK event handling *
/// ***********************************
let event_handler = move | event: Event | {
match event {
// LDK has intercepted an HTLC with the scid we provided to a user.
Event::HTLCIntercepted {
intercept_id,
request_next_hop_scid,
expected_outbound_amount_msat,
..
} => {
// Inform lightning-liquidity of this htlc so it can determine if we should open a channel or not.
let lsps2_service_handler = self.liquidity_manager.lsps2_service_handler().unwrap();
lsps2_service_handler.htlc_intercepted(
requested_next_hop_scid,
intercept_id,
expected_outbound_amount_msat,
).unwrap();
}
// A channel is ready to be used
Event::ChannelReady {
ref channel_id,
user_channel_id,
ref counterparty_node_id,
..
} => {
// Inform lightning-liquidity a channel is ready so it can determine if it should forward the payment
let lsps2_service_handler = self.liquidity_manager.lsps2_service_handler().unwrap();
lsps2_service_handler.channel_ready(user_channel_id, channel_id, counterparty_node_id).unwrap();
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment