@@ -31,6 +31,8 @@ use cdk::{Amount as CdkAmount, StreamExt};
3131
3232use graduated_rebalancer:: ReceivedLightningPayment ;
3333
34+ #[ cfg( feature = "npubcash" ) ]
35+ use nostr_sdk:: ToBech32 ;
3436use tokio:: sync:: { mpsc, watch} ;
3537
3638use std:: collections:: HashMap ;
@@ -52,6 +54,8 @@ pub struct CashuConfig {
5254 pub mint_url : String ,
5355 /// The currency unit to use (typically Sat)
5456 pub unit : CurrencyUnit ,
57+ /// Optional npub.cash URL for lightning address support (e.g., "https://npub.cash")
58+ pub npubcash_url : Option < String > ,
5559}
5660
5761/// A wallet implementation using the Cashu (CDK) SDK.
@@ -68,6 +72,8 @@ pub struct Cashu {
6872 event_queue : Arc < EventQueue > ,
6973 tx_metadata : TxMetadataStore ,
7074 runtime : Arc < Runtime > ,
75+ #[ cfg_attr( not( feature = "npubcash" ) , allow( dead_code) ) ]
76+ npubcash_url : Option < String > ,
7177}
7278
7379impl TrustedWalletInterface for Cashu {
@@ -497,13 +503,34 @@ impl TrustedWalletInterface for Cashu {
497503 fn get_lightning_address (
498504 & self ,
499505 ) -> Pin < Box < dyn Future < Output = Result < Option < String > , TrustedError > > + Send + ' _ > > {
500- Box :: pin ( async { Ok ( None ) } )
506+ Box :: pin ( async {
507+ #[ cfg( feature = "npubcash" ) ]
508+ if let Some ( ref url) = self . npubcash_url {
509+ let keys = self . cashu_wallet . get_npubcash_keys ( ) . map_err ( |e| {
510+ TrustedError :: WalletOperationFailed ( format ! (
511+ "Failed to get npub.cash keys: {e}"
512+ ) )
513+ } ) ?;
514+ let npub = keys. public_key ( ) . to_bech32 ( ) . map_err ( |e| {
515+ TrustedError :: WalletOperationFailed ( format ! ( "Failed to encode npub: {e}" ) )
516+ } ) ?;
517+ let domain = url. trim_start_matches ( "https://" ) . trim_start_matches ( "http://" ) ;
518+ return Ok ( Some ( format ! ( "{npub}@{domain}" ) ) ) ;
519+ }
520+ Ok ( None )
521+ } )
501522 }
502523
503524 fn register_lightning_address (
504525 & self , _name : String ,
505526 ) -> Pin < Box < dyn Future < Output = Result < ( ) , TrustedError > > + Send + ' _ > > {
506527 Box :: pin ( async {
528+ #[ cfg( feature = "npubcash" ) ]
529+ if self . npubcash_url . is_some ( ) {
530+ // npub.cash addresses are deterministic from the Nostr keys,
531+ // and set_mint_url is called during init. Nothing to do here.
532+ return Ok ( ( ) ) ;
533+ }
507534 Err ( TrustedError :: UnsupportedOperation (
508535 "register_lightning_address is not supported in Cashu Wallet" . to_string ( ) ,
509536 ) )
@@ -652,6 +679,61 @@ impl Cashu {
652679 } ) ;
653680 }
654681
682+ // Initialize npub.cash if configured
683+ #[ cfg( feature = "npubcash" ) ]
684+ let npubcash_url = cashu_config. npubcash_url . clone ( ) ;
685+ #[ cfg( not( feature = "npubcash" ) ) ]
686+ let npubcash_url: Option < String > = None ;
687+
688+ #[ cfg( feature = "npubcash" ) ]
689+ if let Some ( ref url) = npubcash_url {
690+ if let Err ( e) = cashu_wallet. enable_npubcash ( url. clone ( ) ) . await {
691+ log_error ! ( logger, "Failed to enable npub.cash: {e}" ) ;
692+ } else {
693+ log_info ! ( logger, "npub.cash enabled with URL: {url}" ) ;
694+
695+ // Start background polling for npub.cash quotes
696+ let wallet_for_npubcash = Arc :: clone ( & cashu_wallet) ;
697+ let sender_for_npubcash = mint_quote_sender. clone ( ) ;
698+ let logger_for_npubcash = Arc :: clone ( & logger) ;
699+ let mut shutdown_for_npubcash = shutdown_sender. subscribe ( ) ;
700+ runtime. spawn_cancellable_background_task ( async move {
701+ let poll_interval = Duration :: from_secs ( 30 ) ;
702+ loop {
703+ tokio:: select! {
704+ _ = shutdown_for_npubcash. changed( ) => {
705+ log_info!( logger_for_npubcash, "npub.cash polling shutdown" ) ;
706+ return ;
707+ }
708+ _ = tokio:: time:: sleep( poll_interval) => {
709+ match wallet_for_npubcash. sync_npubcash_quotes( ) . await {
710+ Ok ( quotes) => {
711+ for quote in quotes {
712+ if matches!( quote. state, cdk:: nuts:: MintQuoteState :: Paid ) {
713+ let id = quote. id. clone( ) ;
714+ if let Err ( e) = sender_for_npubcash. send( quote) . await {
715+ log_error!(
716+ logger_for_npubcash,
717+ "Failed to send npub.cash quote {id} for monitoring: {e}"
718+ ) ;
719+ }
720+ }
721+ }
722+ } ,
723+ Err ( e) => {
724+ log_error!(
725+ logger_for_npubcash,
726+ "Failed to sync npub.cash quotes: {e}"
727+ ) ;
728+ } ,
729+ }
730+ }
731+ }
732+ }
733+ } ) ;
734+ }
735+ }
736+
655737 Ok ( Cashu {
656738 cashu_wallet,
657739 unit : cashu_config. unit ,
@@ -664,6 +746,7 @@ impl Cashu {
664746 event_queue,
665747 tx_metadata,
666748 runtime,
749+ npubcash_url,
667750 } )
668751 }
669752
0 commit comments