Skip to content

Commit

Permalink
feat: phoenixd ln backend
Browse files Browse the repository at this point in the history
  • Loading branch information
thesimplekid committed Aug 16, 2024
1 parent 4a76481 commit 1e4babe
Show file tree
Hide file tree
Showing 17 changed files with 449 additions and 16 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ jobs:
-p cdk-sqlite,
-p cdk-axum,
-p cdk-cln,
-p cdk-fake-wallet,
-p cdk-phoenixd,
-p cdk-strike,
-p cdk-fake-wallet,
--bin cdk-cli,
--bin cdk-mintd,
--examples
]
steps:
- name: Checkout
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ cdk-rexie = { version = "0.3", path = "./crates/cdk-rexie", default-features = f
cdk-sqlite = { version = "0.3", path = "./crates/cdk-sqlite", default-features = false }
cdk-redb = { version = "0.3", path = "./crates/cdk-redb", default-features = false }
cdk-cln = { version = "0.3", path = "./crates/cdk-cln", default-features = false }
cdk-phoenixd = { version = "0.3", path = "./crates/cdk-phoenixd", default-features = false }
cdk-axum = { version = "0.3", path = "./crates/cdk-axum", default-features = false }
cdk-fake-wallet = { version = "0.3", path = "./crates/cdk-fake-wallet", default-features = false }
cdk-strike = { version = "0.3", path = "./crates/cdk-strike", default-features = false }
Expand Down
2 changes: 1 addition & 1 deletion crates/cdk-axum/src/router_handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ pub async fn get_melt_bolt11_quote(
payload.request.to_string(),
payload.unit,
payment_quote.amount,
payment_quote.fee.into(),
payment_quote.fee,
unix_time() + state.quote_ttl,
payment_quote.request_lookup_id,
)
Expand Down
5 changes: 3 additions & 2 deletions crates/cdk-cln/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub struct Cln {
}

impl Cln {
/// Create new ['Cln]
/// Create new [`Cln`]
pub async fn new(
rpc_socket: PathBuf,
fee_reserve: FeeReserve,
Expand Down Expand Up @@ -144,7 +144,8 @@ impl MintLightning for Cln {
Ok(PaymentQuoteResponse {
request_lookup_id: melt_quote_request.request.payment_hash().to_string(),
amount,
fee,
fee: fee.into(),
state: MeltQuoteState::Unpaid,
})
}

Expand Down
3 changes: 2 additions & 1 deletion crates/cdk-fake-wallet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ impl MintLightning for FakeWallet {
Ok(PaymentQuoteResponse {
request_lookup_id: melt_quote_request.request.payment_hash().to_string(),
amount,
fee,
fee: fee.into(),
state: MeltQuoteState::Unpaid,
})
}

Expand Down
2 changes: 2 additions & 0 deletions crates/cdk-mintd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ cdk = { workspace = true, default-features = false, features = ["mint"] }
cdk-redb = { workspace = true, default-features = false, features = ["mint"] }
cdk-sqlite = { workspace = true, default-features = false, features = ["mint"] }
cdk-cln = { workspace = true, default-features = false }
cdk-phoenixd = { workspace = true, default-features = false }
cdk-fake-wallet = { workspace = true, default-features = false }
cdk-strike.workspace = true
cdk-axum = { workspace = true, default-features = false }
Expand All @@ -30,3 +31,4 @@ bip39.workspace = true
tower-http = { version = "0.5.2", features = ["cors"] }
lightning-invoice.workspace = true
home.workspace = true
url.workspace = true
4 changes: 4 additions & 0 deletions crates/cdk-mintd/example.config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,7 @@ ln_backend = "cln"
# api_key=""
# Optional default sats
# supported_units=[""]

# [phoenixd]
# api_password = ""
# api_url = ""
11 changes: 9 additions & 2 deletions crates/cdk-mintd/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ pub enum LnBackend {
Cln,
Strike,
FakeWallet,
// Greenlight,
// Ldk,
Phoenixd,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
Expand All @@ -45,6 +44,12 @@ pub struct Cln {
pub rpc_path: PathBuf,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Phoenixd {
pub api_password: String,
pub api_url: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FakeWallet {
pub supported_units: Vec<CurrencyUnit>,
Expand Down Expand Up @@ -78,6 +83,7 @@ pub struct Settings {
pub ln: Ln,
pub cln: Option<Cln>,
pub strike: Option<Strike>,
pub phoenixd: Option<Phoenixd>,
pub fake_wallet: Option<FakeWallet>,
pub database: Database,
}
Expand Down Expand Up @@ -143,6 +149,7 @@ impl Settings {
LnBackend::Cln => assert!(settings.cln.is_some()),
LnBackend::FakeWallet => (),
LnBackend::Strike => assert!(settings.strike.is_some()),
LnBackend::Phoenixd => assert!(settings.phoenixd.is_some()),
}

Ok(settings)
Expand Down
61 changes: 56 additions & 5 deletions crates/cdk-mintd/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::path::PathBuf;
use std::str::FromStr;
use std::sync::Arc;

use anyhow::{anyhow, Result};
use anyhow::{anyhow, bail, Result};
use axum::Router;
use bip39::Mnemonic;
use cdk::cdk_database::{self, MintDatabase};
Expand All @@ -22,6 +22,7 @@ use cdk::nuts::{
use cdk_axum::LnKey;
use cdk_cln::Cln;
use cdk_fake_wallet::FakeWallet;
use cdk_phoenixd::Phoenixd;
use cdk_redb::MintRedbDatabase;
use cdk_sqlite::MintSqliteDatabase;
use cdk_strike::Strike;
Expand All @@ -32,6 +33,7 @@ use futures::StreamExt;
use tokio::sync::Mutex;
use tower_http::cors::CorsLayer;
use tracing_subscriber::EnvFilter;
use url::Url;

mod cli;
mod config;
Expand Down Expand Up @@ -82,8 +84,8 @@ async fn main() -> anyhow::Result<()> {

let mut contact_info: Option<Vec<ContactInfo>> = None;

if let Some(nostr_contact) = settings.mint_info.contact_nostr_public_key {
let nostr_contact = ContactInfo::new("nostr".to_string(), nostr_contact);
if let Some(nostr_contact) = &settings.mint_info.contact_nostr_public_key {
let nostr_contact = ContactInfo::new("nostr".to_string(), nostr_contact.to_string());

contact_info = match contact_info {
Some(mut vec) => {
Expand All @@ -94,8 +96,8 @@ async fn main() -> anyhow::Result<()> {
};
}

if let Some(email_contact) = settings.mint_info.contact_email {
let email_contact = ContactInfo::new("email".to_string(), email_contact);
if let Some(email_contact) = &settings.mint_info.contact_email {
let email_contact = ContactInfo::new("email".to_string(), email_contact.to_string());

contact_info = match contact_info {
Some(mut vec) => {
Expand Down Expand Up @@ -194,6 +196,55 @@ async fn main() -> anyhow::Result<()> {

routers
}
LnBackend::Phoenixd => {
let api_password = settings
.clone()
.phoenixd
.expect("Checked at config load")
.api_password;

let api_url = settings
.clone()
.phoenixd
.expect("Checked at config load")
.api_url;
if fee_reserve.percent_fee_reserve < 2.0 {
bail!("Fee reserve is too low");
}

let webhook_endpoint = "/webhook/phoenixd";

let mint_url = Url::parse(&settings.info.url)?;

let webhook_url = mint_url.join(webhook_endpoint)?.to_string();

let (sender, receiver) = tokio::sync::mpsc::channel(8);

let phoenixd = Phoenixd::new(
api_password.to_string(),
api_url.to_string(),
MintMeltSettings::default(),
MintMeltSettings::default(),
fee_reserve,
Arc::new(Mutex::new(Some(receiver))),
webhook_url,
)?;

let router = phoenixd
.create_invoice_webhook(webhook_endpoint, sender)
.await?;

supported_units.insert(CurrencyUnit::Sat, (input_fee_ppk, 64));
ln_backends.insert(
LnKey {
unit: CurrencyUnit::Sat,
method: PaymentMethod::Bolt11,
},
Arc::new(phoenixd),
);

vec![router]
}
LnBackend::FakeWallet => {
let units = settings.fake_wallet.unwrap_or_default().supported_units;

Expand Down
24 changes: 24 additions & 0 deletions crates/cdk-phoenixd/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "cdk-phoenixd"
version = { workspace = true }
edition = "2021"
authors = ["CDK Developers"]
homepage.workspace = true
repository.workspace = true
rust-version.workspace = true # MSRV
license.workspace = true
description = "CDK ln backend for phoenixd"

[dependencies]
async-trait.workspace = true
anyhow.workspace = true
axum.workspace = true
bitcoin.workspace = true
cdk = { workspace = true, default-features = false, features = ["mint"] }
futures.workspace = true
tokio.workspace = true
tracing.workspace = true
thiserror.workspace = true
phoenixd-rs = "0.2.0"
# phoenixd-rs = { path = "../../../../phoenixd-rs" }
uuid.workspace = true
46 changes: 46 additions & 0 deletions crates/cdk-phoenixd/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# cdk-phoenixd

## Run phoenixd

The `phoenixd` node is included in the cdk and needs to be run separately.
Get started here: [Phoenixd Server Documentation](https://phoenix.acinq.co/server/get-started)

## Start Phoenixd

By default, `phoenixd` will run with auto-liquidity enabled. While this simplifies channel management, it makes fees non-deterministic, which is not recommended for most scenarios. However, it is necessary to start with auto-liquidity enabled in order to open a channel and get started.

Start the node with auto-liquidity enabled as documented by [Phoenixd](https://phoenix.acinq.co/server/get-started):
```sh
./phoenixd
```

> **Note:** By default the `auto-liquidity` will open a channel of 2m sats depending on the size of mint you plan to run you may want to increase this by setting the `--auto-liquidity` flag to `5m` or `10m`.
## Open Channel

Once the node is running, create an invoice using the phoenixd-cli to fund your node. A portion of this deposit will go to ACINQ as a fee for the provided liquidity, and a portion will cover the mining fee. These two fees cannot be refunded or withdrawn from the node. More on fees can be found [here](https://phoenix.acinq.co/server/auto-liquidity#fees). The remainder will stay as the node balance and can be withdrawn later.
```sh
./phoenix-cli createinvoice \
--description "Fund Node" \
--amountSat 30000
```

> **Note:** The required funds to set up a node could could be greater if on-chain fees are high.
## Check Channel state

After paying the invoice view that a channal has been opened.
```sh
./phoenix-cli listchannels
```

## Restart Phoenixd without `auto-liquidity`

Now that the node has a channel, it is recommended to stop the node and restart it without auto-liquidity. This will prevent phoenixd from opening new channels and incurring additional fees.
```sh
./phoenixd --auto-liquidity off
```

## Start cashu-mintd

Once the node is running following the [cashu-mintd](../cdk-mintd/README.md) to start the mint. by default the `api_url` will be `http://127.0.0.1:9740` and the `api_password` can be found in `~/.phoenix/phoenix.conf` these will need to be set in the `cdk-mintd` config file.
26 changes: 26 additions & 0 deletions crates/cdk-phoenixd/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//! Error for phoenixd ln backend
use thiserror::Error;

/// Phoenixd Error
#[derive(Debug, Error)]
pub enum Error {
/// Invoice amount not defined
#[error("Unknown invoice amount")]
UnknownInvoiceAmount,
/// Unknown invoice
#[error("Unknown invoice")]
UnknownInvoice,
/// Unsupported unit
#[error("Unit Unsupported")]
UnsupportedUnit,
/// Anyhow error
#[error(transparent)]
Anyhow(#[from] anyhow::Error),
}

impl From<Error> for cdk::cdk_lightning::Error {
fn from(e: Error) -> Self {
Self::Lightning(Box::new(e))
}
}
Loading

0 comments on commit 1e4babe

Please sign in to comment.