Skip to content

Drop forge pay artist#2297

Merged
prxt6529 merged 27 commits intomainfrom
drop-forge-pay-artist
Apr 21, 2026
Merged

Drop forge pay artist#2297
prxt6529 merged 27 commits intomainfrom
drop-forge-pay-artist

Conversation

@prxt6529
Copy link
Copy Markdown
Collaborator

@prxt6529 prxt6529 commented Apr 20, 2026

Summary by CodeRabbit

  • New Features

    • Added "Pay Artist" phase to drop forge with on-chain payment support
    • New API endpoint for profile wave data retrieval
    • New subscription counts CSV export capability
    • Enhanced QR scanner error messages with specific failure details
  • Bug Fixes

    • Corrected default site title to "6529.io"
    • Improved subscription query reliability by removing automatic retries

Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR introduces a "Pay Artist" transaction flow to Drop Forge launch claims, adds new API endpoints and schemas for profile waves and mint stats, disables automatic retries in subscription queries, enhances QR scanner error messaging, and refactors launch phase status logic with new helper functions and tests.

Changes

Cohort / File(s) Summary
Query Retry Handling
components/home/now-minting/LatestDropNextMintSubscribe.tsx, components/user/subscriptions/MemeSubscriptionRow.tsx
Disabled automatic retries by adding retry: false to React Query hooks for subscription and consolidation queries.
Subscription Query Tests
__tests__/components/home/LatestDropNextMintSubscribe.test.tsx, __tests__/components/user/subscriptions/MemeSubscriptionRow.test.tsx, __tests__/components/user/subscriptions/UserPageSubscriptionsUpcoming.test.tsx
Added/updated test assertions to verify retry: false is passed to useQuery calls.
Metadata & Title Handling
components/providers/metadata.ts, components/dynamic-head/DynamicHeadTitle.tsx, __tests__/components/providers/metadata.test.ts, __tests__/contexts/TitleContext.test.tsx
Updated default app title to "6529.io", modified dynamic title logic to avoid re-applying default on root route, and added comprehensive title reset/route behavior tests.
Drop Forge Launch Claim Core
components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx, components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.ts
Introduced "Pay Artist" transaction flow with on-chain submission, added mint stat retrieval, refactored phase selection logic with new helpers (findBestMatchingLaunchActionName, getAutoSelectedLaunchPhase, getLaunchListStatus), and expanded action completion tracking.
Drop Forge Launch Claim View
components/drop-forge/launch/DropForgeLaunchClaimPageClient.view.tsx
Added "Pay Artist" phase UI with address input validation, payment amount fields, refactored phase tab rendering with centralized panel composition, and updated prop interfaces to include new pay-artist and mint-stat state.
Drop Forge Claims List
components/drop-forge/DropForgeClaimsListPageClient.tsx
Added local state to track launch claim action completion and loading status, integrated action fetching and matching logic, and updated status pill rendering to use computed launch list status.
Drop Forge Status & Pills
components/drop-forge/drop-forge-status.helpers.ts, components/drop-forge/DropForgeStatusPill.tsx
Extended ClaimPrimaryStatusTone with "post_mint" and "finalized" tones, added corresponding Tailwind styling, and added optional showCheck prop to status pill component.
QR Scanner Error Handling
components/header/share/HeaderQRScanner.tsx, __tests__/components/header/share/HeaderQRScanner.test.tsx
Enhanced error message extraction from QR scan failures with fallback guidance, updated toast messaging with detailed error reasons, and added test cases for error scenarios.
Launch Phase Logic Tests
__tests__/components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.test.ts
Added comprehensive test suite for getLaunchListStatus covering manifold claim state combinations, refactored getAutoSelectedLaunchPhase tests with helper wrapper.
API Client
services/api/memes-minting-claims-api.ts
Added new exported function getMemesMintStat(claimId) to fetch mint statistics from the API.
OpenAPI Specification
openapi.yaml
Renamed drops reactions endpoint from /reactions to /reaction, added new endpoints for profile wave retrieval and redeemed memes CSV download, extended ApiMemesMintStat schema with payment_details field, and added new ApiPaymentDetails and ApiProfileWave schemas.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant View as Pay Artist Phase
    participant Client as DropForgeLaunchClaimPageClient
    participant Handler as Transaction Handler
    participant Contract as Smart Contract
    participant API as Backend API

    User->>View: Enter payment amount & address
    View->>View: Validate address (ENS resolution)
    View->>View: Parse amount to wei
    
    User->>View: Submit Pay Artist transaction
    View->>Client: runPayArtistWrite(actionName)
    
    Client->>Handler: useSendTransaction (prepared payload)
    Handler->>Contract: sendTransaction (payArtist)
    Contract-->>Handler: txHash
    
    Client->>Handler: useWaitForTransactionReceipt(txHash)
    Handler->>Contract: Confirm receipt
    Contract-->>Handler: receipt (success)
    
    Client->>API: markMintingClaimActionCompleted(actionId)
    API-->>Client: success
    
    Client->>View: Update UI (completion state)
    View->>User: Display success, update status
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • simo6529
  • ragnep

Poem

🐰 A rabbit's ode to paying artists on-chain!
Phase by phase, from research to pay,
Transactions bloom in the forge's display,
With ENS addresses and amounts so bright,
The artist receives their due, just right! 🎨✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Drop forge pay artist' directly and clearly summarizes the main change—adding Pay Artist functionality to the drop forge feature.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch drop-forge-pay-artist

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
openapi.yaml (2)

1570-1610: ⚠️ Potential issue | 🟠 Major

Keep a compatibility path for /drops/{dropId}/reactions.

Renaming the public route from plural to singular is a breaking API change for non-generated clients and older app versions. Consider keeping the old path as a deprecated alias until consumers migrate.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openapi.yaml` around lines 1570 - 1610, Add a deprecated alias path for the
old plural route so clients keep working: duplicate the current
/drops/{dropId}/reaction OpenAPI entry under /drops/{dropId}/reactions and point
its post and delete operations to the same operationIds (reactToDrop and
removeReactionFromDrop) or references, mark the operations or path as deprecated
and include a brief description indicating the new preferred path
(/drops/{dropId}/reaction) so generated and non-generated clients will continue
to work until consumers migrate.

9593-9638: ⚠️ Potential issue | 🟡 Minor

The frontend code is already defensive and will not break if payment_details is omitted.

The code uses optional chaining (?.) when accessing payment_details (e.g., response.payment_details?.payment_address), so it gracefully handles cases where the field is missing. The generated ApiMemesMintStat model lacks runtime validation to enforce required fields due to the @ts-nocheck directive.

The actual concern should be addressed at the backend API level: ensure all response builders return payment_details (possibly as null) to satisfy the OpenAPI spec's required constraint. Frontend code will not fail if this is omitted, but the API contract will be violated.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openapi.yaml` around lines 9593 - 9638, The OpenAPI schema marks
payment_details as required in ApiMemesMintStat but backend response builders
sometimes omit it, violating the contract; update the server-side response
construction for the endpoints that return ApiMemesMintStat (where
serializers/builders create ApiMemesMintStat objects) to always include the
payment_details property (set it to the ApiPaymentDetails object or explicit
null when no details exist) so the responses conform to the OpenAPI spec; search
for ApiMemesMintStat and any functions that assemble mint stat responses and
ensure they inject payment_details into the returned payload.
🧹 Nitpick comments (3)
components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx (2)

309-315: Reset handledPayArtistWrite*TxHashRef on claimId change.

handledPayArtistWriteSuccessTxHashRef and handledPayArtistWriteErrorTxHashRef are never reset when claimId changes (the existing claimWrite refs have the same omission). In practice this is harmless because tx hashes are unique, but it makes the lifecycle inconsistent with the surrounding state reset at Lines 522-533. Consider clearing them alongside pendingPayArtistMintingClaimActionRef in that cleanup for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx` around lines
309 - 315, The two refs handledPayArtistWriteSuccessTxHashRef and
handledPayArtistWriteErrorTxHashRef are not being reset when claimId changes;
update the same cleanup that clears pendingPayArtistMintingClaimActionRef (in
the useEffect handling claimId changes inside DropForgeLaunchClaimPageClient) to
also set handledPayArtistWriteSuccessTxHashRef.current and
handledPayArtistWriteErrorTxHashRef.current to null so their lifecycle matches
the other claim-related state (similar to how
handledClaimWriteSuccessTxHashRef/handledClaimWriteErrorTxHashRef are reset).

1413-1440: Active-modal selection: confirm mutual exclusion.

activeTxModal = payArtistTxModal ?? claimTxModal silently hides claimTxModal whenever payArtistTxModal is set. The gating logic around launchActionPending should already prevent overlapping transactions, but there's no assertion/safeguard — a future regression could leave a claimTxModal in "error" state hidden behind a new payArtistTxModal. Consider asserting one-or-the-other (e.g., require callers to clear the other modal before opening a new one) or at least add a comment documenting the precondition.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx` around lines
1413 - 1440, The selection logic for activeTxModal (activeTxModal =
payArtistTxModal ?? claimTxModal) can silently hide claimTxModal when
payArtistTxModal is set; add a safeguard and documentation: in the component
where payArtistTxModal and claimTxModal are controlled (refer to activeTxModal,
payArtistTxModal, claimTxModal and the close functions
closePayArtistTxModal/closeClaimTxModal), either enforce mutual exclusion by
asserting or throwing/logging if both modals are set (e.g., assert
!(payArtistTxModal && claimTxModal)) or clear the other modal before opening a
new one, and add a clear comment describing the precondition (that callers must
not set both or must clear the other). Ensure the escape/overflow effects
continue to reference activeTxModal and activeTxModalClosable after adding the
assertion/clear to avoid regressions.
components/drop-forge/DropForgeClaimsListPageClient.tsx (1)

548-605: N concurrent per-card requests to getMemesMintingClaimActions.

Each LaunchClaimCard instance fires its own getMemesMintingClaimActions(claim.claim_id) on mount, so rendering a full page of CRAFT_CLAIMS_PAGE_SIZE claims triggers that many parallel admin-gated requests just to render status pills. On subsequent polling updates (the fetchPage interval every 10s while any claim is uploading), cards can also remount/refetch. Consider batching into one parent-level fetch (e.g., a list endpoint that returns per-claim action completion) or lifting the query so it runs once per page load rather than per card.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/drop-forge/DropForgeClaimsListPageClient.tsx` around lines 548 -
605, The useEffect in LaunchClaimCard (calling getMemesMintingClaimActions with
claim.claim_id) causes N concurrent per-card admin requests; instead, implement
a single batched query in the parent (DropForgeClaimsListPageClient) that
fetches actions for all visible claim_ids (e.g., in fetchPage or a new
getMemesMintingClaimsActionsBatch) and returns a map from claim_id to
action/completion status; then remove the per-card getMemesMintingClaimActions
call and read researchAirdropCompleted/payArtistCompleted from props passed into
LaunchClaimCard (or from shared context/state keyed by claim.claim_id), ensuring
polling still updates the parent-level map and the cards re-render from that
central source.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@__tests__/components/providers/metadata.test.ts`:
- Around line 71-76: The test for production title is brittle because it relies
on the ambient BASE_ENDPOINT; make the test independent by setting the
environment or inputs so getAppMetadata() runs as if BASE_ENDPOINT is
production. Modify the test that calls getAppMetadata() to explicitly set
process.env.BASE_ENDPOINT (or pass a production config) to a non-staging value
before invoking getAppMetadata(), and restore the original env after the test;
reference the getAppMetadata() call and the BASE_ENDPOINT env var in your change
so the test always expects "6529.io" regardless of CI/local staging settings.

In `@components/drop-forge/DropForgeClaimsListPageClient.tsx`:
- Around line 128-195: getLaunchListStatus currently overrides the "live"
primaryStatus immediately using researchAirdropCompleted/payArtistCompleted
which default to false and can cause a transient incorrect pill; change the
signature to accept tri-state flags (researchAirdropCompleted: boolean | null,
payArtistCompleted: boolean | null) or add an actionsResolved boolean, and
ensure the function returns the incoming primaryStatus (no overrides) when those
flags are null/unresolved (i.e., before getMemesMintingClaimActions finishes);
only apply the "Finalized" / "Live - Pay Artist" overrides when the flags are
explicitly true/false (resolved). Reference getLaunchListStatus,
researchAirdropCompleted, payArtistCompleted and the async caller
getMemesMintingClaimActions to implement the tri-state gating.
- Around line 44-107: Extract the duplicated heuristics into a single shared
helper module and import it in both places: move normalizeLaunchActionName and
findLaunchListActionName (the logic duplicated with
normalizeMintingClaimActionName/findLaunchActionName) into a new helper (e.g.,
launchClaimActions.helpers.ts), export them, and replace the local copies in
DropForgeClaimsListPageClient.tsx and DropForgeLaunchClaimPageClient.tsx with
imports from that module; while doing so keep the existing function names and
scoring/tiebreak logic unchanged, update any references to call the shared
functions, and run typechecks/tests. Also add a short TODO in the helper to
prefer explicit action-name constants or a backend kind discriminator instead of
fragile substring heuristics.

In `@components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx`:
- Around line 729-770: The mintStatRequestedRef gating prevents re-fetching mint
stats after a successful initial fetch because it is only reset on claim-id
change or fetch failure; update the logic so the ref is cleared when leaving the
"payartist" phase or after a successful pay-artist action: in the effect
(useEffect watching selectedPhase) ensure you reset mintStatRequestedRef.current
= false when selectedPhase changes away from "payartist" (or alternatively set
it to false after a successful runPayArtistWrite completion), so that returning
to "payartist" will re-trigger getMemesMintStat; reference mintStatRequestedRef,
selectedPhase, getMemesMintStat and runPayArtistWrite when applying the change.
- Around line 2074-2083: The payArtistWritePending prop should reflect only the
Pay Artist transaction state rather than the combined launchActionPending;
replace payArtistWritePending={launchActionPending} with the Pay Artist-specific
loading flag (e.g., payArtistWrite.isPending || waitPayArtistWrite.isLoading) so
the Pay Artist button spinner maps to Pay Artist write activity, while keeping
the existing combined logic (launchActionPending || mintingClaimActionPending
!== null || ...) for payArtistActionDisabled unchanged.
- Around line 101-164: The normalizeMintingClaimActionName and
findLaunchActionName implementations are duplicated; extract them into a single
shared helper module (e.g., create a drop-forge helper file) and have both
DropForgeLaunchClaimPageClient and DropForgeClaimsListPageClient import the same
functions; move the logic from normalizeMintingClaimActionName and
findLaunchActionName into that module, update both components to import and use
those symbols, and add a TODO/comment to prefer explicit action-name constants
or a backend-supplied kind field to replace the brittle substring heuristics in
future.

In `@components/drop-forge/launch/DropForgeLaunchClaimPageClient.view.tsx`:
- Around line 237-242: The Pay Artist matcher (the switch case handling
"payartist" that returns required/preferred/excluded arrays) must explicitly
exclude airdrop-related actions; add "airdrop" to the excluded array for the
case "payartist" so phrases like "Pay Artist Airdrop" cannot match this phase
and accidentally bind payment metadata to mint/claim actions.
- Around line 1245-1253: formatMintStatEth currently coerces null to 0 via
Number(null), causing missing ETH stats (e.g., proceeds_eth, artist_split_eth)
to display "0" instead of "—"; update formatMintStatEth to first check for null
or undefined (e.g., if (value == null) return "—"), then coerce to Number and
guard with Number.isFinite before formatting, so only valid numeric inputs are
formatted and missing values render as "—".
- Line 1835: The span rendering the "Initialize Claim" label uses a malformed
Tailwind utility `lg:tw:inline`; update the className on that span (the element
containing the text "Initialize Claim") to use the correct responsive utility
`lg:tw-inline` so the text becomes visible on large screens.

In `@openapi.yaml`:
- Around line 10500-10512: The schema ApiPaymentDetails currently lists
designated_payee_name as required which conflicts with has_designated_payee
being false; update the schema by removing designated_payee_name from the
required array and mark the designated_payee_name property as nullable (or
optional) so it may be absent or null when has_designated_payee is false;
reference ApiPaymentDetails, the required array, has_designated_payee, and
designated_payee_name when making the change (if you prefer stricter validation
later, consider replacing with an anyOf/oneOf conditional that requires
designated_payee_name only when has_designated_payee is true).

---

Outside diff comments:
In `@openapi.yaml`:
- Around line 1570-1610: Add a deprecated alias path for the old plural route so
clients keep working: duplicate the current /drops/{dropId}/reaction OpenAPI
entry under /drops/{dropId}/reactions and point its post and delete operations
to the same operationIds (reactToDrop and removeReactionFromDrop) or references,
mark the operations or path as deprecated and include a brief description
indicating the new preferred path (/drops/{dropId}/reaction) so generated and
non-generated clients will continue to work until consumers migrate.
- Around line 9593-9638: The OpenAPI schema marks payment_details as required in
ApiMemesMintStat but backend response builders sometimes omit it, violating the
contract; update the server-side response construction for the endpoints that
return ApiMemesMintStat (where serializers/builders create ApiMemesMintStat
objects) to always include the payment_details property (set it to the
ApiPaymentDetails object or explicit null when no details exist) so the
responses conform to the OpenAPI spec; search for ApiMemesMintStat and any
functions that assemble mint stat responses and ensure they inject
payment_details into the returned payload.

---

Nitpick comments:
In `@components/drop-forge/DropForgeClaimsListPageClient.tsx`:
- Around line 548-605: The useEffect in LaunchClaimCard (calling
getMemesMintingClaimActions with claim.claim_id) causes N concurrent per-card
admin requests; instead, implement a single batched query in the parent
(DropForgeClaimsListPageClient) that fetches actions for all visible claim_ids
(e.g., in fetchPage or a new getMemesMintingClaimsActionsBatch) and returns a
map from claim_id to action/completion status; then remove the per-card
getMemesMintingClaimActions call and read
researchAirdropCompleted/payArtistCompleted from props passed into
LaunchClaimCard (or from shared context/state keyed by claim.claim_id), ensuring
polling still updates the parent-level map and the cards re-render from that
central source.

In `@components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx`:
- Around line 309-315: The two refs handledPayArtistWriteSuccessTxHashRef and
handledPayArtistWriteErrorTxHashRef are not being reset when claimId changes;
update the same cleanup that clears pendingPayArtistMintingClaimActionRef (in
the useEffect handling claimId changes inside DropForgeLaunchClaimPageClient) to
also set handledPayArtistWriteSuccessTxHashRef.current and
handledPayArtistWriteErrorTxHashRef.current to null so their lifecycle matches
the other claim-related state (similar to how
handledClaimWriteSuccessTxHashRef/handledClaimWriteErrorTxHashRef are reset).
- Around line 1413-1440: The selection logic for activeTxModal (activeTxModal =
payArtistTxModal ?? claimTxModal) can silently hide claimTxModal when
payArtistTxModal is set; add a safeguard and documentation: in the component
where payArtistTxModal and claimTxModal are controlled (refer to activeTxModal,
payArtistTxModal, claimTxModal and the close functions
closePayArtistTxModal/closeClaimTxModal), either enforce mutual exclusion by
asserting or throwing/logging if both modals are set (e.g., assert
!(payArtistTxModal && claimTxModal)) or clear the other modal before opening a
new one, and add a clear comment describing the precondition (that callers must
not set both or must clear the other). Ensure the escape/overflow effects
continue to reference activeTxModal and activeTxModalClosable after adding the
assertion/clear to avoid regressions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d8ba2ea0-c9d0-4b79-88e7-6909453acadd

📥 Commits

Reviewing files that changed from the base of the PR and between ffa190f and de0f504.

⛔ Files ignored due to path filters (5)
  • generated/models/ApiMemesMintStat.ts is excluded by !**/generated/**
  • generated/models/ApiPaymentDetails.ts is excluded by !**/generated/**
  • generated/models/ApiProfileWave.ts is excluded by !**/generated/**
  • generated/models/ApiSetProfileWaveRequest.ts is excluded by !**/generated/**
  • generated/models/ObjectSerializer.ts is excluded by !**/generated/**
📒 Files selected for processing (16)
  • __tests__/components/home/LatestDropNextMintSubscribe.test.tsx
  • __tests__/components/providers/metadata.test.ts
  • __tests__/components/user/subscriptions/MemeSubscriptionRow.test.tsx
  • __tests__/components/user/subscriptions/UserPageSubscriptionsUpcoming.test.tsx
  • __tests__/contexts/TitleContext.test.tsx
  • components/drop-forge/DropForgeClaimsListPageClient.tsx
  • components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx
  • components/drop-forge/launch/DropForgeLaunchClaimPageClient.view.tsx
  • components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.ts
  • components/dynamic-head/DynamicHeadTitle.tsx
  • components/home/now-minting/LatestDropNextMintSubscribe.tsx
  • components/providers/metadata.ts
  • components/user/subscriptions/MemeSubscriptionRow.tsx
  • contexts/TitleContext.tsx
  • openapi.yaml
  • services/api/memes-minting-claims-api.ts

Comment thread __tests__/components/providers/metadata.test.ts
Comment thread components/drop-forge/DropForgeClaimsListPageClient.tsx Outdated
Comment thread components/drop-forge/DropForgeClaimsListPageClient.tsx Outdated
Comment thread components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx Outdated
Comment thread components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx
Comment thread components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx
Comment thread components/drop-forge/launch/DropForgeLaunchClaimPageClient.view.tsx Outdated
Comment thread components/drop-forge/launch/DropForgeLaunchClaimPageClient.view.tsx Outdated
Comment thread openapi.yaml
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
__tests__/components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.test.ts (1)

43-149: ⚠️ Potential issue | 🔴 Critical

Add missing required parameters to all getAutoSelectedLaunchPhase test calls.

The function signature now requires researchAirdropCompleted: boolean and payArtistCompleted: boolean, but all 10 test calls omit both. This causes TypeScript compilation to fail. Add these parameters with defaults (e.g., false) to each call, or create a wrapper helper that provides defaults.

Example fix pattern
 describe("getAutoSelectedLaunchPhase", () => {
+  const selectLaunchPhase = (
+    args: Omit<
+      Parameters<typeof getAutoSelectedLaunchPhase>[0],
+      "researchAirdropCompleted" | "payArtistCompleted"
+    > &
+      Partial<
+        Pick<
+          Parameters<typeof getAutoSelectedLaunchPhase>[0],
+          "researchAirdropCompleted" | "payArtistCompleted"
+        >
+      >
+  ) =>
+    getAutoSelectedLaunchPhase({
+      researchAirdropCompleted: false,
+      payArtistCompleted: false,
+      ...args,
+    });
+
   const phases = [

Then replace calls like:

-      getAutoSelectedLaunchPhase({
+      selectLaunchPhase({
         hasPublishedMetadata: false,
         isInitialized: true,
         nowMs: 1_500,
         phases,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@__tests__/components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.test.ts`
around lines 43 - 149, The tests call getAutoSelectedLaunchPhase without the
newly required booleans; update every test invocation of
getAutoSelectedLaunchPhase in this file to include researchAirdropCompleted and
payArtistCompleted (e.g., both false) or add a small wrapper helper that
supplies those defaults and call the wrapper instead; locate calls to
getAutoSelectedLaunchPhase in the tests (e.g., the ten expect(...) blocks) and
add the two boolean properties to the argument object or replace them with the
wrapper to fix the TypeScript errors.
♻️ Duplicate comments (1)
components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx (1)

1082-1123: ⚠️ Potential issue | 🟠 Major

Reset mint-stat request state when leaving Pay Artist.

If the user switches away while getMemesMintStat is in flight, the cleanup marks the request cancelled, so finally skips setMintStatLoading(false) while mintStatRequestedRef.current stays true. Returning to Pay Artist then skips the fetch and can leave the section stuck loading. This is the same unresolved root cause as the previous mint-stat gating comment.

Proposed fix
   useEffect(() => {
     if (!hasWallet || !canAccessLaunchPage) return;
-    if (selectedPhase !== "payartist") return;
+    if (selectedPhase !== "payartist") {
+      mintStatRequestedRef.current = false;
+      setMintStatLoading(false);
+      return;
+    }
     if (mintStatRequestedRef.current) return;
     mintStatRequestedRef.current = true;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx` around lines
1082 - 1123, When leaving the "payartist" phase while getMemesMintStat is in
flight, mintStatRequestedRef.current remains true and the UI can get stuck; in
the useEffect cleanup for the pay-artist branch (the effect referencing
selectedPhase, getMemesMintStat, mintStatRequestedRef, setMintStatLoading) reset
mintStatRequestedRef.current = false and call setMintStatLoading(false) (and
optionally clear mintStatError) so returning to the payartist phase will re-run
the fetch and not leave the section perpetually loading.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/drop-forge/DropForgeClaimsListPageClient.tsx`:
- Around line 388-394: The current logic computes launchListStatus by calling
getLaunchListStatus({ primaryStatus, manifoldClaim, researchAirdropCompleted,
payArtistCompleted, actionsLoaded }) even when the actions fetch failed,
producing a misleading post-launch state; update the fetch flow to reset
actionsLoadFailed before starting, set actionsLoadFailed = true in the fetch
.catch handler, and then compute launchListStatus using actionsLoadFailed ?
primaryStatus : getLaunchListStatus(...) (use the existing symbols
launchListStatus, getLaunchListStatus, primaryStatus, actionsLoaded,
actionsLoadFailed, researchAirdropCompleted, payArtistCompleted) so a failed
actions load preserves the original primaryStatus instead of inventing an
incomplete state.

In `@components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.ts`:
- Around line 311-318: The current finalization check uses payArtistCompleted
alone (in the block returning key "live"), which can mark the launch finalized
even when research is still pending; update the condition to require research
completion as well (e.g., check researchCompleted is true) or guard using
getAutoSelectedLaunchPhase() !== "research" alongside payArtistCompleted before
returning the "Finalized"/"live" status so that both payArtistCompleted and
research are satisfied before marking final.

In `@components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx`:
- Around line 1218-1236: The header status is being computed using
getLaunchListStatus which assumes actionsLoaded=true and thus applies
post-launch overrides before mintingClaimActions are resolved; update
headerStatus computation to detect whether action completion data is loaded
(e.g., derive an actionsLoaded boolean from mintingClaimActionsByName and/or
availableMintingClaimActionNames) and only call getLaunchListStatus with the
real actionsLoaded state or skip applying overrides when actions are not loaded
so primaryStatus is preserved; change the headerStatus logic around
getLaunchListStatus (references: getLaunchActionCompletionState,
mintingClaimActionsByName, availableMintingClaimActionNames,
getLaunchListStatus, primaryStatus, manifoldClaim, researchAirdropCompleted,
payArtistCompleted) to pass the correct actionsLoaded flag or return
primaryStatus when action data is unavailable.

---

Outside diff comments:
In
`@__tests__/components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.test.ts`:
- Around line 43-149: The tests call getAutoSelectedLaunchPhase without the
newly required booleans; update every test invocation of
getAutoSelectedLaunchPhase in this file to include researchAirdropCompleted and
payArtistCompleted (e.g., both false) or add a small wrapper helper that
supplies those defaults and call the wrapper instead; locate calls to
getAutoSelectedLaunchPhase in the tests (e.g., the ten expect(...) blocks) and
add the two boolean properties to the argument object or replace them with the
wrapper to fix the TypeScript errors.

---

Duplicate comments:
In `@components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx`:
- Around line 1082-1123: When leaving the "payartist" phase while
getMemesMintStat is in flight, mintStatRequestedRef.current remains true and the
UI can get stuck; in the useEffect cleanup for the pay-artist branch (the effect
referencing selectedPhase, getMemesMintStat, mintStatRequestedRef,
setMintStatLoading) reset mintStatRequestedRef.current = false and call
setMintStatLoading(false) (and optionally clear mintStatError) so returning to
the payartist phase will re-run the fetch and not leave the section perpetually
loading.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8aebbedb-b2de-48e4-8c94-3e81bd779578

📥 Commits

Reviewing files that changed from the base of the PR and between de0f504 and d5ff8af.

📒 Files selected for processing (5)
  • __tests__/components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.test.ts
  • components/drop-forge/DropForgeClaimsListPageClient.tsx
  • components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx
  • components/drop-forge/launch/DropForgeLaunchClaimPageClient.view.tsx
  • components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.ts

Comment thread components/drop-forge/DropForgeClaimsListPageClient.tsx Outdated
Comment thread components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.ts Outdated
Comment thread components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx Outdated
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx`:
- Around line 104-118: getClaimPresentationState currently treats an empty
metadata_location string as "published" because it only checks != null; update
the hasPublishedMetadata computation inside getClaimPresentationState to ensure
metadata_location is a non-empty, non-whitespace string (e.g. check typeof
claim?.metadata_location === "string" && claim.metadata_location.trim() !== "")
so blank values are treated as unpublished and launch controls stay hidden when
there's no usable CID.
- Around line 1244-1253: The headerStatus useMemo should not infer post-launch
state when action data is unavailable; update the early-return condition in the
headerStatus computation (where primaryStatus, mintingClaimActionsLoaded,
mintingClaimActionsLoadFailed, researchAirdropCompleted, payArtistCompleted, and
getLaunchListStatus are used) so that it returns primaryStatus whenever action
completion state cannot be loaded or is hidden (i.e., when
mintingClaimActionsLoadFailed is true OR mintingClaimActionsLoaded is false),
preserving primaryStatus for non-admin viewers instead of calling
getLaunchListStatus with default false action flags.

In `@components/drop-forge/launch/DropForgeLaunchClaimPageClient.view.tsx`:
- Around line 1615-1624: The EnsAddressInput is wiring both the displayed input
and the resolved address from onAddressChange, which overwrites the user's ENS
text; instead call onPayArtistAddressInputChange from the EnsAddressInput's
onValueChange handler to update the visible input and call
onPayArtistResolvedAddressChange only from onAddressChange to set the resolved
0x address (update the EnsAddressInput props: use
onValueChange={onPayArtistAddressInputChange} and
onAddressChange={onPayArtistResolvedAddressChange}, keeping onLoadingChange and
onError handlers as-is).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 303cd64c-48d9-4cea-bb62-5da5c7e8bd36

📥 Commits

Reviewing files that changed from the base of the PR and between d5ff8af and c296e40.

📒 Files selected for processing (6)
  • __tests__/components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.test.ts
  • components/drop-forge/DropForgeClaimsListPageClient.tsx
  • components/drop-forge/drop-forge-status.helpers.ts
  • components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx
  • components/drop-forge/launch/DropForgeLaunchClaimPageClient.view.tsx
  • components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.ts

Comment thread components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx
Comment thread components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx
Comment thread components/drop-forge/launch/DropForgeLaunchClaimPageClient.view.tsx Outdated
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx (1)

947-952: ⚠️ Potential issue | 🟠 Major

Preserve primary status when action completion data is hidden.

For non-admins, Line 951 marks actions as loaded while action data is empty, so Lines 1252-1258 can infer “Airdrop Research” from default false completion flags. Return primaryStatus when action completion state is unavailable to the viewer.

Suggested fix
   const headerStatus = useMemo(() => {
     if (!primaryStatus) return null;
-    if (mintingClaimActionsLoadFailed) {
+    if (!isClaimsAdmin || mintingClaimActionsLoadFailed) {
       return primaryStatus;
     }
     return getLaunchListStatus({
       primaryStatus,
       manifoldClaim,
@@
     payArtistCompleted,
     mintingClaimActionsLoaded,
     mintingClaimActionsLoadFailed,
+    isClaimsAdmin,
   ]);

Also applies to: 1247-1258

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx` around lines
947 - 952, When action completion data is hidden from non-admins, the effect
erroneously marks actions as loaded and clears action state, causing downstream
code that reads primaryStatus to infer defaults; change the behavior in the
useEffect that currently calls setMintingClaimActionTypes(null),
setMintingClaimActions(null), setMintingClaimActionsLoaded(true),
setMintingClaimActionsLoadFailed(false) so that when actions are unavailable to
the viewer you do NOT overwrite or mark them as loaded—either leave existing
action state intact or
setMintingClaimActionsLoaded(false)/setMintingClaimActionsLoadFailed(true) so
downstream logic that reads primaryStatus returns the existing primaryStatus
instead of defaulting to false; update the effect around the
permissionsLoading/isClaimsAdmin guard and the calls to
setMintingClaimActionTypes, setMintingClaimActions,
setMintingClaimActionsLoaded, and setMintingClaimActionsLoadFailed accordingly
so primaryStatus is preserved when completion state is hidden.
🧹 Nitpick comments (2)
__tests__/components/header/share/HeaderQRScanner.test.tsx (2)

29-33: Minor: renderToastMessage mixes rendering with assertion.

Embedding expect(toastArg?.type).toBe("error") inside a helper named renderToastMessage is a small surprise — failures will point at the helper rather than the test. Consider either renaming it (e.g., renderErrorToastMessage) or moving the type assertion back to the call sites for clearer failure locality. Non-blocking.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@__tests__/components/header/share/HeaderQRScanner.test.tsx` around lines 29 -
33, The helper function renderToastMessage currently mixes rendering with an
assertion (expect(toastArg?.type).toBe("error")), which obscures test failure
locations; update either by renaming renderToastMessage to
renderErrorToastMessage to reflect the embedded assertion or remove the type
assertion from renderToastMessage and perform
expect(toastArg?.type).toBe("error") at each call site; locate the helper by the
function name renderToastMessage and the toastArg usage (toast: jest.Mock) to
make the change.

107-157: LGTM — good coverage of both the message-bearing and fallback paths.

Both rejection shapes (Error with message, bare object without message) are exercised, the toast content is rendered and asserted via DOM queries, and router.push negative assertions guard against accidental navigation on failure. Note the fallback-guidance string is duplicated verbatim between the component (line 44) and the test (line 153); if it ever changes, both must be updated. Consider extracting it to a shared constant if you want to eliminate that coupling.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@__tests__/components/header/share/HeaderQRScanner.test.tsx` around lines 107
- 157, Tests duplicate the scanner fallback guidance string from the
HeaderQRScanner component, causing brittle coupling; extract the message into a
shared exported constant (e.g., SCANNER_FALLBACK_GUIDANCE) from the
HeaderQRScanner module and update the component to use that constant, then
import that constant in
__tests__/components/header/share/HeaderQRScanner.test.tsx and replace the
hardcoded string assertions with the imported constant to keep them in sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.ts`:
- Around line 138-142: The "artist" match config currently excludes
team/research/phase* but not payment verbs, so "Pay Artist" can be selected as
an artist match; update the artist config object (the artist: { required,
preferred, excluded } entry) to include payment-related action tokens such as
"pay", "payment", "pay_artist", "pay-artist", and "payArtist" (and any other
project-specific payment aliases) in its excluded array so payment actions
cannot be chosen as the best "artist" match.

In `@components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx`:
- Around line 2000-2030: The submit path doesn't guard against an in-flight ENS
resolution: update the UI and the runPayArtistWrite handler to block actions
while payArtistAddressLoading is true by (1) adding payArtistAddressLoading to
the button/submit disabled condition so the Pay Artist control is disabled while
resolving, and (2) adding an early return in runPayArtistWrite that checks
payArtistAddressLoading and calls setToast({ message: "Payment address is still
resolving", type: "error" }) before proceeding; reference runPayArtistWrite,
payArtistAddressLoading, payArtistResolvedAddressTrimmed, and
payArtistAddressHasEnsError to locate and modify the checks.

---

Duplicate comments:
In `@components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx`:
- Around line 947-952: When action completion data is hidden from non-admins,
the effect erroneously marks actions as loaded and clears action state, causing
downstream code that reads primaryStatus to infer defaults; change the behavior
in the useEffect that currently calls setMintingClaimActionTypes(null),
setMintingClaimActions(null), setMintingClaimActionsLoaded(true),
setMintingClaimActionsLoadFailed(false) so that when actions are unavailable to
the viewer you do NOT overwrite or mark them as loaded—either leave existing
action state intact or
setMintingClaimActionsLoaded(false)/setMintingClaimActionsLoadFailed(true) so
downstream logic that reads primaryStatus returns the existing primaryStatus
instead of defaulting to false; update the effect around the
permissionsLoading/isClaimsAdmin guard and the calls to
setMintingClaimActionTypes, setMintingClaimActions,
setMintingClaimActionsLoaded, and setMintingClaimActionsLoadFailed accordingly
so primaryStatus is preserved when completion state is hidden.

---

Nitpick comments:
In `@__tests__/components/header/share/HeaderQRScanner.test.tsx`:
- Around line 29-33: The helper function renderToastMessage currently mixes
rendering with an assertion (expect(toastArg?.type).toBe("error")), which
obscures test failure locations; update either by renaming renderToastMessage to
renderErrorToastMessage to reflect the embedded assertion or remove the type
assertion from renderToastMessage and perform
expect(toastArg?.type).toBe("error") at each call site; locate the helper by the
function name renderToastMessage and the toastArg usage (toast: jest.Mock) to
make the change.
- Around line 107-157: Tests duplicate the scanner fallback guidance string from
the HeaderQRScanner component, causing brittle coupling; extract the message
into a shared exported constant (e.g., SCANNER_FALLBACK_GUIDANCE) from the
HeaderQRScanner module and update the component to use that constant, then
import that constant in
__tests__/components/header/share/HeaderQRScanner.test.tsx and replace the
hardcoded string assertions with the imported constant to keep them in sync.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 813d9a9f-12eb-4ca7-8e39-fc08451db178

📥 Commits

Reviewing files that changed from the base of the PR and between f50796a and f8f784d.

📒 Files selected for processing (9)
  • __tests__/components/header/share/HeaderQRScanner.test.tsx
  • __tests__/contexts/TitleContext.test.tsx
  • components/drop-forge/DropForgeClaimsListPageClient.tsx
  • components/drop-forge/DropForgeStatusPill.tsx
  • components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx
  • components/drop-forge/launch/DropForgeLaunchClaimPageClient.view.tsx
  • components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.ts
  • components/dynamic-head/DynamicHeadTitle.tsx
  • components/header/share/HeaderQRScanner.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • components/dynamic-head/DynamicHeadTitle.tsx
  • tests/contexts/TitleContext.test.tsx

Comment thread components/drop-forge/launch/DropForgeLaunchClaimPageClient.tsx
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
@sonarqubecloud
Copy link
Copy Markdown

@prxt6529 prxt6529 merged commit 9dd39b7 into main Apr 21, 2026
8 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.

2 participants