@ensdomains/ensjs 3.0.0-alpha.1 → 3.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/cjs/functions/burnFuses.d.ts +1 -2
- package/dist/cjs/functions/burnFuses.js +3 -3
- package/dist/cjs/functions/createSubname.js +2 -1
- package/dist/cjs/functions/getDNSOwner.d.ts +7 -0
- package/dist/cjs/functions/getDNSOwner.js +81 -0
- package/dist/cjs/functions/getFuses.js +3 -2
- package/dist/cjs/functions/getOwner.js +7 -6
- package/dist/cjs/functions/getProfile.d.ts +1 -1
- package/dist/cjs/functions/getProfile.js +49 -15
- package/dist/cjs/functions/getSpecificRecord.js +22 -5
- package/dist/cjs/functions/getSubnames.js +6 -6
- package/dist/cjs/functions/setRecords.d.ts +1 -2
- package/dist/cjs/functions/setRecords.js +3 -3
- package/dist/cjs/functions/setResolver.d.ts +1 -2
- package/dist/cjs/functions/setResolver.js +3 -3
- package/dist/cjs/functions/transferName.js +3 -2
- package/dist/cjs/functions/transferSubname.js +2 -1
- package/dist/cjs/functions/unwrapName.js +2 -1
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/utils/makeHashIndexes.js +2 -2
- package/dist/cjs/utils/normalise.d.ts +1 -0
- package/dist/cjs/utils/normalise.js +20 -1
- package/dist/cjs/utils/registerHelpers.js +3 -4
- package/dist/esm/functions/burnFuses.d.ts +1 -2
- package/dist/esm/functions/burnFuses.js +3 -3
- package/dist/esm/functions/createSubname.js +2 -1
- package/dist/esm/functions/getDNSOwner.d.ts +7 -0
- package/dist/esm/functions/getDNSOwner.js +51 -0
- package/dist/esm/functions/getFuses.js +4 -3
- package/dist/esm/functions/getOwner.js +7 -6
- package/dist/esm/functions/getProfile.d.ts +1 -1
- package/dist/esm/functions/getProfile.js +49 -15
- package/dist/esm/functions/getSpecificRecord.js +22 -5
- package/dist/esm/functions/getSubnames.js +3 -3
- package/dist/esm/functions/setRecords.d.ts +1 -2
- package/dist/esm/functions/setRecords.js +3 -3
- package/dist/esm/functions/setResolver.d.ts +1 -2
- package/dist/esm/functions/setResolver.js +3 -3
- package/dist/esm/functions/transferName.js +3 -2
- package/dist/esm/functions/transferSubname.js +2 -1
- package/dist/esm/functions/unwrapName.js +2 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/utils/makeHashIndexes.js +2 -2
- package/dist/esm/utils/normalise.d.ts +1 -0
- package/dist/esm/utils/normalise.js +18 -0
- package/dist/esm/utils/registerHelpers.js +3 -4
- package/package.json +11 -5
- package/src/@types/dns-packet/index.d.ts +114 -0
- package/src/{tests → functions}/batch.test.ts +1 -1
- package/src/{tests → functions}/batchWrappers.test.ts +1 -1
- package/src/{tests → functions}/burnFuses.test.ts +4 -3
- package/src/functions/burnFuses.ts +3 -3
- package/src/{tests → functions}/createSubname.test.ts +5 -6
- package/src/functions/createSubname.ts +2 -1
- package/src/{tests → functions}/deleteSubname.test.ts +5 -6
- package/src/functions/getDNSOwner.test.ts +122 -0
- package/src/functions/getDNSOwner.ts +61 -0
- package/src/{tests → functions}/getExpiry.test.ts +1 -1
- package/src/{tests → functions}/getFuses.test.ts +1 -1
- package/src/functions/getFuses.ts +4 -3
- package/src/{tests → functions}/getHistory.test.ts +1 -1
- package/src/{tests → functions}/getName.test.ts +1 -1
- package/src/{tests → functions}/getNames.test.ts +1 -1
- package/src/{tests → functions}/getOwner.test.ts +11 -1
- package/src/functions/getOwner.ts +7 -7
- package/src/{tests → functions}/getProfile.test.ts +29 -11
- package/src/functions/getProfile.ts +77 -13
- package/src/{tests → functions}/getResolver.test.ts +1 -1
- package/src/{tests → functions}/getSpecificRecord.test.ts +1 -1
- package/src/functions/getSpecificRecord.ts +28 -8
- package/src/{tests → functions}/getSubnames.test.ts +1 -1
- package/src/functions/getSubnames.ts +68 -66
- package/src/{tests → functions}/makeCommitment.test.ts +1 -1
- package/src/functions/normalise.test.ts +22 -0
- package/src/{tests → functions}/setName.test.ts +1 -1
- package/src/{tests → functions}/setRecords.test.ts +4 -4
- package/src/functions/setRecords.ts +3 -3
- package/src/{tests → functions}/setResolver.test.ts +1 -1
- package/src/functions/setResolver.ts +3 -3
- package/src/{tests → functions}/transferName.test.ts +4 -3
- package/src/functions/transferName.ts +3 -2
- package/src/{tests → functions}/transferSubname.test.ts +5 -6
- package/src/functions/transferSubname.ts +2 -1
- package/src/{tests → functions}/unwrapName.test.ts +3 -2
- package/src/functions/unwrapName.ts +2 -1
- package/src/{tests → functions}/wrapName.test.ts +5 -8
- package/src/index.ts +7 -0
- package/src/tests/withProvider.test.ts +1 -1
- package/src/utils/makeHashIndexes.ts +4 -4
- package/src/utils/normalise.ts +23 -0
- package/src/utils/registerHelpers.ts +3 -4
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.makeNamehashIndexes = exports.makeOtherIndexes = void 0;
|
|
4
|
-
const
|
|
4
|
+
const normalise_1 = require("./normalise");
|
|
5
5
|
const makeOtherIndexes = (data, findStr) => Array.from(data.matchAll(findStr)).map((x) => x.index / 2 - 1);
|
|
6
6
|
exports.makeOtherIndexes = makeOtherIndexes;
|
|
7
|
-
const makeNamehashIndexes = (data, name) => Array.from(data.matchAll(
|
|
7
|
+
const makeNamehashIndexes = (data, name) => Array.from(data.matchAll((0, normalise_1.namehash)(name).substring(2))).map((x) => x.index / 2 - 1);
|
|
8
8
|
exports.makeNamehashIndexes = makeNamehashIndexes;
|
|
@@ -3,7 +3,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.normalise = void 0;
|
|
6
|
+
exports.namehash = exports.normalise = void 0;
|
|
7
|
+
const utils_1 = require("ethers/lib/utils");
|
|
7
8
|
const uts46bundle_js_1 = __importDefault(require("idna-uts46-hx/uts46bundle.js"));
|
|
9
|
+
const zeros = new Uint8Array(32);
|
|
10
|
+
zeros.fill(0);
|
|
8
11
|
const normalise = (name) => name ? uts46bundle_js_1.default.toUnicode(name, { useStd3ASCII: true }) : name;
|
|
9
12
|
exports.normalise = normalise;
|
|
13
|
+
const namehash = (inputName) => {
|
|
14
|
+
let result = zeros;
|
|
15
|
+
const name = (0, exports.normalise)(inputName);
|
|
16
|
+
if (name) {
|
|
17
|
+
const labels = name.split('.');
|
|
18
|
+
for (var i = labels.length - 1; i >= 0; i--) {
|
|
19
|
+
const labelSha = (0, utils_1.keccak256)((0, utils_1.toUtf8Bytes)(labels[i]));
|
|
20
|
+
result = (0, utils_1.keccak256)((0, utils_1.concat)([result, labelSha]));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
result = (0, utils_1.hexlify)(zeros);
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
28
|
+
exports.namehash = namehash;
|
|
@@ -7,6 +7,7 @@ exports._makeCommitment = exports.makeCommitment = exports.randomSecret = void 0
|
|
|
7
7
|
const ethers_1 = require("ethers");
|
|
8
8
|
const generateFuseInput_1 = __importDefault(require("./generateFuseInput"));
|
|
9
9
|
const labels_1 = require("./labels");
|
|
10
|
+
const normalise_1 = require("./normalise");
|
|
10
11
|
const recordHelpers_1 = require("./recordHelpers");
|
|
11
12
|
const randomSecret = () => {
|
|
12
13
|
const bytes = Buffer.allocUnsafe(32);
|
|
@@ -15,11 +16,9 @@ const randomSecret = () => {
|
|
|
15
16
|
exports.randomSecret = randomSecret;
|
|
16
17
|
const makeCommitment = ({ name, owner, duration, resolver, records, reverseRecord, fuses, }) => {
|
|
17
18
|
const label = (0, labels_1.labelhash)(name.split('.')[0]);
|
|
18
|
-
const
|
|
19
|
+
const hash = (0, normalise_1.namehash)(name);
|
|
19
20
|
const resolverAddress = resolver.address;
|
|
20
|
-
const data = records
|
|
21
|
-
? (0, recordHelpers_1.generateRecordCallArray)(namehash, records, resolver)
|
|
22
|
-
: [];
|
|
21
|
+
const data = records ? (0, recordHelpers_1.generateRecordCallArray)(hash, records, resolver) : [];
|
|
23
22
|
const secret = (0, exports.randomSecret)();
|
|
24
23
|
const fuseData = fuses ? (0, generateFuseInput_1.default)(fuses) : '0';
|
|
25
24
|
const commitment = (0, exports._makeCommitment)({
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ethers } from 'ethers';
|
|
2
1
|
import { ENSArgs } from '..';
|
|
3
2
|
import { FuseOptions } from '../@types/FuseOptions';
|
|
4
|
-
export default function ({ contracts, provider }: ENSArgs<'contracts' | 'provider'>, name: string, fusesToBurn: FuseOptions): Promise<ethers.ContractTransaction>;
|
|
3
|
+
export default function ({ contracts, provider }: ENSArgs<'contracts' | 'provider'>, name: string, fusesToBurn: FuseOptions): Promise<import("ethers").ContractTransaction>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { ethers } from 'ethers';
|
|
2
1
|
import generateFuseInput from '../utils/generateFuseInput';
|
|
2
|
+
import { namehash } from '../utils/normalise';
|
|
3
3
|
export default async function ({ contracts, provider }, name, fusesToBurn) {
|
|
4
4
|
const signer = provider?.getSigner();
|
|
5
5
|
if (!signer) {
|
|
6
6
|
throw new Error('No signer found');
|
|
7
7
|
}
|
|
8
8
|
const nameWrapper = (await contracts?.getNameWrapper()).connect(signer);
|
|
9
|
-
const
|
|
9
|
+
const hash = namehash(name);
|
|
10
10
|
const encodedFuses = generateFuseInput(fusesToBurn);
|
|
11
|
-
return nameWrapper.burnFuses(
|
|
11
|
+
return nameWrapper.burnFuses(hash, encodedFuses);
|
|
12
12
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ethers } from 'ethers';
|
|
2
2
|
import generateFuseInput from '../utils/generateFuseInput';
|
|
3
|
+
import { namehash } from '../utils/normalise';
|
|
3
4
|
export default async function ({ contracts, provider }, { name, owner, resolverAddress, contract, options, ...wrapperArgs }) {
|
|
4
5
|
const signer = provider?.getSigner(options?.addressOrIndex);
|
|
5
6
|
if (!signer) {
|
|
@@ -17,7 +18,7 @@ export default async function ({ contracts, provider }, { name, owner, resolverA
|
|
|
17
18
|
}
|
|
18
19
|
const label = labels.shift();
|
|
19
20
|
const labelhash = ethers.utils.solidityKeccak256(['string'], [label]);
|
|
20
|
-
const parentNodehash =
|
|
21
|
+
const parentNodehash = namehash(labels.join('.'));
|
|
21
22
|
switch (contract) {
|
|
22
23
|
case 'registry': {
|
|
23
24
|
const registry = (await contracts?.getRegistry()).connect(signer);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as packet from 'dns-packet';
|
|
2
|
+
export declare function encodeURLParams(p: {
|
|
3
|
+
[key: string]: string;
|
|
4
|
+
}): string;
|
|
5
|
+
export declare const getDNS: (q: packet.Packet) => Promise<packet.Packet>;
|
|
6
|
+
export declare const dnsQuery: (qtype: string, qname: string) => Promise<packet.Packet>;
|
|
7
|
+
export default function (_: any, dnsName: string): Promise<any>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as packet from 'dns-packet';
|
|
2
|
+
export function encodeURLParams(p) {
|
|
3
|
+
return Object.entries(p)
|
|
4
|
+
.map((kv) => kv.map(encodeURIComponent).join('='))
|
|
5
|
+
.join('&');
|
|
6
|
+
}
|
|
7
|
+
export const getDNS = async (q) => {
|
|
8
|
+
const response = await global.fetch(`https://cloudflare-dns.com/dns-query?${encodeURLParams({
|
|
9
|
+
ct: 'application/dns-udpwireformat',
|
|
10
|
+
dns: packet.encode(q)?.toString('base64'),
|
|
11
|
+
ts: Date.now().toString(),
|
|
12
|
+
})}`);
|
|
13
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
14
|
+
// @ts-ignore:next-line
|
|
15
|
+
const fromArrayBuffer = Buffer.from(arrayBuffer);
|
|
16
|
+
return packet.decode(fromArrayBuffer);
|
|
17
|
+
};
|
|
18
|
+
export const dnsQuery = async (qtype, qname) => {
|
|
19
|
+
const query = {
|
|
20
|
+
type: 'query',
|
|
21
|
+
id: 1,
|
|
22
|
+
flags: packet.RECURSION_DESIRED,
|
|
23
|
+
questions: [
|
|
24
|
+
{
|
|
25
|
+
type: qtype,
|
|
26
|
+
class: 'IN',
|
|
27
|
+
name: qname,
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
additionals: [
|
|
31
|
+
{
|
|
32
|
+
type: 'OPT',
|
|
33
|
+
class: 'IN',
|
|
34
|
+
name: '.',
|
|
35
|
+
udpPayloadSize: 4096,
|
|
36
|
+
flags: packet.DNSSEC_OK,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
answers: [],
|
|
40
|
+
};
|
|
41
|
+
const response = await getDNS(query);
|
|
42
|
+
if (response.rcode !== 'NOERROR') {
|
|
43
|
+
throw new Error(`DNS query failed: ${response.rcode}`);
|
|
44
|
+
}
|
|
45
|
+
return response;
|
|
46
|
+
};
|
|
47
|
+
export default async function (_, dnsName) {
|
|
48
|
+
const result = await dnsQuery('TXT', `_ens.${dnsName}`);
|
|
49
|
+
const address = result?.answers?.[0]?.data?.[0]?.toString()?.split('=')?.[1];
|
|
50
|
+
return address;
|
|
51
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { utils } from 'ethers';
|
|
2
2
|
import { testable as fuseEnums } from '../utils/fuses';
|
|
3
|
+
import { namehash } from '../utils/normalise';
|
|
3
4
|
const NameSafety = [
|
|
4
5
|
'Safe',
|
|
5
6
|
'RegistrantNotWrapped',
|
|
@@ -12,7 +13,7 @@ const raw = async ({ contracts }, name) => {
|
|
|
12
13
|
return {
|
|
13
14
|
to: nameWrapper.address,
|
|
14
15
|
data: nameWrapper.interface.encodeFunctionData('getFuses', [
|
|
15
|
-
|
|
16
|
+
namehash(name),
|
|
16
17
|
]),
|
|
17
18
|
};
|
|
18
19
|
};
|
|
@@ -36,7 +37,7 @@ const decode = async ({ contracts }, data, name) => {
|
|
|
36
37
|
if (utils.hexStripZeros(vulnerableNode) !== '0x') {
|
|
37
38
|
name.split('.').forEach((label, index, arr) => {
|
|
38
39
|
const node = arr.slice(index).join('.');
|
|
39
|
-
const nodehash =
|
|
40
|
+
const nodehash = namehash(node);
|
|
40
41
|
if (nodehash === vulnerableNode) {
|
|
41
42
|
returnVulnerableNode = node;
|
|
42
43
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ethers } from 'ethers';
|
|
2
2
|
import { labelhash } from '../utils/labels';
|
|
3
|
+
import { namehash as makeNamehash } from '../utils/normalise';
|
|
3
4
|
const singleContractOwnerRaw = async ({ contracts }, contract, namehash, labels) => {
|
|
4
5
|
switch (contract) {
|
|
5
6
|
case 'nameWrapper': {
|
|
@@ -28,10 +29,10 @@ const singleContractOwnerRaw = async ({ contracts }, contract, namehash, labels)
|
|
|
28
29
|
}
|
|
29
30
|
};
|
|
30
31
|
const raw = async ({ contracts, multicallWrapper }, name, contract) => {
|
|
31
|
-
const namehash =
|
|
32
|
+
const namehash = makeNamehash(name);
|
|
32
33
|
const labels = name.split('.');
|
|
33
|
-
if (contract) {
|
|
34
|
-
return await singleContractOwnerRaw({ contracts }, contract, namehash, labels);
|
|
34
|
+
if (contract || labels.length === 1) {
|
|
35
|
+
return await singleContractOwnerRaw({ contracts }, contract || 'registry', namehash, labels);
|
|
35
36
|
}
|
|
36
37
|
const registryData = await singleContractOwnerRaw({ contracts }, 'registry', namehash, labels);
|
|
37
38
|
const nameWrapperData = await singleContractOwnerRaw({ contracts }, 'nameWrapper', namehash, labels);
|
|
@@ -46,10 +47,11 @@ const singleContractOwnerDecode = (data) => ethers.utils.defaultAbiCoder.decode(
|
|
|
46
47
|
const decode = async ({ contracts, multicallWrapper }, data, name, contract) => {
|
|
47
48
|
if (data === null)
|
|
48
49
|
return;
|
|
49
|
-
|
|
50
|
+
const labels = name.split('.');
|
|
51
|
+
if (contract || labels.length === 1) {
|
|
50
52
|
const singleOwner = singleContractOwnerDecode(data);
|
|
51
53
|
let obj = {
|
|
52
|
-
ownershipLevel: contract,
|
|
54
|
+
ownershipLevel: contract || 'registry',
|
|
53
55
|
};
|
|
54
56
|
if (contract === 'registrar') {
|
|
55
57
|
return {
|
|
@@ -74,7 +76,6 @@ const decode = async ({ contracts, multicallWrapper }, data, name, contract) =>
|
|
|
74
76
|
const registryOwner = decodedData[0][0];
|
|
75
77
|
const nameWrapperOwner = decodedData[1][0];
|
|
76
78
|
const registrarOwner = decodedData[2]?.[0];
|
|
77
|
-
const labels = name.split('.');
|
|
78
79
|
// check for only .eth names
|
|
79
80
|
if (labels[labels.length - 1] === 'eth') {
|
|
80
81
|
// if the owner on the registrar is the namewrapper, then the namewrapper owner is the owner
|
|
@@ -26,5 +26,5 @@ declare type ProfileOptions = {
|
|
|
26
26
|
texts?: boolean | string[];
|
|
27
27
|
coinTypes?: boolean | string[];
|
|
28
28
|
};
|
|
29
|
-
export default function ({ contracts, gqlInstance, getName, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, }: ENSArgs<'contracts' | 'gqlInstance' | 'getName' | '_getText' | '_getAddr' | '_getContentHash' | 'resolverMulticallWrapper'>, nameOrAddress: string, options?: ProfileOptions): Promise<ResolvedProfile | undefined>;
|
|
29
|
+
export default function ({ contracts, gqlInstance, getName, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, multicallWrapper, }: ENSArgs<'contracts' | 'gqlInstance' | 'getName' | '_getText' | '_getAddr' | '_getContentHash' | 'resolverMulticallWrapper' | 'multicallWrapper'>, nameOrAddress: string, options?: ProfileOptions): Promise<ResolvedProfile | undefined>;
|
|
30
30
|
export {};
|
|
@@ -40,23 +40,39 @@ const makeMulticallData = async ({ _getAddr, _getContentHash, _getText, resolver
|
|
|
40
40
|
const prRawData = await resolverMulticallWrapper.raw(calls.map((x) => x.data));
|
|
41
41
|
return { data: prRawData.data, calls };
|
|
42
42
|
};
|
|
43
|
-
const
|
|
44
|
-
const
|
|
43
|
+
const fetchWithoutResolverMulticall = async ({ multicallWrapper }, calls, resolverAddress) => {
|
|
44
|
+
const callsWithResolver = calls.map((call) => ({
|
|
45
|
+
to: resolverAddress,
|
|
46
|
+
data: call.data.data,
|
|
47
|
+
}));
|
|
48
|
+
return (await multicallWrapper(callsWithResolver)).map((x) => x[1]);
|
|
49
|
+
};
|
|
50
|
+
const getDataForName = async ({ contracts, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, multicallWrapper, }, name, options, fallbackResolver) => {
|
|
45
51
|
const universalResolver = await contracts?.getUniversalResolver();
|
|
46
52
|
const { data, calls } = await makeMulticallData({ _getAddr, _getContentHash, _getText, resolverMulticallWrapper }, name, options);
|
|
47
|
-
let
|
|
53
|
+
let resolvedData;
|
|
54
|
+
let useFallbackResolver = false;
|
|
48
55
|
try {
|
|
49
|
-
|
|
56
|
+
resolvedData = await universalResolver?.resolve(hexEncodeName(name), data);
|
|
50
57
|
}
|
|
51
58
|
catch {
|
|
52
|
-
|
|
59
|
+
useFallbackResolver = true;
|
|
60
|
+
}
|
|
61
|
+
let resolverAddress;
|
|
62
|
+
let recordData;
|
|
63
|
+
if (useFallbackResolver) {
|
|
64
|
+
resolverAddress = fallbackResolver;
|
|
65
|
+
recordData = await fetchWithoutResolverMulticall({ multicallWrapper }, calls, resolverAddress);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
resolverAddress = resolvedData['1'];
|
|
69
|
+
[recordData] = await resolverMulticallWrapper.decode(resolvedData['0']);
|
|
53
70
|
}
|
|
54
|
-
const [recordData] = await resolverMulticallWrapper.decode(resolver['0']);
|
|
55
71
|
const matchAddress = recordData[calls.findIndex((x) => x.key === '60')];
|
|
56
72
|
return {
|
|
57
73
|
address: matchAddress && (await _getAddr.decode(matchAddress)),
|
|
58
74
|
records: await formatRecords({ _getAddr, _getContentHash, _getText }, recordData, calls, options),
|
|
59
|
-
resolverAddress
|
|
75
|
+
resolverAddress,
|
|
60
76
|
};
|
|
61
77
|
};
|
|
62
78
|
const formatRecords = async ({ _getText, _getAddr, _getContentHash, }, data, calls, options) => {
|
|
@@ -66,7 +82,7 @@ const formatRecords = async ({ _getText, _getAddr, _getContentHash, }, data, cal
|
|
|
66
82
|
key: calls[i].key,
|
|
67
83
|
type: calls[i].type,
|
|
68
84
|
};
|
|
69
|
-
if (itemRet.type === '
|
|
85
|
+
if (itemRet.type === 'contenthash') {
|
|
70
86
|
decodedFromAbi = ethers.utils.defaultAbiCoder.decode(['bytes'], item)[0];
|
|
71
87
|
if (ethers.utils.hexStripZeros(decodedFromAbi) === '0x') {
|
|
72
88
|
return;
|
|
@@ -155,6 +171,7 @@ const graphFetch = async ({ gqlInstance }, name, wantedRecords) => {
|
|
|
155
171
|
addr {
|
|
156
172
|
id
|
|
157
173
|
}
|
|
174
|
+
address
|
|
158
175
|
}
|
|
159
176
|
}
|
|
160
177
|
}
|
|
@@ -165,8 +182,14 @@ const graphFetch = async ({ gqlInstance }, name, wantedRecords) => {
|
|
|
165
182
|
return;
|
|
166
183
|
const [{ resolver: resolverResponse, isMigrated, createdAt }] = domains;
|
|
167
184
|
let returnedRecords = {};
|
|
168
|
-
if (!
|
|
185
|
+
if (!resolverResponse)
|
|
169
186
|
return { isMigrated, createdAt };
|
|
187
|
+
if (!wantedRecords)
|
|
188
|
+
return {
|
|
189
|
+
isMigrated,
|
|
190
|
+
createdAt,
|
|
191
|
+
graphResolverAddress: resolverResponse.address,
|
|
192
|
+
};
|
|
170
193
|
Object.keys(wantedRecords).forEach((key) => {
|
|
171
194
|
const data = wantedRecords[key];
|
|
172
195
|
if (typeof data === 'boolean' && data) {
|
|
@@ -178,28 +201,36 @@ const graphFetch = async ({ gqlInstance }, name, wantedRecords) => {
|
|
|
178
201
|
}
|
|
179
202
|
}
|
|
180
203
|
});
|
|
181
|
-
return {
|
|
204
|
+
return {
|
|
205
|
+
...returnedRecords,
|
|
206
|
+
isMigrated,
|
|
207
|
+
createdAt,
|
|
208
|
+
graphResolverAddress: resolverResponse.address,
|
|
209
|
+
};
|
|
182
210
|
};
|
|
183
|
-
const getProfileFromName = async ({ contracts, gqlInstance, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, }, name, options) => {
|
|
211
|
+
const getProfileFromName = async ({ contracts, gqlInstance, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, multicallWrapper, }, name, options) => {
|
|
184
212
|
const usingOptions = !options || options?.texts === true || options?.coinTypes === true
|
|
185
213
|
? options || { contentHash: true, texts: true, coinTypes: true }
|
|
186
214
|
: undefined;
|
|
187
215
|
const graphResult = await graphFetch({ gqlInstance }, name, usingOptions);
|
|
188
216
|
if (!graphResult)
|
|
189
217
|
return;
|
|
190
|
-
const { isMigrated, createdAt, ...wantedRecords } = graphResult;
|
|
218
|
+
const { isMigrated, createdAt, graphResolverAddress, ...wantedRecords } = graphResult;
|
|
219
|
+
if (!graphResolverAddress)
|
|
220
|
+
return { isMigrated, createdAt, message: "Name doesn't have a resolver" };
|
|
191
221
|
const result = await getDataForName({
|
|
192
222
|
contracts,
|
|
193
223
|
_getAddr,
|
|
194
224
|
_getContentHash,
|
|
195
225
|
_getText,
|
|
196
226
|
resolverMulticallWrapper,
|
|
197
|
-
|
|
227
|
+
multicallWrapper,
|
|
228
|
+
}, name, usingOptions ? wantedRecords : options, graphResolverAddress);
|
|
198
229
|
if (!result)
|
|
199
230
|
return { isMigrated, createdAt, message: "Records fetch didn't complete" };
|
|
200
231
|
return { ...result, isMigrated, createdAt, message: undefined };
|
|
201
232
|
};
|
|
202
|
-
const getProfileFromAddress = async ({ contracts, gqlInstance, getName, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, }, address, options) => {
|
|
233
|
+
const getProfileFromAddress = async ({ contracts, gqlInstance, getName, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, multicallWrapper, }, address, options) => {
|
|
203
234
|
let name;
|
|
204
235
|
try {
|
|
205
236
|
name = await getName(address);
|
|
@@ -218,6 +249,7 @@ const getProfileFromAddress = async ({ contracts, gqlInstance, getName, _getAddr
|
|
|
218
249
|
_getContentHash,
|
|
219
250
|
_getText,
|
|
220
251
|
resolverMulticallWrapper,
|
|
252
|
+
multicallWrapper,
|
|
221
253
|
}, name.name, options);
|
|
222
254
|
if (!result || result.message)
|
|
223
255
|
return;
|
|
@@ -228,7 +260,7 @@ const getProfileFromAddress = async ({ contracts, gqlInstance, getName, _getAddr
|
|
|
228
260
|
message: undefined,
|
|
229
261
|
};
|
|
230
262
|
};
|
|
231
|
-
export default async function ({ contracts, gqlInstance, getName, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, }, nameOrAddress, options) {
|
|
263
|
+
export default async function ({ contracts, gqlInstance, getName, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, multicallWrapper, }, nameOrAddress, options) {
|
|
232
264
|
if (options && options.coinTypes && typeof options.coinTypes !== 'boolean') {
|
|
233
265
|
options.coinTypes = options.coinTypes.map((coin) => {
|
|
234
266
|
if (!isNaN(parseInt(coin))) {
|
|
@@ -252,6 +284,7 @@ export default async function ({ contracts, gqlInstance, getName, _getAddr, _get
|
|
|
252
284
|
_getContentHash,
|
|
253
285
|
_getText,
|
|
254
286
|
resolverMulticallWrapper,
|
|
287
|
+
multicallWrapper,
|
|
255
288
|
}, nameOrAddress, options);
|
|
256
289
|
}
|
|
257
290
|
return getProfileFromName({
|
|
@@ -261,5 +294,6 @@ export default async function ({ contracts, gqlInstance, getName, _getAddr, _get
|
|
|
261
294
|
_getContentHash,
|
|
262
295
|
_getText,
|
|
263
296
|
resolverMulticallWrapper,
|
|
297
|
+
multicallWrapper,
|
|
264
298
|
}, nameOrAddress, options);
|
|
265
299
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { formatsByCoinType, formatsByName } from '@ensdomains/address-encoder';
|
|
2
2
|
import { ethers } from 'ethers';
|
|
3
3
|
import { decodeContenthash } from '../utils/contentHash';
|
|
4
|
+
import { namehash } from '../utils/normalise';
|
|
4
5
|
export const _getContentHash = {
|
|
5
6
|
raw: async ({ contracts }, name) => {
|
|
6
7
|
const publicResolver = await contracts?.getPublicResolver();
|
|
7
8
|
return {
|
|
8
9
|
to: '0x0000000000000000000000000000000000000000',
|
|
9
10
|
data: publicResolver.interface.encodeFunctionData('contenthash', [
|
|
10
|
-
|
|
11
|
+
namehash(name),
|
|
11
12
|
]),
|
|
12
13
|
};
|
|
13
14
|
},
|
|
@@ -45,7 +46,7 @@ export const _getText = {
|
|
|
45
46
|
return {
|
|
46
47
|
to: '0x0000000000000000000000000000000000000000',
|
|
47
48
|
data: publicResolver.interface.encodeFunctionData('text', [
|
|
48
|
-
|
|
49
|
+
namehash(name),
|
|
49
50
|
key,
|
|
50
51
|
]),
|
|
51
52
|
};
|
|
@@ -77,10 +78,18 @@ export const _getAddr = {
|
|
|
77
78
|
coinType = 60;
|
|
78
79
|
}
|
|
79
80
|
const publicResolver = await contracts?.getPublicResolver();
|
|
81
|
+
if (coinType === 60 || coinType === '60') {
|
|
82
|
+
return {
|
|
83
|
+
to: '0x0000000000000000000000000000000000000000',
|
|
84
|
+
data: publicResolver.interface.encodeFunctionData('addr(bytes32)', [
|
|
85
|
+
namehash(name),
|
|
86
|
+
]),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
80
89
|
if (bypassFormat) {
|
|
81
90
|
return {
|
|
82
91
|
to: '0x0000000000000000000000000000000000000000',
|
|
83
|
-
data: publicResolver.interface.encodeFunctionData('addr(bytes32,uint256)', [
|
|
92
|
+
data: publicResolver.interface.encodeFunctionData('addr(bytes32,uint256)', [namehash(name), coinType]),
|
|
84
93
|
};
|
|
85
94
|
}
|
|
86
95
|
const formatter = typeof coinType === 'string' && isNaN(parseInt(coinType))
|
|
@@ -91,7 +100,7 @@ export const _getAddr = {
|
|
|
91
100
|
}
|
|
92
101
|
return {
|
|
93
102
|
to: '0x0000000000000000000000000000000000000000',
|
|
94
|
-
data: publicResolver.interface.encodeFunctionData('addr(bytes32,uint256)', [
|
|
103
|
+
data: publicResolver.interface.encodeFunctionData('addr(bytes32,uint256)', [namehash(name), formatter.coinType]),
|
|
95
104
|
};
|
|
96
105
|
},
|
|
97
106
|
decode: async ({ contracts }, data, _name, coinType) => {
|
|
@@ -104,7 +113,15 @@ export const _getAddr = {
|
|
|
104
113
|
const formatter = typeof coinType === 'string' && isNaN(parseInt(coinType))
|
|
105
114
|
? formatsByName[coinType]
|
|
106
115
|
: formatsByCoinType[typeof coinType === 'number' ? coinType : parseInt(coinType)];
|
|
107
|
-
|
|
116
|
+
let response;
|
|
117
|
+
if (coinType === 60 || coinType === '60') {
|
|
118
|
+
;
|
|
119
|
+
[response] = publicResolver.interface.decodeFunctionResult('addr(bytes32)', data);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
;
|
|
123
|
+
[response] = publicResolver.interface.decodeFunctionResult('addr(bytes32,uint256)', data);
|
|
124
|
+
}
|
|
108
125
|
if (!response)
|
|
109
126
|
return;
|
|
110
127
|
if (ethers.utils.hexStripZeros(response) === '0x') {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { namehash } from 'ethers/lib/utils';
|
|
2
1
|
import { truncateFormat } from '../utils/format';
|
|
3
2
|
import { decryptName } from '../utils/labels';
|
|
3
|
+
import { namehash } from '../utils/normalise';
|
|
4
4
|
const largeQuery = async ({ gqlInstance }, { name, page, pageSize = 10, orderDirection, orderBy, lastSubnames }) => {
|
|
5
5
|
const client = gqlInstance.client;
|
|
6
6
|
let finalQuery = gqlInstance.gql `
|
|
@@ -53,7 +53,7 @@ const largeQuery = async ({ gqlInstance }, { name, page, pageSize = 10, orderDir
|
|
|
53
53
|
});
|
|
54
54
|
return {
|
|
55
55
|
subnames: subdomains,
|
|
56
|
-
subnameCount: domain.subdomainCount
|
|
56
|
+
subnameCount: domain.subdomainCount,
|
|
57
57
|
};
|
|
58
58
|
};
|
|
59
59
|
const smallQuery = async ({ gqlInstance }, { name, page, pageSize = 10, orderDirection, orderBy }) => {
|
|
@@ -140,7 +140,7 @@ const smallQuery = async ({ gqlInstance }, { name, page, pageSize = 10, orderDir
|
|
|
140
140
|
});
|
|
141
141
|
return {
|
|
142
142
|
subnames: subdomains,
|
|
143
|
-
subnameCount: domain.subdomainCount
|
|
143
|
+
subnameCount: domain.subdomainCount,
|
|
144
144
|
};
|
|
145
145
|
};
|
|
146
146
|
const getSubnames = (injected, functionArgs) => {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ethers } from 'ethers';
|
|
2
1
|
import { ENSArgs } from '..';
|
|
3
2
|
import { RecordOptions } from '../utils/recordHelpers';
|
|
4
|
-
export default function ({ contracts, provider, getResolver, }: ENSArgs<'contracts' | 'provider' | 'getResolver'>, name: string, records: RecordOptions): Promise<ethers.ContractTransaction | undefined>;
|
|
3
|
+
export default function ({ contracts, provider, getResolver, }: ENSArgs<'contracts' | 'provider' | 'getResolver'>, name: string, records: RecordOptions): Promise<import("ethers").ContractTransaction | undefined>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { namehash } from '../utils/normalise';
|
|
2
2
|
import { generateRecordCallArray } from '../utils/recordHelpers';
|
|
3
3
|
export default async function ({ contracts, provider, getResolver, }, name, records) {
|
|
4
4
|
if (!name.includes('.')) {
|
|
@@ -13,7 +13,7 @@ export default async function ({ contracts, provider, getResolver, }, name, reco
|
|
|
13
13
|
throw new Error('No signer found');
|
|
14
14
|
}
|
|
15
15
|
const resolver = (await contracts?.getPublicResolver(provider, resolverAddress))?.connect(provider?.getSigner());
|
|
16
|
-
const
|
|
17
|
-
const calls = generateRecordCallArray(
|
|
16
|
+
const hash = namehash(name);
|
|
17
|
+
const calls = generateRecordCallArray(hash, records, resolver);
|
|
18
18
|
return resolver?.multicall(calls);
|
|
19
19
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { ethers } from 'ethers';
|
|
2
1
|
import { ENSArgs } from '..';
|
|
3
2
|
export default function ({ contracts, provider }: ENSArgs<'contracts' | 'provider'>, name: string, contract: 'registry' | 'nameWrapper', resolver?: string, options?: {
|
|
4
3
|
addressOrIndex?: string | number;
|
|
5
|
-
}): Promise<ethers.ContractTransaction>;
|
|
4
|
+
}): Promise<import("ethers").ContractTransaction>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { namehash } from '../utils/normalise';
|
|
2
2
|
export default async function ({ contracts, provider }, name, contract, resolver, options) {
|
|
3
3
|
const address = await provider
|
|
4
4
|
?.getSigner(options?.addressOrIndex)
|
|
@@ -12,11 +12,11 @@ export default async function ({ contracts, provider }, name, contract, resolver
|
|
|
12
12
|
switch (contract) {
|
|
13
13
|
case 'registry': {
|
|
14
14
|
const registry = (await contracts?.getRegistry()).connect(provider?.getSigner(options?.addressOrIndex));
|
|
15
|
-
return registry.setResolver(
|
|
15
|
+
return registry.setResolver(namehash(name), resolver);
|
|
16
16
|
}
|
|
17
17
|
case 'nameWrapper': {
|
|
18
18
|
const nameWrapper = (await contracts?.getNameWrapper()).connect(provider?.getSigner(options?.addressOrIndex));
|
|
19
|
-
return nameWrapper.setResolver(
|
|
19
|
+
return nameWrapper.setResolver(namehash(name), resolver);
|
|
20
20
|
}
|
|
21
21
|
default: {
|
|
22
22
|
throw new Error(`Unknown contract: ${contract}`);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ethers } from 'ethers';
|
|
2
|
+
import { namehash } from '../utils/normalise';
|
|
2
3
|
export default async function ({ contracts, provider }, name, newOwner, contract, options) {
|
|
3
4
|
const address = await provider
|
|
4
5
|
?.getSigner(options?.addressOrIndex)
|
|
@@ -9,7 +10,7 @@ export default async function ({ contracts, provider }, name, newOwner, contract
|
|
|
9
10
|
switch (contract) {
|
|
10
11
|
case 'registry': {
|
|
11
12
|
const registry = (await contracts?.getRegistry()).connect(provider?.getSigner(options?.addressOrIndex));
|
|
12
|
-
return registry.setOwner(
|
|
13
|
+
return registry.setOwner(namehash(name), newOwner);
|
|
13
14
|
}
|
|
14
15
|
case 'baseRegistrar': {
|
|
15
16
|
const baseRegistrar = (await contracts?.getBaseRegistrar()).connect(provider?.getSigner(options?.addressOrIndex));
|
|
@@ -21,7 +22,7 @@ export default async function ({ contracts, provider }, name, newOwner, contract
|
|
|
21
22
|
}
|
|
22
23
|
case 'nameWrapper': {
|
|
23
24
|
const nameWrapper = (await contracts?.getNameWrapper()).connect(provider?.getSigner(options?.addressOrIndex));
|
|
24
|
-
return nameWrapper.safeTransferFrom(address, newOwner,
|
|
25
|
+
return nameWrapper.safeTransferFrom(address, newOwner, namehash(name), 1, '0x');
|
|
25
26
|
}
|
|
26
27
|
default: {
|
|
27
28
|
throw new Error(`Unknown contract: ${contract}`);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ethers } from 'ethers';
|
|
2
|
+
import { namehash } from '../utils/normalise';
|
|
2
3
|
export default async function ({ contracts, provider }, name, contract, address, options) {
|
|
3
4
|
const signer = provider?.getSigner(options?.addressOrIndex);
|
|
4
5
|
if (!signer) {
|
|
@@ -7,7 +8,7 @@ export default async function ({ contracts, provider }, name, contract, address,
|
|
|
7
8
|
const labels = name.split('.');
|
|
8
9
|
const label = labels.shift();
|
|
9
10
|
const labelhash = ethers.utils.solidityKeccak256(['string'], [label]);
|
|
10
|
-
const parentNodehash =
|
|
11
|
+
const parentNodehash = namehash(labels.join('.'));
|
|
11
12
|
switch (contract) {
|
|
12
13
|
case 'registry': {
|
|
13
14
|
const registry = (await contracts?.getRegistry()).connect(signer);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { utils } from 'ethers';
|
|
2
|
+
import { namehash } from '../utils/normalise';
|
|
2
3
|
export default async function ({ contracts, provider }, name, newController, newRegistrant, options) {
|
|
3
4
|
const signer = provider?.getSigner(options?.addressOrIndex);
|
|
4
5
|
const address = await signer?.getAddress();
|
|
@@ -7,7 +8,7 @@ export default async function ({ contracts, provider }, name, newController, new
|
|
|
7
8
|
}
|
|
8
9
|
const labels = name.split('.');
|
|
9
10
|
const labelhash = utils.solidityKeccak256(['string'], [labels[0]]);
|
|
10
|
-
const parentNodehash =
|
|
11
|
+
const parentNodehash = namehash(labels.slice(1).join('.'));
|
|
11
12
|
const nameWrapper = (await contracts?.getNameWrapper()).connect(signer);
|
|
12
13
|
if (labels.length === 2 && labels[1] === 'eth') {
|
|
13
14
|
if (!newRegistrant) {
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -466,5 +466,6 @@ export declare class ENS {
|
|
|
466
466
|
transferSubname: (name: string, contract: "nameWrapper" | "registry", address: string, options?: {
|
|
467
467
|
addressOrIndex?: string | number | undefined;
|
|
468
468
|
} | undefined) => Promise<ethers.ContractTransaction>;
|
|
469
|
+
getDNSOwner: (dnsName: string) => Promise<any>;
|
|
469
470
|
}
|
|
470
471
|
export {};
|
package/dist/esm/index.js
CHANGED
|
@@ -129,6 +129,7 @@ export class ENS {
|
|
|
129
129
|
'gqlInstance',
|
|
130
130
|
'getName',
|
|
131
131
|
'resolverMulticallWrapper',
|
|
132
|
+
'multicallWrapper',
|
|
132
133
|
'_getAddr',
|
|
133
134
|
'_getContentHash',
|
|
134
135
|
'_getText',
|
|
@@ -182,6 +183,7 @@ export class ENS {
|
|
|
182
183
|
this.createSubname = this.generateFunction('createSubname', ['contracts', 'provider']);
|
|
183
184
|
this.deleteSubname = this.generateFunction('deleteSubname', ['contracts', 'provider', 'transferSubname']);
|
|
184
185
|
this.transferSubname = this.generateFunction('transferSubname', ['contracts', 'provider']);
|
|
186
|
+
this.getDNSOwner = this.generateFunction('getDNSOwner', []);
|
|
185
187
|
this.options = options;
|
|
186
188
|
this.getContractAddress = options?.getContractAddress || _getContractAddress;
|
|
187
189
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { namehash } from './normalise';
|
|
2
2
|
export const makeOtherIndexes = (data, findStr) => Array.from(data.matchAll(findStr)).map((x) => x.index / 2 - 1);
|
|
3
|
-
export const makeNamehashIndexes = (data, name) => Array.from(data.matchAll(
|
|
3
|
+
export const makeNamehashIndexes = (data, name) => Array.from(data.matchAll(namehash(name).substring(2))).map((x) => x.index / 2 - 1);
|