Skip to content

Commit c51d449

Browse files
committed
mnemonic restore wallet
1 parent 646c312 commit c51d449

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

client/src/bin/space-cli.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ extern crate core;
22

33
use std::{
44
fs, io,
5-
io::{Cursor, IsTerminal},
5+
io::{Cursor, IsTerminal, Write},
66
path::PathBuf,
77
};
88

@@ -78,6 +78,9 @@ enum Commands {
7878
/// Generate a new wallet
7979
#[command(name = "createwallet")]
8080
CreateWallet,
81+
/// Restore wallet from mnemonic phrase
82+
#[command(name = "restorewallet")]
83+
RestoreWallet,
8184
/// Load a wallet
8285
#[command(name = "loadwallet")]
8386
LoadWallet,
@@ -582,7 +585,17 @@ async fn handle_commands(cli: &SpaceCli, command: Commands) -> Result<(), Client
582585
print_list_wallets(result, cli.format);
583586
}
584587
Commands::CreateWallet => {
585-
cli.client.wallet_create(&cli.wallet).await?;
588+
let response = cli.client.wallet_create(&cli.wallet).await?;
589+
println!("⚠️ Write down your recovery phrase NOW!");
590+
println!("This is the ONLY time it will be shown:");
591+
println!("{}", &response);
592+
}
593+
Commands::RestoreWallet => {
594+
print!("Enter mnemonic phrase: ");
595+
io::stdout().flush().unwrap();
596+
let mut mnemonic = String::new();
597+
io::stdin().read_line(&mut mnemonic).unwrap();
598+
cli.client.wallet_restore(&cli.wallet, mnemonic).await?;
586599
}
587600
Commands::LoadWallet => {
588601
cli.client.wallet_load(&cli.wallet).await?;

client/src/rpc.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,10 @@ pub trait Rpc {
230230
async fn wallet_export(&self, name: &str) -> Result<WalletExport, ErrorObjectOwned>;
231231

232232
#[method(name = "walletcreate")]
233-
async fn wallet_create(&self, name: &str) -> Result<(), ErrorObjectOwned>;
233+
async fn wallet_create(&self, name: &str) -> Result<String, ErrorObjectOwned>;
234+
235+
#[method(name = "walletrestore")]
236+
async fn wallet_restore(&self, name: &str, mnemonic: String) -> Result<(), ErrorObjectOwned>;
234237

235238
#[method(name = "walletsendrequest")]
236239
async fn wallet_send_request(
@@ -491,11 +494,18 @@ impl WalletManager {
491494
Ok(export)
492495
}
493496

494-
pub async fn create_wallet(&self, client: &reqwest::Client, name: &str) -> anyhow::Result<()> {
497+
pub async fn create_wallet(&self, client: &reqwest::Client, name: &str) -> anyhow::Result<String> {
495498
let mnemonic: GeneratedKey<_, Tap> =
496499
Mnemonic::generate((WordCount::Words12, Language::English))
497500
.map_err(|_| anyhow!("Mnemonic generation error"))?;
498501

502+
let start_block = self.get_wallet_start_block(client).await?;
503+
self.setup_new_wallet(name.to_string(), mnemonic.to_string(), start_block)?;
504+
self.load_wallet(name).await?;
505+
Ok(mnemonic.to_string())
506+
}
507+
508+
pub async fn restore_wallet(&self, client: &reqwest::Client, name: &str, mnemonic: &str) -> anyhow::Result<()> {
499509
let start_block = self.get_wallet_start_block(client).await?;
500510
self.setup_new_wallet(name.to_string(), mnemonic.to_string(), start_block)?;
501511
self.load_wallet(name).await?;
@@ -513,7 +523,7 @@ impl WalletManager {
513523
return Err(anyhow!(format!("Wallet `{}` already exists", name)));
514524
}
515525

516-
let export = self.wallet_from_mnemonic(name.clone(), mnemonic.to_string(), start_block)?;
526+
let export = self.wallet_from_mnemonic(name.clone(), mnemonic, start_block)?;
517527
fs::create_dir_all(&wallet_path)?;
518528
let wallet_export_path = wallet_path.join("wallet.json");
519529
let mut file = fs::File::create(wallet_export_path)?;
@@ -528,7 +538,7 @@ impl WalletManager {
528538
start_block: BlockId,
529539
) -> anyhow::Result<WalletExport> {
530540
let (network, _) = self.fallback_network();
531-
let xpriv = Self::descriptor_from_mnemonic(network, &mnemonic.to_string())?;
541+
let xpriv = Self::descriptor_from_mnemonic(network, &mnemonic)?;
532542

533543
let (external, internal) = Self::default_descriptors(xpriv);
534544
let tmp = bdk::Wallet::create(external, internal)
@@ -653,7 +663,7 @@ impl WalletManager {
653663
}
654664

655665
fn descriptor_from_mnemonic(network: Network, m: &str) -> anyhow::Result<Xpriv> {
656-
let mnemonic = Mnemonic::parse(m).unwrap();
666+
let mnemonic = Mnemonic::parse(m)?;
657667
let xkey: ExtendedKey = mnemonic.clone().into_extended_key()?;
658668
Ok(xkey.into_xprv(network).expect("xpriv"))
659669
}
@@ -908,7 +918,7 @@ impl RpcServer for RpcServerImpl {
908918
})
909919
}
910920

911-
async fn wallet_create(&self, name: &str) -> Result<(), ErrorObjectOwned> {
921+
async fn wallet_create(&self, name: &str) -> Result<String, ErrorObjectOwned> {
912922
self.wallet_manager
913923
.create_wallet(&self.client, name)
914924
.await
@@ -917,6 +927,15 @@ impl RpcServer for RpcServerImpl {
917927
})
918928
}
919929

930+
async fn wallet_restore(&self, name: &str, mnemonic: String) -> Result<(), ErrorObjectOwned> {
931+
self.wallet_manager
932+
.restore_wallet(&self.client, name, &mnemonic)
933+
.await
934+
.map_err(|error| {
935+
ErrorObjectOwned::owned(RPC_WALLET_NOT_LOADED, error.to_string(), None::<String>)
936+
})
937+
}
938+
920939
async fn wallet_send_request(
921940
&self,
922941
wallet: &str,

0 commit comments

Comments
 (0)