lnv1_lnv2_swap_tests/
swap_tests.rs1use devimint::federation::Client;
2use devimint::version_constants::VERSION_0_9_0_ALPHA;
3use devimint::{cmd, util};
4use fedimint_core::core::OperationId;
5use fedimint_lnv2_client::FinalSendOperationState;
6use lightning_invoice::Bolt11Invoice;
7use tracing::info;
8
9#[path = "common.rs"]
10mod common;
11
12#[tokio::main]
13async fn main() -> anyhow::Result<()> {
14 devimint::run_devfed_test()
15 .call(|dev_fed, _process_mgr| async move {
16 if !util::supports_lnv2() {
17 info!("lnv2 is disabled, skipping");
18 return Ok(());
19 }
20
21 let federation = dev_fed.fed().await?;
22
23 let client = federation
24 .new_joined_client("lnv1-lnv2-swap-test-client")
25 .await?;
26
27 federation.pegin_client(10_000, &client).await?;
28
29 let gw_lnd = dev_fed.gw_lnd().await?;
30
31 let gatewayd_version = util::Gatewayd::version_or_default().await;
32 let gateway_cli_version = util::GatewayCli::version_or_default().await;
33
34 if gatewayd_version < *VERSION_0_9_0_ALPHA || gateway_cli_version < *VERSION_0_9_0_ALPHA
35 {
36 info!("Gateway version too old for swap tests, skipping");
37 return Ok(());
38 }
39
40 info!("Pegging-in gateway...");
41 federation.pegin_gateways(1_000_000, vec![gw_lnd]).await?;
42
43 info!("Testing LNv1 client can pay LNv2 invoice...");
44 let lnd_gw_id = gw_lnd.gateway_id.clone();
45 let (invoice, receive_op) = common::receive(&client, &gw_lnd.addr, 1_000_000).await?;
46 send_lnv1(&client, &lnd_gw_id, &invoice.to_string()).await?;
47 common::await_receive_claimed(&client, receive_op).await?;
48
49 info!("Testing LNv2 client can pay LNv1 invoice...");
50 let (invoice, receive_op) = receive_lnv1(&client, &lnd_gw_id, 1_000_000).await?;
51 common::send(
52 &client,
53 &gw_lnd.addr,
54 &invoice.to_string(),
55 FinalSendOperationState::Success,
56 )
57 .await?;
58 await_receive_lnv1(&client, receive_op).await?;
59
60 info!("LNv1 <-> LNv2 swap tests complete!");
61
62 Ok(())
63 })
64 .await
65}
66
67async fn receive_lnv1(
68 client: &Client,
69 gateway_id: &String,
70 amount_msats: u64,
71) -> anyhow::Result<(Bolt11Invoice, OperationId)> {
72 let invoice_response = cmd!(
73 client,
74 "module",
75 "ln",
76 "invoice",
77 amount_msats,
78 "--gateway-id",
79 gateway_id
80 )
81 .out_json()
82 .await?;
83 let invoice = serde_json::from_value::<Bolt11Invoice>(
84 invoice_response
85 .get("invoice")
86 .expect("Invoice should be present")
87 .clone(),
88 )?;
89 let operation_id = serde_json::from_value::<OperationId>(
90 invoice_response
91 .get("operation_id")
92 .expect("OperationId should be present")
93 .clone(),
94 )?;
95 Ok((invoice, operation_id))
96}
97
98async fn send_lnv1(client: &Client, gateway_id: &str, invoice: &str) -> anyhow::Result<()> {
99 let payment_result = cmd!(
100 client,
101 "module",
102 "ln",
103 "pay",
104 invoice,
105 "--gateway-id",
106 gateway_id
107 )
108 .out_json()
109 .await?;
110 assert!(
111 payment_result.get("Success").is_some() || payment_result.get("preimage").is_some(),
112 "LNv1 payment failed: {payment_result:?}"
113 );
114 Ok(())
115}
116
117async fn await_receive_lnv1(client: &Client, operation_id: OperationId) -> anyhow::Result<()> {
118 let lnv1_response = cmd!(client, "await-invoice", operation_id.fmt_full())
119 .out_json()
120 .await?;
121 assert!(lnv1_response.get("total_amount_msat").is_some());
122 Ok(())
123}