feat/implement-grants-governance-proposal - #3245
Conversation
…4937) Add cost breakdown requirement, spending plan, and expenditure reporting to the grant application and milestone workflow per governance proposal. - New Budget step in grant application form (5-step flow) - Cost breakdown with freeform categories and line-item justification - Spending plan text field for allocation timeline - Standardized Grant Expenditure Report (SGER) form and view - Expenditure report submission via IPFS with local CID tracking - Soft warning on milestone claim when no report submitted - Budget tab on grant detail page - Full backward compatibility: existing grants render without new fields https://claude.ai/code/session_01ETAH8ARoCSmWYkdaKVHCVz
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Governance Frontend – Preview
Built with commit 3e47bfa • Preview environments are automatically destroyed when PRs are closed |
Use Fragment instead of nested Grid for rows so all cells are direct children of the same Grid and columns line up with the headers. https://claude.ai/code/session_01ETAH8ARoCSmWYkdaKVHCVz
Store SGER data in GrantsManager milestone metadata as versioned JSON (milestones + expenditureReports), merge on submit, and call updateMilestoneMetadataURI after pinning. Proposer-only UI for report submission; preserve reports when editing milestone dates. Remove local-only expenditure report CID store. Parse legacy array metadata for backward compatibility. Add i18n string for non-proposer grant recipients. Fix dynamic route Props exports and snapshot aria i18n for typecheck. Made-with: Cursor
Show the expenditure-report warning for the first milestone as well as later ones. Update copy to describe this payout milestone rather than "prior tranche" only. Made-with: Cursor
|
Adding structured financial accountability to the grant lifecycle without breaking existing grants.
Philosophy: additive-only changes (no schema breaks and no contracts changes), data ownership on-chain via IPFS, soft warnings over hard blocks for UX, and surgical scoping, only the grant flow was touched. |
…em in report form
- handleSaveEdit re-reads on-chain milestone metadata URI + IPFS doc before
rebuilding the payload, so concurrently submitted expenditure reports
(other tab, stale React Query cache) are no longer overwritten when a
proposer edits milestone dates. Surface a toast on IPFS upload failure
instead of silently returning.
- ExpenditureReportForm: replace raw <input>/<textarea> with Chakra Input,
Textarea, Field.Root, Field.Label. Drop inline pixel styles. Add min={0}
on number inputs. Use semantic status.negative.strong for negative
unspent amount.
- i18n: add "Failed to upload milestone metadata" across 17 locales and
sort all locale files alphabetically per translate skill rules.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ExpenditureReportView: - Flatten nested Grid (rows used inner Grid; headers misaligned). Use Fragment per row, mirroring CostBreakdownView. - Translate Yes/No/Partially achievement label. - Translate evidence type badge (GitHub/Demo/Dashboard/Audit Report/Other) with type-narrowed t() to satisfy strict i18n typing. - Add rel="noopener noreferrer" to external evidence links and switch to Chakra Link variant="underline" instead of raw blue.500. - Replace red.500 with semantic status.negative.strong for negative unspent display. ExpenditureReportForm: - Validate evidence URLs (must parse; protocol must be http(s)). - Require milestone explanation when status is no/partially. - Require totalReceivedForTranche to be > 0. - Translate evidence type select options. i18n: add GitHub, Demo, Audit Report, "Please specify the total amount received", "Please explain the milestone status" across 17 locales. Reuse the existing "Please enter a valid URL starting with http:// or https://" key from validators.ts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…cAlert - useUpdateGrantMilestoneMetadata: invalidate by ["grantProposalMetadata", proposalId] prefix instead of the full (proposalId, ipfsDescription) key. Catches the registered query regardless of the description CID used at call time, and removes the unused proposalIpfsDescription arg. - MilestoneItem: replace raw orange.50/600/700 SGER-missing warning block with GenericAlert type="warning". Aligns with the project's semantic alert pattern and drops raw palette colors. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ssion) Commit d3795ad switched [proposalId]/[grantId]/[appId] page.tsx Props from Promise<{...}> + await params back to a sync object to silence a typecheck error. In Next.js 15+/16, params is a Promise — accessing it synchronously yields undefined, so any downstream BigInt(proposalId) or similar coercion threw "Cannot convert undefined to a BigInt" the moment a user opened a proposal/grant/app page. Restore Promise-typed params with await across all three dynamic routes to match the layout.tsx pattern already in the codebase. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Card.Title renders <h3> and a Heading inside it renders <h2>, producing invalid HTML. Match the sibling "Results" section (which uses Heading directly with no Card.Title wrapper). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Non-blocking warning under the milestones grid when the sum of milestone amounts doesn't match the cost-breakdown total. Only triggers once both sides are populated so we don't pester users mid-edit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The expenditure report for Milestone N documents how its funds were spent, which is the proof reviewers use to fund Milestone N+1. Realign the UI to that semantic: - Missing-report warning + Approve & Fund override now check the previous milestone's report (Milestone 1 needs no precursor — first funding is never gated). - New warning copy names the two milestones explicitly. - Submit / Update CTA is no longer pinned to the current step; any milestone in InDevelopment (not Rejected) can be reported on by an authorized wallet, since reports are filed after each milestone closes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The mainnet rule (each milestone starts at least one day after the previous ends, end > start by a day) blocks practical end-to-end tests on testnet-staging. Gate that strictness behind getConfig().environment === "mainnet"; everywhere else, same-day chains are accepted and the DatePicker min-pickable date drops the +1 day buffer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
To test the full grant lifecycle quickly (e.g. milestones five minutes apart) the calendar in FormDateInput now exposes hour and minute inputs on every env except mainnet. Today becomes selectable, the popover stays open after picking a day so the tester can dial the time, and a Done button closes it. Mainnet behaviour is unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…mainnet) The grant-edit flow uses src/components/DatePicker (different from the form's FormDateInput). Add an opt-in enableTimeSelection prop: when on in single-variant mode, the popover exposes hour/minute inputs, stays open after the day click for fine-tuning, emits "YYYY-MM-DDTHH:mm", and shows a Done button. MilestoneItem turns it on when env != mainnet and seeds the duration state with HH:mm so existing milestone times round-trip correctly. Transaction-history range picker is untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…osals
Queued proposals can only run after the timelock delay elapses; the
button used to be enabled and tx reverted. Fetch proposalEta from
B3TRGovernor, tick a per-second clock while in Queued, and:
- Disable Execute Proposal while now < eta.
- Render an info alert ("Available to execute in 2h 14m 03s") so the
user knows when to come back.
useProposalEta refetches every 15s for stale-tab safety.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Once a proposal is past its timelock eta, simulate execute() against the node and: - Render an error alert with the decoded revert reason (e.g. "Treasury: transfer limit exceeded") so the executor isn't left guessing. - Disable the Execute Proposal button while the simulation indicates a revert; re-enables automatically when underlying state changes (re-checked every 30s). The simulator decodes Solidity Error(string) reverts and falls back to the raw hex / vmError otherwise. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…imed A report documents how a milestone's funds were spent, so the CTA only makes sense after the receiver has claimed that milestone. Previously every milestone in an InDevelopment grant showed Submit, including ones that had never been funded. New rule: Submit/Update is visible only when milestone.state === Claimed (and the wallet has permission). Read-only report cards keep showing on any milestone that already has a report, regardless of state. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…on report submit ExpenditureReportForm: - Prefill "Total received for this tranche (USD)" from milestone B3TR amount × current B3TR/USD price (only when creating a new report; Update mode keeps the existing value). Helper text explains the source so the user knows they can override. - Validation now produces inline Field.ErrorText / red borders per field instead of toasts, matching the grant creation form pattern. URL invalid → flags the specific evidence-row URL field. - Submit errors render as inline text under the form. MilestonesActions: - handleReportSubmit no longer toasts on success/error; it throws on failure so the form can surface the message inline. Success simply closes the modal (no toast). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the 12 expenditure-report / timelock / budget keys introduced in this branch to de, es, fr, hi, it, ja, ko, nl, pt, ro, ru, sv, tr, tw, vi, zh. Sorts every translation file (including en.json) alphabetically case-insensitive. Translations are best-effort and may benefit from a native-speaker pass, but they're consistent with the fixed-words convention (B3TR/VOT3/B3MO left untranslated; no endorsement-family terms in these strings). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rnance-proposal-Yxx0B # Conflicts: # apps/frontend/src/i18n/languages/de.json # apps/frontend/src/i18n/languages/en.json # apps/frontend/src/i18n/languages/es.json # apps/frontend/src/i18n/languages/fr.json # apps/frontend/src/i18n/languages/hi.json # apps/frontend/src/i18n/languages/it.json # apps/frontend/src/i18n/languages/ja.json # apps/frontend/src/i18n/languages/ko.json # apps/frontend/src/i18n/languages/nl.json # apps/frontend/src/i18n/languages/pt.json # apps/frontend/src/i18n/languages/ro.json # apps/frontend/src/i18n/languages/ru.json # apps/frontend/src/i18n/languages/sv.json # apps/frontend/src/i18n/languages/tr.json # apps/frontend/src/i18n/languages/tw.json # apps/frontend/src/i18n/languages/vi.json # apps/frontend/src/i18n/languages/zh.json
Add cost breakdown requirement, spending plan, and expenditure reporting
to the grant application and milestone workflow per governance proposal.
Frontend
Missing-report warning visibility
GrantsManager V2 -> V3 (contract upgrade)
updateMilestoneMetadataURIwidened from proposer-only to proposer + grants receiver + GRANTS_APPROVER_ROLE + GOVERNANCE_ROLEdeprecated/V2/; upgrade scriptgrants-manager-v3.ts+upgradesConfigentrydeployAllandtest/helpers/deployv3-metadata-access.test.ts(7 tests, shard4k); 36 existing milestone-creation tests still passDemos
New grants creation step
Registrazione.schermo.2026-05-25.alle.15.57.16.mov
First milestone approval (no change)
Registrazione.schermo.2026-05-25.alle.17.04.37.mov
Expenditure report
add.report.mov
Staging demo grant: https://staging.testnet.governance.vebetterdao.org/grants/17676221342976277228059531915983165507149829855567351017761942598283788656553