| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 | 
							- #[cfg(not(target_arch = "wasm32"))]
 
- mod cli {
 
-     use std::collections::HashMap;
 
-     use std::net::SocketAddr;
 
-     use std::path::PathBuf;
 
-     use std::str::FromStr;
 
-     use std::sync::Arc;
 
-     use std::{env, fs};
 
-     use anyhow::{bail, Result};
 
-     use bip39::rand::{thread_rng, Rng};
 
-     use bip39::Mnemonic;
 
-     use cashu::CurrencyUnit;
 
-     use cdk_common::database::{MintAuthDatabase, MintKeysDatabase};
 
-     #[cfg(feature = "redb")]
 
-     use cdk_redb::MintRedbDatabase;
 
-     use cdk_signatory::{db_signatory, grpc_server};
 
-     use cdk_sqlite::mint::MintSqliteAuthDatabase;
 
-     use cdk_sqlite::MintSqliteDatabase;
 
-     use clap::Parser;
 
-     use tracing::Level;
 
-     use tracing_subscriber::EnvFilter;
 
-     const DEFAULT_WORK_DIR: &str = ".cdk-signatory";
 
-     const ENV_MNEMONIC: &str = "CDK_MINTD_MNEMONIC";
 
-     /// Simple CLI application to interact with cashu
 
-     #[derive(Parser)]
 
-     #[command(name = "cashu-signatory")]
 
-     #[command(author = "thesimplekid <tsk@thesimplekid.com>")]
 
-     #[command(version = "0.1.0")]
 
-     #[command(author, version, about, long_about = None)]
 
-     struct Cli {
 
-         /// Database engine to use (sqlite/redb)
 
-         #[arg(short, long, default_value = "sqlite")]
 
-         engine: String,
 
-         /// Database password for sqlcipher
 
-         #[arg(long)]
 
-         password: Option<String>,
 
-         /// Path to working dir
 
-         #[arg(short, long)]
 
-         work_dir: Option<PathBuf>,
 
-         /// Logging level
 
-         #[arg(short, long, default_value = "error")]
 
-         log_level: Level,
 
-         #[arg(long, default_value = "127.0.0.1")]
 
-         listen_addr: String,
 
-         #[arg(long, default_value = "15060")]
 
-         listen_port: u32,
 
-         #[arg(long, short)]
 
-         certs: Option<String>,
 
-         /// Supported units with the format of name,fee and max_order
 
-         #[arg(long, short, default_value = "sat,0,32")]
 
-         units: Vec<String>,
 
-     }
 
-     pub async fn main() -> Result<()> {
 
-         let args: Cli = Cli::parse();
 
-         let default_filter = args.log_level;
 
-         let supported_units = args
 
-             .units
 
-             .into_iter()
 
-             .map(|unit| {
 
-                 let mut parts = unit.split(",").collect::<Vec<_>>();
 
-                 parts.reverse();
 
-                 let unit: CurrencyUnit = parts.pop().unwrap_or_default().parse()?;
 
-                 let fee = parts
 
-                     .pop()
 
-                     .map(|x| x.parse())
 
-                     .transpose()?
 
-                     .unwrap_or_default();
 
-                 let max_order = parts.pop().map(|x| x.parse()).transpose()?.unwrap_or(32);
 
-                 Ok::<(_, (_, _)), anyhow::Error>((unit, (fee, max_order)))
 
-             })
 
-             .collect::<Result<HashMap<_, _>, _>>()?;
 
-         let sqlx_filter = "sqlx=warn,hyper_util=warn,reqwest=warn";
 
-         let env_filter = EnvFilter::new(format!("{default_filter},{sqlx_filter}"));
 
-         // Parse input
 
-         tracing_subscriber::fmt().with_env_filter(env_filter).init();
 
-         let work_dir = match &args.work_dir {
 
-             Some(work_dir) => work_dir.clone(),
 
-             None => {
 
-                 let home_dir = home::home_dir().unwrap();
 
-                 home_dir.join(DEFAULT_WORK_DIR)
 
-             }
 
-         };
 
-         let certs = Some(
 
-             args.certs
 
-                 .map(|x| x.into())
 
-                 .unwrap_or_else(|| work_dir.clone()),
 
-         );
 
-         fs::create_dir_all(&work_dir)?;
 
-         let (localstore, auth_localstore): (
 
-             Arc<dyn MintKeysDatabase<Err = cdk_common::database::Error> + Send + Sync>,
 
-             Arc<dyn MintAuthDatabase<Err = cdk_common::database::Error> + Send + Sync>,
 
-         ) = match args.engine.as_str() {
 
-             "sqlite" => {
 
-                 let sql_path = work_dir.join("cdk-cli.sqlite");
 
-                 #[cfg(not(feature = "sqlcipher"))]
 
-                 let db = (
 
-                     MintSqliteDatabase::new(&sql_path).await?,
 
-                     MintSqliteAuthDatabase::new(&sql_path).await?,
 
-                 );
 
-                 #[cfg(feature = "sqlcipher")]
 
-                 let db = {
 
-                     match args.password {
 
-                         Some(pass) => (
 
-                             MintSqliteDatabase::new(&sql_path, pass).await?,
 
-                             MintSqliteAuthDatabase::new(&sql_path).await?,
 
-                         ),
 
-                         None => bail!("Missing database password"),
 
-                     }
 
-                 };
 
-                 (Arc::new(db.0), Arc::new(db.1))
 
-             }
 
-             "redb" => {
 
-                 #[cfg(feature = "redb")]
 
-                 {
 
-                     let redb_path = work_dir.join("cdk-cli.redb");
 
-                     let db = Arc::new(MintRedbDatabase::new(&redb_path)?);
 
-                     (db.clone(), db)
 
-                 }
 
-                 #[cfg(not(feature = "redb"))]
 
-                 {
 
-                     bail!("redb feature not enabled");
 
-                 }
 
-             }
 
-             _ => bail!("Unknown DB engine"),
 
-         };
 
-         let seed_path = work_dir.join("seed");
 
-         let mnemonic = if let Ok(mnemonic) = env::var(ENV_MNEMONIC) {
 
-             Mnemonic::from_str(&mnemonic)?
 
-         } else {
 
-             match fs::metadata(seed_path.clone()) {
 
-                 Ok(_) => {
 
-                     let contents = fs::read_to_string(seed_path.clone())?;
 
-                     Mnemonic::from_str(&contents)?
 
-                 }
 
-                 Err(_e) => {
 
-                     let mut rng = thread_rng();
 
-                     let random_bytes: [u8; 32] = rng.gen();
 
-                     let mnemonic = Mnemonic::from_entropy(&random_bytes)?;
 
-                     tracing::info!("Creating new seed");
 
-                     fs::write(seed_path, mnemonic.to_string())?;
 
-                     mnemonic
 
-                 }
 
-             }
 
-         };
 
-         let seed = mnemonic.to_seed_normalized("");
 
-         let signatory = db_signatory::DbSignatory::new(
 
-             localstore,
 
-             Some(auth_localstore),
 
-             &seed,
 
-             supported_units,
 
-             Default::default(),
 
-         )
 
-         .await?;
 
-         let socket_addr =
 
-             SocketAddr::from_str(&format!("{}:{}", args.listen_addr, args.listen_port))?;
 
-         grpc_server(signatory, socket_addr, certs).await?;
 
-         Ok(())
 
-     }
 
- }
 
- fn main() {
 
-     #[cfg(target_arch = "wasm32")]
 
-     println!("Not supported in wasm32");
 
-     #[cfg(not(target_arch = "wasm32"))]
 
-     {
 
-         use tokio::runtime::Runtime;
 
-         let rt = Runtime::new().unwrap();
 
-         rt.block_on(async {
 
-             cli::main().await.unwrap();
 
-         });
 
-     }
 
- }
 
 
  |