Skip to main content

lnv1_lnv2_swap_tests/
swap_tests.rs

1use 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}