|  |  | @ -26,12 +26,11 @@ import "dexie-export-import"; | 
			
		
	
		
			
				
					|  |  |  | import { PlatformServiceFactory } from "./PlatformServiceFactory"; | 
			
		
	
		
			
				
					|  |  |  | import { db, accountsDBPromise } from "../db/index"; | 
			
		
	
		
			
				
					|  |  |  | import { Contact, ContactMethod } from "../db/tables/contacts"; | 
			
		
	
		
			
				
					|  |  |  | import { Settings, MASTER_SETTINGS_KEY, SettingsWithJsonStrings, BoundingBox } from "../db/tables/settings"; | 
			
		
	
		
			
				
					|  |  |  | import { Account, AccountEncrypted } from "../db/tables/accounts"; | 
			
		
	
		
			
				
					|  |  |  | import { Settings, MASTER_SETTINGS_KEY, BoundingBox } from "../db/tables/settings"; | 
			
		
	
		
			
				
					|  |  |  | import { Account } from "../db/tables/accounts"; | 
			
		
	
		
			
				
					|  |  |  | import { logger } from "../utils/logger"; | 
			
		
	
		
			
				
					|  |  |  | import { mapColumnsToValues, parseJsonField } from "../db/databaseUtil"; | 
			
		
	
		
			
				
					|  |  |  | import { mapColumnsToValues, parseJsonField, generateUpdateStatement, generateInsertStatement } from "../db/databaseUtil"; | 
			
		
	
		
			
				
					|  |  |  | import { importFromMnemonic } from "../libs/util"; | 
			
		
	
		
			
				
					|  |  |  | import { IIdentifier } from "@veramo/core"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  * Interface for data comparison results between Dexie and SQLite databases | 
			
		
	
	
		
			
				
					|  |  | @ -1028,228 +1027,47 @@ export async function migrateSettings( | 
			
		
	
		
			
				
					|  |  |  |   try { | 
			
		
	
		
			
				
					|  |  |  |     const dexieSettings = await getDexieSettings(); | 
			
		
	
		
			
				
					|  |  |  |     const platformService = PlatformServiceFactory.getInstance(); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // Group settings by DID to handle duplicates
 | 
			
		
	
		
			
				
					|  |  |  |     const settingsByDid = new Map<string, { | 
			
		
	
		
			
				
					|  |  |  |       master?: Settings; | 
			
		
	
		
			
				
					|  |  |  |       account?: Settings; | 
			
		
	
		
			
				
					|  |  |  |     }>(); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // Organize settings by DID
 | 
			
		
	
		
			
				
					|  |  |  |     dexieSettings.forEach(setting => { | 
			
		
	
		
			
				
					|  |  |  |       const isMasterSetting = setting.id === MASTER_SETTINGS_KEY; | 
			
		
	
		
			
				
					|  |  |  |       const did = isMasterSetting ? setting.activeDid : setting.accountDid; | 
			
		
	
		
			
				
					|  |  |  |        | 
			
		
	
		
			
				
					|  |  |  |       if (!did) { | 
			
		
	
		
			
				
					|  |  |  |         result.warnings.push(`Setting ${setting.id} has no DID, skipping`); | 
			
		
	
		
			
				
					|  |  |  |         return; | 
			
		
	
		
			
				
					|  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |       if (!settingsByDid.has(did)) { | 
			
		
	
		
			
				
					|  |  |  |         settingsByDid.set(did, {}); | 
			
		
	
		
			
				
					|  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |       const didSettings = settingsByDid.get(did)!; | 
			
		
	
		
			
				
					|  |  |  |       if (isMasterSetting) { | 
			
		
	
		
			
				
					|  |  |  |         didSettings.master = setting; | 
			
		
	
		
			
				
					|  |  |  |         logger.info("[MigrationService] Found master settings", {  | 
			
		
	
		
			
				
					|  |  |  |           did, | 
			
		
	
		
			
				
					|  |  |  |           id: setting.id, | 
			
		
	
		
			
				
					|  |  |  |           firstName: setting.firstName, | 
			
		
	
		
			
				
					|  |  |  |           isRegistered: setting.isRegistered, | 
			
		
	
		
			
				
					|  |  |  |           profileImageUrl: setting.profileImageUrl, | 
			
		
	
		
			
				
					|  |  |  |           showShortcutBvc: setting.showShortcutBvc, | 
			
		
	
		
			
				
					|  |  |  |           searchBoxes: setting.searchBoxes | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  |     // loop through dexieSettings,
 | 
			
		
	
		
			
				
					|  |  |  |     // load the one with the matching accountDid from sqlite,
 | 
			
		
	
		
			
				
					|  |  |  |     // and if one doesn't exist then insert it,
 | 
			
		
	
		
			
				
					|  |  |  |     // otherwise, update the fields
 | 
			
		
	
		
			
				
					|  |  |  |     dexieSettings.forEach(async (setting) => { | 
			
		
	
		
			
				
					|  |  |  |       const sqliteSettingRaw = await platformService.dbQuery( | 
			
		
	
		
			
				
					|  |  |  |         "SELECT * FROM settings WHERE accountDid = ?", | 
			
		
	
		
			
				
					|  |  |  |         [setting.accountDid] | 
			
		
	
		
			
				
					|  |  |  |       ); | 
			
		
	
		
			
				
					|  |  |  |       if (sqliteSettingRaw?.values?.length) { | 
			
		
	
		
			
				
					|  |  |  |         // should cover the master settings, were accountDid is null
 | 
			
		
	
		
			
				
					|  |  |  |         const sqliteSetting = mapColumnsToValues(sqliteSettingRaw.columns, sqliteSettingRaw.values) as unknown as Settings; | 
			
		
	
		
			
				
					|  |  |  |         let conditional: string; | 
			
		
	
		
			
				
					|  |  |  |         let preparams: unknown[]; | 
			
		
	
		
			
				
					|  |  |  |         if (!setting.accountDid) { | 
			
		
	
		
			
				
					|  |  |  |           conditional = "accountDid is null"; | 
			
		
	
		
			
				
					|  |  |  |           preparams = []; | 
			
		
	
		
			
				
					|  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |           conditional = "accountDid = ?"; | 
			
		
	
		
			
				
					|  |  |  |           preparams = [setting.accountDid]; | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |         const { sql, params } = generateUpdateStatement( | 
			
		
	
		
			
				
					|  |  |  |           sqliteSetting as unknown as Record<string, unknown>, | 
			
		
	
		
			
				
					|  |  |  |           "settings", | 
			
		
	
		
			
				
					|  |  |  |           conditional, | 
			
		
	
		
			
				
					|  |  |  |           preparams | 
			
		
	
		
			
				
					|  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |         await platformService.dbExec(sql, params); | 
			
		
	
		
			
				
					|  |  |  |         result.settingsMigrated++; | 
			
		
	
		
			
				
					|  |  |  |       } else { | 
			
		
	
		
			
				
					|  |  |  |         didSettings.account = setting; | 
			
		
	
		
			
				
					|  |  |  |         logger.info("[MigrationService] Found account settings", {  | 
			
		
	
		
			
				
					|  |  |  |           did, | 
			
		
	
		
			
				
					|  |  |  |           id: setting.id, | 
			
		
	
		
			
				
					|  |  |  |           firstName: setting.firstName, | 
			
		
	
		
			
				
					|  |  |  |           isRegistered: setting.isRegistered, | 
			
		
	
		
			
				
					|  |  |  |           profileImageUrl: setting.profileImageUrl, | 
			
		
	
		
			
				
					|  |  |  |           showShortcutBvc: setting.showShortcutBvc, | 
			
		
	
		
			
				
					|  |  |  |           searchBoxes: setting.searchBoxes | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  |         // insert new setting
 | 
			
		
	
		
			
				
					|  |  |  |         delete setting.activeDid; // ensure we don't set the activeDid (since master settings are an update and don't hit this case)
 | 
			
		
	
		
			
				
					|  |  |  |         const { sql, params } = generateInsertStatement( | 
			
		
	
		
			
				
					|  |  |  |           setting as unknown as Record<string, unknown>, | 
			
		
	
		
			
				
					|  |  |  |           "settings" | 
			
		
	
		
			
				
					|  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |         await platformService.dbExec(sql, params); | 
			
		
	
		
			
				
					|  |  |  |         result.settingsMigrated++; | 
			
		
	
		
			
				
					|  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |     }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // Process each unique DID's settings
 | 
			
		
	
		
			
				
					|  |  |  |     for (const [did, didSettings] of settingsByDid.entries()) { | 
			
		
	
		
			
				
					|  |  |  |       try { | 
			
		
	
		
			
				
					|  |  |  |         // Process master settings
 | 
			
		
	
		
			
				
					|  |  |  |         if (didSettings.master) { | 
			
		
	
		
			
				
					|  |  |  |           const masterData = { | 
			
		
	
		
			
				
					|  |  |  |             id: MASTER_SETTINGS_KEY, | 
			
		
	
		
			
				
					|  |  |  |             activeDid: did, | 
			
		
	
		
			
				
					|  |  |  |             accountDid: "", // Empty for master settings
 | 
			
		
	
		
			
				
					|  |  |  |             apiServer: didSettings.master.apiServer || "", | 
			
		
	
		
			
				
					|  |  |  |             filterFeedByNearby: didSettings.master.filterFeedByNearby || false, | 
			
		
	
		
			
				
					|  |  |  |             filterFeedByVisible: didSettings.master.filterFeedByVisible || false, | 
			
		
	
		
			
				
					|  |  |  |             finishedOnboarding: didSettings.master.finishedOnboarding || false, | 
			
		
	
		
			
				
					|  |  |  |             firstName: didSettings.master.firstName || "", | 
			
		
	
		
			
				
					|  |  |  |             hideRegisterPromptOnNewContact: didSettings.master.hideRegisterPromptOnNewContact || false, | 
			
		
	
		
			
				
					|  |  |  |             isRegistered: didSettings.master.isRegistered || false, | 
			
		
	
		
			
				
					|  |  |  |             lastName: didSettings.master.lastName || "", | 
			
		
	
		
			
				
					|  |  |  |             profileImageUrl: didSettings.master.profileImageUrl || "", | 
			
		
	
		
			
				
					|  |  |  |             searchBoxes: didSettings.master.searchBoxes || [], | 
			
		
	
		
			
				
					|  |  |  |             showShortcutBvc: didSettings.master.showShortcutBvc || false | 
			
		
	
		
			
				
					|  |  |  |           }; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |           // Check if master setting exists
 | 
			
		
	
		
			
				
					|  |  |  |           const existingMaster = await platformService.dbQuery( | 
			
		
	
		
			
				
					|  |  |  |             "SELECT id FROM settings WHERE id = ? AND activeDid = ? AND accountDid = ''", | 
			
		
	
		
			
				
					|  |  |  |             [MASTER_SETTINGS_KEY, did] | 
			
		
	
		
			
				
					|  |  |  |           ); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |           if (existingMaster?.values?.length) { | 
			
		
	
		
			
				
					|  |  |  |             logger.info("[MigrationService] Updating master settings", { did, masterData }); | 
			
		
	
		
			
				
					|  |  |  |             await platformService.dbQuery( | 
			
		
	
		
			
				
					|  |  |  |               `UPDATE settings SET 
 | 
			
		
	
		
			
				
					|  |  |  |                 activeDid = ?, | 
			
		
	
		
			
				
					|  |  |  |                 accountDid = ?, | 
			
		
	
		
			
				
					|  |  |  |                 firstName = ?, | 
			
		
	
		
			
				
					|  |  |  |                 isRegistered = ?, | 
			
		
	
		
			
				
					|  |  |  |                 profileImageUrl = ?, | 
			
		
	
		
			
				
					|  |  |  |                 showShortcutBvc = ?, | 
			
		
	
		
			
				
					|  |  |  |                 searchBoxes = ? | 
			
		
	
		
			
				
					|  |  |  |               WHERE id = ?`,
 | 
			
		
	
		
			
				
					|  |  |  |               [ | 
			
		
	
		
			
				
					|  |  |  |                 masterData.activeDid, | 
			
		
	
		
			
				
					|  |  |  |                 masterData.accountDid, | 
			
		
	
		
			
				
					|  |  |  |                 masterData.firstName, | 
			
		
	
		
			
				
					|  |  |  |                 masterData.isRegistered, | 
			
		
	
		
			
				
					|  |  |  |                 masterData.profileImageUrl, | 
			
		
	
		
			
				
					|  |  |  |                 masterData.showShortcutBvc, | 
			
		
	
		
			
				
					|  |  |  |                 JSON.stringify(masterData.searchBoxes), | 
			
		
	
		
			
				
					|  |  |  |                 MASTER_SETTINGS_KEY | 
			
		
	
		
			
				
					|  |  |  |               ] | 
			
		
	
		
			
				
					|  |  |  |             ); | 
			
		
	
		
			
				
					|  |  |  |           } else { | 
			
		
	
		
			
				
					|  |  |  |             logger.info("[MigrationService] Inserting master settings", { did, masterData }); | 
			
		
	
		
			
				
					|  |  |  |             await platformService.dbQuery( | 
			
		
	
		
			
				
					|  |  |  |               `INSERT INTO settings (
 | 
			
		
	
		
			
				
					|  |  |  |                 id, | 
			
		
	
		
			
				
					|  |  |  |                 activeDid, | 
			
		
	
		
			
				
					|  |  |  |                 accountDid, | 
			
		
	
		
			
				
					|  |  |  |                 firstName, | 
			
		
	
		
			
				
					|  |  |  |                 isRegistered, | 
			
		
	
		
			
				
					|  |  |  |                 profileImageUrl, | 
			
		
	
		
			
				
					|  |  |  |                 showShortcutBvc, | 
			
		
	
		
			
				
					|  |  |  |                 searchBoxes | 
			
		
	
		
			
				
					|  |  |  |               ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
 | 
			
		
	
		
			
				
					|  |  |  |               [ | 
			
		
	
		
			
				
					|  |  |  |                 MASTER_SETTINGS_KEY, | 
			
		
	
		
			
				
					|  |  |  |                 masterData.activeDid, | 
			
		
	
		
			
				
					|  |  |  |                 masterData.accountDid, | 
			
		
	
		
			
				
					|  |  |  |                 masterData.firstName, | 
			
		
	
		
			
				
					|  |  |  |                 masterData.isRegistered, | 
			
		
	
		
			
				
					|  |  |  |                 masterData.profileImageUrl, | 
			
		
	
		
			
				
					|  |  |  |                 masterData.showShortcutBvc, | 
			
		
	
		
			
				
					|  |  |  |                 JSON.stringify(masterData.searchBoxes) | 
			
		
	
		
			
				
					|  |  |  |               ] | 
			
		
	
		
			
				
					|  |  |  |             ); | 
			
		
	
		
			
				
					|  |  |  |           } | 
			
		
	
		
			
				
					|  |  |  |           result.settingsMigrated++; | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         // Process account settings
 | 
			
		
	
		
			
				
					|  |  |  |         if (didSettings.account) { | 
			
		
	
		
			
				
					|  |  |  |           const accountData = { | 
			
		
	
		
			
				
					|  |  |  |             id: 2, // Account settings always use id 2
 | 
			
		
	
		
			
				
					|  |  |  |             activeDid: "", // Empty for account settings
 | 
			
		
	
		
			
				
					|  |  |  |             accountDid: did, | 
			
		
	
		
			
				
					|  |  |  |             apiServer: didSettings.account.apiServer || "", | 
			
		
	
		
			
				
					|  |  |  |             filterFeedByNearby: didSettings.account.filterFeedByNearby || false, | 
			
		
	
		
			
				
					|  |  |  |             filterFeedByVisible: didSettings.account.filterFeedByVisible || false, | 
			
		
	
		
			
				
					|  |  |  |             finishedOnboarding: didSettings.account.finishedOnboarding || false, | 
			
		
	
		
			
				
					|  |  |  |             firstName: didSettings.account.firstName || "", | 
			
		
	
		
			
				
					|  |  |  |             hideRegisterPromptOnNewContact: didSettings.account.hideRegisterPromptOnNewContact || false, | 
			
		
	
		
			
				
					|  |  |  |             isRegistered: didSettings.account.isRegistered || false, | 
			
		
	
		
			
				
					|  |  |  |             lastName: didSettings.account.lastName || "", | 
			
		
	
		
			
				
					|  |  |  |             profileImageUrl: didSettings.account.profileImageUrl || "", | 
			
		
	
		
			
				
					|  |  |  |             searchBoxes: didSettings.account.searchBoxes || [], | 
			
		
	
		
			
				
					|  |  |  |             showShortcutBvc: didSettings.account.showShortcutBvc || false | 
			
		
	
		
			
				
					|  |  |  |           }; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |           // Check if account setting exists
 | 
			
		
	
		
			
				
					|  |  |  |           const existingAccount = await platformService.dbQuery( | 
			
		
	
		
			
				
					|  |  |  |             "SELECT id FROM settings WHERE id = ? AND accountDid = ? AND activeDid = ''", | 
			
		
	
		
			
				
					|  |  |  |             [2, did] | 
			
		
	
		
			
				
					|  |  |  |           ); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |           if (existingAccount?.values?.length) { | 
			
		
	
		
			
				
					|  |  |  |             logger.info("[MigrationService] Updating account settings", { did, accountData }); | 
			
		
	
		
			
				
					|  |  |  |             await platformService.dbQuery( | 
			
		
	
		
			
				
					|  |  |  |               `UPDATE settings SET 
 | 
			
		
	
		
			
				
					|  |  |  |                 activeDid = ?, | 
			
		
	
		
			
				
					|  |  |  |                 accountDid = ?, | 
			
		
	
		
			
				
					|  |  |  |                 firstName = ?, | 
			
		
	
		
			
				
					|  |  |  |                 isRegistered = ?, | 
			
		
	
		
			
				
					|  |  |  |                 profileImageUrl = ?, | 
			
		
	
		
			
				
					|  |  |  |                 showShortcutBvc = ?, | 
			
		
	
		
			
				
					|  |  |  |                 searchBoxes = ? | 
			
		
	
		
			
				
					|  |  |  |               WHERE id = ?`,
 | 
			
		
	
		
			
				
					|  |  |  |               [ | 
			
		
	
		
			
				
					|  |  |  |                 accountData.activeDid, | 
			
		
	
		
			
				
					|  |  |  |                 accountData.accountDid, | 
			
		
	
		
			
				
					|  |  |  |                 accountData.firstName, | 
			
		
	
		
			
				
					|  |  |  |                 accountData.isRegistered, | 
			
		
	
		
			
				
					|  |  |  |                 accountData.profileImageUrl, | 
			
		
	
		
			
				
					|  |  |  |                 accountData.showShortcutBvc, | 
			
		
	
		
			
				
					|  |  |  |                 JSON.stringify(accountData.searchBoxes), | 
			
		
	
		
			
				
					|  |  |  |                 2 | 
			
		
	
		
			
				
					|  |  |  |               ] | 
			
		
	
		
			
				
					|  |  |  |             ); | 
			
		
	
		
			
				
					|  |  |  |           } else { | 
			
		
	
		
			
				
					|  |  |  |             logger.info("[MigrationService] Inserting account settings", { did, accountData }); | 
			
		
	
		
			
				
					|  |  |  |             await platformService.dbQuery( | 
			
		
	
		
			
				
					|  |  |  |               `INSERT INTO settings (
 | 
			
		
	
		
			
				
					|  |  |  |                 id, | 
			
		
	
		
			
				
					|  |  |  |                 activeDid, | 
			
		
	
		
			
				
					|  |  |  |                 accountDid, | 
			
		
	
		
			
				
					|  |  |  |                 firstName, | 
			
		
	
		
			
				
					|  |  |  |                 isRegistered, | 
			
		
	
		
			
				
					|  |  |  |                 profileImageUrl, | 
			
		
	
		
			
				
					|  |  |  |                 showShortcutBvc, | 
			
		
	
		
			
				
					|  |  |  |                 searchBoxes | 
			
		
	
		
			
				
					|  |  |  |               ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
 | 
			
		
	
		
			
				
					|  |  |  |               [ | 
			
		
	
		
			
				
					|  |  |  |                 2, | 
			
		
	
		
			
				
					|  |  |  |                 accountData.activeDid, | 
			
		
	
		
			
				
					|  |  |  |                 accountData.accountDid, | 
			
		
	
		
			
				
					|  |  |  |                 accountData.firstName, | 
			
		
	
		
			
				
					|  |  |  |                 accountData.isRegistered, | 
			
		
	
		
			
				
					|  |  |  |                 accountData.profileImageUrl, | 
			
		
	
		
			
				
					|  |  |  |                 accountData.showShortcutBvc, | 
			
		
	
		
			
				
					|  |  |  |                 JSON.stringify(accountData.searchBoxes) | 
			
		
	
		
			
				
					|  |  |  |               ] | 
			
		
	
		
			
				
					|  |  |  |             ); | 
			
		
	
		
			
				
					|  |  |  |           } | 
			
		
	
		
			
				
					|  |  |  |           result.settingsMigrated++; | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         logger.info("[MigrationService] Successfully migrated settings for DID", { | 
			
		
	
		
			
				
					|  |  |  |           did, | 
			
		
	
		
			
				
					|  |  |  |           masterMigrated: !!didSettings.master, | 
			
		
	
		
			
				
					|  |  |  |           accountMigrated: !!didSettings.account | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |       } catch (error) { | 
			
		
	
		
			
				
					|  |  |  |         const errorMessage = `Failed to migrate settings for DID ${did}: ${error}`; | 
			
		
	
		
			
				
					|  |  |  |         result.errors.push(errorMessage); | 
			
		
	
		
			
				
					|  |  |  |         logger.error("[MigrationService] Settings migration failed:", { | 
			
		
	
		
			
				
					|  |  |  |           error, | 
			
		
	
		
			
				
					|  |  |  |           did | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     if (result.errors.length > 0) { | 
			
		
	
		
			
				
					|  |  |  |       result.success = false; | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     return result; | 
			
		
	
		
			
				
					|  |  |  |   } catch (error) { | 
			
		
	
		
			
				
					|  |  |  |     const errorMessage = `Settings migration failed: ${error}`; | 
			
		
	
	
		
			
				
					|  |  | @ -1277,7 +1095,6 @@ export async function migrateSettings( | 
			
		
	
		
			
				
					|  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  * @async | 
			
		
	
		
			
				
					|  |  |  |  * @function migrateAccounts | 
			
		
	
		
			
				
					|  |  |  |  * @param {boolean} [overwriteExisting=false] - Whether to overwrite existing accounts in SQLite | 
			
		
	
		
			
				
					|  |  |  |  * @returns {Promise<MigrationResult>} Detailed results of the migration operation | 
			
		
	
		
			
				
					|  |  |  |  * @throws {Error} If the migration process fails completely | 
			
		
	
		
			
				
					|  |  |  |  * @example | 
			
		
	
	
		
			
				
					|  |  | @ -1294,12 +1111,8 @@ export async function migrateSettings( | 
			
		
	
		
			
				
					|  |  |  |  * } | 
			
		
	
		
			
				
					|  |  |  |  * ``` | 
			
		
	
		
			
				
					|  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  | export async function migrateAccounts( | 
			
		
	
		
			
				
					|  |  |  |   overwriteExisting: boolean = false, | 
			
		
	
		
			
				
					|  |  |  | ): Promise<MigrationResult> { | 
			
		
	
		
			
				
					|  |  |  |   logger.info("[MigrationService] Starting account migration", { | 
			
		
	
		
			
				
					|  |  |  |     overwriteExisting, | 
			
		
	
		
			
				
					|  |  |  |   }); | 
			
		
	
		
			
				
					|  |  |  | export async function migrateAccounts(): Promise<MigrationResult> { | 
			
		
	
		
			
				
					|  |  |  |   logger.info("[MigrationService] Starting account migration"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   const result: MigrationResult = { | 
			
		
	
		
			
				
					|  |  |  |     success: true, | 
			
		
	
	
		
			
				
					|  |  | @ -1335,67 +1148,17 @@ export async function migrateAccounts( | 
			
		
	
		
			
				
					|  |  |  |           [did] | 
			
		
	
		
			
				
					|  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         if (existingResult?.values?.length && !overwriteExisting) { | 
			
		
	
		
			
				
					|  |  |  |         if (existingResult?.values?.length) { | 
			
		
	
		
			
				
					|  |  |  |           result.warnings.push(`Account with DID ${did} already exists, skipping`); | 
			
		
	
		
			
				
					|  |  |  |           continue; | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         // Map Dexie fields to SQLite fields
 | 
			
		
	
		
			
				
					|  |  |  |         const accountData = { | 
			
		
	
		
			
				
					|  |  |  |           did: account.did, | 
			
		
	
		
			
				
					|  |  |  |           dateCreated: account.dateCreated, | 
			
		
	
		
			
				
					|  |  |  |           derivationPath: account.derivationPath || "", | 
			
		
	
		
			
				
					|  |  |  |           identityEncrBase64: account.identity || "", | 
			
		
	
		
			
				
					|  |  |  |           mnemonicEncrBase64: account.mnemonic || "", | 
			
		
	
		
			
				
					|  |  |  |           passkeyCredIdHex: account.passkeyCredIdHex || "", | 
			
		
	
		
			
				
					|  |  |  |           publicKeyHex: account.publicKeyHex || "" | 
			
		
	
		
			
				
					|  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         // Insert or update the account
 | 
			
		
	
		
			
				
					|  |  |  |         if (existingResult?.values?.length) { | 
			
		
	
		
			
				
					|  |  |  |           await platformService.dbQuery( | 
			
		
	
		
			
				
					|  |  |  |             `UPDATE accounts SET 
 | 
			
		
	
		
			
				
					|  |  |  |               dateCreated = ?, | 
			
		
	
		
			
				
					|  |  |  |               derivationPath = ?, | 
			
		
	
		
			
				
					|  |  |  |               identityEncrBase64 = ?, | 
			
		
	
		
			
				
					|  |  |  |               mnemonicEncrBase64 = ?, | 
			
		
	
		
			
				
					|  |  |  |               passkeyCredIdHex = ?, | 
			
		
	
		
			
				
					|  |  |  |               publicKeyHex = ? | 
			
		
	
		
			
				
					|  |  |  |             WHERE did = ?`,
 | 
			
		
	
		
			
				
					|  |  |  |             [ | 
			
		
	
		
			
				
					|  |  |  |               accountData.dateCreated, | 
			
		
	
		
			
				
					|  |  |  |               accountData.derivationPath, | 
			
		
	
		
			
				
					|  |  |  |               accountData.identityEncrBase64, | 
			
		
	
		
			
				
					|  |  |  |               accountData.mnemonicEncrBase64, | 
			
		
	
		
			
				
					|  |  |  |               accountData.passkeyCredIdHex, | 
			
		
	
		
			
				
					|  |  |  |               accountData.publicKeyHex, | 
			
		
	
		
			
				
					|  |  |  |               did | 
			
		
	
		
			
				
					|  |  |  |             ] | 
			
		
	
		
			
				
					|  |  |  |           ); | 
			
		
	
		
			
				
					|  |  |  |         if (account.mnemonic) { | 
			
		
	
		
			
				
					|  |  |  |           await importFromMnemonic(account.mnemonic, account.derivationPath); | 
			
		
	
		
			
				
					|  |  |  |           result.accountsMigrated++; | 
			
		
	
		
			
				
					|  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |           await platformService.dbQuery( | 
			
		
	
		
			
				
					|  |  |  |             `INSERT INTO accounts (
 | 
			
		
	
		
			
				
					|  |  |  |               did, | 
			
		
	
		
			
				
					|  |  |  |               dateCreated, | 
			
		
	
		
			
				
					|  |  |  |               derivationPath, | 
			
		
	
		
			
				
					|  |  |  |               identityEncrBase64, | 
			
		
	
		
			
				
					|  |  |  |               mnemonicEncrBase64, | 
			
		
	
		
			
				
					|  |  |  |               passkeyCredIdHex, | 
			
		
	
		
			
				
					|  |  |  |               publicKeyHex | 
			
		
	
		
			
				
					|  |  |  |             ) VALUES (?, ?, ?, ?, ?, ?, ?)`,
 | 
			
		
	
		
			
				
					|  |  |  |             [ | 
			
		
	
		
			
				
					|  |  |  |               did, | 
			
		
	
		
			
				
					|  |  |  |               accountData.dateCreated, | 
			
		
	
		
			
				
					|  |  |  |               accountData.derivationPath, | 
			
		
	
		
			
				
					|  |  |  |               accountData.identityEncrBase64, | 
			
		
	
		
			
				
					|  |  |  |               accountData.mnemonicEncrBase64, | 
			
		
	
		
			
				
					|  |  |  |               accountData.passkeyCredIdHex, | 
			
		
	
		
			
				
					|  |  |  |               accountData.publicKeyHex | 
			
		
	
		
			
				
					|  |  |  |             ] | 
			
		
	
		
			
				
					|  |  |  |           ); | 
			
		
	
		
			
				
					|  |  |  |           result.errors.push(`Account with DID ${did} has no mnemonic, skipping`); | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         result.accountsMigrated++; | 
			
		
	
		
			
				
					|  |  |  |         logger.info("[MigrationService] Successfully migrated account", { | 
			
		
	
		
			
				
					|  |  |  |           did, | 
			
		
	
		
			
				
					|  |  |  |           dateCreated: account.dateCreated | 
			
		
	
	
		
			
				
					|  |  | @ -1424,99 +1187,6 @@ export async function migrateAccounts( | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  * Generates SQL INSERT statement and parameters from a model object | 
			
		
	
		
			
				
					|  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  * This helper function creates a parameterized SQL INSERT statement | 
			
		
	
		
			
				
					|  |  |  |  * from a JavaScript object. It filters out undefined values and | 
			
		
	
		
			
				
					|  |  |  |  * creates the appropriate SQL syntax with placeholders. | 
			
		
	
		
			
				
					|  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  * The function is used internally by the migration functions to | 
			
		
	
		
			
				
					|  |  |  |  * safely insert data into the SQLite database. | 
			
		
	
		
			
				
					|  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  * @function generateInsertStatement | 
			
		
	
		
			
				
					|  |  |  |  * @param {Record<string, unknown>} model - The model object containing fields to insert | 
			
		
	
		
			
				
					|  |  |  |  * @param {string} tableName - The name of the table to insert into | 
			
		
	
		
			
				
					|  |  |  |  * @returns {Object} Object containing the SQL statement and parameters array | 
			
		
	
		
			
				
					|  |  |  |  * @returns {string} returns.sql - The SQL INSERT statement | 
			
		
	
		
			
				
					|  |  |  |  * @returns {unknown[]} returns.params - Array of parameter values | 
			
		
	
		
			
				
					|  |  |  |  * @example | 
			
		
	
		
			
				
					|  |  |  |  * ```typescript
 | 
			
		
	
		
			
				
					|  |  |  |  * const contact = { did: 'did:example:123', name: 'John Doe' }; | 
			
		
	
		
			
				
					|  |  |  |  * const { sql, params } = generateInsertStatement(contact, 'contacts'); | 
			
		
	
		
			
				
					|  |  |  |  * // sql: "INSERT INTO contacts (did, name) VALUES (?, ?)"
 | 
			
		
	
		
			
				
					|  |  |  |  * // params: ['did:example:123', 'John Doe']
 | 
			
		
	
		
			
				
					|  |  |  |  * ``` | 
			
		
	
		
			
				
					|  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  | function generateInsertStatement( | 
			
		
	
		
			
				
					|  |  |  |   model: Record<string, unknown>, | 
			
		
	
		
			
				
					|  |  |  |   tableName: string, | 
			
		
	
		
			
				
					|  |  |  | ): { sql: string; params: unknown[] } { | 
			
		
	
		
			
				
					|  |  |  |   const columns = Object.keys(model).filter((key) => model[key] !== undefined); | 
			
		
	
		
			
				
					|  |  |  |   const values = Object.values(model).filter((value) => value !== undefined); | 
			
		
	
		
			
				
					|  |  |  |   const placeholders = values.map(() => "?").join(", "); | 
			
		
	
		
			
				
					|  |  |  |   const insertSql = `INSERT INTO ${tableName} (${columns.join(", ")}) VALUES (${placeholders})`; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   return { | 
			
		
	
		
			
				
					|  |  |  |     sql: insertSql, | 
			
		
	
		
			
				
					|  |  |  |     params: values, | 
			
		
	
		
			
				
					|  |  |  |   }; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  * Generates SQL UPDATE statement and parameters from a model object | 
			
		
	
		
			
				
					|  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  * This helper function creates a parameterized SQL UPDATE statement | 
			
		
	
		
			
				
					|  |  |  |  * from a JavaScript object. It filters out undefined values and | 
			
		
	
		
			
				
					|  |  |  |  * creates the appropriate SQL syntax with placeholders. | 
			
		
	
		
			
				
					|  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  * The function is used internally by the migration functions to | 
			
		
	
		
			
				
					|  |  |  |  * safely update data in the SQLite database. | 
			
		
	
		
			
				
					|  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  * @function generateUpdateStatement | 
			
		
	
		
			
				
					|  |  |  |  * @param {Record<string, unknown>} model - The model object containing fields to update | 
			
		
	
		
			
				
					|  |  |  |  * @param {string} tableName - The name of the table to update | 
			
		
	
		
			
				
					|  |  |  |  * @param {string} whereClause - The WHERE clause for the update (e.g. "id = ?") | 
			
		
	
		
			
				
					|  |  |  |  * @param {unknown[]} [whereParams=[]] - Parameters for the WHERE clause | 
			
		
	
		
			
				
					|  |  |  |  * @returns {Object} Object containing the SQL statement and parameters array | 
			
		
	
		
			
				
					|  |  |  |  * @returns {string} returns.sql - The SQL UPDATE statement | 
			
		
	
		
			
				
					|  |  |  |  * @returns {unknown[]} returns.params - Array of parameter values | 
			
		
	
		
			
				
					|  |  |  |  * @example | 
			
		
	
		
			
				
					|  |  |  |  * ```typescript
 | 
			
		
	
		
			
				
					|  |  |  |  * const contact = { name: 'Jane Doe' }; | 
			
		
	
		
			
				
					|  |  |  |  * const { sql, params } = generateUpdateStatement(contact, 'contacts', 'did = ?', ['did:example:123']); | 
			
		
	
		
			
				
					|  |  |  |  * // sql: "UPDATE contacts SET name = ? WHERE did = ?"
 | 
			
		
	
		
			
				
					|  |  |  |  * // params: ['Jane Doe', 'did:example:123']
 | 
			
		
	
		
			
				
					|  |  |  |  * ``` | 
			
		
	
		
			
				
					|  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  | function generateUpdateStatement( | 
			
		
	
		
			
				
					|  |  |  |   model: Record<string, unknown>, | 
			
		
	
		
			
				
					|  |  |  |   tableName: string, | 
			
		
	
		
			
				
					|  |  |  |   whereClause: string, | 
			
		
	
		
			
				
					|  |  |  |   whereParams: unknown[] = [], | 
			
		
	
		
			
				
					|  |  |  | ): { sql: string; params: unknown[] } { | 
			
		
	
		
			
				
					|  |  |  |   const setClauses: string[] = []; | 
			
		
	
		
			
				
					|  |  |  |   const params: unknown[] = []; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   Object.entries(model).forEach(([key, value]) => { | 
			
		
	
		
			
				
					|  |  |  |     if (value !== undefined) { | 
			
		
	
		
			
				
					|  |  |  |       setClauses.push(`${key} = ?`); | 
			
		
	
		
			
				
					|  |  |  |       params.push(value); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |   }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   if (setClauses.length === 0) { | 
			
		
	
		
			
				
					|  |  |  |     throw new Error("No valid fields to update"); | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   const sql = `UPDATE ${tableName} SET ${setClauses.join(", ")} WHERE ${whereClause}`; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   return { | 
			
		
	
		
			
				
					|  |  |  |     sql, | 
			
		
	
		
			
				
					|  |  |  |     params: [...params, ...whereParams], | 
			
		
	
		
			
				
					|  |  |  |   }; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  * Migrates all data from Dexie to SQLite in the proper order | 
			
		
	
		
			
				
					|  |  |  |  * | 
			
		
	
	
		
			
				
					|  |  | @ -1551,7 +1221,7 @@ export async function migrateAll( | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // Step 1: Migrate Accounts (foundational)
 | 
			
		
	
		
			
				
					|  |  |  |     logger.info("[MigrationService] Step 1: Migrating accounts..."); | 
			
		
	
		
			
				
					|  |  |  |     const accountsResult = await migrateAccounts(overwriteExisting); | 
			
		
	
		
			
				
					|  |  |  |     const accountsResult = await migrateAccounts(); | 
			
		
	
		
			
				
					|  |  |  |     if (!accountsResult.success) { | 
			
		
	
		
			
				
					|  |  |  |       result.errors.push( | 
			
		
	
		
			
				
					|  |  |  |         `Account migration failed: ${accountsResult.errors.join(", ")}`, | 
			
		
	
	
		
			
				
					|  |  | 
 |