From 69a4252e28a5edffb25c5f6f800cb89341e28cb0 Mon Sep 17 00:00:00 2001 From: Radmir Date: Wed, 18 Feb 2026 17:38:28 +0500 Subject: [PATCH 1/2] Clear wallet preferences plist file on wallet deletion When a wallet is deleted, its WalletPreferences (stored in UserDefaults suite) persisted on disk, causing issues when re-importing the same wallet. The completeInitialAddressStatus flag remained true, skipping the Tron multi-sig address check. - Add unit test --- .../WalletService/WalletService.swift | 3 ++- .../Sources/WalletPreferences.swift | 10 ++++++--- .../Tests/WalletPreferencesTests.swift | 21 +++++++++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Packages/FeatureServices/WalletService/WalletService.swift b/Packages/FeatureServices/WalletService/WalletService.swift index aae19e9e0..27c4d6d97 100644 --- a/Packages/FeatureServices/WalletService/WalletService.swift +++ b/Packages/FeatureServices/WalletService/WalletService.swift @@ -24,7 +24,7 @@ public struct WalletService: Sendable { self.keystore = keystore self.walletStore = walletStore self.avatarService = avatarService - walletSessionService = WalletSessionService(walletStore: walletStore, preferences: preferences) + self.walletSessionService = WalletSessionService(walletStore: walletStore, preferences: preferences) self.preferences = preferences } @@ -103,6 +103,7 @@ public struct WalletService: Sendable { try await keystore.deleteKey(for: wallet) try walletStore.deleteWallet(for: wallet.walletId) try avatarService.remove(for: wallet) + try FileManager.default.removeItem(at: WalletPreferences.preferencesURL(walletId: wallet.walletId)) await MainActor.run { if currentWalletId == wallet.walletId { diff --git a/Packages/Preferences/Sources/WalletPreferences.swift b/Packages/Preferences/Sources/WalletPreferences.swift index df9b6ca32..70e5fc947 100644 --- a/Packages/Preferences/Sources/WalletPreferences.swift +++ b/Packages/Preferences/Sources/WalletPreferences.swift @@ -16,7 +16,7 @@ public final class WalletPreferences: @unchecked Sendable { private let defaults: UserDefaults public init(walletId: WalletId) { - self.defaults = Self.suite(walletId: walletId.id) + self.defaults = UserDefaults(suiteName: Self.suiteName(walletId: walletId.id))! } public var completeInitialLoadAssets: Bool { @@ -78,7 +78,11 @@ public final class WalletPreferences: @unchecked Sendable { return .none } - private static func suite(walletId: String) -> UserDefaults { - UserDefaults(suiteName: "wallet_preferences_\(walletId)_v2")! + private static func suiteName(walletId: String) -> String { + "wallet_preferences_\(walletId)_v2" + } + + public static func preferencesURL(walletId: WalletId) -> URL { + FileManager.Directory.library(.preferences).url.appendingPathComponent("\(suiteName(walletId: walletId.id)).plist") } } diff --git a/Packages/Preferences/Tests/WalletPreferencesTests.swift b/Packages/Preferences/Tests/WalletPreferencesTests.swift index 28d177a97..3ea9fc3bb 100644 --- a/Packages/Preferences/Tests/WalletPreferencesTests.swift +++ b/Packages/Preferences/Tests/WalletPreferencesTests.swift @@ -60,6 +60,27 @@ struct WalletPreferencesTests { #expect(!preferences.completeInitialLoadAssets) #expect(!preferences.completeInitialAddressStatus) #expect(preferences.transactionsForAssetTimestamp(assetId: asset.id.identifier) == 0) + } + + @Test + func preferencesURL() { + let walletId = WalletId(id: "test-id") + let url = WalletPreferences.preferencesURL(walletId: walletId) + let expectedURL = FileManager.Directory.library(.preferences).url.appendingPathComponent("wallet_preferences_test-id_v2.plist") + + #expect(url == expectedURL) + } + + @Test + func removePreferencesFile() throws { + let walletId = WalletId(id: UUID().uuidString) + let preferences = WalletPreferences(walletId: walletId) + preferences.assetsTimestamp = 1 + let url = WalletPreferences.preferencesURL(walletId: walletId) + + #expect(FileManager.default.fileExists(atPath: url.path)) + try FileManager.default.removeItem(at: url) + #expect(FileManager.default.fileExists(atPath: url.path) == false) } } From d39b6c973fdbd6a20c9e6d07b4d8b1a7e8d2b334 Mon Sep 17 00:00:00 2001 From: Radmir Date: Thu, 19 Feb 2026 12:04:53 +0500 Subject: [PATCH 2/2] Fix unit test --- .../WalletService/WalletService.swift | 5 ++- .../Sources/WalletPreferences.swift | 34 +++++-------------- .../Tests/WalletPreferencesTests.swift | 22 ------------ 3 files changed, 12 insertions(+), 49 deletions(-) diff --git a/Packages/FeatureServices/WalletService/WalletService.swift b/Packages/FeatureServices/WalletService/WalletService.swift index 27c4d6d97..268494ab0 100644 --- a/Packages/FeatureServices/WalletService/WalletService.swift +++ b/Packages/FeatureServices/WalletService/WalletService.swift @@ -103,12 +103,15 @@ public struct WalletService: Sendable { try await keystore.deleteKey(for: wallet) try walletStore.deleteWallet(for: wallet.walletId) try avatarService.remove(for: wallet) - try FileManager.default.removeItem(at: WalletPreferences.preferencesURL(walletId: wallet.walletId)) + WalletPreferences(walletId: wallet.walletId).clear() await MainActor.run { if currentWalletId == wallet.walletId { walletSessionService.setCurrent(walletId: wallets.first?.walletId) } + if wallets.isEmpty { + Preferences.standard.clear() + } } } diff --git a/Packages/Preferences/Sources/WalletPreferences.swift b/Packages/Preferences/Sources/WalletPreferences.swift index 70e5fc947..3be13e4f0 100644 --- a/Packages/Preferences/Sources/WalletPreferences.swift +++ b/Packages/Preferences/Sources/WalletPreferences.swift @@ -14,16 +14,18 @@ public final class WalletPreferences: @unchecked Sendable { } private let defaults: UserDefaults + private let suiteName: String public init(walletId: WalletId) { - self.defaults = UserDefaults(suiteName: Self.suiteName(walletId: walletId.id))! + self.suiteName = Self.suiteName(walletId: walletId.id) + self.defaults = UserDefaults(suiteName: suiteName)! } public var completeInitialLoadAssets: Bool { set { defaults.setValue(newValue, forKey: Keys.completeInitialLoadAssets) } get { defaults.bool(forKey: Keys.completeInitialLoadAssets) } } - + public var transactionsTimestamp: Int { set { defaults.setValue(newValue, forKey: Keys.transactionsTimestamp) } get { defaults.integer(forKey: Keys.transactionsTimestamp) } @@ -38,17 +40,17 @@ public final class WalletPreferences: @unchecked Sendable { set { defaults.setValue(newValue, forKey: Keys.assetsTimestamp) } get { defaults.integer(forKey: Keys.assetsTimestamp) } } - + public var completeInitialAddressStatus: Bool { set { defaults.setValue(newValue, forKey: Keys.completeInitialAddressStatus) } get { defaults.bool(forKey: Keys.completeInitialAddressStatus) } } - + public func completeInitialSynchronization() { completeInitialAddressStatus = true completeInitialLoadAssets = true } - + // transactions public func setTransactionsForAssetTimestamp(assetId: String, value: Int) { defaults.setValue(value, forKey: String(format: "%@_%@", Keys.transactionsForAsset, assetId)) @@ -59,30 +61,10 @@ public final class WalletPreferences: @unchecked Sendable { } public func clear() { - defaults.dictionaryRepresentation().keys.forEach { - defaults.removeObject(forKey: $0) - } - } - - private func encode(key: String, data: Codable) { - if let encoded = try? JSONEncoder().encode(data) { - defaults.set(encoded, forKey: key) - } - } - - private func decode(key: String) -> T? { - if let data = defaults.object(forKey: key) as? Data, - let typedData = try? JSONDecoder().decode(T.self, from: data){ - return typedData - } - return .none + UserDefaults.standard.removePersistentDomain(forName: suiteName) } private static func suiteName(walletId: String) -> String { "wallet_preferences_\(walletId)_v2" } - - public static func preferencesURL(walletId: WalletId) -> URL { - FileManager.Directory.library(.preferences).url.appendingPathComponent("\(suiteName(walletId: walletId.id)).plist") - } } diff --git a/Packages/Preferences/Tests/WalletPreferencesTests.swift b/Packages/Preferences/Tests/WalletPreferencesTests.swift index 3ea9fc3bb..9a7444c9b 100644 --- a/Packages/Preferences/Tests/WalletPreferencesTests.swift +++ b/Packages/Preferences/Tests/WalletPreferencesTests.swift @@ -61,26 +61,4 @@ struct WalletPreferencesTests { #expect(!preferences.completeInitialAddressStatus) #expect(preferences.transactionsForAssetTimestamp(assetId: asset.id.identifier) == 0) } - - @Test - func preferencesURL() { - let walletId = WalletId(id: "test-id") - let url = WalletPreferences.preferencesURL(walletId: walletId) - let expectedURL = FileManager.Directory.library(.preferences).url.appendingPathComponent("wallet_preferences_test-id_v2.plist") - - #expect(url == expectedURL) - } - - @Test - func removePreferencesFile() throws { - let walletId = WalletId(id: UUID().uuidString) - let preferences = WalletPreferences(walletId: walletId) - preferences.assetsTimestamp = 1 - let url = WalletPreferences.preferencesURL(walletId: walletId) - - #expect(FileManager.default.fileExists(atPath: url.path)) - - try FileManager.default.removeItem(at: url) - #expect(FileManager.default.fileExists(atPath: url.path) == false) - } }