@unstoppabledomains/resolution
Version:
Domain Resolution for blockchain domains
997 lines (996 loc) • 66.3 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Resolution = void 0;
var bn_js_1 = __importDefault(require("bn.js"));
var Ens_1 = __importDefault(require("./Ens"));
var Zns_1 = __importDefault(require("./Zns"));
var Uns_1 = __importDefault(require("./Uns"));
var UdApi_1 = __importDefault(require("./UdApi"));
var publicTypes_1 = require("./types/publicTypes");
var resolutionError_1 = __importStar(require("./errors/resolutionError"));
var DnsUtils_1 = __importDefault(require("./utils/DnsUtils"));
var utils_1 = require("./utils");
var Eip1993Factories_1 = require("./utils/Eip1993Factories");
var configurationError_1 = __importDefault(require("./errors/configurationError"));
var configurationError_2 = require("./errors/configurationError");
var Networking_1 = __importDefault(require("./utils/Networking"));
var prepareAndValidate_1 = require("./utils/prepareAndValidate");
var namehash_1 = require("./utils/namehash");
var DEFAULT_UNS_PROXY_SERVICE_URL = 'https://api.unstoppabledomains.com/resolve';
/**
* Blockchain domain Resolution library - Resolution.
* @example
* ```
* import Resolution from '@unstoppabledomains/resolution';
*
* let resolution = new Resolution({ blockchain: {
* uns: {
* url: "https://mainnet.infura.io/v3/<infura_api_key>",
* network: "mainnet"
* }
* }
* });
*
* let domain = "brad.zil";
* resolution.addr(domain, "eth").then(addr => console.log(addr));;
* ```
*/
var Resolution = /** @class */ (function () {
function Resolution(config) {
var _a;
if (config === void 0) { config = {}; }
var uns = this.getUnsConfig(config);
var unsBase = this.getUnsBaseConfig(config);
var zns = this.getZnsConfig(config);
var ens = this.getEnsConfig(config);
// If both UNS and ZNS use the same UdApi providers, we don't want to call the API twice as it would return same
// responses. It should be enough to compare just the URLs, as the network param isn't actually used in the calls.
var equalUdApiProviders = uns instanceof UdApi_1.default && zns instanceof UdApi_1.default && uns.url === zns.url;
// If a user configures the lib with an API source, we still want to initialise native blockchain services to access
// some non-async methods such as namehash, as they are unavailable in the UdApi service.
this.serviceMap = (_a = {},
_a[publicTypes_1.NamingServiceName.UNS] = {
usedServices: [uns],
native: uns instanceof Uns_1.default ? uns : new Uns_1.default(),
},
_a[publicTypes_1.NamingServiceName.ZNS] = {
usedServices: equalUdApiProviders ? [uns] : [uns, zns],
native: zns instanceof Zns_1.default ? zns : new Zns_1.default(),
},
_a[publicTypes_1.NamingServiceName.ENS] = {
usedServices: [ens],
native: ens instanceof Ens_1.default ? ens : new Ens_1.default(),
},
_a);
if (unsBase) {
this.serviceMap[publicTypes_1.NamingServiceName.UNS_BASE] = {
usedServices: [unsBase],
native: unsBase instanceof Uns_1.default ? unsBase : new Uns_1.default(),
};
}
}
Resolution.prototype.getService = function (serviceName) {
var entry = this.serviceMap[serviceName];
if (!entry) {
throw new configurationError_1.default(configurationError_2.ConfigurationErrorCode.NetworkConfigMissing, {
method: serviceName,
config: serviceName === publicTypes_1.NamingServiceName.UNS_BASE
? "sourceConfig.uns.base"
: "sourceConfig.".concat(serviceName.toLowerCase()),
});
}
return entry;
};
/**
* AutoConfigure the blockchain network between different testnets for ENS and UNS
* We make a "net_version" JSON RPC call to the blockchain either via url or with the help of given provider.
* @param sourceConfig - configuration object for ens and uns
* @returns configured Resolution object
*/
Resolution.autoNetwork = function (sourceConfig) {
return __awaiter(this, void 0, void 0, function () {
var resolution, uns, ens;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
resolution = new this();
if (!sourceConfig.uns && !sourceConfig.ens) {
throw new configurationError_1.default(configurationError_2.ConfigurationErrorCode.UnsupportedNetwork);
}
if (!sourceConfig.uns) return [3 /*break*/, 2];
return [4 /*yield*/, Uns_1.default.autoNetwork(sourceConfig.uns)];
case 1:
uns = _a.sent();
resolution.serviceMap[publicTypes_1.NamingServiceName.UNS] = {
usedServices: [uns],
native: uns,
};
_a.label = 2;
case 2:
if (!sourceConfig.ens) return [3 /*break*/, 4];
return [4 /*yield*/, Ens_1.default.autoNetwork(sourceConfig.ens)];
case 3:
ens = _a.sent();
resolution.serviceMap[publicTypes_1.NamingServiceName.ENS] = {
usedServices: [ens],
native: ens,
};
_a.label = 4;
case 4: return [2 /*return*/, resolution];
}
});
});
};
/**
* Creates a resolution with configured infura id for ens and uns
* @param infura - infura project id
* @param networks - an optional object that describes what network to use when connecting ENS or UNS default is mainnet
*/
Resolution.infura = function (infura, networks) {
var _a, _b, _c, _d, _e, _f;
return new this({
sourceConfig: {
ens: {
url: (0, utils_1.signedInfuraLink)(infura, (_a = networks === null || networks === void 0 ? void 0 : networks.ens) === null || _a === void 0 ? void 0 : _a.network),
network: ((_b = networks === null || networks === void 0 ? void 0 : networks.ens) === null || _b === void 0 ? void 0 : _b.network) || 'mainnet',
},
uns: {
locations: {
Layer1: {
url: (0, utils_1.signedLink)(infura, ((_c = networks === null || networks === void 0 ? void 0 : networks.uns) === null || _c === void 0 ? void 0 : _c.locations.Layer1.network) || 'mainnet', 'infura'),
network: ((_d = networks === null || networks === void 0 ? void 0 : networks.uns) === null || _d === void 0 ? void 0 : _d.locations.Layer1.network) || 'mainnet',
},
Layer2: {
url: (0, utils_1.signedLink)(infura, ((_e = networks === null || networks === void 0 ? void 0 : networks.uns) === null || _e === void 0 ? void 0 : _e.locations.Layer2.network) || 'polygon-mainnet', 'infura'),
network: ((_f = networks === null || networks === void 0 ? void 0 : networks.uns) === null || _f === void 0 ? void 0 : _f.locations.Layer2.network) || 'polygon-mainnet',
},
},
},
},
});
};
/**
* Creates a resolution with configured alchemy API keys for uns
* @param alchemy - alchemy API keys
* @param networks - an optional object that describes what network to use when connecting UNS default is mainnet
*/
Resolution.alchemy = function (alchemy, networks) {
var _a, _b, _c, _d;
return new this({
sourceConfig: {
uns: {
locations: {
Layer1: {
url: (0, utils_1.signedLink)(alchemy, ((_a = networks === null || networks === void 0 ? void 0 : networks.uns) === null || _a === void 0 ? void 0 : _a.locations.Layer1.network) || 'mainnet'),
network: ((_b = networks === null || networks === void 0 ? void 0 : networks.uns) === null || _b === void 0 ? void 0 : _b.locations.Layer1.network) || 'mainnet',
},
Layer2: {
url: (0, utils_1.signedLink)(alchemy, ((_c = networks === null || networks === void 0 ? void 0 : networks.uns) === null || _c === void 0 ? void 0 : _c.locations.Layer2.network) || 'polygon-mainnet'),
network: ((_d = networks === null || networks === void 0 ? void 0 : networks.uns) === null || _d === void 0 ? void 0 : _d.locations.Layer2.network) || 'polygon-mainnet',
},
},
},
},
});
};
/**
* Creates a resolution instance with configured provider
* @param networks - an object that describes what network to use when connecting UNS, ENS, or ZNS default is mainnet
* @see https://eips.ethereum.org/EIPS/eip-1193
*/
Resolution.fromResolutionProvider = function (networks) {
if (networks.ens || networks.uns) {
return this.fromEthereumEip1193Provider({
ens: networks.ens,
uns: networks.uns,
});
}
if (networks.zns) {
return this.fromZilliqaProvider(networks.zns.provider, networks);
}
throw new resolutionError_1.default(resolutionError_1.ResolutionErrorCode.ServiceProviderError, {
providerMessage: 'Must specify network for uns, ens, or zns',
});
};
/**
* Creates a resolution instance with configured provider
* @param networks - an object that describes what network to use when connecting UNS and ENS default is mainnet
* @see https://eips.ethereum.org/EIPS/eip-1193
*/
Resolution.fromEthereumEip1193Provider = function (networks) {
var _a;
var sourceConfig = {};
if (networks.ens) {
sourceConfig.ens = {
provider: networks.ens.provider,
network: ((_a = networks === null || networks === void 0 ? void 0 : networks.ens) === null || _a === void 0 ? void 0 : _a.network) || 'mainnet',
};
}
if (networks.uns) {
sourceConfig.uns = {
locations: {
Layer1: {
provider: networks.uns.locations.Layer1.provider,
network: networks.uns.locations.Layer1.network || 'mainnet',
},
Layer2: {
provider: networks.uns.locations.Layer2.provider,
network: networks.uns.locations.Layer2.network || 'polygon-mainnet',
},
},
};
}
return new this({
sourceConfig: sourceConfig,
});
};
/**
* Creates a resolution instance with configured provider
* @param provider - any provider compatible with EIP-1193
* @param networks - an optional object that describes what network to use when connecting ZNS default is mainnet
* @see https://eips.ethereum.org/EIPS/eip-1193
*/
Resolution.fromZilliqaProvider = function (provider, networks) {
var _a;
return new this({
sourceConfig: {
zns: { provider: provider, network: ((_a = networks === null || networks === void 0 ? void 0 : networks.zns) === null || _a === void 0 ? void 0 : _a.network) || 'mainnet' },
},
});
};
/**
* Create a resolution instance from web3 0.x version provider
* @param networks - Ethereum network configuration with 0.x version provider from web3 ( must implement sendAsync(payload, callback) )
* @see https://github.com/ethereum/web3.js/blob/0.20.7/lib/web3/httpprovider.js#L116
*/
Resolution.fromWeb3Version0Provider = function (networks) {
return this.fromEthereumEip1193Provider({
ens: networks.ens
? {
network: networks.ens.network,
provider: Eip1993Factories_1.Eip1993Factories.fromWeb3Version0Provider(networks.ens.provider),
}
: undefined,
uns: networks.uns
? {
locations: {
Layer1: {
network: networks.uns.locations.Layer1.network,
provider: Eip1993Factories_1.Eip1993Factories.fromWeb3Version0Provider(networks.uns.locations.Layer1.provider),
},
Layer2: {
network: networks.uns.locations.Layer2.network,
provider: Eip1993Factories_1.Eip1993Factories.fromWeb3Version0Provider(networks.uns.locations.Layer2.provider),
},
},
}
: undefined,
});
};
/**
* Create a resolution instance from web3 1.x version provider
* @param networks - an optional object with 1.x version provider from web3 ( must implement send(payload, callback) ) that describes what network to use when connecting ENS or UNS default is mainnet
* @see https://github.com/ethereum/web3.js/blob/1.x/packages/web3-core-helpers/types/index.d.ts#L165
* @see https://github.com/ethereum/web3.js/blob/1.x/packages/web3-providers-http/src/index.js#L95
*/
Resolution.fromWeb3Version1Provider = function (networks) {
return this.fromEthereumEip1193Provider({
ens: networks.ens
? {
network: networks.ens.network,
provider: Eip1993Factories_1.Eip1993Factories.fromWeb3Version1Provider(networks.ens.provider),
}
: undefined,
uns: networks.uns
? {
locations: {
Layer1: {
network: networks.uns.locations.Layer1.network,
provider: Eip1993Factories_1.Eip1993Factories.fromWeb3Version1Provider(networks.uns.locations.Layer1.provider),
},
Layer2: {
network: networks.uns.locations.Layer2.network,
provider: Eip1993Factories_1.Eip1993Factories.fromWeb3Version1Provider(networks.uns.locations.Layer2.provider),
},
},
}
: undefined,
});
};
/**
* Creates instance of resolution from provider that implements Ethers Provider#call interface.
* This wrapper support only `eth_call` method for now, which is enough for all the current Resolution functionality
* @param networks - an object that describes what network to use when connecting ENS or UNS default is mainnet
* @see https://github.com/ethers-io/ethers.js/blob/v4-legacy/providers/abstract-provider.d.ts#L91
* @see https://github.com/ethers-io/ethers.js/blob/v5.0.4/packages/abstract-provider/src.ts/index.ts#L224
* @see https://docs.ethers.io/ethers.js/v5-beta/api-providers.html#jsonrpcprovider-inherits-from-provider
* @see https://github.com/ethers-io/ethers.js/blob/master/packages/providers/src.ts/json-rpc-provider.ts
*/
Resolution.fromEthersProvider = function (networks) {
return this.fromEthereumEip1193Provider({
ens: networks.ens
? {
network: networks.ens.network,
provider: Eip1993Factories_1.Eip1993Factories.fromEthersProvider(networks.ens.provider),
}
: undefined,
uns: networks.uns
? {
locations: {
Layer1: {
network: networks.uns.locations.Layer1.network,
provider: Eip1993Factories_1.Eip1993Factories.fromEthersProvider(networks.uns.locations.Layer1.provider),
},
Layer2: {
network: networks.uns.locations.Layer2.network,
provider: Eip1993Factories_1.Eip1993Factories.fromEthersProvider(networks.uns.locations.Layer2.provider),
},
},
}
: undefined,
});
};
/**
* Resolves given domain name to a specific currency address if exists
* @async
* @param domain - domain name to be resolved
* @param ticker - currency ticker like BTC, ETH, ZIL
* @throws [[ResolutionError]] if address is not found
* @returns A promise that resolves in an address
*/
Resolution.prototype.addr = function (domain, ticker) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return [4 /*yield*/, this.callServiceForDomain(domain, function (service) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(service instanceof Ens_1.default)) return [3 /*break*/, 2];
return [4 /*yield*/, service.addr(domain, ticker)];
case 1: return [2 /*return*/, _a.sent()];
case 2: return [4 /*yield*/, this.record(domain, "crypto.".concat(ticker.toUpperCase(), ".address"))];
case 3: return [2 /*return*/, _a.sent()];
}
});
}); })];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Read multi-chain currency address if exists
* @async
* @param domain - domain name to be resolved
* @param ticker - currency ticker (USDT, FTM, etc.)
* @param chain - chain version, usually means blockchain ( ERC20, BEP2, OMNI, etc. )
* @throws [[ResolutionError]] if address is not found
* @returns A promise that resolves in an adress
*/
Resolution.prototype.multiChainAddr = function (domain, ticker, chain) {
return __awaiter(this, void 0, void 0, function () {
var recordKey;
var _this = this;
return __generator(this, function (_a) {
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
recordKey = "crypto.".concat(ticker.toUpperCase(), ".version.").concat(chain.toUpperCase(), ".address");
return [2 /*return*/, this.callServiceForDomain(domain, function (service) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (service instanceof Ens_1.default) {
throw new resolutionError_1.default(resolutionError_1.ResolutionErrorCode.UnsupportedMethod, {
methodName: 'multiChainAddr',
domain: domain,
method: service.name,
});
}
return [4 /*yield*/, service.record(domain, recordKey)];
case 1: return [2 /*return*/, _a.sent()];
}
});
}); })];
});
});
};
/**
* Resolves given domain name to a verified twitter handle
* @async
* @param domain - domain name to be resolved
* @throws [[ResolutionError]] if twitter is not found
* @returns A promise that resolves in a verified twitter handle
*/
Resolution.prototype.twitter = function (domain) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return [2 /*return*/, this.callServiceForDomain(domain, function (service) {
return service.twitter(domain);
})];
});
});
};
/**
* Resolve a chat id from the domain record
* @param domain - domain name to be resolved
* @throws [[ResolutionError]]
* @returns A promise that resolves in chatId
*/
Resolution.prototype.chatId = function (domain) {
return __awaiter(this, void 0, void 0, function () {
var err_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, this.record(domain, 'gundb.username.value')];
case 1: return [2 /*return*/, _a.sent()];
case 2:
err_1 = _a.sent();
if (err_1.code === resolutionError_1.ResolutionErrorCode.RecordNotFound) {
throw new resolutionError_1.default(resolutionError_1.ResolutionErrorCode.RecordNotFound, {
domain: domain,
method: err_1.method,
methodName: 'chatId',
recordName: err_1.recordName,
});
}
throw err_1;
case 3: return [2 /*return*/];
}
});
});
};
/**
* Resolve a gundb public key from the domain record
* @param domain - domain name to be resolved
* @throws [[ResolutionError]]
* @returns a promise that resolves in gundb public key
*/
Resolution.prototype.chatPk = function (domain) {
return __awaiter(this, void 0, void 0, function () {
var err_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, this.record(domain, 'gundb.public_key.value')];
case 1: return [2 /*return*/, _a.sent()];
case 2:
err_2 = _a.sent();
if (err_2.code === resolutionError_1.ResolutionErrorCode.RecordNotFound) {
throw new resolutionError_1.default(resolutionError_1.ResolutionErrorCode.RecordNotFound, {
domain: domain,
method: err_2.method,
methodName: 'chatId',
recordName: err_2.recordName,
});
}
throw err_2;
case 3: return [2 /*return*/];
}
});
});
};
/**
* Resolves the IPFS hash configured for domain records on ZNS
* @param domain - domain name
* @throws [[ResolutionError]]
*/
Resolution.prototype.ipfsHash = function (domain) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return [4 /*yield*/, this.callServiceForDomain(domain, function (service) { return __awaiter(_this, void 0, void 0, function () {
var contentHash;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(service instanceof Ens_1.default)) return [3 /*break*/, 2];
return [4 /*yield*/, service.record(domain, 'contenthash')];
case 1:
contentHash = _a.sent();
return [2 /*return*/, "ipfs://".concat(contentHash)];
case 2: return [4 /*yield*/, this.getPreferableNewRecord(domain, 'dweb.ipfs.hash', 'ipfs.html.value')];
case 3: return [2 /*return*/, _a.sent()];
}
});
}); })];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Resolves the httpUrl attached to domain
* @param domain - domain name
*/
Resolution.prototype.httpUrl = function (domain) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return [4 /*yield*/, this.callServiceForDomain(domain, function (service) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(service instanceof Ens_1.default)) return [3 /*break*/, 2];
return [4 /*yield*/, service.record(domain, 'url')];
case 1: return [2 /*return*/, _a.sent()];
case 2: return [4 /*yield*/, this.getPreferableNewRecord(domain, 'browser.redirect_url', 'ipfs.redirect_domain.value')];
case 3: return [2 /*return*/, _a.sent()];
}
});
}); })];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Resolves the ipfs email field from whois configurations
* @param domain - domain name
* @throws [[ResolutionError]]
* @returns A Promise that resolves in an email address configured for this domain whois
*/
Resolution.prototype.email = function (domain) {
return __awaiter(this, void 0, void 0, function () {
var key, serviceName, err_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
key = 'whois.email.value';
return [4 /*yield*/, (0, utils_1.findNamingServiceName)(domain)];
case 1:
serviceName = _a.sent();
if (serviceName === 'ENS') {
key = 'email';
}
_a.label = 2;
case 2:
_a.trys.push([2, 4, , 5]);
return [4 /*yield*/, this.record(domain, key)];
case 3: return [2 /*return*/, _a.sent()];
case 4:
err_3 = _a.sent();
throw new resolutionError_1.default(resolutionError_1.ResolutionErrorCode.RecordNotFound, {
domain: domain,
method: err_3.method,
methodName: 'email',
recordName: err_3.recordName,
});
case 5: return [2 /*return*/];
}
});
});
};
/**
* @returns the resolver address for a specific domain
* @param domain - domain to look for
*/
Resolution.prototype.resolver = function (domain) {
return __awaiter(this, void 0, void 0, function () {
var resolver;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return [4 /*yield*/, this.callServiceForDomain(domain, function (service) {
return service.resolver(domain);
})];
case 1:
resolver = _a.sent();
if (!resolver) {
throw new resolutionError_1.default(resolutionError_1.ResolutionErrorCode.UnspecifiedResolver, {
domain: domain,
});
}
return [2 /*return*/, resolver];
}
});
});
};
/**
* @param domain - domain name
* @returns An owner address of the domain
*/
Resolution.prototype.owner = function (domain) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return [2 /*return*/, this.callServiceForDomain(domain, function (service) {
return service.owner(domain);
})];
});
});
};
/**
* @param domain - domain name
* @param network - network name
* @param token - token ticker
* @returns An owner address of the domain
*/
Resolution.prototype.getAddress = function (domain, network, token) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return [2 /*return*/, this.callServiceForDomain(domain, function (service) {
return service.getAddress(domain, network, token);
})];
});
});
};
/**
* @param domain - domain name
* @param recordKey - a name of a record to be resolved
* @returns A record value promise for a given record name
*/
Resolution.prototype.record = function (domain, recordKey) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return [2 /*return*/, this.callServiceForDomain(domain, function (service) {
return service.record(domain, recordKey);
})];
});
});
};
/**
* @param domain domain name
* @param keys Array of record keys to be resolved
* @returns A Promise with key-value mapping of domain records
*/
Resolution.prototype.records = function (domain, keys) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return [2 /*return*/, this.callServiceForDomain(domain, function (service) {
return service.records(domain, keys);
})];
});
});
};
/**
* @param domain domain name
* @returns A Promise of whether or not the domain belongs to a wallet
*/
Resolution.prototype.isRegistered = function (domain) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return [2 /*return*/, this.callServiceForDomainBoolean(domain, function (service) { return service.isRegistered(domain); }, {
throwIfUnsupportedDomain: true,
expectedValue: true,
})];
});
});
};
/**
* @param domain domain name
* @returns A Promise of whether or not the domain is available
*/
Resolution.prototype.isAvailable = function (domain) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return [2 /*return*/, this.callServiceForDomainBoolean(domain, function (service) { return service.isAvailable(domain); }, {
throwIfUnsupportedDomain: true,
expectedValue: false,
})];
});
});
};
/**
* @returns Produces a namehash from supported naming service in hex format with 0x prefix.
* Corresponds to ERC721 token id in case of Ethereum based naming service like ENS or UNS.
* @param domain domain name to be converted
* @param namingService "UNS" or "ZNS" (uses keccak256 or sha256 algorithm respectively)
* @param options formatting options
* @throws [[ResolutionError]] with UnsupportedDomain error code if domain extension is unknown
*/
Resolution.prototype.namehash = function (domain, namingService, options) {
if (options === void 0) { options = publicTypes_1.NamehashOptionsDefault; }
var service = this.getService(namingService);
if (!service) {
throw new resolutionError_1.default(resolutionError_1.ResolutionErrorCode.UnsupportedService, {
namingService: namingService,
});
}
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return this.formatNamehash(service.native.namehash(domain), options);
};
/**
* @returns a namehash of a subdomain with name label
* @param parent namehash of a parent domain
* @param label subdomain name
* @param namingService "ENS", "UNS" or "ZNS" (uses keccak256 or sha256 algorithm respectively)
* @param options formatting options
*/
Resolution.prototype.childhash = function (parent, label, namingService, options) {
if (options === void 0) { options = publicTypes_1.NamehashOptionsDefault; }
try {
var service = this.getService(namingService);
return this.formatNamehash(service.native.childhash(parent, label), options);
}
catch (error) {
if (error instanceof configurationError_1.default &&
error.code === configurationError_2.ConfigurationErrorCode.NetworkConfigMissing) {
throw new resolutionError_1.default(resolutionError_1.ResolutionErrorCode.UnsupportedService, {
namingService: namingService,
});
}
throw error;
}
};
Resolution.prototype.formatNamehash = function (hash, options) {
hash = hash.replace('0x', '');
if (options.format === 'dec') {
return new bn_js_1.default(hash, 'hex').toString(10);
}
else {
return options.prefix ? '0x' + hash : hash;
}
};
/**
* Checks weather the domain name matches the hash
* @param domain - domain name to check against
* @param hash - hash obtained from the blockchain
* @param namingService - "UNS" or "ZNS" (uses keccak256 or sha256 algorithm respectively)
*/
Resolution.prototype.isValidHash = function (domain, hash, namingService) {
var service = this.getService(namingService);
if (!service) {
throw new resolutionError_1.default(resolutionError_1.ResolutionErrorCode.UnsupportedService, {
namingService: namingService,
});
}
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return service.native.namehash(domain) === hash;
};
/**
* Checks if the domain name is valid according to naming service rules
* for valid domain names.
* Example: ENS doesn't allow domains that start from '-' symbol.
* @param domain - domain name to be checked
*/
Resolution.prototype.isSupportedDomain = function (domain) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return [2 /*return*/, this.callServiceForDomainBoolean(domain, function (service) { return service.isSupportedDomain(domain); }, {
throwIfUnsupportedDomain: false,
expectedValue: true,
})];
});
});
};
/**
* Returns all record keys of the domain.
* This method is strongly unrecommended for production use due to lack of support for many ethereum service providers and low performance
* Method is not supported by ENS
* @param domain - domain name
* @deprecated
*/
Resolution.prototype.allRecords = function (domain) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
return [2 /*return*/, this.callServiceForDomain(domain, function (service) {
return service.allRecords(domain);
})];
});
});
};
Resolution.prototype.dns = function (domain, types) {
return __awaiter(this, void 0, void 0, function () {
var dnsUtils, dnsRecordKeys, blockchainData;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
dnsUtils = new DnsUtils_1.default();
domain = (0, prepareAndValidate_1.prepareAndValidateDomain)(domain);
dnsRecordKeys = this.getDnsRecordKeys(types);
return [4 /*yield*/, this.callServiceForDomain(domain, function (service) {
return service.records(domain, dnsRecordKeys);
})];
case 1:
blockchainData = _a.sent();
return [2 /*return*/, dnsUtils.toList(blockchainData)];
}
});
});
};
/**
* Retrieves the tokenURI from the registry smart contract.
* @returns the ERC721Metadata#tokenURI contract method result
* @param domain - domain name
*/
Resolution.prototype.tokenURI = function (domain) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
// The `getTokenUri` method isn't supported in ZNS (it'll throw in the next call)
return [2 /*return*/, this.callServiceForDomain(domain, function (service) {
if (service.name === publicTypes_1.NamingServiceName.UNS) {
var namehash_2 = _this.namehash(domain, publicTypes_1.NamingServiceName.UNS);
return service.getTokenUri(namehash_2);
}
else if (service.name === publicTypes_1.NamingServiceName.ENS) {
return service.getTokenUri(domain);
}
var namehash = _this.namehash(domain, publicTypes_1.NamingServiceName.ZNS);
return service.getTokenUri(namehash);
})];
});
});
};
/**
* Retrieves the data from the endpoint provided by tokenURI from the registry smart contract.
* @returns the JSON response of the token URI endpoint
* @param domain - domain name
*/
Resolution.prototype.tokenURIMetadata = function (domain) {
return __awaiter(this, void 0, void 0, function () {
var tokenUri;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.tokenURI(domain)];
case 1:
tokenUri = _a.sent();
return [2 /*return*/, this.getMetadataFromTokenURI(tokenUri)];
}
});
});
};
/**
* Retrieves address of registry contract used for domain
* @param domain - domain name
* @returns Registry contract address
*/
Resolution.prototype.registryAddress = function (domain) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this.callServiceForDomain(domain, function (service) {
return service.registryAddress(domain);
})];
});
});
};
/**
* Retrieves the domain name from tokenId by parsing registry smart contract event logs.
* @throws {ResolutionError} if returned domain name doesn't match the original namehash.
* @returns the domain name retrieved from token metadata.
* @param hash - domain name hash or label hash.
* @param service - name service which is used for lookup.
*/
Resolution.prototype.unhash = function (hash, service) {
return __awaiter(this, void 0, void 0, function () {
var services, method;
return __generator(this, function (_a) {
hash = (0, namehash_1.fromDecStringToHex)(hash);
services = this.getService(service).usedServices;
method = services[services.length - 1];
return [2 /*return*/, method.getDomainFromTokenId(hash)];
});
});
};
/**
* Retrieves address of registry contract used for domain
* @param domains - domain name
* @returns Promise<Locations> - A map of domain name and Location (a set of attributes like blockchain,
*/
Resolution.prototype.locations = function (domains) {
return __awaiter(this, void 0, void 0, function () {
var zilDomains, ensDomains, nonEnsDomains, unsPromise, unsLocations, znsServices, znsService_1, znsPromise, emptyZilEntries, znsLocations, _i, emptyZilEntries_1, domain, ensLocations, ensDomain;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
zilDomains = domains.filter(function (domain) { return domain.endsWith('.zil'); });
ensDomains = domains.filter(function (domain) {
return domain.match(/^([^\s\\.]+\.)+(eth)+$/);
});
nonEnsDomains = domains.filter(function (domain) { return !domain.match(/^([^\s\\.]+\.)+(eth)+$/); });
unsPromise = this.getService(publicTypes_1.NamingServiceName.UNS).usedServices[0].locations(nonEnsDomains);
return [4 /*yield*/, unsPromise];
case 1:
unsLocations = _a.sent();
if (!zilDomains.length) return [3 /*break*/, 3];
znsServices = this.getService(publicTypes_1.NamingServiceName.ZNS).usedServices;
znsService_1 = znsServices[znsServices.length - 1];
znsPromise = (0, utils_1.wrapResult)(function () { return znsService_1.locations(zilDomains); });
emptyZilEntries = Object.entries(unsLocations).filter(function (_a) {
var domain = _a[0], location = _a[1];
return domain.endsWith('.zil') && !location;
});
return [4 /*yield*/, znsPromise.then(utils_1.unwrapResult)];
case 2:
znsLocations = _a.sent();
for (_i = 0, emptyZilEntries_1 = emptyZilEntries; _i < emptyZilEntries_1.length; _i++) {
domain = emptyZilEntries_1[_i][0];
unsLocations[domain] = znsLocations[domain];
}
_a.label = 3;
case 3:
if (!ensDomains.length) return [3 /*break*/, 5];
return [4 /*yield*/, this.getService(publicTypes_1.NamingServiceName.ENS).usedServices[0].locations(ensDomains)];
case 4:
ensLocations = _a.sent();
for (ensDomain in ensLocations) {
unsLocations[ensDomain] = ensLocations[ensDomain];
}
_a.label = 5;
case 5: return [2 /*return*/, unsLocations];
}
});