@metamask-previews/profile-metrics-controller 0.0.0-preview-e0d310b4
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 +14 -0
- package/LICENSE +20 -0
- package/README.md +13 -0
- package/dist/ProfileMetricsController.cjs +230 -0
- package/dist/ProfileMetricsController.cjs.map +1 -0
- package/dist/ProfileMetricsController.d.cts +120 -0
- package/dist/ProfileMetricsController.d.cts.map +1 -0
- package/dist/ProfileMetricsController.d.mts +120 -0
- package/dist/ProfileMetricsController.d.mts.map +1 -0
- package/dist/ProfileMetricsController.mjs +225 -0
- package/dist/ProfileMetricsController.mjs.map +1 -0
- package/dist/ProfileMetricsService-method-action-types.cjs +7 -0
- package/dist/ProfileMetricsService-method-action-types.cjs.map +1 -0
- package/dist/ProfileMetricsService-method-action-types.d.cts +20 -0
- package/dist/ProfileMetricsService-method-action-types.d.cts.map +1 -0
- package/dist/ProfileMetricsService-method-action-types.d.mts +20 -0
- package/dist/ProfileMetricsService-method-action-types.d.mts.map +1 -0
- package/dist/ProfileMetricsService-method-action-types.mjs +6 -0
- package/dist/ProfileMetricsService-method-action-types.mjs.map +1 -0
- package/dist/ProfileMetricsService.cjs +144 -0
- package/dist/ProfileMetricsService.cjs.map +1 -0
- package/dist/ProfileMetricsService.d.cts +120 -0
- package/dist/ProfileMetricsService.d.cts.map +1 -0
- package/dist/ProfileMetricsService.d.mts +120 -0
- package/dist/ProfileMetricsService.d.mts.map +1 -0
- package/dist/ProfileMetricsService.mjs +140 -0
- package/dist/ProfileMetricsService.mjs.map +1 -0
- package/dist/constants.cjs +29 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/constants.d.cts +14 -0
- package/dist/constants.d.cts.map +1 -0
- package/dist/constants.d.mts +14 -0
- package/dist/constants.d.mts.map +1 -0
- package/dist/constants.mjs +25 -0
- package/dist/constants.mjs.map +1 -0
- package/dist/index.cjs +13 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +7 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +4 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
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");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
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");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _ProfileMetricsController_instances, _ProfileMetricsController_mutex, _ProfileMetricsController_assertUserOptedIn, _ProfileMetricsController_getMetaMetricsId, _ProfileMetricsController_queueFirstSyncIfNeeded, _ProfileMetricsController_addAccountToQueue, _ProfileMetricsController_removeAccountFromQueue;
|
|
13
|
+
import { StaticIntervalPollingController } from "@metamask/polling-controller";
|
|
14
|
+
import { Mutex } from "async-mutex";
|
|
15
|
+
/**
|
|
16
|
+
* The name of the {@link ProfileMetricsController}, used to namespace the
|
|
17
|
+
* controller's actions and events and to namespace the controller's state data
|
|
18
|
+
* when composed with other controllers.
|
|
19
|
+
*/
|
|
20
|
+
export const controllerName = 'ProfileMetricsController';
|
|
21
|
+
/**
|
|
22
|
+
* The metadata for each property in {@link ProfileMetricsControllerState}.
|
|
23
|
+
*/
|
|
24
|
+
const userProfileControllerMetadata = {
|
|
25
|
+
firstSyncCompleted: {
|
|
26
|
+
persist: true,
|
|
27
|
+
includeInDebugSnapshot: true,
|
|
28
|
+
includeInStateLogs: true,
|
|
29
|
+
usedInUi: false,
|
|
30
|
+
},
|
|
31
|
+
syncQueue: {
|
|
32
|
+
persist: true,
|
|
33
|
+
includeInDebugSnapshot: false,
|
|
34
|
+
includeInStateLogs: true,
|
|
35
|
+
usedInUi: false,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Constructs the default {@link ProfileMetricsController} state. This allows
|
|
40
|
+
* consumers to provide a partial state object when initializing the controller
|
|
41
|
+
* and also helps in constructing complete state objects for this controller in
|
|
42
|
+
* tests.
|
|
43
|
+
*
|
|
44
|
+
* @returns The default {@link ProfileMetricsController} state.
|
|
45
|
+
*/
|
|
46
|
+
export function getDefaultProfileMetricsControllerState() {
|
|
47
|
+
return {
|
|
48
|
+
firstSyncCompleted: false,
|
|
49
|
+
syncQueue: {},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const MESSENGER_EXPOSED_METHODS = [];
|
|
53
|
+
export class ProfileMetricsController extends StaticIntervalPollingController() {
|
|
54
|
+
/**
|
|
55
|
+
* Constructs a new {@link ProfileMetricsController}.
|
|
56
|
+
*
|
|
57
|
+
* @param args - The constructor arguments.
|
|
58
|
+
* @param args.messenger - The messenger suited for this controller.
|
|
59
|
+
* @param args.state - The desired state with which to initialize this
|
|
60
|
+
* controller. Missing properties will be filled in with defaults.
|
|
61
|
+
* @param args.assertUserOptedIn - A function that asserts whether the user has
|
|
62
|
+
* opted in to user profile features. If the user has not opted in, sync
|
|
63
|
+
* operations will be no-ops.
|
|
64
|
+
* @param args.getMetaMetricsId - A function that returns the MetaMetrics ID
|
|
65
|
+
* of the user.
|
|
66
|
+
* @param args.interval - The interval, in milliseconds, at which the controller will
|
|
67
|
+
* attempt to send user profile data. Defaults to 10 seconds.
|
|
68
|
+
*/
|
|
69
|
+
constructor({ messenger, state, assertUserOptedIn, getMetaMetricsId, interval = 10 * 1000, }) {
|
|
70
|
+
super({
|
|
71
|
+
messenger,
|
|
72
|
+
metadata: userProfileControllerMetadata,
|
|
73
|
+
name: controllerName,
|
|
74
|
+
state: {
|
|
75
|
+
...getDefaultProfileMetricsControllerState(),
|
|
76
|
+
...state,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
_ProfileMetricsController_instances.add(this);
|
|
80
|
+
_ProfileMetricsController_mutex.set(this, new Mutex());
|
|
81
|
+
_ProfileMetricsController_assertUserOptedIn.set(this, void 0);
|
|
82
|
+
_ProfileMetricsController_getMetaMetricsId.set(this, void 0);
|
|
83
|
+
__classPrivateFieldSet(this, _ProfileMetricsController_assertUserOptedIn, assertUserOptedIn, "f");
|
|
84
|
+
__classPrivateFieldSet(this, _ProfileMetricsController_getMetaMetricsId, getMetaMetricsId, "f");
|
|
85
|
+
this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
86
|
+
this.messenger.subscribe('KeyringController:unlock', () => {
|
|
87
|
+
this.startPolling(null);
|
|
88
|
+
__classPrivateFieldGet(this, _ProfileMetricsController_instances, "m", _ProfileMetricsController_queueFirstSyncIfNeeded).call(this).catch(console.error);
|
|
89
|
+
});
|
|
90
|
+
this.messenger.subscribe('KeyringController:lock', () => {
|
|
91
|
+
this.stopAllPolling();
|
|
92
|
+
});
|
|
93
|
+
this.messenger.subscribe('AccountsController:accountAdded', (account) => {
|
|
94
|
+
__classPrivateFieldGet(this, _ProfileMetricsController_instances, "m", _ProfileMetricsController_addAccountToQueue).call(this, account).catch(console.error);
|
|
95
|
+
});
|
|
96
|
+
this.messenger.subscribe('AccountsController:accountRemoved', (account) => {
|
|
97
|
+
__classPrivateFieldGet(this, _ProfileMetricsController_instances, "m", _ProfileMetricsController_removeAccountFromQueue).call(this, account).catch(console.error);
|
|
98
|
+
});
|
|
99
|
+
this.setIntervalLength(interval);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Execute a single poll to sync user profile data.
|
|
103
|
+
*
|
|
104
|
+
* The queued accounts are sent to the ProfileMetricsService, and the sync
|
|
105
|
+
* queue is cleared. This operation is mutexed to prevent concurrent
|
|
106
|
+
* executions.
|
|
107
|
+
*
|
|
108
|
+
* @returns A promise that resolves when the poll is complete.
|
|
109
|
+
*/
|
|
110
|
+
async _executePoll() {
|
|
111
|
+
await __classPrivateFieldGet(this, _ProfileMetricsController_mutex, "f").runExclusive(async () => {
|
|
112
|
+
for (const [entropySourceId, accounts] of Object.entries(this.state.syncQueue)) {
|
|
113
|
+
await this.messenger.call('ProfileMetricsService:updateProfile', {
|
|
114
|
+
metametricsId: __classPrivateFieldGet(this, _ProfileMetricsController_getMetaMetricsId, "f").call(this),
|
|
115
|
+
entropySourceId: entropySourceId === 'null' ? null : entropySourceId,
|
|
116
|
+
accounts,
|
|
117
|
+
});
|
|
118
|
+
this.update((state) => {
|
|
119
|
+
delete state.syncQueue[entropySourceId];
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
_ProfileMetricsController_mutex = new WeakMap(), _ProfileMetricsController_assertUserOptedIn = new WeakMap(), _ProfileMetricsController_getMetaMetricsId = new WeakMap(), _ProfileMetricsController_instances = new WeakSet(), _ProfileMetricsController_queueFirstSyncIfNeeded =
|
|
126
|
+
/**
|
|
127
|
+
* Add existing accounts to the sync queue if it has not been done yet.
|
|
128
|
+
*
|
|
129
|
+
* This method ensures that the first sync is only executed once,
|
|
130
|
+
* and only if the user has opted in to user profile features.
|
|
131
|
+
*/
|
|
132
|
+
async function _ProfileMetricsController_queueFirstSyncIfNeeded() {
|
|
133
|
+
await __classPrivateFieldGet(this, _ProfileMetricsController_mutex, "f").runExclusive(async () => {
|
|
134
|
+
if (this.state.firstSyncCompleted || !__classPrivateFieldGet(this, _ProfileMetricsController_assertUserOptedIn, "f").call(this)) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const newGroupedAccounts = groupAccountsByEntropySourceId(this.messenger.call('AccountsController:listAccounts'));
|
|
138
|
+
const queuedAddresses = { ...this.state.syncQueue };
|
|
139
|
+
for (const key of Object.keys(newGroupedAccounts)) {
|
|
140
|
+
if (!queuedAddresses[key]) {
|
|
141
|
+
queuedAddresses[key] = [];
|
|
142
|
+
}
|
|
143
|
+
queuedAddresses[key].push(...newGroupedAccounts[key]);
|
|
144
|
+
}
|
|
145
|
+
this.update((state) => {
|
|
146
|
+
state.firstSyncCompleted = true;
|
|
147
|
+
state.syncQueue = queuedAddresses;
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
}, _ProfileMetricsController_addAccountToQueue =
|
|
151
|
+
/**
|
|
152
|
+
* Queue the given account to be synced at the next poll.
|
|
153
|
+
*
|
|
154
|
+
* @param account - The account to sync.
|
|
155
|
+
*/
|
|
156
|
+
async function _ProfileMetricsController_addAccountToQueue(account) {
|
|
157
|
+
await __classPrivateFieldGet(this, _ProfileMetricsController_mutex, "f").runExclusive(async () => {
|
|
158
|
+
if (!__classPrivateFieldGet(this, _ProfileMetricsController_assertUserOptedIn, "f").call(this)) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
this.update((state) => {
|
|
162
|
+
const entropySourceId = getAccountEntropySourceId(account) || 'null';
|
|
163
|
+
if (!state.syncQueue[entropySourceId]) {
|
|
164
|
+
state.syncQueue[entropySourceId] = [];
|
|
165
|
+
}
|
|
166
|
+
state.syncQueue[entropySourceId].push({
|
|
167
|
+
address: account.address,
|
|
168
|
+
scopes: account.scopes,
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
}, _ProfileMetricsController_removeAccountFromQueue =
|
|
173
|
+
/**
|
|
174
|
+
* Remove the given account from the sync queue.
|
|
175
|
+
*
|
|
176
|
+
* @param account - The account address to remove.
|
|
177
|
+
*/
|
|
178
|
+
async function _ProfileMetricsController_removeAccountFromQueue(account) {
|
|
179
|
+
await __classPrivateFieldGet(this, _ProfileMetricsController_mutex, "f").runExclusive(async () => {
|
|
180
|
+
this.update((state) => {
|
|
181
|
+
for (const [entropySourceId, groupedAddresses] of Object.entries(state.syncQueue)) {
|
|
182
|
+
const index = groupedAddresses.findIndex(({ address }) => address === account);
|
|
183
|
+
if (index === -1) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
groupedAddresses.splice(index, 1);
|
|
187
|
+
if (groupedAddresses.length === 0) {
|
|
188
|
+
delete state.syncQueue[entropySourceId];
|
|
189
|
+
}
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
196
|
+
* Retrieves the entropy source ID from the given account, if it exists.
|
|
197
|
+
*
|
|
198
|
+
* @param account - The account from which to retrieve the entropy source ID.
|
|
199
|
+
* @returns The entropy source ID, or null if it does not exist.
|
|
200
|
+
*/
|
|
201
|
+
function getAccountEntropySourceId(account) {
|
|
202
|
+
if (account.options.entropy && account.options.entropy.type === 'mnemonic') {
|
|
203
|
+
return account.options.entropy.id;
|
|
204
|
+
}
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Groups accounts by their entropy source ID.
|
|
209
|
+
*
|
|
210
|
+
* @param accounts - The accounts to group.
|
|
211
|
+
* @returns An object where each key is an entropy source ID and each value is
|
|
212
|
+
* an array of account addresses associated with that entropy source ID.
|
|
213
|
+
*/
|
|
214
|
+
function groupAccountsByEntropySourceId(accounts) {
|
|
215
|
+
return accounts.reduce((result, account) => {
|
|
216
|
+
const entropySourceId = getAccountEntropySourceId(account);
|
|
217
|
+
const key = entropySourceId || 'null';
|
|
218
|
+
if (!result[key]) {
|
|
219
|
+
result[key] = [];
|
|
220
|
+
}
|
|
221
|
+
result[key].push({ address: account.address, scopes: account.scopes });
|
|
222
|
+
return result;
|
|
223
|
+
}, {});
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=ProfileMetricsController.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProfileMetricsController.mjs","sourceRoot":"","sources":["../src/ProfileMetricsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerAccountAddedEvent,\n AccountsControllerListAccountsAction,\n AccountsControllerAccountRemovedEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport type {\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { Mutex } from 'async-mutex';\n\nimport type { ProfileMetricsServiceMethodActions } from '.';\nimport type { AccountWithScopes } from './ProfileMetricsService';\n\n/**\n * The name of the {@link ProfileMetricsController}, used to namespace the\n * controller's actions and events and to namespace the controller's state data\n * when composed with other controllers.\n */\nexport const controllerName = 'ProfileMetricsController';\n\n/**\n * Describes the shape of the state object for {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerState = {\n /**\n * Whether the first sync has been completed.\n */\n firstSyncCompleted: boolean;\n /**\n * The queue of accounts to be synced.\n * Each key is an entropy source ID, and each value is an array of account\n * addresses associated with that entropy source. Accounts with no entropy\n * source ID are grouped under the key \"null\".\n */\n syncQueue: Record<string, AccountWithScopes[]>;\n};\n\n/**\n * The metadata for each property in {@link ProfileMetricsControllerState}.\n */\nconst userProfileControllerMetadata = {\n firstSyncCompleted: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: false,\n },\n syncQueue: {\n persist: true,\n includeInDebugSnapshot: false,\n includeInStateLogs: true,\n usedInUi: false,\n },\n} satisfies StateMetadata<ProfileMetricsControllerState>;\n\n/**\n * Constructs the default {@link ProfileMetricsController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link ProfileMetricsController} state.\n */\nexport function getDefaultProfileMetricsControllerState(): ProfileMetricsControllerState {\n return {\n firstSyncCompleted: false,\n syncQueue: {},\n };\n}\n\nconst MESSENGER_EXPOSED_METHODS = [] as const;\n\n/**\n * Retrieves the state of the {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n ProfileMetricsControllerState\n>;\n\n/**\n * Actions that {@link ProfileMetricsControllerMessenger} exposes to other consumers.\n */\nexport type ProfileMetricsControllerActions =\n | ProfileMetricsControllerGetStateAction\n | ProfileMetricsServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link ProfileMetricsControllerMessenger} calls.\n */\ntype AllowedActions =\n | ProfileMetricsServiceMethodActions\n | AccountsControllerListAccountsAction;\n\n/**\n * Published when the state of {@link ProfileMetricsController} changes.\n */\nexport type ProfileMetricsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n ProfileMetricsControllerState\n >;\n\n/**\n * Events that {@link ProfileMetricsControllerMessenger} exposes to other consumers.\n */\nexport type ProfileMetricsControllerEvents =\n ProfileMetricsControllerStateChangeEvent;\n\n/**\n * Events from other messengers that {@link ProfileMetricsControllerMessenger} subscribes\n * to.\n */\ntype AllowedEvents =\n | KeyringControllerUnlockEvent\n | KeyringControllerLockEvent\n | AccountsControllerAccountAddedEvent\n | AccountsControllerAccountRemovedEvent;\n\n/**\n * The messenger restricted to actions and events accessed by\n * {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerMessenger = Messenger<\n typeof controllerName,\n ProfileMetricsControllerActions | AllowedActions,\n ProfileMetricsControllerEvents | AllowedEvents\n>;\n\nexport class ProfileMetricsController extends StaticIntervalPollingController()<\n typeof controllerName,\n ProfileMetricsControllerState,\n ProfileMetricsControllerMessenger\n> {\n readonly #mutex = new Mutex();\n\n readonly #assertUserOptedIn: () => boolean;\n\n readonly #getMetaMetricsId: () => string;\n\n /**\n * Constructs a new {@link ProfileMetricsController}.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this controller.\n * @param args.state - The desired state with which to initialize this\n * controller. Missing properties will be filled in with defaults.\n * @param args.assertUserOptedIn - A function that asserts whether the user has\n * opted in to user profile features. If the user has not opted in, sync\n * operations will be no-ops.\n * @param args.getMetaMetricsId - A function that returns the MetaMetrics ID\n * of the user.\n * @param args.interval - The interval, in milliseconds, at which the controller will\n * attempt to send user profile data. Defaults to 10 seconds.\n */\n constructor({\n messenger,\n state,\n assertUserOptedIn,\n getMetaMetricsId,\n interval = 10 * 1000,\n }: {\n messenger: ProfileMetricsControllerMessenger;\n state?: Partial<ProfileMetricsControllerState>;\n interval?: number;\n assertUserOptedIn: () => boolean;\n getMetaMetricsId: () => string;\n }) {\n super({\n messenger,\n metadata: userProfileControllerMetadata,\n name: controllerName,\n state: {\n ...getDefaultProfileMetricsControllerState(),\n ...state,\n },\n });\n\n this.#assertUserOptedIn = assertUserOptedIn;\n this.#getMetaMetricsId = getMetaMetricsId;\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n this.messenger.subscribe('KeyringController:unlock', () => {\n this.startPolling(null);\n this.#queueFirstSyncIfNeeded().catch(console.error);\n });\n\n this.messenger.subscribe('KeyringController:lock', () => {\n this.stopAllPolling();\n });\n\n this.messenger.subscribe('AccountsController:accountAdded', (account) => {\n this.#addAccountToQueue(account).catch(console.error);\n });\n\n this.messenger.subscribe('AccountsController:accountRemoved', (account) => {\n this.#removeAccountFromQueue(account).catch(console.error);\n });\n\n this.setIntervalLength(interval);\n }\n\n /**\n * Execute a single poll to sync user profile data.\n *\n * The queued accounts are sent to the ProfileMetricsService, and the sync\n * queue is cleared. This operation is mutexed to prevent concurrent\n * executions.\n *\n * @returns A promise that resolves when the poll is complete.\n */\n async _executePoll(): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n for (const [entropySourceId, accounts] of Object.entries(\n this.state.syncQueue,\n )) {\n await this.messenger.call('ProfileMetricsService:updateProfile', {\n metametricsId: this.#getMetaMetricsId(),\n entropySourceId: entropySourceId === 'null' ? null : entropySourceId,\n accounts,\n });\n this.update((state) => {\n delete state.syncQueue[entropySourceId];\n });\n }\n });\n }\n\n /**\n * Add existing accounts to the sync queue if it has not been done yet.\n *\n * This method ensures that the first sync is only executed once,\n * and only if the user has opted in to user profile features.\n */\n async #queueFirstSyncIfNeeded() {\n await this.#mutex.runExclusive(async () => {\n if (this.state.firstSyncCompleted || !this.#assertUserOptedIn()) {\n return;\n }\n const newGroupedAccounts = groupAccountsByEntropySourceId(\n this.messenger.call('AccountsController:listAccounts'),\n );\n const queuedAddresses = { ...this.state.syncQueue };\n for (const key of Object.keys(newGroupedAccounts)) {\n if (!queuedAddresses[key]) {\n queuedAddresses[key] = [];\n }\n queuedAddresses[key].push(...newGroupedAccounts[key]);\n }\n this.update((state) => {\n state.firstSyncCompleted = true;\n state.syncQueue = queuedAddresses;\n });\n });\n }\n\n /**\n * Queue the given account to be synced at the next poll.\n *\n * @param account - The account to sync.\n */\n async #addAccountToQueue(account: InternalAccount) {\n await this.#mutex.runExclusive(async () => {\n if (!this.#assertUserOptedIn()) {\n return;\n }\n this.update((state) => {\n const entropySourceId = getAccountEntropySourceId(account) || 'null';\n if (!state.syncQueue[entropySourceId]) {\n state.syncQueue[entropySourceId] = [];\n }\n state.syncQueue[entropySourceId].push({\n address: account.address,\n scopes: account.scopes,\n });\n });\n });\n }\n\n /**\n * Remove the given account from the sync queue.\n *\n * @param account - The account address to remove.\n */\n async #removeAccountFromQueue(account: string) {\n await this.#mutex.runExclusive(async () => {\n this.update((state) => {\n for (const [entropySourceId, groupedAddresses] of Object.entries(\n state.syncQueue,\n )) {\n const index = groupedAddresses.findIndex(\n ({ address }) => address === account,\n );\n if (index === -1) {\n continue;\n }\n groupedAddresses.splice(index, 1);\n if (groupedAddresses.length === 0) {\n delete state.syncQueue[entropySourceId];\n }\n break;\n }\n });\n });\n }\n}\n\n/**\n * Retrieves the entropy source ID from the given account, if it exists.\n *\n * @param account - The account from which to retrieve the entropy source ID.\n * @returns The entropy source ID, or null if it does not exist.\n */\nfunction getAccountEntropySourceId(account: InternalAccount): string | null {\n if (account.options.entropy && account.options.entropy.type === 'mnemonic') {\n return account.options.entropy.id;\n }\n return null;\n}\n\n/**\n * Groups accounts by their entropy source ID.\n *\n * @param accounts - The accounts to group.\n * @returns An object where each key is an entropy source ID and each value is\n * an array of account addresses associated with that entropy source ID.\n */\nfunction groupAccountsByEntropySourceId(\n accounts: InternalAccount[],\n): Record<string, AccountWithScopes[]> {\n return accounts.reduce(\n (result: Record<string, AccountWithScopes[]>, account) => {\n const entropySourceId = getAccountEntropySourceId(account);\n const key = entropySourceId || 'null';\n if (!result[key]) {\n result[key] = [];\n }\n result[key].push({ address: account.address, scopes: account.scopes });\n return result;\n },\n {},\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProfileMetricsService-method-action-types.cjs","sourceRoot":"","sources":["../src/ProfileMetricsService-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated by `scripts/generate-method-action-types.ts`.\n * Do not edit manually.\n */\n\nimport type { ProfileMetricsService } from './ProfileMetricsService';\n\n/**\n * Makes a request to the API in order to update the user profile.\n *\n * @param data - The data to send in the profile update request.\n * @returns The response from the API.\n */\nexport type ProfileMetricsServiceUpdateProfileAction = {\n type: `ProfileMetricsService:updateProfile`;\n handler: ProfileMetricsService['updateProfile'];\n};\n\n/**\n * Union of all ProfileMetricsService action types.\n */\nexport type ProfileMetricsServiceMethodActions =\n ProfileMetricsServiceUpdateProfileAction;\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is auto generated by `scripts/generate-method-action-types.ts`.
|
|
3
|
+
* Do not edit manually.
|
|
4
|
+
*/
|
|
5
|
+
import type { ProfileMetricsService } from "./ProfileMetricsService.cjs";
|
|
6
|
+
/**
|
|
7
|
+
* Makes a request to the API in order to update the user profile.
|
|
8
|
+
*
|
|
9
|
+
* @param data - The data to send in the profile update request.
|
|
10
|
+
* @returns The response from the API.
|
|
11
|
+
*/
|
|
12
|
+
export type ProfileMetricsServiceUpdateProfileAction = {
|
|
13
|
+
type: `ProfileMetricsService:updateProfile`;
|
|
14
|
+
handler: ProfileMetricsService['updateProfile'];
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Union of all ProfileMetricsService action types.
|
|
18
|
+
*/
|
|
19
|
+
export type ProfileMetricsServiceMethodActions = ProfileMetricsServiceUpdateProfileAction;
|
|
20
|
+
//# sourceMappingURL=ProfileMetricsService-method-action-types.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProfileMetricsService-method-action-types.d.cts","sourceRoot":"","sources":["../src/ProfileMetricsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,oCAAgC;AAErE;;;;;GAKG;AACH,MAAM,MAAM,wCAAwC,GAAG;IACrD,IAAI,EAAE,qCAAqC,CAAC;IAC5C,OAAO,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAC;CACjD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kCAAkC,GAC5C,wCAAwC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is auto generated by `scripts/generate-method-action-types.ts`.
|
|
3
|
+
* Do not edit manually.
|
|
4
|
+
*/
|
|
5
|
+
import type { ProfileMetricsService } from "./ProfileMetricsService.mjs";
|
|
6
|
+
/**
|
|
7
|
+
* Makes a request to the API in order to update the user profile.
|
|
8
|
+
*
|
|
9
|
+
* @param data - The data to send in the profile update request.
|
|
10
|
+
* @returns The response from the API.
|
|
11
|
+
*/
|
|
12
|
+
export type ProfileMetricsServiceUpdateProfileAction = {
|
|
13
|
+
type: `ProfileMetricsService:updateProfile`;
|
|
14
|
+
handler: ProfileMetricsService['updateProfile'];
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Union of all ProfileMetricsService action types.
|
|
18
|
+
*/
|
|
19
|
+
export type ProfileMetricsServiceMethodActions = ProfileMetricsServiceUpdateProfileAction;
|
|
20
|
+
//# sourceMappingURL=ProfileMetricsService-method-action-types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProfileMetricsService-method-action-types.d.mts","sourceRoot":"","sources":["../src/ProfileMetricsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,oCAAgC;AAErE;;;;;GAKG;AACH,MAAM,MAAM,wCAAwC,GAAG;IACrD,IAAI,EAAE,qCAAqC,CAAC;IAC5C,OAAO,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAC;CACjD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kCAAkC,GAC5C,wCAAwC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProfileMetricsService-method-action-types.mjs","sourceRoot":"","sources":["../src/ProfileMetricsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated by `scripts/generate-method-action-types.ts`.\n * Do not edit manually.\n */\n\nimport type { ProfileMetricsService } from './ProfileMetricsService';\n\n/**\n * Makes a request to the API in order to update the user profile.\n *\n * @param data - The data to send in the profile update request.\n * @returns The response from the API.\n */\nexport type ProfileMetricsServiceUpdateProfileAction = {\n type: `ProfileMetricsService:updateProfile`;\n handler: ProfileMetricsService['updateProfile'];\n};\n\n/**\n * Union of all ProfileMetricsService action types.\n */\nexport type ProfileMetricsServiceMethodActions =\n ProfileMetricsServiceUpdateProfileAction;\n"]}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
+
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");
|
|
6
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
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");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var _a, _ProfileMetricsService_messenger, _ProfileMetricsService_fetch, _ProfileMetricsService_policy, _ProfileMetricsService_baseURL;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ProfileMetricsService = exports.serviceName = void 0;
|
|
16
|
+
const controller_utils_1 = require("@metamask/controller-utils");
|
|
17
|
+
const _1 = require("./index.cjs");
|
|
18
|
+
// === GENERAL ===
|
|
19
|
+
/**
|
|
20
|
+
* The name of the {@link ProfileMetricsService}, used to namespace the
|
|
21
|
+
* service's actions and events.
|
|
22
|
+
*/
|
|
23
|
+
exports.serviceName = 'ProfileMetricsService';
|
|
24
|
+
// === MESSENGER ===
|
|
25
|
+
const MESSENGER_EXPOSED_METHODS = ['updateProfile'];
|
|
26
|
+
// === SERVICE DEFINITION ===
|
|
27
|
+
class ProfileMetricsService {
|
|
28
|
+
/**
|
|
29
|
+
* Constructs a new ProfileMetricsService object.
|
|
30
|
+
*
|
|
31
|
+
* @param args - The constructor arguments.
|
|
32
|
+
* @param args.messenger - The messenger suited for this service.
|
|
33
|
+
* @param args.fetch - A function that can be used to make an HTTP request. If
|
|
34
|
+
* your JavaScript environment supports `fetch` natively, you'll probably want
|
|
35
|
+
* to pass that; otherwise you can pass an equivalent (such as `fetch` via
|
|
36
|
+
* `node-fetch`).
|
|
37
|
+
* @param args.policyOptions - Options to pass to `createServicePolicy`, which
|
|
38
|
+
* is used to wrap each request. See {@link CreateServicePolicyOptions}.
|
|
39
|
+
* @param args.env - The environment to determine the correct API endpoints.
|
|
40
|
+
*/
|
|
41
|
+
constructor({ messenger, fetch: fetchFunction, policyOptions = {}, env = _1.Env.DEV, }) {
|
|
42
|
+
/**
|
|
43
|
+
* The messenger suited for this service.
|
|
44
|
+
*/
|
|
45
|
+
_ProfileMetricsService_messenger.set(this, void 0);
|
|
46
|
+
/**
|
|
47
|
+
* A function that can be used to make an HTTP request.
|
|
48
|
+
*/
|
|
49
|
+
_ProfileMetricsService_fetch.set(this, void 0);
|
|
50
|
+
/**
|
|
51
|
+
* The policy that wraps the request.
|
|
52
|
+
*
|
|
53
|
+
* @see {@link createServicePolicy}
|
|
54
|
+
*/
|
|
55
|
+
_ProfileMetricsService_policy.set(this, void 0);
|
|
56
|
+
/**
|
|
57
|
+
* The API base URL environment.
|
|
58
|
+
*/
|
|
59
|
+
_ProfileMetricsService_baseURL.set(this, void 0);
|
|
60
|
+
this.name = exports.serviceName;
|
|
61
|
+
__classPrivateFieldSet(this, _ProfileMetricsService_messenger, messenger, "f");
|
|
62
|
+
__classPrivateFieldSet(this, _ProfileMetricsService_fetch, fetchFunction, "f");
|
|
63
|
+
__classPrivateFieldSet(this, _ProfileMetricsService_policy, (0, controller_utils_1.createServicePolicy)(policyOptions), "f");
|
|
64
|
+
__classPrivateFieldSet(this, _ProfileMetricsService_baseURL, (0, _1.getEnvUrl)(env), "f");
|
|
65
|
+
__classPrivateFieldGet(this, _ProfileMetricsService_messenger, "f").registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Registers a handler that will be called after a request returns a non-500
|
|
69
|
+
* response, causing a retry. Primarily useful in tests where timers are being
|
|
70
|
+
* mocked.
|
|
71
|
+
*
|
|
72
|
+
* @param listener - The handler to be called.
|
|
73
|
+
* @returns An object that can be used to unregister the handler. See
|
|
74
|
+
* {@link CockatielEvent}.
|
|
75
|
+
* @see {@link createServicePolicy}
|
|
76
|
+
*/
|
|
77
|
+
onRetry(listener) {
|
|
78
|
+
return __classPrivateFieldGet(this, _ProfileMetricsService_policy, "f").onRetry(listener);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Registers a handler that will be called after a set number of retry rounds
|
|
82
|
+
* prove that requests to the API endpoint consistently return a 5xx response.
|
|
83
|
+
*
|
|
84
|
+
* @param listener - The handler to be called.
|
|
85
|
+
* @returns An object that can be used to unregister the handler. See
|
|
86
|
+
* {@link CockatielEvent}.
|
|
87
|
+
* @see {@link createServicePolicy}
|
|
88
|
+
*/
|
|
89
|
+
onBreak(listener) {
|
|
90
|
+
return __classPrivateFieldGet(this, _ProfileMetricsService_policy, "f").onBreak(listener);
|
|
91
|
+
}
|
|
92
|
+
/* eslint-disable jsdoc/check-indentation */
|
|
93
|
+
/**
|
|
94
|
+
* Registers a handler that will be called under one of two circumstances:
|
|
95
|
+
*
|
|
96
|
+
* 1. After a set number of retries prove that requests to the API
|
|
97
|
+
* consistently result in one of the following failures:
|
|
98
|
+
* 1. A connection initiation error
|
|
99
|
+
* 2. A connection reset error
|
|
100
|
+
* 3. A timeout error
|
|
101
|
+
* 4. A non-JSON response
|
|
102
|
+
* 5. A 502, 503, or 504 response
|
|
103
|
+
* 2. After a successful request is made to the API, but the response takes
|
|
104
|
+
* longer than a set duration to return.
|
|
105
|
+
*
|
|
106
|
+
* @param listener - The handler to be called.
|
|
107
|
+
* @returns An object that can be used to unregister the handler. See
|
|
108
|
+
* {@link CockatielEvent}.
|
|
109
|
+
*/
|
|
110
|
+
/* eslint-enable jsdoc/check-indentation */
|
|
111
|
+
onDegraded(listener) {
|
|
112
|
+
return __classPrivateFieldGet(this, _ProfileMetricsService_policy, "f").onDegraded(listener);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Makes a request to the API in order to update the user profile.
|
|
116
|
+
*
|
|
117
|
+
* @param data - The data to send in the profile update request.
|
|
118
|
+
* @returns The response from the API.
|
|
119
|
+
*/
|
|
120
|
+
async updateProfile(data) {
|
|
121
|
+
const authToken = await __classPrivateFieldGet(this, _ProfileMetricsService_messenger, "f").call('AuthenticationController:getBearerToken', data.entropySourceId || undefined);
|
|
122
|
+
await __classPrivateFieldGet(this, _ProfileMetricsService_policy, "f").execute(async () => {
|
|
123
|
+
const url = new URL(`${__classPrivateFieldGet(this, _ProfileMetricsService_baseURL, "f")}/profile/accounts`);
|
|
124
|
+
const localResponse = await __classPrivateFieldGet(this, _ProfileMetricsService_fetch, "f").call(this, url, {
|
|
125
|
+
method: 'PUT',
|
|
126
|
+
headers: {
|
|
127
|
+
Authorization: `Bearer ${authToken}`,
|
|
128
|
+
'Content-Type': 'application/json',
|
|
129
|
+
},
|
|
130
|
+
body: JSON.stringify({
|
|
131
|
+
metametrics_id: data.metametricsId,
|
|
132
|
+
accounts: data.accounts,
|
|
133
|
+
}),
|
|
134
|
+
});
|
|
135
|
+
if (!localResponse.ok) {
|
|
136
|
+
throw new controller_utils_1.HttpError(localResponse.status, `Fetching '${url.toString()}' failed with status '${localResponse.status}'`);
|
|
137
|
+
}
|
|
138
|
+
return localResponse;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.ProfileMetricsService = ProfileMetricsService;
|
|
143
|
+
_a = ProfileMetricsService, _ProfileMetricsService_messenger = new WeakMap(), _ProfileMetricsService_fetch = new WeakMap(), _ProfileMetricsService_policy = new WeakMap(), _ProfileMetricsService_baseURL = new WeakMap();
|
|
144
|
+
//# sourceMappingURL=ProfileMetricsService.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProfileMetricsService.cjs","sourceRoot":"","sources":["../src/ProfileMetricsService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAIA,iEAA4E;AAI5E,kCAA4E;AAE5E,kBAAkB;AAElB;;;GAGG;AACU,QAAA,WAAW,GAAG,uBAAuB,CAAC;AAmBnD,oBAAoB;AAEpB,MAAM,yBAAyB,GAAG,CAAC,eAAe,CAAU,CAAC;AAkC7D,6BAA6B;AAE7B,MAAa,qBAAqB;IAgChC;;;;;;;;;;;;OAYG;IACH,YAAY,EACV,SAAS,EACT,KAAK,EAAE,aAAa,EACpB,aAAa,GAAG,EAAE,EAClB,GAAG,GAAG,MAAG,CAAC,GAAG,GAMd;QAjDD;;WAEG;QACM,mDAES;QAElB;;WAEG;QACM,+CAEK;QAEd;;;;WAIG;QACM,gDAAuB;QAEhC;;WAEG;QACM,iDAAiB;QA0BxB,IAAI,CAAC,IAAI,GAAG,mBAAW,CAAC;QACxB,uBAAA,IAAI,oCAAc,SAAS,MAAA,CAAC;QAC5B,uBAAA,IAAI,gCAAU,aAAa,MAAA,CAAC;QAC5B,uBAAA,IAAI,iCAAW,IAAA,sCAAmB,EAAC,aAAa,CAAC,MAAA,CAAC;QAClD,uBAAA,IAAI,kCAAY,IAAA,YAAS,EAAC,GAAG,CAAC,MAAA,CAAC;QAE/B,uBAAA,IAAI,wCAAW,CAAC,4BAA4B,CAC1C,IAAI,EACJ,yBAAyB,CAC1B,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACH,OAAO,CAAC,QAAiD;QACvD,OAAO,uBAAA,IAAI,qCAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAiD;QACvD,OAAO,uBAAA,IAAI,qCAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED,4CAA4C;IAC5C;;;;;;;;;;;;;;;;OAgBG;IACH,2CAA2C;IAC3C,UAAU,CAAC,QAAoD;QAC7D,OAAO,uBAAA,IAAI,qCAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,aAAa,CAAC,IAAiC;QACnD,MAAM,SAAS,GAAG,MAAM,uBAAA,IAAI,wCAAW,CAAC,IAAI,CAC1C,yCAAyC,EACzC,IAAI,CAAC,eAAe,IAAI,SAAS,CAClC,CAAC;QACF,MAAM,uBAAA,IAAI,qCAAQ,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE;YACpC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,uBAAA,IAAI,sCAAS,mBAAmB,CAAC,CAAC;YACzD,MAAM,aAAa,GAAG,MAAM,uBAAA,IAAI,oCAAO,MAAX,IAAI,EAAQ,GAAG,EAAE;gBAC3C,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,SAAS,EAAE;oBACpC,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,cAAc,EAAE,IAAI,CAAC,aAAa;oBAClC,QAAQ,EAAE,IAAI,CAAC,QAAQ;iBACxB,CAAC;aACH,CAAC,CAAC;YACH,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC;gBACtB,MAAM,IAAI,4BAAS,CACjB,aAAa,CAAC,MAAM,EACpB,aAAa,GAAG,CAAC,QAAQ,EAAE,yBAAyB,aAAa,CAAC,MAAM,GAAG,CAC5E,CAAC;YACJ,CAAC;YACD,OAAO,aAAa,CAAC;QACvB,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAvJD,sDAuJC","sourcesContent":["import type {\n CreateServicePolicyOptions,\n ServicePolicy,\n} from '@metamask/controller-utils';\nimport { createServicePolicy, HttpError } from '@metamask/controller-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport type { AuthenticationController } from '@metamask/profile-sync-controller';\n\nimport { type ProfileMetricsServiceMethodActions, Env, getEnvUrl } from '.';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link ProfileMetricsService}, used to namespace the\n * service's actions and events.\n */\nexport const serviceName = 'ProfileMetricsService';\n\n/**\n * An account address along with its associated scopes.\n */\nexport type AccountWithScopes = {\n address: string;\n scopes: `${string}:${string}`[];\n};\n\n/**\n * The shape of the request object for updating the user profile.\n */\nexport type ProfileMetricsUpdateRequest = {\n metametricsId: string;\n entropySourceId?: string | null;\n accounts: AccountWithScopes[];\n};\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = ['updateProfile'] as const;\n\n/**\n * Actions that {@link ProfileMetricsService} exposes to other consumers.\n */\nexport type ProfileMetricsServiceActions = ProfileMetricsServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link ProfileMetricsService} calls.\n */\ntype AllowedActions =\n AuthenticationController.AuthenticationControllerGetBearerToken;\n\n/**\n * Events that {@link ProfileMetricsService} exposes to other consumers.\n */\nexport type ProfileMetricsServiceEvents = never;\n\n/**\n * Events from other messengers that {@link ProfileMetricsService} subscribes\n * to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link ProfileMetricsService}.\n */\nexport type ProfileMetricsServiceMessenger = Messenger<\n typeof serviceName,\n ProfileMetricsServiceActions | AllowedActions,\n ProfileMetricsServiceEvents | AllowedEvents\n>;\n\n// === SERVICE DEFINITION ===\n\nexport class ProfileMetricsService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n /**\n * The messenger suited for this service.\n */\n readonly #messenger: ConstructorParameters<\n typeof ProfileMetricsService\n >[0]['messenger'];\n\n /**\n * A function that can be used to make an HTTP request.\n */\n readonly #fetch: ConstructorParameters<\n typeof ProfileMetricsService\n >[0]['fetch'];\n\n /**\n * The policy that wraps the request.\n *\n * @see {@link createServicePolicy}\n */\n readonly #policy: ServicePolicy;\n\n /**\n * The API base URL environment.\n */\n readonly #baseURL: string;\n\n /**\n * Constructs a new ProfileMetricsService object.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n * @param args.fetch - A function that can be used to make an HTTP request. If\n * your JavaScript environment supports `fetch` natively, you'll probably want\n * to pass that; otherwise you can pass an equivalent (such as `fetch` via\n * `node-fetch`).\n * @param args.policyOptions - Options to pass to `createServicePolicy`, which\n * is used to wrap each request. See {@link CreateServicePolicyOptions}.\n * @param args.env - The environment to determine the correct API endpoints.\n */\n constructor({\n messenger,\n fetch: fetchFunction,\n policyOptions = {},\n env = Env.DEV,\n }: {\n messenger: ProfileMetricsServiceMessenger;\n fetch: typeof fetch;\n policyOptions?: CreateServicePolicyOptions;\n env?: Env;\n }) {\n this.name = serviceName;\n this.#messenger = messenger;\n this.#fetch = fetchFunction;\n this.#policy = createServicePolicy(policyOptions);\n this.#baseURL = getEnvUrl(env);\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Registers a handler that will be called after a request returns a non-500\n * response, causing a retry. Primarily useful in tests where timers are being\n * mocked.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onRetry(listener: Parameters<ServicePolicy['onRetry']>[0]) {\n return this.#policy.onRetry(listener);\n }\n\n /**\n * Registers a handler that will be called after a set number of retry rounds\n * prove that requests to the API endpoint consistently return a 5xx response.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onBreak(listener: Parameters<ServicePolicy['onBreak']>[0]) {\n return this.#policy.onBreak(listener);\n }\n\n /* eslint-disable jsdoc/check-indentation */\n /**\n * Registers a handler that will be called under one of two circumstances:\n *\n * 1. After a set number of retries prove that requests to the API\n * consistently result in one of the following failures:\n * 1. A connection initiation error\n * 2. A connection reset error\n * 3. A timeout error\n * 4. A non-JSON response\n * 5. A 502, 503, or 504 response\n * 2. After a successful request is made to the API, but the response takes\n * longer than a set duration to return.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n */\n /* eslint-enable jsdoc/check-indentation */\n onDegraded(listener: Parameters<ServicePolicy['onDegraded']>[0]) {\n return this.#policy.onDegraded(listener);\n }\n\n /**\n * Makes a request to the API in order to update the user profile.\n *\n * @param data - The data to send in the profile update request.\n * @returns The response from the API.\n */\n async updateProfile(data: ProfileMetricsUpdateRequest): Promise<void> {\n const authToken = await this.#messenger.call(\n 'AuthenticationController:getBearerToken',\n data.entropySourceId || undefined,\n );\n await this.#policy.execute(async () => {\n const url = new URL(`${this.#baseURL}/profile/accounts`);\n const localResponse = await this.#fetch(url, {\n method: 'PUT',\n headers: {\n Authorization: `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n metametrics_id: data.metametricsId,\n accounts: data.accounts,\n }),\n });\n if (!localResponse.ok) {\n throw new HttpError(\n localResponse.status,\n `Fetching '${url.toString()}' failed with status '${localResponse.status}'`,\n );\n }\n return localResponse;\n });\n }\n}\n"]}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { CreateServicePolicyOptions, ServicePolicy } from "@metamask/controller-utils";
|
|
2
|
+
import type { Messenger } from "@metamask/messenger";
|
|
3
|
+
import type { AuthenticationController } from "@metamask/profile-sync-controller";
|
|
4
|
+
import { type ProfileMetricsServiceMethodActions, Env } from "./index.cjs";
|
|
5
|
+
/**
|
|
6
|
+
* The name of the {@link ProfileMetricsService}, used to namespace the
|
|
7
|
+
* service's actions and events.
|
|
8
|
+
*/
|
|
9
|
+
export declare const serviceName = "ProfileMetricsService";
|
|
10
|
+
/**
|
|
11
|
+
* An account address along with its associated scopes.
|
|
12
|
+
*/
|
|
13
|
+
export type AccountWithScopes = {
|
|
14
|
+
address: string;
|
|
15
|
+
scopes: `${string}:${string}`[];
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* The shape of the request object for updating the user profile.
|
|
19
|
+
*/
|
|
20
|
+
export type ProfileMetricsUpdateRequest = {
|
|
21
|
+
metametricsId: string;
|
|
22
|
+
entropySourceId?: string | null;
|
|
23
|
+
accounts: AccountWithScopes[];
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Actions that {@link ProfileMetricsService} exposes to other consumers.
|
|
27
|
+
*/
|
|
28
|
+
export type ProfileMetricsServiceActions = ProfileMetricsServiceMethodActions;
|
|
29
|
+
/**
|
|
30
|
+
* Actions from other messengers that {@link ProfileMetricsService} calls.
|
|
31
|
+
*/
|
|
32
|
+
type AllowedActions = AuthenticationController.AuthenticationControllerGetBearerToken;
|
|
33
|
+
/**
|
|
34
|
+
* Events that {@link ProfileMetricsService} exposes to other consumers.
|
|
35
|
+
*/
|
|
36
|
+
export type ProfileMetricsServiceEvents = never;
|
|
37
|
+
/**
|
|
38
|
+
* Events from other messengers that {@link ProfileMetricsService} subscribes
|
|
39
|
+
* to.
|
|
40
|
+
*/
|
|
41
|
+
type AllowedEvents = never;
|
|
42
|
+
/**
|
|
43
|
+
* The messenger which is restricted to actions and events accessed by
|
|
44
|
+
* {@link ProfileMetricsService}.
|
|
45
|
+
*/
|
|
46
|
+
export type ProfileMetricsServiceMessenger = Messenger<typeof serviceName, ProfileMetricsServiceActions | AllowedActions, ProfileMetricsServiceEvents | AllowedEvents>;
|
|
47
|
+
export declare class ProfileMetricsService {
|
|
48
|
+
#private;
|
|
49
|
+
/**
|
|
50
|
+
* The name of the service.
|
|
51
|
+
*/
|
|
52
|
+
readonly name: typeof serviceName;
|
|
53
|
+
/**
|
|
54
|
+
* Constructs a new ProfileMetricsService object.
|
|
55
|
+
*
|
|
56
|
+
* @param args - The constructor arguments.
|
|
57
|
+
* @param args.messenger - The messenger suited for this service.
|
|
58
|
+
* @param args.fetch - A function that can be used to make an HTTP request. If
|
|
59
|
+
* your JavaScript environment supports `fetch` natively, you'll probably want
|
|
60
|
+
* to pass that; otherwise you can pass an equivalent (such as `fetch` via
|
|
61
|
+
* `node-fetch`).
|
|
62
|
+
* @param args.policyOptions - Options to pass to `createServicePolicy`, which
|
|
63
|
+
* is used to wrap each request. See {@link CreateServicePolicyOptions}.
|
|
64
|
+
* @param args.env - The environment to determine the correct API endpoints.
|
|
65
|
+
*/
|
|
66
|
+
constructor({ messenger, fetch: fetchFunction, policyOptions, env, }: {
|
|
67
|
+
messenger: ProfileMetricsServiceMessenger;
|
|
68
|
+
fetch: typeof fetch;
|
|
69
|
+
policyOptions?: CreateServicePolicyOptions;
|
|
70
|
+
env?: Env;
|
|
71
|
+
});
|
|
72
|
+
/**
|
|
73
|
+
* Registers a handler that will be called after a request returns a non-500
|
|
74
|
+
* response, causing a retry. Primarily useful in tests where timers are being
|
|
75
|
+
* mocked.
|
|
76
|
+
*
|
|
77
|
+
* @param listener - The handler to be called.
|
|
78
|
+
* @returns An object that can be used to unregister the handler. See
|
|
79
|
+
* {@link CockatielEvent}.
|
|
80
|
+
* @see {@link createServicePolicy}
|
|
81
|
+
*/
|
|
82
|
+
onRetry(listener: Parameters<ServicePolicy['onRetry']>[0]): import("cockatiel").IDisposable;
|
|
83
|
+
/**
|
|
84
|
+
* Registers a handler that will be called after a set number of retry rounds
|
|
85
|
+
* prove that requests to the API endpoint consistently return a 5xx response.
|
|
86
|
+
*
|
|
87
|
+
* @param listener - The handler to be called.
|
|
88
|
+
* @returns An object that can be used to unregister the handler. See
|
|
89
|
+
* {@link CockatielEvent}.
|
|
90
|
+
* @see {@link createServicePolicy}
|
|
91
|
+
*/
|
|
92
|
+
onBreak(listener: Parameters<ServicePolicy['onBreak']>[0]): import("cockatiel").IDisposable;
|
|
93
|
+
/**
|
|
94
|
+
* Registers a handler that will be called under one of two circumstances:
|
|
95
|
+
*
|
|
96
|
+
* 1. After a set number of retries prove that requests to the API
|
|
97
|
+
* consistently result in one of the following failures:
|
|
98
|
+
* 1. A connection initiation error
|
|
99
|
+
* 2. A connection reset error
|
|
100
|
+
* 3. A timeout error
|
|
101
|
+
* 4. A non-JSON response
|
|
102
|
+
* 5. A 502, 503, or 504 response
|
|
103
|
+
* 2. After a successful request is made to the API, but the response takes
|
|
104
|
+
* longer than a set duration to return.
|
|
105
|
+
*
|
|
106
|
+
* @param listener - The handler to be called.
|
|
107
|
+
* @returns An object that can be used to unregister the handler. See
|
|
108
|
+
* {@link CockatielEvent}.
|
|
109
|
+
*/
|
|
110
|
+
onDegraded(listener: Parameters<ServicePolicy['onDegraded']>[0]): import("cockatiel").IDisposable;
|
|
111
|
+
/**
|
|
112
|
+
* Makes a request to the API in order to update the user profile.
|
|
113
|
+
*
|
|
114
|
+
* @param data - The data to send in the profile update request.
|
|
115
|
+
* @returns The response from the API.
|
|
116
|
+
*/
|
|
117
|
+
updateProfile(data: ProfileMetricsUpdateRequest): Promise<void>;
|
|
118
|
+
}
|
|
119
|
+
export {};
|
|
120
|
+
//# sourceMappingURL=ProfileMetricsService.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProfileMetricsService.d.cts","sourceRoot":"","sources":["../src/ProfileMetricsService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAC1B,aAAa,EACd,mCAAmC;AAEpC,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AACrD,OAAO,KAAK,EAAE,wBAAwB,EAAE,0CAA0C;AAElF,OAAO,EAAE,KAAK,kCAAkC,EAAE,GAAG,EAAa,oBAAU;AAI5E;;;GAGG;AACH,eAAO,MAAM,WAAW,0BAA0B,CAAC;AAEnD;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,EAAE,EAAE,CAAC;CACjC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B,CAAC;AAMF;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG,kCAAkC,CAAC;AAE9E;;GAEG;AACH,KAAK,cAAc,GACjB,wBAAwB,CAAC,sCAAsC,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG,KAAK,CAAC;AAEhD;;;GAGG;AACH,KAAK,aAAa,GAAG,KAAK,CAAC;AAE3B;;;GAGG;AACH,MAAM,MAAM,8BAA8B,GAAG,SAAS,CACpD,OAAO,WAAW,EAClB,4BAA4B,GAAG,cAAc,EAC7C,2BAA2B,GAAG,aAAa,CAC5C,CAAC;AAIF,qBAAa,qBAAqB;;IAChC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,OAAO,WAAW,CAAC;IA4BlC;;;;;;;;;;;;OAYG;gBACS,EACV,SAAS,EACT,KAAK,EAAE,aAAa,EACpB,aAAkB,EAClB,GAAa,GACd,EAAE;QACD,SAAS,EAAE,8BAA8B,CAAC;QAC1C,KAAK,EAAE,OAAO,KAAK,CAAC;QACpB,aAAa,CAAC,EAAE,0BAA0B,CAAC;QAC3C,GAAG,CAAC,EAAE,GAAG,CAAC;KACX;IAaD;;;;;;;;;OASG;IACH,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAIzD;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAKzD;;;;;;;;;;;;;;;;OAgBG;IAEH,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAI/D;;;;;OAKG;IACG,aAAa,CAAC,IAAI,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC;CA2BtE"}
|