Skip to content

Instantly share code, notes, and snippets.

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

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

Select an option

Save johncantrell97/1d869aedcb8aef3f69874c15a0793dae to your computer and use it in GitHub Desktop.
lightning-liquidity LSP Client Example
// **************************************
// STEP 1: Initialize liquidity manager *
// **************************************
// Create a client config for LSPS2
let liquidity_client_config = LiquidityClientConfig {
lsps2_client_config: Some(LSPS2ClientConfig {})
};
// Create a liquidity manager which acts as a custom message handler
let liquidity_manager = new LiquidityManager(
keys_manager,
channel_manager,
None,
None,
None,
Some(liquidity_client_config),
);
// 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: Request opening fee parameters *
// ****************************************
// A map we can use to lookup payment size when we receive OpeningParametersReady events
let mut request_id_to_payment_size_map = HashMap::new();
let lsp_pubkey = PublicKey::from_str("LSP_PUBKEY").unwrap();
let payment_size_msat = Some(100_000_000);
// (optional) token to authenticate with the LSP
let token = Some("lspstoken".to_string());
// Request the LSP's opening parameters
let lsps2_client_handler = liquidity_manager.lsps2_client_handler().unwrap();
let request_id = lsps2_client_handler.request_opening_params(lsp_pubkey, token);
// Store the payment size using the returned request_id as key so we can look it up later.
request_id_to_payment_size_map.insert(request_id, payment_size_msat);
// *******************************************
// STEP 3: 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::LSPS2Client(event) => match event {
// The LSP has provided their opening parameters
LSPS2ClientEvent::OpeningParametersReady { request_id, opening_fee_params_menu, .. } => {
// Pick an opening fee parameters from the menu
let opening_fee_params = opening_fee_params_menu[0].clone();
// get payment_size_msat using the request_id
let payment_size_msat = request_id_to_payment_size_map.get(&request_id).unwrap_or(None);
// Provide the information to lightning-liquidity so it can handle the response
let lsps2_client_handler = liquidity_manager.lsps2_client_handler().unwrap();
lsps2_client_handler.select_opening_params(&counterparty_node_id, payment_size_msat, opening_fee_params).unwrap();
}
// The LSP has provided the parameters we need to generate our invoice
LSPS2ServiceEvent::InvoiceParametersReady { request_id, counterparty_node_id, intercept_scid, cltv_expiry_delta, payment_size_msat } => {
let invoice_expiry_delta_secs = 60 * 60 * 24 * 3;
// create a payment_hash and payment_secret using LDK ChannelManager
let (payment_hash, payment_secret) = channel_manager.create_inbound_payment(None, invoice_expiry_delta_secs, None).unwrap();
// Create a route hint that will ensure the payment is routed through the LSP
let lsp_route_hint = RouteHint(vec![RouteHintHop {
src_node_id: counterparty_node_id,
short_channel_id: intercept_scid,
fees: RoutingFees { base_msat: 0, proportional_millionths: 0 },
cltv_expiry_delta: cltv_expiry_delta.try_into().unwrap(),
htlc_minimum_msat: None,
htlc_maximum_msat: None,
}]);
// Create an invoice that uses the route hint we created above
let mut invoice = InvoiceBuilder::new(network.into())
.description("Coins pls!".into())
.payment_hash(sha256::Hash::from_slice(&payment_hash.0).unwrap())
.payment_secret(payment_secret)
.current_timestamp()
.min_final_cltv_expiry_delta(MIN_FINAL_CLTV_EXPIRY_DELTA.into())
.private_route(lsp_route_hint);
// Set payment amount if we provided one
if let Some(payment_size_msat) = payment_size_msat {
invoice = invoice.amount_milli_satoshis(payment_size_msat)
};
// Sign the invoice
let invoice = invoice
.build_signed(|hash| {
Secp256k1::new().sign_ecdsa_recoverable(
hash,
&self.keys_manager.get_node_secret_key(),
)
})
.unwrap();
println!("JIT Channel Invoice: {:?}", invoice)l
}
}
}
}
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment