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