feat: resolve ENS names and reject misshaped files on voter CSV import#332
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Gaston Review
Verdict: Approved
Score: ████████░░ 8/10
Pull Request Summary
This PR adds ENS name resolution during voter CSV import — ENS names in the address column are resolved to wallet addresses before the sync runs — and rejects files that don't match the expected template shape (address in the first column). New pure utility functions are well-tested, and the UI surfaces progress and errors clearly.
Review Summary
🟡 Warning — Async Papa.parse callback has no error boundary
The complete callback in handleCsvImport is now async but has no try-catch. If resolveEnsNames (or anything else in the callback) throws, the 'Resolving ENS names…' note stays permanently visible with no way to dismiss it, and there's an unhandled promise rejection. Wrap the async body in try/catch and show the error via setImportError.
🔵 Suggestion — ENS client missing batch config that exists elsewhere
The existing useEnsResolution.ts hook creates its mainnet client with batch: { batchSize: 100, wait: 10 }. The new ensClient in src/lib/ens.ts doesn't batch, so a CSV with many ENS names fires one RPC call per name. Consider adding the same batch config, or even sharing the client.
Clean, well-structured PR. Logic is properly separated into pure functions with good test coverage. The main concern is the unguarded async callback: if resolveEnsNames unexpectedly throws, the "Resolving ENS names…" message gets stuck with no way for the user to recover. The ENS client should also pick up the same batching config used elsewhere. Neither is a blocker, but the missing try-catch is the kind of thing that bites you in prod.
📌 2 inline comments
🟡 Warning: 1 · 🔵 Suggestion: 1
🔍 Reviewed by Gaston
There was a problem hiding this comment.
Gaston Review
Verdict: Approved
Score: ████████░░ 8/10
Pull Request Summary
This PR adds ENS name resolution during voter CSV import, validates that uploaded files match the expected template shape, and extracts a shared batched mainnet client used by both the new resolver and the existing useEnsResolution hook.
Both concerns from the prior review are addressed cleanly: the async callback now has a try-catch that surfaces errors in the UI, and the ENS client is extracted to src/lib/ens.ts with batching config, shared across both call sites. The pure utility functions have solid test coverage, the error UX is sensible (dismissible alert with a template link), and the skipEmptyLines addition is a nice touch. Good work — ship it.
🔍 Reviewed by Gaston
Restore EIP-55 typo detection via isVoterAddress (accept non-checksummed lower/upper case, reject mixed-case with a bad checksum). Distinguish transient ENS RPC failures from unregistered names so imports can retry, report unresolved ENS names instead of a wrong-column error, guard the async import against a double-upload race, and turn the import note red when rows are dropped for a malformed address.
There was a problem hiding this comment.
Gaston Review
Verdict: Approved
Score: ████████░░ 8/10
Pull Request Summary
This PR adds ENS name resolution during voter CSV import (ENS names in the address column are resolved to wallet addresses before the roster sync runs), rejects files that don't match the expected template shape, validates EIP-55 checksums on mixed-case addresses to catch typos, and extracts a shared batched mainnet client used by both the new resolver and the existing useEnsResolution hook.
Both concerns from prior reviews are addressed: the async Papa.parse callback has a try-catch that surfaces errors in the UI, and the ENS client is extracted to src/lib/ens.ts with batching config shared across both call sites. The stale-callback guard via importSeq is a nice pattern for preventing race conditions on rapid re-uploads. Pure utility functions are well-separated and thoroughly tested. Error UX is solid — transient RPC failures get a retry prompt, unregistered names get a specific message, and malformed files point to the template. Ship it.
🔍 Reviewed by Gaston
There was a problem hiding this comment.
Gaston Review
Verdict: Approved
Score: ████████░░ 8/10
Pull Request Summary
This PR adds ENS name resolution during voter CSV import (.eth names in the address column are resolved to wallet addresses before the roster sync), rejects files that don't match the expected template shape, validates EIP-55 checksums on mixed-case addresses to catch typos, and extracts a shared batched mainnet client used by both the new resolver and the existing useEnsResolution hook.
All concerns from prior reviews are addressed. The async callback has a try-catch, the ENS client is shared with batching, the stale-callback guard prevents race conditions, and the .eth-only ENS detection avoids misclassifying dotted strings from wrong-shaped files. Pure functions are well-separated with thorough test coverage. Error UX is thoughtful — transient RPC failures prompt a retry, unregistered names get a specific message, and malformed files point to the template. Clean work, ready to ship.
🔍 Reviewed by Gaston
There was a problem hiding this comment.
Gaston Review
Verdict: Approved
Score: ████████░░ 8/10
Pull Request Summary
This PR adds ENS name resolution during voter CSV import (.eth names in the address column are resolved to wallet addresses before the roster sync), rejects files that don't match the expected template shape, validates EIP-55 checksums on mixed-case addresses to catch typos, and extracts a shared batched mainnet client used by both the new resolver and the existing useEnsResolution hook.
Fourth pass — all prior concerns are addressed and the code hasn't regressed. The async callback has a try-catch, the ENS client is shared with batching, the stale-callback guard prevents race conditions, and the .eth-only ENS detection avoids misclassifying dotted strings from wrong-shaped files. Pure functions are well-separated with thorough test coverage. Error UX is thoughtful. Ship it.
🔍 Reviewed by Gaston
Voter CSV import had two failure modes that produced silent no-ops:
Name, Wallet, Email) had every row skipped with no feedback.name.eth) in the address column were rejected as invalid addresses.Changes
.ethnames in the address column are resolved to addresses (mainnet) before validation/sync.src/lib/ens.ts(resolveEnsNames) plus pure helpersisEnsName/collectEnsNames/applyEnsResolutions/validateCsvShape, with unit tests.Verification
pnpm vitest run(voterCsv): 15 passingpnpm typecheck,pnpm lint,pnpm prettier: clean