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:
@@ -39,6 +39,7 @@
|
||||
#include "wallet/lite_wallet_state_mapper.h"
|
||||
#include "config/settings.h"
|
||||
#include "data/wallet_state.h"
|
||||
#include "data/portfolio.h"
|
||||
#include "fake_lite_backend.h"
|
||||
|
||||
#include <chrono>
|
||||
@@ -2581,6 +2582,46 @@ void testConsoleModel()
|
||||
}
|
||||
}
|
||||
|
||||
// Portfolio helpers — sum/query a labeled address group against per-address balances.
|
||||
void testPortfolioHelpers()
|
||||
{
|
||||
using dragonx::data::AddressInfo;
|
||||
using dragonx::data::SumPortfolioBalance;
|
||||
using dragonx::data::PortfolioEntryContains;
|
||||
using dragonx::data::PortfolioEntryAdd;
|
||||
using dragonx::data::PortfolioEntryRemove;
|
||||
|
||||
std::vector<AddressInfo> wallet;
|
||||
auto mk = [](const char* addr, double bal, const char* type) {
|
||||
AddressInfo a; a.address = addr; a.balance = bal; a.type = type; return a;
|
||||
};
|
||||
wallet.push_back(mk("R-t1", 1.5, "transparent"));
|
||||
wallet.push_back(mk("R-t2", 2.0, "transparent"));
|
||||
wallet.push_back(mk("zs-s1", 10.0, "shielded"));
|
||||
wallet.push_back(mk("zs-s2", 0.25, "shielded"));
|
||||
|
||||
// Empty group sums to 0.
|
||||
EXPECT_NEAR(SumPortfolioBalance({}, wallet), 0.0, 1e-9);
|
||||
// A group of two known addresses.
|
||||
EXPECT_NEAR(SumPortfolioBalance({"R-t1", "zs-s1"}, wallet), 11.5, 1e-9);
|
||||
// Unknown addresses contribute 0 (not present in the wallet).
|
||||
EXPECT_NEAR(SumPortfolioBalance({"R-t2", "does-not-exist"}, wallet), 2.0, 1e-9);
|
||||
// All shielded.
|
||||
EXPECT_NEAR(SumPortfolioBalance({"zs-s1", "zs-s2"}, wallet), 10.25, 1e-9);
|
||||
|
||||
// Membership + add/remove semantics.
|
||||
std::vector<std::string> group = {"R-t1"};
|
||||
EXPECT_TRUE(PortfolioEntryContains(group, "R-t1"));
|
||||
EXPECT_FALSE(PortfolioEntryContains(group, "R-t2"));
|
||||
EXPECT_TRUE(PortfolioEntryAdd(group, "R-t2")); // added
|
||||
EXPECT_FALSE(PortfolioEntryAdd(group, "R-t2")); // already present -> no-op
|
||||
EXPECT_EQ(group.size(), static_cast<size_t>(2));
|
||||
EXPECT_TRUE(PortfolioEntryRemove(group, "R-t1")); // removed
|
||||
EXPECT_FALSE(PortfolioEntryRemove(group, "R-t1"));// gone -> no-op
|
||||
EXPECT_EQ(group.size(), static_cast<size_t>(1));
|
||||
EXPECT_EQ(group[0], std::string("R-t2"));
|
||||
}
|
||||
|
||||
// ComputeConsoleFoldSpans — brace/bracket matching over pretty-printed JSON lines.
|
||||
void testConsoleFoldSpans()
|
||||
{
|
||||
@@ -5311,6 +5352,7 @@ int main()
|
||||
testDaemonLifecycleAdapters();
|
||||
testConsoleTextLayout();
|
||||
testConsoleModel();
|
||||
testPortfolioHelpers();
|
||||
testConsoleFoldSpans();
|
||||
testConsoleScrollController();
|
||||
testConsoleSelectionController();
|
||||
|
||||
Reference in New Issue
Block a user