wallet: fix confirmations count, ability to repost and cancel transaction at posting state after timeout, repost height, fix posting state flag, cancel tx at send/receive modal
This commit is contained in:
parent
f42fd94281
commit
1b7d96eff5
5 changed files with 132 additions and 38 deletions
|
@ -358,8 +358,9 @@ impl WalletContent {
|
|||
columns[1].vertical_centered_justified(|ui| {
|
||||
let is_messages = current_type == WalletTabType::Messages;
|
||||
View::tab_button(ui, CHAT_CIRCLE_TEXT, is_messages, || {
|
||||
let dandelion = wallet.get_config().use_dandelion.unwrap_or(true);
|
||||
self.current_tab = Box::new(WalletMessages::new(dandelion));
|
||||
self.current_tab = Box::new(
|
||||
WalletMessages::new(wallet.can_use_dandelion())
|
||||
);
|
||||
});
|
||||
});
|
||||
columns[2].vertical_centered_justified(|ui| {
|
||||
|
|
|
@ -671,7 +671,7 @@ impl WalletMessages {
|
|||
} else {
|
||||
t!("wallets.invoice_desc","amount" => amount_format)
|
||||
};
|
||||
ui.label(RichText::new(desc_text).size(16.0).color(Colors::INACTIVE_TEXT));
|
||||
ui.label(RichText::new(desc_text).size(16.0).color(Colors::GRAY));
|
||||
ui.add_space(6.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(3.0);
|
||||
|
@ -699,12 +699,37 @@ impl WalletMessages {
|
|||
});
|
||||
ui.add_space(2.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(10.0);
|
||||
});
|
||||
|
||||
// Show modal buttons.
|
||||
ui.add_space(12.0);
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0);
|
||||
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
// Button to cancel transaction.
|
||||
let clear_text = format!("{} {}", PROHIBIT, t!("modal.cancel"));
|
||||
View::button(ui, clear_text, Colors::BUTTON, || {
|
||||
if let Ok(slate) = wallet.parse_slatepack(self.request_edit.clone()) {
|
||||
if let Some(tx) = wallet.tx_by_slate(&slate) {
|
||||
wallet.cancel(tx.data.id);
|
||||
}
|
||||
}
|
||||
self.amount_edit = "".to_string();
|
||||
self.request_edit = "".to_string();
|
||||
modal.close();
|
||||
});
|
||||
});
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
// Draw copy button.
|
||||
let copy_text = format!("{} {}", COPY, t!("copy"));
|
||||
View::button(ui, copy_text, Colors::BUTTON, || {
|
||||
cb.copy_string_to_buffer(self.request_edit.clone());
|
||||
self.amount_edit = "".to_string();
|
||||
self.request_edit = "".to_string();
|
||||
modal.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
use egui::{Align, Id, Layout, Margin, RichText, Rounding, ScrollArea};
|
||||
use egui::scroll_area::ScrollBarVisibility;
|
||||
use grin_core::core::amount_to_hr_string;
|
||||
use grin_wallet_libwallet::{TxLogEntryType};
|
||||
use grin_wallet_libwallet::{Slate, SlateState, TxLogEntryType};
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{ARROW_CIRCLE_DOWN, BRIDGE, CALENDAR_CHECK, CHAT_CIRCLE_TEXT, CHECK_CIRCLE, DOTS_THREE_CIRCLE, FILE_TEXT, GEAR_FINE, PROHIBIT, X_CIRCLE};
|
||||
use crate::gui::icons::{ARROW_CIRCLE_DOWN, ARROWS_CLOCKWISE, BRIDGE, CALENDAR_CHECK, CHAT_CIRCLE_TEXT, CHECK_CIRCLE, DOTS_THREE_CIRCLE, FILE_TEXT, GEAR_FINE, PROHIBIT, X_CIRCLE};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Root, View};
|
||||
use crate::gui::views::wallets::types::WalletTab;
|
||||
|
@ -183,14 +183,43 @@ fn tx_item_ui(ui: &mut egui::Ui,
|
|||
//TODO: Show tx info
|
||||
});
|
||||
|
||||
if !tx.posting && !tx.data.confirmed &&
|
||||
// Setup flag to repost unconfirmed posting transaction after min confirmation time.
|
||||
let last_height = data.info.last_confirmed_height;
|
||||
let min_conf = data.info.minimum_confirmations;
|
||||
let can_repost = tx.posting && tx.repost_height.is_some() &&
|
||||
last_height - tx.repost_height.unwrap() > min_conf;
|
||||
|
||||
// Draw cancel button for txs to repost or also non-cancelled, non-posting.
|
||||
if can_repost || (!tx.posting && !tx.data.confirmed &&
|
||||
tx.data.tx_type != TxLogEntryType::TxReceivedCancelled
|
||||
&& tx.data.tx_type != TxLogEntryType::TxSentCancelled {
|
||||
&& tx.data.tx_type != TxLogEntryType::TxSentCancelled) {
|
||||
View::item_button(ui, Rounding::default(), PROHIBIT, Some(Colors::RED), || {
|
||||
wallet.cancel(tx.data.id);
|
||||
});
|
||||
}
|
||||
|
||||
// Draw button to repost transaction.
|
||||
if can_repost {
|
||||
View::item_button(ui,
|
||||
Rounding::default(),
|
||||
ARROWS_CLOCKWISE,
|
||||
Some(Colors::GREEN), || {
|
||||
// Create slate to check existing file.
|
||||
let mut slate = Slate::blank(1, false);
|
||||
slate.id = tx.data.tx_slate_id.unwrap();
|
||||
slate.state = match tx.data.tx_type {
|
||||
TxLogEntryType::TxReceived => SlateState::Invoice3,
|
||||
_ => SlateState::Standard3
|
||||
};
|
||||
// Post tx after getting slate from slatepack file.
|
||||
if let Some(sp) = wallet.read_slatepack(&slate) {
|
||||
if let Ok(s) = wallet.parse_slatepack(sp) {
|
||||
let _ = wallet.post(&s, wallet.can_use_dandelion());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let layout_size = ui.available_size();
|
||||
ui.allocate_ui_with_layout(layout_size, Layout::left_to_right(Align::Center), |ui| {
|
||||
ui.add_space(12.0);
|
||||
|
@ -230,9 +259,7 @@ fn tx_item_ui(ui: &mut egui::Ui,
|
|||
|| tx.data.tx_type == TxLogEntryType::TxReceivedCancelled;
|
||||
if is_canceled {
|
||||
format!("{} {}", X_CIRCLE, t!("wallets.tx_canceled"))
|
||||
} else if tx.posting || (tx.data.kernel_excess.is_some() &&
|
||||
(tx.data.tx_type == TxLogEntryType::TxReceived ||
|
||||
tx.data.tx_type == TxLogEntryType::TxSent)) {
|
||||
} else if tx.posting {
|
||||
format!("{} {}", DOTS_THREE_CIRCLE, t!("wallets.tx_finalizing"))
|
||||
} else {
|
||||
match tx.data.tx_type {
|
||||
|
@ -254,7 +281,7 @@ fn tx_item_ui(ui: &mut egui::Ui,
|
|||
format!("{} {}", CHECK_CIRCLE, t!("wallets.tx_confirmed"))
|
||||
},
|
||||
TxLogEntryType::TxSent | TxLogEntryType::TxReceived => {
|
||||
if data.info.last_confirmed_height - tx_height > min_conf + 1 {
|
||||
if data.info.last_confirmed_height - tx_height > min_conf {
|
||||
let text = if tx.data.tx_type == TxLogEntryType::TxSent {
|
||||
t!("wallets.tx_sent")
|
||||
} else {
|
||||
|
|
|
@ -28,7 +28,7 @@ pub enum PhraseMode {
|
|||
Import
|
||||
}
|
||||
|
||||
/// Mnemonic phrase size based on words count.
|
||||
/// Mnemonic phrase size based on entropy.
|
||||
#[derive(PartialEq, Clone)]
|
||||
pub enum PhraseSize { Words12, Words15, Words18, Words21, Words24 }
|
||||
|
||||
|
@ -41,7 +41,7 @@ impl PhraseSize {
|
|||
PhraseSize::Words24
|
||||
];
|
||||
|
||||
/// Gen words count number.
|
||||
/// Get entropy value.
|
||||
pub fn value(&self) -> usize {
|
||||
match *self {
|
||||
PhraseSize::Words12 => 12,
|
||||
|
@ -52,7 +52,7 @@ impl PhraseSize {
|
|||
}
|
||||
}
|
||||
|
||||
/// Gen entropy size for current phrase size.
|
||||
/// Get entropy size for current phrase size.
|
||||
pub fn entropy_size(&self) -> usize {
|
||||
match *self {
|
||||
PhraseSize::Words12 => 16,
|
||||
|
@ -63,6 +63,7 @@ impl PhraseSize {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get phrase type for entropy size.
|
||||
pub fn type_for_value(count: usize) -> Option<PhraseSize> {
|
||||
if Self::is_correct_count(count) {
|
||||
match count {
|
||||
|
@ -90,7 +91,7 @@ impl PhraseSize {
|
|||
}
|
||||
}
|
||||
|
||||
/// Check if correct word count provided.
|
||||
/// Check if correct entropy size was provided.
|
||||
pub fn is_correct_count(count: usize) -> bool {
|
||||
count == 12 || count == 15 || count == 18 || count == 21 || count == 24
|
||||
}
|
||||
|
@ -144,8 +145,10 @@ pub struct WalletData {
|
|||
pub struct WalletTransaction {
|
||||
/// Transaction information.
|
||||
pub data: TxLogEntry,
|
||||
/// Calculated total transaction amount.
|
||||
/// Calculated transaction amount between debited and credited amount.
|
||||
pub amount: u64,
|
||||
/// Flag to check if transaction is posting after finalizing.
|
||||
pub posting: bool
|
||||
/// Flag to check if transaction is posting after finalization.
|
||||
pub posting: bool,
|
||||
/// Last wallet block height of transaction reposting.
|
||||
pub repost_height: Option<u64>
|
||||
}
|
|
@ -13,7 +13,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
use std::{fs, thread};
|
||||
use std::collections::BTreeSet;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::net::{SocketAddr, TcpListener};
|
||||
|
@ -64,6 +63,7 @@ pub struct Wallet {
|
|||
is_open: Arc<AtomicBool>,
|
||||
/// Flag to check if wallet is closing.
|
||||
closing: Arc<AtomicBool>,
|
||||
|
||||
/// Flag to check if wallet was deleted to remove it from the list.
|
||||
deleted: Arc<AtomicBool>,
|
||||
|
||||
|
@ -222,7 +222,13 @@ impl Wallet {
|
|||
w_config.save();
|
||||
}
|
||||
|
||||
/// Update usage of Dandelion to broadcast transactions.
|
||||
/// Check if Dandelion usage is needed to post transactions.
|
||||
pub fn can_use_dandelion(&self) -> bool {
|
||||
let r_config = self.config.read().unwrap();
|
||||
r_config.use_dandelion.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Update usage of Dandelion to post transactions.
|
||||
pub fn update_use_dandelion(&self, use_dandelion: bool) {
|
||||
let mut w_config = self.config.write().unwrap();
|
||||
w_config.use_dandelion = Some(use_dandelion);
|
||||
|
@ -470,7 +476,7 @@ impl Wallet {
|
|||
}
|
||||
|
||||
/// Create Slatepack message from provided slate.
|
||||
fn create_slatepack_message(&self, slate: Slate) -> Result<String, Error> {
|
||||
fn create_slatepack_message(&self, slate: &Slate) -> Result<String, Error> {
|
||||
let mut message = "".to_string();
|
||||
let mut api = Owner::new(self.instance.clone().unwrap(), None);
|
||||
controller::owner_single_use(None, None, Some(&mut api), |api, m| {
|
||||
|
@ -528,7 +534,7 @@ impl Wallet {
|
|||
api.tx_lock_outputs(None, &slate)?;
|
||||
|
||||
// Create Slatepack message response.
|
||||
let response = self.create_slatepack_message(slate)?;
|
||||
let response = self.create_slatepack_message(&slate)?;
|
||||
|
||||
// Sync wallet info.
|
||||
self.sync();
|
||||
|
@ -547,7 +553,7 @@ impl Wallet {
|
|||
let slate = api.issue_invoice_tx(None, args)?;
|
||||
|
||||
// Create Slatepack message response.
|
||||
let response = self.create_slatepack_message(slate)?;
|
||||
let response = self.create_slatepack_message(&slate)?;
|
||||
|
||||
// Sync wallet info.
|
||||
self.sync();
|
||||
|
@ -571,7 +577,7 @@ impl Wallet {
|
|||
api.tx_lock_outputs(None, &slate)?;
|
||||
|
||||
// Create Slatepack message response.
|
||||
let response = self.create_slatepack_message(slate)?;
|
||||
let response = self.create_slatepack_message(&slate)?;
|
||||
|
||||
// Sync wallet info.
|
||||
self.sync();
|
||||
|
@ -588,7 +594,7 @@ impl Wallet {
|
|||
Ok(())
|
||||
})?;
|
||||
// Create Slatepack message response.
|
||||
let response = self.create_slatepack_message(slate)?;
|
||||
let response = self.create_slatepack_message(&slate)?;
|
||||
|
||||
// Sync wallet info.
|
||||
self.sync();
|
||||
|
@ -601,10 +607,9 @@ impl Wallet {
|
|||
let mut slate = self.parse_slatepack(message)?;
|
||||
let api = Owner::new(self.instance.clone().unwrap(), None);
|
||||
slate = api.finalize_tx(None, &slate)?;
|
||||
// Create Slatepack message.
|
||||
let _ = self.create_slatepack_message(slate.clone())?;
|
||||
// Post transaction to blockchain.
|
||||
api.post_tx(None, &slate, dandelion)?;
|
||||
let _ = self.create_slatepack_message(&slate)?;
|
||||
let _ = self.post(&slate, dandelion);
|
||||
// Sync wallet info.
|
||||
self.sync();
|
||||
Ok(slate)
|
||||
|
@ -615,6 +620,24 @@ impl Wallet {
|
|||
// Post transaction to blockchain.
|
||||
let api = Owner::new(self.instance.clone().unwrap(), None);
|
||||
api.post_tx(None, slate, dandelion)?;
|
||||
// Setup transaction repost height and posting flag.
|
||||
let mut slate = slate.clone();
|
||||
if slate.state == SlateState::Invoice2 {
|
||||
slate.state = SlateState::Invoice3
|
||||
} else if slate.state == SlateState::Standard2 {
|
||||
slate.state = SlateState::Standard3
|
||||
};
|
||||
if let Some(tx) = self.tx_by_slate(&slate) {
|
||||
let mut w_data = self.data.write().unwrap();
|
||||
let mut data = w_data.clone().unwrap();
|
||||
for t in &mut data.txs {
|
||||
if t.data.id == tx.data.id {
|
||||
t.repost_height = Some(data.info.last_confirmed_height);
|
||||
t.posting = true;
|
||||
}
|
||||
}
|
||||
*w_data = Some(data);
|
||||
}
|
||||
// Sync wallet info.
|
||||
self.sync();
|
||||
Ok(())
|
||||
|
@ -922,7 +945,7 @@ fn sync_wallet_data(wallet: &Wallet) {
|
|||
});
|
||||
|
||||
let txs_args = RetrieveTxQueryArgs {
|
||||
exclude_cancelled: Some(true),
|
||||
exclude_cancelled: Some(false),
|
||||
sort_field: Some(RetrieveTxQuerySortField::CreationTimestamp),
|
||||
sort_order: Some(RetrieveTxQuerySortOrder::Desc),
|
||||
..Default::default()
|
||||
|
@ -956,9 +979,10 @@ fn sync_wallet_data(wallet: &Wallet) {
|
|||
}).collect::<Vec<TxLogEntry>>();
|
||||
|
||||
// Create wallet txs.
|
||||
let mut txs: Vec<WalletTransaction> = vec![];
|
||||
let mut new_txs: Vec<WalletTransaction> = vec![];
|
||||
for tx in &filter_txs {
|
||||
println!("{}", serde_json::to_string(tx).unwrap());
|
||||
// Setup transaction amount.
|
||||
let amount = if tx.amount_debited > tx.amount_credited {
|
||||
tx.amount_debited - tx.amount_credited
|
||||
} else {
|
||||
|
@ -979,7 +1003,7 @@ fn sync_wallet_data(wallet: &Wallet) {
|
|||
|
||||
// Setup posting status if we have other tx with same slate id.
|
||||
let mut same_tx_posting = false;
|
||||
for t in &mut txs {
|
||||
for t in &mut new_txs {
|
||||
if t.data.tx_slate_id == tx.tx_slate_id &&
|
||||
tx.tx_type != t.data.tx_type {
|
||||
same_tx_posting = t.posting ||
|
||||
|
@ -995,16 +1019,30 @@ fn sync_wallet_data(wallet: &Wallet) {
|
|||
false
|
||||
};
|
||||
|
||||
txs.push(WalletTransaction {
|
||||
// Setup reposting height.
|
||||
let mut repost_height = None;
|
||||
if posting {
|
||||
if let Some(mut data) = wallet.get_data() {
|
||||
for t in data.txs {
|
||||
if t.data.id == tx.id {
|
||||
repost_height = t.repost_height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new_txs.push(WalletTransaction {
|
||||
data: tx.clone(),
|
||||
amount,
|
||||
posting,
|
||||
repost_height,
|
||||
})
|
||||
}
|
||||
|
||||
// Update wallet data.
|
||||
let mut w_data = wallet.data.write().unwrap();
|
||||
*w_data = Some(WalletData { info: info.1, txs });
|
||||
*w_data = Some(WalletData { info: info.1, txs: new_txs });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue