@metamask/name-controller 1.0.0 → 2.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 CHANGED
@@ -6,9 +6,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.0.0]
10
+ ### Changed
11
+ - **BREAKING**: Support rate limiting in name providers ([#1715](https://github.com/MetaMask/core/pull/1715))
12
+ - Breaking changes:
13
+ - Change `proposedNames` property in `NameEntry` type from string array to new `ProposedNamesEntry` type
14
+ - Remove `proposedNamesLastUpdated` property from `NameEntry` type
15
+ - Add `onlyUpdateAfterDelay` option to `UpdateProposedNamesRequest` type
16
+ - Add `updateDelay` constructor option
17
+ - Add `updateDelay` property to `NameProviderSourceResult` type
18
+ - Add `isEnabled` callback option to `ENSNameProvider`, `EtherscanNameProvider`, `LensNameProvider`, and `TokenNameProvider`
19
+ - Existing proposed names in state are only updated if the `NameProvider` has no errors and the `proposedNames` property is not `undefined`
20
+ - Dormant proposed names are automatically removed when calling `updateProposedNames` ([#1688](https://github.com/MetaMask/core/pull/1688))
21
+ - The `setName` method accepts a `null` value for the `name` property to enable removing saved names ([#1688](https://github.com/MetaMask/core/pull/1688))
22
+ - Update TypeScript to v4.8.x ([#1718](https://github.com/MetaMask/core/pull/1718))
23
+
9
24
  ## [1.0.0]
10
25
  ### Added
11
26
  - Initial Release ([#1647](https://github.com/MetaMask/core/pull/1647))
12
27
 
13
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/name-controller@1.0.0...HEAD
28
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/name-controller@2.0.0...HEAD
29
+ [2.0.0]: https://github.com/MetaMask/core/compare/@metamask/name-controller@1.0.0...@metamask/name-controller@2.0.0
14
30
  [1.0.0]: https://github.com/MetaMask/core/releases/tag/@metamask/name-controller@1.0.0
@@ -4,11 +4,15 @@ import type { Patch } from 'immer';
4
4
  import type { NameProvider } from './types';
5
5
  import { NameType } from './types';
6
6
  declare const controllerName = "NameController";
7
+ export declare type ProposedNamesEntry = {
8
+ proposedNames: string[];
9
+ lastRequestTime: number | null;
10
+ updateDelay: number | null;
11
+ };
7
12
  export declare type NameEntry = {
8
13
  name: string | null;
9
14
  sourceId: string | null;
10
- proposedNames: Record<string, string[] | null>;
11
- proposedNamesLastUpdated: number | null;
15
+ proposedNames: Record<string, ProposedNamesEntry>;
12
16
  };
13
17
  export declare type SourceEntry = {
14
18
  label: string;
@@ -33,11 +37,13 @@ export declare type NameControllerOptions = {
33
37
  messenger: NameControllerMessenger;
34
38
  providers: NameProvider[];
35
39
  state?: Partial<NameControllerState>;
40
+ updateDelay?: number;
36
41
  };
37
42
  export declare type UpdateProposedNamesRequest = {
38
43
  value: string;
39
44
  type: NameType;
40
45
  sourceIds?: string[];
46
+ onlyUpdateAfterDelay?: boolean;
41
47
  };
42
48
  export declare type UpdateProposedNamesResult = {
43
49
  results: Record<string, {
@@ -48,7 +54,7 @@ export declare type UpdateProposedNamesResult = {
48
54
  export declare type SetNameRequest = {
49
55
  value: string;
50
56
  type: NameType;
51
- name: string;
57
+ name: string | null;
52
58
  sourceId?: string;
53
59
  };
54
60
  /**
@@ -64,8 +70,9 @@ export declare class NameController extends BaseControllerV2<typeof controllerNa
64
70
  * @param options.messenger - Restricted controller messenger for the name controller.
65
71
  * @param options.providers - Array of name provider instances to propose names.
66
72
  * @param options.state - Initial state to set on the controller.
73
+ * @param options.updateDelay - The delay in seconds before a new request to a source should be made.
67
74
  */
68
- constructor({ getChainId, messenger, providers, state, }: NameControllerOptions);
75
+ constructor({ getChainId, messenger, providers, state, updateDelay, }: NameControllerOptions);
69
76
  /**
70
77
  * Set the user specified name for a value.
71
78
  *
@@ -1 +1 @@
1
- {"version":3,"file":"NameController.d.ts","sourceRoot":"","sources":["../src/NameController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAEnC,OAAO,KAAK,EACV,YAAY,EAGb,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,QAAA,MAAM,cAAc,mBAAmB,CAAC;AAcxC,oBAAY,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;IAC/C,wBAAwB,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC,CAAC;AAEF,oBAAY,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,oBAAY,mBAAmB,GAAG;IAEhC,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IACnE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CAC1C,CAAC;AAEF,oBAAY,YAAY,GAAG;IACzB,IAAI,EAAE,GAAG,OAAO,cAAc,WAAW,CAAC;IAC1C,OAAO,EAAE,MAAM,mBAAmB,CAAC;CACpC,CAAC;AAEF,oBAAY,eAAe,GAAG;IAC5B,IAAI,EAAE,GAAG,OAAO,cAAc,cAAc,CAAC;IAC7C,OAAO,EAAE,CAAC,mBAAmB,EAAE,KAAK,EAAE,CAAC,CAAC;CACzC,CAAC;AAEF,oBAAY,qBAAqB,GAAG,YAAY,CAAC;AAEjD,oBAAY,oBAAoB,GAAG,eAAe,CAAC;AAEnD,oBAAY,uBAAuB,GAAG,6BAA6B,CACjE,OAAO,cAAc,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,KAAK,EACL,KAAK,CACN,CAAC;AAEF,oBAAY,qBAAqB,GAAG;IAClC,UAAU,EAAE,MAAM,MAAM,CAAC;IACzB,SAAS,EAAE,uBAAuB,CAAC;IACnC,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;CACtC,CAAC;AAEF,oBAAY,0BAA0B,GAAG;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAEF,oBAAY,yBAAyB,GAAG;IACtC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACxE,CAAC;AAEF,oBAAY,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,qBAAa,cAAe,SAAQ,gBAAgB,CAClD,OAAO,cAAc,EACrB,mBAAmB,EACnB,uBAAuB,CACxB;;IAKC;;;;;;;;OAQG;gBACS,EACV,UAAU,EACV,SAAS,EACT,SAAS,EACT,KAAK,GACN,EAAE,qBAAqB;IAYxB;;;;;;;;OAQG;IACH,OAAO,CAAC,OAAO,EAAE,cAAc;IAQ/B;;;;;;;;OAQG;IACG,mBAAmB,CACvB,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,yBAAyB,CAAC;CAgVtC"}
1
+ {"version":3,"file":"NameController.d.ts","sourceRoot":"","sources":["../src/NameController.ts"],"names":[],"mappings":"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"}
@@ -19,11 +19,12 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
19
19
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
20
20
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
21
21
  };
22
- var _NameController_instances, _NameController_getChainId, _NameController_providers, _NameController_updateProposedNameState, _NameController_updateSourceState, _NameController_getUpdateProposedNamesResult, _NameController_getProviderResponse, _NameController_updateEntry, _NameController_getTypeVariationKey, _NameController_getCurrentTimeSeconds, _NameController_validateSetNameRequest, _NameController_validateUpdateProposedNamesRequest, _NameController_validateValue, _NameController_validateType, _NameController_validateName, _NameController_validateSourceIds, _NameController_validateSourceId, _NameController_validateDuplicateSourceIds, _NameController_getAllSourceIds, _NameController_getSourceIds;
22
+ var _NameController_instances, _NameController_getChainId, _NameController_providers, _NameController_updateDelay, _NameController_updateProposedNameState, _NameController_updateSourceState, _NameController_getUpdateProposedNamesResult, _NameController_getProviderResponse, _NameController_normalizeProviderResult, _NameController_normalizeProviderSourceResult, _NameController_updateEntry, _NameController_getTypeVariationKey, _NameController_getCurrentTimeSeconds, _NameController_validateSetNameRequest, _NameController_validateUpdateProposedNamesRequest, _NameController_validateValue, _NameController_validateType, _NameController_validateName, _NameController_validateSourceIds, _NameController_validateSourceId, _NameController_validateDuplicateSourceIds, _NameController_getAllSourceIds, _NameController_getSourceIds, _NameController_removeDormantProposedNames;
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
24
  exports.NameController = void 0;
25
25
  const base_controller_1 = require("@metamask/base-controller");
26
26
  const types_1 = require("./types");
27
+ const DEFAULT_UPDATE_DELAY = 60 * 2; // 2 Minutes
27
28
  const controllerName = 'NameController';
28
29
  const stateMetadata = {
29
30
  names: { persist: true, anonymous: false },
@@ -47,8 +48,9 @@ class NameController extends base_controller_1.BaseControllerV2 {
47
48
  * @param options.messenger - Restricted controller messenger for the name controller.
48
49
  * @param options.providers - Array of name provider instances to propose names.
49
50
  * @param options.state - Initial state to set on the controller.
51
+ * @param options.updateDelay - The delay in seconds before a new request to a source should be made.
50
52
  */
51
- constructor({ getChainId, messenger, providers, state, }) {
53
+ constructor({ getChainId, messenger, providers, state, updateDelay, }) {
52
54
  super({
53
55
  name: controllerName,
54
56
  metadata: stateMetadata,
@@ -58,8 +60,10 @@ class NameController extends base_controller_1.BaseControllerV2 {
58
60
  _NameController_instances.add(this);
59
61
  _NameController_getChainId.set(this, void 0);
60
62
  _NameController_providers.set(this, void 0);
63
+ _NameController_updateDelay.set(this, void 0);
61
64
  __classPrivateFieldSet(this, _NameController_getChainId, getChainId, "f");
62
65
  __classPrivateFieldSet(this, _NameController_providers, providers, "f");
66
+ __classPrivateFieldSet(this, _NameController_updateDelay, updateDelay !== null && updateDelay !== void 0 ? updateDelay : DEFAULT_UPDATE_DELAY, "f");
63
67
  }
64
68
  /**
65
69
  * Set the user specified name for a value.
@@ -72,8 +76,12 @@ class NameController extends base_controller_1.BaseControllerV2 {
72
76
  */
73
77
  setName(request) {
74
78
  __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_validateSetNameRequest).call(this, request);
75
- const { value, type, name, sourceId } = request;
76
- __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_updateEntry).call(this, value, type, { name, sourceId: sourceId !== null && sourceId !== void 0 ? sourceId : null });
79
+ const { value, type, name, sourceId: requestSourceId } = request;
80
+ const sourceId = requestSourceId !== null && requestSourceId !== void 0 ? requestSourceId : null;
81
+ __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_updateEntry).call(this, value, type, (entry) => {
82
+ entry.name = name;
83
+ entry.sourceId = sourceId;
84
+ });
77
85
  }
78
86
  /**
79
87
  * Generate the proposed names for a value using the name providers and store them in the state.
@@ -96,30 +104,31 @@ class NameController extends base_controller_1.BaseControllerV2 {
96
104
  }
97
105
  }
98
106
  exports.NameController = NameController;
99
- _NameController_getChainId = new WeakMap(), _NameController_providers = new WeakMap(), _NameController_instances = new WeakSet(), _NameController_updateProposedNameState = function _NameController_updateProposedNameState(request, providerResponses) {
100
- var _a, _b, _c;
107
+ _NameController_getChainId = new WeakMap(), _NameController_providers = new WeakMap(), _NameController_updateDelay = new WeakMap(), _NameController_instances = new WeakSet(), _NameController_updateProposedNameState = function _NameController_updateProposedNameState(request, providerResponses) {
101
108
  const { value, type } = request;
102
- const newProposedNames = {};
103
- for (const providerResponse of providerResponses) {
104
- const { results, error: responseError } = providerResponse;
105
- if (responseError) {
106
- continue;
107
- }
108
- for (const sourceId of Object.keys(providerResponse.results)) {
109
- const result = results[sourceId];
110
- const { proposedNames } = result;
111
- let finalProposedNames = result.error ? null : proposedNames !== null && proposedNames !== void 0 ? proposedNames : [];
112
- if (finalProposedNames) {
113
- finalProposedNames = finalProposedNames.filter((proposedName) => proposedName === null || proposedName === void 0 ? void 0 : proposedName.length);
109
+ const currentTime = __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_getCurrentTimeSeconds).call(this);
110
+ __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_updateEntry).call(this, value, type, (entry) => {
111
+ var _a;
112
+ __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_removeDormantProposedNames).call(this, entry.proposedNames, type);
113
+ for (const providerResponse of providerResponses) {
114
+ const { results } = providerResponse;
115
+ for (const sourceId of Object.keys(providerResponse.results)) {
116
+ const result = results[sourceId];
117
+ const { proposedNames, updateDelay } = result;
118
+ const proposedNameEntry = (_a = entry.proposedNames[sourceId]) !== null && _a !== void 0 ? _a : {
119
+ proposedNames: [],
120
+ lastRequestTime: null,
121
+ updateDelay: null,
122
+ };
123
+ entry.proposedNames[sourceId] = proposedNameEntry;
124
+ if (proposedNames) {
125
+ proposedNameEntry.proposedNames = proposedNames;
126
+ }
127
+ proposedNameEntry.lastRequestTime = currentTime;
128
+ proposedNameEntry.updateDelay = updateDelay !== null && updateDelay !== void 0 ? updateDelay : null;
114
129
  }
115
- newProposedNames[sourceId] = finalProposedNames;
116
130
  }
117
- }
118
- const variationKey = __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_getTypeVariationKey).call(this, type);
119
- const existingProposedNames = (_c = (_b = (_a = this.state.names[type]) === null || _a === void 0 ? void 0 : _a[value]) === null || _b === void 0 ? void 0 : _b[variationKey]) === null || _c === void 0 ? void 0 : _c.proposedNames;
120
- const proposedNames = Object.assign(Object.assign({}, existingProposedNames), newProposedNames);
121
- const proposedNamesLastUpdated = __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_getCurrentTimeSeconds).call(this);
122
- __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_updateEntry).call(this, value, type, { proposedNames, proposedNamesLastUpdated });
131
+ });
123
132
  }, _NameController_updateSourceState = function _NameController_updateSourceState(providers) {
124
133
  const newNameSources = Object.assign({}, this.state.nameSources);
125
134
  for (const provider of providers) {
@@ -137,27 +146,37 @@ _NameController_getChainId = new WeakMap(), _NameController_providers = new Weak
137
146
  return providerResponses.reduce((acc, providerResponse) => {
138
147
  const { results } = providerResponse;
139
148
  for (const sourceId of Object.keys(results)) {
140
- const { proposedNames: resultProposedNames, error: resultError } = results[sourceId];
141
- let proposedNames = resultError
142
- ? undefined
143
- : resultProposedNames !== null && resultProposedNames !== void 0 ? resultProposedNames : [];
144
- if (proposedNames) {
145
- proposedNames = proposedNames.filter((proposedName) => proposedName === null || proposedName === void 0 ? void 0 : proposedName.length);
146
- }
149
+ const { proposedNames, error } = results[sourceId];
147
150
  acc.results[sourceId] = {
148
151
  proposedNames,
149
- error: resultError,
152
+ error,
150
153
  };
151
154
  }
152
155
  return acc;
153
156
  }, { results: {} });
154
157
  }, _NameController_getProviderResponse = function _NameController_getProviderResponse(request, chainId, provider) {
155
- var _a;
156
158
  return __awaiter(this, void 0, void 0, function* () {
157
- const { value, type, sourceIds: requestedSourceIds } = request;
159
+ const { value, type, sourceIds: requestedSourceIds, onlyUpdateAfterDelay, } = request;
160
+ const variationKey = __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_getTypeVariationKey).call(this, type);
158
161
  const supportedSourceIds = __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_getSourceIds).call(this, provider, type);
159
- const matchingSourceIds = (_a = requestedSourceIds === null || requestedSourceIds === void 0 ? void 0 : requestedSourceIds.filter((sourceId) => supportedSourceIds.includes(sourceId))) !== null && _a !== void 0 ? _a : supportedSourceIds;
160
- if (requestedSourceIds && !matchingSourceIds.length) {
162
+ const currentTime = __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_getCurrentTimeSeconds).call(this);
163
+ const matchingSourceIds = supportedSourceIds.filter((sourceId) => {
164
+ var _a, _b, _c, _d, _e, _f, _g;
165
+ if (requestedSourceIds && !requestedSourceIds.includes(sourceId)) {
166
+ return false;
167
+ }
168
+ if (onlyUpdateAfterDelay) {
169
+ const entry = (_c = (_b = (_a = this.state.names[type]) === null || _a === void 0 ? void 0 : _a[value]) === null || _b === void 0 ? void 0 : _b[variationKey]) !== null && _c !== void 0 ? _c : {};
170
+ const proposedNamesEntry = (_e = (_d = entry.proposedNames) === null || _d === void 0 ? void 0 : _d[sourceId]) !== null && _e !== void 0 ? _e : {};
171
+ const lastRequestTime = (_f = proposedNamesEntry.lastRequestTime) !== null && _f !== void 0 ? _f : 0;
172
+ const updateDelay = (_g = proposedNamesEntry.updateDelay) !== null && _g !== void 0 ? _g : __classPrivateFieldGet(this, _NameController_updateDelay, "f");
173
+ if (currentTime - lastRequestTime < updateDelay) {
174
+ return false;
175
+ }
176
+ }
177
+ return true;
178
+ });
179
+ if (!matchingSourceIds.length) {
161
180
  return undefined;
162
181
  }
163
182
  const providerRequest = {
@@ -175,24 +194,31 @@ _NameController_getChainId = new WeakMap(), _NameController_providers = new Weak
175
194
  catch (error) {
176
195
  responseError = error;
177
196
  }
178
- let results = {};
179
- if (response === null || response === void 0 ? void 0 : response.results) {
180
- results = Object.keys(response.results).reduce((acc, sourceId) => {
181
- if (!requestedSourceIds || requestedSourceIds.includes(sourceId)) {
182
- acc[sourceId] = response.results[sourceId];
183
- }
184
- return acc;
185
- }, {});
186
- }
187
- if (responseError) {
188
- results = supportedSourceIds.reduce((acc, sourceId) => {
189
- acc[sourceId] = { proposedNames: [], error: responseError };
190
- return acc;
191
- }, {});
192
- }
193
- return { results, error: responseError };
197
+ return __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_normalizeProviderResult).call(this, response, responseError, matchingSourceIds);
194
198
  });
195
- }, _NameController_updateEntry = function _NameController_updateEntry(value, type, data) {
199
+ }, _NameController_normalizeProviderResult = function _NameController_normalizeProviderResult(result, responseError, matchingSourceIds) {
200
+ const error = responseError !== null && responseError !== void 0 ? responseError : undefined;
201
+ const results = matchingSourceIds.reduce((acc, sourceId) => {
202
+ var _a;
203
+ const sourceResult = (_a = result === null || result === void 0 ? void 0 : result.results) === null || _a === void 0 ? void 0 : _a[sourceId];
204
+ const normalizedSourceResult = __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_normalizeProviderSourceResult).call(this, sourceResult, responseError);
205
+ return Object.assign(Object.assign({}, acc), { [sourceId]: normalizedSourceResult });
206
+ }, {});
207
+ return { results, error };
208
+ }, _NameController_normalizeProviderSourceResult = function _NameController_normalizeProviderSourceResult(result, responseError) {
209
+ var _a, _b, _c, _d;
210
+ const error = (_b = (_a = result === null || result === void 0 ? void 0 : result.error) !== null && _a !== void 0 ? _a : responseError) !== null && _b !== void 0 ? _b : undefined;
211
+ const updateDelay = (_c = result === null || result === void 0 ? void 0 : result.updateDelay) !== null && _c !== void 0 ? _c : undefined;
212
+ let proposedNames = error ? undefined : (_d = result === null || result === void 0 ? void 0 : result.proposedNames) !== null && _d !== void 0 ? _d : undefined;
213
+ if (proposedNames) {
214
+ proposedNames = proposedNames.filter((proposedName) => proposedName === null || proposedName === void 0 ? void 0 : proposedName.length);
215
+ }
216
+ return {
217
+ proposedNames,
218
+ error,
219
+ updateDelay,
220
+ };
221
+ }, _NameController_updateEntry = function _NameController_updateEntry(value, type, callback) {
196
222
  const variationKey = __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_getTypeVariationKey).call(this, type);
197
223
  this.update((state) => {
198
224
  var _a;
@@ -200,14 +226,13 @@ _NameController_getChainId = new WeakMap(), _NameController_providers = new Weak
200
226
  state.names[type] = typeEntries;
201
227
  const variationEntries = typeEntries[value] || {};
202
228
  typeEntries[value] = variationEntries;
203
- const currentEntry = (_a = variationEntries[variationKey]) !== null && _a !== void 0 ? _a : {
229
+ const entry = (_a = variationEntries[variationKey]) !== null && _a !== void 0 ? _a : {
204
230
  proposedNames: {},
205
- proposedNamesLastUpdated: null,
206
231
  name: null,
207
232
  sourceId: null,
208
233
  };
209
- const updatedEntry = Object.assign(Object.assign({}, currentEntry), data);
210
- variationEntries[variationKey] = updatedEntry;
234
+ variationEntries[variationKey] = entry;
235
+ callback(entry);
211
236
  });
212
237
  }, _NameController_getTypeVariationKey = function _NameController_getTypeVariationKey(type) {
213
238
  switch (type) {
@@ -223,7 +248,7 @@ _NameController_getChainId = new WeakMap(), _NameController_providers = new Weak
223
248
  __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_validateValue).call(this, value, errorMessages);
224
249
  __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_validateType).call(this, type, errorMessages);
225
250
  __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_validateName).call(this, name, errorMessages);
226
- __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_validateSourceId).call(this, sourceId, type, errorMessages);
251
+ __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_validateSourceId).call(this, sourceId, type, name, errorMessages);
227
252
  if (errorMessages.length) {
228
253
  throw new Error(errorMessages.join(' '));
229
254
  }
@@ -246,8 +271,11 @@ _NameController_getChainId = new WeakMap(), _NameController_providers = new Weak
246
271
  errorMessages.push(`Must specify one of the following types: ${Object.values(types_1.NameType).join(', ')}`);
247
272
  }
248
273
  }, _NameController_validateName = function _NameController_validateName(name, errorMessages) {
274
+ if (name === null) {
275
+ return;
276
+ }
249
277
  if (!(name === null || name === void 0 ? void 0 : name.length) || typeof name !== 'string') {
250
- errorMessages.push('Must specify a non-empty string for name.');
278
+ errorMessages.push('Must specify a non-empty string or null for name.');
251
279
  }
252
280
  }, _NameController_validateSourceIds = function _NameController_validateSourceIds(sourceIds, type, errorMessages) {
253
281
  if (!sourceIds) {
@@ -264,10 +292,14 @@ _NameController_getChainId = new WeakMap(), _NameController_providers = new Weak
264
292
  if (missingSourceIds.length) {
265
293
  errorMessages.push(`Unknown source IDs for type '${type}': ${missingSourceIds.join(', ')}`);
266
294
  }
267
- }, _NameController_validateSourceId = function _NameController_validateSourceId(sourceId, type, errorMessages) {
295
+ }, _NameController_validateSourceId = function _NameController_validateSourceId(sourceId, type, name, errorMessages) {
268
296
  if (sourceId === null || sourceId === undefined) {
269
297
  return;
270
298
  }
299
+ if (name === null) {
300
+ errorMessages.push(`Cannot specify a source ID when clearing the saved name: ${sourceId}`);
301
+ return;
302
+ }
271
303
  const allSourceIds = __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_getAllSourceIds).call(this, type);
272
304
  if (!sourceId.length || typeof sourceId !== 'string') {
273
305
  errorMessages.push('Must specify a non-empty string for sourceId.');
@@ -289,5 +321,14 @@ _NameController_getChainId = new WeakMap(), _NameController_providers = new Weak
289
321
  .flat());
290
322
  }, _NameController_getSourceIds = function _NameController_getSourceIds(provider, type) {
291
323
  return provider.getMetadata().sourceIds[type];
324
+ }, _NameController_removeDormantProposedNames = function _NameController_removeDormantProposedNames(proposedNames, type) {
325
+ if (Object.keys(proposedNames).length === 0) {
326
+ return;
327
+ }
328
+ const typeSourceIds = __classPrivateFieldGet(this, _NameController_instances, "m", _NameController_getAllSourceIds).call(this, type);
329
+ const dormantSourceIds = Object.keys(proposedNames).filter((sourceId) => !typeSourceIds.includes(sourceId));
330
+ for (const dormantSourceId of dormantSourceIds) {
331
+ delete proposedNames[dormantSourceId];
332
+ }
292
333
  };
293
334
  //# sourceMappingURL=NameController.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NameController.js","sourceRoot":"","sources":["../src/NameController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AACA,+DAA6D;AAQ7D,mCAAmC;AAEnC,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAExC,MAAM,aAAa,GAAG;IACpB,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE;IAC1C,WAAW,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE;CACjD,CAAC;AAEF,MAAM,eAAe,GAAG,GAAG,EAAE,CAAC,CAAC;IAC7B,KAAK,EAAE;QACL,CAAC,gBAAQ,CAAC,gBAAgB,CAAC,EAAE,EAAE;KAChC;IACD,WAAW,EAAE,EAAE;CAChB,CAAC,CAAC;AAiEH;;GAEG;AACH,MAAa,cAAe,SAAQ,kCAInC;IAKC;;;;;;;;OAQG;IACH,YAAY,EACV,UAAU,EACV,SAAS,EACT,SAAS,EACT,KAAK,GACiB;QACtB,KAAK,CAAC;YACJ,IAAI,EAAE,cAAc;YACpB,QAAQ,EAAE,aAAa;YACvB,SAAS;YACT,KAAK,kCAAO,eAAe,EAAE,GAAK,KAAK,CAAE;SAC1C,CAAC,CAAC;;QAxBL,6CAA0B;QAE1B,4CAA2B;QAwBzB,uBAAA,IAAI,8BAAe,UAAU,MAAA,CAAC;QAC9B,uBAAA,IAAI,6BAAc,SAAS,MAAA,CAAC;IAC9B,CAAC;IAED;;;;;;;;OAQG;IACH,OAAO,CAAC,OAAuB;QAC7B,uBAAA,IAAI,yEAAwB,MAA5B,IAAI,EAAyB,OAAO,CAAC,CAAC;QAEtC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;QAEhD,uBAAA,IAAI,8DAAa,MAAjB,IAAI,EAAc,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,aAAR,QAAQ,cAAR,QAAQ,GAAI,IAAI,EAAE,CAAC,CAAC;IACvE,CAAC;IAED;;;;;;;;OAQG;IACG,mBAAmB,CACvB,OAAmC;;YAEnC,uBAAA,IAAI,qFAAoC,MAAxC,IAAI,EAAqC,OAAO,CAAC,CAAC;YAElD,MAAM,OAAO,GAAG,uBAAA,IAAI,kCAAY,MAAhB,IAAI,CAAc,CAAC;YAEnC,MAAM,iBAAiB,GAAG,CACxB,MAAM,OAAO,CAAC,GAAG,CACf,uBAAA,IAAI,iCAAW,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAC/B,uBAAA,IAAI,sEAAqB,MAAzB,IAAI,EAAsB,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CACtD,CACF,CACF,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAyB,CAAC;YAElE,uBAAA,IAAI,0EAAyB,MAA7B,IAAI,EAA0B,OAAO,EAAE,iBAAiB,CAAC,CAAC;YAC1D,uBAAA,IAAI,oEAAmB,MAAvB,IAAI,EAAoB,uBAAA,IAAI,iCAAW,CAAC,CAAC;YAEzC,OAAO,uBAAA,IAAI,+EAA8B,MAAlC,IAAI,EAA+B,iBAAiB,CAAC,CAAC;QAC/D,CAAC;KAAA;CA+TF;AA/YD,wCA+YC;6NA5TG,OAAmC,EACnC,iBAAuC;;IAEvC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAChC,MAAM,gBAAgB,GAA4C,EAAE,CAAC;IAErE,KAAK,MAAM,gBAAgB,IAAI,iBAAiB,EAAE;QAChD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,gBAAgB,CAAC;QAE3D,IAAI,aAAa,EAAE;YACjB,SAAS;SACV;QAED,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE;YAC5D,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;YACjC,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC;YACjC,IAAI,kBAAkB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,aAAb,aAAa,cAAb,aAAa,GAAI,EAAE,CAAC;YAEnE,IAAI,kBAAkB,EAAE;gBACtB,kBAAkB,GAAG,kBAAkB,CAAC,MAAM,CAC5C,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,MAAM,CACvC,CAAC;aACH;YAED,gBAAgB,CAAC,QAAQ,CAAC,GAAG,kBAAkB,CAAC;SACjD;KACF;IAED,MAAM,YAAY,GAAG,uBAAA,IAAI,sEAAqB,MAAzB,IAAI,EAAsB,IAAI,CAAC,CAAC;IAErD,MAAM,qBAAqB,GACzB,MAAA,MAAA,MAAA,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,0CAAG,KAAK,CAAC,0CAAG,YAAY,CAAC,0CAAE,aAAa,CAAC;IAEjE,MAAM,aAAa,mCACd,qBAAqB,GACrB,gBAAgB,CACpB,CAAC;IAEF,MAAM,wBAAwB,GAAG,uBAAA,IAAI,wEAAuB,MAA3B,IAAI,CAAyB,CAAC;IAE/D,uBAAA,IAAI,8DAAa,MAAjB,IAAI,EAAc,KAAK,EAAE,IAAI,EAAE,EAAE,aAAa,EAAE,wBAAwB,EAAE,CAAC,CAAC;AAC9E,CAAC,iFAEkB,SAAyB;IAC1C,MAAM,cAAc,qBAAQ,IAAI,CAAC,KAAK,CAAC,WAAW,CAAE,CAAC;IAErD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE;QAChC,MAAM,EAAE,YAAY,EAAE,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;QAEhD,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE;YAChD,cAAc,CAAC,QAAQ,CAAC,GAAG;gBACzB,KAAK,EAAE,YAAY,CAAC,QAAQ,CAAC;aAC9B,CAAC;SACH;KACF;IAED,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QACpB,KAAK,CAAC,WAAW,GAAG,cAAc,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,uGAGC,iBAAuC;IAEvC,OAAO,iBAAiB,CAAC,MAAM,CAC7B,CAAC,GAA8B,EAAE,gBAAgB,EAAE,EAAE;QACnD,MAAM,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAC;QAErC,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;YAC3C,MAAM,EAAE,aAAa,EAAE,mBAAmB,EAAE,KAAK,EAAE,WAAW,EAAE,GAC9D,OAAO,CAAC,QAAQ,CAAC,CAAC;YAEpB,IAAI,aAAa,GAAG,WAAW;gBAC7B,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,mBAAmB,aAAnB,mBAAmB,cAAnB,mBAAmB,GAAI,EAAE,CAAC;YAE9B,IAAI,aAAa,EAAE;gBACjB,aAAa,GAAG,aAAa,CAAC,MAAM,CAClC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,MAAM,CACvC,CAAC;aACH;YAED,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG;gBACtB,aAAa;gBACb,KAAK,EAAE,WAAW;aACnB,CAAC;SACH;QAED,OAAO,GAAG,CAAC;IACb,CAAC,EACD,EAAE,OAAO,EAAE,EAAE,EAAE,CAChB,CAAC;AACJ,CAAC,qFAGC,OAAmC,EACnC,OAAe,EACf,QAAsB;;;QAEtB,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC;QAC/D,MAAM,kBAAkB,GAAG,uBAAA,IAAI,+DAAc,MAAlB,IAAI,EAAe,QAAQ,EAAE,IAAI,CAAC,CAAC;QAE9D,MAAM,iBAAiB,GACrB,MAAA,kBAAkB,aAAlB,kBAAkB,uBAAlB,kBAAkB,CAAE,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CACtC,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CACtC,mCAAI,kBAAkB,CAAC;QAE1B,IAAI,kBAAkB,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE;YACnD,OAAO,SAAS,CAAC;SAClB;QAED,MAAM,eAAe,GAAwB;YAC3C,OAAO;YACP,KAAK;YACL,IAAI;YACJ,SAAS,EAAE,kBAAkB,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS;SAC9D,CAAC;QAEF,IAAI,aAAkC,CAAC;QACvC,IAAI,QAAwC,CAAC;QAE7C,IAAI;YACF,QAAQ,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;YAC5D,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC;SAChC;QAAC,OAAO,KAAK,EAAE;YACd,aAAa,GAAG,KAAK,CAAC;SACvB;QAED,IAAI,OAAO,GAAG,EAAE,CAAC;QAEjB,IAAI,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,OAAO,EAAE;YACrB,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,CAC5C,CAAC,GAAkC,EAAE,QAAQ,EAAE,EAAE;gBAC/C,IAAI,CAAC,kBAAkB,IAAI,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;oBAChE,GAAG,CAAC,QAAQ,CAAC,GAAI,QAA+B,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;iBACpE;gBAED,OAAO,GAAG,CAAC;YACb,CAAC,EACD,EAAE,CACH,CAAC;SACH;QAED,IAAI,aAAa,EAAE;YACjB,OAAO,GAAG,kBAAkB,CAAC,MAAM,CACjC,CAAC,GAAkC,EAAE,QAAQ,EAAE,EAAE;gBAC/C,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,aAAa,EAAE,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;gBAC5D,OAAO,GAAG,CAAC;YACb,CAAC,EACD,EAAE,CACH,CAAC;SACH;QAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;;sEAG9B,KAAa,EAAE,IAAc,EAAE,IAAwB;IAClE,MAAM,YAAY,GAAG,uBAAA,IAAI,sEAAqB,MAAzB,IAAI,EAAsB,IAAI,CAAC,CAAC;IAErD,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;;QACpB,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5C,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC;QAEhC,MAAM,gBAAgB,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAClD,WAAW,CAAC,KAAK,CAAC,GAAG,gBAAgB,CAAC;QAEtC,MAAM,YAAY,GAAG,MAAA,gBAAgB,CAAC,YAAY,CAAC,mCAAI;YACrD,aAAa,EAAE,EAAE;YACjB,wBAAwB,EAAE,IAAI;YAC9B,IAAI,EAAE,IAAI;YACV,QAAQ,EAAE,IAAI;SACf,CAAC;QAEF,MAAM,YAAY,mCAAQ,YAAY,GAAK,IAAI,CAAE,CAAC;QAElD,gBAAgB,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,qFAEoB,IAAc;IACjC,QAAQ,IAAI,EAAE;QACZ,OAAO,CAAC,CAAC;YACP,OAAO,uBAAA,IAAI,kCAAY,MAAhB,IAAI,CAAc,CAAC;SAC3B;KACF;AACH,CAAC;IAGC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;AACvC,CAAC,2FAEuB,OAAuB;IAC7C,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAChD,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC,uBAAA,IAAI,gEAAe,MAAnB,IAAI,EAAgB,KAAK,EAAE,aAAa,CAAC,CAAC;IAC1C,uBAAA,IAAI,+DAAc,MAAlB,IAAI,EAAe,IAAI,EAAE,aAAa,CAAC,CAAC;IACxC,uBAAA,IAAI,+DAAc,MAAlB,IAAI,EAAe,IAAI,EAAE,aAAa,CAAC,CAAC;IACxC,uBAAA,IAAI,mEAAkB,MAAtB,IAAI,EAAmB,QAAQ,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;IAEtD,IAAI,aAAa,CAAC,MAAM,EAAE;QACxB,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;KAC1C;AACH,CAAC,mHAEmC,OAAmC;IACrE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC3C,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC,uBAAA,IAAI,gEAAe,MAAnB,IAAI,EAAgB,KAAK,EAAE,aAAa,CAAC,CAAC;IAC1C,uBAAA,IAAI,+DAAc,MAAlB,IAAI,EAAe,IAAI,EAAE,aAAa,CAAC,CAAC;IACxC,uBAAA,IAAI,oEAAmB,MAAvB,IAAI,EAAoB,SAAS,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;IACxD,uBAAA,IAAI,6EAA4B,MAAhC,IAAI,EAA6B,IAAI,EAAE,aAAa,CAAC,CAAC;IAEtD,IAAI,aAAa,CAAC,MAAM,EAAE;QACxB,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;KAC1C;AACH,CAAC,yEAEc,KAAa,EAAE,aAAuB;IACnD,IAAI,CAAC,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,MAAM,CAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;QAC/C,aAAa,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;KAClE;AACH,CAAC,uEAEa,IAAc,EAAE,aAAuB;IACnD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,gBAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;QAC3C,aAAa,CAAC,IAAI,CAChB,4CAA4C,MAAM,CAAC,MAAM,CACvD,gBAAQ,CACT,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACf,CAAC;KACH;AACH,CAAC,uEAEa,IAAY,EAAE,aAAuB;IACjD,IAAI,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,MAAM,CAAA,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;QAC7C,aAAa,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;KACjE;AACH,CAAC,iFAGC,SAA+B,EAC/B,IAAc,EACd,aAAuB;IAEvB,IAAI,CAAC,SAAS,EAAE;QACd,OAAO;KACR;IAED,MAAM,YAAY,GAAG,uBAAA,IAAI,kEAAiB,MAArB,IAAI,EAAkB,IAAI,CAAC,CAAC;IACjD,MAAM,gBAAgB,GAAG,EAAE,CAAC;IAE5B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE;QAChC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;YACpC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAChC,SAAS;SACV;KACF;IAED,IAAI,gBAAgB,CAAC,MAAM,EAAE;QAC3B,aAAa,CAAC,IAAI,CAChB,gCAAgC,IAAI,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACxE,CAAC;KACH;AACH,CAAC,+EAGC,QAA4B,EAC5B,IAAc,EACd,aAAuB;IAEvB,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,SAAS,EAAE;QAC/C,OAAO;KACR;IAED,MAAM,YAAY,GAAG,uBAAA,IAAI,kEAAiB,MAArB,IAAI,EAAkB,IAAI,CAAC,CAAC;IAEjD,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;QACpD,aAAa,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;QACpE,OAAO;KACR;IAED,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;QACpC,aAAa,CAAC,IAAI,CAAC,+BAA+B,IAAI,MAAM,QAAQ,EAAE,CAAC,CAAC;KACzE;AACH,CAAC,mGAE2B,IAAc,EAAE,aAAuB;IACjE,MAAM,YAAY,GAAG,uBAAA,IAAI,kEAAiB,MAArB,IAAI,EAAkB,IAAI,CAAC,CAAC;IAEjD,MAAM,kBAAkB,GAAG,YAAY,CAAC,MAAM,CAC5C,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,KAAK,CAC9D,CAAC;IAEF,IAAI,kBAAkB,CAAC,MAAM,EAAE;QAC7B,aAAa,CAAC,IAAI,CAChB,wCAAwC,IAAI,MAAM,kBAAkB,CAAC,IAAI,CACvE,IAAI,CACL,EAAE,CACJ,CAAC;KACH;AACH,CAAC,6EAEgB,IAAc;IAC7B,OAAO,CACL,uBAAA,IAAI,iCAAW;QACb,0BAA0B;SACzB,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,uBAAA,IAAI,+DAAc,MAAlB,IAAI,EAAe,QAAQ,EAAE,IAAI,CAAC,CAAC;SACrD,IAAI,EAAE,CACV,CAAC;AACJ,CAAC,uEAEa,QAAsB,EAAE,IAAc;IAClD,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAChD,CAAC","sourcesContent":["import type { RestrictedControllerMessenger } from '@metamask/base-controller';\nimport { BaseControllerV2 } from '@metamask/base-controller';\nimport type { Patch } from 'immer';\n\nimport type {\n NameProvider,\n NameProviderRequest,\n NameProviderResult,\n} from './types';\nimport { NameType } from './types';\n\nconst controllerName = 'NameController';\n\nconst stateMetadata = {\n names: { persist: true, anonymous: false },\n nameSources: { persist: true, anonymous: false },\n};\n\nconst getDefaultState = () => ({\n names: {\n [NameType.ETHEREUM_ADDRESS]: {},\n },\n nameSources: {},\n});\n\nexport type NameEntry = {\n name: string | null;\n sourceId: string | null;\n proposedNames: Record<string, string[] | null>;\n proposedNamesLastUpdated: number | null;\n};\n\nexport type SourceEntry = {\n label: string;\n};\n\nexport type NameControllerState = {\n // Type > Value > Variation > Entry\n names: Record<NameType, Record<string, Record<string, NameEntry>>>;\n nameSources: Record<string, SourceEntry>;\n};\n\nexport type GetNameState = {\n type: `${typeof controllerName}:getState`;\n handler: () => NameControllerState;\n};\n\nexport type NameStateChange = {\n type: `${typeof controllerName}:stateChange`;\n payload: [NameControllerState, Patch[]];\n};\n\nexport type NameControllerActions = GetNameState;\n\nexport type NameControllerEvents = NameStateChange;\n\nexport type NameControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n NameControllerActions,\n NameControllerEvents,\n never,\n never\n>;\n\nexport type NameControllerOptions = {\n getChainId: () => string;\n messenger: NameControllerMessenger;\n providers: NameProvider[];\n state?: Partial<NameControllerState>;\n};\n\nexport type UpdateProposedNamesRequest = {\n value: string;\n type: NameType;\n sourceIds?: string[];\n};\n\nexport type UpdateProposedNamesResult = {\n results: Record<string, { proposedNames?: string[]; error?: unknown }>;\n};\n\nexport type SetNameRequest = {\n value: string;\n type: NameType;\n name: string;\n sourceId?: string;\n};\n\n/**\n * Controller for storing and deriving names for values such as Ethereum addresses.\n */\nexport class NameController extends BaseControllerV2<\n typeof controllerName,\n NameControllerState,\n NameControllerMessenger\n> {\n #getChainId: () => string;\n\n #providers: NameProvider[];\n\n /**\n * Construct a Name controller.\n *\n * @param options - Controller options.\n * @param options.getChainId - Callback that returns the chain ID of the current network.\n * @param options.messenger - Restricted controller messenger for the name controller.\n * @param options.providers - Array of name provider instances to propose names.\n * @param options.state - Initial state to set on the controller.\n */\n constructor({\n getChainId,\n messenger,\n providers,\n state,\n }: NameControllerOptions) {\n super({\n name: controllerName,\n metadata: stateMetadata,\n messenger,\n state: { ...getDefaultState(), ...state },\n });\n\n this.#getChainId = getChainId;\n this.#providers = providers;\n }\n\n /**\n * Set the user specified name for a value.\n *\n * @param request - Request object.\n * @param request.name - Name to set.\n * @param request.sourceId - Optional ID of the source of the proposed name.\n * @param request.type - Type of value to set the name for.\n * @param request.value - Value to set the name for.\n */\n setName(request: SetNameRequest) {\n this.#validateSetNameRequest(request);\n\n const { value, type, name, sourceId } = request;\n\n this.#updateEntry(value, type, { name, sourceId: sourceId ?? null });\n }\n\n /**\n * Generate the proposed names for a value using the name providers and store them in the state.\n *\n * @param request - Request object.\n * @param request.value - Value to update the proposed names for.\n * @param request.type - Type of value to update the proposed names for.\n * @param request.sourceIds - Optional array of source IDs to limit which sources are used by the providers. If not provided, all sources in all providers will be used.\n * @returns The updated proposed names for the value.\n */\n async updateProposedNames(\n request: UpdateProposedNamesRequest,\n ): Promise<UpdateProposedNamesResult> {\n this.#validateUpdateProposedNamesRequest(request);\n\n const chainId = this.#getChainId();\n\n const providerResponses = (\n await Promise.all(\n this.#providers.map((provider) =>\n this.#getProviderResponse(request, chainId, provider),\n ),\n )\n ).filter((response) => Boolean(response)) as NameProviderResult[];\n\n this.#updateProposedNameState(request, providerResponses);\n this.#updateSourceState(this.#providers);\n\n return this.#getUpdateProposedNamesResult(providerResponses);\n }\n\n #updateProposedNameState(\n request: UpdateProposedNamesRequest,\n providerResponses: NameProviderResult[],\n ) {\n const { value, type } = request;\n const newProposedNames: { [sourceId: string]: string[] | null } = {};\n\n for (const providerResponse of providerResponses) {\n const { results, error: responseError } = providerResponse;\n\n if (responseError) {\n continue;\n }\n\n for (const sourceId of Object.keys(providerResponse.results)) {\n const result = results[sourceId];\n const { proposedNames } = result;\n let finalProposedNames = result.error ? null : proposedNames ?? [];\n\n if (finalProposedNames) {\n finalProposedNames = finalProposedNames.filter(\n (proposedName) => proposedName?.length,\n );\n }\n\n newProposedNames[sourceId] = finalProposedNames;\n }\n }\n\n const variationKey = this.#getTypeVariationKey(type);\n\n const existingProposedNames =\n this.state.names[type]?.[value]?.[variationKey]?.proposedNames;\n\n const proposedNames = {\n ...existingProposedNames,\n ...newProposedNames,\n };\n\n const proposedNamesLastUpdated = this.#getCurrentTimeSeconds();\n\n this.#updateEntry(value, type, { proposedNames, proposedNamesLastUpdated });\n }\n\n #updateSourceState(providers: NameProvider[]) {\n const newNameSources = { ...this.state.nameSources };\n\n for (const provider of providers) {\n const { sourceLabels } = provider.getMetadata();\n\n for (const sourceId of Object.keys(sourceLabels)) {\n newNameSources[sourceId] = {\n label: sourceLabels[sourceId],\n };\n }\n }\n\n this.update((state) => {\n state.nameSources = newNameSources;\n });\n }\n\n #getUpdateProposedNamesResult(\n providerResponses: NameProviderResult[],\n ): UpdateProposedNamesResult {\n return providerResponses.reduce(\n (acc: UpdateProposedNamesResult, providerResponse) => {\n const { results } = providerResponse;\n\n for (const sourceId of Object.keys(results)) {\n const { proposedNames: resultProposedNames, error: resultError } =\n results[sourceId];\n\n let proposedNames = resultError\n ? undefined\n : resultProposedNames ?? [];\n\n if (proposedNames) {\n proposedNames = proposedNames.filter(\n (proposedName) => proposedName?.length,\n );\n }\n\n acc.results[sourceId] = {\n proposedNames,\n error: resultError,\n };\n }\n\n return acc;\n },\n { results: {} },\n );\n }\n\n async #getProviderResponse(\n request: UpdateProposedNamesRequest,\n chainId: string,\n provider: NameProvider,\n ): Promise<NameProviderResult | undefined> {\n const { value, type, sourceIds: requestedSourceIds } = request;\n const supportedSourceIds = this.#getSourceIds(provider, type);\n\n const matchingSourceIds =\n requestedSourceIds?.filter((sourceId) =>\n supportedSourceIds.includes(sourceId),\n ) ?? supportedSourceIds;\n\n if (requestedSourceIds && !matchingSourceIds.length) {\n return undefined;\n }\n\n const providerRequest: NameProviderRequest = {\n chainId,\n value,\n type,\n sourceIds: requestedSourceIds ? matchingSourceIds : undefined,\n };\n\n let responseError: unknown | undefined;\n let response: NameProviderResult | undefined;\n\n try {\n response = await provider.getProposedNames(providerRequest);\n responseError = response.error;\n } catch (error) {\n responseError = error;\n }\n\n let results = {};\n\n if (response?.results) {\n results = Object.keys(response.results).reduce(\n (acc: NameProviderResult['results'], sourceId) => {\n if (!requestedSourceIds || requestedSourceIds.includes(sourceId)) {\n acc[sourceId] = (response as NameProviderResult).results[sourceId];\n }\n\n return acc;\n },\n {},\n );\n }\n\n if (responseError) {\n results = supportedSourceIds.reduce(\n (acc: NameProviderResult['results'], sourceId) => {\n acc[sourceId] = { proposedNames: [], error: responseError };\n return acc;\n },\n {},\n );\n }\n\n return { results, error: responseError };\n }\n\n #updateEntry(value: string, type: NameType, data: Partial<NameEntry>) {\n const variationKey = this.#getTypeVariationKey(type);\n\n this.update((state) => {\n const typeEntries = state.names[type] || {};\n state.names[type] = typeEntries;\n\n const variationEntries = typeEntries[value] || {};\n typeEntries[value] = variationEntries;\n\n const currentEntry = variationEntries[variationKey] ?? {\n proposedNames: {},\n proposedNamesLastUpdated: null,\n name: null,\n sourceId: null,\n };\n\n const updatedEntry = { ...currentEntry, ...data };\n\n variationEntries[variationKey] = updatedEntry;\n });\n }\n\n #getTypeVariationKey(type: NameType): string {\n switch (type) {\n default: {\n return this.#getChainId();\n }\n }\n }\n\n #getCurrentTimeSeconds(): number {\n return Math.round(Date.now() / 1000);\n }\n\n #validateSetNameRequest(request: SetNameRequest) {\n const { name, value, type, sourceId } = request;\n const errorMessages: string[] = [];\n\n this.#validateValue(value, errorMessages);\n this.#validateType(type, errorMessages);\n this.#validateName(name, errorMessages);\n this.#validateSourceId(sourceId, type, errorMessages);\n\n if (errorMessages.length) {\n throw new Error(errorMessages.join(' '));\n }\n }\n\n #validateUpdateProposedNamesRequest(request: UpdateProposedNamesRequest) {\n const { value, type, sourceIds } = request;\n const errorMessages: string[] = [];\n\n this.#validateValue(value, errorMessages);\n this.#validateType(type, errorMessages);\n this.#validateSourceIds(sourceIds, type, errorMessages);\n this.#validateDuplicateSourceIds(type, errorMessages);\n\n if (errorMessages.length) {\n throw new Error(errorMessages.join(' '));\n }\n }\n\n #validateValue(value: string, errorMessages: string[]) {\n if (!value?.length || typeof value !== 'string') {\n errorMessages.push('Must specify a non-empty string for value.');\n }\n }\n\n #validateType(type: NameType, errorMessages: string[]) {\n if (!Object.values(NameType).includes(type)) {\n errorMessages.push(\n `Must specify one of the following types: ${Object.values(\n NameType,\n ).join(', ')}`,\n );\n }\n }\n\n #validateName(name: string, errorMessages: string[]) {\n if (!name?.length || typeof name !== 'string') {\n errorMessages.push('Must specify a non-empty string for name.');\n }\n }\n\n #validateSourceIds(\n sourceIds: string[] | undefined,\n type: NameType,\n errorMessages: string[],\n ) {\n if (!sourceIds) {\n return;\n }\n\n const allSourceIds = this.#getAllSourceIds(type);\n const missingSourceIds = [];\n\n for (const sourceId of sourceIds) {\n if (!allSourceIds.includes(sourceId)) {\n missingSourceIds.push(sourceId);\n continue;\n }\n }\n\n if (missingSourceIds.length) {\n errorMessages.push(\n `Unknown source IDs for type '${type}': ${missingSourceIds.join(', ')}`,\n );\n }\n }\n\n #validateSourceId(\n sourceId: string | undefined,\n type: NameType,\n errorMessages: string[],\n ) {\n if (sourceId === null || sourceId === undefined) {\n return;\n }\n\n const allSourceIds = this.#getAllSourceIds(type);\n\n if (!sourceId.length || typeof sourceId !== 'string') {\n errorMessages.push('Must specify a non-empty string for sourceId.');\n return;\n }\n\n if (!allSourceIds.includes(sourceId)) {\n errorMessages.push(`Unknown source ID for type '${type}': ${sourceId}`);\n }\n }\n\n #validateDuplicateSourceIds(type: NameType, errorMessages: string[]) {\n const allSourceIds = this.#getAllSourceIds(type);\n\n const duplicateSourceIds = allSourceIds.filter(\n (sourceId, index) => allSourceIds.indexOf(sourceId) !== index,\n );\n\n if (duplicateSourceIds.length) {\n errorMessages.push(\n `Duplicate source IDs found for type '${type}': ${duplicateSourceIds.join(\n ', ',\n )}`,\n );\n }\n }\n\n #getAllSourceIds(type: NameType): string[] {\n return (\n this.#providers\n /* istanbul ignore next */\n .map((provider) => this.#getSourceIds(provider, type))\n .flat()\n );\n }\n\n #getSourceIds(provider: NameProvider, type: NameType): string[] {\n return provider.getMetadata().sourceIds[type];\n }\n}\n"]}
1
+ {"version":3,"file":"NameController.js","sourceRoot":"","sources":["../src/NameController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RestrictedControllerMessenger } from '@metamask/base-controller';\nimport { BaseControllerV2 } from '@metamask/base-controller';\nimport type { Patch } from 'immer';\n\nimport type {\n NameProvider,\n NameProviderRequest,\n NameProviderResult,\n NameProviderSourceResult,\n} from './types';\nimport { NameType } from './types';\n\nconst DEFAULT_UPDATE_DELAY = 60 * 2; // 2 Minutes\n\nconst controllerName = 'NameController';\n\nconst stateMetadata = {\n names: { persist: true, anonymous: false },\n nameSources: { persist: true, anonymous: false },\n};\n\nconst getDefaultState = () => ({\n names: {\n [NameType.ETHEREUM_ADDRESS]: {},\n },\n nameSources: {},\n});\n\nexport type ProposedNamesEntry = {\n proposedNames: string[];\n lastRequestTime: number | null;\n updateDelay: number | null;\n};\n\nexport type NameEntry = {\n name: string | null;\n sourceId: string | null;\n proposedNames: Record<string, ProposedNamesEntry>;\n};\n\nexport type SourceEntry = {\n label: string;\n};\n\nexport type NameControllerState = {\n // Type > Value > Variation > Entry\n names: Record<NameType, Record<string, Record<string, NameEntry>>>;\n nameSources: Record<string, SourceEntry>;\n};\n\nexport type GetNameState = {\n type: `${typeof controllerName}:getState`;\n handler: () => NameControllerState;\n};\n\nexport type NameStateChange = {\n type: `${typeof controllerName}:stateChange`;\n payload: [NameControllerState, Patch[]];\n};\n\nexport type NameControllerActions = GetNameState;\n\nexport type NameControllerEvents = NameStateChange;\n\nexport type NameControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n NameControllerActions,\n NameControllerEvents,\n never,\n never\n>;\n\nexport type NameControllerOptions = {\n getChainId: () => string;\n messenger: NameControllerMessenger;\n providers: NameProvider[];\n state?: Partial<NameControllerState>;\n updateDelay?: number;\n};\n\nexport type UpdateProposedNamesRequest = {\n value: string;\n type: NameType;\n sourceIds?: string[];\n onlyUpdateAfterDelay?: boolean;\n};\n\nexport type UpdateProposedNamesResult = {\n results: Record<string, { proposedNames?: string[]; error?: unknown }>;\n};\n\nexport type SetNameRequest = {\n value: string;\n type: NameType;\n name: string | null;\n sourceId?: string;\n};\n\n/**\n * Controller for storing and deriving names for values such as Ethereum addresses.\n */\nexport class NameController extends BaseControllerV2<\n typeof controllerName,\n NameControllerState,\n NameControllerMessenger\n> {\n #getChainId: () => string;\n\n #providers: NameProvider[];\n\n #updateDelay: number;\n\n /**\n * Construct a Name controller.\n *\n * @param options - Controller options.\n * @param options.getChainId - Callback that returns the chain ID of the current network.\n * @param options.messenger - Restricted controller messenger for the name controller.\n * @param options.providers - Array of name provider instances to propose names.\n * @param options.state - Initial state to set on the controller.\n * @param options.updateDelay - The delay in seconds before a new request to a source should be made.\n */\n constructor({\n getChainId,\n messenger,\n providers,\n state,\n updateDelay,\n }: NameControllerOptions) {\n super({\n name: controllerName,\n metadata: stateMetadata,\n messenger,\n state: { ...getDefaultState(), ...state },\n });\n\n this.#getChainId = getChainId;\n this.#providers = providers;\n this.#updateDelay = updateDelay ?? DEFAULT_UPDATE_DELAY;\n }\n\n /**\n * Set the user specified name for a value.\n *\n * @param request - Request object.\n * @param request.name - Name to set.\n * @param request.sourceId - Optional ID of the source of the proposed name.\n * @param request.type - Type of value to set the name for.\n * @param request.value - Value to set the name for.\n */\n setName(request: SetNameRequest) {\n this.#validateSetNameRequest(request);\n\n const { value, type, name, sourceId: requestSourceId } = request;\n const sourceId = requestSourceId ?? null;\n\n this.#updateEntry(value, type, (entry: NameEntry) => {\n entry.name = name;\n entry.sourceId = sourceId;\n });\n }\n\n /**\n * Generate the proposed names for a value using the name providers and store them in the state.\n *\n * @param request - Request object.\n * @param request.value - Value to update the proposed names for.\n * @param request.type - Type of value to update the proposed names for.\n * @param request.sourceIds - Optional array of source IDs to limit which sources are used by the providers. If not provided, all sources in all providers will be used.\n * @returns The updated proposed names for the value.\n */\n async updateProposedNames(\n request: UpdateProposedNamesRequest,\n ): Promise<UpdateProposedNamesResult> {\n this.#validateUpdateProposedNamesRequest(request);\n\n const chainId = this.#getChainId();\n\n const providerResponses = (\n await Promise.all(\n this.#providers.map((provider) =>\n this.#getProviderResponse(request, chainId, provider),\n ),\n )\n ).filter((response) => Boolean(response)) as NameProviderResult[];\n\n this.#updateProposedNameState(request, providerResponses);\n this.#updateSourceState(this.#providers);\n\n return this.#getUpdateProposedNamesResult(providerResponses);\n }\n\n #updateProposedNameState(\n request: UpdateProposedNamesRequest,\n providerResponses: NameProviderResult[],\n ) {\n const { value, type } = request;\n const currentTime = this.#getCurrentTimeSeconds();\n\n this.#updateEntry(value, type, (entry: NameEntry) => {\n this.#removeDormantProposedNames(entry.proposedNames, type);\n\n for (const providerResponse of providerResponses) {\n const { results } = providerResponse;\n\n for (const sourceId of Object.keys(providerResponse.results)) {\n const result = results[sourceId];\n const { proposedNames, updateDelay } = result;\n\n const proposedNameEntry = entry.proposedNames[sourceId] ?? {\n proposedNames: [],\n lastRequestTime: null,\n updateDelay: null,\n };\n\n entry.proposedNames[sourceId] = proposedNameEntry;\n\n if (proposedNames) {\n proposedNameEntry.proposedNames = proposedNames;\n }\n\n proposedNameEntry.lastRequestTime = currentTime;\n proposedNameEntry.updateDelay = updateDelay ?? null;\n }\n }\n });\n }\n\n #updateSourceState(providers: NameProvider[]) {\n const newNameSources = { ...this.state.nameSources };\n\n for (const provider of providers) {\n const { sourceLabels } = provider.getMetadata();\n\n for (const sourceId of Object.keys(sourceLabels)) {\n newNameSources[sourceId] = {\n label: sourceLabels[sourceId],\n };\n }\n }\n\n this.update((state) => {\n state.nameSources = newNameSources;\n });\n }\n\n #getUpdateProposedNamesResult(\n providerResponses: NameProviderResult[],\n ): UpdateProposedNamesResult {\n return providerResponses.reduce(\n (acc: UpdateProposedNamesResult, providerResponse) => {\n const { results } = providerResponse;\n\n for (const sourceId of Object.keys(results)) {\n const { proposedNames, error } = results[sourceId];\n\n acc.results[sourceId] = {\n proposedNames,\n error,\n };\n }\n\n return acc;\n },\n { results: {} },\n );\n }\n\n async #getProviderResponse(\n request: UpdateProposedNamesRequest,\n chainId: string,\n provider: NameProvider,\n ): Promise<NameProviderResult | undefined> {\n const {\n value,\n type,\n sourceIds: requestedSourceIds,\n onlyUpdateAfterDelay,\n } = request;\n\n const variationKey = this.#getTypeVariationKey(type);\n const supportedSourceIds = this.#getSourceIds(provider, type);\n const currentTime = this.#getCurrentTimeSeconds();\n\n const matchingSourceIds = supportedSourceIds.filter((sourceId) => {\n if (requestedSourceIds && !requestedSourceIds.includes(sourceId)) {\n return false;\n }\n\n if (onlyUpdateAfterDelay) {\n const entry = this.state.names[type]?.[value]?.[variationKey] ?? {};\n const proposedNamesEntry = entry.proposedNames?.[sourceId] ?? {};\n const lastRequestTime = proposedNamesEntry.lastRequestTime ?? 0;\n const updateDelay = proposedNamesEntry.updateDelay ?? this.#updateDelay;\n\n if (currentTime - lastRequestTime < updateDelay) {\n return false;\n }\n }\n\n return true;\n });\n\n if (!matchingSourceIds.length) {\n return undefined;\n }\n\n const providerRequest: NameProviderRequest = {\n chainId,\n value,\n type,\n sourceIds: requestedSourceIds ? matchingSourceIds : undefined,\n };\n\n let responseError: unknown | undefined;\n let response: NameProviderResult | undefined;\n\n try {\n response = await provider.getProposedNames(providerRequest);\n responseError = response.error;\n } catch (error) {\n responseError = error;\n }\n\n return this.#normalizeProviderResult(\n response,\n responseError,\n matchingSourceIds,\n );\n }\n\n #normalizeProviderResult(\n result: NameProviderResult | undefined,\n responseError: unknown,\n matchingSourceIds: string[],\n ): NameProviderResult {\n const error = responseError ?? undefined;\n\n const results = matchingSourceIds.reduce((acc, sourceId) => {\n const sourceResult = result?.results?.[sourceId];\n\n const normalizedSourceResult = this.#normalizeProviderSourceResult(\n sourceResult,\n responseError,\n );\n\n return {\n ...acc,\n [sourceId]: normalizedSourceResult,\n };\n }, {});\n\n return { results, error };\n }\n\n #normalizeProviderSourceResult(\n result: NameProviderSourceResult | undefined,\n responseError: unknown,\n ): NameProviderSourceResult | undefined {\n const error = result?.error ?? responseError ?? undefined;\n const updateDelay = result?.updateDelay ?? undefined;\n let proposedNames = error ? undefined : result?.proposedNames ?? undefined;\n\n if (proposedNames) {\n proposedNames = proposedNames.filter(\n (proposedName) => proposedName?.length,\n );\n }\n\n return {\n proposedNames,\n error,\n updateDelay,\n };\n }\n\n #updateEntry(\n value: string,\n type: NameType,\n callback: (entry: NameEntry) => void,\n ) {\n const variationKey = this.#getTypeVariationKey(type);\n\n this.update((state) => {\n const typeEntries = state.names[type] || {};\n state.names[type] = typeEntries;\n\n const variationEntries = typeEntries[value] || {};\n typeEntries[value] = variationEntries;\n\n const entry = variationEntries[variationKey] ?? {\n proposedNames: {},\n name: null,\n sourceId: null,\n };\n variationEntries[variationKey] = entry;\n\n callback(entry);\n });\n }\n\n #getTypeVariationKey(type: NameType): string {\n switch (type) {\n default: {\n return this.#getChainId();\n }\n }\n }\n\n #getCurrentTimeSeconds(): number {\n return Math.round(Date.now() / 1000);\n }\n\n #validateSetNameRequest(request: SetNameRequest) {\n const { name, value, type, sourceId } = request;\n const errorMessages: string[] = [];\n\n this.#validateValue(value, errorMessages);\n this.#validateType(type, errorMessages);\n this.#validateName(name, errorMessages);\n this.#validateSourceId(sourceId, type, name, errorMessages);\n\n if (errorMessages.length) {\n throw new Error(errorMessages.join(' '));\n }\n }\n\n #validateUpdateProposedNamesRequest(request: UpdateProposedNamesRequest) {\n const { value, type, sourceIds } = request;\n const errorMessages: string[] = [];\n\n this.#validateValue(value, errorMessages);\n this.#validateType(type, errorMessages);\n this.#validateSourceIds(sourceIds, type, errorMessages);\n this.#validateDuplicateSourceIds(type, errorMessages);\n\n if (errorMessages.length) {\n throw new Error(errorMessages.join(' '));\n }\n }\n\n #validateValue(value: string, errorMessages: string[]) {\n if (!value?.length || typeof value !== 'string') {\n errorMessages.push('Must specify a non-empty string for value.');\n }\n }\n\n #validateType(type: NameType, errorMessages: string[]) {\n if (!Object.values(NameType).includes(type)) {\n errorMessages.push(\n `Must specify one of the following types: ${Object.values(\n NameType,\n ).join(', ')}`,\n );\n }\n }\n\n #validateName(name: string | null, errorMessages: string[]) {\n if (name === null) {\n return;\n }\n\n if (!name?.length || typeof name !== 'string') {\n errorMessages.push('Must specify a non-empty string or null for name.');\n }\n }\n\n #validateSourceIds(\n sourceIds: string[] | undefined,\n type: NameType,\n errorMessages: string[],\n ) {\n if (!sourceIds) {\n return;\n }\n\n const allSourceIds = this.#getAllSourceIds(type);\n const missingSourceIds = [];\n\n for (const sourceId of sourceIds) {\n if (!allSourceIds.includes(sourceId)) {\n missingSourceIds.push(sourceId);\n continue;\n }\n }\n\n if (missingSourceIds.length) {\n errorMessages.push(\n `Unknown source IDs for type '${type}': ${missingSourceIds.join(', ')}`,\n );\n }\n }\n\n #validateSourceId(\n sourceId: string | undefined,\n type: NameType,\n name: string | null,\n errorMessages: string[],\n ) {\n if (sourceId === null || sourceId === undefined) {\n return;\n }\n\n if (name === null) {\n errorMessages.push(\n `Cannot specify a source ID when clearing the saved name: ${sourceId}`,\n );\n return;\n }\n\n const allSourceIds = this.#getAllSourceIds(type);\n\n if (!sourceId.length || typeof sourceId !== 'string') {\n errorMessages.push('Must specify a non-empty string for sourceId.');\n return;\n }\n\n if (!allSourceIds.includes(sourceId)) {\n errorMessages.push(`Unknown source ID for type '${type}': ${sourceId}`);\n }\n }\n\n #validateDuplicateSourceIds(type: NameType, errorMessages: string[]) {\n const allSourceIds = this.#getAllSourceIds(type);\n\n const duplicateSourceIds = allSourceIds.filter(\n (sourceId, index) => allSourceIds.indexOf(sourceId) !== index,\n );\n\n if (duplicateSourceIds.length) {\n errorMessages.push(\n `Duplicate source IDs found for type '${type}': ${duplicateSourceIds.join(\n ', ',\n )}`,\n );\n }\n }\n\n #getAllSourceIds(type: NameType): string[] {\n return (\n this.#providers\n /* istanbul ignore next */\n .map((provider) => this.#getSourceIds(provider, type))\n .flat()\n );\n }\n\n #getSourceIds(provider: NameProvider, type: NameType): string[] {\n return provider.getMetadata().sourceIds[type];\n }\n\n #removeDormantProposedNames(\n proposedNames: Record<string, ProposedNamesEntry>,\n type: NameType,\n ) {\n if (Object.keys(proposedNames).length === 0) {\n return;\n }\n\n const typeSourceIds = this.#getAllSourceIds(type);\n\n const dormantSourceIds = Object.keys(proposedNames).filter(\n (sourceId) => !typeSourceIds.includes(sourceId),\n );\n\n for (const dormantSourceId of dormantSourceIds) {\n delete proposedNames[dormantSourceId];\n }\n }\n}\n"]}
@@ -0,0 +1,5 @@
1
+ /// <reference types="debug" />
2
+ import { createModuleLogger } from '@metamask/utils';
3
+ export declare const projectLogger: import("debug").Debugger;
4
+ export { createModuleLogger };
5
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":";AAAA,OAAO,EAAuB,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1E,eAAO,MAAM,aAAa,0BAAyC,CAAC;AAEpE,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
package/dist/logger.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createModuleLogger = exports.projectLogger = void 0;
4
+ const utils_1 = require("@metamask/utils");
5
+ Object.defineProperty(exports, "createModuleLogger", { enumerable: true, get: function () { return utils_1.createModuleLogger; } });
6
+ exports.projectLogger = (0, utils_1.createProjectLogger)('name-controller');
7
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":";;;AAAA,2CAA0E;AAIjE,mGAJqB,0BAAkB,OAIrB;AAFd,QAAA,aAAa,GAAG,IAAA,2BAAmB,EAAC,iBAAiB,CAAC,CAAC","sourcesContent":["import { createProjectLogger, createModuleLogger } from '@metamask/utils';\n\nexport const projectLogger = createProjectLogger('name-controller');\n\nexport { createModuleLogger };\n"]}
@@ -2,7 +2,8 @@ import type { NameProvider, NameProviderMetadata, NameProviderRequest, NameProvi
2
2
  export declare type ReverseLookupCallback = (address: string, chainId: string) => Promise<string>;
3
3
  export declare class ENSNameProvider implements NameProvider {
4
4
  #private;
5
- constructor({ reverseLookup }: {
5
+ constructor({ isEnabled, reverseLookup, }: {
6
+ isEnabled?: () => boolean;
6
7
  reverseLookup: ReverseLookupCallback;
7
8
  });
8
9
  getMetadata(): NameProviderMetadata;
@@ -1 +1 @@
1
- {"version":3,"file":"ens.d.ts","sourceRoot":"","sources":["../../src/providers/ens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,UAAU,CAAC;AAGlB,oBAAY,qBAAqB,GAAG,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC,MAAM,CAAC,CAAC;AAKrB,qBAAa,eAAgB,YAAW,YAAY;;gBAGtC,EAAE,aAAa,EAAE,EAAE;QAAE,aAAa,EAAE,qBAAqB,CAAA;KAAE;IAIvE,WAAW,IAAI,oBAAoB;IAO7B,gBAAgB,CACpB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC;CAU/B"}
1
+ {"version":3,"file":"ens.d.ts","sourceRoot":"","sources":["../../src/providers/ens.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,UAAU,CAAC;AAGlB,oBAAY,qBAAqB,GAAG,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC,MAAM,CAAC,CAAC;AAOrB,qBAAa,eAAgB,YAAW,YAAY;;gBAKtC,EACV,SAAS,EACT,aAAa,GACd,EAAE;QACD,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;QAC1B,aAAa,EAAE,qBAAqB,CAAC;KACtC;IAKD,WAAW,IAAI,oBAAoB;IAO7B,gBAAgB,CACpB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC;CAiC/B"}
@@ -19,15 +19,19 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
19
19
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
20
20
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
21
21
  };
22
- var _ENSNameProvider_reverseLookup;
22
+ var _ENSNameProvider_isEnabled, _ENSNameProvider_reverseLookup;
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
24
  exports.ENSNameProvider = void 0;
25
+ const logger_1 = require("../logger");
25
26
  const types_1 = require("../types");
26
27
  const ID = 'ens';
27
28
  const LABEL = 'Ethereum Name Service (ENS)';
29
+ const log = (0, logger_1.createModuleLogger)(logger_1.projectLogger, 'ens');
28
30
  class ENSNameProvider {
29
- constructor({ reverseLookup }) {
31
+ constructor({ isEnabled, reverseLookup, }) {
32
+ _ENSNameProvider_isEnabled.set(this, void 0);
30
33
  _ENSNameProvider_reverseLookup.set(this, void 0);
34
+ __classPrivateFieldSet(this, _ENSNameProvider_isEnabled, isEnabled || (() => true), "f");
31
35
  __classPrivateFieldSet(this, _ENSNameProvider_reverseLookup, reverseLookup, "f");
32
36
  }
33
37
  getMetadata() {
@@ -38,16 +42,35 @@ class ENSNameProvider {
38
42
  }
39
43
  getProposedNames(request) {
40
44
  return __awaiter(this, void 0, void 0, function* () {
45
+ if (!__classPrivateFieldGet(this, _ENSNameProvider_isEnabled, "f").call(this)) {
46
+ log('Skipping request as disabled');
47
+ return {
48
+ results: {
49
+ [ID]: {
50
+ proposedNames: [],
51
+ },
52
+ },
53
+ };
54
+ }
41
55
  const { value, chainId } = request;
42
- const proposedName = yield __classPrivateFieldGet(this, _ENSNameProvider_reverseLookup, "f").call(this, value, chainId);
43
- return {
44
- results: {
45
- [ID]: { proposedNames: [proposedName] },
46
- },
47
- };
56
+ log('Invoking callback', { value, chainId });
57
+ try {
58
+ const proposedName = yield __classPrivateFieldGet(this, _ENSNameProvider_reverseLookup, "f").call(this, value, chainId);
59
+ const proposedNames = proposedName ? [proposedName] : [];
60
+ log('New proposed names', proposedNames);
61
+ return {
62
+ results: {
63
+ [ID]: { proposedNames },
64
+ },
65
+ };
66
+ }
67
+ catch (error) {
68
+ log('Request failed', error);
69
+ throw error;
70
+ }
48
71
  });
49
72
  }
50
73
  }
51
74
  exports.ENSNameProvider = ENSNameProvider;
52
- _ENSNameProvider_reverseLookup = new WeakMap();
75
+ _ENSNameProvider_isEnabled = new WeakMap(), _ENSNameProvider_reverseLookup = new WeakMap();
53
76
  //# sourceMappingURL=ens.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ens.js","sourceRoot":"","sources":["../../src/providers/ens.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAMA,oCAAoC;AAOpC,MAAM,EAAE,GAAG,KAAK,CAAC;AACjB,MAAM,KAAK,GAAG,6BAA6B,CAAC;AAE5C,MAAa,eAAe;IAG1B,YAAY,EAAE,aAAa,EAA4C;QAFvE,iDAAsC;QAGpC,uBAAA,IAAI,kCAAkB,aAAa,MAAA,CAAC;IACtC,CAAC;IAED,WAAW;QACT,OAAO;YACL,SAAS,EAAE,EAAE,CAAC,gBAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;YAChD,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE;SAC9B,CAAC;IACJ,CAAC;IAEK,gBAAgB,CACpB,OAA4B;;YAE5B,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;YACnC,MAAM,YAAY,GAAG,MAAM,uBAAA,IAAI,sCAAe,MAAnB,IAAI,EAAgB,KAAK,EAAE,OAAO,CAAC,CAAC;YAE/D,OAAO;gBACL,OAAO,EAAE;oBACP,CAAC,EAAE,CAAC,EAAE,EAAE,aAAa,EAAE,CAAC,YAAY,CAAC,EAAE;iBACxC;aACF,CAAC;QACJ,CAAC;KAAA;CACF;AA1BD,0CA0BC","sourcesContent":["import type {\n NameProvider,\n NameProviderMetadata,\n NameProviderRequest,\n NameProviderResult,\n} from '../types';\nimport { NameType } from '../types';\n\nexport type ReverseLookupCallback = (\n address: string,\n chainId: string,\n) => Promise<string>;\n\nconst ID = 'ens';\nconst LABEL = 'Ethereum Name Service (ENS)';\n\nexport class ENSNameProvider implements NameProvider {\n #reverseLookup: ReverseLookupCallback;\n\n constructor({ reverseLookup }: { reverseLookup: ReverseLookupCallback }) {\n this.#reverseLookup = reverseLookup;\n }\n\n getMetadata(): NameProviderMetadata {\n return {\n sourceIds: { [NameType.ETHEREUM_ADDRESS]: [ID] },\n sourceLabels: { [ID]: LABEL },\n };\n }\n\n async getProposedNames(\n request: NameProviderRequest,\n ): Promise<NameProviderResult> {\n const { value, chainId } = request;\n const proposedName = await this.#reverseLookup(value, chainId);\n\n return {\n results: {\n [ID]: { proposedNames: [proposedName] },\n },\n };\n }\n}\n"]}
1
+ {"version":3,"file":"ens.js","sourceRoot":"","sources":["../../src/providers/ens.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA,sCAA8D;AAO9D,oCAAoC;AAOpC,MAAM,EAAE,GAAG,KAAK,CAAC;AACjB,MAAM,KAAK,GAAG,6BAA6B,CAAC;AAE5C,MAAM,GAAG,GAAG,IAAA,2BAAkB,EAAC,sBAAa,EAAE,KAAK,CAAC,CAAC;AAErD,MAAa,eAAe;IAK1B,YAAY,EACV,SAAS,EACT,aAAa,GAId;QAVD,6CAA0B;QAE1B,iDAAsC;QASpC,uBAAA,IAAI,8BAAc,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAA,CAAC;QAC5C,uBAAA,IAAI,kCAAkB,aAAa,MAAA,CAAC;IACtC,CAAC;IAED,WAAW;QACT,OAAO;YACL,SAAS,EAAE,EAAE,CAAC,gBAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;YAChD,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE;SAC9B,CAAC;IACJ,CAAC;IAEK,gBAAgB,CACpB,OAA4B;;YAE5B,IAAI,CAAC,uBAAA,IAAI,kCAAW,MAAf,IAAI,CAAa,EAAE;gBACtB,GAAG,CAAC,8BAA8B,CAAC,CAAC;gBAEpC,OAAO;oBACL,OAAO,EAAE;wBACP,CAAC,EAAE,CAAC,EAAE;4BACJ,aAAa,EAAE,EAAE;yBAClB;qBACF;iBACF,CAAC;aACH;YAED,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;YAEnC,GAAG,CAAC,mBAAmB,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YAE7C,IAAI;gBACF,MAAM,YAAY,GAAG,MAAM,uBAAA,IAAI,sCAAe,MAAnB,IAAI,EAAgB,KAAK,EAAE,OAAO,CAAC,CAAC;gBAC/D,MAAM,aAAa,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAEzD,GAAG,CAAC,oBAAoB,EAAE,aAAa,CAAC,CAAC;gBAEzC,OAAO;oBACL,OAAO,EAAE;wBACP,CAAC,EAAE,CAAC,EAAE,EAAE,aAAa,EAAE;qBACxB;iBACF,CAAC;aACH;YAAC,OAAO,KAAK,EAAE;gBACd,GAAG,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;gBAC7B,MAAM,KAAK,CAAC;aACb;QACH,CAAC;KAAA;CACF;AA1DD,0CA0DC","sourcesContent":["import { projectLogger, createModuleLogger } from '../logger';\nimport type {\n NameProvider,\n NameProviderMetadata,\n NameProviderRequest,\n NameProviderResult,\n} from '../types';\nimport { NameType } from '../types';\n\nexport type ReverseLookupCallback = (\n address: string,\n chainId: string,\n) => Promise<string>;\n\nconst ID = 'ens';\nconst LABEL = 'Ethereum Name Service (ENS)';\n\nconst log = createModuleLogger(projectLogger, 'ens');\n\nexport class ENSNameProvider implements NameProvider {\n #isEnabled: () => boolean;\n\n #reverseLookup: ReverseLookupCallback;\n\n constructor({\n isEnabled,\n reverseLookup,\n }: {\n isEnabled?: () => boolean;\n reverseLookup: ReverseLookupCallback;\n }) {\n this.#isEnabled = isEnabled || (() => true);\n this.#reverseLookup = reverseLookup;\n }\n\n getMetadata(): NameProviderMetadata {\n return {\n sourceIds: { [NameType.ETHEREUM_ADDRESS]: [ID] },\n sourceLabels: { [ID]: LABEL },\n };\n }\n\n async getProposedNames(\n request: NameProviderRequest,\n ): Promise<NameProviderResult> {\n if (!this.#isEnabled()) {\n log('Skipping request as disabled');\n\n return {\n results: {\n [ID]: {\n proposedNames: [],\n },\n },\n };\n }\n\n const { value, chainId } = request;\n\n log('Invoking callback', { value, chainId });\n\n try {\n const proposedName = await this.#reverseLookup(value, chainId);\n const proposedNames = proposedName ? [proposedName] : [];\n\n log('New proposed names', proposedNames);\n\n return {\n results: {\n [ID]: { proposedNames },\n },\n };\n } catch (error) {\n log('Request failed', error);\n throw error;\n }\n }\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import type { NameProvider, NameProviderMetadata, NameProviderRequest, NameProviderResult } from '../types';
2
2
  export declare class EtherscanNameProvider implements NameProvider {
3
3
  #private;
4
- constructor({ apiKey }?: {
5
- apiKey?: string;
4
+ constructor({ isEnabled }?: {
5
+ isEnabled?: () => boolean;
6
6
  });
7
7
  getMetadata(): NameProviderMetadata;
8
8
  getProposedNames(request: NameProviderRequest): Promise<NameProviderResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"etherscan.d.ts","sourceRoot":"","sources":["../../src/providers/etherscan.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,UAAU,CAAC;AA4BlB,qBAAa,qBAAsB,YAAW,YAAY;;gBAG5C,EAAE,MAAM,EAAE,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO;IAIhD,WAAW,IAAI,oBAAoB;IAO7B,gBAAgB,CACpB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC;CAkD/B"}
1
+ {"version":3,"file":"etherscan.d.ts","sourceRoot":"","sources":["../../src/providers/etherscan.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,UAAU,CAAC;AAgClB,qBAAa,qBAAsB,YAAW,YAAY;;gBAO5C,EAAE,SAAS,EAAE,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAA;KAAO;IAI7D,WAAW,IAAI,oBAAoB;IAO7B,gBAAgB,CACpB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC;CAkH/B"}
@@ -19,19 +19,26 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
19
19
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
20
20
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
21
21
  };
22
- var _EtherscanNameProvider_instances, _EtherscanNameProvider_apiKey, _EtherscanNameProvider_getUrl;
22
+ var _EtherscanNameProvider_instances, _EtherscanNameProvider_isEnabled, _EtherscanNameProvider_lastRequestTime, _EtherscanNameProvider_mutex, _EtherscanNameProvider_sendRequest, _EtherscanNameProvider_getUrl;
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
24
  exports.EtherscanNameProvider = void 0;
25
+ const async_mutex_1 = require("async-mutex");
25
26
  const constants_1 = require("../constants");
27
+ const logger_1 = require("../logger");
26
28
  const types_1 = require("../types");
27
29
  const util_1 = require("../util");
28
30
  const ID = 'etherscan';
29
31
  const LABEL = 'Etherscan (Verified Contract Name)';
32
+ const RATE_LIMIT_UPDATE_DELAY = 5; // 5 Seconds
33
+ const RATE_LIMIT_INTERVAL = RATE_LIMIT_UPDATE_DELAY * 1000;
34
+ const log = (0, logger_1.createModuleLogger)(logger_1.projectLogger, 'etherscan');
30
35
  class EtherscanNameProvider {
31
- constructor({ apiKey } = {}) {
36
+ constructor({ isEnabled } = {}) {
32
37
  _EtherscanNameProvider_instances.add(this);
33
- _EtherscanNameProvider_apiKey.set(this, void 0);
34
- __classPrivateFieldSet(this, _EtherscanNameProvider_apiKey, apiKey, "f");
38
+ _EtherscanNameProvider_isEnabled.set(this, void 0);
39
+ _EtherscanNameProvider_lastRequestTime.set(this, 0);
40
+ _EtherscanNameProvider_mutex.set(this, new async_mutex_1.Mutex());
41
+ __classPrivateFieldSet(this, _EtherscanNameProvider_isEnabled, isEnabled || (() => true), "f");
35
42
  }
36
43
  getMetadata() {
37
44
  return {
@@ -42,28 +49,85 @@ class EtherscanNameProvider {
42
49
  getProposedNames(request) {
43
50
  var _a;
44
51
  return __awaiter(this, void 0, void 0, function* () {
45
- const { value, chainId } = request;
46
- const url = __classPrivateFieldGet(this, _EtherscanNameProvider_instances, "m", _EtherscanNameProvider_getUrl).call(this, chainId, {
47
- module: 'contract',
48
- action: 'getsourcecode',
49
- address: value,
50
- apikey: __classPrivateFieldGet(this, _EtherscanNameProvider_apiKey, "f"),
51
- });
52
- const responseData = (yield (0, util_1.handleFetch)(url));
53
- const results = (_a = responseData === null || responseData === void 0 ? void 0 : responseData.result) !== null && _a !== void 0 ? _a : [];
54
- const proposedNames = results.map((result) => result.ContractName);
55
- return {
56
- results: {
57
- [ID]: {
58
- proposedNames,
52
+ if (!__classPrivateFieldGet(this, _EtherscanNameProvider_isEnabled, "f").call(this)) {
53
+ log('Skipping request as disabled');
54
+ return {
55
+ results: {
56
+ [ID]: {
57
+ proposedNames: [],
58
+ },
59
+ },
60
+ };
61
+ }
62
+ const releaseLock = yield __classPrivateFieldGet(this, _EtherscanNameProvider_mutex, "f").acquire();
63
+ try {
64
+ const { value, chainId } = request;
65
+ const time = Date.now();
66
+ const timeSinceLastRequest = time - __classPrivateFieldGet(this, _EtherscanNameProvider_lastRequestTime, "f");
67
+ if (timeSinceLastRequest < RATE_LIMIT_INTERVAL) {
68
+ log('Skipping request to avoid rate limit');
69
+ return {
70
+ results: {
71
+ [ID]: {
72
+ updateDelay: RATE_LIMIT_UPDATE_DELAY,
73
+ },
74
+ },
75
+ };
76
+ }
77
+ const url = __classPrivateFieldGet(this, _EtherscanNameProvider_instances, "m", _EtherscanNameProvider_getUrl).call(this, chainId, {
78
+ module: 'contract',
79
+ action: 'getsourcecode',
80
+ address: value,
81
+ });
82
+ const { responseData, error } = yield __classPrivateFieldGet(this, _EtherscanNameProvider_instances, "m", _EtherscanNameProvider_sendRequest).call(this, url);
83
+ if (error) {
84
+ log('Request failed', error);
85
+ throw error;
86
+ }
87
+ if ((responseData === null || responseData === void 0 ? void 0 : responseData.message) === 'NOTOK') {
88
+ log('Request warning', responseData.result);
89
+ return {
90
+ results: {
91
+ [ID]: {
92
+ updateDelay: RATE_LIMIT_UPDATE_DELAY,
93
+ },
94
+ },
95
+ };
96
+ }
97
+ const results = (_a = responseData === null || responseData === void 0 ? void 0 : responseData.result) !== null && _a !== void 0 ? _a : [];
98
+ const proposedNames = results.map((result) => result.ContractName);
99
+ log('New proposed names', proposedNames);
100
+ return {
101
+ results: {
102
+ [ID]: {
103
+ proposedNames,
104
+ },
59
105
  },
60
- },
61
- };
106
+ };
107
+ }
108
+ finally {
109
+ releaseLock();
110
+ }
62
111
  });
63
112
  }
64
113
  }
65
114
  exports.EtherscanNameProvider = EtherscanNameProvider;
66
- _EtherscanNameProvider_apiKey = new WeakMap(), _EtherscanNameProvider_instances = new WeakSet(), _EtherscanNameProvider_getUrl = function _EtherscanNameProvider_getUrl(chainId, params) {
115
+ _EtherscanNameProvider_isEnabled = new WeakMap(), _EtherscanNameProvider_lastRequestTime = new WeakMap(), _EtherscanNameProvider_mutex = new WeakMap(), _EtherscanNameProvider_instances = new WeakSet(), _EtherscanNameProvider_sendRequest = function _EtherscanNameProvider_sendRequest(url) {
116
+ return __awaiter(this, void 0, void 0, function* () {
117
+ try {
118
+ log('Sending request', url);
119
+ const responseData = (yield (0, util_1.handleFetch)(url));
120
+ return { responseData };
121
+ }
122
+ catch (error) {
123
+ (0, util_1.assertIsError)(error);
124
+ return { error };
125
+ }
126
+ finally {
127
+ __classPrivateFieldSet(this, _EtherscanNameProvider_lastRequestTime, Date.now(), "f");
128
+ }
129
+ });
130
+ }, _EtherscanNameProvider_getUrl = function _EtherscanNameProvider_getUrl(chainId, params) {
67
131
  const networkInfo = constants_1.ETHERSCAN_SUPPORTED_NETWORKS[chainId];
68
132
  if (!networkInfo) {
69
133
  throw new Error(`Etherscan does not support chain with ID: ${chainId}`);
@@ -71,9 +135,6 @@ _EtherscanNameProvider_apiKey = new WeakMap(), _EtherscanNameProvider_instances
71
135
  let url = `https://${networkInfo.subdomain}.${networkInfo.domain}/api`;
72
136
  Object.keys(params).forEach((key, index) => {
73
137
  const value = params[key];
74
- if (!value) {
75
- return;
76
- }
77
138
  url += `${index === 0 ? '?' : '&'}${key}=${value}`;
78
139
  });
79
140
  return url;
@@ -1 +1 @@
1
- {"version":3,"file":"etherscan.js","sourceRoot":"","sources":["../../src/providers/etherscan.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAA4D;AAO5D,oCAAoC;AACpC,kCAAsC;AAEtC,MAAM,EAAE,GAAG,WAAW,CAAC;AACvB,MAAM,KAAK,GAAG,oCAAoC,CAAC;AAuBnD,MAAa,qBAAqB;IAGhC,YAAY,EAAE,MAAM,KAA0B,EAAE;;QAFhD,gDAAiB;QAGf,uBAAA,IAAI,iCAAW,MAAM,MAAA,CAAC;IACxB,CAAC;IAED,WAAW;QACT,OAAO;YACL,SAAS,EAAE,EAAE,CAAC,gBAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;YAChD,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE;SAC9B,CAAC;IACJ,CAAC;IAEK,gBAAgB,CACpB,OAA4B;;;YAE5B,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;YAEnC,MAAM,GAAG,GAAG,uBAAA,IAAI,uEAAQ,MAAZ,IAAI,EAAS,OAAO,EAAE;gBAChC,MAAM,EAAE,UAAU;gBAClB,MAAM,EAAE,eAAe;gBACvB,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,uBAAA,IAAI,qCAAQ;aACrB,CAAC,CAAC;YAEH,MAAM,YAAY,GAAG,CAAC,MAAM,IAAA,kBAAW,EACrC,GAAG,CACJ,CAAmC,CAAC;YAErC,MAAM,OAAO,GAAG,MAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,MAAM,mCAAI,EAAE,CAAC;YAC3C,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YAEnE,OAAO;gBACL,OAAO,EAAE;oBACP,CAAC,EAAE,CAAC,EAAE;wBACJ,aAAa;qBACd;iBACF;aACF,CAAC;;KACH;CA0BF;AAlED,sDAkEC;wKAxBS,OAAe,EAAE,MAA0C;IAGjE,MAAM,WAAW,GACf,wCAA4B,CAAC,OAA2B,CAAC,CAAC;IAE5D,IAAI,CAAC,WAAW,EAAE;QAChB,MAAM,IAAI,KAAK,CAAC,6CAA6C,OAAO,EAAE,CAAC,CAAC;KACzE;IAED,IAAI,GAAG,GAAG,WAAW,WAAW,CAAC,SAAS,IAAI,WAAW,CAAC,MAAM,MAAM,CAAC;IAEvE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QACzC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAE1B,IAAI,CAAC,KAAK,EAAE;YACV,OAAO;SACR;QAED,GAAG,IAAI,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["import { ETHERSCAN_SUPPORTED_NETWORKS } from '../constants';\nimport type {\n NameProvider,\n NameProviderMetadata,\n NameProviderRequest,\n NameProviderResult,\n} from '../types';\nimport { NameType } from '../types';\nimport { handleFetch } from '../util';\n\nconst ID = 'etherscan';\nconst LABEL = 'Etherscan (Verified Contract Name)';\n\ntype EtherscanGetSourceCodeResponse = {\n status: '1' | '0';\n message: string;\n result: [\n {\n SourceCode: string;\n ABI: string;\n ContractName: string;\n CompilerVersion: string;\n OptimizationUsed: string;\n Runs: string;\n ConstructorArguments: string;\n Library: string;\n LicenseType: string;\n Proxy: string;\n Implementation: string;\n SwarmSource: string;\n },\n ];\n};\n\nexport class EtherscanNameProvider implements NameProvider {\n #apiKey?: string;\n\n constructor({ apiKey }: { apiKey?: string } = {}) {\n this.#apiKey = apiKey;\n }\n\n getMetadata(): NameProviderMetadata {\n return {\n sourceIds: { [NameType.ETHEREUM_ADDRESS]: [ID] },\n sourceLabels: { [ID]: LABEL },\n };\n }\n\n async getProposedNames(\n request: NameProviderRequest,\n ): Promise<NameProviderResult> {\n const { value, chainId } = request;\n\n const url = this.#getUrl(chainId, {\n module: 'contract',\n action: 'getsourcecode',\n address: value,\n apikey: this.#apiKey,\n });\n\n const responseData = (await handleFetch(\n url,\n )) as EtherscanGetSourceCodeResponse;\n\n const results = responseData?.result ?? [];\n const proposedNames = results.map((result) => result.ContractName);\n\n return {\n results: {\n [ID]: {\n proposedNames,\n },\n },\n };\n }\n\n #getUrl(chainId: string, params: Record<string, string | undefined>): string {\n type SupportedChainId = keyof typeof ETHERSCAN_SUPPORTED_NETWORKS;\n\n const networkInfo =\n ETHERSCAN_SUPPORTED_NETWORKS[chainId as SupportedChainId];\n\n if (!networkInfo) {\n throw new Error(`Etherscan does not support chain with ID: ${chainId}`);\n }\n\n let url = `https://${networkInfo.subdomain}.${networkInfo.domain}/api`;\n\n Object.keys(params).forEach((key, index) => {\n const value = params[key];\n\n if (!value) {\n return;\n }\n\n url += `${index === 0 ? '?' : '&'}${key}=${value}`;\n });\n\n return url;\n }\n}\n"]}
1
+ {"version":3,"file":"etherscan.js","sourceRoot":"","sources":["../../src/providers/etherscan.ts"],"names":[],"mappings":"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","sourcesContent":["import { Mutex } from 'async-mutex';\n\nimport { ETHERSCAN_SUPPORTED_NETWORKS } from '../constants';\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type {\n NameProvider,\n NameProviderMetadata,\n NameProviderRequest,\n NameProviderResult,\n} from '../types';\nimport { NameType } from '../types';\nimport { handleFetch, assertIsError } from '../util';\n\nconst ID = 'etherscan';\nconst LABEL = 'Etherscan (Verified Contract Name)';\nconst RATE_LIMIT_UPDATE_DELAY = 5; // 5 Seconds\nconst RATE_LIMIT_INTERVAL = RATE_LIMIT_UPDATE_DELAY * 1000;\n\nconst log = createModuleLogger(projectLogger, 'etherscan');\n\ntype EtherscanGetSourceCodeResponse = {\n status: '1' | '0';\n message: string;\n result: [\n {\n SourceCode: string;\n ABI: string;\n ContractName: string;\n CompilerVersion: string;\n OptimizationUsed: string;\n Runs: string;\n ConstructorArguments: string;\n Library: string;\n LicenseType: string;\n Proxy: string;\n Implementation: string;\n SwarmSource: string;\n },\n ];\n};\n\nexport class EtherscanNameProvider implements NameProvider {\n #isEnabled: () => boolean;\n\n #lastRequestTime = 0;\n\n #mutex = new Mutex();\n\n constructor({ isEnabled }: { isEnabled?: () => boolean } = {}) {\n this.#isEnabled = isEnabled || (() => true);\n }\n\n getMetadata(): NameProviderMetadata {\n return {\n sourceIds: { [NameType.ETHEREUM_ADDRESS]: [ID] },\n sourceLabels: { [ID]: LABEL },\n };\n }\n\n async getProposedNames(\n request: NameProviderRequest,\n ): Promise<NameProviderResult> {\n if (!this.#isEnabled()) {\n log('Skipping request as disabled');\n\n return {\n results: {\n [ID]: {\n proposedNames: [],\n },\n },\n };\n }\n\n const releaseLock = await this.#mutex.acquire();\n\n try {\n const { value, chainId } = request;\n\n const time = Date.now();\n const timeSinceLastRequest = time - this.#lastRequestTime;\n\n if (timeSinceLastRequest < RATE_LIMIT_INTERVAL) {\n log('Skipping request to avoid rate limit');\n\n return {\n results: {\n [ID]: {\n updateDelay: RATE_LIMIT_UPDATE_DELAY,\n },\n },\n };\n }\n\n const url = this.#getUrl(chainId, {\n module: 'contract',\n action: 'getsourcecode',\n address: value,\n });\n\n const { responseData, error } = await this.#sendRequest(url);\n\n if (error) {\n log('Request failed', error);\n throw error;\n }\n\n if (responseData?.message === 'NOTOK') {\n log('Request warning', responseData.result);\n\n return {\n results: {\n [ID]: {\n updateDelay: RATE_LIMIT_UPDATE_DELAY,\n },\n },\n };\n }\n\n const results = responseData?.result ?? [];\n const proposedNames = results.map((result) => result.ContractName);\n\n log('New proposed names', proposedNames);\n\n return {\n results: {\n [ID]: {\n proposedNames,\n },\n },\n };\n } finally {\n releaseLock();\n }\n }\n\n async #sendRequest(url: string): Promise<{\n responseData?: EtherscanGetSourceCodeResponse;\n error?: Error;\n }> {\n try {\n log('Sending request', url);\n\n const responseData = (await handleFetch(\n url,\n )) as EtherscanGetSourceCodeResponse;\n\n return { responseData };\n } catch (error) {\n assertIsError(error);\n return { error };\n } finally {\n this.#lastRequestTime = Date.now();\n }\n }\n\n #getUrl(chainId: string, params: Record<string, string | undefined>): string {\n type SupportedChainId = keyof typeof ETHERSCAN_SUPPORTED_NETWORKS;\n\n const networkInfo =\n ETHERSCAN_SUPPORTED_NETWORKS[chainId as SupportedChainId];\n\n if (!networkInfo) {\n throw new Error(`Etherscan does not support chain with ID: ${chainId}`);\n }\n\n let url = `https://${networkInfo.subdomain}.${networkInfo.domain}/api`;\n\n Object.keys(params).forEach((key, index) => {\n const value = params[key];\n url += `${index === 0 ? '?' : '&'}${key}=${value}`;\n });\n\n return url;\n }\n}\n"]}
@@ -1,5 +1,9 @@
1
1
  import type { NameProvider, NameProviderMetadata, NameProviderRequest, NameProviderResult } from '../types';
2
2
  export declare class LensNameProvider implements NameProvider {
3
+ #private;
4
+ constructor({ isEnabled }?: {
5
+ isEnabled?: () => boolean;
6
+ });
3
7
  getMetadata(): NameProviderMetadata;
4
8
  getProposedNames(request: NameProviderRequest): Promise<NameProviderResult>;
5
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lens.d.ts","sourceRoot":"","sources":["../../src/providers/lens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,UAAU,CAAC;AA2BlB,qBAAa,gBAAiB,YAAW,YAAY;IACnD,WAAW,IAAI,oBAAoB;IAO7B,gBAAgB,CACpB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC;CAkB/B"}
1
+ {"version":3,"file":"lens.d.ts","sourceRoot":"","sources":["../../src/providers/lens.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,UAAU,CAAC;AA6BlB,qBAAa,gBAAiB,YAAW,YAAY;;gBAGvC,EAAE,SAAS,EAAE,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAA;KAAO;IAI7D,WAAW,IAAI,oBAAoB;IAO7B,gBAAgB,CACpB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC;CA0C/B"}
@@ -8,8 +8,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
12
+ if (kind === "m") throw new TypeError("Private method is not writable");
13
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
14
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
15
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
16
+ };
17
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
18
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
19
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
20
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
21
+ };
22
+ var _LensNameProvider_isEnabled;
11
23
  Object.defineProperty(exports, "__esModule", { value: true });
12
24
  exports.LensNameProvider = void 0;
25
+ const logger_1 = require("../logger");
13
26
  const types_1 = require("../types");
14
27
  const util_1 = require("../util");
15
28
  const ID = 'lens';
@@ -23,7 +36,12 @@ query HandlesForAddress($address: EthereumAddress!) {
23
36
  }
24
37
  }
25
38
  }`;
39
+ const log = (0, logger_1.createModuleLogger)(logger_1.projectLogger, 'lens');
26
40
  class LensNameProvider {
41
+ constructor({ isEnabled } = {}) {
42
+ _LensNameProvider_isEnabled.set(this, void 0);
43
+ __classPrivateFieldSet(this, _LensNameProvider_isEnabled, isEnabled || (() => true), "f");
44
+ }
27
45
  getMetadata() {
28
46
  return {
29
47
  sourceIds: { [types_1.NameType.ETHEREUM_ADDRESS]: [ID] },
@@ -33,21 +51,39 @@ class LensNameProvider {
33
51
  getProposedNames(request) {
34
52
  var _a, _b;
35
53
  return __awaiter(this, void 0, void 0, function* () {
54
+ if (!__classPrivateFieldGet(this, _LensNameProvider_isEnabled, "f").call(this)) {
55
+ log('Skipping request as disabled');
56
+ return {
57
+ results: {
58
+ [ID]: {
59
+ proposedNames: [],
60
+ },
61
+ },
62
+ };
63
+ }
36
64
  const { value } = request;
37
- const responseData = yield (0, util_1.graphQL)(LENS_URL, QUERY, {
38
- address: value,
39
- });
40
- const profiles = (_b = (_a = responseData === null || responseData === void 0 ? void 0 : responseData.profiles) === null || _a === void 0 ? void 0 : _a.items) !== null && _b !== void 0 ? _b : [];
41
- const proposedNames = profiles.map((profile) => profile.handle);
42
- return {
43
- results: {
44
- [ID]: {
45
- proposedNames,
65
+ const variables = { address: value };
66
+ log('Sending request', { variables });
67
+ try {
68
+ const responseData = yield (0, util_1.graphQL)(LENS_URL, QUERY, variables);
69
+ const profiles = (_b = (_a = responseData === null || responseData === void 0 ? void 0 : responseData.profiles) === null || _a === void 0 ? void 0 : _a.items) !== null && _b !== void 0 ? _b : [];
70
+ const proposedNames = profiles.map((profile) => profile.handle);
71
+ log('New proposed names', proposedNames);
72
+ return {
73
+ results: {
74
+ [ID]: {
75
+ proposedNames,
76
+ },
46
77
  },
47
- },
48
- };
78
+ };
79
+ }
80
+ catch (error) {
81
+ log('Request failed', error);
82
+ throw error;
83
+ }
49
84
  });
50
85
  }
51
86
  }
52
87
  exports.LensNameProvider = LensNameProvider;
88
+ _LensNameProvider_isEnabled = new WeakMap();
53
89
  //# sourceMappingURL=lens.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lens.js","sourceRoot":"","sources":["../../src/providers/lens.ts"],"names":[],"mappings":";;;;;;;;;;;;AAMA,oCAAoC;AACpC,kCAAkC;AAElC,MAAM,EAAE,GAAG,MAAM,CAAC;AAClB,MAAM,KAAK,GAAG,eAAe,CAAC;AAC9B,MAAM,QAAQ,GAAG,sBAAsB,CAAC;AAExC,MAAM,KAAK,GAAG;;;;;;;EAOZ,CAAC;AAYH,MAAa,gBAAgB;IAC3B,WAAW;QACT,OAAO;YACL,SAAS,EAAE,EAAE,CAAC,gBAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;YAChD,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE;SAC9B,CAAC;IACJ,CAAC;IAEK,gBAAgB,CACpB,OAA4B;;;YAE5B,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;YAE1B,MAAM,YAAY,GAAG,MAAM,IAAA,cAAO,EAAe,QAAQ,EAAE,KAAK,EAAE;gBAChE,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,MAAA,MAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,QAAQ,0CAAE,KAAK,mCAAI,EAAE,CAAC;YACrD,MAAM,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAEhE,OAAO;gBACL,OAAO,EAAE;oBACP,CAAC,EAAE,CAAC,EAAE;wBACJ,aAAa;qBACd;iBACF;aACF,CAAC;;KACH;CACF;AA5BD,4CA4BC","sourcesContent":["import type {\n NameProvider,\n NameProviderMetadata,\n NameProviderRequest,\n NameProviderResult,\n} from '../types';\nimport { NameType } from '../types';\nimport { graphQL } from '../util';\n\nconst ID = 'lens';\nconst LABEL = 'Lens Protocol';\nconst LENS_URL = `https://api.lens.dev`;\n\nconst QUERY = `\nquery HandlesForAddress($address: EthereumAddress!) {\n profiles(request: { ownedBy: [$address] }) {\n items {\n handle\n }\n }\n}`;\n\ntype LensResponse = {\n profiles: {\n items: [\n {\n handle: string;\n },\n ];\n };\n};\n\nexport class LensNameProvider implements NameProvider {\n getMetadata(): NameProviderMetadata {\n return {\n sourceIds: { [NameType.ETHEREUM_ADDRESS]: [ID] },\n sourceLabels: { [ID]: LABEL },\n };\n }\n\n async getProposedNames(\n request: NameProviderRequest,\n ): Promise<NameProviderResult> {\n const { value } = request;\n\n const responseData = await graphQL<LensResponse>(LENS_URL, QUERY, {\n address: value,\n });\n\n const profiles = responseData?.profiles?.items ?? [];\n const proposedNames = profiles.map((profile) => profile.handle);\n\n return {\n results: {\n [ID]: {\n proposedNames,\n },\n },\n };\n }\n}\n"]}
1
+ {"version":3,"file":"lens.js","sourceRoot":"","sources":["../../src/providers/lens.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA,sCAA8D;AAO9D,oCAAoC;AACpC,kCAAkC;AAElC,MAAM,EAAE,GAAG,MAAM,CAAC;AAClB,MAAM,KAAK,GAAG,eAAe,CAAC;AAC9B,MAAM,QAAQ,GAAG,sBAAsB,CAAC;AAExC,MAAM,KAAK,GAAG;;;;;;;EAOZ,CAAC;AAEH,MAAM,GAAG,GAAG,IAAA,2BAAkB,EAAC,sBAAa,EAAE,MAAM,CAAC,CAAC;AAYtD,MAAa,gBAAgB;IAG3B,YAAY,EAAE,SAAS,KAAoC,EAAE;QAF7D,8CAA0B;QAGxB,uBAAA,IAAI,+BAAc,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAA,CAAC;IAC9C,CAAC;IAED,WAAW;QACT,OAAO;YACL,SAAS,EAAE,EAAE,CAAC,gBAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;YAChD,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE;SAC9B,CAAC;IACJ,CAAC;IAEK,gBAAgB,CACpB,OAA4B;;;YAE5B,IAAI,CAAC,uBAAA,IAAI,mCAAW,MAAf,IAAI,CAAa,EAAE;gBACtB,GAAG,CAAC,8BAA8B,CAAC,CAAC;gBAEpC,OAAO;oBACL,OAAO,EAAE;wBACP,CAAC,EAAE,CAAC,EAAE;4BACJ,aAAa,EAAE,EAAE;yBAClB;qBACF;iBACF,CAAC;aACH;YAED,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;YAC1B,MAAM,SAAS,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAErC,GAAG,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;YAEtC,IAAI;gBACF,MAAM,YAAY,GAAG,MAAM,IAAA,cAAO,EAChC,QAAQ,EACR,KAAK,EACL,SAAS,CACV,CAAC;gBAEF,MAAM,QAAQ,GAAG,MAAA,MAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,QAAQ,0CAAE,KAAK,mCAAI,EAAE,CAAC;gBACrD,MAAM,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAEhE,GAAG,CAAC,oBAAoB,EAAE,aAAa,CAAC,CAAC;gBAEzC,OAAO;oBACL,OAAO,EAAE;wBACP,CAAC,EAAE,CAAC,EAAE;4BACJ,aAAa;yBACd;qBACF;iBACF,CAAC;aACH;YAAC,OAAO,KAAK,EAAE;gBACd,GAAG,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;gBAC7B,MAAM,KAAK,CAAC;aACb;;KACF;CACF;AA1DD,4CA0DC","sourcesContent":["import { createModuleLogger, projectLogger } from '../logger';\nimport type {\n NameProvider,\n NameProviderMetadata,\n NameProviderRequest,\n NameProviderResult,\n} from '../types';\nimport { NameType } from '../types';\nimport { graphQL } from '../util';\n\nconst ID = 'lens';\nconst LABEL = 'Lens Protocol';\nconst LENS_URL = `https://api.lens.dev`;\n\nconst QUERY = `\nquery HandlesForAddress($address: EthereumAddress!) {\n profiles(request: { ownedBy: [$address] }) {\n items {\n handle\n }\n }\n}`;\n\nconst log = createModuleLogger(projectLogger, 'lens');\n\ntype LensResponse = {\n profiles: {\n items: [\n {\n handle: string;\n },\n ];\n };\n};\n\nexport class LensNameProvider implements NameProvider {\n #isEnabled: () => boolean;\n\n constructor({ isEnabled }: { isEnabled?: () => boolean } = {}) {\n this.#isEnabled = isEnabled || (() => true);\n }\n\n getMetadata(): NameProviderMetadata {\n return {\n sourceIds: { [NameType.ETHEREUM_ADDRESS]: [ID] },\n sourceLabels: { [ID]: LABEL },\n };\n }\n\n async getProposedNames(\n request: NameProviderRequest,\n ): Promise<NameProviderResult> {\n if (!this.#isEnabled()) {\n log('Skipping request as disabled');\n\n return {\n results: {\n [ID]: {\n proposedNames: [],\n },\n },\n };\n }\n\n const { value } = request;\n const variables = { address: value };\n\n log('Sending request', { variables });\n\n try {\n const responseData = await graphQL<LensResponse>(\n LENS_URL,\n QUERY,\n variables,\n );\n\n const profiles = responseData?.profiles?.items ?? [];\n const proposedNames = profiles.map((profile) => profile.handle);\n\n log('New proposed names', proposedNames);\n\n return {\n results: {\n [ID]: {\n proposedNames,\n },\n },\n };\n } catch (error) {\n log('Request failed', error);\n throw error;\n }\n }\n}\n"]}
@@ -1,5 +1,9 @@
1
1
  import type { NameProvider, NameProviderMetadata, NameProviderRequest, NameProviderResult } from '../types';
2
2
  export declare class TokenNameProvider implements NameProvider {
3
+ #private;
4
+ constructor({ isEnabled }?: {
5
+ isEnabled?: () => boolean;
6
+ });
3
7
  getMetadata(): NameProviderMetadata;
4
8
  getProposedNames(request: NameProviderRequest): Promise<NameProviderResult>;
5
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/providers/token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,UAAU,CAAC;AAOlB,qBAAa,iBAAkB,YAAW,YAAY;IACpD,WAAW,IAAI,oBAAoB;IAO7B,gBAAgB,CACpB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC;CAc/B"}
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/providers/token.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,UAAU,CAAC;AASlB,qBAAa,iBAAkB,YAAW,YAAY;;gBAGxC,EAAE,SAAS,EAAE,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAA;KAAO;IAI7D,WAAW,IAAI,oBAAoB;IAO7B,gBAAgB,CACpB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC;CAqC/B"}
@@ -8,13 +8,31 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
12
+ if (kind === "m") throw new TypeError("Private method is not writable");
13
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
14
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
15
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
16
+ };
17
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
18
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
19
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
20
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
21
+ };
22
+ var _TokenNameProvider_isEnabled;
11
23
  Object.defineProperty(exports, "__esModule", { value: true });
12
24
  exports.TokenNameProvider = void 0;
25
+ const logger_1 = require("../logger");
13
26
  const types_1 = require("../types");
14
27
  const util_1 = require("../util");
15
28
  const ID = 'token';
16
29
  const LABEL = 'Blockchain (Token Name)';
30
+ const log = (0, logger_1.createModuleLogger)(logger_1.projectLogger, 'token');
17
31
  class TokenNameProvider {
32
+ constructor({ isEnabled } = {}) {
33
+ _TokenNameProvider_isEnabled.set(this, void 0);
34
+ __classPrivateFieldSet(this, _TokenNameProvider_isEnabled, isEnabled || (() => true), "f");
35
+ }
18
36
  getMetadata() {
19
37
  return {
20
38
  sourceIds: { [types_1.NameType.ETHEREUM_ADDRESS]: [ID] },
@@ -23,19 +41,39 @@ class TokenNameProvider {
23
41
  }
24
42
  getProposedNames(request) {
25
43
  return __awaiter(this, void 0, void 0, function* () {
44
+ if (!__classPrivateFieldGet(this, _TokenNameProvider_isEnabled, "f").call(this)) {
45
+ log('Skipping request as disabled');
46
+ return {
47
+ results: {
48
+ [ID]: {
49
+ proposedNames: [],
50
+ },
51
+ },
52
+ };
53
+ }
26
54
  const { value, chainId } = request;
27
55
  const url = `https://token-api.metaswap.codefi.network/token/${chainId}?address=${value}`;
28
- const responseData = yield (0, util_1.handleFetch)(url);
29
- const proposedName = responseData.name;
30
- return {
31
- results: {
32
- [ID]: {
33
- proposedNames: [proposedName],
56
+ log('Sending request', url);
57
+ try {
58
+ const responseData = yield (0, util_1.handleFetch)(url);
59
+ const proposedName = responseData.name;
60
+ const proposedNames = proposedName ? [proposedName] : [];
61
+ log('New proposed names', proposedNames);
62
+ return {
63
+ results: {
64
+ [ID]: {
65
+ proposedNames,
66
+ },
34
67
  },
35
- },
36
- };
68
+ };
69
+ }
70
+ catch (error) {
71
+ log('Request failed', error);
72
+ throw error;
73
+ }
37
74
  });
38
75
  }
39
76
  }
40
77
  exports.TokenNameProvider = TokenNameProvider;
78
+ _TokenNameProvider_isEnabled = new WeakMap();
41
79
  //# sourceMappingURL=token.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/providers/token.ts"],"names":[],"mappings":";;;;;;;;;;;;AAMA,oCAAoC;AACpC,kCAAsC;AAEtC,MAAM,EAAE,GAAG,OAAO,CAAC;AACnB,MAAM,KAAK,GAAG,yBAAyB,CAAC;AAExC,MAAa,iBAAiB;IAC5B,WAAW;QACT,OAAO;YACL,SAAS,EAAE,EAAE,CAAC,gBAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;YAChD,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE;SAC9B,CAAC;IACJ,CAAC;IAEK,gBAAgB,CACpB,OAA4B;;YAE5B,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;YACnC,MAAM,GAAG,GAAG,mDAAmD,OAAO,YAAY,KAAK,EAAE,CAAC;YAC1F,MAAM,YAAY,GAAG,MAAM,IAAA,kBAAW,EAAC,GAAG,CAAC,CAAC;YAC5C,MAAM,YAAY,GAAG,YAAY,CAAC,IAAI,CAAC;YAEvC,OAAO;gBACL,OAAO,EAAE;oBACP,CAAC,EAAE,CAAC,EAAE;wBACJ,aAAa,EAAE,CAAC,YAAY,CAAC;qBAC9B;iBACF;aACF,CAAC;QACJ,CAAC;KAAA;CACF;AAxBD,8CAwBC","sourcesContent":["import type {\n NameProvider,\n NameProviderMetadata,\n NameProviderRequest,\n NameProviderResult,\n} from '../types';\nimport { NameType } from '../types';\nimport { handleFetch } from '../util';\n\nconst ID = 'token';\nconst LABEL = 'Blockchain (Token Name)';\n\nexport class TokenNameProvider implements NameProvider {\n getMetadata(): NameProviderMetadata {\n return {\n sourceIds: { [NameType.ETHEREUM_ADDRESS]: [ID] },\n sourceLabels: { [ID]: LABEL },\n };\n }\n\n async getProposedNames(\n request: NameProviderRequest,\n ): Promise<NameProviderResult> {\n const { value, chainId } = request;\n const url = `https://token-api.metaswap.codefi.network/token/${chainId}?address=${value}`;\n const responseData = await handleFetch(url);\n const proposedName = responseData.name;\n\n return {\n results: {\n [ID]: {\n proposedNames: [proposedName],\n },\n },\n };\n }\n}\n"]}
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/providers/token.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA,sCAA8D;AAO9D,oCAAoC;AACpC,kCAAsC;AAEtC,MAAM,EAAE,GAAG,OAAO,CAAC;AACnB,MAAM,KAAK,GAAG,yBAAyB,CAAC;AAExC,MAAM,GAAG,GAAG,IAAA,2BAAkB,EAAC,sBAAa,EAAE,OAAO,CAAC,CAAC;AAEvD,MAAa,iBAAiB;IAG5B,YAAY,EAAE,SAAS,KAAoC,EAAE;QAF7D,+CAA0B;QAGxB,uBAAA,IAAI,gCAAc,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAA,CAAC;IAC9C,CAAC;IAED,WAAW;QACT,OAAO;YACL,SAAS,EAAE,EAAE,CAAC,gBAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;YAChD,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE;SAC9B,CAAC;IACJ,CAAC;IAEK,gBAAgB,CACpB,OAA4B;;YAE5B,IAAI,CAAC,uBAAA,IAAI,oCAAW,MAAf,IAAI,CAAa,EAAE;gBACtB,GAAG,CAAC,8BAA8B,CAAC,CAAC;gBAEpC,OAAO;oBACL,OAAO,EAAE;wBACP,CAAC,EAAE,CAAC,EAAE;4BACJ,aAAa,EAAE,EAAE;yBAClB;qBACF;iBACF,CAAC;aACH;YAED,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;YACnC,MAAM,GAAG,GAAG,mDAAmD,OAAO,YAAY,KAAK,EAAE,CAAC;YAE1F,GAAG,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;YAE5B,IAAI;gBACF,MAAM,YAAY,GAAG,MAAM,IAAA,kBAAW,EAAC,GAAG,CAAC,CAAC;gBAC5C,MAAM,YAAY,GAAG,YAAY,CAAC,IAAI,CAAC;gBACvC,MAAM,aAAa,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAEzD,GAAG,CAAC,oBAAoB,EAAE,aAAa,CAAC,CAAC;gBAEzC,OAAO;oBACL,OAAO,EAAE;wBACP,CAAC,EAAE,CAAC,EAAE;4BACJ,aAAa;yBACd;qBACF;iBACF,CAAC;aACH;YAAC,OAAO,KAAK,EAAE;gBACd,GAAG,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;gBAC7B,MAAM,KAAK,CAAC;aACb;QACH,CAAC;KAAA;CACF;AArDD,8CAqDC","sourcesContent":["import { createModuleLogger, projectLogger } from '../logger';\nimport type {\n NameProvider,\n NameProviderMetadata,\n NameProviderRequest,\n NameProviderResult,\n} from '../types';\nimport { NameType } from '../types';\nimport { handleFetch } from '../util';\n\nconst ID = 'token';\nconst LABEL = 'Blockchain (Token Name)';\n\nconst log = createModuleLogger(projectLogger, 'token');\n\nexport class TokenNameProvider implements NameProvider {\n #isEnabled: () => boolean;\n\n constructor({ isEnabled }: { isEnabled?: () => boolean } = {}) {\n this.#isEnabled = isEnabled || (() => true);\n }\n\n getMetadata(): NameProviderMetadata {\n return {\n sourceIds: { [NameType.ETHEREUM_ADDRESS]: [ID] },\n sourceLabels: { [ID]: LABEL },\n };\n }\n\n async getProposedNames(\n request: NameProviderRequest,\n ): Promise<NameProviderResult> {\n if (!this.#isEnabled()) {\n log('Skipping request as disabled');\n\n return {\n results: {\n [ID]: {\n proposedNames: [],\n },\n },\n };\n }\n\n const { value, chainId } = request;\n const url = `https://token-api.metaswap.codefi.network/token/${chainId}?address=${value}`;\n\n log('Sending request', url);\n\n try {\n const responseData = await handleFetch(url);\n const proposedName = responseData.name;\n const proposedNames = proposedName ? [proposedName] : [];\n\n log('New proposed names', proposedNames);\n\n return {\n results: {\n [ID]: {\n proposedNames,\n },\n },\n };\n } catch (error) {\n log('Request failed', error);\n throw error;\n }\n }\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -34,6 +34,11 @@ export declare type NameProviderSourceResult = {
34
34
  * Undefined if there is an error.
35
35
  */
36
36
  proposedNames?: string[];
37
+ /**
38
+ * The delay in seconds before the next request to the source should be made.
39
+ * Can be used to avoid rate limiting for example.
40
+ */
41
+ updateDelay?: number;
37
42
  /**
38
43
  * An error that occurred while fetching the proposed names from the source.
39
44
  * Undefined if there was no error.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,oBAAY,QAAQ;IAClB,0CAA0C;IAC1C,gBAAgB,oBAAoB;CACrC;AAED,wCAAwC;AACxC,oBAAY,oBAAoB,GAAG;IACjC;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAEtC;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC,CAAC;AAEF,mEAAmE;AACnE,oBAAY,mBAAmB,GAAG;IAChC,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAEhB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB,wCAAwC;IACxC,IAAI,EAAE,QAAQ,CAAC;IAEf,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,oGAAoG;AACpG,oBAAY,wBAAwB,GAAG;IACrC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,+EAA+E;AAC/E,oBAAY,kBAAkB,GAAG;IAC/B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IAElD;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,qFAAqF;AACrF,oBAAY,YAAY,GAAG;IACzB;;OAEG;IACH,WAAW,IAAI,oBAAoB,CAAC;IAEpC;;;;OAIG;IACH,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC7E,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,oBAAY,QAAQ;IAClB,0CAA0C;IAC1C,gBAAgB,oBAAoB;CACrC;AAED,wCAAwC;AACxC,oBAAY,oBAAoB,GAAG;IACjC;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAEtC;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC,CAAC;AAEF,mEAAmE;AACnE,oBAAY,mBAAmB,GAAG;IAChC,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAEhB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB,wCAAwC;IACxC,IAAI,EAAE,QAAQ,CAAC;IAEf,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,oGAAoG;AACpG,oBAAY,wBAAwB,GAAG;IACrC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,+EAA+E;AAC/E,oBAAY,kBAAkB,GAAG;IAC/B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IAElD;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,qFAAqF;AACrF,oBAAY,YAAY,GAAG;IACzB;;OAEG;IACH,WAAW,IAAI,oBAAoB,CAAC;IAEpC;;;;OAIG;IACH,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC7E,CAAC"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAAA,sDAAsD;AACtD,IAAY,QAGX;AAHD,WAAY,QAAQ;IAClB,0CAA0C;IAC1C,gDAAoC,CAAA;AACtC,CAAC,EAHW,QAAQ,GAAR,gBAAQ,KAAR,gBAAQ,QAGnB","sourcesContent":["/** The name types supported by the NameController. */\nexport enum NameType {\n /** The address of an Ethereum account. */\n ETHEREUM_ADDRESS = 'ethereumAddress',\n}\n\n/** The metadata for a name provider. */\nexport type NameProviderMetadata = {\n /**\n * IDs for each alternate source of proposed names.\n * Keyed by the name type.\n */\n sourceIds: Record<NameType, string[]>;\n\n /**\n * Friendly labels to describe each source of proposed names.\n * Keyed by the source ID.\n */\n sourceLabels: Record<string, string>;\n};\n\n/** The request data to get proposed names from a name provider. */\nexport type NameProviderRequest = {\n /** The current chain ID of the client. */\n chainId: string;\n\n /** The optional list of source IDs to get proposed names from. */\n sourceIds?: string[];\n\n /** The type of name being requested. */\n type: NameType;\n\n /** The raw value to get proposed names for. */\n value: string;\n};\n\n/** The resulting data after requesting proposed names from a name provider, for a single source. */\nexport type NameProviderSourceResult = {\n /**\n * The array of proposed names from the source.\n * Undefined if there is an error.\n */\n proposedNames?: string[];\n\n /**\n * An error that occurred while fetching the proposed names from the source.\n * Undefined if there was no error.\n */\n error?: unknown;\n};\n\n/** The resulting data after requesting proposed names from a name provider. */\nexport type NameProviderResult = {\n /**\n * The resulting data from each alternate source of proposed names supported by the name provider.\n * Keyed by the source ID.\n */\n results: Record<string, NameProviderSourceResult>;\n\n /**\n * An error that occurred while fetching the proposed names that was not specific to a single source.\n * Undefined if there was no error.\n */\n error?: unknown;\n};\n\n/** An object capable of proposing friendly names for a raw value of a given type. */\nexport type NameProvider = {\n /**\n * Returns metadata about the name provider.\n */\n getMetadata(): NameProviderMetadata;\n\n /**\n * Returns proposed names for the given value and request data.\n *\n * @param request - The request data including the value to propose names for.\n */\n getProposedNames(request: NameProviderRequest): Promise<NameProviderResult>;\n};\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAAA,sDAAsD;AACtD,IAAY,QAGX;AAHD,WAAY,QAAQ;IAClB,0CAA0C;IAC1C,gDAAoC,CAAA;AACtC,CAAC,EAHW,QAAQ,GAAR,gBAAQ,KAAR,gBAAQ,QAGnB","sourcesContent":["/** The name types supported by the NameController. */\nexport enum NameType {\n /** The address of an Ethereum account. */\n ETHEREUM_ADDRESS = 'ethereumAddress',\n}\n\n/** The metadata for a name provider. */\nexport type NameProviderMetadata = {\n /**\n * IDs for each alternate source of proposed names.\n * Keyed by the name type.\n */\n sourceIds: Record<NameType, string[]>;\n\n /**\n * Friendly labels to describe each source of proposed names.\n * Keyed by the source ID.\n */\n sourceLabels: Record<string, string>;\n};\n\n/** The request data to get proposed names from a name provider. */\nexport type NameProviderRequest = {\n /** The current chain ID of the client. */\n chainId: string;\n\n /** The optional list of source IDs to get proposed names from. */\n sourceIds?: string[];\n\n /** The type of name being requested. */\n type: NameType;\n\n /** The raw value to get proposed names for. */\n value: string;\n};\n\n/** The resulting data after requesting proposed names from a name provider, for a single source. */\nexport type NameProviderSourceResult = {\n /**\n * The array of proposed names from the source.\n * Undefined if there is an error.\n */\n proposedNames?: string[];\n\n /**\n * The delay in seconds before the next request to the source should be made.\n * Can be used to avoid rate limiting for example.\n */\n updateDelay?: number;\n\n /**\n * An error that occurred while fetching the proposed names from the source.\n * Undefined if there was no error.\n */\n error?: unknown;\n};\n\n/** The resulting data after requesting proposed names from a name provider. */\nexport type NameProviderResult = {\n /**\n * The resulting data from each alternate source of proposed names supported by the name provider.\n * Keyed by the source ID.\n */\n results: Record<string, NameProviderSourceResult>;\n\n /**\n * An error that occurred while fetching the proposed names that was not specific to a single source.\n * Undefined if there was no error.\n */\n error?: unknown;\n};\n\n/** An object capable of proposing friendly names for a raw value of a given type. */\nexport type NameProvider = {\n /**\n * Returns metadata about the name provider.\n */\n getMetadata(): NameProviderMetadata;\n\n /**\n * Returns proposed names for the given value and request data.\n *\n * @param request - The request data including the value to propose names for.\n */\n getProposedNames(request: NameProviderRequest): Promise<NameProviderResult>;\n};\n"]}
package/dist/util.d.ts CHANGED
@@ -22,4 +22,14 @@ export declare function handleFetch(request: string, options?: RequestInit): Pro
22
22
  * @returns The fetch response.
23
23
  */
24
24
  export declare function successfulFetch(request: string, options?: RequestInit): Promise<Response>;
25
+ /**
26
+ * Assert that a value is an error. If it's not an error, throw an
27
+ * error that wraps the given value.
28
+ *
29
+ * TODO: Migrate this to @metamask/utils
30
+ *
31
+ * @param error - The value that we expect to be an error.
32
+ * @throws Throws an error wrapping the given value if it's not an error.
33
+ */
34
+ export declare function assertIsError(error: unknown): asserts error is Error;
25
35
  //# sourceMappingURL=util.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAsB,OAAO,CAAC,CAAC,EAC7B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC,CAeZ;AAID;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,gBAIvE;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,qBAQ3E"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAsB,OAAO,CAAC,CAAC,EAC7B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC,CAeZ;AAID;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,gBAIvE;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,qBAQ3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAKpE"}
package/dist/util.js CHANGED
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.successfulFetch = exports.handleFetch = exports.graphQL = void 0;
12
+ exports.assertIsError = exports.successfulFetch = exports.handleFetch = exports.graphQL = void 0;
13
13
  /**
14
14
  * Execute a GraphQL query.
15
15
  *
@@ -67,4 +67,20 @@ function successfulFetch(request, options) {
67
67
  });
68
68
  }
69
69
  exports.successfulFetch = successfulFetch;
70
+ /**
71
+ * Assert that a value is an error. If it's not an error, throw an
72
+ * error that wraps the given value.
73
+ *
74
+ * TODO: Migrate this to @metamask/utils
75
+ *
76
+ * @param error - The value that we expect to be an error.
77
+ * @throws Throws an error wrapping the given value if it's not an error.
78
+ */
79
+ function assertIsError(error) {
80
+ if (error instanceof Error) {
81
+ return;
82
+ }
83
+ throw new Error(`Invalid error of type '${typeof error}'`);
84
+ }
85
+ exports.assertIsError = assertIsError;
70
86
  //# sourceMappingURL=util.js.map
package/dist/util.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA;;;;;;GAMG;AACH,SAAsB,OAAO,CAC3B,GAAW,EACX,KAAa,EACb,SAA8B;;QAE9B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,KAAK;YACL,SAAS;SACV,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE;YACtC,IAAI;YACJ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;aACnC;SACF,CAAC,CAAC;QAEH,OAAO,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI,CAAC;IACxB,CAAC;CAAA;AAnBD,0BAmBC;AAED,+FAA+F;AAE/F;;;;;;GAMG;AACH,SAAsB,WAAW,CAAC,OAAe,EAAE,OAAqB;;QACtE,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrC,OAAO,MAAM,CAAC;IAChB,CAAC;CAAA;AAJD,kCAIC;AAED;;;;;;GAMG;AACH,SAAsB,eAAe,CAAC,OAAe,EAAE,OAAqB;;QAC1E,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;YAChB,MAAM,IAAI,KAAK,CACb,6BAA6B,QAAQ,CAAC,MAAM,kBAAkB,OAAO,GAAG,CACzE,CAAC;SACH;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CAAA;AARD,0CAQC","sourcesContent":["/**\n * Execute a GraphQL query.\n *\n * @param url - GraphQL endpoint URL.\n * @param query - GraphQL query.\n * @param variables - GraphQL variables.\n */\nexport async function graphQL<T>(\n url: string,\n query: string,\n variables: Record<string, any>,\n): Promise<T> {\n const body = JSON.stringify({\n query,\n variables,\n });\n\n const response = await handleFetch(url, {\n body,\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n return response?.data;\n}\n\n// Below functions are intentionally copied from controller-utils to avoid a package dependency\n\n/**\n * Execute fetch and return object response.\n *\n * @param request - The request information.\n * @param options - The fetch options.\n * @returns The fetch response JSON data.\n */\nexport async function handleFetch(request: string, options?: RequestInit) {\n const response = await successfulFetch(request, options);\n const object = await response.json();\n return object;\n}\n\n/**\n * Execute fetch and verify that the response was successful.\n *\n * @param request - Request information.\n * @param options - Fetch options.\n * @returns The fetch response.\n */\nexport async function successfulFetch(request: string, options?: RequestInit) {\n const response = await fetch(request, options);\n if (!response.ok) {\n throw new Error(\n `Fetch failed with status '${response.status}' for request '${request}'`,\n );\n }\n return response;\n}\n"]}
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA;;;;;;GAMG;AACH,SAAsB,OAAO,CAC3B,GAAW,EACX,KAAa,EACb,SAA8B;;QAE9B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,KAAK;YACL,SAAS;SACV,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE;YACtC,IAAI;YACJ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;aACnC;SACF,CAAC,CAAC;QAEH,OAAO,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI,CAAC;IACxB,CAAC;CAAA;AAnBD,0BAmBC;AAED,+FAA+F;AAE/F;;;;;;GAMG;AACH,SAAsB,WAAW,CAAC,OAAe,EAAE,OAAqB;;QACtE,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrC,OAAO,MAAM,CAAC;IAChB,CAAC;CAAA;AAJD,kCAIC;AAED;;;;;;GAMG;AACH,SAAsB,eAAe,CAAC,OAAe,EAAE,OAAqB;;QAC1E,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;YAChB,MAAM,IAAI,KAAK,CACb,6BAA6B,QAAQ,CAAC,MAAM,kBAAkB,OAAO,GAAG,CACzE,CAAC;SACH;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CAAA;AARD,0CAQC;AAED;;;;;;;;GAQG;AACH,SAAgB,aAAa,CAAC,KAAc;IAC1C,IAAI,KAAK,YAAY,KAAK,EAAE;QAC1B,OAAO;KACR;IACD,MAAM,IAAI,KAAK,CAAC,0BAA0B,OAAO,KAAK,GAAG,CAAC,CAAC;AAC7D,CAAC;AALD,sCAKC","sourcesContent":["/**\n * Execute a GraphQL query.\n *\n * @param url - GraphQL endpoint URL.\n * @param query - GraphQL query.\n * @param variables - GraphQL variables.\n */\nexport async function graphQL<T>(\n url: string,\n query: string,\n variables: Record<string, any>,\n): Promise<T> {\n const body = JSON.stringify({\n query,\n variables,\n });\n\n const response = await handleFetch(url, {\n body,\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n return response?.data;\n}\n\n// Below functions are intentionally copied from controller-utils to avoid a package dependency\n\n/**\n * Execute fetch and return object response.\n *\n * @param request - The request information.\n * @param options - The fetch options.\n * @returns The fetch response JSON data.\n */\nexport async function handleFetch(request: string, options?: RequestInit) {\n const response = await successfulFetch(request, options);\n const object = await response.json();\n return object;\n}\n\n/**\n * Execute fetch and verify that the response was successful.\n *\n * @param request - Request information.\n * @param options - Fetch options.\n * @returns The fetch response.\n */\nexport async function successfulFetch(request: string, options?: RequestInit) {\n const response = await fetch(request, options);\n if (!response.ok) {\n throw new Error(\n `Fetch failed with status '${response.status}' for request '${request}'`,\n );\n }\n return response;\n}\n\n/**\n * Assert that a value is an error. If it's not an error, throw an\n * error that wraps the given value.\n *\n * TODO: Migrate this to @metamask/utils\n *\n * @param error - The value that we expect to be an error.\n * @throws Throws an error wrapping the given value if it's not an error.\n */\nexport function assertIsError(error: unknown): asserts error is Error {\n if (error instanceof Error) {\n return;\n }\n throw new Error(`Invalid error of type '${typeof error}'`);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/name-controller",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "Stores and suggests names for values such as Ethereum addresses",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -29,7 +29,9 @@
29
29
  "test:watch": "jest --watch"
30
30
  },
31
31
  "dependencies": {
32
- "@metamask/base-controller": "^3.2.1",
32
+ "@metamask/base-controller": "^3.2.2",
33
+ "@metamask/utils": "^6.2.0",
34
+ "async-mutex": "^0.2.6",
33
35
  "immer": "^9.0.6"
34
36
  },
35
37
  "devDependencies": {
@@ -38,9 +40,9 @@
38
40
  "deepmerge": "^4.2.2",
39
41
  "jest": "^27.5.1",
40
42
  "ts-jest": "^27.1.4",
41
- "typedoc": "^0.22.15",
42
- "typedoc-plugin-missing-exports": "^0.22.6",
43
- "typescript": "~4.6.3"
43
+ "typedoc": "^0.23.15",
44
+ "typedoc-plugin-missing-exports": "^0.23.0",
45
+ "typescript": "~4.8.4"
44
46
  },
45
47
  "engines": {
46
48
  "node": ">=16.0.0"