Review page: show live network fee for the amount (priced like GRIM's send modal)
This commit is contained in:
@@ -138,6 +138,9 @@ pub struct SendFlow {
|
||||
/// Set when the success screen's "Receipt" button is tapped: the host view
|
||||
/// opens the receipt for the latest tx with this npub after the flow closes.
|
||||
pub receipt_npub: Option<String>,
|
||||
/// Atomic amount (nanogrin) we last asked the wallet to price, so the review
|
||||
/// page dispatches one `CalculateFee` per amount instead of every frame.
|
||||
fee_requested_for: Option<u64>,
|
||||
}
|
||||
|
||||
impl Default for SendFlow {
|
||||
@@ -162,6 +165,7 @@ impl Default for SendFlow {
|
||||
scan_open: false,
|
||||
request: false,
|
||||
receipt_npub: None,
|
||||
fee_requested_for: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1115,11 +1119,24 @@ impl SendFlow {
|
||||
&t!("goblin.send.row_delivery_val"),
|
||||
);
|
||||
} else {
|
||||
w::info_row(
|
||||
ui,
|
||||
&t!("goblin.send.row_network_fee"),
|
||||
&t!("goblin.send.row_network_fee_val"),
|
||||
);
|
||||
// Live network fee for this exact amount, priced by the wallet (one
|
||||
// async CalculateFee per amount, like GRIM's send modal). Until the
|
||||
// first result lands we show an ellipsis rather than a wrong number.
|
||||
let amount_nano = amount_from_hr_string(&amount).unwrap_or(0);
|
||||
if amount_nano > 0 && self.fee_requested_for != Some(amount_nano) {
|
||||
self.fee_requested_for = Some(amount_nano);
|
||||
wallet.task(WalletTask::CalculateFee(amount_nano, 0));
|
||||
}
|
||||
let fee_val = match wallet.calculated_fee(amount_nano) {
|
||||
Some(fee) => format!("{} {}", w::amount_str(fee), w::TSU),
|
||||
None => {
|
||||
// Result lands on a worker thread; poll until it does.
|
||||
ui.ctx()
|
||||
.request_repaint_after(std::time::Duration::from_millis(120));
|
||||
"…".to_string()
|
||||
}
|
||||
};
|
||||
w::info_row(ui, &t!("goblin.send.row_network_fee"), &fee_val);
|
||||
w::info_row(
|
||||
ui,
|
||||
&t!("goblin.send.row_privacy"),
|
||||
|
||||
@@ -126,6 +126,9 @@ pub struct Wallet {
|
||||
|
||||
/// Amount requests to calculate fee.
|
||||
fee_calculating: Arc<AtomicU8>,
|
||||
/// Last calculated network fee as `(amount, fee)` so a screen can read the
|
||||
/// fee for the amount it is showing without owning the task-result slot.
|
||||
last_fee: Arc<RwLock<Option<(u64, u64)>>>,
|
||||
|
||||
/// Flag to check if sending request is creating.
|
||||
send_creating: Arc<AtomicBool>,
|
||||
@@ -176,6 +179,7 @@ impl Wallet {
|
||||
message_opening: Arc::new(AtomicBool::from(false)),
|
||||
send_creating: Arc::new(AtomicBool::new(false)),
|
||||
fee_calculating: Arc::new(AtomicU8::new(0)),
|
||||
last_fee: Arc::new(RwLock::new(None)),
|
||||
invoice_creating: Arc::new(AtomicBool::new(false)),
|
||||
proof_verifying: Arc::new(AtomicBool::new(false)),
|
||||
tasks_sender: Arc::new(RwLock::new(None)),
|
||||
@@ -1389,6 +1393,14 @@ impl Wallet {
|
||||
self.fee_calculating.load(Ordering::Relaxed) > 0
|
||||
}
|
||||
|
||||
/// Last calculated network fee for `amount`, if one is cached. Returns
|
||||
/// `None` until a `CalculateFee` task for that exact amount has completed.
|
||||
pub fn calculated_fee(&self, amount: u64) -> Option<u64> {
|
||||
self.last_fee
|
||||
.read()
|
||||
.and_then(|(a, f)| if a == amount { Some(f) } else { None })
|
||||
}
|
||||
|
||||
/// Initialize a transaction to send amount.
|
||||
fn send(&self, a: u64, dest: Option<SlatepackAddress>) -> Result<Slate, Error> {
|
||||
let config = self.get_config();
|
||||
@@ -2154,6 +2166,7 @@ async fn handle_task(w: &Wallet, t: WalletTask) {
|
||||
}
|
||||
// Calculate fee for provided amount.
|
||||
if let Ok(fee) = w.calculate_fee(*a) {
|
||||
*w.last_fee.write() = Some((*a, fee));
|
||||
w.on_task_result(None, &WalletTask::CalculateFee(*a, fee))
|
||||
}
|
||||
let calculating = w.fee_calculating.load(Ordering::Relaxed);
|
||||
|
||||
Reference in New Issue
Block a user