Skip to content

Closes #969 - #976

Merged
Chucks1093 merged 1 commit into
accesslayerorg:mainfrom
actvabdulrahman:main
Sep 27, 2026
Merged

Chucks1093 merged 1 commit into
accesslayerorg:mainfrom
actvabdulrahman:main

Conversation

@actvabdulrahman

Copy link
Copy Markdown
Contributor

Summary

  • Investigated issue Implement governance proposal submission and voting API #969 ("Implement governance proposal submission and voting API") and found the 4 requested REST endpoints already exist off-chain (proposal creation, list, detail, vote — see src/modules/keys/keys.routes.ts and src/modules/creators/creators.routes.ts), including eligibility checks and DB-level double-vote prevention (@@unique([keyId, proposalId, voter])). No governance smart contract exists yet in accesslayer-contracts, so real on-chain submission and event-driven state sync are genuinely blocked, not something this PR can complete — see "Scope descoped" below.
  • Found and fixed one real, concrete bug uncovered during that investigation: castKeyProposalVote inserted a GovernanceVote row but never updated GovernanceProposal.totalVotingWeight or results, so list/detail tallies were immediately stale after every vote cast.
  • Fix: inside the existing atomic $transaction, the proposal is re-read, its active status re-checked, and a new pure helper applyVoteWeight increments totalVotingWeight and results[optionIndex] alongside the vote insert and activity log — all in the same transaction, so a vote can never be recorded without its tally updating (or vice versa).
  • Added src/modules/keys/key-proposal-votes.service.test.ts with mocked-Prisma unit tests covering applyVoteWeight directly (single vote, repeated same option, distinct options tracked independently, untouched result buckets preserved, large totals without floating-point drift via toBigInt) and the full castKeyProposalVote flow (tally accumulation across 3 distinct wallets/options, and every existing guard still enforced: DuplicateVoteError, HolderNotEligibleError, OptionIndexOutOfRangeError, closed-proposal rejection).

Scope descoped (blocked, tracked for a follow-up issue): real on-chain contract submission (create_proposal/cast_vote are currently TODO stubs; submitTransaction is a non-functional placeholder; no governance contract or Soroban client binding exists in this repo) and event-driven proposal-state sync (no Soroban event fetcher exists anywhere in the codebase; the existing governance-sync.job.ts only does time-based expiry). Both require a governance contract to be defined in accesslayer-contracts first — attempting them here would mean building against something that doesn't exist.

Testing

  • pnpm lint
  • pnpm build
  • pnpm exec prisma generate when schema or generated types changed

(No Prisma schema changes were made — this fix only touches service logic and adds tests, so prisma generate isn't applicable. pnpm test src/modules/keys/key-proposal-votes.service.test.ts also run: 13/13 pass.)

Checklist

  • Linked issue or backlog item
  • No secrets or live credentials added
  • Docs updated if setup or env changed
  • Change is scoped to one problem

(No docs updates needed — no setup or environment variables changed; this is a pure bugfix within existing service logic.)

@drips-wave

drips-wave Bot commented Sep 27, 2026

Copy link
Copy Markdown

Hey @actvabdulrahman! 👋 It looks like this PR isn't linked to any issue.

If this PR is for one of the issues assigned to you as part of a Wave, please link it to ensure your contribution is tracked properly. You can do this by adding a keyword to the PR description (e.g., Closes #123), or by clicking a button below:

Issue Title
#969 Implement governance proposal submission and voting API Link to this issue

ℹ️ Learn more about linking PRs to issues

@Chucks1093
Chucks1093 merged commit c9161c4 into accesslayerorg:main Sep 27, 2026
1 check passed
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.

2 participants