@ensdomains/ensjs 3.0.0-alpha.53 → 3.0.0-alpha.54
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/dist/cjs/functions/getProfile.js +3 -6
- package/dist/cjs/functions/initialGetters.js +0 -2
- package/dist/cjs/index.js +0 -5
- package/dist/cjs/utils/consts.js +3 -1
- package/dist/cjs/utils/validation.js +41 -47
- package/dist/esm/functions/getProfile.mjs +3 -6
- package/dist/esm/functions/initialGetters.mjs +4 -6
- package/dist/esm/index.mjs +0 -5
- package/dist/esm/utils/consts.mjs +3 -1
- package/dist/esm/utils/validation.mjs +42 -49
- package/dist/types/functions/initialGetters.d.ts +0 -1
- package/dist/types/functions/types.d.ts +0 -2
- package/dist/types/index.d.ts +0 -32
- package/dist/types/utils/consts.d.ts +1 -0
- package/dist/types/utils/validation.d.ts +10 -6
- package/package.json +1 -1
- package/src/functions/getProfile.ts +3 -7
- package/src/functions/initialGetters.ts +0 -1
- package/src/functions/types.ts +0 -2
- package/src/index.ts +0 -6
- package/src/utils/consts.ts +1 -0
- package/src/utils/validation.test.ts +164 -0
- package/src/utils/validation.ts +51 -51
- package/dist/cjs/functions/getRecords.js +0 -31
- package/dist/esm/functions/getRecords.mjs +0 -12
- package/dist/types/functions/getRecords.d.ts +0 -35
- package/src/functions/getRecords.ts +0 -23
|
@@ -23,11 +23,11 @@ __export(getProfile_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(getProfile_exports);
|
|
24
24
|
var import_address_encoder = require("@ensdomains/address-encoder");
|
|
25
25
|
var import_abi = require("@ethersproject/abi");
|
|
26
|
+
var import_address = require("@ethersproject/address");
|
|
26
27
|
var import_bytes = require("@ethersproject/bytes");
|
|
27
28
|
var import_contentHash = require("../utils/contentHash");
|
|
28
29
|
var import_hexEncodedName = require("../utils/hexEncodedName");
|
|
29
30
|
var import_normalise = require("../utils/normalise");
|
|
30
|
-
var import_validation = require("../utils/validation");
|
|
31
31
|
const makeMulticallData = async ({
|
|
32
32
|
_getAddr,
|
|
33
33
|
_getContentHash,
|
|
@@ -468,11 +468,8 @@ async function getProfile_default({
|
|
|
468
468
|
options.fallback.coinTypes = options.fallback.coinTypes.map(mapCoinTypes);
|
|
469
469
|
}
|
|
470
470
|
}
|
|
471
|
-
const
|
|
472
|
-
if (
|
|
473
|
-
throw new Error("Invalid input type");
|
|
474
|
-
}
|
|
475
|
-
if (inputType.type === "address") {
|
|
471
|
+
const inputIsAddress = (0, import_address.isAddress)(nameOrAddress);
|
|
472
|
+
if (inputIsAddress) {
|
|
476
473
|
return getProfileFromAddress(
|
|
477
474
|
{
|
|
478
475
|
contracts,
|
|
@@ -32,7 +32,6 @@ __export(initialGetters_exports, {
|
|
|
32
32
|
getOwner: () => import_getOwner.default,
|
|
33
33
|
getPrice: () => import_getPrice.default,
|
|
34
34
|
getProfile: () => import_getProfile.default,
|
|
35
|
-
getRecords: () => import_getRecords.default,
|
|
36
35
|
getSubnames: () => import_getSubnames.default,
|
|
37
36
|
supportsTLD: () => import_supportsTLD.default
|
|
38
37
|
});
|
|
@@ -45,7 +44,6 @@ var import_getNames = __toESM(require("./getNames"));
|
|
|
45
44
|
var import_getOwner = __toESM(require("./getOwner"));
|
|
46
45
|
var import_getPrice = __toESM(require("./getPrice"));
|
|
47
46
|
var import_getProfile = __toESM(require("./getProfile"));
|
|
48
|
-
var import_getRecords = __toESM(require("./getRecords"));
|
|
49
47
|
__reExport(initialGetters_exports, require("./getSpecificRecord"), module.exports);
|
|
50
48
|
var import_getSubnames = __toESM(require("./getSubnames"));
|
|
51
49
|
var import_supportsTLD = __toESM(require("./supportsTLD"));
|
package/dist/cjs/index.js
CHANGED
package/dist/cjs/utils/consts.js
CHANGED
|
@@ -19,8 +19,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
var consts_exports = {};
|
|
20
20
|
__export(consts_exports, {
|
|
21
21
|
EMPTY_ADDRESS: () => EMPTY_ADDRESS,
|
|
22
|
-
MAX_INT_64: () => MAX_INT_64
|
|
22
|
+
MAX_INT_64: () => MAX_INT_64,
|
|
23
|
+
MINIMUM_DOT_ETH_CHARS: () => MINIMUM_DOT_ETH_CHARS
|
|
23
24
|
});
|
|
24
25
|
module.exports = __toCommonJS(consts_exports);
|
|
25
26
|
const EMPTY_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
26
27
|
const MAX_INT_64 = BigInt("18446744073709551615");
|
|
28
|
+
const MINIMUM_DOT_ETH_CHARS = 3;
|
|
@@ -19,70 +19,64 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
var validation_exports = {};
|
|
20
20
|
__export(validation_exports, {
|
|
21
21
|
checkIsDotEth: () => checkIsDotEth,
|
|
22
|
-
|
|
23
|
-
validateName: () => validateName
|
|
24
|
-
validateTLD: () => validateTLD
|
|
22
|
+
parseInput: () => parseInput,
|
|
23
|
+
validateName: () => validateName
|
|
25
24
|
});
|
|
26
25
|
module.exports = __toCommonJS(validation_exports);
|
|
27
|
-
var
|
|
26
|
+
var import_consts = require("./consts");
|
|
28
27
|
var import_labels = require("./labels");
|
|
29
28
|
var import_normalise = require("./normalise");
|
|
30
29
|
const validateName = (name) => {
|
|
31
30
|
const nameArray = name.split(".");
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const normalizedArray = nameArray.map((label) => {
|
|
31
|
+
const normalisedArray = nameArray.map((label) => {
|
|
32
|
+
if (label.length === 0)
|
|
33
|
+
throw new Error("Name cannot have empty labels");
|
|
36
34
|
if (label === "[root]") {
|
|
35
|
+
if (name !== label)
|
|
36
|
+
throw new Error("Root label must be the only label");
|
|
37
37
|
return label;
|
|
38
38
|
}
|
|
39
|
-
return (0, import_labels.isEncodedLabelhash)(label) ? label : (0, import_normalise.normalise)(label);
|
|
39
|
+
return (0, import_labels.isEncodedLabelhash)(label) ? (0, import_labels.checkLabel)(label) || label : (0, import_normalise.normalise)(label);
|
|
40
40
|
});
|
|
41
|
-
const
|
|
42
|
-
(0, import_labels.saveName)(
|
|
43
|
-
return
|
|
41
|
+
const normalisedName = normalisedArray.join(".");
|
|
42
|
+
(0, import_labels.saveName)(normalisedName);
|
|
43
|
+
return normalisedName;
|
|
44
44
|
};
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const parseInputType = (input) => {
|
|
50
|
-
const validTLD = validateTLD(input);
|
|
51
|
-
const regex = /[^.]+$/;
|
|
45
|
+
const parseInput = (input) => {
|
|
46
|
+
var _a;
|
|
47
|
+
let nameReference = input;
|
|
48
|
+
let isValid = false;
|
|
52
49
|
try {
|
|
53
|
-
validateName(input);
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
type: "unknown"
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
if (input.indexOf(".") !== -1) {
|
|
60
|
-
const termArray = input.split(".");
|
|
61
|
-
const tld = input.match(regex) ? input.match(regex)[0] : "";
|
|
62
|
-
if (validTLD) {
|
|
63
|
-
if (tld === "eth" && [...termArray[termArray.length - 2]].length < 3) {
|
|
64
|
-
return {
|
|
65
|
-
type: "name",
|
|
66
|
-
info: "short"
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
return {
|
|
70
|
-
type: "name",
|
|
71
|
-
info: "supported"
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
return {
|
|
75
|
-
type: "name",
|
|
76
|
-
info: "unsupported"
|
|
77
|
-
};
|
|
50
|
+
nameReference = validateName(input);
|
|
51
|
+
isValid = true;
|
|
52
|
+
} catch {
|
|
78
53
|
}
|
|
79
|
-
|
|
54
|
+
const normalisedName = isValid ? nameReference : void 0;
|
|
55
|
+
const labels = nameReference.split(".");
|
|
56
|
+
const tld = labels[labels.length - 1];
|
|
57
|
+
const isETH = tld === "eth";
|
|
58
|
+
const labelDataArray = (0, import_normalise.split)(nameReference);
|
|
59
|
+
const isShort = (((_a = labelDataArray[0].output) == null ? void 0 : _a.length) || 0) < import_consts.MINIMUM_DOT_ETH_CHARS;
|
|
60
|
+
if (labels.length === 1) {
|
|
80
61
|
return {
|
|
81
|
-
type: "
|
|
62
|
+
type: "label",
|
|
63
|
+
normalised: normalisedName,
|
|
64
|
+
isShort,
|
|
65
|
+
isValid,
|
|
66
|
+
is2LD: false,
|
|
67
|
+
isETH,
|
|
68
|
+
labelDataArray
|
|
82
69
|
};
|
|
83
70
|
}
|
|
71
|
+
const is2LD = labels.length === 2;
|
|
84
72
|
return {
|
|
85
|
-
type: "
|
|
73
|
+
type: "name",
|
|
74
|
+
normalised: normalisedName,
|
|
75
|
+
isShort: isETH && is2LD ? isShort : false,
|
|
76
|
+
isValid,
|
|
77
|
+
is2LD,
|
|
78
|
+
isETH,
|
|
79
|
+
labelDataArray
|
|
86
80
|
};
|
|
87
81
|
};
|
|
88
82
|
const checkIsDotEth = (labels) => labels.length === 2 && labels[1] === "eth";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// src/functions/getProfile.ts
|
|
2
2
|
import { formatsByName } from "@ensdomains/address-encoder";
|
|
3
3
|
import { defaultAbiCoder } from "@ethersproject/abi";
|
|
4
|
+
import { isAddress } from "@ethersproject/address";
|
|
4
5
|
import { hexStripZeros, isBytesLike } from "@ethersproject/bytes";
|
|
5
6
|
import { decodeContenthash } from "../utils/contentHash.mjs";
|
|
6
7
|
import { hexEncodeName } from "../utils/hexEncodedName.mjs";
|
|
7
8
|
import { namehash } from "../utils/normalise.mjs";
|
|
8
|
-
import { parseInputType } from "../utils/validation.mjs";
|
|
9
9
|
var makeMulticallData = async ({
|
|
10
10
|
_getAddr,
|
|
11
11
|
_getContentHash,
|
|
@@ -446,11 +446,8 @@ async function getProfile_default({
|
|
|
446
446
|
options.fallback.coinTypes = options.fallback.coinTypes.map(mapCoinTypes);
|
|
447
447
|
}
|
|
448
448
|
}
|
|
449
|
-
const
|
|
450
|
-
if (
|
|
451
|
-
throw new Error("Invalid input type");
|
|
452
|
-
}
|
|
453
|
-
if (inputType.type === "address") {
|
|
449
|
+
const inputIsAddress = isAddress(nameOrAddress);
|
|
450
|
+
if (inputIsAddress) {
|
|
454
451
|
return getProfileFromAddress(
|
|
455
452
|
{
|
|
456
453
|
contracts,
|
|
@@ -7,10 +7,9 @@ import { default as default5 } from "./getNames.mjs";
|
|
|
7
7
|
import { default as default6 } from "./getOwner.mjs";
|
|
8
8
|
import { default as default7 } from "./getPrice.mjs";
|
|
9
9
|
import { default as default8 } from "./getProfile.mjs";
|
|
10
|
-
import { default as default9 } from "./getRecords.mjs";
|
|
11
10
|
export * from "./getSpecificRecord.mjs";
|
|
12
|
-
import { default as
|
|
13
|
-
import { default as
|
|
11
|
+
import { default as default9 } from "./getSubnames.mjs";
|
|
12
|
+
import { default as default10 } from "./supportsTLD.mjs";
|
|
14
13
|
export {
|
|
15
14
|
default2 as batch,
|
|
16
15
|
default3 as getExpiry,
|
|
@@ -19,7 +18,6 @@ export {
|
|
|
19
18
|
default6 as getOwner,
|
|
20
19
|
default7 as getPrice,
|
|
21
20
|
default8 as getProfile,
|
|
22
|
-
default9 as
|
|
23
|
-
default10 as
|
|
24
|
-
default11 as supportsTLD
|
|
21
|
+
default9 as getSubnames,
|
|
22
|
+
default10 as supportsTLD
|
|
25
23
|
};
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,69 +1,62 @@
|
|
|
1
1
|
// src/utils/validation.ts
|
|
2
|
-
import {
|
|
3
|
-
import { isEncodedLabelhash, saveName } from "./labels.mjs";
|
|
4
|
-
import { normalise } from "./normalise.mjs";
|
|
2
|
+
import { MINIMUM_DOT_ETH_CHARS } from "./consts.mjs";
|
|
3
|
+
import { checkLabel, isEncodedLabelhash, saveName } from "./labels.mjs";
|
|
4
|
+
import { normalise, split } from "./normalise.mjs";
|
|
5
5
|
var validateName = (name) => {
|
|
6
6
|
const nameArray = name.split(".");
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const normalizedArray = nameArray.map((label) => {
|
|
7
|
+
const normalisedArray = nameArray.map((label) => {
|
|
8
|
+
if (label.length === 0)
|
|
9
|
+
throw new Error("Name cannot have empty labels");
|
|
11
10
|
if (label === "[root]") {
|
|
11
|
+
if (name !== label)
|
|
12
|
+
throw new Error("Root label must be the only label");
|
|
12
13
|
return label;
|
|
13
14
|
}
|
|
14
|
-
return isEncodedLabelhash(label) ? label : normalise(label);
|
|
15
|
+
return isEncodedLabelhash(label) ? checkLabel(label) || label : normalise(label);
|
|
15
16
|
});
|
|
16
|
-
const
|
|
17
|
-
saveName(
|
|
18
|
-
return
|
|
17
|
+
const normalisedName = normalisedArray.join(".");
|
|
18
|
+
saveName(normalisedName);
|
|
19
|
+
return normalisedName;
|
|
19
20
|
};
|
|
20
|
-
var
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
};
|
|
24
|
-
var parseInputType = (input) => {
|
|
25
|
-
const validTLD = validateTLD(input);
|
|
26
|
-
const regex = /[^.]+$/;
|
|
21
|
+
var parseInput = (input) => {
|
|
22
|
+
let nameReference = input;
|
|
23
|
+
let isValid = false;
|
|
27
24
|
try {
|
|
28
|
-
validateName(input);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
type: "unknown"
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
if (input.indexOf(".") !== -1) {
|
|
35
|
-
const termArray = input.split(".");
|
|
36
|
-
const tld = input.match(regex) ? input.match(regex)[0] : "";
|
|
37
|
-
if (validTLD) {
|
|
38
|
-
if (tld === "eth" && [...termArray[termArray.length - 2]].length < 3) {
|
|
39
|
-
return {
|
|
40
|
-
type: "name",
|
|
41
|
-
info: "short"
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
return {
|
|
45
|
-
type: "name",
|
|
46
|
-
info: "supported"
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
return {
|
|
50
|
-
type: "name",
|
|
51
|
-
info: "unsupported"
|
|
52
|
-
};
|
|
25
|
+
nameReference = validateName(input);
|
|
26
|
+
isValid = true;
|
|
27
|
+
} catch {
|
|
53
28
|
}
|
|
54
|
-
|
|
29
|
+
const normalisedName = isValid ? nameReference : void 0;
|
|
30
|
+
const labels = nameReference.split(".");
|
|
31
|
+
const tld = labels[labels.length - 1];
|
|
32
|
+
const isETH = tld === "eth";
|
|
33
|
+
const labelDataArray = split(nameReference);
|
|
34
|
+
const isShort = (labelDataArray[0].output?.length || 0) < MINIMUM_DOT_ETH_CHARS;
|
|
35
|
+
if (labels.length === 1) {
|
|
55
36
|
return {
|
|
56
|
-
type: "
|
|
37
|
+
type: "label",
|
|
38
|
+
normalised: normalisedName,
|
|
39
|
+
isShort,
|
|
40
|
+
isValid,
|
|
41
|
+
is2LD: false,
|
|
42
|
+
isETH,
|
|
43
|
+
labelDataArray
|
|
57
44
|
};
|
|
58
45
|
}
|
|
46
|
+
const is2LD = labels.length === 2;
|
|
59
47
|
return {
|
|
60
|
-
type: "
|
|
48
|
+
type: "name",
|
|
49
|
+
normalised: normalisedName,
|
|
50
|
+
isShort: isETH && is2LD ? isShort : false,
|
|
51
|
+
isValid,
|
|
52
|
+
is2LD,
|
|
53
|
+
isETH,
|
|
54
|
+
labelDataArray
|
|
61
55
|
};
|
|
62
56
|
};
|
|
63
57
|
var checkIsDotEth = (labels) => labels.length === 2 && labels[1] === "eth";
|
|
64
58
|
export {
|
|
65
59
|
checkIsDotEth,
|
|
66
|
-
|
|
67
|
-
validateName
|
|
68
|
-
validateTLD
|
|
60
|
+
parseInput,
|
|
61
|
+
validateName
|
|
69
62
|
};
|
|
@@ -6,7 +6,6 @@ export { default as getNames } from './getNames';
|
|
|
6
6
|
export { default as getOwner } from './getOwner';
|
|
7
7
|
export { default as getPrice } from './getPrice';
|
|
8
8
|
export { default as getProfile } from './getProfile';
|
|
9
|
-
export { default as getRecords } from './getRecords';
|
|
10
9
|
export * from './getSpecificRecord';
|
|
11
10
|
export { default as getSubnames } from './getSubnames';
|
|
12
11
|
export { default as supportsTLD } from './supportsTLD';
|
|
@@ -13,7 +13,6 @@ import type getNames from './getNames';
|
|
|
13
13
|
import type getOwner from './getOwner';
|
|
14
14
|
import type getPrice from './getPrice';
|
|
15
15
|
import type getProfile from './getProfile';
|
|
16
|
-
import type getRecords from './getRecords';
|
|
17
16
|
import type getResolver from './getResolver';
|
|
18
17
|
import type { getABI, getAddr, getContentHash, getText, _getABI, _getAddr, _getContentHash, _getText } from './getSpecificRecord';
|
|
19
18
|
import type getSubnames from './getSubnames';
|
|
@@ -53,7 +52,6 @@ declare type Function = {
|
|
|
53
52
|
getOwner: typeof getOwner;
|
|
54
53
|
getPrice: typeof getPrice;
|
|
55
54
|
getProfile: typeof getProfile;
|
|
56
|
-
getRecords: typeof getRecords;
|
|
57
55
|
getResolver: typeof getResolver;
|
|
58
56
|
getAddr: typeof getAddr;
|
|
59
57
|
getContentHash: typeof getContentHash;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -182,38 +182,6 @@ export declare class ENS {
|
|
|
182
182
|
isInvalidResolverAddress?: boolean | undefined;
|
|
183
183
|
reverseResolverAddress?: string | undefined;
|
|
184
184
|
} | undefined>;
|
|
185
|
-
getRecords: (name: string, options?: {
|
|
186
|
-
contentHash?: boolean | undefined;
|
|
187
|
-
texts?: boolean | string[] | undefined;
|
|
188
|
-
coinTypes?: boolean | string[] | undefined;
|
|
189
|
-
resolverAddress?: string | undefined;
|
|
190
|
-
} | undefined) => Promise<{
|
|
191
|
-
isMigrated: boolean | null;
|
|
192
|
-
createdAt: string | null;
|
|
193
|
-
address?: string | undefined;
|
|
194
|
-
name?: string | null | undefined;
|
|
195
|
-
decryptedName?: string | null | undefined;
|
|
196
|
-
match?: boolean | undefined;
|
|
197
|
-
message?: string | undefined;
|
|
198
|
-
records?: {
|
|
199
|
-
contentHash?: string | import("./utils/contentHash").DecodedContentHash | null | undefined;
|
|
200
|
-
texts?: {
|
|
201
|
-
key: string | number;
|
|
202
|
-
type: "text" | "addr" | "contentHash";
|
|
203
|
-
coin?: string | undefined;
|
|
204
|
-
value: string;
|
|
205
|
-
}[] | undefined;
|
|
206
|
-
coinTypes?: {
|
|
207
|
-
key: string | number;
|
|
208
|
-
type: "text" | "addr" | "contentHash";
|
|
209
|
-
coin?: string | undefined;
|
|
210
|
-
value: string;
|
|
211
|
-
}[] | undefined;
|
|
212
|
-
} | undefined;
|
|
213
|
-
resolverAddress?: string | undefined;
|
|
214
|
-
isInvalidResolverAddress?: boolean | undefined;
|
|
215
|
-
reverseResolverAddress?: string | undefined;
|
|
216
|
-
} | undefined>;
|
|
217
185
|
getName: GeneratedRawFunction<{
|
|
218
186
|
raw: ({ contracts }: ENSArgs<"contracts">, address: string) => Promise<{
|
|
219
187
|
to: string;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { Label } from './normalise';
|
|
1
2
|
export declare const validateName: (name: string) => string;
|
|
2
|
-
export declare
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
export declare type ParsedInputResult = {
|
|
4
|
+
type: 'name' | 'label';
|
|
5
|
+
normalised: string | undefined;
|
|
6
|
+
isValid: boolean;
|
|
7
|
+
isShort: boolean;
|
|
8
|
+
is2LD: boolean;
|
|
9
|
+
isETH: boolean;
|
|
10
|
+
labelDataArray: Label[];
|
|
6
11
|
};
|
|
7
|
-
export declare const
|
|
12
|
+
export declare const parseInput: (input: string) => ParsedInputResult;
|
|
8
13
|
export declare const checkIsDotEth: (labels: string[]) => boolean;
|
|
9
|
-
export {};
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { formatsByName } from '@ensdomains/address-encoder'
|
|
2
2
|
import { defaultAbiCoder } from '@ethersproject/abi'
|
|
3
|
+
import { isAddress } from '@ethersproject/address'
|
|
3
4
|
import { hexStripZeros, isBytesLike } from '@ethersproject/bytes'
|
|
4
5
|
import { ENSArgs } from '..'
|
|
5
6
|
import { decodeContenthash, DecodedContentHash } from '../utils/contentHash'
|
|
6
7
|
import { hexEncodeName } from '../utils/hexEncodedName'
|
|
7
8
|
import { namehash } from '../utils/normalise'
|
|
8
|
-
import { parseInputType } from '../utils/validation'
|
|
9
9
|
|
|
10
10
|
type InternalProfileOptions = {
|
|
11
11
|
contentHash?: boolean | string | DecodedContentHash
|
|
@@ -653,13 +653,9 @@ export default async function (
|
|
|
653
653
|
}
|
|
654
654
|
}
|
|
655
655
|
|
|
656
|
-
const
|
|
656
|
+
const inputIsAddress = isAddress(nameOrAddress)
|
|
657
657
|
|
|
658
|
-
if (
|
|
659
|
-
throw new Error('Invalid input type')
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
if (inputType.type === 'address') {
|
|
658
|
+
if (inputIsAddress) {
|
|
663
659
|
return getProfileFromAddress(
|
|
664
660
|
{
|
|
665
661
|
contracts,
|
|
@@ -6,7 +6,6 @@ export { default as getNames } from './getNames'
|
|
|
6
6
|
export { default as getOwner } from './getOwner'
|
|
7
7
|
export { default as getPrice } from './getPrice'
|
|
8
8
|
export { default as getProfile } from './getProfile'
|
|
9
|
-
export { default as getRecords } from './getRecords'
|
|
10
9
|
export * from './getSpecificRecord'
|
|
11
10
|
export { default as getSubnames } from './getSubnames'
|
|
12
11
|
export { default as supportsTLD } from './supportsTLD'
|
package/src/functions/types.ts
CHANGED
|
@@ -17,7 +17,6 @@ import type getNames from './getNames'
|
|
|
17
17
|
import type getOwner from './getOwner'
|
|
18
18
|
import type getPrice from './getPrice'
|
|
19
19
|
import type getProfile from './getProfile'
|
|
20
|
-
import type getRecords from './getRecords'
|
|
21
20
|
import type getResolver from './getResolver'
|
|
22
21
|
import type {
|
|
23
22
|
getABI,
|
|
@@ -71,7 +70,6 @@ type Function = {
|
|
|
71
70
|
getOwner: typeof getOwner
|
|
72
71
|
getPrice: typeof getPrice
|
|
73
72
|
getProfile: typeof getProfile
|
|
74
|
-
getRecords: typeof getRecords
|
|
75
73
|
getResolver: typeof getResolver
|
|
76
74
|
getAddr: typeof getAddr
|
|
77
75
|
getContentHash: typeof getContentHash
|
package/src/index.ts
CHANGED
|
@@ -431,12 +431,6 @@ export class ENS {
|
|
|
431
431
|
'getProfile',
|
|
432
432
|
)
|
|
433
433
|
|
|
434
|
-
public getRecords = this.generateFunction<FunctionTypes['getRecords']>(
|
|
435
|
-
'initialGetters',
|
|
436
|
-
['getProfile'],
|
|
437
|
-
'getRecords',
|
|
438
|
-
)
|
|
439
|
-
|
|
440
434
|
public getName = this.generateRawFunction<FunctionTypes['getName']>(
|
|
441
435
|
'initialGetters',
|
|
442
436
|
['contracts'],
|
package/src/utils/consts.ts
CHANGED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
2
|
+
import { parseInput, validateName } from './validation'
|
|
3
|
+
|
|
4
|
+
declare namespace localStorage {
|
|
5
|
+
const getItem: jest.MockedFn<Storage['getItem']>
|
|
6
|
+
const setItem: jest.MockedFn<Storage['setItem']>
|
|
7
|
+
const removeItem: jest.MockedFn<Storage['removeItem']>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const labelsMock = {
|
|
11
|
+
'0x68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87':
|
|
12
|
+
'something',
|
|
13
|
+
'0x4f5b812789fc606be1b3b16908db13fc7a9adf7ca72641f84d75b47069d3d7f0': 'eth',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const labelsMockJSON = JSON.stringify(labelsMock)
|
|
17
|
+
|
|
18
|
+
describe('validateName()', () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
localStorage.getItem.mockClear()
|
|
21
|
+
localStorage.setItem.mockClear()
|
|
22
|
+
localStorage.getItem.mockImplementation(() => labelsMockJSON)
|
|
23
|
+
})
|
|
24
|
+
it('should throw if the name has an empty label', () => {
|
|
25
|
+
expect(() => validateName('foo..bar')).toThrowError(
|
|
26
|
+
'Name cannot have empty labels',
|
|
27
|
+
)
|
|
28
|
+
expect(() => validateName('.foo.bar')).toThrowError(
|
|
29
|
+
'Name cannot have empty labels',
|
|
30
|
+
)
|
|
31
|
+
expect(() => validateName('foo.bar.')).toThrowError(
|
|
32
|
+
'Name cannot have empty labels',
|
|
33
|
+
)
|
|
34
|
+
})
|
|
35
|
+
it('should allow names with [root] as a label', () => {
|
|
36
|
+
expect(validateName('[root]')).toEqual('[root]')
|
|
37
|
+
})
|
|
38
|
+
it('should throw if the name has [root] as a label and is not the only label', () => {
|
|
39
|
+
expect(() => validateName('foo.[root].bar')).toThrowError(
|
|
40
|
+
'Root label must be the only label',
|
|
41
|
+
)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('should get the decoded label hash from local storage', () => {
|
|
45
|
+
expect(
|
|
46
|
+
validateName(
|
|
47
|
+
'thing.[68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87].eth',
|
|
48
|
+
),
|
|
49
|
+
).toEqual('thing.something.eth')
|
|
50
|
+
expect(localStorage.getItem).toHaveBeenCalled()
|
|
51
|
+
})
|
|
52
|
+
it('should fallback to encoded label hash if the decoded label hash is not in local storage', () => {
|
|
53
|
+
expect(
|
|
54
|
+
validateName(
|
|
55
|
+
'something.[8c6c947d200f53fa1127b152f95b118f9e1d0eeb06fc678b6fc8a6d5c6fc5e17].eth',
|
|
56
|
+
),
|
|
57
|
+
).toEqual(
|
|
58
|
+
'something.[8c6c947d200f53fa1127b152f95b118f9e1d0eeb06fc678b6fc8a6d5c6fc5e17].eth',
|
|
59
|
+
)
|
|
60
|
+
expect(localStorage.getItem).toHaveBeenCalled()
|
|
61
|
+
expect(
|
|
62
|
+
validateName(
|
|
63
|
+
'[8c6c947d200f53fa1127b152f95b118f9e1d0eeb06fc678b6fc8a6d5c6fc5e17]',
|
|
64
|
+
),
|
|
65
|
+
).toEqual(
|
|
66
|
+
'[8c6c947d200f53fa1127b152f95b118f9e1d0eeb06fc678b6fc8a6d5c6fc5e17]',
|
|
67
|
+
)
|
|
68
|
+
})
|
|
69
|
+
it('should normalise the name', () => {
|
|
70
|
+
expect(validateName('aAaaA.eth')).toEqual('aaaaa.eth')
|
|
71
|
+
})
|
|
72
|
+
it('should save the normalised name to local storage', () => {
|
|
73
|
+
validateName('swAgCity.eth')
|
|
74
|
+
expect(localStorage.setItem).toHaveBeenCalledWith(
|
|
75
|
+
'ensjs:labels',
|
|
76
|
+
JSON.stringify({
|
|
77
|
+
...labelsMock,
|
|
78
|
+
'0xee3bbc5c1db3f1dbd5ec4cdfd627fb76aba6215d814354b6c0f8d74253adf1a8':
|
|
79
|
+
'swagcity',
|
|
80
|
+
}),
|
|
81
|
+
)
|
|
82
|
+
})
|
|
83
|
+
it('should return the normalised name', () => {
|
|
84
|
+
expect(validateName('swAgCity.eth')).toEqual('swagcity.eth')
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
describe('parseInput()', () => {
|
|
89
|
+
it('should parse the input', () => {
|
|
90
|
+
expect(parseInput('bar.eth')).toEqual({
|
|
91
|
+
type: 'name',
|
|
92
|
+
normalised: 'bar.eth',
|
|
93
|
+
isShort: false,
|
|
94
|
+
isValid: true,
|
|
95
|
+
is2LD: true,
|
|
96
|
+
isETH: true,
|
|
97
|
+
labelDataArray: expect.any(Array),
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
it('should return a normalised name', () => {
|
|
101
|
+
expect(parseInput('bAr.etH').normalised).toEqual('bar.eth')
|
|
102
|
+
})
|
|
103
|
+
it('should parse the input if it is invalid', () => {
|
|
104
|
+
expect(parseInput('bar..eth')).toEqual({
|
|
105
|
+
type: 'name',
|
|
106
|
+
normalised: undefined,
|
|
107
|
+
isShort: false,
|
|
108
|
+
isValid: false,
|
|
109
|
+
is2LD: false,
|
|
110
|
+
isETH: true,
|
|
111
|
+
labelDataArray: expect.any(Array),
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
it('should return type as label if input is a label', () => {
|
|
115
|
+
expect(parseInput('bar').type).toEqual('label')
|
|
116
|
+
})
|
|
117
|
+
describe('should return correct value', () => {
|
|
118
|
+
describe('isShort', () => {
|
|
119
|
+
it('should return true if input is label and less than 3 characters', () => {
|
|
120
|
+
expect(parseInput('ba').isShort).toEqual(true)
|
|
121
|
+
})
|
|
122
|
+
it('should return true if input is less than 3 char emoji', () => {
|
|
123
|
+
expect(parseInput('🇺🇸').isShort).toEqual(true)
|
|
124
|
+
})
|
|
125
|
+
it('should return false if input is 3 char emoji', () => {
|
|
126
|
+
expect(parseInput('🏳️🌈').isShort).toEqual(false)
|
|
127
|
+
})
|
|
128
|
+
it('should return false if input is label and 3 characters', () => {
|
|
129
|
+
expect(parseInput('bar').isShort).toEqual(false)
|
|
130
|
+
})
|
|
131
|
+
it('should return true if input is 2LD .eth name and label is less than 3 characters', () => {
|
|
132
|
+
expect(parseInput('ba.eth').isShort).toEqual(true)
|
|
133
|
+
})
|
|
134
|
+
it('should return false if input is 2LD .eth name and label is 3 characters', () => {
|
|
135
|
+
expect(parseInput('bar.eth').isShort).toEqual(false)
|
|
136
|
+
})
|
|
137
|
+
it('should return false if input is 2LD other name and label is less than 3 characters', () => {
|
|
138
|
+
expect(parseInput('ba.com').isShort).toEqual(false)
|
|
139
|
+
})
|
|
140
|
+
it('should return false if input is 3LD .eth name and label is less than 3 characters', () => {
|
|
141
|
+
expect(parseInput('ba.bar.eth').isShort).toEqual(false)
|
|
142
|
+
})
|
|
143
|
+
})
|
|
144
|
+
describe('is2LD', () => {
|
|
145
|
+
it('should return true if input is 2LD name', () => {
|
|
146
|
+
expect(parseInput('bar.eth').is2LD).toEqual(true)
|
|
147
|
+
})
|
|
148
|
+
it('should return false if input is 3LD name', () => {
|
|
149
|
+
expect(parseInput('bar.foo.eth').is2LD).toEqual(false)
|
|
150
|
+
})
|
|
151
|
+
it('should return false if input is label', () => {
|
|
152
|
+
expect(parseInput('bar').is2LD).toEqual(false)
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
describe('isETH', () => {
|
|
156
|
+
it('should return true if input is .eth name', () => {
|
|
157
|
+
expect(parseInput('bar.eth').isETH).toEqual(true)
|
|
158
|
+
})
|
|
159
|
+
it('should return false if input is other name', () => {
|
|
160
|
+
expect(parseInput('bar.com').isETH).toEqual(false)
|
|
161
|
+
})
|
|
162
|
+
})
|
|
163
|
+
})
|
|
164
|
+
})
|
package/src/utils/validation.ts
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isEncodedLabelhash, saveName } from './labels'
|
|
3
|
-
import { normalise } from './normalise'
|
|
1
|
+
import { MINIMUM_DOT_ETH_CHARS } from './consts'
|
|
2
|
+
import { checkLabel, isEncodedLabelhash, saveName } from './labels'
|
|
3
|
+
import { Label, normalise, split } from './normalise'
|
|
4
4
|
|
|
5
5
|
export const validateName = (name: string) => {
|
|
6
6
|
const nameArray = name.split('.')
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
const normalizedArray = nameArray.map((label) => {
|
|
7
|
+
const normalisedArray = nameArray.map((label) => {
|
|
8
|
+
if (label.length === 0) throw new Error('Name cannot have empty labels')
|
|
10
9
|
if (label === '[root]') {
|
|
10
|
+
if (name !== label) throw new Error('Root label must be the only label')
|
|
11
11
|
return label
|
|
12
12
|
}
|
|
13
|
-
return isEncodedLabelhash(label)
|
|
13
|
+
return isEncodedLabelhash(label)
|
|
14
|
+
? checkLabel(label) || label
|
|
15
|
+
: normalise(label)
|
|
14
16
|
})
|
|
15
|
-
const
|
|
16
|
-
saveName(
|
|
17
|
-
return
|
|
17
|
+
const normalisedName = normalisedArray.join('.')
|
|
18
|
+
saveName(normalisedName)
|
|
19
|
+
return normalisedName
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
export
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
export type ParsedInputResult = {
|
|
23
|
+
type: 'name' | 'label'
|
|
24
|
+
normalised: string | undefined
|
|
25
|
+
isValid: boolean
|
|
26
|
+
isShort: boolean
|
|
27
|
+
is2LD: boolean
|
|
28
|
+
isETH: boolean
|
|
29
|
+
labelDataArray: Label[]
|
|
23
30
|
}
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export const parseInputType = (input: string): InputType => {
|
|
31
|
-
const validTLD = validateTLD(input)
|
|
32
|
-
const regex = /[^.]+$/
|
|
32
|
+
export const parseInput = (input: string): ParsedInputResult => {
|
|
33
|
+
let nameReference = input
|
|
34
|
+
let isValid = false
|
|
33
35
|
|
|
34
36
|
try {
|
|
35
|
-
validateName(input)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
type: 'unknown',
|
|
39
|
-
}
|
|
40
|
-
}
|
|
37
|
+
nameReference = validateName(input)
|
|
38
|
+
isValid = true
|
|
39
|
+
} catch {}
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
const termArray = input.split('.')
|
|
44
|
-
const tld = input.match(regex) ? input.match(regex)![0] : ''
|
|
45
|
-
if (validTLD) {
|
|
46
|
-
if (tld === 'eth' && [...termArray[termArray.length - 2]].length < 3) {
|
|
47
|
-
// code-point length
|
|
48
|
-
return {
|
|
49
|
-
type: 'name',
|
|
50
|
-
info: 'short',
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return {
|
|
54
|
-
type: 'name',
|
|
55
|
-
info: 'supported',
|
|
56
|
-
}
|
|
57
|
-
}
|
|
41
|
+
const normalisedName = isValid ? nameReference : undefined
|
|
58
42
|
|
|
43
|
+
const labels = nameReference.split('.')
|
|
44
|
+
const tld = labels[labels.length - 1]
|
|
45
|
+
const isETH = tld === 'eth'
|
|
46
|
+
const labelDataArray = split(nameReference)
|
|
47
|
+
const isShort =
|
|
48
|
+
(labelDataArray[0].output?.length || 0) < MINIMUM_DOT_ETH_CHARS
|
|
49
|
+
|
|
50
|
+
if (labels.length === 1) {
|
|
59
51
|
return {
|
|
60
|
-
type: '
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
52
|
+
type: 'label',
|
|
53
|
+
normalised: normalisedName,
|
|
54
|
+
isShort,
|
|
55
|
+
isValid,
|
|
56
|
+
is2LD: false,
|
|
57
|
+
isETH,
|
|
58
|
+
labelDataArray,
|
|
67
59
|
}
|
|
68
60
|
}
|
|
61
|
+
|
|
62
|
+
const is2LD = labels.length === 2
|
|
69
63
|
return {
|
|
70
|
-
type: '
|
|
64
|
+
type: 'name',
|
|
65
|
+
normalised: normalisedName,
|
|
66
|
+
isShort: isETH && is2LD ? isShort : false,
|
|
67
|
+
isValid,
|
|
68
|
+
is2LD,
|
|
69
|
+
isETH,
|
|
70
|
+
labelDataArray,
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var getRecords_exports = {};
|
|
20
|
-
__export(getRecords_exports, {
|
|
21
|
-
default: () => getRecords_default
|
|
22
|
-
});
|
|
23
|
-
module.exports = __toCommonJS(getRecords_exports);
|
|
24
|
-
var import_validation = require("../utils/validation");
|
|
25
|
-
async function getRecords_default({ getProfile }, name, options) {
|
|
26
|
-
const inputType = (0, import_validation.parseInputType)(name);
|
|
27
|
-
if (inputType.type !== "name" && inputType.type !== "label") {
|
|
28
|
-
throw new Error("Input must be an ENS name");
|
|
29
|
-
}
|
|
30
|
-
return getProfile(name, options);
|
|
31
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// src/functions/getRecords.ts
|
|
2
|
-
import { parseInputType } from "../utils/validation.mjs";
|
|
3
|
-
async function getRecords_default({ getProfile }, name, options) {
|
|
4
|
-
const inputType = parseInputType(name);
|
|
5
|
-
if (inputType.type !== "name" && inputType.type !== "label") {
|
|
6
|
-
throw new Error("Input must be an ENS name");
|
|
7
|
-
}
|
|
8
|
-
return getProfile(name, options);
|
|
9
|
-
}
|
|
10
|
-
export {
|
|
11
|
-
getRecords_default as default
|
|
12
|
-
};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { ENSArgs } from '..';
|
|
2
|
-
declare type ProfileOptions = {
|
|
3
|
-
contentHash?: boolean;
|
|
4
|
-
texts?: boolean | string[];
|
|
5
|
-
coinTypes?: boolean | string[];
|
|
6
|
-
resolverAddress?: string;
|
|
7
|
-
};
|
|
8
|
-
export default function ({ getProfile }: ENSArgs<'getProfile'>, name: string, options?: ProfileOptions): Promise<{
|
|
9
|
-
isMigrated: boolean | null;
|
|
10
|
-
createdAt: string | null;
|
|
11
|
-
address?: string | undefined;
|
|
12
|
-
name?: string | null | undefined;
|
|
13
|
-
decryptedName?: string | null | undefined;
|
|
14
|
-
match?: boolean | undefined;
|
|
15
|
-
message?: string | undefined;
|
|
16
|
-
records?: {
|
|
17
|
-
contentHash?: string | import("../utils/contentHash").DecodedContentHash | null | undefined;
|
|
18
|
-
texts?: {
|
|
19
|
-
key: string | number;
|
|
20
|
-
type: "text" | "addr" | "contentHash";
|
|
21
|
-
coin?: string | undefined;
|
|
22
|
-
value: string;
|
|
23
|
-
}[] | undefined;
|
|
24
|
-
coinTypes?: {
|
|
25
|
-
key: string | number;
|
|
26
|
-
type: "text" | "addr" | "contentHash";
|
|
27
|
-
coin?: string | undefined;
|
|
28
|
-
value: string;
|
|
29
|
-
}[] | undefined;
|
|
30
|
-
} | undefined;
|
|
31
|
-
resolverAddress?: string | undefined;
|
|
32
|
-
isInvalidResolverAddress?: boolean | undefined;
|
|
33
|
-
reverseResolverAddress?: string | undefined;
|
|
34
|
-
} | undefined>;
|
|
35
|
-
export {};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { ENSArgs } from '..'
|
|
2
|
-
import { parseInputType } from '../utils/validation'
|
|
3
|
-
|
|
4
|
-
type ProfileOptions = {
|
|
5
|
-
contentHash?: boolean
|
|
6
|
-
texts?: boolean | string[]
|
|
7
|
-
coinTypes?: boolean | string[]
|
|
8
|
-
resolverAddress?: string
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export default async function (
|
|
12
|
-
{ getProfile }: ENSArgs<'getProfile'>,
|
|
13
|
-
name: string,
|
|
14
|
-
options?: ProfileOptions,
|
|
15
|
-
) {
|
|
16
|
-
const inputType = parseInputType(name)
|
|
17
|
-
|
|
18
|
-
if (inputType.type !== 'name' && inputType.type !== 'label') {
|
|
19
|
-
throw new Error('Input must be an ENS name')
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return getProfile(name, options)
|
|
23
|
-
}
|