Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: bolt12 #370

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0848ad4
feat: pay bolt12 (backends not impl)
thesimplekid Sep 27, 2024
b1b6d4c
feat: phd pay offer
thesimplekid Oct 1, 2024
1c2c7a3
feat: cdk-cli melt bolt12
thesimplekid Oct 1, 2024
880fcc5
chore: update phd-rs
thesimplekid Oct 2, 2024
cd591ab
fix: check phd has valid payment id
thesimplekid Oct 2, 2024
f1494c5
fix: add unknown state to sql
thesimplekid Oct 2, 2024
113a449
feat: cln fetch invoice
thesimplekid Oct 2, 2024
fc046b7
feat: cln pay bolt12
thesimplekid Oct 2, 2024
de6e75e
feat: logging amoints
thesimplekid Oct 3, 2024
0933111
fix: phd fee
thesimplekid Oct 3, 2024
0b1464a
feat: bolt12 mint endpoints
thesimplekid Oct 3, 2024
d249f65
chore: clippy
thesimplekid Oct 4, 2024
bed9543
feat: cln mint via bolt12
thesimplekid Oct 4, 2024
25d8fde
feat: cdk-cli mint bolt12
thesimplekid Oct 4, 2024
98d7489
feat: mint cli
thesimplekid Oct 4, 2024
aa0ccab
feat: bolt12 info
thesimplekid Oct 4, 2024
f364fad
feat: wait any invoice, use offer id
thesimplekid Oct 5, 2024
2ac7c08
feat: add bolt12 router
thesimplekid Oct 6, 2024
bc2d114
feat: add cancel to wait invoice
thesimplekid Oct 6, 2024
590ad0d
feat: nut18/19 settings
thesimplekid Oct 7, 2024
122130e
feat: nut18/19 mint melt settings
thesimplekid Oct 7, 2024
10d8435
refactor: ln backend set up helpers
thesimplekid Oct 8, 2024
b34aa44
refactor: ln routers
thesimplekid Oct 8, 2024
24b637e
fix: rename cdk-mintd bin
thesimplekid Oct 8, 2024
baee4ea
fix: itest kill script
thesimplekid Oct 8, 2024
6bbfd56
feat: mint builder
thesimplekid Oct 8, 2024
54b783a
feat: use mintbuilder
thesimplekid Oct 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions crates/cdk-axum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ pub struct MintState {
}

/// Create mint [`Router`] with required endpoints for cashu mint
pub async fn create_mint_router(mint: Arc<Mint>, cache_ttl: u64, cache_tti: u64) -> Result<Router> {
pub async fn create_mint_router(
mint: Arc<Mint>,
cache_ttl: u64,
cache_tti: u64,
include_bolt12: bool,
) -> Result<Router> {
let state = MintState {
mint,
cache: Cache::builder()
Expand All @@ -33,7 +38,7 @@ pub async fn create_mint_router(mint: Arc<Mint>, cache_ttl: u64, cache_tti: u64)
.build(),
};

let v1_router = Router::new()
let mut v1_router = Router::new()
.route("/keys", get(get_keys))
.route("/keysets", get(get_keysets))
.route("/keys/:keyset_id", get(get_keyset_pubkeys))
Expand All @@ -54,7 +59,32 @@ pub async fn create_mint_router(mint: Arc<Mint>, cache_ttl: u64, cache_tti: u64)
.route("/info", get(get_mint_info))
.route("/restore", post(post_restore));

// Conditionally create and merge bolt12_router
if include_bolt12 {
let bolt12_router = create_bolt12_router(state.clone());
//v1_router = bolt12_router.merge(v1_router);
v1_router = v1_router.merge(bolt12_router);
}

// Nest the combined router under "/v1"
let mint_router = Router::new().nest("/v1", v1_router).with_state(state);

Ok(mint_router)
}

fn create_bolt12_router(state: MintState) -> Router<MintState> {
Router::new()
.route("/melt/quote/bolt12", post(get_melt_bolt12_quote))
.route(
"/melt/quote/bolt12/:quote_id",
get(get_check_melt_bolt11_quote),
)
.route("/melt/bolt12", post(post_melt_bolt12))
.route("/mint/quote/bolt12", post(get_mint_bolt12_quote))
.route(
"/mint/quote/bolt12/:quote_id",
get(get_check_mint_bolt11_quote),
)
.route("/mint/bolt12", post(post_mint_bolt12))
.with_state(state)
}
57 changes: 52 additions & 5 deletions crates/cdk-axum/src/router_handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use axum::response::{IntoResponse, Response};
use cdk::error::ErrorResponse;
use cdk::nuts::{
CheckStateRequest, CheckStateResponse, Id, KeysResponse, KeysetResponse, MeltBolt11Request,
MeltQuoteBolt11Request, MeltQuoteBolt11Response, MintBolt11Request, MintBolt11Response,
MintInfo, MintQuoteBolt11Request, MintQuoteBolt11Response, RestoreRequest, RestoreResponse,
SwapRequest, SwapResponse,
MeltBolt12Request, MeltQuoteBolt11Request, MeltQuoteBolt11Response, MeltQuoteBolt12Request,
MintBolt11Request, MintBolt11Response, MintInfo, MintQuoteBolt11Request,
MintQuoteBolt11Response, RestoreRequest, RestoreResponse, SwapRequest, SwapResponse,
};
use cdk::util::unix_time;
use cdk::Error;
Expand Down Expand Up @@ -92,6 +92,19 @@ pub async fn get_mint_bolt11_quote(
Ok(Json(quote))
}

pub async fn get_mint_bolt12_quote(
State(state): State<MintState>,
Json(payload): Json<MintQuoteBolt11Request>,
) -> Result<Json<MintQuoteBolt11Response>, Response> {
let quote = state
.mint
.get_mint_bolt12_quote(payload)
.await
.map_err(into_response)?;

Ok(Json(quote))
}

pub async fn get_check_mint_bolt11_quote(
State(state): State<MintState>,
Path(quote_id): Path<String>,
Expand Down Expand Up @@ -124,6 +137,22 @@ pub async fn post_mint_bolt11(
Ok(Json(res))
}

pub async fn post_mint_bolt12(
State(state): State<MintState>,
Json(payload): Json<MintBolt11Request>,
) -> Result<Json<MintBolt11Response>, Response> {
let res = state
.mint
.process_mint_request(payload)
.await
.map_err(|err| {
tracing::error!("Could not process mint: {}", err);
into_response(err)
})?;

Ok(Json(res))
}

pub async fn get_melt_bolt11_quote(
State(state): State<MintState>,
Json(payload): Json<MeltQuoteBolt11Request>,
Expand Down Expand Up @@ -157,12 +186,30 @@ pub async fn post_melt_bolt11(
State(state): State<MintState>,
Json(payload): Json<MeltBolt11Request>,
) -> Result<Json<MeltQuoteBolt11Response>, Response> {
let res = state
let res = state.mint.melt(&payload).await.map_err(into_response)?;

Ok(Json(res))
}

pub async fn get_melt_bolt12_quote(
State(state): State<MintState>,
Json(payload): Json<MeltQuoteBolt12Request>,
) -> Result<Json<MeltQuoteBolt11Response>, Response> {
let quote = state
.mint
.melt_bolt11(&payload)
.get_melt_bolt12_quote(&payload)
.await
.map_err(into_response)?;

Ok(Json(quote))
}

pub async fn post_melt_bolt12(
State(state): State<MintState>,
Json(payload): Json<MeltBolt12Request>,
) -> Result<Json<MeltQuoteBolt11Response>, Response> {
let res = state.mint.melt(&payload).await.map_err(into_response)?;

Ok(Json(res))
}

Expand Down
2 changes: 1 addition & 1 deletion crates/cdk-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ enum Commands {
#[tokio::main]
async fn main() -> Result<()> {
let args: Cli = Cli::parse();
let default_filter = args.log_level;
let default_filter = "debug";
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set this back to arg


let sqlx_filter = "sqlx=warn";

Expand Down
49 changes: 35 additions & 14 deletions crates/cdk-cli/src/sub_commands/melt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ use std::io::Write;
use std::str::FromStr;

use anyhow::{bail, Result};
use cdk::nuts::CurrencyUnit;
use cdk::amount::Amount;
use cdk::nuts::{CurrencyUnit, PaymentMethod};
use cdk::wallet::multi_mint_wallet::{MultiMintWallet, WalletKey};
use cdk::Bolt11Invoice;
// use cdk::Bolt11Invoice;
use clap::Args;

use crate::sub_commands::balance::mint_balances;
Expand All @@ -15,13 +16,19 @@ pub struct MeltSubCommand {
/// Currency unit e.g. sat
#[arg(default_value = "sat")]
unit: String,
/// Payment method
#[arg(short, long, default_value = "bolt11")]
method: String,
/// Amount
#[arg(short, long)]
amount: Option<u64>,
}

pub async fn pay(
multi_mint_wallet: &MultiMintWallet,
sub_command_args: &MeltSubCommand,
) -> Result<()> {
let unit = CurrencyUnit::from_str(&sub_command_args.unit)?;
let unit = CurrencyUnit::from_str(&sub_command_args.unit).unwrap();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove unwrap

let mints_amounts = mint_balances(multi_mint_wallet, &unit).await?;

println!("Enter mint number to melt from");
Expand All @@ -44,22 +51,36 @@ pub async fn pay(
.await
.expect("Known wallet");

println!("Enter bolt11 invoice request");
let method = PaymentMethod::from_str(&sub_command_args.method)?;
match method {
PaymentMethod::Bolt11 => {
println!("Enter bolt11 invoice request");
}
PaymentMethod::Bolt12 => {
println!("Enter bolt12 invoice request");
}
_ => panic!("Unknown payment method"),
}

let mut user_input = String::new();
let stdin = io::stdin();
io::stdout().flush().unwrap();
stdin.read_line(&mut user_input)?;
let bolt11 = Bolt11Invoice::from_str(user_input.trim())?;

if bolt11
.amount_milli_satoshis()
.unwrap()
.gt(&(<cdk::Amount as Into<u64>>::into(mints_amounts[mint_number].1) * 1000_u64))
{
bail!("Not enough funds");
}
let quote = wallet.melt_quote(bolt11.to_string(), None).await?;

let quote = match method {
PaymentMethod::Bolt11 => {
wallet
.melt_quote(user_input.trim().to_string(), None)
.await?
}
PaymentMethod::Bolt12 => {
let amount = sub_command_args.amount.map(Amount::from);
wallet
.melt_bolt12_quote(user_input.trim().to_string(), amount)
.await?
}
_ => panic!("Unsupported payment methof"),
};

println!("{:?}", quote);

Expand Down
26 changes: 21 additions & 5 deletions crates/cdk-cli/src/sub_commands/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use anyhow::Result;
use cdk::amount::SplitTarget;
use cdk::cdk_database::{Error, WalletDatabase};
use cdk::mint_url::MintUrl;
use cdk::nuts::{CurrencyUnit, MintQuoteState};
use cdk::nuts::{CurrencyUnit, MintQuoteState, PaymentMethod};
use cdk::wallet::multi_mint_wallet::WalletKey;
use cdk::wallet::{MultiMintWallet, Wallet};
use cdk::Amount;
Expand All @@ -21,8 +21,11 @@ pub struct MintSubCommand {
/// Amount
amount: u64,
/// Currency unit e.g. sat
#[arg(default_value = "sat")]
#[arg(short, long, default_value = "sat")]
unit: String,
/// Payment method
#[arg(long, default_value = "bolt11")]
method: String,
/// Quote description
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
Expand Down Expand Up @@ -51,9 +54,22 @@ pub async fn mint(
}
};

let quote = wallet
.mint_quote(Amount::from(sub_command_args.amount), description)
.await?;
let method = PaymentMethod::from_str(&sub_command_args.method)?;

let quote = match method {
PaymentMethod::Bolt11 => {
println!("Bolt11");
wallet
.mint_quote(Amount::from(sub_command_args.amount), description)
.await?
}
PaymentMethod::Bolt12 => {
wallet
.mint_bolt12_quote(Amount::from(sub_command_args.amount), description)
.await?
}
_ => panic!("Unsupported unit"),
};

println!("Quote: {:#?}", quote);

Expand Down
1 change: 1 addition & 0 deletions crates/cdk-cln/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ async-trait = "0.1"
bitcoin = { version = "0.32.2", default-features = false }
cdk = { path = "../cdk", version = "0.4.0", default-features = false, features = ["mint"] }
cln-rpc = "0.2.0"
lightning = { version = "0.0.124", default-features = false, features = ["std"]}
futures = { version = "0.3.28", default-features = false }
tokio = { version = "1", default-features = false }
tokio-util = { version = "0.7.11", default-features = false }
Expand Down
3 changes: 3 additions & 0 deletions crates/cdk-cln/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ pub enum Error {
/// Invalid payment hash
#[error("Invalid hash")]
InvalidHash,
/// Wrong payment type
#[error("Wrong payment type")]
WrongPaymentType,
/// Cln Error
#[error(transparent)]
Cln(#[from] cln_rpc::Error),
Expand Down
Loading
Loading