wallet: accounts balance calculating optimization, payment proof support on send, selection_strategy_is_use_all
This commit is contained in:
parent
af597df7b1
commit
c52da4f479
2 changed files with 56 additions and 46 deletions
|
@ -125,7 +125,7 @@ impl MessageRequestModal {
|
||||||
let res = if invoice {
|
let res = if invoice {
|
||||||
wallet.issue_invoice(a)
|
wallet.issue_invoice(a)
|
||||||
} else {
|
} else {
|
||||||
wallet.send(a)
|
wallet.send(a, None)
|
||||||
};
|
};
|
||||||
let mut w_result = result.write();
|
let mut w_result = result.write();
|
||||||
*w_result = Some(res);
|
*w_result = Some(res);
|
||||||
|
|
|
@ -461,19 +461,19 @@ impl Wallet {
|
||||||
let instance = r_inst.clone().unwrap();
|
let instance = r_inst.clone().unwrap();
|
||||||
let mut api = Owner::new(instance, None);
|
let mut api = Owner::new(instance, None);
|
||||||
controller::owner_single_use(None, None, Some(&mut api), |api, m| {
|
controller::owner_single_use(None, None, Some(&mut api), |api, m| {
|
||||||
api.create_account_path(m, label)?;
|
let id = api.create_account_path(m, label)?;
|
||||||
|
if self.get_data().is_none() {
|
||||||
// Update account list at separate thread.
|
return Err(Error::GenericError("No wallet data".to_string()));
|
||||||
if let Some(data) = self.get_data() {
|
}
|
||||||
let last_height = data.info.last_confirmed_height;
|
let current_height = self.get_data().unwrap().info.last_confirmed_height;
|
||||||
let wallet = self.clone();
|
if let Some(spendable_amount) = self.account_balance(current_height, api, m) {
|
||||||
thread::spawn(move || {
|
let mut w_data = self.accounts.write();
|
||||||
update_accounts(&wallet, last_height, None);
|
w_data.push(WalletAccount {
|
||||||
|
spendable_amount,
|
||||||
|
label: label.clone(),
|
||||||
|
path: id.to_bip_32_string(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh wallet info.
|
|
||||||
sync_wallet_data(&self, false);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -512,6 +512,30 @@ impl Wallet {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate current account balance.
|
||||||
|
fn account_balance(
|
||||||
|
&self,
|
||||||
|
current_height: u64,
|
||||||
|
o: &mut Owner<DefaultLCProvider<HTTPNodeClient, ExtKeychain>, HTTPNodeClient, ExtKeychain>,
|
||||||
|
m: Option<&SecretKey>)
|
||||||
|
-> Option<u64> {
|
||||||
|
if let Ok(outputs) = o.retrieve_outputs(m, false, false, None) {
|
||||||
|
let mut spendable = 0;
|
||||||
|
let min_confirmations = self.get_config().min_confirmations;
|
||||||
|
for out_mapping in outputs.1 {
|
||||||
|
let out = out_mapping.output;
|
||||||
|
if out.status == grin_wallet_libwallet::OutputStatus::Unspent {
|
||||||
|
if !out.is_coinbase || out.lock_height <= current_height
|
||||||
|
|| out.num_confirmations(current_height) >= min_confirmations {
|
||||||
|
spendable += out.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Some(spendable);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
/// Get list of accounts for the wallet.
|
/// Get list of accounts for the wallet.
|
||||||
pub fn accounts(&self) -> Vec<WalletAccount> {
|
pub fn accounts(&self) -> Vec<WalletAccount> {
|
||||||
self.accounts.read().clone()
|
self.accounts.read().clone()
|
||||||
|
@ -682,14 +706,15 @@ impl Wallet {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize a transaction to send amount, return request for funds receiver.
|
/// Initialize a transaction to send amount, return request for funds receiver.
|
||||||
pub fn send(&self, amount: u64) -> Result<WalletTransaction, Error> {
|
pub fn send(&self, amount: u64, receiver: Option<SlatepackAddress>) -> Result<WalletTransaction, Error> {
|
||||||
let config = self.get_config();
|
let config = self.get_config();
|
||||||
let args = InitTxArgs {
|
let args = InitTxArgs {
|
||||||
|
payment_proof_recipient_address: receiver,
|
||||||
src_acct_name: Some(config.account),
|
src_acct_name: Some(config.account),
|
||||||
amount,
|
amount,
|
||||||
minimum_confirmations: config.min_confirmations,
|
minimum_confirmations: config.min_confirmations,
|
||||||
num_change_outputs: 1,
|
num_change_outputs: 1,
|
||||||
selection_strategy_is_use_all: false,
|
selection_strategy_is_use_all: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let r_inst = self.instance.as_ref().read();
|
let r_inst = self.instance.as_ref().read();
|
||||||
|
@ -715,7 +740,7 @@ impl Wallet {
|
||||||
amount: u64,
|
amount: u64,
|
||||||
addr: &SlatepackAddress) -> Result<WalletTransaction, Error> {
|
addr: &SlatepackAddress) -> Result<WalletTransaction, Error> {
|
||||||
// Initialize transaction.
|
// Initialize transaction.
|
||||||
let tx = self.send(amount)?;
|
let tx = self.send(amount, Some(addr.clone()))?;
|
||||||
let slate_res = self.read_slate_by_tx(&tx);
|
let slate_res = self.read_slate_by_tx(&tx);
|
||||||
if slate_res.is_none() {
|
if slate_res.is_none() {
|
||||||
return Err(Error::GenericError("Slate not found".to_string()));
|
return Err(Error::GenericError("Slate not found".to_string()));
|
||||||
|
@ -727,10 +752,9 @@ impl Wallet {
|
||||||
let r_inst = self.instance.as_ref().read();
|
let r_inst = self.instance.as_ref().read();
|
||||||
let instance = r_inst.clone().unwrap();
|
let instance = r_inst.clone().unwrap();
|
||||||
let id = slate.clone().id;
|
let id = slate.clone().id;
|
||||||
cancel_tx(instance, None, &None, None, Some(id.clone())).unwrap();
|
if cancel_tx(instance, None, &None, None, Some(id.clone())).is_ok() {
|
||||||
|
sync_wallet_data(&self, false);
|
||||||
// Refresh wallet info to update statuses.
|
}
|
||||||
sync_wallet_data(&self, false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize parameters.
|
// Initialize parameters.
|
||||||
|
@ -833,7 +857,7 @@ impl Wallet {
|
||||||
src_acct_name: None,
|
src_acct_name: None,
|
||||||
amount: slate.amount,
|
amount: slate.amount,
|
||||||
minimum_confirmations: config.min_confirmations,
|
minimum_confirmations: config.min_confirmations,
|
||||||
selection_strategy_is_use_all: false,
|
selection_strategy_is_use_all: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let r_inst = self.instance.as_ref().read();
|
let r_inst = self.instance.as_ref().read();
|
||||||
|
@ -937,10 +961,9 @@ impl Wallet {
|
||||||
}
|
}
|
||||||
let r_inst = wallet.instance.as_ref().read();
|
let r_inst = wallet.instance.as_ref().read();
|
||||||
let instance = r_inst.clone().unwrap();
|
let instance = r_inst.clone().unwrap();
|
||||||
let _ = cancel_tx(instance, None, &None, Some(id), None);
|
if cancel_tx(instance, None, &None, Some(id), None).is_ok() {
|
||||||
|
sync_wallet_data(&wallet, false);
|
||||||
// Refresh wallet info to update statuses.
|
}
|
||||||
sync_wallet_data(&wallet, false);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1437,12 +1460,11 @@ fn start_api_server(wallet: &Wallet) -> Result<(ApiServer, u16), Error> {
|
||||||
|
|
||||||
/// Update wallet accounts data.
|
/// Update wallet accounts data.
|
||||||
fn update_accounts(wallet: &Wallet, current_height: u64, current_spendable: Option<u64>) {
|
fn update_accounts(wallet: &Wallet, current_height: u64, current_spendable: Option<u64>) {
|
||||||
// Update only current account if list is not empty.
|
if let Some(spendable) = current_spendable {
|
||||||
if current_spendable.is_some() {
|
|
||||||
let mut accounts = wallet.accounts.read().clone();
|
let mut accounts = wallet.accounts.read().clone();
|
||||||
for a in accounts.iter_mut() {
|
for a in accounts.iter_mut() {
|
||||||
if a.label == wallet.get_config().account {
|
if a.label == wallet.get_config().account {
|
||||||
a.spendable_amount = current_spendable.unwrap();
|
a.spendable_amount = spendable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Save accounts data.
|
// Save accounts data.
|
||||||
|
@ -1456,26 +1478,14 @@ fn update_accounts(wallet: &Wallet, current_height: u64, current_spendable: Opti
|
||||||
let mut accounts = vec![];
|
let mut accounts = vec![];
|
||||||
for a in api.accounts(m)? {
|
for a in api.accounts(m)? {
|
||||||
api.set_active_account(m, a.label.as_str())?;
|
api.set_active_account(m, a.label.as_str())?;
|
||||||
// Calculate wallet account balance.
|
// Calculate account balance.
|
||||||
let outputs = api.retrieve_outputs(m, true, false, None)?;
|
if let Some(spendable_amount) = wallet.account_balance(current_height, api, m) {
|
||||||
let min_confirmations = wallet.get_config().min_confirmations;
|
accounts.push(WalletAccount {
|
||||||
let mut spendable_amount = 0;
|
spendable_amount,
|
||||||
for out_mapping in outputs.1 {
|
label: a.label,
|
||||||
let out = out_mapping.output;
|
path: a.path.to_bip_32_string(),
|
||||||
if out.status == grin_wallet_libwallet::OutputStatus::Unspent {
|
});
|
||||||
if !out.is_coinbase || out.lock_height <= current_height
|
|
||||||
|| out.num_confirmations(current_height) >= min_confirmations {
|
|
||||||
spendable_amount += out.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add account to list.
|
|
||||||
accounts.push(WalletAccount {
|
|
||||||
spendable_amount,
|
|
||||||
label: a.label,
|
|
||||||
path: a.path.to_bip_32_string(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
// Sort in reverse.
|
// Sort in reverse.
|
||||||
accounts.reverse();
|
accounts.reverse();
|
||||||
|
|
Loading…
Reference in a new issue