@metamask/ens-controller 1.0.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [1.0.0]
10
+ ### Added
11
+ - Initial release
12
+ - As a result of converting our shared controllers repo into a monorepo ([#831](https://github.com/MetaMask/controllers/pull/831)), we've created this package from select parts of [`@metamask/controllers` v33.0.0](https://github.com/MetaMask/controllers/tree/v33.0.0), namely:
13
+ - `src/third-party/EnsController.ts`
14
+ - `src/third-party/EnsController.test.ts`
15
+
16
+ All changes listed after this point were applied to this package following the monorepo conversion.
17
+
18
+ [Unreleased]: https://github.com/MetaMask/controllers/compare/@metamask/ens-controller@1.0.0...HEAD
19
+ [1.0.0]: https://github.com/MetaMask/controllers/releases/tag/@metamask/ens-controller@1.0.0
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 MetaMask
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # `@metamask/ens-controller`
2
+
3
+ Maps ENS names to their resolved addresses by chain id.
4
+
5
+ ## Installation
6
+
7
+ `yarn add @metamask/ens-controller`
8
+
9
+ or
10
+
11
+ `npm install @metamask/ens-controller`
12
+
13
+ ## Contributing
14
+
15
+ This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/controllers#readme).
@@ -0,0 +1,76 @@
1
+ import { BaseController, BaseConfig, BaseState } from '@metamask/base-controller';
2
+ /**
3
+ * @type EnsEntry
4
+ *
5
+ * ENS entry representation
6
+ * @property chainId - Id of the associated chain
7
+ * @property ensName - The ENS name
8
+ * @property address - Hex address with the ENS name, or null
9
+ */
10
+ export interface EnsEntry {
11
+ chainId: string;
12
+ ensName: string;
13
+ address: string | null;
14
+ }
15
+ /**
16
+ * @type EnsState
17
+ *
18
+ * ENS controller state
19
+ * @property ensEntries - Object of ENS entry objects
20
+ */
21
+ export interface EnsState extends BaseState {
22
+ ensEntries: {
23
+ [chainId: string]: {
24
+ [ensName: string]: EnsEntry;
25
+ };
26
+ };
27
+ }
28
+ /**
29
+ * Controller that manages a list ENS names and their resolved addresses
30
+ * by chainId. A null address indicates an unresolved ENS name.
31
+ */
32
+ export declare class EnsController extends BaseController<BaseConfig, EnsState> {
33
+ /**
34
+ * Name of this controller used during composition
35
+ */
36
+ name: string;
37
+ /**
38
+ * Creates an EnsController instance.
39
+ *
40
+ * @param config - Initial options used to configure this controller.
41
+ * @param state - Initial state to set on this controller.
42
+ */
43
+ constructor(config?: Partial<BaseConfig>, state?: Partial<EnsState>);
44
+ /**
45
+ * Remove all chain Ids and ENS entries from state.
46
+ */
47
+ clear(): void;
48
+ /**
49
+ * Delete an ENS entry.
50
+ *
51
+ * @param chainId - Parent chain of the ENS entry to delete.
52
+ * @param ensName - Name of the ENS entry to delete.
53
+ * @returns Boolean indicating if the entry was deleted.
54
+ */
55
+ delete(chainId: string, ensName: string): boolean;
56
+ /**
57
+ * Retrieve a DNS entry.
58
+ *
59
+ * @param chainId - Parent chain of the ENS entry to retrieve.
60
+ * @param ensName - Name of the ENS entry to retrieve.
61
+ * @returns The EnsEntry or null if it does not exist.
62
+ */
63
+ get(chainId: string, ensName: string): EnsEntry | null;
64
+ /**
65
+ * Add or update an ENS entry by chainId and ensName.
66
+ *
67
+ * A null address indicates that the ENS name does not resolve.
68
+ *
69
+ * @param chainId - Id of the associated chain.
70
+ * @param ensName - The ENS name.
71
+ * @param address - Associated address (or null) to add or update.
72
+ * @returns Boolean indicating if the entry was set.
73
+ */
74
+ set(chainId: string, ensName: string, address: string | null): boolean;
75
+ }
76
+ export default EnsController;
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EnsController = void 0;
4
+ const base_controller_1 = require("@metamask/base-controller");
5
+ const controller_utils_1 = require("@metamask/controller-utils");
6
+ /**
7
+ * Controller that manages a list ENS names and their resolved addresses
8
+ * by chainId. A null address indicates an unresolved ENS name.
9
+ */
10
+ class EnsController extends base_controller_1.BaseController {
11
+ /**
12
+ * Creates an EnsController instance.
13
+ *
14
+ * @param config - Initial options used to configure this controller.
15
+ * @param state - Initial state to set on this controller.
16
+ */
17
+ constructor(config, state) {
18
+ super(config, state);
19
+ /**
20
+ * Name of this controller used during composition
21
+ */
22
+ this.name = 'EnsController';
23
+ this.defaultState = { ensEntries: {} };
24
+ this.initialize();
25
+ }
26
+ /**
27
+ * Remove all chain Ids and ENS entries from state.
28
+ */
29
+ clear() {
30
+ this.update({ ensEntries: {} });
31
+ }
32
+ /**
33
+ * Delete an ENS entry.
34
+ *
35
+ * @param chainId - Parent chain of the ENS entry to delete.
36
+ * @param ensName - Name of the ENS entry to delete.
37
+ * @returns Boolean indicating if the entry was deleted.
38
+ */
39
+ delete(chainId, ensName) {
40
+ const normalizedEnsName = (0, controller_utils_1.normalizeEnsName)(ensName);
41
+ if (!normalizedEnsName ||
42
+ !this.state.ensEntries[chainId] ||
43
+ !this.state.ensEntries[chainId][normalizedEnsName]) {
44
+ return false;
45
+ }
46
+ const ensEntries = Object.assign({}, this.state.ensEntries);
47
+ delete ensEntries[chainId][normalizedEnsName];
48
+ if (Object.keys(ensEntries[chainId]).length === 0) {
49
+ delete ensEntries[chainId];
50
+ }
51
+ this.update({ ensEntries });
52
+ return true;
53
+ }
54
+ /**
55
+ * Retrieve a DNS entry.
56
+ *
57
+ * @param chainId - Parent chain of the ENS entry to retrieve.
58
+ * @param ensName - Name of the ENS entry to retrieve.
59
+ * @returns The EnsEntry or null if it does not exist.
60
+ */
61
+ get(chainId, ensName) {
62
+ const normalizedEnsName = (0, controller_utils_1.normalizeEnsName)(ensName);
63
+ // TODO Explicitly handle the case where `normalizedEnsName` is `null`
64
+ // eslint-disable-next-line no-implicit-coercion
65
+ return !!normalizedEnsName && this.state.ensEntries[chainId]
66
+ ? this.state.ensEntries[chainId][normalizedEnsName] || null
67
+ : null;
68
+ }
69
+ /**
70
+ * Add or update an ENS entry by chainId and ensName.
71
+ *
72
+ * A null address indicates that the ENS name does not resolve.
73
+ *
74
+ * @param chainId - Id of the associated chain.
75
+ * @param ensName - The ENS name.
76
+ * @param address - Associated address (or null) to add or update.
77
+ * @returns Boolean indicating if the entry was set.
78
+ */
79
+ set(chainId, ensName, address) {
80
+ if (!Number.isInteger(Number.parseInt(chainId, 10)) ||
81
+ !ensName ||
82
+ typeof ensName !== 'string' ||
83
+ (address && !(0, controller_utils_1.isValidHexAddress)(address))) {
84
+ throw new Error(`Invalid ENS entry: { chainId:${chainId}, ensName:${ensName}, address:${address}}`);
85
+ }
86
+ const normalizedEnsName = (0, controller_utils_1.normalizeEnsName)(ensName);
87
+ if (!normalizedEnsName) {
88
+ throw new Error(`Invalid ENS name: ${ensName}`);
89
+ }
90
+ const normalizedAddress = address ? (0, controller_utils_1.toChecksumHexAddress)(address) : null;
91
+ const subState = this.state.ensEntries[chainId];
92
+ if ((subState === null || subState === void 0 ? void 0 : subState[normalizedEnsName]) &&
93
+ subState[normalizedEnsName].address === normalizedAddress) {
94
+ return false;
95
+ }
96
+ this.update({
97
+ ensEntries: Object.assign(Object.assign({}, this.state.ensEntries), { [chainId]: Object.assign(Object.assign({}, this.state.ensEntries[chainId]), { [normalizedEnsName]: {
98
+ address: normalizedAddress,
99
+ chainId,
100
+ ensName: normalizedEnsName,
101
+ } }) }),
102
+ });
103
+ return true;
104
+ }
105
+ }
106
+ exports.EnsController = EnsController;
107
+ exports.default = EnsController;
108
+ //# sourceMappingURL=EnsController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EnsController.js","sourceRoot":"","sources":["../src/EnsController.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BaseController,\n BaseConfig,\n BaseState,\n} from '@metamask/base-controller';\nimport {\n normalizeEnsName,\n isValidHexAddress,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\n\n/**\n * @type EnsEntry\n *\n * ENS entry representation\n * @property chainId - Id of the associated chain\n * @property ensName - The ENS name\n * @property address - Hex address with the ENS name, or null\n */\nexport interface EnsEntry {\n chainId: string;\n ensName: string;\n address: string | null;\n}\n\n/**\n * @type EnsState\n *\n * ENS controller state\n * @property ensEntries - Object of ENS entry objects\n */\nexport interface EnsState extends BaseState {\n ensEntries: { [chainId: string]: { [ensName: string]: EnsEntry } };\n}\n\n/**\n * Controller that manages a list ENS names and their resolved addresses\n * by chainId. A null address indicates an unresolved ENS name.\n */\nexport class EnsController extends BaseController<BaseConfig, EnsState> {\n /**\n * Name of this controller used during composition\n */\n override name = 'EnsController';\n\n /**\n * Creates an EnsController instance.\n *\n * @param config - Initial options used to configure this controller.\n * @param state - Initial state to set on this controller.\n */\n constructor(config?: Partial<BaseConfig>, state?: Partial<EnsState>) {\n super(config, state);\n\n this.defaultState = { ensEntries: {} };\n\n this.initialize();\n }\n\n /**\n * Remove all chain Ids and ENS entries from state.\n */\n clear() {\n this.update({ ensEntries: {} });\n }\n\n /**\n * Delete an ENS entry.\n *\n * @param chainId - Parent chain of the ENS entry to delete.\n * @param ensName - Name of the ENS entry to delete.\n * @returns Boolean indicating if the entry was deleted.\n */\n delete(chainId: string, ensName: string): boolean {\n const normalizedEnsName = normalizeEnsName(ensName);\n if (\n !normalizedEnsName ||\n !this.state.ensEntries[chainId] ||\n !this.state.ensEntries[chainId][normalizedEnsName]\n ) {\n return false;\n }\n\n const ensEntries = Object.assign({}, this.state.ensEntries);\n delete ensEntries[chainId][normalizedEnsName];\n\n if (Object.keys(ensEntries[chainId]).length === 0) {\n delete ensEntries[chainId];\n }\n\n this.update({ ensEntries });\n return true;\n }\n\n /**\n * Retrieve a DNS entry.\n *\n * @param chainId - Parent chain of the ENS entry to retrieve.\n * @param ensName - Name of the ENS entry to retrieve.\n * @returns The EnsEntry or null if it does not exist.\n */\n get(chainId: string, ensName: string): EnsEntry | null {\n const normalizedEnsName = normalizeEnsName(ensName);\n\n // TODO Explicitly handle the case where `normalizedEnsName` is `null`\n // eslint-disable-next-line no-implicit-coercion\n return !!normalizedEnsName && this.state.ensEntries[chainId]\n ? this.state.ensEntries[chainId][normalizedEnsName] || null\n : null;\n }\n\n /**\n * Add or update an ENS entry by chainId and ensName.\n *\n * A null address indicates that the ENS name does not resolve.\n *\n * @param chainId - Id of the associated chain.\n * @param ensName - The ENS name.\n * @param address - Associated address (or null) to add or update.\n * @returns Boolean indicating if the entry was set.\n */\n set(chainId: string, ensName: string, address: string | null): boolean {\n if (\n !Number.isInteger(Number.parseInt(chainId, 10)) ||\n !ensName ||\n typeof ensName !== 'string' ||\n (address && !isValidHexAddress(address))\n ) {\n throw new Error(\n `Invalid ENS entry: { chainId:${chainId}, ensName:${ensName}, address:${address}}`,\n );\n }\n\n const normalizedEnsName = normalizeEnsName(ensName);\n if (!normalizedEnsName) {\n throw new Error(`Invalid ENS name: ${ensName}`);\n }\n\n const normalizedAddress = address ? toChecksumHexAddress(address) : null;\n const subState = this.state.ensEntries[chainId];\n\n if (\n subState?.[normalizedEnsName] &&\n subState[normalizedEnsName].address === normalizedAddress\n ) {\n return false;\n }\n\n this.update({\n ensEntries: {\n ...this.state.ensEntries,\n [chainId]: {\n ...this.state.ensEntries[chainId],\n [normalizedEnsName]: {\n address: normalizedAddress,\n chainId,\n ensName: normalizedEnsName,\n },\n },\n },\n });\n return true;\n }\n}\n\nexport default EnsController;\n"]}
@@ -0,0 +1 @@
1
+ export * from './EnsController';
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./EnsController"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC","sourcesContent":["export * from './EnsController';\n"]}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@metamask/ens-controller",
3
+ "version": "1.0.0",
4
+ "description": "Maps ENS names to their resolved addresses by chain id",
5
+ "keywords": [
6
+ "MetaMask",
7
+ "Ethereum"
8
+ ],
9
+ "homepage": "https://github.com/MetaMask/controllers/tree/main/packages/ens-controller#readme",
10
+ "bugs": {
11
+ "url": "https://github.com/MetaMask/controllers/issues"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/MetaMask/controllers.git"
16
+ },
17
+ "license": "MIT",
18
+ "main": "./dist/index.js",
19
+ "types": "./dist/index.d.ts",
20
+ "files": [
21
+ "dist/"
22
+ ],
23
+ "scripts": {
24
+ "build:docs": "typedoc",
25
+ "changelog:validate": "../../scripts/validate-changelog.sh @metamask/ens-controller",
26
+ "prepare-manifest:preview": "../../scripts/prepare-preview-manifest.sh",
27
+ "publish:preview": "yarn npm publish --tag preview",
28
+ "test": "jest",
29
+ "test:watch": "jest --watch"
30
+ },
31
+ "dependencies": {
32
+ "@metamask/base-controller": "~1.0.0",
33
+ "@metamask/controller-utils": "~1.0.0"
34
+ },
35
+ "devDependencies": {
36
+ "@metamask/auto-changelog": "^3.1.0",
37
+ "@types/jest": "^26.0.22",
38
+ "deepmerge": "^4.2.2",
39
+ "jest": "^26.4.2",
40
+ "ts-jest": "^26.5.2",
41
+ "typedoc": "^0.22.15",
42
+ "typedoc-plugin-missing-exports": "^0.22.6",
43
+ "typescript": "~4.6.3"
44
+ },
45
+ "engines": {
46
+ "node": ">=14.0.0"
47
+ },
48
+ "publishConfig": {
49
+ "access": "public",
50
+ "registry": "https://registry.npmjs.org/"
51
+ }
52
+ }