Skip to content

Fix proposal voting#3119

Merged
feruzm merged 2 commits intodevelopmentfrom
prop
Feb 19, 2026
Merged

Fix proposal voting#3119
feruzm merged 2 commits intodevelopmentfrom
prop

Conversation

@feruzm
Copy link
Copy Markdown
Member

@feruzm feruzm commented Feb 19, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Fixed active proposal selection to display the latest ECENCY-created proposal instead of the first found.
    • Prevented the proposal vote UI from rendering when there is no active proposal selected.
  • Refactor

    • Streamlined proposal voting authentication to use a centralized auth context.
    • Simplified error handling and retry behavior for voting, with clearer user-facing notifications.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 19, 2026

No actionable comments were generated in the recent review. 🎉


📝 Walkthrough

Walkthrough

Refactored proposal voting auth to use a centralized auth context, selected the latest ECENCY-created active proposal by highest proposal_id, simplified broadcast/mutation and retry/error handling, and added a render guard when the active proposal id is missing.

Changes

Cohort / File(s) Summary
Proposal voting auth & broadcast
src/providers/queries/proposalQueries.ts
Replaced local credential handling (private keys, PIN, decrypt, HiveSigner flows) with useAuthContext; unified auth passed to broadcast mutation; simplified retry and error handling; active proposal query now selects highest proposal_id.
Render guard
src/components/proposalVoteRequest/container/proposalVoteRequest.tsx
Added skipRender guard and dependency for _ecencyProposalId to avoid rendering when the proposal id is falsy.
Dependency update
package.json
Bumped @ecency/sdk from ^2.0.5 to ^2.0.6.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Client as Client
participant UI as ProposalVoteRequest
participant Auth as AuthContext (useAuthContext)
participant Broad as BroadcastMutation
participant API as Hive/Blockchain API

Client->>UI: user votes on proposal
UI->>Auth: request auth (token/credentials)
Auth-->>UI: returns unified auth
UI->>Broad: call broadcastMutation with auth + vote
Broad->>API: send broadcast request
API-->>Broad: success / error
Broad-->>UI: result
UI-->>Client: show toast / update cache

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A little hop, a tidy refactor,
Auth in one basket, fewer things to proctor.
The newest proposal now takes the lead,
Broadcasts hum softly — cleaner code indeed. 🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix proposal voting' accurately reflects the main change in the changeset, which involves refactoring proposal voting logic to use a centralized auth context and fixing edge cases.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch prop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/providers/queries/proposalQueries.ts (1)

100-108: Duplicate operation definition — consider extracting a shared builder.

The update_proposal_votes operation object is defined identically in both the useBroadcastMutation builder (lines 82–91) and the mutationFn (lines 100–108). If one changes without the other, voting could break silently for certain auth types.

♻️ Extract a shared operation builder
 export const useProposalVoteMutation = () => {
   const dispatch = useAppDispatch();
   const intl = useIntl();
   const { executeOperation } = useActiveKeyOperation();
   const currentAccount = useAppSelector(selectCurrentAccount);
   const auth = useAuthContext();
 
+  const buildOperations = (proposalId: number) => [
+    [
+      'update_proposal_votes',
+      {
+        voter: currentAccount.name,
+        proposal_ids: [proposalId],
+        approve: true,
+        extensions: [],
+      },
+    ],
+  ];
+
   const broadcastMutation = useBroadcastMutation<{ proposalId: number }>(
     ['proposals', 'vote'],
     currentAccount.name,
-    ({ proposalId }) => [
-      [
-        'update_proposal_votes',
-        {
-          voter: currentAccount.name,
-          proposal_ids: [proposalId],
-          approve: true,
-          extensions: [],
-        },
-      ],
-    ],
+    ({ proposalId }) => buildOperations(proposalId),
     () => {},
     auth,
     'active',
   );
 
   return useMutation<any, Error, { proposalId: number }>({
     mutationFn: async ({ proposalId }) => {
-      const operation = [
-        'update_proposal_votes',
-        {
-          voter: currentAccount.name,
-          proposal_ids: [proposalId],
-          approve: true,
-          extensions: [],,
-        },
-      ];
-
       return executeOperation({
-        operations: [operation],
+        operations: buildOperations(proposalId),
         privateKeyHandler: async () => {
           return broadcastMutation.mutateAsync({ proposalId });
         },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/providers/queries/proposalQueries.ts` around lines 100 - 108, Duplicate
construction of the update_proposal_votes operation is present in both the
useBroadcastMutation builder and the mutationFn; extract a single helper like
buildUpdateProposalVotes(voter, proposalIds, approve) and replace both inline
operation arrays with calls to that helper, passing currentAccount.name and
[proposalId] (and approve: true) so both code paths use the identical operation
payload (ensure the helper returns the exact array shape used by
update_proposal_votes).
src/components/proposalVoteRequest/container/proposalVoteRequest.tsx (1)

68-70: Consider a non-null assertion or type guard for _ecencyProposalId.

While the skipRender guard on line 51 ensures _ecencyProposalId is truthy at runtime before _voteAction can be called, TypeScript won't narrow the type through the useMemo → early-return indirection. This means _ecencyProposalId is still typed as number | undefined on line 69, which may produce a type error when passed to mutate({ proposalId: number }).

🔧 Suggested fix
   const _voteAction = () => {
-    proposalVoteMutation.mutate({ proposalId: _ecencyProposalId });
+    proposalVoteMutation.mutate({ proposalId: _ecencyProposalId! });
   };

Or, for a safer alternative, add an explicit guard:

   const _voteAction = () => {
+    if (!_ecencyProposalId) return;
     proposalVoteMutation.mutate({ proposalId: _ecencyProposalId });
   };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/proposalVoteRequest/container/proposalVoteRequest.tsx` around
lines 68 - 70, The call to proposalVoteMutation.mutate passes _ecencyProposalId
which is typed number | undefined; update the _voteAction function to ensure a
non-null number is passed by either using a non-null assertion (e.g.
_ecencyProposalId!) or an explicit guard/early return that checks typeof
_ecencyProposalId === 'number' before calling mutate; reference the existing
_voteAction, _ecencyProposalId and proposalVoteMutation symbols so the compiler
sees a narrowed type when calling mutate.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/components/proposalVoteRequest/container/proposalVoteRequest.tsx`:
- Around line 68-70: The call to proposalVoteMutation.mutate passes
_ecencyProposalId which is typed number | undefined; update the _voteAction
function to ensure a non-null number is passed by either using a non-null
assertion (e.g. _ecencyProposalId!) or an explicit guard/early return that
checks typeof _ecencyProposalId === 'number' before calling mutate; reference
the existing _voteAction, _ecencyProposalId and proposalVoteMutation symbols so
the compiler sees a narrowed type when calling mutate.

In `@src/providers/queries/proposalQueries.ts`:
- Around line 100-108: Duplicate construction of the update_proposal_votes
operation is present in both the useBroadcastMutation builder and the
mutationFn; extract a single helper like buildUpdateProposalVotes(voter,
proposalIds, approve) and replace both inline operation arrays with calls to
that helper, passing currentAccount.name and [proposalId] (and approve: true) so
both code paths use the identical operation payload (ensure the helper returns
the exact array shape used by update_proposal_votes).

@feruzm feruzm merged commit 7aac834 into development Feb 19, 2026
1 of 3 checks passed
@feruzm feruzm deleted the prop branch February 19, 2026 08:03
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