Skip to content

feat(ui): group Masternodes and Voting under a Governance menu - #924

Merged
QuantumExplorer merged 3 commits into
developfrom
feat/governance-menu
Aug 7, 2026
Merged

feat(ui): group Masternodes and Voting under a Governance menu#924
QuantumExplorer merged 3 commits into
developfrom
feat/governance-menu

Conversation

@QuantumExplorer

@QuantumExplorer QuantumExplorer commented Aug 7, 2026

Copy link
Copy Markdown
Member

What

Two menu changes, one commit each.

1. Governance submenu. The main menu's "Voting" row becomes Governance, a new submenu holding Masternodes (moved out of Tools) and Voting.

2. Retired masternodes collapse. The Masternodes list splits into two sections: registrations still on the network stay expanded at the top, retired ones move to a DisclosureGroup at the bottom, collapsed by default with a count on its label.

Decisions worth reviewing

Governance is not DashPay-gated, unlike the row it replaces. The old Voting row required #if DASHPAY and VotingPrefs.votingEnabled. Masternodes was never gated at all, so gating the parent would have made it unreachable in the dashwallet scheme — a regression. Governance is therefore always present and its contents adapt: Masternodes always, Voting only under DASHPAY when the preference is on. With voting disabled, Governance holds Masternodes alone.

Masternodes moves rather than being duplicated, keeping one path to the screen. "Masternode Keychain" stays in Tools — that is key material, not governance. Say the word if you want a Tools shortcut kept as well.

Only retired collapses. MasternodeStatus has four cases; inactive (PoSe-banned) and unknown (masternode list not yet synced) stay in the top section alongside active. A banned node is a problem worth surfacing and unknown is a transient sync state, so burying either would hide something actionable. Trivial to change if you want the top section to be strictly active.

Notes

  • The Masternodes hosting wrapper (UIHostingController + NavigationStack, needed for row drill-downs) and the UIKit push for UsernameVotingViewController move verbatim — behaviour unchanged.
  • New screen follows the SwiftUI-first rule: GovernanceMenuScreen + @MainActor GovernanceMenuViewModel, matching the ToolsMenuScreen idiom.
  • Both list sections render only when non-empty, so a wallet with no retired nodes sees no stray disclosure row; the existing empty state is untouched.
  • One new English string (Governance); Retired already existed.

Not included

A PoSe score next to the status ("Active — With Score 5") was requested and is not implementable from our data, so nothing was built. The score (nPoSePenalty) is not in the DML wire format that an SPV client receives — MasternodeListEntry carries only is_valid, and that boolean is already what drives the existing "Inactive" label. pose_penalty exists in rust-dashcore solely under rpc-json, i.e. the full-node protx RPC surface. Surfacing a real score would mean querying a Core node, which is a separate architectural decision for a screen that is currently a pure local snapshot.

Verification

dashpay scheme builds clean (arm64 simulator) from develop with no dependency on #922, and was installed to the simulator. Not visually confirmed on-device: the simulator is PIN-gated.

Summary by CodeRabbit

  • New Features

    • Added a Governance section to the main menu.
    • Added access to Masternodes and, when enabled, Username Voting.
    • Separated active and retired masternode registrations, with retired nodes shown in a collapsible section.
  • Improvements

    • Moved Masternodes from the Tools menu into Governance.
    • Added English labels for Governance and username voting features.

QuantumExplorer and others added 2 commits August 7, 2026 19:58
Main menu: "Voting" becomes "Governance", a submenu holding Masternodes
(moved out of Tools) and Voting.

Gating changes deliberately. The old Voting row was `#if DASHPAY` plus
`VotingPrefs.votingEnabled`; Governance carries neither, because
Masternodes was never DashPay-gated and gating the parent would make it
unreachable in the dashwallet scheme. Governance is therefore always
present, and its contents adapt: Masternodes always, Voting only under
DASHPAY when the preference is on. With voting off, Governance holds
Masternodes alone.

Masternodes moves rather than being duplicated — one path to the screen.
"Masternode Keychain" stays in Tools; that is key material, not
governance. The hosting wrapper (UIHostingController + NavigationStack
for row drill-downs) and the UIKit push for UsernameVotingViewController
move verbatim, so behaviour is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Registrations still on the network stay expanded at the top; retired
ones move to a DisclosureGroup at the bottom, collapsed by default with
a count on its label.

Only `retired` (collateral spent / revoked / expired) moves down.
`inactive` (PoSe-banned) and `unknown` (masternode list not yet
synced) stay in the top section: a banned node is a problem worth
surfacing, and unknown is a transient sync state, so burying either
would hide something actionable.

Both sections render only when non-empty, so a wallet with no retired
nodes sees no stray disclosure row, and the existing empty state is
untouched. Row construction is shared between the two sections rather
than duplicated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b90ecb67-77f7-478e-8b8d-d35ae48560e8

📥 Commits

Reviewing files that changed from the base of the PR and between 2d64eb5 and bc7a325.

📒 Files selected for processing (1)
  • DashWallet/Sources/UI/Menu/Governance/GovernanceMenuViewModel.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • DashWallet/Sources/UI/Menu/Governance/GovernanceMenuViewModel.swift

📝 Walkthrough

Walkthrough

The PR adds a Governance submenu, moves Masternodes into it, conditionally exposes username voting, and separates current and retired masternode registrations.

Changes

Governance menu

Layer / File(s) Summary
Governance screen and destinations
DashWallet/Sources/UI/Menu/Governance/*, DashWallet/en.lproj/Localizable.strings, DashWallet.xcodeproj/project.pbxproj
Adds the Governance view model and screen. The screen routes to Masternodes and, when enabled, username voting. The project includes both new Swift files and localization entries.
Main menu Governance routing
DashWallet/Sources/UI/Menu/Main/*
Replaces the voting menu destination with an always-available Governance destination and presents GovernanceMenuScreen.
Masternode placement and registration sections
DashWallet/Sources/UI/Menu/Tools/*
Removes Masternodes from the Tools menu. MasternodesScreen separates current and retired registrations, with retired entries in a collapsed disclosure section.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MainMenuViewController
  participant GovernanceMenuScreen
  participant MasternodesScreen
  MainMenuViewController->>GovernanceMenuScreen: Present Governance
  GovernanceMenuScreen->>MasternodesScreen: Push Masternodes
  MasternodesScreen-->>GovernanceMenuScreen: Navigate back
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: grouping Masternodes and Voting under a new Governance menu.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/governance-menu

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@DashWallet/Sources/UI/Menu/Governance/GovernanceMenuViewModel.swift`:
- Around line 17-28: Add an explicit Combine import alongside Foundation in
GovernanceMenuViewModel.swift so ObservableObject and `@Published` resolve
directly from their defining module.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6a1432aa-5267-4e57-a103-352ecd37635b

📥 Commits

Reviewing files that changed from the base of the PR and between 9e3b0e4 and 2d64eb5.

📒 Files selected for processing (9)
  • DashWallet.xcodeproj/project.pbxproj
  • DashWallet/Sources/UI/Menu/Governance/GovernanceMenuScreen.swift
  • DashWallet/Sources/UI/Menu/Governance/GovernanceMenuViewModel.swift
  • DashWallet/Sources/UI/Menu/Main/MainMenuViewController.swift
  • DashWallet/Sources/UI/Menu/Main/MainMenuViewModel.swift
  • DashWallet/Sources/UI/Menu/Tools/MasternodesScreen.swift
  • DashWallet/Sources/UI/Menu/Tools/ToolsMenuScreen.swift
  • DashWallet/Sources/UI/Menu/Tools/ToolsMenuViewModel.swift
  • DashWallet/en.lproj/Localizable.strings
💤 Files with no reviewable changes (2)
  • DashWallet/Sources/UI/Menu/Tools/ToolsMenuScreen.swift
  • DashWallet/Sources/UI/Menu/Tools/ToolsMenuViewModel.swift

Comment thread DashWallet/Sources/UI/Menu/Governance/GovernanceMenuViewModel.swift
`ObservableObject` and `@Published` are Combine symbols; the file
imported only Foundation and relied on transitively picking them up.
It compiled either way, but every sibling menu view model
(MainMenuViewModel, ToolsMenuViewModel, SettingsMenuViewModel) imports
Combine explicitly — this was the outlier.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@QuantumExplorer
QuantumExplorer merged commit 3ee774e into develop Aug 7, 2026
3 checks passed
QuantumExplorer added a commit that referenced this pull request Aug 7, 2026
develop does not compile: #923 and #924 collided after both merged
green independently.

#923 replaced UsernameVotingViewController with the SwiftUI
UsernameVotingScreen and updated the showVoting() that lived in
MainMenuViewController when that PR was written. #924 had since moved
the Voting entry point into GovernanceMenuScreen, which #923 never saw.

On the merged tip the live entry point (Governance) still called the
deleted controller — a hard build error — while the updated copy in
MainMenuViewController was orphaned, since #924 removed its caller.

Points Governance at UsernameVotingScreen (exactly what #923 wrote, in
the location that is actually reachable) and deletes the dead copy.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant