Skip to content

refactor: extract useWalletAddress() hook to deduplicate session casts - #288

Merged
Benjtalkshow merged 3 commits into
boundlessfi:mainfrom
shogun444:feat/extract-use-wallet-address-hook
Jun 27, 2026
Merged

refactor: extract useWalletAddress() hook to deduplicate session casts#288
Benjtalkshow merged 3 commits into
boundlessfi:mainfrom
shogun444:feat/extract-use-wallet-address-hook

Conversation

@shogun444

@shogun444 shogun444 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #275

This PR extracts the duplicated wallet address lookup logic into a dedicated useWalletAddress() hook and updates all existing consumers to use it. The wallet resolution behavior remains unchanged (walletAddress → address → null), while removing repeated session casts and keeping the fallback logic centralized.

Changes

  • Added hooks/use-wallet-address.ts

  • Replaced duplicated wallet address session casts in:

    • hooks/use-competition-join-state.ts
    • components/bounty/competition-submission.tsx
    • components/bounty/competition-judging.tsx
    • components/bounty/fcfs-approval-panel.tsx
    • components/bounty/fcfs-claim-button.tsx
  • Preserved the existing walletAddress → address → null fallback behavior

  • Added unit tests covering the hook's behavior across all expected session states

  • Removed the duplicated wallet-address casts from the targeted components and hooks

Testing

  • pnpm tsc --noEmit
  • Hook unit tests passing (5/5)
  • Verified no targeted wallet-address session casts remain in components/ and hooks/

Notes

  • No functional behavior has changed—this is a refactor that centralizes wallet address resolution.
  • The existing session.id casts in fcfs-approval-panel.tsx and fcfs-claim-button.tsx were intentionally left unchanged because they are unrelated to this issue.
  • bounty-detail-client.tsx was not modified since it uses a different access pattern and is outside the scope of this issue.

Summary by CodeRabbit

  • New Features
    • Added a unified wallet-address hook and applied it to bounty/competition approval, submission, claim, and join flows for consistent connect/ownership checks.
  • Bug Fixes
    • Fixed cases where actions appeared disabled or failed when the wallet address was stored under a different session field.
    • Improved reliability of approval/submission/claim gating and optimistic join/approval state tracking.
  • Tests
    • Added unit tests covering wallet-address resolution across common session/user scenarios.

Replace duplicated (session?.user as { walletAddress?: string; address?: string })
wallet address extraction across 5 files with a single shared hook.

New hook at hooks/use-wallet-address.ts:
- Returns walletAddress, falls back to address, then null
- Marked 'use client' for client component usage
- Includes 5 unit tests

Files updated:
- hooks/use-competition-join-state.ts
- components/bounty/competition-submission.tsx
- components/bounty/competition-judging.tsx
- components/bounty/fcfs-approval-panel.tsx
- components/bounty/fcfs-claim-button.tsx

Closes boundlessfi#275
@vercel

vercel Bot commented Jun 26, 2026

Copy link
Copy Markdown

@shogun444 is attempting to deploy a commit to the Threadflow Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Jun 26, 2026

Copy link
Copy Markdown

@shogun444 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 75eaee62-ec93-4602-b2f4-563d969f181c

📥 Commits

Reviewing files that changed from the base of the PR and between bd26edb and 2ff3b29.

📒 Files selected for processing (2)
  • components/bounty-detail/bounty-detail-client.tsx
  • hooks/__tests__/use-wallet-address.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • hooks/tests/use-wallet-address.test.ts

📝 Walkthrough

Walkthrough

A new useWalletAddress() hook centralizes session wallet lookup, and the competition, FCFS, and bounty detail callers that previously read session user fields now use it. Tests cover the hook’s fallback behavior.

Changes

Wallet Address Hook Extraction

Layer / File(s) Summary
Hook and test coverage
hooks/use-wallet-address.ts, hooks/__tests__/use-wallet-address.test.ts
useWalletAddress() reads authClient.useSession(), and the test suite checks walletAddress, address, and empty-session returns.
Competition consumers
components/bounty/competition-submission.tsx, components/bounty/competition-judging.tsx, hooks/use-competition-join-state.ts
walletAddress now comes from useWalletAddress() in competition submission, judging, and join-state logic.
FCFS consumers
components/bounty/fcfs-approval-panel.tsx, components/bounty/fcfs-claim-button.tsx
FCFS approval and claim flows now call useWalletAddress() for wallet gating, ownership checks, and mutation inputs.
Bounty detail client
components/bounty-detail/bounty-detail-client.tsx
BountyDetailClient now uses useWalletAddress() for its wallet-based role and submission checks.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • boundlessfi/bounties#161: Shares the FCFS approval/claim paths and the same wallet-address-derived ownership checks.
  • boundlessfi/bounties#178: Shares the competition flow and the same session-to-wallet-address handling now centralized in useWalletAddress().
  • boundlessfi/bounties#200: Also touches components/bounty-detail/bounty-detail-client.tsx and its wallet-address-driven flow.

Suggested reviewers

  • Benjtalkshow

Poem

I hopped through code with twitchy nose,
and found one hook where wallet grows.
No casty maze, no doubled lore,
just tidy paws and session store.
🐇🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning bounty-detail-client.tsx was changed even though the linked issue scoped the refactor to five specific files. Remove the bounty-detail-client.tsx change from this PR, or split it into a separate change if it is intentionally part of the cleanup.
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main refactor: extracting a shared useWalletAddress hook to replace duplicated session casts.
Linked Issues check ✅ Passed The PR adds the hook, updates the five specified consumers, and adds tests while preserving the wallet-address fallback behavior.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@hooks/__tests__/use-wallet-address.test.ts`:
- Line 10: The test file is using a CommonJS require for the mocked auth module,
which violates the lint rule and breaks CI. Replace the require of
`@/lib/auth-client` with a standard ESM import in
hooks/__tests__/use-wallet-address.test.ts, and update the mock setup in the
useSession-related test code to use a separately named mocked reference such as
mockUseSession instead of authClient.useSession.mockReturnValue(...). Keep the
rest of the test behavior unchanged.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f52ccc27-a80c-4bc1-aeca-299eed48af86

📥 Commits

Reviewing files that changed from the base of the PR and between 9e5dc91 and bd26edb.

📒 Files selected for processing (7)
  • components/bounty/competition-judging.tsx
  • components/bounty/competition-submission.tsx
  • components/bounty/fcfs-approval-panel.tsx
  • components/bounty/fcfs-claim-button.tsx
  • hooks/__tests__/use-wallet-address.test.ts
  • hooks/use-competition-join-state.ts
  • hooks/use-wallet-address.ts

Comment thread hooks/__tests__/use-wallet-address.test.ts Outdated

@Benjtalkshow Benjtalkshow left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great work, all 5 target files are migrated cleanly and the test suite
passes. Two things before merge: pnpm tsc --noEmit fails on the test file
because authClient.useSession.mockReturnValue needs (authClient.useSession as jest.Mock).mockReturnValue(...) so TS recognizes the Jest mock API —
runtime is fine but CI will block. Also, components/bounty-detail/ bounty-detail-client.tsx:150 has the same (session?.user as { walletAddress ?: string })?.walletAddress pattern; please migrate it to
const walletAddress = useWalletAddress() ?? "" so the hook fully replaces
the duplicated cast. A screenshot of one wallet-gated button (Claim or Join
Competition) in the connected state would also help confirm no regression
from the refactor.

@shogun444

shogun444 commented Jun 27, 2026

Copy link
Copy Markdown
Contributor Author

@Benjtalkshow Addressed both review items:

  1. Test TS fix: Cast authClient.useSession as jest.Mock in all 5 test cases - pnpm tsc --noEmit now passes
  2. bounty-detail-client.tsx migration: Replaced inline (session?.user as { walletAddress?: string })?.walletAddress || "" with useWalletAddress() ?? "" and moved hook call before early returns

All wallet-address session casts are now removed from components/ and hooks/.

Re: screenshot - the backend GraphQL API (/api/graphql) is returning 404 on both production and local environments, so I can't render bounties to capture the wallet-gated button. the screenshot can be captured once the API is back online.

@shogun444
shogun444 requested a review from Benjtalkshow June 27, 2026 07:07

@Benjtalkshow Benjtalkshow left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM!

@Benjtalkshow
Benjtalkshow merged commit 742fee5 into boundlessfi:main Jun 27, 2026
4 of 5 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.

Extract a useWalletAddress() hook to remove duplicated session casts

2 participants