Skip to content

feat: Implement community bounty boosting#750

Closed
codebestia wants to merge 1 commit intoSolFoundry:mainfrom
codebestia:feat/bounty-boost-mechanism
Closed

feat: Implement community bounty boosting#750
codebestia wants to merge 1 commit 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

@codebestia codebestia closed this Mar 23, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 23, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a0b8442c-79f4-45c7-9fdd-2957f94a9d7e

📥 Commits

Reviewing files that changed from the base of the PR and between 9fc631f and 7e4f3fb.

📒 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

📝 Walkthrough

Walkthrough

This PR implements a complete "bounty boost" feature enabling community members to add funds to bounty prize pools. It includes a new bounty_boosts database table (with migration), three REST API endpoints (POST to create boosts, GET for boost history and leaderboard), backend service layer for boost creation/queries/refunds, ORM models and Pydantic schemas, custom exceptions, a React component (BoostPanel) and custom hook (useBoost) for the frontend UI, TypeScript types, and comprehensive test coverage for both backend services and frontend components.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Possibly related PRs

Suggested labels

approved, paid

Suggested reviewers

  • chronoeth-creator
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

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