UNPKG

whoisens-lib

Version:

Whois for ENS (Ethereum Name Service) lookup service

303 lines (246 loc) 9.02 kB
import config from '../config.js'; import { EthAddressType, IENSParams, InvalidEthNameError, IResponseResponseInfo, NameIsNotRegisteredError } from './types.js'; import ENSRoot from './ENSRoot.js'; import Registrar from './Registrar.js'; import Resolver from './Resolver.js'; import ReverseResolver from './ReverseResolver.js'; import utils from '../utils/index.js'; import BaseClass from './BaseClass.js'; import Config from './Config.js'; import debug from 'debug'; export default class ENS extends BaseClass { private readonly ENSRoot: ENSRoot; private Registrar: Registrar; private Resolver: Resolver; private ReverseResolver: ReverseResolver; /** * Store original requested Ethereum Name, as ethAddress could be transform to hex representation if needed */ private ethAddressOriginal: string | undefined; private ethAddress: string | undefined; private ethAddressType: EthAddressType | undefined; private resolveAddress: string | undefined; /** * @event */ static EVENT_ETH_ADDRESS = 'ethAddress'; /** * @event */ static EVENT_ETH_ADDRESS_TYPE = 'ethAddressType'; /** * @event */ static EVENT_SET_RESPONSE = 'setResponse'; constructor(params: IENSParams = {}) { super(); Config.getInstance().currentNetworkURL = params.networkURL || config.networkURL; Config.getInstance().contractAddress = params.contractAddress; this.ENSRoot = new ENSRoot(); } getEthAddressType(): EthAddressType { return this.ethAddressType; } /** * Init with eth address * * @fires ENS.EVENT_ETH_NAME * @fires ENS.EVENT_ETH_NAME_TYPE */ public init(ethAddress: string): void { this.ethAddressOriginal = ethAddress; this.ethAddress = ethAddress; this.emit(ENS.EVENT_ETH_ADDRESS, this.ethAddress); this.ethAddressType = utils.getAddressType(this.ethAddress); this.emit(ENS.EVENT_ETH_ADDRESS_TYPE, this.ethAddressType); if (this.ethAddressType === EthAddressType.error) throw new InvalidEthNameError(this.ethAddress); this.ethAddress = utils.reverseAddressToHex(this.ethAddress); } public async getInfo() { if (!this.ethAddress || !this.ethAddressType) throw new Error('Please call init before'); let controllerResult; let ownerResult; let resolverAddress; if (this.ethAddressType === EthAddressType.error) return; if (this.ethAddressType === EthAddressType.name) { controllerResult = await this.getController(); if (!utils.isResult(controllerResult.result)) return; ownerResult = await this.getOwner(); if (!ownerResult.result) return; await this.getExpirationDate(); resolverAddress = await this.getAddress(); await this.getContentHash(); if (!utils.isResult(resolverAddress.result)) return; this.resolveAddress = resolverAddress.result; } await this.getReverseRecord(); } /** * Get controller address. * * @fires ENS.EVENT_SET_RESPONSE * @type {object} * @property resultName {string} controllerResult * * @return Promise<Response> */ public async getController(): Promise<IResponseResponseInfo> { const EVENT_PROPERTY = 'controllerResult'; try { const controllerResult = await this.ENSRoot.getController(this.ethAddress); return this.sendResponse(EVENT_PROPERTY, controllerResult); } catch(error) { this.sendError(EVENT_PROPERTY, error); } } /** * Get Registrar owner. * * @fires ENS.EVENT_SET_RESPONSE * @type {object} * @property resultName {string} registrarOwnerResult * * @return Promise<Response> */ public async getOwner(): Promise<IResponseResponseInfo> { const EVENT_PROPERTY = 'ownerResult'; try { await this.initRegistrar(); const registrarOwnerResult = await this.Registrar.getOwner(); return this.sendResponse(EVENT_PROPERTY, registrarOwnerResult); } catch(error) { this.sendError(EVENT_PROPERTY, error); } } /** * Get name expiration date. * * @fires ENS.EVENT_SET_RESPONSE * @type {object} * @property resultName {string} nameExpires * * @return Promise<Response> */ public async getExpirationDate(): Promise<IResponseResponseInfo> { const EVENT_PROPERTY = 'expirationDateResult'; try { await this.initRegistrar(); const nameExpires = await this.Registrar.getExpirationDate(); return this.sendResponse(EVENT_PROPERTY, nameExpires); } catch(error) { this.sendError(EVENT_PROPERTY, error); } } /** * Get address * * @fires ENS.EVENT_SET_RESPONSE * @type {object} * @property resultName {string} resolverAddress * * @return Promise<Response> */ public async getAddress(): Promise<IResponseResponseInfo> { const EVENT_PROPERTY = 'addressResult'; try { if (await this.isNameRegistered()) { await this.initResolver(); const resolverAddress = await this.Resolver.getAddress(); return this.sendResponse(EVENT_PROPERTY, resolverAddress); } else { this.sendError(EVENT_PROPERTY, new NameIsNotRegisteredError()); } } catch(error) { this.sendError(EVENT_PROPERTY, error); } } /** * Get content hash * * @fires ENS.EVENT_SET_RESPONSE * @type {object} * @property resultName {string} resolverContentHash * * @return Promise<Response> */ public async getContentHash(): Promise<IResponseResponseInfo> { const EVENT_PROPERTY = 'contentHashResult'; try { await this.initResolver(); const resolverContentHash = await this.Resolver.getContentHash(); return this.sendResponse(EVENT_PROPERTY, resolverContentHash); } catch(error) { this.sendError(EVENT_PROPERTY, error); } } /** * Get reverse record, e.g. name from address * * @fires ENS.EVENT_SET_RESPONSE * @type {object} * @property resultName {string} revertResolverResult * * @return Promise<Response> */ public async getReverseRecord(): Promise<IResponseResponseInfo> { const EVENT_PROPERTY = 'reverseRecordResult'; try { const address = this.resolveAddress || this.ethAddress; this.ReverseResolver = new ReverseResolver(address); const revertResolverResult = await this.ReverseResolver.getName(); return this.sendResponse(EVENT_PROPERTY, revertResolverResult); } catch(error) { this.sendError(EVENT_PROPERTY, error); } } public async resolve(): Promise<IResponseResponseInfo> { if (this.ethAddressType === EthAddressType.name) return this.getAddress(); if (this.ethAddressType === EthAddressType.address) return this.getReverseRecord(); } private async initRegistrar() { if (!this.Registrar) this.Registrar = new Registrar(this.ethAddress); } private async initResolver() { if (!this.Resolver) this.Resolver = new Resolver(this.ethAddress); } private async isNameRegistered() { await this.initRegistrar(); const owner = await this.Registrar.getOwner(); return utils.isResult(owner.result); } private sendResponse(resultName: string, result: IResponseResponseInfo): IResponseResponseInfo { result = this.extendResultWithAdditionalInfo(result); this.emit(ENS.EVENT_SET_RESPONSE, { resultName, result }); return result; } private sendError(resultName: string, result: any) { debug('error')(`${resultName}: ${result}`); this.sendResponse(resultName, result); throw result; } private extendResultWithAdditionalInfo(result: IResponseResponseInfo): IResponseResponseInfo { const outputResult = { ...result, data: { ...result.data, address: this.ethAddress, addressType: this.ethAddressType } }; const nameMain = this.ethAddressType === EthAddressType.name && utils.getNameMain(this.ethAddress); const address = result.data && result.data.reverseAddress || outputResult.data.address; const addressParent = address && utils.getAddressParent(address); if (nameMain) outputResult.data.nameMain = nameMain; if (addressParent) outputResult.data.addressParent = addressParent; return outputResult; } }