Skip to content

Commit

Permalink
Add restore settings to backup files.
Browse files Browse the repository at this point in the history
- Make models for full backup
  • Loading branch information
ant013 committed Sep 14, 2023
1 parent b6b029b commit 8d3d59b
Show file tree
Hide file tree
Showing 14 changed files with 130 additions and 45 deletions.
12 changes: 12 additions & 0 deletions UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1955,6 +1955,7 @@
ABC9A0F42A6687705CAD1340 /* NftAssetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AF9C0D0174A5B6A91F13 /* NftAssetViewController.swift */; };
ABC9A1117A41AB8CE00FDEDB /* WalletConnectAppShowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A845B2969166028BA5F0 /* WalletConnectAppShowView.swift */; };
ABC9A133A6BF0FC9A87FA14A /* ContactBookSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A99184EE1D5D052C52E9 /* ContactBookSettingsViewController.swift */; };
ABC9A13D78DD5F176A170B65 /* FullBackup.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A41F6AA0B65FDA91EB68 /* FullBackup.swift */; };
ABC9A13DB3ADB580D59F66E4 /* SendEip1155ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A23CB332521C0607CC6B /* SendEip1155ViewModel.swift */; };
ABC9A13F4C814FFB31FF13CA /* SendEip721ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A7315E119F0B1581B70C /* SendEip721ViewController.swift */; };
ABC9A140CD70E91A1F4A3A5B /* DonateAddressModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A0B7E7360DC0357B2D0F /* DonateAddressModule.swift */; };
Expand Down Expand Up @@ -1992,6 +1993,7 @@
ABC9A2AA80535822D8731DA4 /* ContactBookViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A2D87362E00FD9FB5688 /* ContactBookViewController.swift */; };
ABC9A2B6F1CF39D5CE9EA489 /* BackupCloudPassphraseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A8E4CDD143171A1F9C46 /* BackupCloudPassphraseViewController.swift */; };
ABC9A2BE94B97921C3017C3F /* ContactBookContactService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A5E6F7C6887DD5DFF6E4 /* ContactBookContactService.swift */; };
ABC9A2C4301447E0EEA1D16F /* FullBackup.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A41F6AA0B65FDA91EB68 /* FullBackup.swift */; };
ABC9A2C671DE8C67F192D22E /* ContactBookAddressService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AC8CCF3B57FDFC817356 /* ContactBookAddressService.swift */; };
ABC9A2CA505DB49DE0FB28DD /* WalletTokenBalanceCustomAmountCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AD448DC071D8800C6B12 /* WalletTokenBalanceCustomAmountCell.swift */; };
ABC9A2D0ACEDCFA5FDB04D89 /* IndicatorDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A12E4155640075755699 /* IndicatorDataSource.swift */; };
Expand Down Expand Up @@ -2159,6 +2161,7 @@
ABC9A96132AD85DD613EC773 /* ProFeaturesStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AB785128005F6C2C9F9A /* ProFeaturesStorage.swift */; };
ABC9A994D6AC5771ED49EFD1 /* DonateAddressViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A72B62F6152709348A6D /* DonateAddressViewModel.swift */; };
ABC9A99724D817AF0E6C5EC3 /* FileStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AB0A37663BC3F17C7A81 /* FileStorage.swift */; };
ABC9A99861B1F83A19EA370D /* AppearanceBackup.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AA7FC181E0E0FB74BEF5 /* AppearanceBackup.swift */; };
ABC9A998ECDE5438D94FBAE7 /* MarketDiscoveryCategoryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9ADFD9DA59BD2FB21C51B /* MarketDiscoveryCategoryService.swift */; };
ABC9A9A9FE5A83A6F0C3BFE9 /* SendEip721ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A7C3BC5FC664BBF14C4F /* SendEip721ViewModel.swift */; };
ABC9A9AC7890BE4AAE7DDC84 /* WalletConnectSessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AC0B5943DF3B61B20BF6 /* WalletConnectSessionManager.swift */; };
Expand All @@ -2171,6 +2174,7 @@
ABC9AA27A42D7E2A72B4A932 /* RestoreTypeModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AAC741F9A54293CD21B1 /* RestoreTypeModule.swift */; };
ABC9AA27A709AC5F85176A53 /* WalletConnectModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A0F966294A4E629CCB65 /* WalletConnectModule.swift */; };
ABC9AA309248821942E78740 /* MarketCardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A2B7FBA735A76083990C /* MarketCardCell.swift */; };
ABC9AA39ED35D6EF41A5353D /* AppearanceBackup.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AA7FC181E0E0FB74BEF5 /* AppearanceBackup.swift */; };
ABC9AA462C94586CD8233295 /* WalletConnectAppShowModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A9E2C039C005650491D2 /* WalletConnectAppShowModule.swift */; };
ABC9AA4B0A6C33CAD5F3B050 /* ChartIndicatorsModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AB3EC7A1FB0D6C9F7F89 /* ChartIndicatorsModule.swift */; };
ABC9AA78419B8BFEC23E8E02 /* TokenSelectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A791A47F4F1E71B51B3B /* TokenSelectView.swift */; };
Expand Down Expand Up @@ -3704,6 +3708,7 @@
ABC9A3F41BDCD5F4146E6E06 /* SendBinanceService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendBinanceService.swift; sourceTree = "<group>"; };
ABC9A3FB680357E569B6DB5F /* WalletConnectAppShowViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletConnectAppShowViewModel.swift; sourceTree = "<group>"; };
ABC9A3FBE68E228E3BE66F7B /* WalletTokenListDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletTokenListDataSource.swift; sourceTree = "<group>"; };
ABC9A41F6AA0B65FDA91EB68 /* FullBackup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullBackup.swift; sourceTree = "<group>"; };
ABC9A4544AB5CA22ADE16417 /* WalletConnectSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletConnectSession.swift; sourceTree = "<group>"; };
ABC9A45E29D1773EF27A0074 /* RestoreCloudModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreCloudModule.swift; sourceTree = "<group>"; };
ABC9A4674CCDED7C12EB5C09 /* ContactBookAddressModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactBookAddressModule.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3780,6 +3785,7 @@
ABC9AA751C8B09F90F716231 /* RestoreCloudViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreCloudViewController.swift; sourceTree = "<group>"; };
ABC9AA77C414AC06C41F9319 /* SessionRequestFilterManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionRequestFilterManager.swift; sourceTree = "<group>"; };
ABC9AA7F2ECF212EF8B70470 /* SendConfirmationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendConfirmationViewController.swift; sourceTree = "<group>"; };
ABC9AA7FC181E0E0FB74BEF5 /* AppearanceBackup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearanceBackup.swift; sourceTree = "<group>"; };
ABC9AA8F31619609907AD67E /* MacdIndicatorDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MacdIndicatorDataSource.swift; sourceTree = "<group>"; };
ABC9AA99463E646706E8E36D /* RestoreCloudPassphraseViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreCloudPassphraseViewModel.swift; sourceTree = "<group>"; };
ABC9AAB6BA03FFE92F247FF6 /* ProChartFetcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProChartFetcher.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -6995,6 +7001,8 @@
ABC9AAEA86EF9D14503A4791 /* WalletBackupCrypto.swift */,
ABC9A89726499CDB4F697EDD /* CipherParams.swift */,
ABC9AECEEB35D57CB0965E79 /* WalletBackup.swift */,
ABC9A41F6AA0B65FDA91EB68 /* FullBackup.swift */,
ABC9AA7FC181E0E0FB74BEF5 /* AppearanceBackup.swift */,
);
path = Crypto;
sourceTree = "<group>";
Expand Down Expand Up @@ -9104,6 +9112,8 @@
11B359425D03F504ECA51B1A /* BlockchainSettingsView.swift in Sources */,
11B35FFD159D864F6D914F08 /* AppearanceView.swift in Sources */,
11B350CA618DD7BBA452FC33 /* AppearanceViewModel.swift in Sources */,
ABC9A13D78DD5F176A170B65 /* FullBackup.swift in Sources */,
ABC9AA39ED35D6EF41A5353D /* AppearanceBackup.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -10380,6 +10390,8 @@
11B35B6E11AE440A79D53E0F /* BlockchainSettingsView.swift in Sources */,
11B35245CD0D5B0E44E413F4 /* AppearanceView.swift in Sources */,
11B35A18AA61F8C06AB1C15B /* AppearanceViewModel.swift in Sources */,
ABC9A2C4301447E0EEA1D16F /* FullBackup.swift in Sources */,
ABC9A99861B1F83A19EA370D /* AppearanceBackup.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
3 changes: 2 additions & 1 deletion UnstoppableWallet/UnstoppableWallet/Core/App.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ class App {
accountRestoreWarningManager = AccountRestoreWarningManager(accountManager: accountManager, localStorage: StorageKit.LocalStorage.default)
accountFactory = AccountFactory(accountManager: accountManager)

cloudAccountBackupManager = CloudAccountBackupManager(ubiquityContainerIdentifier: AppConfig.sharedCloudContainer, logger: logger)
backupManager = BackupManager(accountManager: accountManager)

kitCleaner = KitCleaner(accountManager: accountManager)
Expand Down Expand Up @@ -192,6 +191,8 @@ class App {
restoreSettingsManager = RestoreSettingsManager(storage: restoreSettingsStorage)
predefinedBlockchainService = PredefinedBlockchainService(restoreSettingsManager: restoreSettingsManager)

cloudAccountBackupManager = CloudAccountBackupManager(ubiquityContainerIdentifier: AppConfig.sharedCloudContainer, restoreSettingsManager: restoreSettingsManager, logger: logger)

let hsLabelProvider = HsLabelProvider(networkManager: networkManager)
let evmLabelStorage = EvmLabelStorage(dbPool: dbPool)
let syncerStateStorage = SyncerStateStorage(dbPool: dbPool)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Foundation
import Chart
import CurrencyKit
import ThemeKit

struct AppearanceBackup {
let lockTimeEnabled: Bool
let remoteContactsSync: Bool
let defaultProviders: [DefaultProvider]
let chartIndicators: [ChartIndicator]
let indicatorsShown: Bool
let currentLanguage: String
let baseCurrency: Currency

let mode: ThemeMode
let showMarketTab: Bool
let launchScreen: LaunchScreen
let conversionTokenQueryId: String?
let balancePrimaryValue: BalancePrimaryValue
let balanceAutoHide: Bool
let appIcon: AppIcon
}

extension AppearanceBackup {
struct DefaultProvider {
let blockchainTypeId: String
let provider: String
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Foundation

struct FullBackup {
let wallets: [WalletBackup]
let watchlistIds: [String]
let contacts: ContactBook?
let appearance: AppearanceBackup?
}
19 changes: 16 additions & 3 deletions UnstoppableWallet/UnstoppableWallet/Core/Crypto/WalletBackup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,31 +54,40 @@ class WalletBackup: Codable {
}

extension WalletBackup {
struct Settings: Codable {
let type: String
let value: String
}

struct EnabledWallet: Codable {
let tokenQueryId: String
let coinName: String?
let coinCode: String?
let tokenDecimals: Int?
let settings: [String: String]

enum CodingKeys: String, CodingKey {
case tokenQueryId = "token_query_id"
case coinName = "coin_name"
case coinCode = "coin_code"
case tokenDecimals = "decimals"
case settings
}

init(tokenQueryId: String, coinName: String?, coinCode: String?, tokenDecimals: Int?) {
init(tokenQueryId: String, coinName: String?, coinCode: String?, tokenDecimals: Int?, settings: [String: String]) {
self.tokenQueryId = tokenQueryId
self.coinName = coinName
self.coinCode = coinCode
self.tokenDecimals = tokenDecimals
self.settings = settings
}

init(_ wallet: Wallet) {
init(_ wallet: Wallet, settings: [String: String]) {
tokenQueryId = wallet.token.tokenQuery.id
coinName = wallet.coin.name
coinCode = wallet.coin.code
tokenDecimals = wallet.decimals
self.settings = settings
}

init(from decoder: Decoder) throws {
Expand All @@ -87,8 +96,9 @@ extension WalletBackup {
let coinName = try? container.decode(String.self, forKey: .coinName)
let coinCode = try container.decode(String.self, forKey: .coinCode)
let tokenDecimals = try container.decode(Int.self, forKey: .tokenDecimals)
let settings = try? container.decode([String: String].self, forKey: .settings)

self.init(tokenQueryId: tokenQueryId, coinName: coinName, coinCode: coinCode, tokenDecimals: tokenDecimals)
self.init(tokenQueryId: tokenQueryId, coinName: coinName, coinCode: coinCode, tokenDecimals: tokenDecimals, settings: settings ?? [:])
}

public func encode(to encoder: Encoder) throws {
Expand All @@ -97,6 +107,9 @@ extension WalletBackup {
try container.encode(coinName, forKey: .coinName)
try container.encode(coinCode, forKey: .coinCode)
try container.encode(tokenDecimals, forKey: .tokenDecimals)
if !settings.isEmpty {
try container.encode(settings, forKey: .settings)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ extension AdapterFactory {
return try? DashAdapter(wallet: wallet, syncMode: syncMode)

case (.native, .zcash):
let restoreSettings = restoreSettingsManager.settings(account: wallet.account, blockchainType: .zcash)
let restoreSettings = restoreSettingsManager.settings(accountId: wallet.account.id, blockchainType: .zcash)
return try? ZcashAdapter(wallet: wallet, restoreSettings: restoreSettings)

case (.native, .binanceChain), (.bep2, .binanceChain):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
import Foundation
import Combine
import HsToolKit
import Foundation
import HsExtensions
import HsToolKit

class CloudAccountBackupManager {
static private let batchingInterval: TimeInterval = 1
static private let fileExtension = ".json"
private static let batchingInterval: TimeInterval = 1
private static let fileExtension = ".json"

private let ubiquityContainerIdentifier: String?
private let fileStorage: FileStorage
private let restoreSettingsManager: RestoreSettingsManager
private let logger: Logger?

private var metadataMonitor: MetadataMonitor?
private var publishers = [AnyCancellable]()

var iCloudUrl: URL? {
FileManager
.default
.url(forUbiquityContainerIdentifier: ubiquityContainerIdentifier)?
.appendingPathComponent("Documents")
.default
.url(forUbiquityContainerIdentifier: ubiquityContainerIdentifier)?
.appendingPathComponent("Documents")
}

@PostPublished private(set) var items = [String: WalletBackup]()
@PostPublished private(set) var state = State.loading

init(ubiquityContainerIdentifier: String?, logger: Logger?) {
init(ubiquityContainerIdentifier: String?, restoreSettingsManager: RestoreSettingsManager, logger: Logger?) {
self.ubiquityContainerIdentifier = ubiquityContainerIdentifier
self.restoreSettingsManager = restoreSettingsManager

fileStorage = FileStorage(logger: logger)
self.logger = logger
Expand All @@ -49,10 +51,10 @@ class CloudAccountBackupManager {
logger?.debug("=C-MANAGER> Turn ON monitor")

metadataMonitor.needUpdatePublisher
.receive(on: DispatchQueue.main)
.sink { [weak self] in
self?.reload()
}.store(in: &publishers)
.receive(on: DispatchQueue.main)
.sink { [weak self] in
self?.reload()
}.store(in: &publishers)
}

private func reload() {
Expand Down Expand Up @@ -113,43 +115,49 @@ class CloudAccountBackupManager {
logger?.log(level: .debug, message: "CloudAccountManager.downloadItems, read \(items.count) files")
return items
}

}

extension CloudAccountBackupManager {

func backedUp(uniqueId: Data) -> Bool {
items.contains { _, backup in backup.id == uniqueId.hs.hex }
}

var existFilenames: [String] {
items.map { ($0.key as NSString).deletingPathExtension }
}

}

extension CloudAccountBackupManager {

var isAvailable: Bool {
iCloudUrl != nil
}

func save(accountType: AccountType, wallets: [Wallet], isManualBackedUp: Bool, passphrase: String, name: String) throws {
func save(account: Account, wallets: [Wallet], isManualBackedUp: Bool, passphrase: String, name: String) throws {
guard let iCloudUrl else {
throw BackupError.urlNotAvailable
}

do {
let name = name + Self.fileExtension
let encoded = try WalletBackupConverter.encode(accountType: accountType, wallets: wallets.map { WalletBackup.EnabledWallet($0) }, isManualBackedUp: isManualBackedUp, passphrase: passphrase)
let encoded = try WalletBackupConverter.encode(
accountType: account.type,
wallets: wallets.map {
let settings = restoreSettingsManager
.settings(accountId: account.id, blockchainType: $0.token.blockchainType)
.reduce(into: [:], { $0[$1.0.rawValue] = $1.1 })

return WalletBackup.EnabledWallet($0, settings: settings)
},
isManualBackedUp: isManualBackedUp,
passphrase: passphrase
)

try fileStorage.write(directoryUrl: iCloudUrl, filename: name, data: encoded)
logger?.log(level: .debug, message: "CloudAccountManager.downloadItems, save \(name)")
} catch {
logger?.log(level: .debug, message: "CloudAccountManager.downloadItems, can't save \(name). Because: \(error)")
throw error
}

}

func delete(uniqueId: Data) throws {
Expand All @@ -162,7 +170,7 @@ extension CloudAccountBackupManager {
throw BackupError.urlNotAvailable
}

guard let item = items.first(where: { name, backup in backup.id == uniqueId }) else {
guard let item = items.first(where: { _, backup in backup.id == uniqueId }) else {
throw BackupError.itemNotFound
}

Expand All @@ -179,11 +187,9 @@ extension CloudAccountBackupManager {
throw error
}
}

}

extension CloudAccountBackupManager {

enum BackupError: Error {
case urlNotAvailable
case itemNotFound
Expand All @@ -194,5 +200,4 @@ extension CloudAccountBackupManager {
case success
case error(Error)
}

}
Loading

0 comments on commit 8d3d59b

Please sign in to comment.