feat(portfolio): persisted portfolio entries + pure sum helpers
Foundation for the Market tab's configurable portfolio (custom labels tied to
groups of addresses):
- Settings gains a PortfolioEntry {label, addresses[]} list, persisted in
settings.json as a JSON array-of-objects (same mechanism as lite_servers_),
with get/setPortfolioEntries().
- data/portfolio.h (header-only, ImGui-free): SumPortfolioBalance() sums a
group's DRGX balance against the live per-address list (unknown addresses
contribute 0), plus PortfolioEntryContains/Add/Remove group helpers.
- Unit-tested (testPortfolioHelpers): empty/known/unknown-address sums, and the
add/remove/contains membership semantics.
UI (editor dialog, Market card rework, Overview right-click) comes next.
Full-node + lite build clean; ctest green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
61
src/data/portfolio.h
Normal file
61
src/data/portfolio.h
Normal file
@@ -0,0 +1,61 @@
|
||||
// DragonX Wallet - ImGui Edition
|
||||
// Copyright 2024-2026 The Hush Developers
|
||||
// Released under the GPLv3
|
||||
//
|
||||
// Portfolio helpers — pure balance math for the Market tab's configurable portfolio.
|
||||
// A portfolio entry is a user label tied to a group of wallet addresses (persisted in
|
||||
// Settings as PortfolioEntry); these helpers sum/query that group against the live
|
||||
// per-address balance list. No I/O, no ImGui — unit-testable.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wallet_state.h" // AddressInfo
|
||||
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace dragonx {
|
||||
namespace data {
|
||||
|
||||
// Sum the DRGX balance of `entryAddresses` by looking them up in the wallet's per-address
|
||||
// list. Addresses not present in the wallet contribute 0 (e.g. removed/rescanned). Pure.
|
||||
inline double SumPortfolioBalance(const std::vector<std::string>& entryAddresses,
|
||||
const std::vector<AddressInfo>& walletAddresses)
|
||||
{
|
||||
if (entryAddresses.empty()) return 0.0;
|
||||
std::unordered_set<std::string> want(entryAddresses.begin(), entryAddresses.end());
|
||||
double sum = 0.0;
|
||||
for (const auto& a : walletAddresses)
|
||||
if (want.count(a.address)) sum += a.balance;
|
||||
return sum;
|
||||
}
|
||||
|
||||
// Whether `address` is part of the entry's address group.
|
||||
inline bool PortfolioEntryContains(const std::vector<std::string>& entryAddresses,
|
||||
const std::string& address)
|
||||
{
|
||||
for (const auto& a : entryAddresses)
|
||||
if (a == address) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add `address` to the group if absent (returns true if it was added).
|
||||
inline bool PortfolioEntryAdd(std::vector<std::string>& entryAddresses, const std::string& address)
|
||||
{
|
||||
if (address.empty() || PortfolioEntryContains(entryAddresses, address)) return false;
|
||||
entryAddresses.push_back(address);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove `address` from the group if present (returns true if it was removed).
|
||||
inline bool PortfolioEntryRemove(std::vector<std::string>& entryAddresses, const std::string& address)
|
||||
{
|
||||
for (auto it = entryAddresses.begin(); it != entryAddresses.end(); ++it) {
|
||||
if (*it == address) { entryAddresses.erase(it); return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace data
|
||||
} // namespace dragonx
|
||||
Reference in New Issue
Block a user