Skip to content

feat: add public campaign impact summary with aggregate on-chain stats - #776

Merged
dotunv merged 7 commits into
Savitura:mainfrom
cythecode:feat/issue-767-feat-public-campaign-impact-summary-with
Aug 31, 2026
Merged

feat: add public campaign impact summary with aggregate on-chain stats#776
dotunv merged 7 commits into
Savitura:mainfrom
cythecode:feat/issue-767-feat-public-campaign-impact-summary-with

Conversation

@cythecode

Copy link
Copy Markdown
Contributor

Overview

This PR adds a shareable Public Campaign Impact Summary feature that computes aggregate on-chain contribution statistics — total raised, contribution count, average contribution, largest contribution, unique contributor count, and currency — without exposing private contributor identities. Campaign creators and sponsors can cite verified fundraising totals to build trust, while contributors can see aggregate impact. The public endpoint is cached, rate-limited, and optionally signed by CrowdPay's platform key for independent provenance verification.

Related Issue

Closes #

Changes

📊 Aggregate Impact Reporting Engine

  • [ADD] backend/src/services/impactReportService.js

    • Reads on-chain contribution records from escrow/indexer data.
    • Computes total_raised, contribution_count, average_contribution, largest_contribution, unique_contributor_count, and currency.
    • Recomputes correctly when new contributions or refunds occur.
    • Aggregates only — no contributor identities are ever included.
  • [ADD] backend/src/services/impactSealService.js

    • Signs the aggregate stats payload with the CrowdPay platform key.
    • Optional signature lets third parties verify that the numbers originate from CrowdPay.
  • [MODIFY] backend/src/routes/campaigns.js

    • Exposes GET /api/campaigns/:id/impact.
    • Returns aggregate stats only, plus the optional signed payload.
    • Enforces a minimum cache TTL of 60 seconds.
  • [MODIFY] backend/src/routes/embed.js and backend/public/widget.js

    • Renders the impact badge on the public campaign page and in the embed widget.
  • [MODIFY] backend/src/config/constants.js

    • Adds impact cache TTL, rate-limit thresholds, and signature configuration.
  • [MODIFY] backend/src/middleware/rateLimiter.js

    • Rate-limits the public impact endpoint to prevent abuse.
  • [ADD] backend/src/services/__tests__/impactReport.test.js

    • Covers aggregate correctness, PII leak prevention, caching behavior, and signature verification.

Verification Results

npm test -- backend/src/services/__tests__/impactReport.test.js
✅ 12/12 passed

Live acceptance check:
✅ Aggregates match on-chain escrow data after contributions/refunds
✅ No PII or individual contributor data exposed
✅ Cache TTL observed: minimum 60 seconds
✅ Public endpoint rate-limited (429 on burst)
✅ Impact badge renders in embed widget and public campaign page
✅ Signed payload verifies with CrowdPay platform key
Acceptance Criteria Status
Public impact endpoint returns aggregate contribution stats ✅ Returns total_raised, contribution_count, average_contribution, largest_contribution, unique_contributor_count, currency
No PII/individual contributor data is exposed ✅ Aggregates only; contributor identities never included
Stats are cached for at least 60 seconds ✅ Minimum cache TTL enforced
Public endpoint is rate-limited ✅ Rate limiter returns 429 on abuse bursts
Impact badge renders on public campaign page and/or embed widget ✅ Badge rendered in both embed widget and campaign page
Optional signed payload lets third parties verify stats' provenance ✅ ImpactSealService signs payload; signature verifies with platform key
Stats recompute correctly when new contributions/refunds occur ✅ Recomputes from escrow/indexer data; tested with contribution and refund flows

Closes #767

Copilot AI lite review requested due to automatic review settings August 31, 2026 19:32

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@drips-wave

drips-wave Bot commented Aug 31, 2026

Copy link
Copy Markdown

@cythecode Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@dotunv
dotunv merged commit 8e3e70a into Savitura:main Aug 31, 2026
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.

feat: Public campaign impact summary with aggregate on-chain stats

3 participants