-
Notifications
You must be signed in to change notification settings - Fork 2
use EFP as the resolution source for ENS names #1515
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
bc86fa5
3eefe90
81f8a84
4742909
4c1f0ab
45245b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,37 @@ | ||
| "use client"; | ||
|
|
||
| import { useQuery, useQueries } from "@tanstack/react-query"; | ||
| import { Address, isAddress } from "viem"; | ||
| import { normalize } from "viem/ens"; | ||
| import { publicClient } from "@/shared/services/wallet/wallet"; | ||
| import axios from "axios"; | ||
| import { Address } from "viem"; | ||
|
|
||
| const getEnsUrl = (address: Address | `${string}.eth`) => { | ||
| return `https://api.ethfollow.xyz/api/v1/users/${address}/ens`; | ||
| }; | ||
|
|
||
| type EnsRecords = { | ||
| avatar?: string; | ||
| "com.discord"?: string; | ||
| "com.github"?: string; | ||
| "com.twitter"?: string; | ||
| description?: string; | ||
| email?: string; | ||
| header?: string; | ||
| location?: string; | ||
| name?: string; | ||
| "org.telegram"?: string; | ||
| url?: string; | ||
| [key: string]: string | undefined; | ||
| }; | ||
|
|
||
| type EnsApiResponse = { | ||
| ens: { | ||
| name: string; | ||
| address: Address; | ||
| avatar: string | null; | ||
| records: EnsRecords | null; | ||
| updated_at: string; | ||
| }; | ||
| }; | ||
|
|
||
| type EnsData = { | ||
| address: Address; | ||
|
|
@@ -14,7 +42,7 @@ type EnsData = { | |
|
|
||
| /** | ||
| * Hook to fetch ENS data for a single address | ||
| * @param address - Ethereum address (e.g., "0x123...") | ||
| * @param address - Ethereum address (e.g., "0x123..." ) | ||
| * @returns Object containing ENS data, error, and loading state | ||
| */ | ||
| export const useEnsData = (address: Address | null | undefined) => { | ||
|
|
@@ -35,32 +63,35 @@ export const useEnsData = (address: Address | null | undefined) => { | |
| }; | ||
|
|
||
| /** | ||
| * Fetches ENS data using viem for a single address | ||
| * Fetches ENS data from the API for a single address | ||
| * @param address - Ethereum address | ||
| * @returns Promise resolving to EnsData | ||
| * @throws Error if the API request fails or response is invalid | ||
| */ | ||
| export const fetchEnsDataFromAddress = async ({ | ||
| address, | ||
| }: { | ||
| address: Address; | ||
| }): Promise<EnsData> => { | ||
| let ensName: string | null = null; | ||
| let avatarUrl: string | null = null; | ||
| const response = await axios.get<EnsApiResponse>(getEnsUrl(address)); | ||
| const data = response.data; | ||
|
|
||
| if (isAddress(address)) { | ||
| ensName = await publicClient.getEnsName({ address }); | ||
| // Validate response structure | ||
| if (!data?.ens) { | ||
| throw new Error("Invalid ENS API response: missing ens field"); | ||
| } | ||
|
|
||
| // Get avatar URL if we have an ENS name | ||
| if (ensName) { | ||
| avatarUrl = await publicClient.getEnsAvatar({ name: normalize(ensName) }); | ||
| if (!data.ens.address) { | ||
| throw new Error("Invalid ENS API response: missing address field"); | ||
| } | ||
|
|
||
| // Empty name is valid (means no ENS name exists for this address) | ||
| // Transform API response to match expected EnsData structure | ||
| return { | ||
| address: address, | ||
| avatar_url: avatarUrl, | ||
| ens: ensName || "", | ||
| avatar: avatarUrl, | ||
| address: data.ens.address, | ||
| avatar_url: data.ens.avatar, | ||
| ens: data.ens.name, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing null fallback for
|
||
| avatar: data.ens.avatar, | ||
| }; | ||
| }; | ||
|
|
||
|
|
@@ -69,10 +100,19 @@ export const fetchAddressFromEnsName = async ({ | |
| }: { | ||
| ensName: `${string}.eth`; | ||
| }): Promise<Address | null> => { | ||
| const address = await publicClient.getEnsAddress({ | ||
| name: normalize(ensName), | ||
| }); | ||
| return address || null; | ||
| const response = await axios.get<EnsApiResponse>(getEnsUrl(ensName)); | ||
| const data = response.data; | ||
|
|
||
| // Validate response structure | ||
| if (!data?.ens) { | ||
| return null; | ||
| } | ||
|
|
||
| if (!data.ens.address) { | ||
| return null; | ||
| } | ||
|
|
||
| return data.ens.address; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Function throws instead of returning null, breaking callers
|
||
| }; | ||
|
|
||
| /** | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what happens with the UI when this is thrown?
if a problem happens, we should handle it silently
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing, UI falls back silently