|
8 | 8 | mod common;
|
9 | 9 |
|
10 | 10 | use common::{
|
11 |
| - do_channel_full_cycle, expect_channel_ready_event, expect_event, expect_payment_received_event, |
12 |
| - expect_payment_successful_event, generate_blocks_and_wait, open_channel, |
13 |
| - premine_and_distribute_funds, random_config, setup_bitcoind_and_electrsd, setup_builder, |
14 |
| - setup_node, setup_two_nodes, wait_for_tx, TestChainSource, TestSyncStore, |
| 11 | + do_channel_full_cycle, expect_channel_pending_event, expect_channel_ready_event, expect_event, |
| 12 | + expect_payment_received_event, expect_payment_successful_event, generate_blocks_and_wait, |
| 13 | + open_channel, premine_and_distribute_funds, random_config, setup_bitcoind_and_electrsd, |
| 14 | + setup_builder, setup_node, setup_two_nodes, wait_for_tx, TestChainSource, TestSyncStore, |
15 | 15 | };
|
16 | 16 |
|
17 | 17 | use ldk_node::config::EsploraSyncConfig;
|
| 18 | +use ldk_node::liquidity::LSPS2ServiceConfig; |
18 | 19 | use ldk_node::payment::{
|
19 | 20 | ConfirmationStatus, PaymentDirection, PaymentKind, PaymentStatus, QrPaymentResult,
|
20 | 21 | SendingParameters,
|
@@ -1038,3 +1039,108 @@ fn unified_qr_send_receive() {
|
1038 | 1039 | assert_eq!(node_b.list_balances().total_onchain_balance_sats, 800_000);
|
1039 | 1040 | assert_eq!(node_b.list_balances().total_lightning_balance_sats, 200_000);
|
1040 | 1041 | }
|
| 1042 | + |
| 1043 | +#[test] |
| 1044 | +fn lsps2_client_service_integration() { |
| 1045 | + let (bitcoind, electrsd) = setup_bitcoind_and_electrsd(); |
| 1046 | + |
| 1047 | + let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap()); |
| 1048 | + |
| 1049 | + let mut sync_config = EsploraSyncConfig::default(); |
| 1050 | + sync_config.onchain_wallet_sync_interval_secs = 100000; |
| 1051 | + sync_config.lightning_wallet_sync_interval_secs = 100000; |
| 1052 | + |
| 1053 | + // Setup three nodes: service, client, and payer |
| 1054 | + let channel_opening_fee_ppm = 10_000; |
| 1055 | + let channel_over_provisioning_ppm = 100_000; |
| 1056 | + let lsps2_service_config = LSPS2ServiceConfig { |
| 1057 | + require_token: None, |
| 1058 | + advertise_service: false, |
| 1059 | + channel_opening_fee_ppm, |
| 1060 | + channel_over_provisioning_ppm, |
| 1061 | + max_payment_size_msat: 1_000_000_000, |
| 1062 | + min_payment_size_msat: 0, |
| 1063 | + min_channel_lifetime: 100, |
| 1064 | + min_channel_opening_fee_msat: 0, |
| 1065 | + max_client_to_self_delay: 1024, |
| 1066 | + }; |
| 1067 | + |
| 1068 | + let service_config = random_config(true); |
| 1069 | + setup_builder!(service_builder, service_config); |
| 1070 | + service_builder.set_chain_source_esplora(esplora_url.clone(), Some(sync_config)); |
| 1071 | + service_builder.set_liquidity_provider_lsps2(lsps2_service_config); |
| 1072 | + let service_node = service_builder.build().unwrap(); |
| 1073 | + service_node.start().unwrap(); |
| 1074 | + |
| 1075 | + let service_node_id = service_node.node_id(); |
| 1076 | + let service_addr = service_node.listening_addresses().unwrap().first().unwrap().clone(); |
| 1077 | + |
| 1078 | + let client_config = random_config(true); |
| 1079 | + setup_builder!(client_builder, client_config); |
| 1080 | + client_builder.set_chain_source_esplora(esplora_url.clone(), Some(sync_config)); |
| 1081 | + client_builder.set_liquidity_source_lsps2(service_node_id, service_addr, None); |
| 1082 | + let client_node = client_builder.build().unwrap(); |
| 1083 | + client_node.start().unwrap(); |
| 1084 | + |
| 1085 | + let payer_config = random_config(true); |
| 1086 | + setup_builder!(payer_builder, payer_config); |
| 1087 | + payer_builder.set_chain_source_esplora(esplora_url.clone(), Some(sync_config)); |
| 1088 | + let payer_node = payer_builder.build().unwrap(); |
| 1089 | + payer_node.start().unwrap(); |
| 1090 | + |
| 1091 | + let service_addr = service_node.onchain_payment().new_address().unwrap(); |
| 1092 | + let client_addr = client_node.onchain_payment().new_address().unwrap(); |
| 1093 | + let payer_addr = payer_node.onchain_payment().new_address().unwrap(); |
| 1094 | + |
| 1095 | + let premine_amount_sat = 10_000_000; |
| 1096 | + |
| 1097 | + premine_and_distribute_funds( |
| 1098 | + &bitcoind.client, |
| 1099 | + &electrsd.client, |
| 1100 | + vec![service_addr, client_addr, payer_addr], |
| 1101 | + Amount::from_sat(premine_amount_sat), |
| 1102 | + ); |
| 1103 | + service_node.sync_wallets().unwrap(); |
| 1104 | + client_node.sync_wallets().unwrap(); |
| 1105 | + payer_node.sync_wallets().unwrap(); |
| 1106 | + |
| 1107 | + // Open a channel payer -> service that will allow paying the JIT invoice |
| 1108 | + println!("Opening channel payer_node -> service_node!"); |
| 1109 | + open_channel(&payer_node, &service_node, 5_000_000, false, &electrsd); |
| 1110 | + |
| 1111 | + generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6); |
| 1112 | + service_node.sync_wallets().unwrap(); |
| 1113 | + payer_node.sync_wallets().unwrap(); |
| 1114 | + expect_channel_ready_event!(payer_node, service_node.node_id()); |
| 1115 | + expect_channel_ready_event!(service_node, payer_node.node_id()); |
| 1116 | + |
| 1117 | + let invoice_description = |
| 1118 | + Bolt11InvoiceDescription::Direct(Description::new(String::from("asdf")).unwrap()); |
| 1119 | + let jit_amount_msat = 100_000_000; |
| 1120 | + |
| 1121 | + println!("Generating JIT invoice!"); |
| 1122 | + let jit_invoice = client_node |
| 1123 | + .bolt11_payment() |
| 1124 | + .receive_via_jit_channel(jit_amount_msat, &invoice_description.into(), 1024, None) |
| 1125 | + .unwrap(); |
| 1126 | + |
| 1127 | + // Have the payer_node pay the invoice, therby triggering channel open service_node -> client_node. |
| 1128 | + println!("Paying JIT invoice!"); |
| 1129 | + let payment_id = payer_node.bolt11_payment().send(&jit_invoice, None).unwrap(); |
| 1130 | + expect_channel_pending_event!(service_node, client_node.node_id()); |
| 1131 | + expect_channel_ready_event!(service_node, client_node.node_id()); |
| 1132 | + expect_channel_pending_event!(client_node, service_node.node_id()); |
| 1133 | + expect_channel_ready_event!(client_node, service_node.node_id()); |
| 1134 | + |
| 1135 | + let service_fee_msat = (jit_amount_msat * channel_opening_fee_ppm as u64) / 1_000_000; |
| 1136 | + let expected_received_amount_msat = jit_amount_msat - service_fee_msat; |
| 1137 | + expect_payment_successful_event!(payer_node, Some(payment_id), None); |
| 1138 | + expect_payment_received_event!(client_node, expected_received_amount_msat); |
| 1139 | + |
| 1140 | + let expected_channel_overprovisioning_msat = |
| 1141 | + (expected_received_amount_msat * channel_over_provisioning_ppm as u64) / 1_000_000; |
| 1142 | + let expected_channel_size_sat = |
| 1143 | + (expected_received_amount_msat + expected_channel_overprovisioning_msat) / 1000; |
| 1144 | + let channel_value_sats = client_node.list_channels().first().unwrap().channel_value_sats; |
| 1145 | + assert_eq!(channel_value_sats, expected_channel_size_sat); |
| 1146 | +} |
0 commit comments