@metamask/profile-sync-controller 20.0.0 → 22.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -1
- package/dist/controllers/authentication/AuthenticationController.cjs +16 -9
- package/dist/controllers/authentication/AuthenticationController.cjs.map +1 -1
- package/dist/controllers/authentication/AuthenticationController.d.cts +6 -1
- package/dist/controllers/authentication/AuthenticationController.d.cts.map +1 -1
- package/dist/controllers/authentication/AuthenticationController.d.mts +6 -1
- package/dist/controllers/authentication/AuthenticationController.d.mts.map +1 -1
- package/dist/controllers/authentication/AuthenticationController.mjs +16 -9
- package/dist/controllers/authentication/AuthenticationController.mjs.map +1 -1
- package/dist/controllers/user-storage/UserStorageController.cjs +24 -47
- package/dist/controllers/user-storage/UserStorageController.cjs.map +1 -1
- package/dist/controllers/user-storage/UserStorageController.d.cts +16 -49
- package/dist/controllers/user-storage/UserStorageController.d.cts.map +1 -1
- package/dist/controllers/user-storage/UserStorageController.d.mts +16 -49
- package/dist/controllers/user-storage/UserStorageController.d.mts.map +1 -1
- package/dist/controllers/user-storage/UserStorageController.mjs +24 -47
- package/dist/controllers/user-storage/UserStorageController.mjs.map +1 -1
- package/dist/controllers/user-storage/account-syncing/controller-integration.cjs +185 -166
- package/dist/controllers/user-storage/account-syncing/controller-integration.cjs.map +1 -1
- package/dist/controllers/user-storage/account-syncing/controller-integration.d.cts +3 -0
- package/dist/controllers/user-storage/account-syncing/controller-integration.d.cts.map +1 -1
- package/dist/controllers/user-storage/account-syncing/controller-integration.d.mts +3 -0
- package/dist/controllers/user-storage/account-syncing/controller-integration.d.mts.map +1 -1
- package/dist/controllers/user-storage/account-syncing/controller-integration.mjs +185 -166
- package/dist/controllers/user-storage/account-syncing/controller-integration.mjs.map +1 -1
- package/dist/controllers/user-storage/account-syncing/types.cjs.map +1 -1
- package/dist/controllers/user-storage/account-syncing/types.d.cts +2 -0
- package/dist/controllers/user-storage/account-syncing/types.d.cts.map +1 -1
- package/dist/controllers/user-storage/account-syncing/types.d.mts +2 -0
- package/dist/controllers/user-storage/account-syncing/types.d.mts.map +1 -1
- package/dist/controllers/user-storage/account-syncing/types.mjs.map +1 -1
- package/dist/controllers/user-storage/constants.cjs +14 -1
- package/dist/controllers/user-storage/constants.cjs.map +1 -1
- package/dist/controllers/user-storage/constants.d.cts +11 -0
- package/dist/controllers/user-storage/constants.d.cts.map +1 -1
- package/dist/controllers/user-storage/constants.d.mts +11 -0
- package/dist/controllers/user-storage/constants.d.mts.map +1 -1
- package/dist/controllers/user-storage/constants.mjs +13 -0
- package/dist/controllers/user-storage/constants.mjs.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/controller-integration.cjs +227 -162
- package/dist/controllers/user-storage/contact-syncing/controller-integration.cjs.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/controller-integration.d.cts +3 -0
- package/dist/controllers/user-storage/contact-syncing/controller-integration.d.cts.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/controller-integration.d.mts +3 -0
- package/dist/controllers/user-storage/contact-syncing/controller-integration.d.mts.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/controller-integration.mjs +227 -162
- package/dist/controllers/user-storage/contact-syncing/controller-integration.mjs.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/types.cjs.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/types.d.cts +2 -0
- package/dist/controllers/user-storage/contact-syncing/types.d.cts.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/types.d.mts +2 -0
- package/dist/controllers/user-storage/contact-syncing/types.d.mts.map +1 -1
- package/dist/controllers/user-storage/contact-syncing/types.mjs.map +1 -1
- package/dist/controllers/user-storage/mocks/mockResponses.cjs +1 -1
- package/dist/controllers/user-storage/mocks/mockResponses.cjs.map +1 -1
- package/dist/controllers/user-storage/mocks/mockResponses.d.cts +9 -9
- package/dist/controllers/user-storage/mocks/mockResponses.d.cts.map +1 -1
- package/dist/controllers/user-storage/mocks/mockResponses.d.mts +9 -9
- package/dist/controllers/user-storage/mocks/mockResponses.d.mts.map +1 -1
- package/dist/controllers/user-storage/mocks/mockResponses.mjs +1 -1
- package/dist/controllers/user-storage/mocks/mockResponses.mjs.map +1 -1
- package/dist/controllers/user-storage/types.cjs.map +1 -1
- package/dist/controllers/user-storage/types.d.cts +3 -3
- package/dist/controllers/user-storage/types.d.cts.map +1 -1
- package/dist/controllers/user-storage/types.d.mts +3 -3
- package/dist/controllers/user-storage/types.d.mts.map +1 -1
- package/dist/controllers/user-storage/types.mjs.map +1 -1
- package/dist/sdk/user-storage.cjs +3 -9
- package/dist/sdk/user-storage.cjs.map +1 -1
- package/dist/sdk/user-storage.d.cts +0 -1
- package/dist/sdk/user-storage.d.cts.map +1 -1
- package/dist/sdk/user-storage.d.mts +0 -1
- package/dist/sdk/user-storage.d.mts.map +1 -1
- package/dist/sdk/user-storage.mjs +3 -9
- package/dist/sdk/user-storage.mjs.map +1 -1
- package/dist/shared/storage-schema.cjs +9 -32
- package/dist/shared/storage-schema.cjs.map +1 -1
- package/dist/shared/storage-schema.d.cts +10 -42
- package/dist/shared/storage-schema.d.cts.map +1 -1
- package/dist/shared/storage-schema.d.mts +10 -42
- package/dist/shared/storage-schema.d.mts.map +1 -1
- package/dist/shared/storage-schema.mjs +8 -31
- package/dist/shared/storage-schema.mjs.map +1 -1
- package/package.json +5 -7
- package/dist/controllers/user-storage/network-syncing/add-network-utils.cjs +0 -36
- package/dist/controllers/user-storage/network-syncing/add-network-utils.cjs.map +0 -1
- package/dist/controllers/user-storage/network-syncing/add-network-utils.d.cts +0 -22
- package/dist/controllers/user-storage/network-syncing/add-network-utils.d.cts.map +0 -1
- package/dist/controllers/user-storage/network-syncing/add-network-utils.d.mts +0 -22
- package/dist/controllers/user-storage/network-syncing/add-network-utils.d.mts.map +0 -1
- package/dist/controllers/user-storage/network-syncing/add-network-utils.mjs +0 -31
- package/dist/controllers/user-storage/network-syncing/add-network-utils.mjs.map +0 -1
- package/dist/controllers/user-storage/network-syncing/controller-integration.cjs +0 -193
- package/dist/controllers/user-storage/network-syncing/controller-integration.cjs.map +0 -1
- package/dist/controllers/user-storage/network-syncing/controller-integration.d.cts +0 -57
- package/dist/controllers/user-storage/network-syncing/controller-integration.d.cts.map +0 -1
- package/dist/controllers/user-storage/network-syncing/controller-integration.d.mts +0 -57
- package/dist/controllers/user-storage/network-syncing/controller-integration.d.mts.map +0 -1
- package/dist/controllers/user-storage/network-syncing/controller-integration.mjs +0 -191
- package/dist/controllers/user-storage/network-syncing/controller-integration.mjs.map +0 -1
- package/dist/controllers/user-storage/network-syncing/services.cjs +0 -79
- package/dist/controllers/user-storage/network-syncing/services.cjs.map +0 -1
- package/dist/controllers/user-storage/network-syncing/services.d.cts +0 -34
- package/dist/controllers/user-storage/network-syncing/services.d.cts.map +0 -1
- package/dist/controllers/user-storage/network-syncing/services.d.mts +0 -34
- package/dist/controllers/user-storage/network-syncing/services.d.mts.map +0 -1
- package/dist/controllers/user-storage/network-syncing/services.mjs +0 -73
- package/dist/controllers/user-storage/network-syncing/services.mjs.map +0 -1
- package/dist/controllers/user-storage/network-syncing/sync-all.cjs +0 -153
- package/dist/controllers/user-storage/network-syncing/sync-all.cjs.map +0 -1
- package/dist/controllers/user-storage/network-syncing/sync-all.d.cts +0 -32
- package/dist/controllers/user-storage/network-syncing/sync-all.d.cts.map +0 -1
- package/dist/controllers/user-storage/network-syncing/sync-all.d.mts +0 -32
- package/dist/controllers/user-storage/network-syncing/sync-all.d.mts.map +0 -1
- package/dist/controllers/user-storage/network-syncing/sync-all.mjs +0 -145
- package/dist/controllers/user-storage/network-syncing/sync-all.mjs.map +0 -1
- package/dist/controllers/user-storage/network-syncing/sync-mutations.cjs +0 -28
- package/dist/controllers/user-storage/network-syncing/sync-mutations.cjs.map +0 -1
- package/dist/controllers/user-storage/network-syncing/sync-mutations.d.cts +0 -17
- package/dist/controllers/user-storage/network-syncing/sync-mutations.d.cts.map +0 -1
- package/dist/controllers/user-storage/network-syncing/sync-mutations.d.mts +0 -17
- package/dist/controllers/user-storage/network-syncing/sync-mutations.d.mts.map +0 -1
- package/dist/controllers/user-storage/network-syncing/sync-mutations.mjs +0 -22
- package/dist/controllers/user-storage/network-syncing/sync-mutations.mjs.map +0 -1
- package/dist/controllers/user-storage/network-syncing/types.cjs +0 -16
- package/dist/controllers/user-storage/network-syncing/types.cjs.map +0 -1
- package/dist/controllers/user-storage/network-syncing/types.d.cts +0 -15
- package/dist/controllers/user-storage/network-syncing/types.d.cts.map +0 -1
- package/dist/controllers/user-storage/network-syncing/types.d.mts +0 -15
- package/dist/controllers/user-storage/network-syncing/types.d.mts.map +0 -1
- package/dist/controllers/user-storage/network-syncing/types.mjs +0 -11
- package/dist/controllers/user-storage/network-syncing/types.mjs.map +0 -1
- package/dist/controllers/user-storage/network-syncing/update-network-utils.cjs +0 -129
- package/dist/controllers/user-storage/network-syncing/update-network-utils.cjs.map +0 -1
- package/dist/controllers/user-storage/network-syncing/update-network-utils.d.cts +0 -59
- package/dist/controllers/user-storage/network-syncing/update-network-utils.d.cts.map +0 -1
- package/dist/controllers/user-storage/network-syncing/update-network-utils.d.mts +0 -59
- package/dist/controllers/user-storage/network-syncing/update-network-utils.d.mts.map +0 -1
- package/dist/controllers/user-storage/network-syncing/update-network-utils.mjs +0 -122
- package/dist/controllers/user-storage/network-syncing/update-network-utils.mjs.map +0 -1
|
@@ -3,4 +3,15 @@ export declare const BACKUPANDSYNC_FEATURES: {
|
|
|
3
3
|
readonly accountSyncing: "accountSyncing";
|
|
4
4
|
readonly contactSyncing: "contactSyncing";
|
|
5
5
|
};
|
|
6
|
+
/**
|
|
7
|
+
* Trace names for UserStorage syncing operations
|
|
8
|
+
*/
|
|
9
|
+
export declare const TraceName: {
|
|
10
|
+
readonly ContactSyncFull: "Contact Sync Full";
|
|
11
|
+
readonly ContactSyncSaveBatch: "Contact Sync Save Batch";
|
|
12
|
+
readonly ContactSyncUpdateRemote: "Contact Sync Update Remote";
|
|
13
|
+
readonly ContactSyncDeleteRemote: "Contact Sync Delete Remote";
|
|
14
|
+
readonly AccountSyncFull: "Account Sync Full";
|
|
15
|
+
readonly AccountSyncSaveIndividual: "Account Sync Save Individual";
|
|
16
|
+
};
|
|
6
17
|
//# sourceMappingURL=constants.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.cts","sourceRoot":"","sources":["../../../src/controllers/user-storage/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB;;;;CAIzB,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.cts","sourceRoot":"","sources":["../../../src/controllers/user-storage/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB;;;;CAIzB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,SAAS;;;;;;;CAUZ,CAAC"}
|
|
@@ -3,4 +3,15 @@ export declare const BACKUPANDSYNC_FEATURES: {
|
|
|
3
3
|
readonly accountSyncing: "accountSyncing";
|
|
4
4
|
readonly contactSyncing: "contactSyncing";
|
|
5
5
|
};
|
|
6
|
+
/**
|
|
7
|
+
* Trace names for UserStorage syncing operations
|
|
8
|
+
*/
|
|
9
|
+
export declare const TraceName: {
|
|
10
|
+
readonly ContactSyncFull: "Contact Sync Full";
|
|
11
|
+
readonly ContactSyncSaveBatch: "Contact Sync Save Batch";
|
|
12
|
+
readonly ContactSyncUpdateRemote: "Contact Sync Update Remote";
|
|
13
|
+
readonly ContactSyncDeleteRemote: "Contact Sync Delete Remote";
|
|
14
|
+
readonly AccountSyncFull: "Account Sync Full";
|
|
15
|
+
readonly AccountSyncSaveIndividual: "Account Sync Save Individual";
|
|
16
|
+
};
|
|
6
17
|
//# sourceMappingURL=constants.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../../src/controllers/user-storage/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB;;;;CAIzB,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../../src/controllers/user-storage/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB;;;;CAIzB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,SAAS;;;;;;;CAUZ,CAAC"}
|
|
@@ -3,4 +3,17 @@ export const BACKUPANDSYNC_FEATURES = {
|
|
|
3
3
|
accountSyncing: 'accountSyncing',
|
|
4
4
|
contactSyncing: 'contactSyncing',
|
|
5
5
|
};
|
|
6
|
+
/**
|
|
7
|
+
* Trace names for UserStorage syncing operations
|
|
8
|
+
*/
|
|
9
|
+
export const TraceName = {
|
|
10
|
+
// Contact syncing traces
|
|
11
|
+
ContactSyncFull: 'Contact Sync Full',
|
|
12
|
+
ContactSyncSaveBatch: 'Contact Sync Save Batch',
|
|
13
|
+
ContactSyncUpdateRemote: 'Contact Sync Update Remote',
|
|
14
|
+
ContactSyncDeleteRemote: 'Contact Sync Delete Remote',
|
|
15
|
+
// Account syncing traces
|
|
16
|
+
AccountSyncFull: 'Account Sync Full',
|
|
17
|
+
AccountSyncSaveIndividual: 'Account Sync Save Individual',
|
|
18
|
+
};
|
|
6
19
|
//# sourceMappingURL=constants.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.mjs","sourceRoot":"","sources":["../../../src/controllers/user-storage/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,IAAI,EAAE,MAAM;IACZ,cAAc,EAAE,gBAAgB;IAChC,cAAc,EAAE,gBAAgB;CACxB,CAAC","sourcesContent":["export const BACKUPANDSYNC_FEATURES = {\n main: 'main',\n accountSyncing: 'accountSyncing',\n contactSyncing: 'contactSyncing',\n} as const;\n"]}
|
|
1
|
+
{"version":3,"file":"constants.mjs","sourceRoot":"","sources":["../../../src/controllers/user-storage/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,IAAI,EAAE,MAAM;IACZ,cAAc,EAAE,gBAAgB;IAChC,cAAc,EAAE,gBAAgB;CACxB,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,yBAAyB;IACzB,eAAe,EAAE,mBAAmB;IACpC,oBAAoB,EAAE,yBAAyB;IAC/C,uBAAuB,EAAE,4BAA4B;IACrD,uBAAuB,EAAE,4BAA4B;IAErD,yBAAyB;IACzB,eAAe,EAAE,mBAAmB;IACpC,yBAAyB,EAAE,8BAA8B;CACjD,CAAC","sourcesContent":["export const BACKUPANDSYNC_FEATURES = {\n main: 'main',\n accountSyncing: 'accountSyncing',\n contactSyncing: 'contactSyncing',\n} as const;\n\n/**\n * Trace names for UserStorage syncing operations\n */\nexport const TraceName = {\n // Contact syncing traces\n ContactSyncFull: 'Contact Sync Full',\n ContactSyncSaveBatch: 'Contact Sync Save Batch',\n ContactSyncUpdateRemote: 'Contact Sync Update Remote',\n ContactSyncDeleteRemote: 'Contact Sync Delete Remote',\n\n // Account syncing traces\n AccountSyncFull: 'Account Sync Full',\n AccountSyncSaveIndividual: 'Account Sync Save Individual',\n} as const;\n"]}
|
|
@@ -5,6 +5,7 @@ const sync_utils_1 = require("./sync-utils.cjs");
|
|
|
5
5
|
const utils_1 = require("./utils.cjs");
|
|
6
6
|
const utils_2 = require("./utils.cjs");
|
|
7
7
|
const storage_schema_1 = require("../../../shared/storage-schema.cjs");
|
|
8
|
+
const constants_1 = require("../constants.cjs");
|
|
8
9
|
/**
|
|
9
10
|
* Creates a unique key for a contact based on chainId and address
|
|
10
11
|
*
|
|
@@ -35,138 +36,163 @@ function createContactKey(contact) {
|
|
|
35
36
|
*
|
|
36
37
|
* @param config - Parameters used for syncing callbacks
|
|
37
38
|
* @param options - Parameters used for syncing operations
|
|
39
|
+
* @returns Promise that resolves when contact synchronization is complete
|
|
38
40
|
*/
|
|
39
41
|
async function syncContactsWithUserStorage(config, options) {
|
|
40
|
-
const { getMessenger, getUserStorageControllerInstance } = options;
|
|
42
|
+
const { getMessenger, getUserStorageControllerInstance, trace } = options;
|
|
41
43
|
const { onContactSyncErroneousSituation, onContactUpdated, onContactDeleted, } = config;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
localContactsMap
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
//
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
contactsToAddOrUpdateLocally.push(remoteContact);
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
// SCENARIO 4 & 6: Contact exists on both sides - check for conflicts
|
|
90
|
-
const hasContentDifference = localContact.name !== remoteContact.name ||
|
|
91
|
-
localContact.memo !== remoteContact.memo;
|
|
92
|
-
if (hasContentDifference) {
|
|
93
|
-
// Check timestamps to determine which version to keep
|
|
94
|
-
const localTimestamp = localContact.lastUpdatedAt || 0;
|
|
95
|
-
const remoteTimestamp = remoteContact.lastUpdatedAt || 0;
|
|
96
|
-
if (localTimestamp >= remoteTimestamp) {
|
|
97
|
-
// Local is newer (or same age) - use local version
|
|
98
|
-
contactsToUpdateRemotely.push(localContact);
|
|
44
|
+
// Cannot perform sync, conditions not met
|
|
45
|
+
if (!(0, sync_utils_1.canPerformContactSyncing)(options)) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
// NOTE: Pre-sync operations (canPerformContactSyncing, AddressBookController:list, getRemoteContacts)
|
|
49
|
+
// are intentionally outside try-catch to let errors bubble up to Sentry for better debugging.
|
|
50
|
+
// Only "erroneous situation" errors during sync logic itself should be caught.
|
|
51
|
+
// Get all local contacts from AddressBookController (exclude chain "*" contacts)
|
|
52
|
+
const localVisibleContacts = getMessenger()
|
|
53
|
+
.call('AddressBookController:list')
|
|
54
|
+
.filter((contact) => !(0, utils_2.isContactBridgedFromAccounts)(contact))
|
|
55
|
+
.filter((contact) => contact.address && contact.chainId && contact.name?.trim()) || [];
|
|
56
|
+
// Get remote contacts from user storage API
|
|
57
|
+
const remoteContacts = await getRemoteContacts(options);
|
|
58
|
+
// Filter remote contacts to exclude invalid ones (or empty array if no remote contacts)
|
|
59
|
+
const validRemoteContacts = remoteContacts?.filter((contact) => contact.address && contact.chainId && contact.name?.trim()) || [];
|
|
60
|
+
const performSync = async () => {
|
|
61
|
+
try {
|
|
62
|
+
// Activate sync semaphore to prevent event loops
|
|
63
|
+
await getUserStorageControllerInstance().setIsContactSyncingInProgress(true);
|
|
64
|
+
// Prepare maps for efficient lookup
|
|
65
|
+
const localContactsMap = new Map();
|
|
66
|
+
const remoteContactsMap = new Map();
|
|
67
|
+
localVisibleContacts.forEach((contact) => {
|
|
68
|
+
const key = createContactKey(contact);
|
|
69
|
+
localContactsMap.set(key, contact);
|
|
70
|
+
});
|
|
71
|
+
validRemoteContacts.forEach((contact) => {
|
|
72
|
+
const key = createContactKey(contact);
|
|
73
|
+
remoteContactsMap.set(key, contact);
|
|
74
|
+
});
|
|
75
|
+
// Lists to track contacts that need to be synced
|
|
76
|
+
const contactsToAddOrUpdateLocally = [];
|
|
77
|
+
const contactsToDeleteLocally = [];
|
|
78
|
+
const contactsToUpdateRemotely = [];
|
|
79
|
+
// SCENARIO 2 & 6: Process remote contacts - handle new device sync and remote updates
|
|
80
|
+
for (const remoteContact of validRemoteContacts) {
|
|
81
|
+
const key = createContactKey(remoteContact);
|
|
82
|
+
const localContact = localContactsMap.get(key);
|
|
83
|
+
// Handle remote contact based on its status and local existence
|
|
84
|
+
if (remoteContact.deletedAt) {
|
|
85
|
+
// SCENARIO 8: Remote deletion - should be applied locally if contact exists locally
|
|
86
|
+
if (localContact) {
|
|
87
|
+
contactsToDeleteLocally.push(remoteContact);
|
|
99
88
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
89
|
+
}
|
|
90
|
+
else if (!localContact) {
|
|
91
|
+
// SCENARIO 2: New contact from remote - import to local
|
|
92
|
+
contactsToAddOrUpdateLocally.push(remoteContact);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// SCENARIO 4 & 6: Contact exists on both sides - check for conflicts
|
|
96
|
+
const hasContentDifference = localContact.name !== remoteContact.name ||
|
|
97
|
+
localContact.memo !== remoteContact.memo;
|
|
98
|
+
if (hasContentDifference) {
|
|
99
|
+
// Check timestamps to determine which version to keep
|
|
100
|
+
const localTimestamp = localContact.lastUpdatedAt || 0;
|
|
101
|
+
const remoteTimestamp = remoteContact.lastUpdatedAt || 0;
|
|
102
|
+
if (localTimestamp >= remoteTimestamp) {
|
|
103
|
+
// Local is newer (or same age) - use local version
|
|
104
|
+
contactsToUpdateRemotely.push(localContact);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// Remote is newer - use remote version
|
|
108
|
+
contactsToAddOrUpdateLocally.push(remoteContact);
|
|
109
|
+
}
|
|
103
110
|
}
|
|
111
|
+
// Else: content is identical, no action needed
|
|
104
112
|
}
|
|
105
|
-
// Else: content is identical, no action needed
|
|
106
113
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
// SCENARIO 1, 3 & 5: Process local contacts not in remote - handles first sync and new local contacts
|
|
115
|
+
for (const localContact of localVisibleContacts) {
|
|
116
|
+
const key = createContactKey(localContact);
|
|
117
|
+
const remoteContact = remoteContactsMap.get(key);
|
|
118
|
+
if (!remoteContact) {
|
|
119
|
+
// New local contact or first sync - add to remote
|
|
120
|
+
contactsToUpdateRemotely.push(localContact);
|
|
121
|
+
}
|
|
115
122
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
123
|
+
// Apply local deletions
|
|
124
|
+
// Note: Individual errors are intentionally NOT caught here to ensure they reach Sentry
|
|
125
|
+
// for debugging. Previous versions silently suppressed these errors which made
|
|
126
|
+
// troubleshooting contact sync issues difficult.
|
|
127
|
+
for (const contact of contactsToDeleteLocally) {
|
|
120
128
|
getMessenger().call('AddressBookController:delete', contact.chainId, contact.address);
|
|
121
129
|
if (onContactDeleted) {
|
|
122
130
|
onContactDeleted();
|
|
123
131
|
}
|
|
124
132
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (!contact.deletedAt) {
|
|
132
|
-
try {
|
|
133
|
+
// Apply local additions/updates
|
|
134
|
+
// Note: Individual errors are intentionally NOT caught here to ensure they reach Sentry
|
|
135
|
+
// for debugging. Previous versions silently suppressed these errors which made
|
|
136
|
+
// troubleshooting contact sync issues difficult.
|
|
137
|
+
for (const contact of contactsToAddOrUpdateLocally) {
|
|
138
|
+
if (!contact.deletedAt) {
|
|
133
139
|
getMessenger().call('AddressBookController:set', contact.address, contact.name || '', contact.chainId, contact.memo || '', contact.addressType);
|
|
134
140
|
if (onContactUpdated) {
|
|
135
141
|
onContactUpdated();
|
|
136
142
|
}
|
|
137
143
|
}
|
|
138
|
-
|
|
139
|
-
|
|
144
|
+
}
|
|
145
|
+
// Apply changes to remote storage
|
|
146
|
+
if (contactsToUpdateRemotely.length > 0) {
|
|
147
|
+
const updatedRemoteContacts = {};
|
|
148
|
+
for (const localContact of contactsToUpdateRemotely) {
|
|
149
|
+
const key = createContactKey(localContact);
|
|
150
|
+
updatedRemoteContacts[key] = {
|
|
151
|
+
...remoteContactsMap.get(key),
|
|
152
|
+
...localContact,
|
|
153
|
+
lastUpdatedAt: Date.now(), // mark as updated
|
|
154
|
+
};
|
|
140
155
|
}
|
|
156
|
+
// Save updated contacts to remote storage
|
|
157
|
+
await saveContactsToUserStorage(Object.values(updatedRemoteContacts), options);
|
|
141
158
|
}
|
|
142
159
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
...localContact,
|
|
151
|
-
lastUpdatedAt: Date.now(), // mark as updated
|
|
152
|
-
};
|
|
160
|
+
catch (error) {
|
|
161
|
+
if (onContactSyncErroneousSituation) {
|
|
162
|
+
onContactSyncErroneousSituation('Error synchronizing contacts', {
|
|
163
|
+
error,
|
|
164
|
+
});
|
|
165
|
+
// Re-throw the error to be handled by the caller
|
|
166
|
+
throw error;
|
|
153
167
|
}
|
|
154
|
-
// Save updated contacts to remote storage
|
|
155
|
-
await saveContactsToUserStorage(Object.values(updatedRemoteContacts), options);
|
|
156
168
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (onContactSyncErroneousSituation) {
|
|
160
|
-
onContactSyncErroneousSituation('Error synchronizing contacts', {
|
|
161
|
-
error,
|
|
162
|
-
});
|
|
163
|
-
// Re-throw the error to be handled by the caller
|
|
164
|
-
throw error;
|
|
169
|
+
finally {
|
|
170
|
+
await getUserStorageControllerInstance().setIsContactSyncingInProgress(false);
|
|
165
171
|
}
|
|
172
|
+
};
|
|
173
|
+
if (trace) {
|
|
174
|
+
// Gather pre-sync metrics for performance analysis
|
|
175
|
+
const initialLocalContacts = localVisibleContacts;
|
|
176
|
+
const initialValidRemoteContacts = validRemoteContacts;
|
|
177
|
+
await trace({
|
|
178
|
+
name: constants_1.TraceName.ContactSyncFull,
|
|
179
|
+
data: {
|
|
180
|
+
localContactCount: initialLocalContacts.length,
|
|
181
|
+
remoteContactCount: initialValidRemoteContacts.length,
|
|
182
|
+
isFirstSync: initialValidRemoteContacts.length === 0 &&
|
|
183
|
+
initialLocalContacts.length > 0,
|
|
184
|
+
isNewDeviceSync: initialLocalContacts.length === 0 &&
|
|
185
|
+
initialValidRemoteContacts.length > 0,
|
|
186
|
+
isRegularSync: initialLocalContacts.length > 0 &&
|
|
187
|
+
initialValidRemoteContacts.length > 0,
|
|
188
|
+
hasDataToSync: initialLocalContacts.length > 0 ||
|
|
189
|
+
initialValidRemoteContacts.length > 0,
|
|
190
|
+
expectedWorkload: initialLocalContacts.length + initialValidRemoteContacts.length,
|
|
191
|
+
},
|
|
192
|
+
}, performSync);
|
|
193
|
+
return;
|
|
166
194
|
}
|
|
167
|
-
|
|
168
|
-
await getUserStorageControllerInstance().setIsContactSyncingInProgress(false);
|
|
169
|
-
}
|
|
195
|
+
await performSync();
|
|
170
196
|
}
|
|
171
197
|
exports.syncContactsWithUserStorage = syncContactsWithUserStorage;
|
|
172
198
|
/**
|
|
@@ -198,19 +224,34 @@ async function getRemoteContacts(options) {
|
|
|
198
224
|
*
|
|
199
225
|
* @param contacts - The contacts to save to user storage
|
|
200
226
|
* @param options - Parameters used for saving contacts
|
|
227
|
+
* @returns Promise that resolves when contacts are saved
|
|
201
228
|
*/
|
|
202
229
|
async function saveContactsToUserStorage(contacts, options) {
|
|
203
|
-
const { getUserStorageControllerInstance } = options;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
230
|
+
const { getUserStorageControllerInstance, trace } = options;
|
|
231
|
+
const saveContacts = async () => {
|
|
232
|
+
if (!contacts || contacts.length === 0) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
// Convert each AddressBookEntry to UserStorageContactEntry format and create key-value pairs
|
|
236
|
+
const storageEntries = contacts.map((contact) => {
|
|
237
|
+
const key = createContactKey(contact);
|
|
238
|
+
const storageEntry = (0, utils_1.mapAddressBookEntryToUserStorageEntry)(contact);
|
|
239
|
+
return [key, JSON.stringify(storageEntry)];
|
|
240
|
+
});
|
|
241
|
+
await getUserStorageControllerInstance().performBatchSetStorage(storage_schema_1.USER_STORAGE_FEATURE_NAMES.addressBook, storageEntries);
|
|
242
|
+
};
|
|
243
|
+
return trace
|
|
244
|
+
? await trace({
|
|
245
|
+
name: constants_1.TraceName.ContactSyncSaveBatch,
|
|
246
|
+
data: {
|
|
247
|
+
contactCount: contacts.length,
|
|
248
|
+
// Performance scaling indicators
|
|
249
|
+
hasBatchOperations: contacts.length > 1,
|
|
250
|
+
chainCount: new Set(contacts.map((c) => c.chainId)).size,
|
|
251
|
+
hasMemosCount: contacts.filter((c) => c.memo?.length).length,
|
|
252
|
+
},
|
|
253
|
+
}, saveContacts)
|
|
254
|
+
: await saveContacts();
|
|
214
255
|
}
|
|
215
256
|
/**
|
|
216
257
|
* Updates a single contact in remote storage without performing a full sync
|
|
@@ -218,24 +259,41 @@ async function saveContactsToUserStorage(contacts, options) {
|
|
|
218
259
|
*
|
|
219
260
|
* @param contact - The contact that was updated locally
|
|
220
261
|
* @param options - Parameters used for syncing operations
|
|
262
|
+
* @returns Promise that resolves when the contact is updated
|
|
221
263
|
*/
|
|
222
264
|
async function updateContactInRemoteStorage(contact, options) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
!
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
265
|
+
const { trace } = options;
|
|
266
|
+
const updateContact = async () => {
|
|
267
|
+
if (!(0, sync_utils_1.canPerformContactSyncing)(options) ||
|
|
268
|
+
!contact.address ||
|
|
269
|
+
!contact.chainId ||
|
|
270
|
+
!contact.name?.trim()) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
const { getUserStorageControllerInstance } = options;
|
|
274
|
+
// Create an updated entry with timestamp
|
|
275
|
+
const updatedEntry = {
|
|
276
|
+
...contact,
|
|
277
|
+
lastUpdatedAt: contact.lastUpdatedAt || Date.now(),
|
|
278
|
+
};
|
|
279
|
+
const key = createContactKey(contact);
|
|
280
|
+
const storageEntry = (0, utils_1.mapAddressBookEntryToUserStorageEntry)(updatedEntry);
|
|
281
|
+
// Save individual contact to remote storage
|
|
282
|
+
await getUserStorageControllerInstance().performSetStorage(`${storage_schema_1.USER_STORAGE_FEATURE_NAMES.addressBook}.${key}`, JSON.stringify(storageEntry));
|
|
234
283
|
};
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
284
|
+
if (trace) {
|
|
285
|
+
return await trace({
|
|
286
|
+
name: constants_1.TraceName.ContactSyncUpdateRemote,
|
|
287
|
+
data: {
|
|
288
|
+
chainId: contact.chainId,
|
|
289
|
+
// Performance indicators
|
|
290
|
+
hasTimestamp: Boolean(contact.lastUpdatedAt),
|
|
291
|
+
hasMemo: Boolean(contact.memo?.length),
|
|
292
|
+
isUpdate: Boolean(contact.lastUpdatedAt), // vs new contact
|
|
293
|
+
},
|
|
294
|
+
}, updateContact);
|
|
295
|
+
}
|
|
296
|
+
return await updateContact();
|
|
239
297
|
}
|
|
240
298
|
exports.updateContactInRemoteStorage = updateContactInRemoteStorage;
|
|
241
299
|
/**
|
|
@@ -244,38 +302,45 @@ exports.updateContactInRemoteStorage = updateContactInRemoteStorage;
|
|
|
244
302
|
*
|
|
245
303
|
* @param contact - The contact that was deleted locally (contains at least address and chainId)
|
|
246
304
|
* @param options - Parameters used for syncing operations
|
|
305
|
+
* @returns Promise that resolves when the contact is marked as deleted
|
|
247
306
|
*/
|
|
248
307
|
async function deleteContactInRemoteStorage(contact, options) {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
!
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const key = createContactKey(contact);
|
|
257
|
-
try {
|
|
258
|
-
// Try to get the existing contact first
|
|
259
|
-
const existingContactJson = await getUserStorageControllerInstance().performGetStorage(`${storage_schema_1.USER_STORAGE_FEATURE_NAMES.addressBook}.${key}`);
|
|
260
|
-
if (existingContactJson) {
|
|
261
|
-
// Mark the existing contact as deleted
|
|
262
|
-
const existingStorageEntry = JSON.parse(existingContactJson);
|
|
263
|
-
const existingContact = (0, utils_1.mapUserStorageEntryToAddressBookEntry)(existingStorageEntry);
|
|
264
|
-
const now = Date.now();
|
|
265
|
-
const deletedContact = {
|
|
266
|
-
...existingContact,
|
|
267
|
-
deletedAt: now,
|
|
268
|
-
lastUpdatedAt: now,
|
|
269
|
-
};
|
|
270
|
-
const deletedStorageEntry = (0, utils_1.mapAddressBookEntryToUserStorageEntry)(deletedContact);
|
|
271
|
-
// Save the deleted contact back to storage
|
|
272
|
-
await getUserStorageControllerInstance().performSetStorage(`${storage_schema_1.USER_STORAGE_FEATURE_NAMES.addressBook}.${key}`, JSON.stringify(deletedStorageEntry));
|
|
308
|
+
const { trace } = options;
|
|
309
|
+
const deleteContact = async () => {
|
|
310
|
+
if (!(0, sync_utils_1.canPerformContactSyncing)(options) ||
|
|
311
|
+
!contact.address ||
|
|
312
|
+
!contact.chainId ||
|
|
313
|
+
!contact.name?.trim()) {
|
|
314
|
+
return;
|
|
273
315
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
316
|
+
const { getUserStorageControllerInstance } = options;
|
|
317
|
+
const key = createContactKey(contact);
|
|
318
|
+
try {
|
|
319
|
+
// Try to get the existing contact first
|
|
320
|
+
const existingContactJson = await getUserStorageControllerInstance().performGetStorage(`${storage_schema_1.USER_STORAGE_FEATURE_NAMES.addressBook}.${key}`);
|
|
321
|
+
if (existingContactJson) {
|
|
322
|
+
// Mark the existing contact as deleted
|
|
323
|
+
const existingStorageEntry = JSON.parse(existingContactJson);
|
|
324
|
+
const existingContact = (0, utils_1.mapUserStorageEntryToAddressBookEntry)(existingStorageEntry);
|
|
325
|
+
const now = Date.now();
|
|
326
|
+
const deletedContact = {
|
|
327
|
+
...existingContact,
|
|
328
|
+
deletedAt: now,
|
|
329
|
+
lastUpdatedAt: now,
|
|
330
|
+
};
|
|
331
|
+
const deletedStorageEntry = (0, utils_1.mapAddressBookEntryToUserStorageEntry)(deletedContact);
|
|
332
|
+
// Save the deleted contact back to storage
|
|
333
|
+
await getUserStorageControllerInstance().performSetStorage(`${storage_schema_1.USER_STORAGE_FEATURE_NAMES.addressBook}.${key}`, JSON.stringify(deletedStorageEntry));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
catch {
|
|
337
|
+
// If contact doesn't exist in remote storage, no need to mark as deleted
|
|
338
|
+
console.warn('Contact not found in remote storage for deletion:', key);
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
return trace
|
|
342
|
+
? await trace({ name: constants_1.TraceName.ContactSyncDeleteRemote }, deleteContact)
|
|
343
|
+
: await deleteContact();
|
|
279
344
|
}
|
|
280
345
|
exports.deleteContactInRemoteStorage = deleteContactInRemoteStorage;
|
|
281
346
|
//# sourceMappingURL=controller-integration.cjs.map
|