fix(tx): track async operations to completion (send/shield/auto-shield)
z_sendmany returns an opid immediately; the tx is built/signed/broadcast asynchronously afterward. The send path showed "Transaction sent successfully!" and cleared the form on opid receipt, so a later async failure contradicted it. Shield/merge stored the opid only in a dialog-local static (never polled), and auto-shield ran a blocking z_shieldcoinbase on the UI thread and discarded its opid — async failures of all three were silently lost. - Add App::trackOperation(opid) so shield/merge/auto-shield register with the shared opid poller (failures surface, balances refresh on completion). - Defer the full-node send's success/failure to the poller via per-opid callbacks (parseOperationStatusPoll now exposes failureByOpid); the "Sending..." spinner covers the finalizing window, and the form is kept until terminal status. - Dispatch auto-shield through the worker thread and use the configured fee. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
19
src/app.h
19
src/app.h
@@ -250,11 +250,18 @@ public:
|
||||
// Wallet backup
|
||||
void backupWallet(const std::string& destination, std::function<void(bool, const std::string&)> callback);
|
||||
|
||||
// Transaction operations
|
||||
void sendTransaction(const std::string& from, const std::string& to,
|
||||
// Transaction operations
|
||||
void sendTransaction(const std::string& from, const std::string& to,
|
||||
double amount, double fee, const std::string& memo,
|
||||
std::function<void(bool success, const std::string& result)> callback);
|
||||
|
||||
// Register a daemon async operation id (z_shieldcoinbase / z_mergetoaddress /
|
||||
// auto-shield) with the shared opid poller so its eventual success/failure is
|
||||
// surfaced and balances/transactions refresh on completion. z_sendmany uses the
|
||||
// richer pending-send path internally; this is for operations with no optimistic
|
||||
// transaction row of their own.
|
||||
void trackOperation(const std::string& opid);
|
||||
|
||||
// Force refresh
|
||||
void refreshNow();
|
||||
void refreshMiningInfo();
|
||||
@@ -399,6 +406,10 @@ private:
|
||||
const std::string& txid);
|
||||
void removePendingSendTransactions(const std::vector<std::string>& opids,
|
||||
bool restoreBalances);
|
||||
// Deliver a deferred z_sendmany result to its waiting UI callback once the opid
|
||||
// reaches a terminal status. Returns true if a callback was registered (and fired).
|
||||
bool invokeSendResultCallback(const std::string& opid, bool ok,
|
||||
const std::string& result);
|
||||
void applyPendingSendBalanceDeltas(bool includeAggregateBalances);
|
||||
std::string transactionHistoryCacheWalletIdentity() const;
|
||||
bool ensureTransactionHistoryCacheUnlockedFor(const std::string& walletIdentity);
|
||||
@@ -576,6 +587,10 @@ private:
|
||||
std::int64_t timestamp = 0;
|
||||
};
|
||||
std::unordered_map<std::string, PendingSendInfo> pending_send_info_;
|
||||
// z_sendmany UI callbacks held until the opid reaches a terminal status, so the
|
||||
// user isn't told "sent successfully" before the tx is actually built/broadcast.
|
||||
std::unordered_map<std::string, std::function<void(bool, const std::string&)>>
|
||||
pending_send_callbacks_;
|
||||
// Txids from completed z_sendmany operations.
|
||||
// Ensures shielded sends are discoverable by z_viewtransaction
|
||||
// even when they don't appear in listtransactions or
|
||||
|
||||
Reference in New Issue
Block a user