mirror of
https://github.com/Qortal/piratewallet-light-cli.git
synced 2025-07-30 20:01:26 +00:00
Merge branch 'master' of github.com:adityapk00/lightwalletclient
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,4 +3,5 @@ Cargo.lock
|
|||||||
.vscode/
|
.vscode/
|
||||||
history.txt
|
history.txt
|
||||||
/.idea/
|
/.idea/
|
||||||
tarpaulin-report.html
|
tarpaulin-report.html
|
||||||
|
/log*
|
@@ -139,7 +139,7 @@ impl Command for BalanceCommand {
|
|||||||
"Show the current TAZ balance in the wallet".to_string()
|
"Show the current TAZ balance in the wallet".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String {
|
fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String {
|
||||||
lightclient.do_sync(true);
|
lightclient.do_sync(true);
|
||||||
|
|
||||||
format!("{}", lightclient.do_balance().pretty(2))
|
format!("{}", lightclient.do_balance().pretty(2))
|
||||||
@@ -311,6 +311,32 @@ impl Command for TransactionsCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct NewAddressCommand {}
|
||||||
|
impl Command for NewAddressCommand {
|
||||||
|
fn help(&self) -> String {
|
||||||
|
let mut h = vec![];
|
||||||
|
h.push("Create a new address in this wallet");
|
||||||
|
h.push("Usage:");
|
||||||
|
h.push("new [z | t]");
|
||||||
|
h.push("");
|
||||||
|
h.push("Example:");
|
||||||
|
h.push("To create a new z address:");
|
||||||
|
h.push("new z");
|
||||||
|
h.join("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn short_help(&self) -> String {
|
||||||
|
"Create a new address in this wallet".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exec(&self, args: &[&str], lightclient: &LightClient) -> String {
|
||||||
|
if args.len() != 1 {
|
||||||
|
return format!("No address type specified\n{}", self.help());
|
||||||
|
}
|
||||||
|
|
||||||
|
format!("{}", lightclient.do_new_address(args[0]).pretty(2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct NotesCommand {}
|
struct NotesCommand {}
|
||||||
impl Command for NotesCommand {
|
impl Command for NotesCommand {
|
||||||
@@ -388,6 +414,7 @@ pub fn get_commands() -> Box<HashMap<String, Box<dyn Command>>> {
|
|||||||
map.insert("quit".to_string(), Box::new(QuitCommand{}));
|
map.insert("quit".to_string(), Box::new(QuitCommand{}));
|
||||||
map.insert("list".to_string(), Box::new(TransactionsCommand{}));
|
map.insert("list".to_string(), Box::new(TransactionsCommand{}));
|
||||||
map.insert("notes".to_string(), Box::new(NotesCommand{}));
|
map.insert("notes".to_string(), Box::new(NotesCommand{}));
|
||||||
|
map.insert("new".to_string(), Box::new(NewAddressCommand{}));
|
||||||
map.insert("seed".to_string(), Box::new(SeedCommand{}));
|
map.insert("seed".to_string(), Box::new(SeedCommand{}));
|
||||||
|
|
||||||
Box::new(map)
|
Box::new(map)
|
||||||
|
@@ -10,7 +10,7 @@ use std::io;
|
|||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::{BufReader, BufWriter, Error, ErrorKind};
|
use std::io::{BufReader, BufWriter, Error, ErrorKind};
|
||||||
|
|
||||||
use json::{object, JsonValue};
|
use json::{object, array, JsonValue};
|
||||||
use zcash_primitives::transaction::{TxId, Transaction};
|
use zcash_primitives::transaction::{TxId, Transaction};
|
||||||
use zcash_client_backend::{
|
use zcash_client_backend::{
|
||||||
constants::testnet, constants::mainnet, constants::regtest, encoding::encode_payment_address,
|
constants::testnet, constants::mainnet, constants::regtest, encoding::encode_payment_address,
|
||||||
@@ -190,7 +190,7 @@ impl LightClient {
|
|||||||
|
|
||||||
let wallet = LightWallet::read(&mut file_buffer, config)?;
|
let wallet = LightWallet::read(&mut file_buffer, config)?;
|
||||||
LightClient {
|
LightClient {
|
||||||
wallet : Arc::new(wallet),
|
wallet : Arc::new(wallet),
|
||||||
config : config.clone(),
|
config : config.clone(),
|
||||||
sapling_output : vec![],
|
sapling_output : vec![],
|
||||||
sapling_spend : vec![]
|
sapling_spend : vec![]
|
||||||
@@ -225,7 +225,7 @@ impl LightClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Export private keys
|
// Export private keys
|
||||||
pub fn do_export(&self, addr: Option<String>) -> json::JsonValue {
|
pub fn do_export(&self, addr: Option<String>) -> JsonValue {
|
||||||
// Clone address so it can be moved into the closure
|
// Clone address so it can be moved into the closure
|
||||||
let address = addr.clone();
|
let address = addr.clone();
|
||||||
|
|
||||||
@@ -259,14 +259,14 @@ impl LightClient {
|
|||||||
all_keys.into()
|
all_keys.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_address(&self) -> json::JsonValue {
|
pub fn do_address(&self) -> JsonValue {
|
||||||
// Collect z addresses
|
// Collect z addresses
|
||||||
let z_addresses = self.wallet.address.iter().map( |ad| {
|
let z_addresses = self.wallet.address.read().unwrap().iter().map( |ad| {
|
||||||
encode_payment_address(self.config.hrp_sapling_address(), &ad)
|
encode_payment_address(self.config.hrp_sapling_address(), &ad)
|
||||||
}).collect::<Vec<String>>();
|
}).collect::<Vec<String>>();
|
||||||
|
|
||||||
// Collect t addresses
|
// Collect t addresses
|
||||||
let t_addresses = self.wallet.tkeys.iter().map( |sk| {
|
let t_addresses = self.wallet.tkeys.read().unwrap().iter().map( |sk| {
|
||||||
self.wallet.address_from_sk(&sk)
|
self.wallet.address_from_sk(&sk)
|
||||||
}).collect::<Vec<String>>();
|
}).collect::<Vec<String>>();
|
||||||
|
|
||||||
@@ -276,9 +276,9 @@ impl LightClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_balance(&self) -> json::JsonValue {
|
pub fn do_balance(&self) -> JsonValue {
|
||||||
// Collect z addresses
|
// Collect z addresses
|
||||||
let z_addresses = self.wallet.address.iter().map( |ad| {
|
let z_addresses = self.wallet.address.read().unwrap().iter().map( |ad| {
|
||||||
let address = encode_payment_address(self.config.hrp_sapling_address(), &ad);
|
let address = encode_payment_address(self.config.hrp_sapling_address(), &ad);
|
||||||
object!{
|
object!{
|
||||||
"address" => address.clone(),
|
"address" => address.clone(),
|
||||||
@@ -288,7 +288,7 @@ impl LightClient {
|
|||||||
}).collect::<Vec<JsonValue>>();
|
}).collect::<Vec<JsonValue>>();
|
||||||
|
|
||||||
// Collect t addresses
|
// Collect t addresses
|
||||||
let t_addresses = self.wallet.tkeys.iter().map( |sk| {
|
let t_addresses = self.wallet.tkeys.read().unwrap().iter().map( |sk| {
|
||||||
let address = self.wallet.address_from_sk(&sk);
|
let address = self.wallet.address_from_sk(&sk);
|
||||||
|
|
||||||
// Get the balance for this address
|
// Get the balance for this address
|
||||||
@@ -516,6 +516,23 @@ impl LightClient {
|
|||||||
JsonValue::Array(tx_list)
|
JsonValue::Array(tx_list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new address, deriving it from the seed.
|
||||||
|
pub fn do_new_address(&self, addr_type: &str) -> JsonValue {
|
||||||
|
let new_address = match addr_type {
|
||||||
|
"z" => self.wallet.add_zaddr(),
|
||||||
|
"t" => self.wallet.add_taddr(),
|
||||||
|
_ => {
|
||||||
|
let e = format!("Unrecognized address type: {}", addr_type);
|
||||||
|
error!("{}", e);
|
||||||
|
return object!{
|
||||||
|
"error" => e
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
array![new_address]
|
||||||
|
}
|
||||||
|
|
||||||
pub fn do_rescan(&self) -> String {
|
pub fn do_rescan(&self) -> String {
|
||||||
info!("Rescan starting");
|
info!("Rescan starting");
|
||||||
// First, clear the state from the wallet
|
// First, clear the state from the wallet
|
||||||
@@ -630,7 +647,7 @@ impl LightClient {
|
|||||||
|
|
||||||
// We'll also fetch all the txids that our transparent addresses are involved with
|
// We'll also fetch all the txids that our transparent addresses are involved with
|
||||||
// TODO: Use for all t addresses
|
// TODO: Use for all t addresses
|
||||||
let address = self.wallet.address_from_sk(&self.wallet.tkeys[0]);
|
let address = self.wallet.address_from_sk(&self.wallet.tkeys.read().unwrap()[0]);
|
||||||
let wallet = self.wallet.clone();
|
let wallet = self.wallet.clone();
|
||||||
fetch_transparent_txids(&self.get_server_uri(), address, start_height, end_height,
|
fetch_transparent_txids(&self.get_server_uri(), address, start_height, end_height,
|
||||||
move |tx_bytes: &[u8], height: u64 | {
|
move |tx_bytes: &[u8], height: u64 | {
|
||||||
@@ -692,15 +709,15 @@ impl LightClient {
|
|||||||
let rawtx = self.wallet.send_to_address(
|
let rawtx = self.wallet.send_to_address(
|
||||||
u32::from_str_radix(&self.config.consensus_branch_id, 16).unwrap(), // Blossom ID
|
u32::from_str_radix(&self.config.consensus_branch_id, 16).unwrap(), // Blossom ID
|
||||||
&self.sapling_spend, &self.sapling_output,
|
&self.sapling_spend, &self.sapling_output,
|
||||||
&addr, value, memo
|
vec![(&addr, value, memo)]
|
||||||
);
|
);
|
||||||
|
|
||||||
match rawtx {
|
match rawtx {
|
||||||
Some(txbytes) => match broadcast_raw_tx(&self.get_server_uri(), txbytes) {
|
Ok(txbytes) => match broadcast_raw_tx(&self.get_server_uri(), txbytes) {
|
||||||
Ok(k) => k,
|
Ok(k) => k,
|
||||||
Err(e) => e,
|
Err(e) => e,
|
||||||
},
|
},
|
||||||
None => format!("No Tx to broadcast")
|
Err(e) => format!("No Tx to broadcast. Error was: {}", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,7 @@ use zcash_primitives::{
|
|||||||
fs::{Fs, FsRepr},
|
fs::{Fs, FsRepr},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
use zcash_primitives::zip32::ExtendedSpendingKey;
|
||||||
|
|
||||||
|
|
||||||
pub struct BlockData {
|
pub struct BlockData {
|
||||||
@@ -468,10 +469,11 @@ pub struct SpendableNote {
|
|||||||
pub diversifier: Diversifier,
|
pub diversifier: Diversifier,
|
||||||
pub note: Note<Bls12>,
|
pub note: Note<Bls12>,
|
||||||
pub witness: IncrementalWitness<Node>,
|
pub witness: IncrementalWitness<Node>,
|
||||||
|
pub extsk: ExtendedSpendingKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpendableNote {
|
impl SpendableNote {
|
||||||
pub fn from(txid: TxId, nd: &SaplingNoteData, anchor_offset: usize) -> Option<Self> {
|
pub fn from(txid: TxId, nd: &SaplingNoteData, anchor_offset: usize, extsk: &ExtendedSpendingKey) -> Option<Self> {
|
||||||
// Include only notes that haven't been spent, or haven't been included in an unconfirmed spend yet.
|
// Include only notes that haven't been spent, or haven't been included in an unconfirmed spend yet.
|
||||||
if nd.spent.is_none() && nd.unconfirmed_spent.is_none() {
|
if nd.spent.is_none() && nd.unconfirmed_spent.is_none() {
|
||||||
let witness = nd.witnesses.get(nd.witnesses.len() - anchor_offset - 1);
|
let witness = nd.witnesses.get(nd.witnesses.len() - anchor_offset - 1);
|
||||||
@@ -482,6 +484,7 @@ impl SpendableNote {
|
|||||||
diversifier: nd.diversifier,
|
diversifier: nd.diversifier,
|
||||||
note: nd.note.clone(),
|
note: nd.note.clone(),
|
||||||
witness: w.clone(),
|
witness: w.clone(),
|
||||||
|
extsk: extsk.clone(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@@ -7,7 +7,7 @@ mod lightwallet;
|
|||||||
mod commands;
|
mod commands;
|
||||||
|
|
||||||
use std::io::{Result, Error, ErrorKind};
|
use std::io::{Result, Error, ErrorKind};
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use lightclient::{LightClient, LightClientConfig};
|
use lightclient::{LightClient, LightClientConfig};
|
||||||
@@ -136,7 +136,6 @@ pub fn main() {
|
|||||||
Err(e) => { eprintln!("Failed to start wallet. Error was:\n{}", e); return; }
|
Err(e) => { eprintln!("Failed to start wallet. Error was:\n{}", e); return; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// At startup, run a sync
|
// At startup, run a sync
|
||||||
let sync_update = lightclient.do_sync(true);
|
let sync_update = lightclient.do_sync(true);
|
||||||
println!("{}", sync_update);
|
println!("{}", sync_update);
|
||||||
@@ -150,7 +149,8 @@ pub fn main() {
|
|||||||
match command_rx.recv_timeout(Duration::from_secs(5 * 60)) {
|
match command_rx.recv_timeout(Duration::from_secs(5 * 60)) {
|
||||||
Ok((cmd, args)) => {
|
Ok((cmd, args)) => {
|
||||||
let args = args.iter().map(|s| s.as_ref()).collect();
|
let args = args.iter().map(|s| s.as_ref()).collect();
|
||||||
let cmd_response = commands::do_user_command(&cmd, &args, &lc);
|
|
||||||
|
let cmd_response = commands::do_user_command(&cmd, &args, lc.as_ref());
|
||||||
resp_tx.send(cmd_response).unwrap();
|
resp_tx.send(cmd_response).unwrap();
|
||||||
|
|
||||||
if cmd == "quit" {
|
if cmd == "quit" {
|
||||||
|
Reference in New Issue
Block a user