use super::*;
#[derive(Debug, Clone)]
pub(crate) struct Timestamp(bitcoincore_rpc::json::Timestamp);
impl FromStr for Timestamp {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(if s == "now" {
Self(bitcoincore_rpc::json::Timestamp::Now)
} else {
Self(bitcoincore_rpc::json::Timestamp::Time(s.parse()?))
})
}
}
#[derive(Debug, Parser)]
pub(crate) struct Restore {
#[clap(value_enum, long, help = "Restore wallet from <SOURCE> on stdin.")]
from: Source,
#[arg(long, help = "Use <PASSPHRASE> when deriving wallet.")]
pub(crate) passphrase: Option<String>,
#[arg(
long,
help = "Scan chain from <TIMESTAMP> onwards. Can be a unix timestamp in \
seconds or the string `now`, to skip scanning"
)]
pub(crate) timestamp: Option<Timestamp>,
}
#[derive(clap::ValueEnum, Debug, Clone)]
enum Source {
Descriptor,
Mnemonic,
}
impl Restore {
pub(crate) fn run(self, name: String, settings: &Settings) -> SubcommandResult {
ensure!(
!settings
.bitcoin_rpc_client(None)?
.list_wallet_dir()?
.iter()
.any(|wallet_name| wallet_name == &name),
"wallet `{}` already exists",
name
);
match self.from {
Source::Descriptor => {
ensure!(
self.passphrase.is_none(),
"descriptor does not take a passphrase"
);
ensure!(
self.timestamp.is_none(),
"descriptor does not take a timestamp"
);
let mut buffer = String::new();
io::stdin().read_to_string(&mut buffer)?;
let wallet_descriptors: ListDescriptorsResult = serde_json::from_str(&buffer)?;
Wallet::initialize_from_descriptors(name, settings, wallet_descriptors.descriptors)?;
}
Source::Mnemonic => {
let mut buffer = String::new();
io::stdin().read_line(&mut buffer)?;
let mnemonic = Mnemonic::from_str(&buffer)?;
Wallet::initialize(
name,
settings,
mnemonic.to_seed(self.passphrase.unwrap_or_default()),
self
.timestamp
.unwrap_or(Timestamp(bitcoincore_rpc::json::Timestamp::Time(0)))
.0,
)?;
}
}
Ok(None)
}
}