| 
					
				 | 
			
			
				@@ -0,0 +1,117 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use std::fs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use std::str::FromStr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use std::sync::Arc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use anyhow::{bail, Result}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use cdk::cdk_database::WalletDatabase; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use cdk::wallet::Wallet; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use cdk::{cdk_database, Mnemonic}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use cdk_redb::RedbWalletDatabase; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use cdk_sqlite::WalletSQLiteDatabase; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use clap::{Parser, Subcommand}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use rand::Rng; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+mod sub_commands; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/// Simple CLI application to interact with cashu 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#[derive(Parser)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#[command(name = "cashu-tool")] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#[command(author = "thesimplekid <tsk@thesimplekid.com>")] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#[command(version = "0.1")] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#[command(author, version, about, long_about = None)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct Cli { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Database engine to use (sqlite/redb) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[arg(short, long, default_value = "sqlite")] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    engine: String, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Path to Seed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[arg(short, long, default_value = "./seed")] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    seed_path: String, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// File Path to save proofs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[arg(short, long)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    db_path: Option<String>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #[command(subcommand)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    command: Commands, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const DEFAULT_REDB_DB_PATH: &str = "./cashu_tool.redb"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const DEFAULT_SQLITE_DB_PATH: &str = "./cashu_tool.redb"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#[derive(Subcommand)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+enum Commands { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Decode a token 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    DecodeToken(sub_commands::decode_token::DecodeTokenSubCommand), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Pay bolt11 invoice 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Melt(sub_commands::melt::MeltSubCommand), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Receive token 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Receive(sub_commands::receive::ReceiveSubCommand), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Create token from wallet balance 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    CreateToken(sub_commands::create_token::CreateTokenSubCommand), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Check if wallet balance is spendable 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    CheckSpendable, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// View mint info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    MintInfo(sub_commands::mint_info::MintInfoSubcommand), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Mint proofs via bolt11 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Mint(sub_commands::mint::MintSubCommand), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Restore proofs from seed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Restore(sub_commands::restore::RestoreSubCommand), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#[tokio::main] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+async fn main() -> Result<()> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tracing_subscriber::fmt() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .with_max_level(tracing::Level::WARN) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .init(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Parse input 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let args: Cli = Cli::parse(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let localstore: Arc<dyn WalletDatabase<Err = cdk_database::Error> + Send + Sync> = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        match args.engine.as_str() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            "sqlite" => Arc::new(RedbWalletDatabase::new(DEFAULT_REDB_DB_PATH)?), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            "redb" => Arc::new(WalletSQLiteDatabase::new(DEFAULT_SQLITE_DB_PATH).await?), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            _ => bail!("Unknown DB engine"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mnemonic = match fs::metadata(args.seed_path.clone()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Ok(_) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let contents = fs::read_to_string(args.seed_path.clone())?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Mnemonic::from_str(&contents)? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Err(_e) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let mut rng = rand::thread_rng(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let random_bytes: [u8; 32] = rng.gen(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let mnemnic = Mnemonic::from_entropy(&random_bytes)?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            tracing::info!("Using randomly generated seed you will not be able to restore"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            mnemnic 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let wallet = Wallet::new(localstore, &mnemonic.to_seed_normalized(""), vec![]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    match &args.command { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Commands::DecodeToken(sub_command_args) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            sub_commands::decode_token::decode_token(sub_command_args) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Commands::Melt(sub_command_args) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            sub_commands::melt::melt(wallet, sub_command_args).await 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Commands::Receive(sub_command_args) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            sub_commands::receive::receive(wallet, sub_command_args).await 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Commands::CreateToken(sub_command_args) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            sub_commands::create_token::create_token(wallet, sub_command_args).await 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Commands::CheckSpendable => sub_commands::check_spent::check_spent(wallet).await, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Commands::MintInfo(sub_command_args) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            sub_commands::mint_info::mint_info(sub_command_args).await 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Commands::Mint(sub_command_args) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            sub_commands::mint::mint(wallet, sub_command_args).await 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Commands::Restore(sub_command_args) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            sub_commands::restore::restore(wallet, sub_command_args).await 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |