Skip to content

Fix Farcaster identity: Steemhunt API + Neynar fallback#253

Merged
realproject7 merged 2 commits intomainfrom
task/250-farcaster-steemhunt-fallback
Mar 17, 2026
Merged

Fix Farcaster identity: Steemhunt API + Neynar fallback#253
realproject7 merged 2 commits intomainfrom
task/250-farcaster-steemhunt-fallback

Conversation

@realproject7
Copy link
Copy Markdown
Owner

Summary

  • Rewrite lib/farcaster.ts to use Steemhunt's free Farcaster Indexer API (fc.hunt.town) as primary lookup
  • Falls back to Neynar only when NEYNAR_API_KEY is configured
  • Simple implementation: in-memory Map cache (1h TTL), 3s request timeout, in-flight dedup
  • No external dependencies added (no node-cache needed)
  • Existing consumers (WriterIdentity.tsx, WriterIdentityClient.tsx) require no changes — same lookupByAddress() signature and FarcasterProfile type

Fixes #250

Test plan

  • Farcaster username + avatar displays for wallets linked to FC accounts (without NEYNAR_API_KEY)
  • Falls back to Neynar if Steemhunt returns null and API key is set
  • Falls back to truncated address if both fail
  • npm run typecheck passes

🤖 Generated with Claude Code

Rewrite lib/farcaster.ts to use Steemhunt's free Farcaster Indexer API
as the primary lookup, falling back to Neynar only when NEYNAR_API_KEY
is configured. Simple in-memory cache (1h TTL) with in-flight dedup.

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.

APPROVE — with one non-blocking observation.

Observation (non-blocking): null results are now cached for 1h.
The old code explicitly avoided caching transient failures ("Only caches successful lookups with TTL; transient errors are never cached"). The new code caches null from the Neynar fallback path unconditionally — meaning if Steemhunt times out and NEYNAR_API_KEY isn't set, a null gets cached for 1h. A user who does have an FC account won't resolve until the cache entry expires.

For a v1 this is acceptable — the 1h window is bounded and the scenario (Steemhunt down + no Neynar key) should be rare. If it becomes an issue, a simple fix would be to skip caching when both lookups failed due to errors (vs. a genuine "no profile" result).

What looks good:

  • In-flight dedup prevents thundering herd on popular addresses
  • AbortSignal.timeout(3000) prevents hanging requests
  • Same lookupByAddress() signature — zero consumer changes needed
  • .catch(() => null) on both paths ensures no unhandled rejections
  • Clean separation of steemhuntLookup / neynarLookup

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 Steemhunt-first / Neynar-fallback flow matches the ticket, but the new cache semantics introduce a regression: transient lookup failures are now cached as null for one hour.

Findings

  • [medium] lookupByAddress() now caches negative results for the full TTL, including transient network timeouts and 5xxs from Steemhunt/Neynar. Because both lookups are wrapped in .catch(() => null) and the final branch always does cache.set(key, { profile: fallback, expiresAt: ... }), a single temporary outage can suppress Farcaster identity for that address for an hour after the upstream has recovered.
    • File: lib/farcaster.ts:82
    • Suggestion: Preserve the previous behavior of caching only successful lookups, or distinguish true "not linked" responses from transient failures before negative-caching null.

Decision

Request changes. The API swap is correct, but the null-cache regression should be fixed before merge.

Distinguish between "API confirmed wallet not linked" (cache null for 1h)
and "transient error" (don't cache, retry next request). Addresses T2a
review feedback on PR #253.

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 follow-up patch fixes the cache regression from the earlier review. Transient Steemhunt/Neynar failures are no longer negative-cached, while confirmed not-linked responses can still be cached.

Findings

  • [info] No blocking issues found in the updated patch.

Decision

Approve. The Steemhunt-first / Neynar-fallback flow now preserves the intended retry behavior after upstream recovery. CI was still pending when reviewed.

@realproject7 realproject7 merged commit 61f26bf into main Mar 17, 2026
1 check 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.

Fix Farcaster identity: use Steemhunt API (free) with Neynar fallback

2 participants