115 lines
3.4 KiB
JavaScript
115 lines
3.4 KiB
JavaScript
// from https://github.com/ChainSafe/web3.js/issues/2683#issuecomment-547348416
|
|
|
|
import namehash from 'eth-ens-namehash'
|
|
import ABI from 'web3-eth-ens/lib/resources/ABI/Resolver'
|
|
import uniq from 'lodash/uniq'
|
|
import chunk from 'lodash/chunk'
|
|
import { CHUNK_COUNT_PER_BATCH_REQUEST } from '@/constants'
|
|
|
|
const { isAddress } = require('web3-utils')
|
|
|
|
export const createBatchRequestCallback = (resolve, reject) => (error, data) => {
|
|
if (error) {
|
|
reject(error)
|
|
} else {
|
|
resolve(data)
|
|
}
|
|
}
|
|
|
|
const CACHE = {}
|
|
|
|
const createFetchNodeAddresses = (registryContract, batch) => async (address) => {
|
|
const addressLower = address.toLowerCase()
|
|
|
|
const node = addressLower.substr(2) + '.addr.reverse'
|
|
const nodeHash = namehash.hash(node)
|
|
let nodeAddress = null
|
|
|
|
if (!CACHE[addressLower]) {
|
|
try {
|
|
nodeAddress = await new Promise((resolve, reject) => {
|
|
const callback = createBatchRequestCallback(resolve, reject)
|
|
const requestData = registryContract.methods.resolver(nodeHash).call.request(callback)
|
|
batch.add(requestData)
|
|
})
|
|
|
|
if (+nodeAddress === 0) nodeAddress = null
|
|
} catch (error) {
|
|
console.error(`Error resolve ens for "${address}"`, error.message)
|
|
// do nothing
|
|
}
|
|
}
|
|
|
|
return {
|
|
addressLower,
|
|
address,
|
|
nodeHash,
|
|
nodeAddress
|
|
}
|
|
}
|
|
|
|
const createFetchEnsNames = (web3, batch, results) => async (data) => {
|
|
const { address, addressLower, nodeHash, nodeAddress } = data
|
|
if (!nodeAddress) return results
|
|
|
|
if (CACHE[addressLower]) {
|
|
results[address] = CACHE[addressLower]
|
|
return results
|
|
}
|
|
|
|
const nodeContract = new web3.eth.Contract(ABI, nodeAddress)
|
|
|
|
try {
|
|
const ensName = await new Promise((resolve, reject) => {
|
|
const callback = createBatchRequestCallback(resolve, reject)
|
|
const requestData = nodeContract.methods.name(nodeHash).call.request(callback)
|
|
batch.add(requestData)
|
|
})
|
|
|
|
const isZeroAddress = ensName.trim().length && isAddress(ensName) && BigInt(ensName) === BigInt(0)
|
|
|
|
if (isZeroAddress) return results
|
|
|
|
CACHE[addressLower] = ensName
|
|
results[address] = ensName
|
|
|
|
return results
|
|
} catch (error) {
|
|
console.error(`Error lookupAddress ens for "${address}"`, error.message)
|
|
return results
|
|
}
|
|
}
|
|
|
|
export const lookupAddressesRequest = async (addressList, web3, registryContract) => {
|
|
const fetchNodeAddressesBatch = new web3.BatchRequest()
|
|
const fetchNodeAddresses = createFetchNodeAddresses(registryContract, fetchNodeAddressesBatch)
|
|
const fetchNodeAddressesPromises = uniq(addressList).map(fetchNodeAddresses)
|
|
fetchNodeAddressesBatch.execute()
|
|
|
|
const nodeAddresses = await Promise.all(fetchNodeAddressesPromises)
|
|
|
|
const results = {}
|
|
const fetchEnsNamesBatch = new web3.BatchRequest()
|
|
const fetchEnsNames = createFetchEnsNames(web3, fetchEnsNamesBatch, results)
|
|
const fetchEnsNamesPromises = nodeAddresses.map(fetchEnsNames)
|
|
fetchEnsNamesBatch.execute()
|
|
|
|
await Promise.all(fetchEnsNamesPromises)
|
|
return results
|
|
}
|
|
|
|
export const lookupAddresses = async (addressList, web3) => {
|
|
const registryContract = await web3.eth.ens.registry.contract
|
|
// web3.eth.ens._lastSyncCheck = Date.now() // - need for test in fork
|
|
|
|
const addressListChunks = chunk(addressList, CHUNK_COUNT_PER_BATCH_REQUEST)
|
|
let results = {}
|
|
|
|
for await (const list of addressListChunks) {
|
|
const result = await lookupAddressesRequest(list, web3, registryContract)
|
|
results = { ...results, ...result }
|
|
}
|
|
|
|
return results
|
|
}
|