@metamask-previews/profile-sync-controller 24.0.0-preview-b13da658 → 24.0.0-preview-a421f85b
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 +0 -9
- package/dist/controllers/user-storage/UserStorageController.cjs +80 -4
- package/dist/controllers/user-storage/UserStorageController.cjs.map +1 -1
- package/dist/controllers/user-storage/UserStorageController.d.cts +54 -5
- package/dist/controllers/user-storage/UserStorageController.d.cts.map +1 -1
- package/dist/controllers/user-storage/UserStorageController.d.mts +54 -5
- package/dist/controllers/user-storage/UserStorageController.d.mts.map +1 -1
- package/dist/controllers/user-storage/UserStorageController.mjs +76 -0
- package/dist/controllers/user-storage/UserStorageController.mjs.map +1 -1
- package/dist/controllers/user-storage/account-syncing/constants.cjs +51 -0
- package/dist/controllers/user-storage/account-syncing/constants.cjs.map +1 -0
- package/dist/controllers/user-storage/account-syncing/constants.d.cts +4 -0
- package/dist/controllers/user-storage/account-syncing/constants.d.cts.map +1 -0
- package/dist/controllers/user-storage/account-syncing/constants.d.mts +4 -0
- package/dist/controllers/user-storage/account-syncing/constants.d.mts.map +1 -0
- package/dist/controllers/user-storage/account-syncing/constants.mjs +48 -0
- package/dist/controllers/user-storage/account-syncing/constants.mjs.map +1 -0
- package/dist/controllers/user-storage/account-syncing/controller-integration.cjs +271 -0
- package/dist/controllers/user-storage/account-syncing/controller-integration.cjs.map +1 -0
- package/dist/controllers/user-storage/account-syncing/controller-integration.d.cts +38 -0
- package/dist/controllers/user-storage/account-syncing/controller-integration.d.cts.map +1 -0
- package/dist/controllers/user-storage/account-syncing/controller-integration.d.mts +38 -0
- package/dist/controllers/user-storage/account-syncing/controller-integration.d.mts.map +1 -0
- package/dist/controllers/user-storage/account-syncing/controller-integration.mjs +265 -0
- package/dist/controllers/user-storage/account-syncing/controller-integration.mjs.map +1 -0
- package/dist/controllers/user-storage/account-syncing/setup-subscriptions.cjs +41 -0
- package/dist/controllers/user-storage/account-syncing/setup-subscriptions.cjs.map +1 -0
- package/dist/controllers/user-storage/account-syncing/setup-subscriptions.d.cts +8 -0
- package/dist/controllers/user-storage/account-syncing/setup-subscriptions.d.cts.map +1 -0
- package/dist/controllers/user-storage/account-syncing/setup-subscriptions.d.mts +8 -0
- package/dist/controllers/user-storage/account-syncing/setup-subscriptions.d.mts.map +1 -0
- package/dist/controllers/user-storage/account-syncing/setup-subscriptions.mjs +37 -0
- package/dist/controllers/user-storage/account-syncing/setup-subscriptions.mjs.map +1 -0
- package/dist/controllers/user-storage/account-syncing/sync-utils.cjs +61 -0
- package/dist/controllers/user-storage/account-syncing/sync-utils.cjs.map +1 -0
- package/dist/controllers/user-storage/account-syncing/sync-utils.d.cts +30 -0
- package/dist/controllers/user-storage/account-syncing/sync-utils.d.cts.map +1 -0
- package/dist/controllers/user-storage/account-syncing/sync-utils.d.mts +30 -0
- package/dist/controllers/user-storage/account-syncing/sync-utils.d.mts.map +1 -0
- package/dist/controllers/user-storage/account-syncing/sync-utils.mjs +55 -0
- package/dist/controllers/user-storage/account-syncing/sync-utils.mjs.map +1 -0
- package/dist/controllers/user-storage/account-syncing/types.cjs +3 -0
- package/dist/controllers/user-storage/account-syncing/types.cjs.map +1 -0
- package/dist/controllers/user-storage/account-syncing/types.d.cts +25 -0
- package/dist/controllers/user-storage/account-syncing/types.d.cts.map +1 -0
- package/dist/controllers/user-storage/account-syncing/types.d.mts +25 -0
- package/dist/controllers/user-storage/account-syncing/types.d.mts.map +1 -0
- package/dist/controllers/user-storage/account-syncing/types.mjs +2 -0
- package/dist/controllers/user-storage/account-syncing/types.mjs.map +1 -0
- package/dist/controllers/user-storage/account-syncing/utils.cjs +36 -0
- package/dist/controllers/user-storage/account-syncing/utils.cjs.map +1 -0
- package/dist/controllers/user-storage/account-syncing/utils.d.cts +18 -0
- package/dist/controllers/user-storage/account-syncing/utils.d.cts.map +1 -0
- package/dist/controllers/user-storage/account-syncing/utils.d.mts +18 -0
- package/dist/controllers/user-storage/account-syncing/utils.d.mts.map +1 -0
- package/dist/controllers/user-storage/account-syncing/utils.mjs +31 -0
- package/dist/controllers/user-storage/account-syncing/utils.mjs.map +1 -0
- package/dist/controllers/user-storage/constants.cjs +3 -0
- package/dist/controllers/user-storage/constants.cjs.map +1 -1
- package/dist/controllers/user-storage/constants.d.cts +2 -0
- package/dist/controllers/user-storage/constants.d.cts.map +1 -1
- package/dist/controllers/user-storage/constants.d.mts +2 -0
- package/dist/controllers/user-storage/constants.d.mts.map +1 -1
- package/dist/controllers/user-storage/constants.mjs +3 -0
- package/dist/controllers/user-storage/constants.mjs.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { KeyringTypes } from "@metamask/keyring-controller";
|
|
2
|
+
import { canPerformAccountSyncing, getInternalAccountsList, getUserStorageAccountsList } from "./sync-utils.mjs";
|
|
3
|
+
import { isNameDefaultAccountName, mapInternalAccountToUserStorageAccount } from "./utils.mjs";
|
|
4
|
+
import { USER_STORAGE_FEATURE_NAMES } from "../../../shared/storage-schema.mjs";
|
|
5
|
+
import { TraceName } from "../constants.mjs";
|
|
6
|
+
/**
|
|
7
|
+
* Saves an individual internal account to the user storage.
|
|
8
|
+
*
|
|
9
|
+
* @param internalAccount - The internal account to save
|
|
10
|
+
* @param options - parameters used for saving the internal account
|
|
11
|
+
* @returns Promise that resolves when the account is saved
|
|
12
|
+
*/
|
|
13
|
+
export async function saveInternalAccountToUserStorage(internalAccount, options) {
|
|
14
|
+
const { trace } = options;
|
|
15
|
+
const saveAccount = async () => {
|
|
16
|
+
const { getUserStorageControllerInstance } = options;
|
|
17
|
+
if (getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()) {
|
|
18
|
+
// If multichain account syncing is enabled, we do not push account syncing V1 data anymore.
|
|
19
|
+
// AccountTreeController handles proper multichain account syncing
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (!canPerformAccountSyncing(options) ||
|
|
23
|
+
internalAccount.metadata.keyring.type !== String(KeyringTypes.hd) // sync only EVM accounts until we support multichain accounts
|
|
24
|
+
) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
// properties of `options` are (wrongly?) typed as `Json` and eslint crashes if we try to interpret it as such and call a `?.toString()` on it.
|
|
28
|
+
// but we know this is a string?, so we can safely cast it
|
|
29
|
+
const entropySourceId = internalAccount.options?.entropySource;
|
|
30
|
+
try {
|
|
31
|
+
// Map the internal account to the user storage account schema
|
|
32
|
+
const mappedAccount = mapInternalAccountToUserStorageAccount(internalAccount);
|
|
33
|
+
await getUserStorageControllerInstance().performSetStorage(`${USER_STORAGE_FEATURE_NAMES.accounts}.${internalAccount.address}`, JSON.stringify(mappedAccount), entropySourceId);
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
// istanbul ignore next
|
|
37
|
+
const errorMessage = e instanceof Error ? e.message : JSON.stringify(e);
|
|
38
|
+
throw new Error(`UserStorageController - failed to save account to user storage - ${errorMessage}`);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
if (trace) {
|
|
42
|
+
return await trace({ name: TraceName.AccountSyncSaveIndividual }, saveAccount);
|
|
43
|
+
}
|
|
44
|
+
return await saveAccount();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Saves the list of internal accounts to the user storage.
|
|
48
|
+
*
|
|
49
|
+
* @param options - parameters used for saving the list of internal accounts
|
|
50
|
+
* @param entropySourceId - The entropy source ID used to derive the key,
|
|
51
|
+
* when multiple sources are available (Multi-SRP).
|
|
52
|
+
* @returns Promise that resolves when all accounts are saved
|
|
53
|
+
*/
|
|
54
|
+
export async function saveInternalAccountsListToUserStorage(options, entropySourceId) {
|
|
55
|
+
const { getUserStorageControllerInstance } = options;
|
|
56
|
+
if (getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()) {
|
|
57
|
+
// If multichain account syncing is enabled, we do not push account syncing V1 data anymore.
|
|
58
|
+
// AccountTreeController handles proper multichain account syncing
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const internalAccountsList = await getInternalAccountsList(options, entropySourceId);
|
|
62
|
+
if (!internalAccountsList?.length) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const internalAccountsListFormattedForUserStorage = internalAccountsList.map(mapInternalAccountToUserStorageAccount);
|
|
66
|
+
await getUserStorageControllerInstance().performBatchSetStorage(USER_STORAGE_FEATURE_NAMES.accounts, internalAccountsListFormattedForUserStorage.map((account) => [
|
|
67
|
+
account.a,
|
|
68
|
+
JSON.stringify(account),
|
|
69
|
+
]), entropySourceId);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Syncs the internal accounts list with the user storage accounts list.
|
|
73
|
+
* This method is used to make sure that the internal accounts list is up-to-date with the user storage accounts list and vice-versa.
|
|
74
|
+
* It will add new accounts to the internal accounts list, update/merge conflicting names and re-upload the results in some cases to the user storage.
|
|
75
|
+
*
|
|
76
|
+
* @param config - parameters used for syncing the internal accounts list with the user storage accounts list
|
|
77
|
+
* @param options - parameters used for syncing the internal accounts list with the user storage accounts list
|
|
78
|
+
* @param entropySourceId - The entropy source ID used to derive the key,
|
|
79
|
+
* @returns Promise that resolves when synchronization is complete
|
|
80
|
+
*/
|
|
81
|
+
export async function syncInternalAccountsWithUserStorage(config, options, entropySourceId) {
|
|
82
|
+
const { trace } = options;
|
|
83
|
+
const performAccountSync = async () => {
|
|
84
|
+
if (!canPerformAccountSyncing(options)) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const { maxNumberOfAccountsToAdd = Infinity, onAccountAdded, onAccountNameUpdated, onAccountSyncErroneousSituation, } = config;
|
|
88
|
+
const { getMessenger, getUserStorageControllerInstance } = options;
|
|
89
|
+
try {
|
|
90
|
+
await getUserStorageControllerInstance().setIsAccountSyncingInProgress(true);
|
|
91
|
+
const userStorageAccountsList = await getUserStorageAccountsList(options, entropySourceId);
|
|
92
|
+
if (!userStorageAccountsList || !userStorageAccountsList.length) {
|
|
93
|
+
await saveInternalAccountsListToUserStorage(options, entropySourceId);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// Keep a record if erroneous situations are found during the sync
|
|
97
|
+
// This is done so we can send the context to Sentry in case of an erroneous situation
|
|
98
|
+
let erroneousSituationsFound = false;
|
|
99
|
+
// Prepare an array of internal accounts to be saved to the user storage
|
|
100
|
+
const internalAccountsToBeSavedToUserStorage = [];
|
|
101
|
+
// Compare internal accounts list with user storage accounts list
|
|
102
|
+
// First step: compare lengths
|
|
103
|
+
const internalAccountsList = await getInternalAccountsList(options, entropySourceId);
|
|
104
|
+
if (!internalAccountsList || !internalAccountsList.length) {
|
|
105
|
+
throw new Error(`Failed to get internal accounts list`);
|
|
106
|
+
}
|
|
107
|
+
const hasMoreUserStorageAccountsThanInternalAccounts = userStorageAccountsList.length > internalAccountsList.length;
|
|
108
|
+
// We don't want to remove existing accounts for a user
|
|
109
|
+
// so we only add new accounts if the user has more accounts in user storage than internal accounts
|
|
110
|
+
if (hasMoreUserStorageAccountsThanInternalAccounts) {
|
|
111
|
+
const numberOfAccountsToAdd = Math.min(userStorageAccountsList.length, maxNumberOfAccountsToAdd) -
|
|
112
|
+
internalAccountsList.length;
|
|
113
|
+
// Create new accounts to match the user storage accounts list
|
|
114
|
+
await getMessenger().call('KeyringController:withKeyring', {
|
|
115
|
+
id: entropySourceId,
|
|
116
|
+
}, async ({ keyring }) => {
|
|
117
|
+
await keyring.addAccounts(numberOfAccountsToAdd);
|
|
118
|
+
});
|
|
119
|
+
// TODO: below code is kept for analytics but should probably be re-thought
|
|
120
|
+
for (let i = 0; i < numberOfAccountsToAdd; i++) {
|
|
121
|
+
onAccountAdded?.();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Second step: compare account names
|
|
125
|
+
// Get the internal accounts list again since new accounts might have been added in the previous step
|
|
126
|
+
const refreshedInternalAccountsList = await getInternalAccountsList(options, entropySourceId);
|
|
127
|
+
const newlyAddedAccounts = refreshedInternalAccountsList.filter((account) => !internalAccountsList.find((a) => a.address === account.address));
|
|
128
|
+
for (const internalAccount of refreshedInternalAccountsList) {
|
|
129
|
+
const userStorageAccount = userStorageAccountsList.find((account) => account.a === internalAccount.address);
|
|
130
|
+
// If the account is not present in user storage
|
|
131
|
+
// istanbul ignore next
|
|
132
|
+
if (!userStorageAccount) {
|
|
133
|
+
// If the account was just added in the previous step, skip saving it, it's likely to be a bogus account
|
|
134
|
+
if (newlyAddedAccounts.includes(internalAccount)) {
|
|
135
|
+
erroneousSituationsFound = true;
|
|
136
|
+
onAccountSyncErroneousSituation?.('An account was added to the internal accounts list but was not present in the user storage accounts list', {
|
|
137
|
+
internalAccount,
|
|
138
|
+
userStorageAccount,
|
|
139
|
+
newlyAddedAccounts,
|
|
140
|
+
userStorageAccountsList,
|
|
141
|
+
internalAccountsList,
|
|
142
|
+
refreshedInternalAccountsList,
|
|
143
|
+
internalAccountsToBeSavedToUserStorage,
|
|
144
|
+
});
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
// Otherwise, it means that this internal account was present before the sync, and needs to be saved to the user storage
|
|
148
|
+
internalAccountsToBeSavedToUserStorage.push(internalAccount);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
// From this point on, we know that the account is present in
|
|
152
|
+
// both the internal accounts list and the user storage accounts list
|
|
153
|
+
// One or both accounts have default names
|
|
154
|
+
const isInternalAccountNameDefault = isNameDefaultAccountName(internalAccount.metadata.name);
|
|
155
|
+
const isUserStorageAccountNameDefault = isNameDefaultAccountName(userStorageAccount.n);
|
|
156
|
+
// Internal account has default name
|
|
157
|
+
if (isInternalAccountNameDefault) {
|
|
158
|
+
if (!isUserStorageAccountNameDefault) {
|
|
159
|
+
getMessenger().call('AccountsController:updateAccountMetadata', internalAccount.id, {
|
|
160
|
+
name: userStorageAccount.n,
|
|
161
|
+
});
|
|
162
|
+
onAccountNameUpdated?.();
|
|
163
|
+
}
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
// Internal account has custom name but user storage account has default name
|
|
167
|
+
if (isUserStorageAccountNameDefault) {
|
|
168
|
+
internalAccountsToBeSavedToUserStorage.push(internalAccount);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
// Both accounts have custom names
|
|
172
|
+
// User storage account has a nameLastUpdatedAt timestamp
|
|
173
|
+
// Note: not storing the undefined checks in constants to act as a type guard
|
|
174
|
+
if (userStorageAccount.nlu !== undefined) {
|
|
175
|
+
if (internalAccount.metadata.nameLastUpdatedAt !== undefined) {
|
|
176
|
+
const isInternalAccountNameNewer = internalAccount.metadata.nameLastUpdatedAt >
|
|
177
|
+
userStorageAccount.nlu;
|
|
178
|
+
if (isInternalAccountNameNewer) {
|
|
179
|
+
internalAccountsToBeSavedToUserStorage.push(internalAccount);
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
getMessenger().call('AccountsController:updateAccountMetadata', internalAccount.id, {
|
|
184
|
+
name: userStorageAccount.n,
|
|
185
|
+
nameLastUpdatedAt: userStorageAccount.nlu,
|
|
186
|
+
});
|
|
187
|
+
const areInternalAndUserStorageAccountNamesEqual = internalAccount.metadata.name === userStorageAccount.n;
|
|
188
|
+
if (!areInternalAndUserStorageAccountNamesEqual) {
|
|
189
|
+
onAccountNameUpdated?.();
|
|
190
|
+
}
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
else if (internalAccount.metadata.nameLastUpdatedAt !== undefined) {
|
|
194
|
+
internalAccountsToBeSavedToUserStorage.push(internalAccount);
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Save the internal accounts list to the user storage
|
|
199
|
+
if (internalAccountsToBeSavedToUserStorage.length) {
|
|
200
|
+
if (!getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()) {
|
|
201
|
+
// If multichain account syncing is enabled, we do not push account syncing V1 data anymore.
|
|
202
|
+
// AccountTreeController handles proper multichain account syncing
|
|
203
|
+
await getUserStorageControllerInstance().performBatchSetStorage(USER_STORAGE_FEATURE_NAMES.accounts, internalAccountsToBeSavedToUserStorage.map((account) => [
|
|
204
|
+
account.address,
|
|
205
|
+
JSON.stringify(mapInternalAccountToUserStorageAccount(account)),
|
|
206
|
+
]), entropySourceId);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// In case we have corrupted user storage with accounts that don't exist in the internal accounts list
|
|
210
|
+
// Delete those accounts from the user storage
|
|
211
|
+
const userStorageAccountsToBeDeleted = userStorageAccountsList.filter((account) => !refreshedInternalAccountsList.find((a) => a.address === account.a));
|
|
212
|
+
if (userStorageAccountsToBeDeleted.length) {
|
|
213
|
+
if (!getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()) {
|
|
214
|
+
// If multichain account syncing is enabled, we do not push account syncing V1 data anymore.
|
|
215
|
+
// AccountTreeController handles proper multichain account syncing
|
|
216
|
+
await getUserStorageControllerInstance().performBatchDeleteStorage(USER_STORAGE_FEATURE_NAMES.accounts, userStorageAccountsToBeDeleted.map((account) => account.a), entropySourceId);
|
|
217
|
+
erroneousSituationsFound = true;
|
|
218
|
+
onAccountSyncErroneousSituation?.('An account was present in the user storage accounts list but was not found in the internal accounts list after the sync', {
|
|
219
|
+
userStorageAccountsToBeDeleted,
|
|
220
|
+
internalAccountsList,
|
|
221
|
+
refreshedInternalAccountsList,
|
|
222
|
+
internalAccountsToBeSavedToUserStorage,
|
|
223
|
+
userStorageAccountsList,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (erroneousSituationsFound) {
|
|
228
|
+
const [finalUserStorageAccountsList, finalInternalAccountsList] = await Promise.all([
|
|
229
|
+
getUserStorageAccountsList(options, entropySourceId),
|
|
230
|
+
getInternalAccountsList(options, entropySourceId),
|
|
231
|
+
]);
|
|
232
|
+
const doesEveryAccountInInternalAccountsListExistInUserStorageAccountsList = finalInternalAccountsList.every((account) => finalUserStorageAccountsList?.some((userStorageAccount) => userStorageAccount.a === account.address));
|
|
233
|
+
// istanbul ignore next
|
|
234
|
+
const doesEveryAccountInUserStorageAccountsListExistInInternalAccountsList = (finalUserStorageAccountsList?.length || 0) > maxNumberOfAccountsToAdd
|
|
235
|
+
? true
|
|
236
|
+
: finalUserStorageAccountsList?.every((account) => finalInternalAccountsList.some((internalAccount) => internalAccount.address === account.a));
|
|
237
|
+
const doFinalListsMatch = doesEveryAccountInInternalAccountsListExistInUserStorageAccountsList &&
|
|
238
|
+
doesEveryAccountInUserStorageAccountsListExistInInternalAccountsList;
|
|
239
|
+
const context = {
|
|
240
|
+
finalUserStorageAccountsList,
|
|
241
|
+
finalInternalAccountsList,
|
|
242
|
+
};
|
|
243
|
+
if (doFinalListsMatch) {
|
|
244
|
+
onAccountSyncErroneousSituation?.('Erroneous situations were found during the sync, but final state matches the expected state', context);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
onAccountSyncErroneousSituation?.('Erroneous situations were found during the sync, and final state does not match the expected state', context);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch (e) {
|
|
252
|
+
// istanbul ignore next
|
|
253
|
+
const errorMessage = e instanceof Error ? e.message : JSON.stringify(e);
|
|
254
|
+
throw new Error(`UserStorageController - failed to sync user storage accounts list - ${errorMessage}`);
|
|
255
|
+
}
|
|
256
|
+
finally {
|
|
257
|
+
await getUserStorageControllerInstance().setIsAccountSyncingInProgress(false);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
if (trace) {
|
|
261
|
+
return await trace({ name: TraceName.AccountSyncFull }, performAccountSync);
|
|
262
|
+
}
|
|
263
|
+
return await performAccountSync();
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=controller-integration.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller-integration.mjs","sourceRoot":"","sources":["../../../../src/controllers/user-storage/account-syncing/controller-integration.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeyringTypes } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport {\n canPerformAccountSyncing,\n getInternalAccountsList,\n getUserStorageAccountsList,\n} from './sync-utils';\nimport type { AccountSyncingOptions } from './types';\nimport {\n isNameDefaultAccountName,\n mapInternalAccountToUserStorageAccount,\n} from './utils';\nimport { USER_STORAGE_FEATURE_NAMES } from '../../../shared/storage-schema';\nimport { TraceName } from '../constants';\n\n/**\n * Saves an individual internal account to the user storage.\n *\n * @param internalAccount - The internal account to save\n * @param options - parameters used for saving the internal account\n * @returns Promise that resolves when the account is saved\n */\nexport async function saveInternalAccountToUserStorage(\n internalAccount: InternalAccount,\n options: AccountSyncingOptions,\n): Promise<void> {\n const { trace } = options;\n\n const saveAccount = async () => {\n const { getUserStorageControllerInstance } = options;\n\n if (\n getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()\n ) {\n // If multichain account syncing is enabled, we do not push account syncing V1 data anymore.\n // AccountTreeController handles proper multichain account syncing\n return;\n }\n\n if (\n !canPerformAccountSyncing(options) ||\n internalAccount.metadata.keyring.type !== String(KeyringTypes.hd) // sync only EVM accounts until we support multichain accounts\n ) {\n return;\n }\n\n // properties of `options` are (wrongly?) typed as `Json` and eslint crashes if we try to interpret it as such and call a `?.toString()` on it.\n // but we know this is a string?, so we can safely cast it\n const entropySourceId = internalAccount.options?.entropySource as\n | string\n | undefined;\n\n try {\n // Map the internal account to the user storage account schema\n const mappedAccount =\n mapInternalAccountToUserStorageAccount(internalAccount);\n\n await getUserStorageControllerInstance().performSetStorage(\n `${USER_STORAGE_FEATURE_NAMES.accounts}.${internalAccount.address}`,\n JSON.stringify(mappedAccount),\n entropySourceId,\n );\n } catch (e) {\n // istanbul ignore next\n const errorMessage = e instanceof Error ? e.message : JSON.stringify(e);\n throw new Error(\n `UserStorageController - failed to save account to user storage - ${errorMessage}`,\n );\n }\n };\n\n if (trace) {\n return await trace(\n { name: TraceName.AccountSyncSaveIndividual },\n saveAccount,\n );\n }\n\n return await saveAccount();\n}\n\n/**\n * Saves the list of internal accounts to the user storage.\n *\n * @param options - parameters used for saving the list of internal accounts\n * @param entropySourceId - The entropy source ID used to derive the key,\n * when multiple sources are available (Multi-SRP).\n * @returns Promise that resolves when all accounts are saved\n */\nexport async function saveInternalAccountsListToUserStorage(\n options: AccountSyncingOptions,\n entropySourceId: string,\n): Promise<void> {\n const { getUserStorageControllerInstance } = options;\n if (\n getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()\n ) {\n // If multichain account syncing is enabled, we do not push account syncing V1 data anymore.\n // AccountTreeController handles proper multichain account syncing\n return;\n }\n\n const internalAccountsList = await getInternalAccountsList(\n options,\n entropySourceId,\n );\n\n if (!internalAccountsList?.length) {\n return;\n }\n\n const internalAccountsListFormattedForUserStorage = internalAccountsList.map(\n mapInternalAccountToUserStorageAccount,\n );\n\n await getUserStorageControllerInstance().performBatchSetStorage(\n USER_STORAGE_FEATURE_NAMES.accounts,\n internalAccountsListFormattedForUserStorage.map((account) => [\n account.a,\n JSON.stringify(account),\n ]),\n entropySourceId,\n );\n}\n\ntype SyncInternalAccountsWithUserStorageConfig = {\n maxNumberOfAccountsToAdd?: number;\n onAccountAdded?: () => void;\n onAccountNameUpdated?: () => void;\n onAccountSyncErroneousSituation?: (\n errorMessage: string,\n sentryContext?: Record<string, unknown>,\n ) => void;\n};\n\n/**\n * Syncs the internal accounts list with the user storage accounts list.\n * This method is used to make sure that the internal accounts list is up-to-date with the user storage accounts list and vice-versa.\n * It will add new accounts to the internal accounts list, update/merge conflicting names and re-upload the results in some cases to the user storage.\n *\n * @param config - parameters used for syncing the internal accounts list with the user storage accounts list\n * @param options - parameters used for syncing the internal accounts list with the user storage accounts list\n * @param entropySourceId - The entropy source ID used to derive the key,\n * @returns Promise that resolves when synchronization is complete\n */\nexport async function syncInternalAccountsWithUserStorage(\n config: SyncInternalAccountsWithUserStorageConfig,\n options: AccountSyncingOptions,\n entropySourceId: string,\n): Promise<void> {\n const { trace } = options;\n\n const performAccountSync = async () => {\n if (!canPerformAccountSyncing(options)) {\n return;\n }\n\n const {\n maxNumberOfAccountsToAdd = Infinity,\n onAccountAdded,\n onAccountNameUpdated,\n onAccountSyncErroneousSituation,\n } = config;\n const { getMessenger, getUserStorageControllerInstance } = options;\n\n try {\n await getUserStorageControllerInstance().setIsAccountSyncingInProgress(\n true,\n );\n\n const userStorageAccountsList = await getUserStorageAccountsList(\n options,\n entropySourceId,\n );\n\n if (!userStorageAccountsList || !userStorageAccountsList.length) {\n await saveInternalAccountsListToUserStorage(options, entropySourceId);\n return;\n }\n // Keep a record if erroneous situations are found during the sync\n // This is done so we can send the context to Sentry in case of an erroneous situation\n let erroneousSituationsFound = false;\n\n // Prepare an array of internal accounts to be saved to the user storage\n const internalAccountsToBeSavedToUserStorage: InternalAccount[] = [];\n\n // Compare internal accounts list with user storage accounts list\n // First step: compare lengths\n const internalAccountsList = await getInternalAccountsList(\n options,\n entropySourceId,\n );\n\n if (!internalAccountsList || !internalAccountsList.length) {\n throw new Error(`Failed to get internal accounts list`);\n }\n\n const hasMoreUserStorageAccountsThanInternalAccounts =\n userStorageAccountsList.length > internalAccountsList.length;\n\n // We don't want to remove existing accounts for a user\n // so we only add new accounts if the user has more accounts in user storage than internal accounts\n if (hasMoreUserStorageAccountsThanInternalAccounts) {\n const numberOfAccountsToAdd =\n Math.min(userStorageAccountsList.length, maxNumberOfAccountsToAdd) -\n internalAccountsList.length;\n\n // Create new accounts to match the user storage accounts list\n await getMessenger().call(\n 'KeyringController:withKeyring',\n {\n id: entropySourceId,\n },\n async ({ keyring }) => {\n await keyring.addAccounts(numberOfAccountsToAdd);\n },\n );\n\n // TODO: below code is kept for analytics but should probably be re-thought\n for (let i = 0; i < numberOfAccountsToAdd; i++) {\n onAccountAdded?.();\n }\n }\n\n // Second step: compare account names\n // Get the internal accounts list again since new accounts might have been added in the previous step\n const refreshedInternalAccountsList = await getInternalAccountsList(\n options,\n entropySourceId,\n );\n\n const newlyAddedAccounts = refreshedInternalAccountsList.filter(\n (account) =>\n !internalAccountsList.find((a) => a.address === account.address),\n );\n\n for (const internalAccount of refreshedInternalAccountsList) {\n const userStorageAccount = userStorageAccountsList.find(\n (account) => account.a === internalAccount.address,\n );\n\n // If the account is not present in user storage\n // istanbul ignore next\n if (!userStorageAccount) {\n // If the account was just added in the previous step, skip saving it, it's likely to be a bogus account\n if (newlyAddedAccounts.includes(internalAccount)) {\n erroneousSituationsFound = true;\n onAccountSyncErroneousSituation?.(\n 'An account was added to the internal accounts list but was not present in the user storage accounts list',\n {\n internalAccount,\n userStorageAccount,\n newlyAddedAccounts,\n userStorageAccountsList,\n internalAccountsList,\n refreshedInternalAccountsList,\n internalAccountsToBeSavedToUserStorage,\n },\n );\n continue;\n }\n // Otherwise, it means that this internal account was present before the sync, and needs to be saved to the user storage\n internalAccountsToBeSavedToUserStorage.push(internalAccount);\n continue;\n }\n\n // From this point on, we know that the account is present in\n // both the internal accounts list and the user storage accounts list\n\n // One or both accounts have default names\n const isInternalAccountNameDefault = isNameDefaultAccountName(\n internalAccount.metadata.name,\n );\n const isUserStorageAccountNameDefault = isNameDefaultAccountName(\n userStorageAccount.n,\n );\n\n // Internal account has default name\n if (isInternalAccountNameDefault) {\n if (!isUserStorageAccountNameDefault) {\n getMessenger().call(\n 'AccountsController:updateAccountMetadata',\n internalAccount.id,\n {\n name: userStorageAccount.n,\n },\n );\n\n onAccountNameUpdated?.();\n }\n continue;\n }\n\n // Internal account has custom name but user storage account has default name\n if (isUserStorageAccountNameDefault) {\n internalAccountsToBeSavedToUserStorage.push(internalAccount);\n continue;\n }\n\n // Both accounts have custom names\n\n // User storage account has a nameLastUpdatedAt timestamp\n // Note: not storing the undefined checks in constants to act as a type guard\n if (userStorageAccount.nlu !== undefined) {\n if (internalAccount.metadata.nameLastUpdatedAt !== undefined) {\n const isInternalAccountNameNewer =\n internalAccount.metadata.nameLastUpdatedAt >\n userStorageAccount.nlu;\n\n if (isInternalAccountNameNewer) {\n internalAccountsToBeSavedToUserStorage.push(internalAccount);\n continue;\n }\n }\n\n getMessenger().call(\n 'AccountsController:updateAccountMetadata',\n internalAccount.id,\n {\n name: userStorageAccount.n,\n nameLastUpdatedAt: userStorageAccount.nlu,\n },\n );\n\n const areInternalAndUserStorageAccountNamesEqual =\n internalAccount.metadata.name === userStorageAccount.n;\n\n if (!areInternalAndUserStorageAccountNamesEqual) {\n onAccountNameUpdated?.();\n }\n\n continue;\n } else if (internalAccount.metadata.nameLastUpdatedAt !== undefined) {\n internalAccountsToBeSavedToUserStorage.push(internalAccount);\n continue;\n }\n }\n\n // Save the internal accounts list to the user storage\n if (internalAccountsToBeSavedToUserStorage.length) {\n if (\n !getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()\n ) {\n // If multichain account syncing is enabled, we do not push account syncing V1 data anymore.\n // AccountTreeController handles proper multichain account syncing\n await getUserStorageControllerInstance().performBatchSetStorage(\n USER_STORAGE_FEATURE_NAMES.accounts,\n internalAccountsToBeSavedToUserStorage.map((account) => [\n account.address,\n JSON.stringify(mapInternalAccountToUserStorageAccount(account)),\n ]),\n entropySourceId,\n );\n }\n }\n\n // In case we have corrupted user storage with accounts that don't exist in the internal accounts list\n // Delete those accounts from the user storage\n const userStorageAccountsToBeDeleted = userStorageAccountsList.filter(\n (account) =>\n !refreshedInternalAccountsList.find((a) => a.address === account.a),\n );\n\n if (userStorageAccountsToBeDeleted.length) {\n if (\n !getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()\n ) {\n // If multichain account syncing is enabled, we do not push account syncing V1 data anymore.\n // AccountTreeController handles proper multichain account syncing\n await getUserStorageControllerInstance().performBatchDeleteStorage(\n USER_STORAGE_FEATURE_NAMES.accounts,\n userStorageAccountsToBeDeleted.map((account) => account.a),\n entropySourceId,\n );\n erroneousSituationsFound = true;\n onAccountSyncErroneousSituation?.(\n 'An account was present in the user storage accounts list but was not found in the internal accounts list after the sync',\n {\n userStorageAccountsToBeDeleted,\n internalAccountsList,\n refreshedInternalAccountsList,\n internalAccountsToBeSavedToUserStorage,\n userStorageAccountsList,\n },\n );\n }\n }\n\n if (erroneousSituationsFound) {\n const [finalUserStorageAccountsList, finalInternalAccountsList] =\n await Promise.all([\n getUserStorageAccountsList(options, entropySourceId),\n getInternalAccountsList(options, entropySourceId),\n ]);\n\n const doesEveryAccountInInternalAccountsListExistInUserStorageAccountsList =\n finalInternalAccountsList.every((account) =>\n finalUserStorageAccountsList?.some(\n (userStorageAccount) => userStorageAccount.a === account.address,\n ),\n );\n\n // istanbul ignore next\n const doesEveryAccountInUserStorageAccountsListExistInInternalAccountsList =\n (finalUserStorageAccountsList?.length || 0) > maxNumberOfAccountsToAdd\n ? true\n : finalUserStorageAccountsList?.every((account) =>\n finalInternalAccountsList.some(\n (internalAccount) => internalAccount.address === account.a,\n ),\n );\n\n const doFinalListsMatch =\n doesEveryAccountInInternalAccountsListExistInUserStorageAccountsList &&\n doesEveryAccountInUserStorageAccountsListExistInInternalAccountsList;\n\n const context = {\n finalUserStorageAccountsList,\n finalInternalAccountsList,\n };\n if (doFinalListsMatch) {\n onAccountSyncErroneousSituation?.(\n 'Erroneous situations were found during the sync, but final state matches the expected state',\n context,\n );\n } else {\n onAccountSyncErroneousSituation?.(\n 'Erroneous situations were found during the sync, and final state does not match the expected state',\n context,\n );\n }\n }\n } catch (e) {\n // istanbul ignore next\n const errorMessage = e instanceof Error ? e.message : JSON.stringify(e);\n throw new Error(\n `UserStorageController - failed to sync user storage accounts list - ${errorMessage}`,\n );\n } finally {\n await getUserStorageControllerInstance().setIsAccountSyncingInProgress(\n false,\n );\n }\n };\n\n if (trace) {\n return await trace({ name: TraceName.AccountSyncFull }, performAccountSync);\n }\n\n return await performAccountSync();\n}\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setupAccountSyncingSubscriptions = void 0;
|
|
4
|
+
const controller_integration_1 = require("./controller-integration.cjs");
|
|
5
|
+
const sync_utils_1 = require("./sync-utils.cjs");
|
|
6
|
+
/**
|
|
7
|
+
* Initialize and setup events to listen to for account syncing
|
|
8
|
+
*
|
|
9
|
+
* @param options - parameters used for initializing and enabling account syncing
|
|
10
|
+
*/
|
|
11
|
+
function setupAccountSyncingSubscriptions(options) {
|
|
12
|
+
const { getMessenger, getUserStorageControllerInstance } = options;
|
|
13
|
+
getMessenger().subscribe('AccountsController:accountAdded', async (account) => {
|
|
14
|
+
if (!(0, sync_utils_1.canPerformAccountSyncing)(options) ||
|
|
15
|
+
!getUserStorageControllerInstance().state
|
|
16
|
+
.hasAccountSyncingSyncedAtLeastOnce ||
|
|
17
|
+
// If multichain account syncing is enabled, we do not push account syncing V1 data anymore.
|
|
18
|
+
// AccountTreeController handles proper multichain account syncing
|
|
19
|
+
getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const { eventQueue } = getUserStorageControllerInstance();
|
|
23
|
+
eventQueue.push(async () => await (0, controller_integration_1.saveInternalAccountToUserStorage)(account, options));
|
|
24
|
+
await eventQueue.run();
|
|
25
|
+
});
|
|
26
|
+
getMessenger().subscribe('AccountsController:accountRenamed', async (account) => {
|
|
27
|
+
if (!(0, sync_utils_1.canPerformAccountSyncing)(options) ||
|
|
28
|
+
!getUserStorageControllerInstance().state
|
|
29
|
+
.hasAccountSyncingSyncedAtLeastOnce ||
|
|
30
|
+
// If multichain account syncing is enabled, we do not push account syncing V1 data anymore.
|
|
31
|
+
// AccountTreeController handles proper multichain account syncing
|
|
32
|
+
getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const { eventQueue } = getUserStorageControllerInstance();
|
|
36
|
+
eventQueue.push(async () => await (0, controller_integration_1.saveInternalAccountToUserStorage)(account, options));
|
|
37
|
+
await eventQueue.run();
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
exports.setupAccountSyncingSubscriptions = setupAccountSyncingSubscriptions;
|
|
41
|
+
//# sourceMappingURL=setup-subscriptions.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-subscriptions.cjs","sourceRoot":"","sources":["../../../../src/controllers/user-storage/account-syncing/setup-subscriptions.ts"],"names":[],"mappings":";;;AAAA,yEAA4E;AAC5E,iDAAwD;AAGxD;;;;GAIG;AACH,SAAgB,gCAAgC,CAC9C,OAA8B;IAE9B,MAAM,EAAE,YAAY,EAAE,gCAAgC,EAAE,GAAG,OAAO,CAAC;IAEnE,YAAY,EAAE,CAAC,SAAS,CACtB,iCAAiC,EAEjC,KAAK,EAAE,OAAO,EAAE,EAAE;QAChB,IACE,CAAC,IAAA,qCAAwB,EAAC,OAAO,CAAC;YAClC,CAAC,gCAAgC,EAAE,CAAC,KAAK;iBACtC,kCAAkC;YACrC,4FAA4F;YAC5F,kEAAkE;YAClE,gCAAgC,EAAE,CAAC,oCAAoC,EAAE,EACzE;YACA,OAAO;SACR;QAED,MAAM,EAAE,UAAU,EAAE,GAAG,gCAAgC,EAAE,CAAC;QAE1D,UAAU,CAAC,IAAI,CACb,KAAK,IAAI,EAAE,CAAC,MAAM,IAAA,yDAAgC,EAAC,OAAO,EAAE,OAAO,CAAC,CACrE,CAAC;QACF,MAAM,UAAU,CAAC,GAAG,EAAE,CAAC;IACzB,CAAC,CACF,CAAC;IAEF,YAAY,EAAE,CAAC,SAAS,CACtB,mCAAmC,EAEnC,KAAK,EAAE,OAAO,EAAE,EAAE;QAChB,IACE,CAAC,IAAA,qCAAwB,EAAC,OAAO,CAAC;YAClC,CAAC,gCAAgC,EAAE,CAAC,KAAK;iBACtC,kCAAkC;YACrC,4FAA4F;YAC5F,kEAAkE;YAClE,gCAAgC,EAAE,CAAC,oCAAoC,EAAE,EACzE;YACA,OAAO;SACR;QAED,MAAM,EAAE,UAAU,EAAE,GAAG,gCAAgC,EAAE,CAAC;QAE1D,UAAU,CAAC,IAAI,CACb,KAAK,IAAI,EAAE,CAAC,MAAM,IAAA,yDAAgC,EAAC,OAAO,EAAE,OAAO,CAAC,CACrE,CAAC;QACF,MAAM,UAAU,CAAC,GAAG,EAAE,CAAC;IACzB,CAAC,CACF,CAAC;AACJ,CAAC;AApDD,4EAoDC","sourcesContent":["import { saveInternalAccountToUserStorage } from './controller-integration';\nimport { canPerformAccountSyncing } from './sync-utils';\nimport type { AccountSyncingOptions } from './types';\n\n/**\n * Initialize and setup events to listen to for account syncing\n *\n * @param options - parameters used for initializing and enabling account syncing\n */\nexport function setupAccountSyncingSubscriptions(\n options: AccountSyncingOptions,\n) {\n const { getMessenger, getUserStorageControllerInstance } = options;\n\n getMessenger().subscribe(\n 'AccountsController:accountAdded',\n\n async (account) => {\n if (\n !canPerformAccountSyncing(options) ||\n !getUserStorageControllerInstance().state\n .hasAccountSyncingSyncedAtLeastOnce ||\n // If multichain account syncing is enabled, we do not push account syncing V1 data anymore.\n // AccountTreeController handles proper multichain account syncing\n getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()\n ) {\n return;\n }\n\n const { eventQueue } = getUserStorageControllerInstance();\n\n eventQueue.push(\n async () => await saveInternalAccountToUserStorage(account, options),\n );\n await eventQueue.run();\n },\n );\n\n getMessenger().subscribe(\n 'AccountsController:accountRenamed',\n\n async (account) => {\n if (\n !canPerformAccountSyncing(options) ||\n !getUserStorageControllerInstance().state\n .hasAccountSyncingSyncedAtLeastOnce ||\n // If multichain account syncing is enabled, we do not push account syncing V1 data anymore.\n // AccountTreeController handles proper multichain account syncing\n getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()\n ) {\n return;\n }\n\n const { eventQueue } = getUserStorageControllerInstance();\n\n eventQueue.push(\n async () => await saveInternalAccountToUserStorage(account, options),\n );\n await eventQueue.run();\n },\n );\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AccountSyncingOptions } from "./types.cjs";
|
|
2
|
+
/**
|
|
3
|
+
* Initialize and setup events to listen to for account syncing
|
|
4
|
+
*
|
|
5
|
+
* @param options - parameters used for initializing and enabling account syncing
|
|
6
|
+
*/
|
|
7
|
+
export declare function setupAccountSyncingSubscriptions(options: AccountSyncingOptions): void;
|
|
8
|
+
//# sourceMappingURL=setup-subscriptions.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-subscriptions.d.cts","sourceRoot":"","sources":["../../../../src/controllers/user-storage/account-syncing/setup-subscriptions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAgB;AAErD;;;;GAIG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,qBAAqB,QAmD/B"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AccountSyncingOptions } from "./types.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Initialize and setup events to listen to for account syncing
|
|
4
|
+
*
|
|
5
|
+
* @param options - parameters used for initializing and enabling account syncing
|
|
6
|
+
*/
|
|
7
|
+
export declare function setupAccountSyncingSubscriptions(options: AccountSyncingOptions): void;
|
|
8
|
+
//# sourceMappingURL=setup-subscriptions.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-subscriptions.d.mts","sourceRoot":"","sources":["../../../../src/controllers/user-storage/account-syncing/setup-subscriptions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAgB;AAErD;;;;GAIG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,qBAAqB,QAmD/B"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { saveInternalAccountToUserStorage } from "./controller-integration.mjs";
|
|
2
|
+
import { canPerformAccountSyncing } from "./sync-utils.mjs";
|
|
3
|
+
/**
|
|
4
|
+
* Initialize and setup events to listen to for account syncing
|
|
5
|
+
*
|
|
6
|
+
* @param options - parameters used for initializing and enabling account syncing
|
|
7
|
+
*/
|
|
8
|
+
export function setupAccountSyncingSubscriptions(options) {
|
|
9
|
+
const { getMessenger, getUserStorageControllerInstance } = options;
|
|
10
|
+
getMessenger().subscribe('AccountsController:accountAdded', async (account) => {
|
|
11
|
+
if (!canPerformAccountSyncing(options) ||
|
|
12
|
+
!getUserStorageControllerInstance().state
|
|
13
|
+
.hasAccountSyncingSyncedAtLeastOnce ||
|
|
14
|
+
// If multichain account syncing is enabled, we do not push account syncing V1 data anymore.
|
|
15
|
+
// AccountTreeController handles proper multichain account syncing
|
|
16
|
+
getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const { eventQueue } = getUserStorageControllerInstance();
|
|
20
|
+
eventQueue.push(async () => await saveInternalAccountToUserStorage(account, options));
|
|
21
|
+
await eventQueue.run();
|
|
22
|
+
});
|
|
23
|
+
getMessenger().subscribe('AccountsController:accountRenamed', async (account) => {
|
|
24
|
+
if (!canPerformAccountSyncing(options) ||
|
|
25
|
+
!getUserStorageControllerInstance().state
|
|
26
|
+
.hasAccountSyncingSyncedAtLeastOnce ||
|
|
27
|
+
// If multichain account syncing is enabled, we do not push account syncing V1 data anymore.
|
|
28
|
+
// AccountTreeController handles proper multichain account syncing
|
|
29
|
+
getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const { eventQueue } = getUserStorageControllerInstance();
|
|
33
|
+
eventQueue.push(async () => await saveInternalAccountToUserStorage(account, options));
|
|
34
|
+
await eventQueue.run();
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=setup-subscriptions.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-subscriptions.mjs","sourceRoot":"","sources":["../../../../src/controllers/user-storage/account-syncing/setup-subscriptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,qCAAiC;AAC5E,OAAO,EAAE,wBAAwB,EAAE,yBAAqB;AAGxD;;;;GAIG;AACH,MAAM,UAAU,gCAAgC,CAC9C,OAA8B;IAE9B,MAAM,EAAE,YAAY,EAAE,gCAAgC,EAAE,GAAG,OAAO,CAAC;IAEnE,YAAY,EAAE,CAAC,SAAS,CACtB,iCAAiC,EAEjC,KAAK,EAAE,OAAO,EAAE,EAAE;QAChB,IACE,CAAC,wBAAwB,CAAC,OAAO,CAAC;YAClC,CAAC,gCAAgC,EAAE,CAAC,KAAK;iBACtC,kCAAkC;YACrC,4FAA4F;YAC5F,kEAAkE;YAClE,gCAAgC,EAAE,CAAC,oCAAoC,EAAE,EACzE;YACA,OAAO;SACR;QAED,MAAM,EAAE,UAAU,EAAE,GAAG,gCAAgC,EAAE,CAAC;QAE1D,UAAU,CAAC,IAAI,CACb,KAAK,IAAI,EAAE,CAAC,MAAM,gCAAgC,CAAC,OAAO,EAAE,OAAO,CAAC,CACrE,CAAC;QACF,MAAM,UAAU,CAAC,GAAG,EAAE,CAAC;IACzB,CAAC,CACF,CAAC;IAEF,YAAY,EAAE,CAAC,SAAS,CACtB,mCAAmC,EAEnC,KAAK,EAAE,OAAO,EAAE,EAAE;QAChB,IACE,CAAC,wBAAwB,CAAC,OAAO,CAAC;YAClC,CAAC,gCAAgC,EAAE,CAAC,KAAK;iBACtC,kCAAkC;YACrC,4FAA4F;YAC5F,kEAAkE;YAClE,gCAAgC,EAAE,CAAC,oCAAoC,EAAE,EACzE;YACA,OAAO;SACR;QAED,MAAM,EAAE,UAAU,EAAE,GAAG,gCAAgC,EAAE,CAAC;QAE1D,UAAU,CAAC,IAAI,CACb,KAAK,IAAI,EAAE,CAAC,MAAM,gCAAgC,CAAC,OAAO,EAAE,OAAO,CAAC,CACrE,CAAC;QACF,MAAM,UAAU,CAAC,GAAG,EAAE,CAAC;IACzB,CAAC,CACF,CAAC;AACJ,CAAC","sourcesContent":["import { saveInternalAccountToUserStorage } from './controller-integration';\nimport { canPerformAccountSyncing } from './sync-utils';\nimport type { AccountSyncingOptions } from './types';\n\n/**\n * Initialize and setup events to listen to for account syncing\n *\n * @param options - parameters used for initializing and enabling account syncing\n */\nexport function setupAccountSyncingSubscriptions(\n options: AccountSyncingOptions,\n) {\n const { getMessenger, getUserStorageControllerInstance } = options;\n\n getMessenger().subscribe(\n 'AccountsController:accountAdded',\n\n async (account) => {\n if (\n !canPerformAccountSyncing(options) ||\n !getUserStorageControllerInstance().state\n .hasAccountSyncingSyncedAtLeastOnce ||\n // If multichain account syncing is enabled, we do not push account syncing V1 data anymore.\n // AccountTreeController handles proper multichain account syncing\n getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()\n ) {\n return;\n }\n\n const { eventQueue } = getUserStorageControllerInstance();\n\n eventQueue.push(\n async () => await saveInternalAccountToUserStorage(account, options),\n );\n await eventQueue.run();\n },\n );\n\n getMessenger().subscribe(\n 'AccountsController:accountRenamed',\n\n async (account) => {\n if (\n !canPerformAccountSyncing(options) ||\n !getUserStorageControllerInstance().state\n .hasAccountSyncingSyncedAtLeastOnce ||\n // If multichain account syncing is enabled, we do not push account syncing V1 data anymore.\n // AccountTreeController handles proper multichain account syncing\n getUserStorageControllerInstance().getIsMultichainAccountSyncingEnabled()\n ) {\n return;\n }\n\n const { eventQueue } = getUserStorageControllerInstance();\n\n eventQueue.push(\n async () => await saveInternalAccountToUserStorage(account, options),\n );\n await eventQueue.run();\n },\n );\n}\n"]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getUserStorageAccountsList = exports.getInternalAccountsList = exports.canPerformAccountSyncing = void 0;
|
|
4
|
+
const keyring_controller_1 = require("@metamask/keyring-controller");
|
|
5
|
+
const storage_schema_1 = require("../../../shared/storage-schema.cjs");
|
|
6
|
+
/**
|
|
7
|
+
* Checks if account syncing can be performed based on a set of conditions
|
|
8
|
+
*
|
|
9
|
+
* @param options - parameters used for checking if account syncing can be performed
|
|
10
|
+
* @returns Returns true if account syncing can be performed, false otherwise.
|
|
11
|
+
*/
|
|
12
|
+
function canPerformAccountSyncing(options) {
|
|
13
|
+
const { getMessenger, getUserStorageControllerInstance } = options;
|
|
14
|
+
const { isBackupAndSyncEnabled, isAccountSyncingEnabled, isAccountSyncingInProgress, } = getUserStorageControllerInstance().state;
|
|
15
|
+
const isAuthEnabled = getMessenger().call('AuthenticationController:isSignedIn');
|
|
16
|
+
if (!isBackupAndSyncEnabled ||
|
|
17
|
+
!isAccountSyncingEnabled ||
|
|
18
|
+
!isAuthEnabled ||
|
|
19
|
+
isAccountSyncingInProgress) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
exports.canPerformAccountSyncing = canPerformAccountSyncing;
|
|
25
|
+
/**
|
|
26
|
+
* Get the list of internal accounts
|
|
27
|
+
* This function returns only the internal accounts that are from the primary SRP
|
|
28
|
+
* and are from the HD keyring
|
|
29
|
+
*
|
|
30
|
+
* @param options - parameters used for getting the list of internal accounts
|
|
31
|
+
* @param entropySourceId - The entropy source ID used to derive the key,
|
|
32
|
+
* when multiple sources are available (Multi-SRP).
|
|
33
|
+
* @returns the list of internal accounts
|
|
34
|
+
*/
|
|
35
|
+
async function getInternalAccountsList(options, entropySourceId) {
|
|
36
|
+
const { getMessenger } = options;
|
|
37
|
+
let internalAccountsList = getMessenger().call('AccountsController:listAccounts');
|
|
38
|
+
const doEachInternalAccountHaveEntropySource = internalAccountsList.every((account) => Boolean(account.options.entropySource));
|
|
39
|
+
if (!doEachInternalAccountHaveEntropySource) {
|
|
40
|
+
await getMessenger().call('AccountsController:updateAccounts');
|
|
41
|
+
internalAccountsList = getMessenger().call('AccountsController:listAccounts');
|
|
42
|
+
}
|
|
43
|
+
return internalAccountsList.filter((account) => entropySourceId === account.options.entropySource &&
|
|
44
|
+
account.metadata.keyring.type === String(keyring_controller_1.KeyringTypes.hd));
|
|
45
|
+
}
|
|
46
|
+
exports.getInternalAccountsList = getInternalAccountsList;
|
|
47
|
+
/**
|
|
48
|
+
* Get the list of user storage accounts
|
|
49
|
+
*
|
|
50
|
+
* @param options - parameters used for getting the list of user storage accounts
|
|
51
|
+
* @param entropySourceId - The entropy source ID used to derive the storage key,
|
|
52
|
+
* when multiple sources are available (Multi-SRP).
|
|
53
|
+
* @returns the list of user storage accounts
|
|
54
|
+
*/
|
|
55
|
+
async function getUserStorageAccountsList(options, entropySourceId) {
|
|
56
|
+
const { getUserStorageControllerInstance } = options;
|
|
57
|
+
const rawAccountsListResponse = await getUserStorageControllerInstance().performGetStorageAllFeatureEntries(storage_schema_1.USER_STORAGE_FEATURE_NAMES.accounts, entropySourceId);
|
|
58
|
+
return (rawAccountsListResponse?.map((rawAccount) => JSON.parse(rawAccount)) ?? null);
|
|
59
|
+
}
|
|
60
|
+
exports.getUserStorageAccountsList = getUserStorageAccountsList;
|
|
61
|
+
//# sourceMappingURL=sync-utils.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-utils.cjs","sourceRoot":"","sources":["../../../../src/controllers/user-storage/account-syncing/sync-utils.ts"],"names":[],"mappings":";;;AAAA,qEAA4D;AAI5D,uEAA4E;AAE5E;;;;;GAKG;AACH,SAAgB,wBAAwB,CACtC,OAA8B;IAE9B,MAAM,EAAE,YAAY,EAAE,gCAAgC,EAAE,GAAG,OAAO,CAAC;IAEnE,MAAM,EACJ,sBAAsB,EACtB,uBAAuB,EACvB,0BAA0B,GAC3B,GAAG,gCAAgC,EAAE,CAAC,KAAK,CAAC;IAC7C,MAAM,aAAa,GAAG,YAAY,EAAE,CAAC,IAAI,CACvC,qCAAqC,CACtC,CAAC;IAEF,IACE,CAAC,sBAAsB;QACvB,CAAC,uBAAuB;QACxB,CAAC,aAAa;QACd,0BAA0B,EAC1B;QACA,OAAO,KAAK,CAAC;KACd;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAxBD,4DAwBC;AAED;;;;;;;;;GASG;AACI,KAAK,UAAU,uBAAuB,CAC3C,OAA8B,EAC9B,eAAuB;IAEvB,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;IAEjC,IAAI,oBAAoB,GAAG,YAAY,EAAE,CAAC,IAAI,CAC5C,iCAAiC,CAClC,CAAC;IAEF,MAAM,sCAAsC,GAAG,oBAAoB,CAAC,KAAK,CACvE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CACpD,CAAC;IAEF,IAAI,CAAC,sCAAsC,EAAE;QAC3C,MAAM,YAAY,EAAE,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QAC/D,oBAAoB,GAAG,YAAY,EAAE,CAAC,IAAI,CACxC,iCAAiC,CAClC,CAAC;KACH;IAED,OAAO,oBAAoB,CAAC,MAAM,CAChC,CAAC,OAAO,EAAE,EAAE,CACV,eAAe,KAAK,OAAO,CAAC,OAAO,CAAC,aAAa;QACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,iCAAY,CAAC,EAAE,CAAC,CAC5D,CAAC;AACJ,CAAC;AA1BD,0DA0BC;AAED;;;;;;;GAOG;AACI,KAAK,UAAU,0BAA0B,CAC9C,OAA8B,EAC9B,eAAwB;IAExB,MAAM,EAAE,gCAAgC,EAAE,GAAG,OAAO,CAAC;IAErD,MAAM,uBAAuB,GAC3B,MAAM,gCAAgC,EAAE,CAAC,kCAAkC,CACzE,2CAA0B,CAAC,QAAQ,EACnC,eAAe,CAChB,CAAC;IAEJ,OAAO,CACL,uBAAuB,EAAE,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,IAAI,CAC7E,CAAC;AACJ,CAAC;AAfD,gEAeC","sourcesContent":["import { KeyringTypes } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport type { AccountSyncingOptions, UserStorageAccount } from './types';\nimport { USER_STORAGE_FEATURE_NAMES } from '../../../shared/storage-schema';\n\n/**\n * Checks if account syncing can be performed based on a set of conditions\n *\n * @param options - parameters used for checking if account syncing can be performed\n * @returns Returns true if account syncing can be performed, false otherwise.\n */\nexport function canPerformAccountSyncing(\n options: AccountSyncingOptions,\n): boolean {\n const { getMessenger, getUserStorageControllerInstance } = options;\n\n const {\n isBackupAndSyncEnabled,\n isAccountSyncingEnabled,\n isAccountSyncingInProgress,\n } = getUserStorageControllerInstance().state;\n const isAuthEnabled = getMessenger().call(\n 'AuthenticationController:isSignedIn',\n );\n\n if (\n !isBackupAndSyncEnabled ||\n !isAccountSyncingEnabled ||\n !isAuthEnabled ||\n isAccountSyncingInProgress\n ) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Get the list of internal accounts\n * This function returns only the internal accounts that are from the primary SRP\n * and are from the HD keyring\n *\n * @param options - parameters used for getting the list of internal accounts\n * @param entropySourceId - The entropy source ID used to derive the key,\n * when multiple sources are available (Multi-SRP).\n * @returns the list of internal accounts\n */\nexport async function getInternalAccountsList(\n options: AccountSyncingOptions,\n entropySourceId: string,\n): Promise<InternalAccount[]> {\n const { getMessenger } = options;\n\n let internalAccountsList = getMessenger().call(\n 'AccountsController:listAccounts',\n );\n\n const doEachInternalAccountHaveEntropySource = internalAccountsList.every(\n (account) => Boolean(account.options.entropySource),\n );\n\n if (!doEachInternalAccountHaveEntropySource) {\n await getMessenger().call('AccountsController:updateAccounts');\n internalAccountsList = getMessenger().call(\n 'AccountsController:listAccounts',\n );\n }\n\n return internalAccountsList.filter(\n (account) =>\n entropySourceId === account.options.entropySource &&\n account.metadata.keyring.type === String(KeyringTypes.hd), // sync only EVM accounts until we support multichain accounts\n );\n}\n\n/**\n * Get the list of user storage accounts\n *\n * @param options - parameters used for getting the list of user storage accounts\n * @param entropySourceId - The entropy source ID used to derive the storage key,\n * when multiple sources are available (Multi-SRP).\n * @returns the list of user storage accounts\n */\nexport async function getUserStorageAccountsList(\n options: AccountSyncingOptions,\n entropySourceId?: string,\n): Promise<UserStorageAccount[] | null> {\n const { getUserStorageControllerInstance } = options;\n\n const rawAccountsListResponse =\n await getUserStorageControllerInstance().performGetStorageAllFeatureEntries(\n USER_STORAGE_FEATURE_NAMES.accounts,\n entropySourceId,\n );\n\n return (\n rawAccountsListResponse?.map((rawAccount) => JSON.parse(rawAccount)) ?? null\n );\n}\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { InternalAccount } from "@metamask/keyring-internal-api";
|
|
2
|
+
import type { AccountSyncingOptions, UserStorageAccount } from "./types.cjs";
|
|
3
|
+
/**
|
|
4
|
+
* Checks if account syncing can be performed based on a set of conditions
|
|
5
|
+
*
|
|
6
|
+
* @param options - parameters used for checking if account syncing can be performed
|
|
7
|
+
* @returns Returns true if account syncing can be performed, false otherwise.
|
|
8
|
+
*/
|
|
9
|
+
export declare function canPerformAccountSyncing(options: AccountSyncingOptions): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Get the list of internal accounts
|
|
12
|
+
* This function returns only the internal accounts that are from the primary SRP
|
|
13
|
+
* and are from the HD keyring
|
|
14
|
+
*
|
|
15
|
+
* @param options - parameters used for getting the list of internal accounts
|
|
16
|
+
* @param entropySourceId - The entropy source ID used to derive the key,
|
|
17
|
+
* when multiple sources are available (Multi-SRP).
|
|
18
|
+
* @returns the list of internal accounts
|
|
19
|
+
*/
|
|
20
|
+
export declare function getInternalAccountsList(options: AccountSyncingOptions, entropySourceId: string): Promise<InternalAccount[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Get the list of user storage accounts
|
|
23
|
+
*
|
|
24
|
+
* @param options - parameters used for getting the list of user storage accounts
|
|
25
|
+
* @param entropySourceId - The entropy source ID used to derive the storage key,
|
|
26
|
+
* when multiple sources are available (Multi-SRP).
|
|
27
|
+
* @returns the list of user storage accounts
|
|
28
|
+
*/
|
|
29
|
+
export declare function getUserStorageAccountsList(options: AccountSyncingOptions, entropySourceId?: string): Promise<UserStorageAccount[] | null>;
|
|
30
|
+
//# sourceMappingURL=sync-utils.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-utils.d.cts","sourceRoot":"","sources":["../../../../src/controllers/user-storage/account-syncing/sync-utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAEtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,oBAAgB;AAGzE;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAsBT;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,qBAAqB,EAC9B,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,eAAe,EAAE,CAAC,CAuB5B;AAED;;;;;;;GAOG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,qBAAqB,EAC9B,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,kBAAkB,EAAE,GAAG,IAAI,CAAC,CAYtC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { InternalAccount } from "@metamask/keyring-internal-api";
|
|
2
|
+
import type { AccountSyncingOptions, UserStorageAccount } from "./types.mjs";
|
|
3
|
+
/**
|
|
4
|
+
* Checks if account syncing can be performed based on a set of conditions
|
|
5
|
+
*
|
|
6
|
+
* @param options - parameters used for checking if account syncing can be performed
|
|
7
|
+
* @returns Returns true if account syncing can be performed, false otherwise.
|
|
8
|
+
*/
|
|
9
|
+
export declare function canPerformAccountSyncing(options: AccountSyncingOptions): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Get the list of internal accounts
|
|
12
|
+
* This function returns only the internal accounts that are from the primary SRP
|
|
13
|
+
* and are from the HD keyring
|
|
14
|
+
*
|
|
15
|
+
* @param options - parameters used for getting the list of internal accounts
|
|
16
|
+
* @param entropySourceId - The entropy source ID used to derive the key,
|
|
17
|
+
* when multiple sources are available (Multi-SRP).
|
|
18
|
+
* @returns the list of internal accounts
|
|
19
|
+
*/
|
|
20
|
+
export declare function getInternalAccountsList(options: AccountSyncingOptions, entropySourceId: string): Promise<InternalAccount[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Get the list of user storage accounts
|
|
23
|
+
*
|
|
24
|
+
* @param options - parameters used for getting the list of user storage accounts
|
|
25
|
+
* @param entropySourceId - The entropy source ID used to derive the storage key,
|
|
26
|
+
* when multiple sources are available (Multi-SRP).
|
|
27
|
+
* @returns the list of user storage accounts
|
|
28
|
+
*/
|
|
29
|
+
export declare function getUserStorageAccountsList(options: AccountSyncingOptions, entropySourceId?: string): Promise<UserStorageAccount[] | null>;
|
|
30
|
+
//# sourceMappingURL=sync-utils.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-utils.d.mts","sourceRoot":"","sources":["../../../../src/controllers/user-storage/account-syncing/sync-utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAEtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,oBAAgB;AAGzE;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAsBT;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,qBAAqB,EAC9B,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,eAAe,EAAE,CAAC,CAuB5B;AAED;;;;;;;GAOG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,qBAAqB,EAC9B,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,kBAAkB,EAAE,GAAG,IAAI,CAAC,CAYtC"}
|