mirror of
https://github.com/Qortal/piratewallet-light-cli.git
synced 2025-10-28 19:02:39 +00:00
Cleanup
This commit is contained in:
@@ -27,7 +27,7 @@ impl Command for SyncCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String {
|
fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String {
|
||||||
lightclient.do_sync()
|
lightclient.do_sync(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ impl Command for InfoCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String {
|
fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String {
|
||||||
lightclient.do_sync();
|
lightclient.do_sync(true);
|
||||||
lightclient.do_info()
|
lightclient.do_info()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ impl Command for BalanceCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String {
|
fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String {
|
||||||
lightclient.do_sync();
|
lightclient.do_sync(true);
|
||||||
|
|
||||||
format!("{}", lightclient.do_address().pretty(2))
|
format!("{}", lightclient.do_address().pretty(2))
|
||||||
}
|
}
|
||||||
@@ -181,7 +181,7 @@ impl Command for SendCommand {
|
|||||||
|
|
||||||
let memo = if args.len() == 3 { Some(args[2].to_string()) } else {None};
|
let memo = if args.len() == 3 { Some(args[2].to_string()) } else {None};
|
||||||
|
|
||||||
lightclient.do_sync();
|
lightclient.do_sync(true);
|
||||||
|
|
||||||
lightclient.do_send(args[0], value, memo)
|
lightclient.do_send(args[0], value, memo)
|
||||||
}
|
}
|
||||||
@@ -249,7 +249,7 @@ impl Command for TransactionsCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String {
|
fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String {
|
||||||
lightclient.do_sync();
|
lightclient.do_sync(true);
|
||||||
|
|
||||||
format!("{}", lightclient.do_list_transactions().pretty(2))
|
format!("{}", lightclient.do_list_transactions().pretty(2))
|
||||||
}
|
}
|
||||||
@@ -289,7 +289,7 @@ impl Command for NotesCommand {
|
|||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
lightclient.do_sync();
|
lightclient.do_sync(true);
|
||||||
|
|
||||||
format!("{}", lightclient.do_list_notes(all_notes).pretty(2))
|
format!("{}", lightclient.do_list_notes(all_notes).pretty(2))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -274,6 +274,7 @@ impl LightClient {
|
|||||||
|
|
||||||
// Collect UTXOs
|
// Collect UTXOs
|
||||||
let utxos = self.wallet.get_utxos().iter()
|
let utxos = self.wallet.get_utxos().iter()
|
||||||
|
.filter(|utxo| utxo.unconfirmed_spent.is_none()) // Filter out unconfirmed from the list of utxos
|
||||||
.map(|utxo| {
|
.map(|utxo| {
|
||||||
object!{
|
object!{
|
||||||
"created_in_block" => utxo.height,
|
"created_in_block" => utxo.height,
|
||||||
@@ -289,25 +290,20 @@ impl LightClient {
|
|||||||
.collect::<Vec<JsonValue>>();
|
.collect::<Vec<JsonValue>>();
|
||||||
|
|
||||||
// Collect pending UTXOs
|
// Collect pending UTXOs
|
||||||
let pending_utxos = self.wallet.txs.read().unwrap().iter()
|
let pending_utxos = self.wallet.get_utxos().iter()
|
||||||
.flat_map( |(txid, wtx)| {
|
.filter(|utxo| utxo.unconfirmed_spent.is_some()) // Filter to include only unconfirmed utxos
|
||||||
wtx.utxos.iter().filter_map(move |utxo|
|
.map(|utxo|
|
||||||
if utxo.unconfirmed_spent.is_some() {
|
object!{
|
||||||
Some(object!{
|
"created_in_block" => utxo.height,
|
||||||
"created_in_block" => wtx.block,
|
"created_in_txid" => format!("{}", utxo.txid),
|
||||||
"created_in_txid" => format!("{}", txid),
|
|
||||||
"value" => utxo.value,
|
"value" => utxo.value,
|
||||||
"scriptkey" => hex::encode(utxo.script.clone()),
|
"scriptkey" => hex::encode(utxo.script.clone()),
|
||||||
"is_change" => false, // TODO: Identify notes as change
|
"is_change" => false, // TODO: Identify notes as change
|
||||||
"address" => utxo.address.clone(),
|
"address" => utxo.address.clone(),
|
||||||
"spent" => utxo.spent.map(|spent_txid| format!("{}", spent_txid)),
|
"spent" => utxo.spent.map(|spent_txid| format!("{}", spent_txid)),
|
||||||
"unconfirmed_spent" => utxo.unconfirmed_spent.map(|spent_txid| format!("{}", spent_txid)),
|
"unconfirmed_spent" => utxo.unconfirmed_spent.map(|spent_txid| format!("{}", spent_txid)),
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
|
||||||
.collect::<Vec<JsonValue>>();;
|
.collect::<Vec<JsonValue>>();;
|
||||||
|
|
||||||
let mut res = object!{
|
let mut res = object!{
|
||||||
@@ -430,13 +426,13 @@ impl LightClient {
|
|||||||
self.set_wallet_initial_state();
|
self.set_wallet_initial_state();
|
||||||
|
|
||||||
// Then, do a sync, which will force a full rescan from the initial state
|
// Then, do a sync, which will force a full rescan from the initial state
|
||||||
let response = self.do_sync();
|
let response = self.do_sync(true);
|
||||||
info!("Rescan finished");
|
info!("Rescan finished");
|
||||||
|
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_sync(&self) -> String {
|
pub fn do_sync(&self, print_updates: bool) -> String {
|
||||||
// Sync is 3 parts
|
// Sync is 3 parts
|
||||||
// 1. Get the latest block
|
// 1. Get the latest block
|
||||||
// 2. Get all the blocks that we don't have
|
// 2. Get all the blocks that we don't have
|
||||||
@@ -471,7 +467,7 @@ impl LightClient {
|
|||||||
let local_bytes_downloaded = bytes_downloaded.clone();
|
let local_bytes_downloaded = bytes_downloaded.clone();
|
||||||
|
|
||||||
// Show updates only if we're syncing a lot of blocks
|
// Show updates only if we're syncing a lot of blocks
|
||||||
if end_height - last_scanned_height > 100 {
|
if print_updates && end_height - last_scanned_height > 100 {
|
||||||
print!("Syncing {}/{}\r", last_scanned_height, last_block);
|
print!("Syncing {}/{}\r", last_scanned_height, last_block);
|
||||||
io::stdout().flush().ok().expect("Could not flush stdout");
|
io::stdout().flush().ok().expect("Could not flush stdout");
|
||||||
}
|
}
|
||||||
@@ -506,7 +502,9 @@ impl LightClient {
|
|||||||
end_height = last_block;
|
end_height = last_block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!(); // Print a new line, to finalize the syncing updates
|
if print_updates{
|
||||||
|
println!(""); // New line to finish up the updates
|
||||||
|
}
|
||||||
|
|
||||||
let mut responses = vec![];
|
let mut responses = vec![];
|
||||||
|
|
||||||
|
|||||||
@@ -1235,24 +1235,9 @@ impl LightWallet {
|
|||||||
// ZecWallet will add all your t-address funds into that transaction, and send them to your shielded
|
// ZecWallet will add all your t-address funds into that transaction, and send them to your shielded
|
||||||
// address as change.
|
// address as change.
|
||||||
let tinputs = self.get_utxos().iter()
|
let tinputs = self.get_utxos().iter()
|
||||||
.map(|utxo| {
|
.filter(|utxo| utxo.unconfirmed_spent.is_none()) // Remove any unconfirmed spends
|
||||||
let outpoint: OutPoint = utxo.to_outpoint();
|
.map(|utxo| utxo.clone())
|
||||||
|
.collect::<Vec<Utxo>>();
|
||||||
// Mark this utxo as uncofirmed spent
|
|
||||||
let mut txs = self.txs.write().unwrap();
|
|
||||||
let mut spent_utxo = txs.get_mut(&utxo.txid).unwrap().utxos.iter_mut()
|
|
||||||
.find(|u| utxo.txid == u.txid && utxo.output_index == u.output_index)
|
|
||||||
.unwrap();
|
|
||||||
spent_utxo.unconfirmed_spent = Some(utxo.txid);
|
|
||||||
|
|
||||||
let coin = TxOut {
|
|
||||||
value: Amount::from_u64(utxo.value).unwrap(),
|
|
||||||
script_pubkey: Script { 0: utxo.script.clone() },
|
|
||||||
};
|
|
||||||
|
|
||||||
(outpoint, coin)
|
|
||||||
})
|
|
||||||
.collect::<Vec<(OutPoint, TxOut)>>();
|
|
||||||
|
|
||||||
if let Err(e) = match to {
|
if let Err(e) = match to {
|
||||||
address::RecipientAddress::Shielded(_) => {
|
address::RecipientAddress::Shielded(_) => {
|
||||||
@@ -1261,20 +1246,28 @@ impl LightWallet {
|
|||||||
let sk = self.tkeys[0];
|
let sk = self.tkeys[0];
|
||||||
|
|
||||||
// Add all tinputs
|
// Add all tinputs
|
||||||
tinputs.iter().map( |(outpoint, coin)| {
|
tinputs.iter()
|
||||||
|
.map(|utxo| {
|
||||||
|
let outpoint: OutPoint = utxo.to_outpoint();
|
||||||
|
|
||||||
|
let coin = TxOut {
|
||||||
|
value: Amount::from_u64(utxo.value).unwrap(),
|
||||||
|
script_pubkey: Script { 0: utxo.script.clone() },
|
||||||
|
};
|
||||||
|
|
||||||
builder.add_transparent_input(sk, outpoint.clone(), coin.clone())
|
builder.add_transparent_input(sk, outpoint.clone(), coin.clone())
|
||||||
}).collect::<Result<Vec<_>, _>>()
|
})
|
||||||
}
|
.collect::<Result<Vec<_>, _>>()
|
||||||
_ => {Ok(vec![])}
|
},
|
||||||
|
_ => Ok(vec![])
|
||||||
} {
|
} {
|
||||||
eprintln!("Error adding transparent inputs: {:?}", e);
|
eprintln!("Error adding transparent inputs: {:?}", e);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confirm we were able to select sufficient value
|
// Confirm we were able to select sufficient value
|
||||||
// TODO: If we're sending to a t-address, we could also use t-address inputs
|
|
||||||
let selected_value = notes.iter().map(|selected| selected.note.value).sum::<u64>()
|
let selected_value = notes.iter().map(|selected| selected.note.value).sum::<u64>()
|
||||||
+ tinputs.iter().map::<u64, _>(|(_, coin)| coin.value.into()).sum::<u64>();
|
+ tinputs.iter().map::<u64, _>(|utxo| utxo.value.into()).sum::<u64>();
|
||||||
|
|
||||||
if selected_value < u64::from(target_value) {
|
if selected_value < u64::from(target_value) {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
@@ -1329,19 +1322,26 @@ impl LightWallet {
|
|||||||
println!("Transaction ID: {}", tx.txid());
|
println!("Transaction ID: {}", tx.txid());
|
||||||
|
|
||||||
// Mark notes as spent.
|
// Mark notes as spent.
|
||||||
// TODO: This is only a non-confirmed spend, and the note should be marked as such.
|
{
|
||||||
|
// Mark sapling notes as unconfirmed spent
|
||||||
let mut txs = self.txs.write().unwrap();
|
let mut txs = self.txs.write().unwrap();
|
||||||
for selected in notes {
|
for selected in notes {
|
||||||
let mut spent_note = txs
|
let mut spent_note = txs.get_mut(&selected.txid).unwrap()
|
||||||
.get_mut(&selected.txid)
|
.notes.iter_mut()
|
||||||
.unwrap()
|
|
||||||
.notes
|
|
||||||
.iter_mut()
|
|
||||||
.find(|nd| &nd.nullifier[..] == &selected.nullifier[..])
|
.find(|nd| &nd.nullifier[..] == &selected.nullifier[..])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
spent_note.unconfirmed_spent = Some(tx.txid());
|
spent_note.unconfirmed_spent = Some(tx.txid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark this utxo as unconfirmed spent
|
||||||
|
for utxo in tinputs {
|
||||||
|
let mut spent_utxo = txs.get_mut(&utxo.txid).unwrap().utxos.iter_mut()
|
||||||
|
.find(|u| utxo.txid == u.txid && utxo.output_index == u.output_index)
|
||||||
|
.unwrap();
|
||||||
|
spent_utxo.unconfirmed_spent = Some(tx.txid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return the encoded transaction, so the caller can send it.
|
// Return the encoded transaction, so the caller can send it.
|
||||||
let mut raw_tx = vec![];
|
let mut raw_tx = vec![];
|
||||||
tx.write(&mut raw_tx).unwrap();
|
tx.write(&mut raw_tx).unwrap();
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ pub fn main() {
|
|||||||
info!("{}", lightclient.do_info());
|
info!("{}", lightclient.do_info());
|
||||||
|
|
||||||
// At startup, run a sync
|
// At startup, run a sync
|
||||||
let sync_update = lightclient.do_sync();
|
let sync_update = lightclient.do_sync(true);
|
||||||
println!("{}", sync_update);
|
println!("{}", sync_update);
|
||||||
|
|
||||||
let (command_tx, command_rx) = std::sync::mpsc::channel::<(String, Vec<String>)>();
|
let (command_tx, command_rx) = std::sync::mpsc::channel::<(String, Vec<String>)>();
|
||||||
@@ -91,8 +91,8 @@ pub fn main() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// Timeout. Do a sync to keep the wallet up-to-date
|
// Timeout. Do a sync to keep the wallet up-to-date. False to whether to print updates on the console
|
||||||
lc.do_sync();
|
lc.do_sync(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user