-
-
Save johncantrell97/1d869aedcb8aef3f69874c15a0793dae to your computer and use it in GitHub Desktop.
lightning-liquidity LSP Client Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ************************************** | |
| // 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