@@ -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 {
@@ -480,13 +486,38 @@ impl TrustedWalletInterface for Cashu {
480486 fn get_lightning_address (
481487 & self ,
482488 ) -> Pin < Box < dyn Future < Output = Result < Option < String > , TrustedError > > + Send + ' _ > > {
483- Box :: pin ( async { Ok ( None ) } )
489+ Box :: pin ( async {
490+ #[ cfg( feature = "npubcash" ) ]
491+ if let Some ( ref url) = self . npubcash_url {
492+ let keys = self . cashu_wallet . get_npubcash_keys ( ) . map_err ( |e| {
493+ TrustedError :: WalletOperationFailed ( format ! (
494+ "Failed to get npub.cash keys: {e}"
495+ ) )
496+ } ) ?;
497+ let npub = keys. public_key ( ) . to_bech32 ( ) . map_err ( |e| {
498+ TrustedError :: WalletOperationFailed ( format ! (
499+ "Failed to encode npub: {e}"
500+ ) )
501+ } ) ?;
502+ let domain = url
503+ . trim_start_matches ( "https://" )
504+ . trim_start_matches ( "http://" ) ;
505+ return Ok ( Some ( format ! ( "{npub}@{domain}" ) ) ) ;
506+ }
507+ Ok ( None )
508+ } )
484509 }
485510
486511 fn register_lightning_address (
487512 & self , _name : String ,
488513 ) -> Pin < Box < dyn Future < Output = Result < ( ) , TrustedError > > + Send + ' _ > > {
489514 Box :: pin ( async {
515+ #[ cfg( feature = "npubcash" ) ]
516+ if self . npubcash_url . is_some ( ) {
517+ // npub.cash addresses are deterministic from the Nostr keys,
518+ // and set_mint_url is called during init. Nothing to do here.
519+ return Ok ( ( ) ) ;
520+ }
490521 Err ( TrustedError :: UnsupportedOperation (
491522 "register_lightning_address is not supported in Cashu Wallet" . to_string ( ) ,
492523 ) )
@@ -637,6 +668,61 @@ impl Cashu {
637668 } ) ;
638669 }
639670
671+ // Initialize npub.cash if configured
672+ #[ cfg( feature = "npubcash" ) ]
673+ let npubcash_url = cashu_config. npubcash_url . clone ( ) ;
674+ #[ cfg( not( feature = "npubcash" ) ) ]
675+ let npubcash_url: Option < String > = None ;
676+
677+ #[ cfg( feature = "npubcash" ) ]
678+ if let Some ( ref url) = npubcash_url {
679+ if let Err ( e) = cashu_wallet. enable_npubcash ( url. clone ( ) ) . await {
680+ log_error ! ( logger, "Failed to enable npub.cash: {e}" ) ;
681+ } else {
682+ log_info ! ( logger, "npub.cash enabled with URL: {url}" ) ;
683+
684+ // Start background polling for npub.cash quotes
685+ let wallet_for_npubcash = Arc :: clone ( & cashu_wallet) ;
686+ let sender_for_npubcash = mint_quote_sender. clone ( ) ;
687+ let logger_for_npubcash = Arc :: clone ( & logger) ;
688+ let mut shutdown_for_npubcash = shutdown_sender. subscribe ( ) ;
689+ runtime. spawn_cancellable_background_task ( async move {
690+ let poll_interval = Duration :: from_secs ( 30 ) ;
691+ loop {
692+ tokio:: select! {
693+ _ = shutdown_for_npubcash. changed( ) => {
694+ log_info!( logger_for_npubcash, "npub.cash polling shutdown" ) ;
695+ return ;
696+ }
697+ _ = tokio:: time:: sleep( poll_interval) => {
698+ match wallet_for_npubcash. sync_npubcash_quotes( ) . await {
699+ Ok ( quotes) => {
700+ for quote in quotes {
701+ if matches!( quote. state, cdk:: nuts:: MintQuoteState :: Paid ) {
702+ let id = quote. id. clone( ) ;
703+ if let Err ( e) = sender_for_npubcash. send( quote) . await {
704+ log_error!(
705+ logger_for_npubcash,
706+ "Failed to send npub.cash quote {id} for monitoring: {e}"
707+ ) ;
708+ }
709+ }
710+ }
711+ } ,
712+ Err ( e) => {
713+ log_error!(
714+ logger_for_npubcash,
715+ "Failed to sync npub.cash quotes: {e}"
716+ ) ;
717+ } ,
718+ }
719+ }
720+ }
721+ }
722+ } ) ;
723+ }
724+ }
725+
640726 Ok ( Cashu {
641727 cashu_wallet,
642728 unit : cashu_config. unit ,
@@ -649,6 +735,7 @@ impl Cashu {
649735 event_queue,
650736 tx_metadata,
651737 runtime,
738+ npubcash_url,
652739 } )
653740 }
654741
0 commit comments