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