Skip to content

Commit

Permalink
feat: lnd payment processor tests
Browse files Browse the repository at this point in the history
  • Loading branch information
thesimplekid committed Feb 23, 2025
1 parent 039a6e1 commit 97987de
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 63 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
build-args:
ln:
[
-p cdk-integration-tests,
FAKEWALLET,
CLN,
LND
]
steps:
- name: checkout
Expand All @@ -217,7 +219,7 @@ jobs:
- name: Rust Cache
uses: Swatinem/rust-cache@v2
- name: Test
run: nix develop -i -L .#stable --command just itest-payment-processor
run: nix develop -i -L .#stable --command just itest-payment-processor ${{matrix.ln}}

msrv-build:
name: "MSRV build"
Expand Down
43 changes: 30 additions & 13 deletions crates/cdk-integration-tests/tests/payment_processor.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Tests where we expect the payment processor to respond with an error or pass
use std::env;
use std::sync::Arc;

use anyhow::{bail, Result};
Expand All @@ -9,6 +10,7 @@ use cdk::cdk_database::WalletMemoryDatabase;
use cdk::nuts::nut00::ProofsMethods;
use cdk::nuts::CurrencyUnit;
use cdk::wallet::Wallet;
use cdk_fake_wallet::create_fake_invoice;
use cdk_integration_tests::init_regtest::{get_lnd_dir, get_mint_url, LND_RPC_ADDR};
use cdk_integration_tests::wait_for_mint_to_be_paid;
use ln_regtest_rs::ln_client::{LightningClient, LndClient};
Expand All @@ -29,8 +31,6 @@ async fn init_lnd_client() -> LndClient {

#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn test_regtest_mint() -> Result<()> {
let lnd_client = init_lnd_client().await;

let wallet = Wallet::new(
&get_mint_url("0"),
CurrencyUnit::Sat,
Expand All @@ -45,7 +45,13 @@ async fn test_regtest_mint() -> Result<()> {

assert_eq!(mint_quote.amount, mint_amount);

lnd_client.pay_invoice(mint_quote.request).await?;
let ln_backend = env::var("LN_BACKEND")?;

if ln_backend != "FAKEWALLET" {
let lnd_client = init_lnd_client().await;

lnd_client.pay_invoice(mint_quote.request).await?;
}

wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60).await?;

Expand All @@ -62,8 +68,6 @@ async fn test_regtest_mint() -> Result<()> {

#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn test_regtest_mint_melt() -> Result<()> {
let lnd_client = init_lnd_client().await;

let wallet = Wallet::new(
&get_mint_url("0"),
CurrencyUnit::Sat,
Expand All @@ -78,7 +82,12 @@ async fn test_regtest_mint_melt() -> Result<()> {

assert_eq!(mint_quote.amount, mint_amount);

lnd_client.pay_invoice(mint_quote.request).await?;
let ln_backend = env::var("LN_BACKEND")?;
if ln_backend != "FAKEWALLET" {
let lnd_client = init_lnd_client().await;

lnd_client.pay_invoice(mint_quote.request).await?;
}

wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60).await?;

Expand All @@ -90,7 +99,12 @@ async fn test_regtest_mint_melt() -> Result<()> {

assert!(mint_amount == 100.into());

let invoice = lnd_client.create_invoice(Some(50)).await?;
let invoice = if ln_backend != "FAKEWALLET" {
let lnd_client = init_lnd_client().await;
lnd_client.create_invoice(Some(50)).await?
} else {
create_fake_invoice(50000, "".to_string()).to_string()
};

let melt_quote = wallet.melt_quote(invoice, None).await?;

Expand All @@ -101,7 +115,11 @@ async fn test_regtest_mint_melt() -> Result<()> {

#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn test_pay_invoice_twice() -> Result<()> {
let lnd_client = init_lnd_client().await;
let ln_backend = env::var("LN_BACKEND")?;
if ln_backend == "FAKEWALLET" {
// We can only preform this test on regtest backends as fake wallet just marks the quote as paid
return Ok(());
}

let seed = Mnemonic::generate(12)?.to_seed_normalized("");
let wallet = Wallet::new(
Expand All @@ -114,10 +132,9 @@ async fn test_pay_invoice_twice() -> Result<()> {

let mint_quote = wallet.mint_quote(100.into(), None).await?;

lnd_client
.pay_invoice(mint_quote.request)
.await
.expect("Could not pay invoice");
let lnd_client = init_lnd_client().await;

lnd_client.pay_invoice(mint_quote.request).await?;

wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60).await?;

Expand All @@ -129,7 +146,7 @@ async fn test_pay_invoice_twice() -> Result<()> {

assert_eq!(mint_amount, 100.into());

let invoice = lnd_client.create_invoice(Some(10)).await?;
let invoice = lnd_client.create_invoice(Some(25)).await?;

let melt_quote = wallet.melt_quote(invoice.clone(), None).await?;

Expand Down
4 changes: 3 additions & 1 deletion crates/cdk-payment-processor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ name = "cdk-payment-processor"
path = "src/bin/payment_processor.rs"

[features]
default = ["cln", "fake"]
default = ["cln", "fake", "lnd"]
bench = []
cln = ["dep:cdk-cln"]
fake = ["dep:cdk-fake-wallet"]
lnd = ["dep:cdk-lnd"]

[dependencies]
anyhow = "1.0"
Expand All @@ -30,6 +31,7 @@ bitcoin = { version = "0.32.2", features = [
] }
cdk-common = { path = "../cdk-common", default-features = false, version = "0.7.1", features = ["mint"] }
cdk-cln = { path = "../cdk-cln", default-features = false, version = "0.7.1", optional = true }
cdk-lnd = { path = "../cdk-lnd", default-features = false, version = "0.7.1", optional = true }
cdk-fake-wallet = { path = "../cdk-fake-wallet", default-features = false, version = "0.7.1", optional = true }
serde = { version = "1", features = ["derive"] }
thiserror = "2"
Expand Down
84 changes: 71 additions & 13 deletions crates/cdk-payment-processor/src/bin/payment_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ pub const ENV_PAYMENT_PROCESSOR_TLS_DIR: &str = "CDK_PAYMENT_PROCESSOR_TLS_DIR";
// CLN
pub const ENV_CLN_RPC_PATH: &str = "CDK_PAYMENT_PROCESSOR_CLN_RPC_PATH";
pub const ENV_CLN_BOLT12: &str = "CDK_PAYMENT_PROCESSOR_CLN_BOLT12";
pub const ENV_CLN_FEE_PERCENT: &str = "CDK_PAYMENT_PROCESSOR_CLN_FEE_PERCENT";
pub const ENV_CLN_RESERVE_FEE_MIN: &str = "CDK_PAYMENT_PROCESSOR_CLN_RESERVE_FEE_MIN";

pub const ENV_FEE_PERCENT: &str = "CDK_PAYMENT_PROCESSOR_FEE_PERCENT";
pub const ENV_RESERVE_FEE_MIN: &str = "CDK_PAYMENT_PROCESSOR_RESERVE_FEE_MIN";

// LND environment variables
pub const ENV_LND_ADDRESS: &str = "CDK_PAYMENT_PROCESSOR_LND_ADDRESS";
pub const ENV_LND_CERT_FILE: &str = "CDK_PAYMENT_PROCESSOR_LND_CERT_FILE";
pub const ENV_LND_MACAROON_FILE: &str = "CDK_PAYMENT_PROCESSOR_LND_MACAROON_FILE";

#[tokio::main]
async fn main() -> anyhow::Result<()> {
Expand All @@ -47,7 +53,7 @@ async fn main() -> anyhow::Result<()> {
.map(PathBuf::from);

let ln_backed: Arc<dyn MintPayment<Err = payment::Error> + Send + Sync> =
match ln_backend.as_str() {
match ln_backend.to_uppercase().as_str() {
#[cfg(feature = "cln")]
"CLN" => {
let cln_settings = Cln::default().from_env();
Expand All @@ -56,15 +62,9 @@ async fn main() -> anyhow::Result<()> {
percent_fee_reserve: cln_settings.fee_percent,
};

println!("{}", cln_settings.rpc_path.display());

Arc::new(
cdk_cln::Cln::new(cln_settings.rpc_path, fee_reserve)
.await
.expect("Could not create cln"),
)
Arc::new(cdk_cln::Cln::new(cln_settings.rpc_path, fee_reserve).await?)
}
"fakewallet" => {
"FAKEWALLET" => {
let fee_reserve = FeeReserve {
min_fee_reserve: 1.into(),
percent_fee_reserve: 0.0,
Expand All @@ -75,6 +75,25 @@ async fn main() -> anyhow::Result<()> {

Arc::new(fake_wallet)
}
#[cfg(feature = "lnd")]
"LND" => {
let lnd_settings = Lnd::default().from_env();
let fee_reserve = FeeReserve {
min_fee_reserve: lnd_settings.reserve_fee_min,
percent_fee_reserve: lnd_settings.fee_percent,
};

Arc::new(
cdk_lnd::Lnd::new(
lnd_settings.address,
lnd_settings.cert_file,
lnd_settings.macaroon_file,
fee_reserve,
)
.await?,
)
}

_ => {
bail!("Unknown payment processor");
}
Expand Down Expand Up @@ -117,14 +136,53 @@ impl Cln {
}

// Fee percent
if let Ok(fee_str) = env::var(ENV_CLN_FEE_PERCENT) {
if let Ok(fee_str) = env::var(ENV_FEE_PERCENT) {
if let Ok(fee) = fee_str.parse() {
self.fee_percent = fee;
}
}

// Reserve fee minimum
if let Ok(reserve_fee_str) = env::var(ENV_CLN_RESERVE_FEE_MIN) {
if let Ok(reserve_fee_str) = env::var(ENV_RESERVE_FEE_MIN) {
if let Ok(reserve_fee) = reserve_fee_str.parse::<u64>() {
self.reserve_fee_min = reserve_fee.into();
}
}

self
}
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Lnd {
pub address: String,
pub cert_file: PathBuf,
pub macaroon_file: PathBuf,
pub fee_percent: f32,
pub reserve_fee_min: Amount,
}

impl Lnd {
pub fn from_env(mut self) -> Self {
if let Ok(address) = env::var(ENV_LND_ADDRESS) {
self.address = address;
}

if let Ok(cert_path) = env::var(ENV_LND_CERT_FILE) {
self.cert_file = PathBuf::from(cert_path);
}

if let Ok(macaroon_path) = env::var(ENV_LND_MACAROON_FILE) {
self.macaroon_file = PathBuf::from(macaroon_path);
}

if let Ok(fee_str) = env::var(ENV_FEE_PERCENT) {
if let Ok(fee) = fee_str.parse() {
self.fee_percent = fee;
}
}

if let Ok(reserve_fee_str) = env::var(ENV_RESERVE_FEE_MIN) {
if let Ok(reserve_fee) = reserve_fee_str.parse::<u64>() {
self.reserve_fee_min = reserve_fee.into();
}
Expand Down
66 changes: 35 additions & 31 deletions misc/mintd_payment_processor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ trap cleanup EXIT
export cdk_itests=$(mktemp -d)
export cdk_itests_mint_addr="127.0.0.1";
export cdk_itests_mint_port_0=8086;
export cdk_itests_mint_port_1=8087;


export LN_BACKEND="$1";

URL="http://$cdk_itests_mint_addr:$cdk_itests_mint_port_0/v1/info"
# Check if the temporary directory was created successfully
Expand All @@ -47,43 +49,46 @@ echo "Temp directory created: $cdk_itests"
export MINT_DATABASE="$1";

cargo build -p cdk-integration-tests
cargo run --bin start_regtest &
cdk_regtest_pid=$!


mkfifo "$cdk_itests/progress_pipe"
rm -f "$cdk_itests/signal_received" # Ensure clean state

# Start reading from pipe in background
(while read line; do
case "$line" in
"checkpoint1")
echo "Reached first checkpoint"
touch "$cdk_itests/signal_received"
exit 0
;;
esac
done < "$cdk_itests/progress_pipe") &

# Wait for up to 120 seconds
for ((i=0; i<120; i++)); do
if [ -f "$cdk_itests/signal_received" ]; then
echo "break signal received"
break
fi
sleep 1
done
echo "Regtest set up continuing"


if [ "$LN_BACKEND" != "FAKEWALLET" ]; then
cargo run --bin start_regtest &
cdk_regtest_pid=$!
mkfifo "$cdk_itests/progress_pipe"
rm -f "$cdk_itests/signal_received" # Ensure clean state
# Start reading from pipe in background
(while read line; do
case "$line" in
"checkpoint1")
echo "Reached first checkpoint"
touch "$cdk_itests/signal_received"
exit 0
;;
esac
done < "$cdk_itests/progress_pipe") &
# Wait for up to 120 seconds
for ((i=0; i<120; i++)); do
if [ -f "$cdk_itests/signal_received" ]; then
echo "break signal received"
break
fi
sleep 1
done
echo "Regtest set up continuing"
fi

# Start payment processor


export CDK_PAYMENT_PROCESSOR_CLN_RPC_PATH="$cdk_itests/cln/one/regtest/lightning-rpc";
export CDK_PAYMENT_PROCESSOR_LN_BACKEND="CLN";

export CDK_PAYMENT_PROCESSOR_LND_ADDRESS="https://localhost:10010";
export CDK_PAYMENT_PROCESSOR_LND_CERT_FILE="$cdk_itests/lnd/two/tls.cert";
export CDK_PAYMENT_PROCESSOR_LND_MACAROON_FILE="$cdk_itests/lnd/two/data/chain/bitcoin/regtest/admin.macaroon";

export CDK_PAYMENT_PROCESSOR_LN_BACKEND=$LN_BACKEND;
export CDK_PAYMENT_PROCESSOR_LISTEN_HOST="127.0.0.1";
export CDK_PAYMENT_PROCESSOR_LISTEN_PORT="8090";
# export CDK_PAYMENT_PROCESSOR_TLS_DIR="";

echo "$CDK_PAYMENT_PROCESSOR_CLN_RPC_PATH"

Expand All @@ -93,7 +98,6 @@ cdk_payment_processor_pid=$!

sleep 10;


export CDK_MINTD_URL="http://$cdk_itests_mint_addr:$cdk_itests_mint_port_0";
export CDK_MINTD_WORK_DIR="$cdk_itests";
export CDK_MINTD_LISTEN_HOST=$cdk_itests_mint_addr;
Expand Down
4 changes: 2 additions & 2 deletions misc/test.just
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fake-mint-itest db:
./misc/fake_itests.sh "{{db}}"

itest-payment-processor:
itest-payment-processor ln:
#!/usr/bin/env bash
./misc/mintd_payment_processor.sh
./misc/mintd_payment_processor.sh "{{ln}}"

0 comments on commit 97987de

Please sign in to comment.