[#1255] Refactor ClaimPanel → ClaimCard (v5 breakdown + deadline)#1293
Conversation
ClaimCard handles 3 settlement variants: normal (proof + breakdown + claim), final-burn (burn tx link), not-eligible. Normal variant: breakdown from /projection (spend × multiplier), claim amount from /proof (authoritative), on-chain claimDeadline countdown with post-deadline disable. ClaimPanel becomes thin wrapper around ClaimCard mode="normal". Closes #1255 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
realproject7
left a comment
There was a problem hiding this comment.
@re2 review — APPROVE ✅
Checked against issue #1255 acceptance criteria:
| Criterion | Status |
|---|---|
Breakdown from /projection (spend × multiplier = weighted spend) |
✅ |
Claim amount from /proof (authoritative, never overridden) |
✅ |
claimDeadline from on-chain MerkleClaim.claimDeadline() |
✅ useReadContract |
| Post-deadline: button disabled + "Claim Window Closed" | ✅ |
| Real-time countdown (days + hours) | ✅ 1s interval |
| All 3 variants (normal, final-burn, not eligible) | ✅ |
| Already claimed: shows "Claimed" + explorer link | ✅ |
ClaimPanel → thin wrapper <ClaimCard mode="normal" /> |
✅ net -234 lines |
| Version 1.39.0 → 1.40.0 (feature) | ✅ |
Code review notes:
- Source-of-truth correct:
/proof.amountfor claim tx,/projectionfor display breakdown, on-chain for deadline - Component split clean:
ClaimCard→FinalBurnCard|NormalClaimCard→ClaimCardInner - Uses
EXPLORER_URLfrom constants (not hardcoded basescan) useReadContractforclaimed()gated onproofData.eligible— avoids unnecessary RPC calls- Claim tx:
writeContract→onSuccesscaptures hash →useWaitForTransactionReceiptconfirms staleTime: Infinityon proof query — correct, proofs are immutable once finalized
No blocking issues found.
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: REQUEST CHANGES
Summary
The refactor keeps the proof-backed claim path and adds the v5 breakdown/deadline UI, but it misses the explicit source-of-truth guard for finalized proof vs live projection divergence.
Findings
- [high] Live projection breakdown is shown unconditionally, even when it can diverge from the finalized claim amount.
- File:
src/components/airdrop/ClaimCard.tsx:170 - #1255 explicitly says
/proof.amountis authoritative and/projectionis explanatory only; if/projection.weighted_spendand/proof.amountimply a material mismatch (>1% delta), the claim amount must remain visible/actionable but the breakdown must be hidden or marked stale/unavailable. This implementation renders the projection breakdown wheneverprojectionexists and never compares it againstproofData.amount, so users can see a confident breakdown that does not explain the actual on-chain claim. - Suggestion: compare the projected claim implied by projection data to
proofData.amount; when the delta is over the tolerance, keep the claim UI enabled using/proof.amountbut suppress the breakdown or show a clear stale/unavailable message.
- File:
Decision
Requesting changes until the projection/proof divergence guard from #1255 is implemented. CI was still pending at review time.
When /projection implied amount diverges >1% from /proof amount, breakdown is marked stale/unavailable instead of showing potentially misleading numbers. Claim button remains actionable with /proof amount (authoritative). Normal case shows full breakdown. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: REQUEST CHANGES
Summary
The divergence guard has been added, but the comparison uses incompatible units and will incorrectly mark valid breakdowns stale.
Findings
- [high] Projection/proof divergence check compares PLOT amount to a unitless share fraction.
- File:
src/components/airdrop/ClaimCard.tsx:171 proofAmountNumis the finalized claim amount in PLOT afterformatUnits, whileimpliedAmountisweighted_spend / community_total, a fractional share between 0 and 1. For a valid claim of, say, 100 PLOT with a 0.0005 pool share, this computes almost 100% delta and hides the normal breakdown even when it is correct. #1255 requires hiding/marking stale only for material divergence, not for every normal claim.- Suggestion: compare
/proof.amountto a projected claim amount in the same units, e.g. use the relevantprojection.projected_share.<tier>value for the finalized settlement tier if available, or omit the delta check and mark breakdown stale only when the endpoint cannot provide a same-unit projected amount. Keep the claim button driven by/proof.amount.
- File:
Decision
Requesting changes until the divergence guard compares values in the same units and preserves the normal breakdown for matching claims. CI was still pending at review time.
…laim
Remove broken unit-mismatch comparison. Breakdown always shown as
explanatory ("How your share was calculated") with clear note that
final claim amount is from the on-chain settlement. Claim button
always driven by /proof.amount (authoritative).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: REQUEST CHANGES
Summary
The unit-mismatch comparison was removed, but the PR still does not satisfy #1255’s divergence handling requirement. Without a same-unit check, the UI should not present live projection math as “how your share was calculated.”
Findings
- [high] Projection breakdown is still presented as authoritative calculation when divergence cannot be checked.
- File:
src/components/airdrop/ClaimCard.tsx:172 - #1255 requires that when
/projectionand/proof.amountmaterially diverge, the proof amount stays actionable and the breakdown is hidden or marked stale/unavailable. The updated code no longer attempts the invalid comparison, but it now always renders the projection block as “How your share was calculated” and only adds a small note that the final claim amount is from settlement. If the client cannot compare in the same units, this block must be explicitly marked as live/explanatory and not final, or shown as unavailable/stale, so users are not told stale projection math is how their finalized claim was calculated. - Suggestion: either fetch enough finalized context to compare against
/proof.amount, or change the projection block heading/copy to make it clearly “Live contribution breakdown (may not reflect final settlement)” and keep/proof.amountas the only finalized claim amount.
- File:
Decision
Requesting changes until the breakdown is clearly marked non-final/stale when no same-unit divergence check is possible. CI was still pending at review time.
Breakdown header now reads "Live contribution breakdown (may not reflect final settlement)" — explicitly non-final. Claim amount from /proof remains the only finalized value. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: REQUEST CHANGES
Summary
The latest copy fix resolves the prior breakdown-label issue, but the PR still fails required lint/typecheck on the current head.
Findings
- [high]
lint-and-typecheckfails due an unescaped apostrophe in JSX.- File:
src/components/airdrop/ClaimCard.tsx:139 - ESLint reports
react/no-unescaped-entitiesforYou weren't eligible for this campaign.This blocks CI. - Suggestion: use
You weren't eligible for this campaign.or equivalent escaped text.
- File:
Decision
Requesting changes until the lint failure is fixed and CI is green. The prior projection/proof copy concern is resolved by the new “Live contribution breakdown (may not reflect final settlement)” label.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: APPROVE
Summary
The requested fixes are resolved. The live projection breakdown is now explicitly labeled as non-final, the finalized claim amount remains driven by /proof.amount, and the lint failure has been fixed.
Findings
- None blocking.
Decision
Approving PR #1293. The ClaimCard refactor now satisfies #1255 for settlement variants, proof-backed claiming, explanatory projection breakdown, on-chain deadline display/disable behavior, and latest CI is green.
Summary
Full v5 ClaimCard with 3 settlement variants:
/projection(spend × multiplier = weighted spend), claim amount from/proof(authoritative), on-chainclaimDeadline()countdown with post-deadline disableSource-of-truth rule
/proof.amount(authoritative, never overridden)/projection(explanatory)MerkleClaim.claimDeadline()(single source of truth)ClaimPanel
Now a thin wrapper:
<ClaimCard mode="normal" />Version
1.39.0 → 1.40.0 (feature)
Closes #1255
🤖 Generated with Claude Code