feat(lite): per-address balances from unspent notes/utxos
applyLiteRefreshModelToWalletState now derives each address's balance by summing its unspent notes/utxos (excluding spent and unconfirmed-spent outputs) instead of the aggregate-only zeros, so the Receive/Balance UI shows per-address amounts. The notes parser shape is confirmed against do_list_notes in the backend source. testLitePerAddressBalances covers the summing + spent-exclusion. Completes M2. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
#include "../data/wallet_state.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include <sodium.h>
|
||||
@@ -37,13 +39,26 @@ void applyLiteRefreshModelToWalletState(const LiteWalletAppRefreshModel& model,
|
||||
}
|
||||
|
||||
if (model.hasAddresses) {
|
||||
// Per-address balances from unspent notes/utxos (when the notes command succeeded).
|
||||
// Sum the value of outputs at each address that are neither spent nor unconfirmed-spent.
|
||||
std::unordered_map<std::string, std::uint64_t> perAddressZatoshis;
|
||||
if (model.hasSpendableOutputs) {
|
||||
for (const auto& output : model.spendableOutputs) {
|
||||
if (output.spent || output.unconfirmedSpent) continue;
|
||||
perAddressZatoshis[output.address] += output.valueZatoshis;
|
||||
}
|
||||
}
|
||||
|
||||
state.addresses.clear();
|
||||
state.z_addresses.clear();
|
||||
state.t_addresses.clear();
|
||||
for (const auto& addr : model.addresses) {
|
||||
AddressInfo info;
|
||||
info.address = addr.address;
|
||||
info.balance = 0.0; // lite address listing is aggregate-only; per-address balance is M2b (notes correlation)
|
||||
const auto it = perAddressZatoshis.find(addr.address);
|
||||
info.balance = it != perAddressZatoshis.end()
|
||||
? static_cast<double>(it->second) / kZatoshisPerCoin
|
||||
: 0.0;
|
||||
info.type = (addr.kind == LiteWalletAppAddressKind::Shielded) ? "shielded" : "transparent";
|
||||
info.has_spending_key = addr.spendabilityKnown ? addr.spendable : true;
|
||||
if (addr.kind == LiteWalletAppAddressKind::Shielded) {
|
||||
|
||||
Reference in New Issue
Block a user