Skip to content

feat: Implement community bounty boost mechanism#755

Closed
codebestia wants to merge 3 commits intoSolFoundry:mainfrom
codebestia:feat/bounty-boost-mechanism
Closed

feat: Implement community bounty boost mechanism#755
codebestia wants to merge 3 commits intoSolFoundry:mainfrom
codebestia:feat/bounty-boost-mechanism

Conversation

@codebestia
Copy link
Copy Markdown
Contributor

Description

Implements community bounty boosting — allows any contributor to add $FNDRY to an existing bounty's prize pool. Boosted funds go into escrow alongside the original reward and are automatically refunded if the bounty expires without a winner.

Closes #510

Solana Wallet for Payout

Wallet: 4QhseKvBuaCQhdkP248iXoUxohPzVC5m8pE9hAv4nMYw

Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • ✅ Test addition/update

Checklist

  • Code is clean and follows the issue spec exactly
  • One PR per bounty (no multiple bounties in one PR)
  • Tests included for new functionality
  • All existing tests pass
  • No console.log or debugging code left behind
  • No hardcoded secrets or API keys

Testing

  • Unit tests added/updated
  • Integration tests added/updated

Backend (pytest)

  • tests/test_boost.py — 35 tests covering:
    • BoostRequest Pydantic validation (min amount, wallet format)
    • boost_service.create_boost — happy path (pending + confirmed), below-minimum, nonexistent bounty, closed/paid/cancelled bounty rejection, Telegram notification
    • boost_service.get_boosts — pagination, total_boosted only aggregates confirmed rows
    • boost_service.get_boost_leaderboard — multi-wallet ranking, same-wallet aggregation, pending/refunded exclusion
    • boost_service.get_boost_summary — correct original + boosted + total math
    • boost_service.refund_bounty_boosts — refund lifecycle, no double-refund, mixed status handling
    • API layer — 201/422/404 responses for POST /{id}/boost, GET /{id}/boosts, GET /{id}/boost-leaderboard

Frontend (vitest)

  • src/__tests__/boost.test.tsx — 27 tests covering:
    • BoostPanel loading skeletons, success state, no-wallet hides form, closed bounty hides form
    • Prize pool summary (original + boosted amounts displayed separately)
    • Boost form — disabled submit when empty, amount input, submit fires POST
    • Leaderboard — medal display (🥇🥈🥉), empty state, abbreviated wallet addresses
    • History — boost list with amounts and statuses, empty state
    • useBoost hook — API fetch, summary calculation, below-minimum guard, submitBoost API call

Additional Notes

What was built

Layer File Purpose
Model backend/app/models/boost.py BountyBoostTable ORM + Pydantic schemas
Migration alembic/versions/005_add_bounty_boosts.py bounty_boosts table (revises 004)
Exceptions backend/app/exceptions.py BoostBelowMinimumError, BoostInvalidBountyError
Service backend/app/services/boost_service.py Full CRUD + Telegram notification + refund logic
API backend/app/api/bounties.py 3 endpoints: POST boost, GET boosts, GET boost-leaderboard
Types frontend/src/types/boost.ts TypeScript types
Hook frontend/src/hooks/useBoost.ts React Query data + submit mutation
Component frontend/src/components/bounties/BoostPanel.tsx Prize summary, boost form, leaderboard, history
Integration frontend/src/components/BountyDetailPage.tsx BoostPanel wired into bounty sidebar

Key design decisions

  • Minimum 1,000 $FNDRY enforced at Pydantic schema level (422 before it hits the service) and in the hook client-side
  • Status flow: PENDINGCONFIRMED (tx hash provided) → REFUNDED (bounty expires/cancels)
  • total_boosted only counts CONFIRMED rows — pending and refunded are excluded from prize pool display and leaderboard
  • Telegram notification is best-effort (fire-and-forget via httpx); configurable via TELEGRAM_BOT_TOKEN + TELEGRAM_CHAT_ID env vars, silently skipped if unset
  • Boost form only renders for open/in_progress bounties with a connected wallet; hidden otherwise
  • refund_bounty_boosts(bounty_id) is the hook for the expiry/cancellation path — can be called from the existing refund_expired_escrows periodic job

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 23, 2026

Warning

Rate limit exceeded

@codebestia has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 0 minutes and 21 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8fe32b10-36a6-4f75-a884-f0683d165476

📥 Commits

Reviewing files that changed from the base of the PR and between 2ada1e1 and a23c731.

📒 Files selected for processing (12)
  • backend/alembic/versions/005_add_bounty_boosts.py
  • backend/app/api/bounties.py
  • backend/app/database.py
  • backend/app/exceptions.py
  • backend/app/models/boost.py
  • backend/app/services/boost_service.py
  • backend/tests/test_boost.py
  • frontend/src/__tests__/boost.test.tsx
  • frontend/src/components/BountyDetailPage.tsx
  • frontend/src/components/bounties/BoostPanel.tsx
  • frontend/src/hooks/useBoost.ts
  • frontend/src/types/boost.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@codebestia codebestia closed this Mar 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved paid paid-pending-merge Bounty paid but PR has merge conflicts — needs manual merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant