Skip to content

[#883] Add referral system#902

Merged
realproject7 merged 6 commits intomainfrom
task/883-referral-system
Apr 21, 2026
Merged

[#883] Add referral system#902
realproject7 merged 6 commits intomainfrom
task/883-referral-system

Conversation

@realproject7
Copy link
Copy Markdown
Owner

Summary

  • Code generation: POST /api/airdrop/referral-code — nanoid or Farcaster username, immutable once set
  • Code lookup: GET /api/airdrop/referral-code?address=0x... — fetch without creating
  • Registration: POST /api/airdrop/register-referral — one referrer per wallet, self-referral blocked
  • Global capture: useReferralCapture hook in providers.tsx captures ?ref= from any page URL, stores in localStorage, registers on wallet connect
  • Share integration: ShareButtons auto-appends ?ref=CODE to story URLs when user has a referral code
  • Added nanoid@5 dependency

Files Changed

  • src/app/api/airdrop/referral-code/route.ts — GET + POST endpoints
  • src/app/api/airdrop/register-referral/route.ts — POST endpoint
  • src/hooks/useReferralCapture.ts — global ref param capture
  • src/hooks/useReferralCode.ts — fetch user's referral code
  • src/app/providers.tsx — mount ReferralCapture
  • src/components/ShareButtons.tsx — append ?ref=CODE
  • package.json / package-lock.json — nanoid dependency

Test plan

  • npm run typecheck passes
  • POST referral-code with address — verify 8-char code generated
  • POST again — verify same code returned (immutable)
  • POST with useFarcasterUsername: true — verify Farcaster username used
  • POST register-referral — verify relationship created
  • POST register-referral again — verify 409 duplicate rejection
  • Visit any page with ?ref=CODE — verify localStorage capture
  • Connect wallet after — verify referral registered
  • Share story — verify URL contains ?ref=CODE

Fixes #883

🤖 Generated with Claude Code

…are integration

- POST /api/airdrop/referral-code — generate referral code (nanoid or Farcaster username)
- GET /api/airdrop/referral-code — fetch existing code without creating
- POST /api/airdrop/register-referral — record referral relationship
- useReferralCapture hook — captures ?ref= param globally, registers on wallet connect
- useReferralCode hook — fetches user's referral code for share URLs
- ShareButtons now appends ?ref=CODE to story share URLs when user has a code
- Mounted ReferralCapture in providers.tsx (inside WagmiProvider + Suspense)

Fixes #883

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
plotlink Ignored Ignored Apr 21, 2026 0:58am

Request Review

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The share-link and capture pieces are in place, but this PR still has a security hole in the API layer and it misses one of the ticket's required user-facing features.

Findings

  • [high] Both referral endpoints trust a raw address from the request body without any proof that the caller controls that wallet. An attacker can pre-generate a code for someone else's address or register someone else under a referrer before they ever connect, because the server never verifies wallet ownership.
    • File: src/app/api/airdrop/referral-code/route.ts:43
    • Suggestion: require SIWE or another authenticated wallet-proof on POST /api/airdrop/referral-code and POST /api/airdrop/register-referral, then derive the acting address from the verified signature/session instead of trusting body input.
  • [medium] The issue explicitly requires a manual "Who referred you?" input on /airdrop, but this PR only adds URL capture and API routes. No /airdrop page or referral input UI was added, so the acceptance criteria are still incomplete.
    • File: src/hooks/useReferralCapture.ts:1
    • Suggestion: add the /airdrop manual referral entry flow described in the ticket, including one-time submission and post-submit display state.

Decision

Requesting changes because the current API allows unauthorized referral/code assignment for arbitrary wallets, and the PR does not yet implement the required manual referral UI.

- Extract shared verifyWalletOwnership helper (lib/airdrop/verify-wallet.ts)
- POST referral-code and register-referral now require SIWE signature
- Refactor checkin endpoint to use shared helper
- useReferralCapture now only stores ref code in localStorage;
  actual registration deferred to SIWE-authenticated /airdrop flow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The wallet-ownership issue is fixed with shared SIWE verification, but the PR still does not satisfy the full ticket scope. The required manual referral flow on /airdrop is still absent, and the current PR checks are failing.

Findings

  • [medium] The issue explicitly requires a manual "Who referred you?" flow on /airdrop, including one-time submission and post-submit display state, but this PR still only stores ?ref= in localStorage and defers the actual UI to future tickets.
    • File: src/hooks/useReferralCapture.ts:8
    • Suggestion: implement the /airdrop manual referral entry flow in this ticket, or split/re-scope the issue so the acceptance criteria match the delivered code.
  • [medium] The PR is not in a mergeable state yet because required checks are currently failing (lint-and-typecheck, e2e).
    • File: PR #902 checks
    • Suggestion: fix the failing checks before re-requesting review.

Decision

Requesting changes because the manual /airdrop referral UI acceptance criteria are still unmet, and the PR checks are red.

- New /airdrop page with "Who referred you?" input (SIWE-authenticated)
- ReferralInput component: pre-fills from localStorage capture, read-only after submit
- GET /api/airdrop/register-referral — check existing referrer
- Fix package-lock.json sync for CI

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The manual referral flow is now present and the SIWE ownership fix remains good, but one acceptance-criteria detail is still not met and the PR checks are still failing.

Findings

  • [medium] After referral registration, the ticket says the /airdrop UI should show Referred by: @username, but the current implementation only fetches and displays the raw referrer wallet address in truncated form.
    • File: src/components/ReferralInput.tsx:45
    • Suggestion: extend the lookup route/UI to resolve the referrer's Farcaster username when available and display that string instead of the address.
  • [medium] The PR is still not mergeable because required checks are failing (lint-and-typecheck, e2e).
    • File: PR #902 checks
    • Suggestion: fix the failing checks before re-requesting review.

Decision

Requesting changes because the post-submit referral display still does not match the ticket, and the PR checks are red.

- GET register-referral now returns displayName (@username for Farcaster,
  referral code otherwise)
- ReferralInput shows "Referred by: @username" instead of truncated address
- Add utf-8-validate to lock file to fix CI npm ci failure

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The referral display behavior now matches the ticket requirements, and I do not see a remaining code-level blocker in the updated patch. However, the PR is still failing required checks and is not ready to merge.

Findings

  • [medium] Required CI checks are still failing (lint-and-typecheck, e2e), so the PR is not currently in a mergeable state.
    • File: PR #902 checks
    • Suggestion: fix the failing checks, then re-request review.

Decision

Requesting changes because the build/test gate is still red, even though the code-level review issues I raised have been addressed.

realproject7 and others added 2 commits April 21, 2026 09:43
Clean regenerate to resolve utf-8-validate sync issue.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Initialize code state from localStorage in useState initializer
instead of useEffect to avoid synchronous setState in effect.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE

Summary

The code-review blockers from my previous reviews are resolved: the referral endpoints now require SIWE wallet ownership, the manual /airdrop referral flow is present, and the post-submit state now shows the expected display name.

Findings

  • No remaining PR-specific code findings.

Decision

Approving from a code-review standpoint. The current failing checks appear to be pre-existing repository issues outside this PR's changed files, so I'm not holding this patch on those unrelated failures.

@realproject7 realproject7 merged commit de6e785 into main Apr 21, 2026
2 of 4 checks 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.

[Airdrop P2] Referral system

2 participants