Commit b967b1b2 authored by Noah Zinsmeister's avatar Noah Zinsmeister Committed by GitHub

fix: introduce safeNamehash (#2925)

* namehash -> safeNamehash where necessary

* cleanup

* address comment
parent 596ea030
import { namehash } from '@ethersproject/hash'
import { useMemo } from 'react' import { useMemo } from 'react'
import { safeNamehash } from 'utils/safeNamehash'
import { useSingleCallResult } from '../state/multicall/hooks' import { useSingleCallResult } from '../state/multicall/hooks'
import isZero from '../utils/isZero' import isZero from '../utils/isZero'
...@@ -11,14 +11,10 @@ import useDebounce from './useDebounce' ...@@ -11,14 +11,10 @@ import useDebounce from './useDebounce'
*/ */
export default function useENSAddress(ensName?: string | null): { loading: boolean; address: string | null } { export default function useENSAddress(ensName?: string | null): { loading: boolean; address: string | null } {
const debouncedName = useDebounce(ensName, 200) const debouncedName = useDebounce(ensName, 200)
const ensNodeArgument = useMemo(() => { const ensNodeArgument = useMemo(
if (!debouncedName) return [undefined] () => [debouncedName === null ? undefined : safeNamehash(debouncedName)],
try { [debouncedName]
return debouncedName ? [namehash(debouncedName)] : [undefined] )
} catch (error) {
return [undefined]
}
}, [debouncedName])
const registrarContract = useENSRegistrarContract(false) const registrarContract = useENSRegistrarContract(false)
const resolverAddress = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument) const resolverAddress = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument)
const resolverAddressResult = resolverAddress.result?.[0] const resolverAddressResult = resolverAddress.result?.[0]
......
import { namehash } from '@ethersproject/hash' import { namehash } from '@ethersproject/hash'
import { useEffect, useMemo, useState } from 'react' import { useEffect, useMemo, useState } from 'react'
import { safeNamehash } from 'utils/safeNamehash'
import uriToHttp from 'utils/uriToHttp' import uriToHttp from 'utils/uriToHttp'
import { useSingleCallResult } from '../state/multicall/hooks' import { useSingleCallResult } from '../state/multicall/hooks'
...@@ -21,15 +22,12 @@ export default function useENSAvatar( ...@@ -21,15 +22,12 @@ export default function useENSAvatar(
const debouncedAddress = useDebounce(address, 200) const debouncedAddress = useDebounce(address, 200)
const node = useMemo(() => { const node = useMemo(() => {
if (!debouncedAddress || !isAddress(debouncedAddress)) return undefined if (!debouncedAddress || !isAddress(debouncedAddress)) return undefined
try { return namehash(`${debouncedAddress.toLowerCase().substr(2)}.addr.reverse`)
return debouncedAddress ? namehash(`${debouncedAddress.toLowerCase().substr(2)}.addr.reverse`) : undefined
} catch (error) {
return undefined
}
}, [debouncedAddress]) }, [debouncedAddress])
const addressAvatar = useAvatarFromNode(node) const addressAvatar = useAvatarFromNode(node)
const nameAvatar = useAvatarFromNode(namehash(useENSName(address).ENSName ?? '')) const ENSName = useENSName(address).ENSName
const nameAvatar = useAvatarFromNode(ENSName === null ? undefined : safeNamehash(ENSName))
let avatar = addressAvatar.avatar || nameAvatar.avatar let avatar = addressAvatar.avatar || nameAvatar.avatar
const nftAvatar = useAvatarFromNFT(avatar, enforceOwnership) const nftAvatar = useAvatarFromNFT(avatar, enforceOwnership)
......
import { namehash } from '@ethersproject/hash'
import { useMemo } from 'react' import { useMemo } from 'react'
import { safeNamehash } from 'utils/safeNamehash'
import { useSingleCallResult } from '../state/multicall/hooks' import { useSingleCallResult } from '../state/multicall/hooks'
import isZero from '../utils/isZero' import isZero from '../utils/isZero'
...@@ -9,14 +9,7 @@ import { useENSRegistrarContract, useENSResolverContract } from './useContract' ...@@ -9,14 +9,7 @@ import { useENSRegistrarContract, useENSResolverContract } from './useContract'
* Does a lookup for an ENS name to find its contenthash. * Does a lookup for an ENS name to find its contenthash.
*/ */
export default function useENSContentHash(ensName?: string | null): { loading: boolean; contenthash: string | null } { export default function useENSContentHash(ensName?: string | null): { loading: boolean; contenthash: string | null } {
const ensNodeArgument = useMemo(() => { const ensNodeArgument = useMemo(() => [ensName === null ? undefined : safeNamehash(ensName)], [ensName])
if (!ensName) return [undefined]
try {
return ensName ? [namehash(ensName)] : [undefined]
} catch (error) {
return [undefined]
}
}, [ensName])
const registrarContract = useENSRegistrarContract(false) const registrarContract = useENSRegistrarContract(false)
const resolverAddressResult = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument) const resolverAddressResult = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument)
const resolverAddress = resolverAddressResult.result?.[0] const resolverAddress = resolverAddressResult.result?.[0]
......
...@@ -15,11 +15,7 @@ export default function useENSName(address?: string): { ENSName: string | null; ...@@ -15,11 +15,7 @@ export default function useENSName(address?: string): { ENSName: string | null;
const debouncedAddress = useDebounce(address, 200) const debouncedAddress = useDebounce(address, 200)
const ensNodeArgument = useMemo(() => { const ensNodeArgument = useMemo(() => {
if (!debouncedAddress || !isAddress(debouncedAddress)) return [undefined] if (!debouncedAddress || !isAddress(debouncedAddress)) return [undefined]
try { return [namehash(`${debouncedAddress.toLowerCase().substr(2)}.addr.reverse`)]
return debouncedAddress ? [namehash(`${debouncedAddress.toLowerCase().substr(2)}.addr.reverse`)] : [undefined]
} catch (error) {
return [undefined]
}
}, [debouncedAddress]) }, [debouncedAddress])
const registrarContract = useENSRegistrarContract(false) const registrarContract = useENSRegistrarContract(false)
const resolverAddress = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument) const resolverAddress = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument)
......
import { namehash } from '@ethersproject/hash'
import { safeNamehash } from './safeNamehash'
describe('#safeNamehash', () => {
const emoji = '🤔'
it('#namehash fails', () => {
expect(() => namehash(emoji)).toThrow('STRINGPREP_CONTAINS_UNASSIGNED')
})
// suppress console.debug for the next test
beforeEach(() => {
// eslint-disable-next-line @typescript-eslint/no-empty-function
jest.spyOn(console, 'debug').mockImplementation(() => {})
})
it('works', () => {
expect(safeNamehash(emoji)).toEqual(undefined)
})
})
import { namehash } from '@ethersproject/hash'
export function safeNamehash(name?: string): string | undefined {
if (name === undefined) return undefined
try {
return namehash(name)
} catch (error) {
console.debug(error)
return undefined
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment