From 59a0a2cadc1e7ee2396c8a3794b8f77789fce3e8 Mon Sep 17 00:00:00 2001 From: EA Date: Mon, 9 Sep 2024 17:15:13 +0600 Subject: [PATCH] Auto-enable jettons on restore or watch Ton blockchain --- .../project.pbxproj | 44 ++++--- .../Core/Adapters/TonEventConverter.swift | 2 +- .../Core/Adapters/TonTransactionAdapter.swift | 2 +- .../UnstoppableWallet/Core/App.swift | 12 +- .../Factories/EvmAccountManagerFactory.swift | 8 +- .../Core/Managers/EvmAccountManager.swift | 8 +- .../EvmAccountRestoreStateManager.swift | 21 --- .../Core/Managers/RestoreStateManager.swift | 35 +++++ .../Core/Managers/TonKitManager.swift | 121 +++++++++++++++++- .../Core/Managers/TronAccountManager.swift | 8 +- .../EvmAccountRestoreStateStorage.swift | 23 ---- .../Core/Storage/RestoreStateStorage.swift | 23 ++++ .../Core/Storage/StorageMigrator.swift | 20 +++ .../EvmAccountRestoreState.swift | 0 .../Models/RestoreState.swift | 24 ++++ .../Models/TransactionValue.swift | 23 ++-- .../RestoreSelect/RestoreSelectModule.swift | 2 +- .../RestoreSelect/RestoreSelectService.swift | 8 +- 18 files changed, 279 insertions(+), 105 deletions(-) delete mode 100644 UnstoppableWallet/UnstoppableWallet/Core/Managers/EvmAccountRestoreStateManager.swift create mode 100644 UnstoppableWallet/UnstoppableWallet/Core/Managers/RestoreStateManager.swift delete mode 100644 UnstoppableWallet/UnstoppableWallet/Core/Storage/EvmAccountRestoreStateStorage.swift create mode 100644 UnstoppableWallet/UnstoppableWallet/Core/Storage/RestoreStateStorage.swift rename UnstoppableWallet/UnstoppableWallet/Models/{ => Deprecated}/EvmAccountRestoreState.swift (100%) create mode 100644 UnstoppableWallet/UnstoppableWallet/Models/RestoreState.swift diff --git a/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj b/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj index e1ff9a2d38..721108128c 100644 --- a/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj +++ b/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj @@ -539,7 +539,7 @@ 11B35631E5455A54854A2A6F /* RestoreMnemonicService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35D55DCC92BED4FA87CA0 /* RestoreMnemonicService.swift */; }; 11B356330572A72E56DC2FEA /* PasscodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B359FC4FE023FBA0E1726C /* PasscodeView.swift */; }; 11B35633B952154A098532A4 /* NftCollectionModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35708A630D70385F34A8B /* NftCollectionModule.swift */; }; - 11B3563B5D19C7A4EDFC8FC1 /* EvmAccountRestoreStateStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35999E6C5518115365410 /* EvmAccountRestoreStateStorage.swift */; }; + 11B3563B5D19C7A4EDFC8FC1 /* RestoreStateStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35999E6C5518115365410 /* RestoreStateStorage.swift */; }; 11B3563BF84B730CB695FAB4 /* FaqViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35C09B59EF5DEB6D7EB07 /* FaqViewModel.swift */; }; 11B3563E71C4AC16DFE8AB76 /* ActiveAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35F98E89F83A30870F404 /* ActiveAccount.swift */; }; 11B3564236FEF4E5ACC8C838 /* UnlockModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B354506A9B41DCD49B2807 /* UnlockModule.swift */; }; @@ -629,7 +629,7 @@ 11B357388B82489E53C13772 /* RestoreSettingsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B357F15913DDAE69C9B0E0 /* RestoreSettingsManager.swift */; }; 11B3573B753DB244EEBAAA35 /* ReceiveSelectCoinViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B358B8D6DFEAEDE84D53DE /* ReceiveSelectCoinViewController.swift */; }; 11B3573B8B8DA5C1DE332EB6 /* EvmNetworkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35711A471C5A45DD87108 /* EvmNetworkViewController.swift */; }; - 11B3573F7ED8577EF9F12EF9 /* EvmAccountRestoreStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350A3E8F85D6FA2E17173 /* EvmAccountRestoreStateManager.swift */; }; + 11B3573F7ED8577EF9F12EF9 /* RestoreStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350A3E8F85D6FA2E17173 /* RestoreStateManager.swift */; }; 11B357408E3CCC0B93C42F67 /* WCSignEthereumTransactionRequestViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35A74A323368707589FA3 /* WCSignEthereumTransactionRequestViewModel.swift */; }; 11B3574287AAA5FC16E3E3DA /* NavigationRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3578FB80AA013BD351A26 /* NavigationRow.swift */; }; 11B35749EBFB7FE593BECE9E /* ExtendedKeyViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35F95A84DD0F232E5A9CD /* ExtendedKeyViewModel.swift */; }; @@ -956,7 +956,7 @@ 11B35AC33360F772120B9562 /* RestoreSettingsStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350DD8FFDB14904D23AE0 /* RestoreSettingsStorage.swift */; }; 11B35AC389ACC3E4096EC645 /* PoolGroupFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B356F9C155F16A441EC3A0 /* PoolGroupFactory.swift */; }; 11B35AC60BE4DC210C3C2312 /* NftActivityService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B351E034126F57DB7B4263 /* NftActivityService.swift */; }; - 11B35AC9650545DEBC6C2C90 /* EvmAccountRestoreState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35466A996318C03265848 /* EvmAccountRestoreState.swift */; }; + 11B35AC9650545DEBC6C2C90 /* RestoreState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35466A996318C03265848 /* RestoreState.swift */; }; 11B35ACD13702502B1ED3362 /* HighlightedTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35AC2D01DF06DC50EAC6A /* HighlightedTextView.swift */; }; 11B35ACE7B126DCF9F7F1A19 /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35A6BEF8299304625D6D0 /* SearchBar.swift */; }; 11B35AD1BD3E71EC4C29051F /* NftCollectionViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35396831B92AAC156DF1D /* NftCollectionViewModel.swift */; }; @@ -978,7 +978,7 @@ 11B35B100187D9909A8490A7 /* NftAdapterManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3551049F83912B54DB356 /* NftAdapterManager.swift */; }; 11B35B10C473B24F3AD2F1D3 /* EvmAccountManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35A296048CDD27A26FE9E /* EvmAccountManager.swift */; }; 11B35B11E8F3DA194D632310 /* NftMetadataSyncer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35DA9FF23D110A042EDD6 /* NftMetadataSyncer.swift */; }; - 11B35B152001ADE5E98D1414 /* EvmAccountRestoreState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35466A996318C03265848 /* EvmAccountRestoreState.swift */; }; + 11B35B152001ADE5E98D1414 /* RestoreState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35466A996318C03265848 /* RestoreState.swift */; }; 11B35B15B1815F7EEB128C5F /* BinanceAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35AAAC675987369F2DA1B /* BinanceAdapter.swift */; }; 11B35B172B09C2017B389C07 /* AlertTitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35BF766EAC97E74CD620D /* AlertTitleCell.swift */; }; 11B35B177527D30099B67C91 /* FeeData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B3542B6FE4B4F0C0B65369 /* FeeData.swift */; }; @@ -1068,7 +1068,7 @@ 11B35C357E406E8BC5BF1D94 /* NftMetadataSyncRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35B58E21336A3DF5A9B45 /* NftMetadataSyncRecord.swift */; }; 11B35C3A0B6DE83A66371224 /* SetPasscodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35A10404D5E085E482CC7 /* SetPasscodeView.swift */; }; 11B35C3AFFA5B40481AF15B9 /* AccountRecord_v_0_19.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350F6C5F6ABC288511AF0 /* AccountRecord_v_0_19.swift */; }; - 11B35C43886D9A0F0C69EF33 /* EvmAccountRestoreStateStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35999E6C5518115365410 /* EvmAccountRestoreStateStorage.swift */; }; + 11B35C43886D9A0F0C69EF33 /* RestoreStateStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35999E6C5518115365410 /* RestoreStateStorage.swift */; }; 11B35C47A06C0A4F7231C511 /* NftCollectionAssetsModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35100DD6E2DBF905FD19B /* NftCollectionAssetsModule.swift */; }; 11B35C4A0250F05179488A91 /* CexWithdrawNetworkRaw.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35EC03BB5316524050518 /* CexWithdrawNetworkRaw.swift */; }; 11B35C4D4120D85CD32CAD0F /* TransactionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350CCAA0C9F2F5279F680 /* TransactionsViewController.swift */; }; @@ -1279,7 +1279,7 @@ 11B35EBB5EE2A4AE7332F86F /* WalletElementServiceFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35F4B9522FCCD91582AAF /* WalletElementServiceFactory.swift */; }; 11B35EBBFE0CA22D35BA4A94 /* KeychainManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35196B818E6069195BAF1 /* KeychainManager.swift */; }; 11B35EBC08855AC0CDC0AF09 /* PostCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35C2A54889447CE58B377 /* PostCell.swift */; }; - 11B35EBC6D5608F23DF8581E /* EvmAccountRestoreStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350A3E8F85D6FA2E17173 /* EvmAccountRestoreStateManager.swift */; }; + 11B35EBC6D5608F23DF8581E /* RestoreStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B350A3E8F85D6FA2E17173 /* RestoreStateManager.swift */; }; 11B35EBDDAB95E919600AE72 /* NftActivityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B354FFF7ED1253E3BD804A /* NftActivityViewController.swift */; }; 11B35EBE688A7C4F9B92F865 /* ReceiveModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35CF031BC81E4D401CA01 /* ReceiveModule.swift */; }; 11B35EC3B9E9C778183E1136 /* EvmNftAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35C2397749C5654830540 /* EvmNftAdapter.swift */; }; @@ -2965,6 +2965,8 @@ D3A580982BE8AA90003953F4 /* BitcoinSendSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3A580962BE8AA90003953F4 /* BitcoinSendSettingsViewModel.swift */; }; D3A87D592C89BEAE00F6F619 /* AddJettonBlockchainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3A87D582C89BEAE00F6F619 /* AddJettonBlockchainService.swift */; }; D3A87D5A2C89BEAE00F6F619 /* AddJettonBlockchainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3A87D582C89BEAE00F6F619 /* AddJettonBlockchainService.swift */; }; + D3A87D5C2C8EFB1A00F6F619 /* EvmAccountRestoreState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3A87D5B2C8EFB1A00F6F619 /* EvmAccountRestoreState.swift */; }; + D3A87D5D2C8EFB1A00F6F619 /* EvmAccountRestoreState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3A87D5B2C8EFB1A00F6F619 /* EvmAccountRestoreState.swift */; }; D3AF5A8929FFD85800C1399E /* RxCocoa in Frameworks */ = {isa = PBXBuildFile; productRef = D3AF5A8829FFD85800C1399E /* RxCocoa */; }; D3AF5A8B29FFD85800C1399E /* RxRelay in Frameworks */ = {isa = PBXBuildFile; productRef = D3AF5A8A29FFD85800C1399E /* RxRelay */; }; D3AF5A8D29FFD85800C1399E /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = D3AF5A8C29FFD85800C1399E /* RxSwift */; }; @@ -3195,7 +3197,7 @@ 11B350911E00460DA8925165 /* ManageAccountsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManageAccountsService.swift; sourceTree = ""; }; 11B3509AC90AEDF72F5989C6 /* EnabledWallet_v_0_34.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnabledWallet_v_0_34.swift; sourceTree = ""; }; 11B3509FA9990463C6BE0FEB /* MultiSwapRevokeViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiSwapRevokeViewModel.swift; sourceTree = ""; }; - 11B350A3E8F85D6FA2E17173 /* EvmAccountRestoreStateManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EvmAccountRestoreStateManager.swift; sourceTree = ""; }; + 11B350A3E8F85D6FA2E17173 /* RestoreStateManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreStateManager.swift; sourceTree = ""; }; 11B350B29037572DDAAF9E16 /* AddEvmSyncSourceViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddEvmSyncSourceViewModel.swift; sourceTree = ""; }; 11B350B29B000CD809F81228 /* BlockchainTokensViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlockchainTokensViewModel.swift; sourceTree = ""; }; 11B350B97B976126C34F9A5F /* WalletModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletModule.swift; sourceTree = ""; }; @@ -3374,7 +3376,7 @@ 11B3545402F742FE641B9B6C /* CoinAnalyticsModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoinAnalyticsModule.swift; sourceTree = ""; }; 11B3546480B733000550BEB6 /* RestoreSettingRecord.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreSettingRecord.swift; sourceTree = ""; }; 11B35464B8D90CBE6E864B92 /* NftKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NftKey.swift; sourceTree = ""; }; - 11B35466A996318C03265848 /* EvmAccountRestoreState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EvmAccountRestoreState.swift; sourceTree = ""; }; + 11B35466A996318C03265848 /* RestoreState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreState.swift; sourceTree = ""; }; 11B35466E6DC969B551B10D3 /* CoinAnalyticsIssuesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoinAnalyticsIssuesView.swift; sourceTree = ""; }; 11B35469BE6FC454CD6D15B5 /* BtcBlockchainSettingsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BtcBlockchainSettingsService.swift; sourceTree = ""; }; 11B354712C102B954BCEE258 /* FilterView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FilterView.swift; sourceTree = ""; }; @@ -3594,7 +3596,7 @@ 11B35997A9E413878F48313B /* ActivateSubscriptionModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivateSubscriptionModule.swift; sourceTree = ""; }; 11B359980AA45D6B44151D7A /* StatManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatManager.swift; sourceTree = ""; }; 11B3599833F166185872A3AC /* RecipientAndSlippageMultiSwapSettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipientAndSlippageMultiSwapSettingsView.swift; sourceTree = ""; }; - 11B35999E6C5518115365410 /* EvmAccountRestoreStateStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EvmAccountRestoreStateStorage.swift; sourceTree = ""; }; + 11B35999E6C5518115365410 /* RestoreStateStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreStateStorage.swift; sourceTree = ""; }; 11B359A35AEB7964A94AFFC0 /* BiometryType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BiometryType.swift; sourceTree = ""; }; 11B359B9C1E0BB4D32599695 /* MarkdownViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownViewModel.swift; sourceTree = ""; }; 11B359BBFCD82C3C6DC06F96 /* FeeRateProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeeRateProvider.swift; sourceTree = ""; }; @@ -4644,6 +4646,7 @@ D3A580932BE8AA80003953F4 /* BitcoinSendSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BitcoinSendSettingsView.swift; sourceTree = ""; }; D3A580962BE8AA90003953F4 /* BitcoinSendSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BitcoinSendSettingsViewModel.swift; sourceTree = ""; }; D3A87D582C89BEAE00F6F619 /* AddJettonBlockchainService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddJettonBlockchainService.swift; sourceTree = ""; }; + D3A87D5B2C8EFB1A00F6F619 /* EvmAccountRestoreState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EvmAccountRestoreState.swift; sourceTree = ""; }; D3B476A321D0D64E008B0C3E /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = ""; }; D3B476A421D0D64E008B0C3E /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; D3B476A521D0D659008B0C3E /* zh */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh; path = zh.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -5075,6 +5078,7 @@ 11B3528DDD55DDA1BAC2BADB /* ActiveAccount_v_0_36.swift */, 11B356A734526DECD9606A66 /* AccountRecord_v_0_36.swift */, 11B35E255F6CA21FFA9E6B42 /* FavoriteCoinRecord_v_0_38.swift */, + D3A87D5B2C8EFB1A00F6F619 /* EvmAccountRestoreState.swift */, ); path = Deprecated; sourceTree = ""; @@ -5382,7 +5386,7 @@ 11B351609863530CA8259648 /* BalanceConversionManager.swift */, 11B35A309C359456D7DF1A03 /* AppIconManager.swift */, 11B352FBA1B29357E0120055 /* BalanceHiddenManager.swift */, - 11B350A3E8F85D6FA2E17173 /* EvmAccountRestoreStateManager.swift */, + 11B350A3E8F85D6FA2E17173 /* RestoreStateManager.swift */, 11B3551049F83912B54DB356 /* NftAdapterManager.swift */, 11B359FE71F5DE6AAD2BA3D8 /* NftMetadataManager.swift */, 11B35DA9FF23D110A042EDD6 /* NftMetadataSyncer.swift */, @@ -5744,7 +5748,7 @@ 11B354C4EB27186435736BBA /* BalancePrimaryValue.swift */, 11B35588D5C27AD3673DEE2F /* AppIcon.swift */, ABC9AF8E8DE67732371A00E0 /* FeePriceScale.swift */, - 11B35466A996318C03265848 /* EvmAccountRestoreState.swift */, + 11B35466A996318C03265848 /* RestoreState.swift */, 11B35E3ACDEDBA3D8BC05467 /* NftRecords */, 11B35BEEB24CDB82D3F4E7C0 /* NftAddressMetadata.swift */, 11B351924AF4DA7A0BC6D1A1 /* NftUid.swift */, @@ -5930,7 +5934,7 @@ 11B35025FD5E96FD1AB359E9 /* EnabledWalletCacheStorage.swift */, 11B35F007444A766AF8CD20D /* EvmLabelStorage.swift */, 11B35FA71AA140CD3764C6BC /* SyncerStateStorage.swift */, - 11B35999E6C5518115365410 /* EvmAccountRestoreStateStorage.swift */, + 11B35999E6C5518115365410 /* RestoreStateStorage.swift */, 11B3564E87C69B2989E6A3D2 /* EvmSyncSourceStorage.swift */, 11B35A6DE18A1E6E837DFB21 /* ContactBookManager.swift */, 11B356DBFFBD17DA5DA5D0E0 /* CexAssetManager.swift */, @@ -9945,10 +9949,10 @@ 11B35DF1D8B5125CF13A1812 /* RestoreMnemonicHintView.swift in Sources */, 11B35C8A1082D0A8F0B354B1 /* RestoreMnemonicHintCell.swift in Sources */, D3402AF22BF5D59D003BF6F8 /* WatchlistModifier.swift in Sources */, - 11B35AC9650545DEBC6C2C90 /* EvmAccountRestoreState.swift in Sources */, - 11B35EBC6D5608F23DF8581E /* EvmAccountRestoreStateManager.swift in Sources */, + 11B35AC9650545DEBC6C2C90 /* RestoreState.swift in Sources */, + 11B35EBC6D5608F23DF8581E /* RestoreStateManager.swift in Sources */, D3402AF82BF71C11003BF6F8 /* WatchlistManager.swift in Sources */, - 11B35C43886D9A0F0C69EF33 /* EvmAccountRestoreStateStorage.swift in Sources */, + 11B35C43886D9A0F0C69EF33 /* RestoreStateStorage.swift in Sources */, 11B35B100187D9909A8490A7 /* NftAdapterManager.swift in Sources */, 11B35EC3B9E9C778183E1136 /* EvmNftAdapter.swift in Sources */, 11B350F58D6907C9A9A79F6B /* NftViewController.swift in Sources */, @@ -10441,6 +10445,7 @@ 11B35993ADB991F644E5EE98 /* PasscodeLockState.swift in Sources */, 11B35F906F9708CFC86E53FB /* NoPasscodeViewController.swift in Sources */, ABC9A5E5EFF9D46D036F52B9 /* ProposalChain.swift in Sources */, + D3A87D5D2C8EFB1A00F6F619 /* EvmAccountRestoreState.swift in Sources */, ABC9A220C97C81DC578AA3C7 /* ProposalValidator.swift in Sources */, ABC9A38390F78983E4DBD25D /* Eip155ProposalHandler.swift in Sources */, ABC9A1DBAB7096605C181247 /* WalletConnectRequestChain.swift in Sources */, @@ -11405,9 +11410,9 @@ 11B35FD18C255E2C6D75F38A /* RestoreMnemonicHintView.swift in Sources */, D3402AF72BF71C11003BF6F8 /* WatchlistManager.swift in Sources */, 11B356BCDD5E64C6D6F49489 /* RestoreMnemonicHintCell.swift in Sources */, - 11B35B152001ADE5E98D1414 /* EvmAccountRestoreState.swift in Sources */, - 11B3573F7ED8577EF9F12EF9 /* EvmAccountRestoreStateManager.swift in Sources */, - 11B3563B5D19C7A4EDFC8FC1 /* EvmAccountRestoreStateStorage.swift in Sources */, + 11B35B152001ADE5E98D1414 /* RestoreState.swift in Sources */, + 11B3573F7ED8577EF9F12EF9 /* RestoreStateManager.swift in Sources */, + 11B3563B5D19C7A4EDFC8FC1 /* RestoreStateStorage.swift in Sources */, D3402AEE2BF5D58B003BF6F8 /* WatchlistViewModel.swift in Sources */, 11B356C6C07BE3588A5D52DE /* NftAdapterManager.swift in Sources */, 11B3583C1A73A11974ADAEBB /* EvmNftAdapter.swift in Sources */, @@ -11897,6 +11902,7 @@ 11B35051B85C51018A1C7A3A /* KeychainStorage.swift in Sources */, 11B35A81895CBF7E86C0C437 /* UserDefaultsStorage.swift in Sources */, 11B35259209EA0C688BB2EC9 /* PasscodeLockState.swift in Sources */, + D3A87D5C2C8EFB1A00F6F619 /* EvmAccountRestoreState.swift in Sources */, 11B35F3DB270A794ADF675FB /* NoPasscodeViewController.swift in Sources */, ABC9AB92AA6E6B239B147FA7 /* ProposalChain.swift in Sources */, ABC9A9DFE387DE03A693A06A /* ProposalValidator.swift in Sources */, @@ -12874,7 +12880,7 @@ repositoryURL = "https://github.com/horizontalsystems/TonKit.Swift"; requirement = { kind = exactVersion; - version = 1.0.4; + version = 1.0.6; }; }; 6BF66DD82BA1A73300963242 /* XCRemoteSwiftPackageReference "ObjectMapper" */ = { diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Adapters/TonEventConverter.swift b/UnstoppableWallet/UnstoppableWallet/Core/Adapters/TonEventConverter.swift index 3aadfbcc9a..c33252992e 100644 --- a/UnstoppableWallet/UnstoppableWallet/Core/Adapters/TonEventConverter.swift +++ b/UnstoppableWallet/UnstoppableWallet/Core/Adapters/TonEventConverter.swift @@ -38,7 +38,7 @@ class TonEventConverter { return .coinValue(token: token, value: value) } else { let value = convertAmount(amount: value, decimals: jetton.decimals, sign: sign) - return .jettonValue(name: jetton.name, symbol: jetton.symbol, decimals: jetton.decimals, value: value) + return .jettonValue(jetton: jetton, value: value) } } diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Adapters/TonTransactionAdapter.swift b/UnstoppableWallet/UnstoppableWallet/Core/Adapters/TonTransactionAdapter.swift index 40631f93c1..03823ed6f0 100644 --- a/UnstoppableWallet/UnstoppableWallet/Core/Adapters/TonTransactionAdapter.swift +++ b/UnstoppableWallet/UnstoppableWallet/Core/Adapters/TonTransactionAdapter.swift @@ -119,7 +119,7 @@ extension TonTransactionAdapter: ITransactionsAdapter { tonKit.eventPublisher(tagQuery: tagQuery(token: token, filter: filter, address: address)) .asObservable() .map { [converter] in - $0.map { converter.transactionRecord(event: $0) } + $0.events.map { converter.transactionRecord(event: $0) } } } diff --git a/UnstoppableWallet/UnstoppableWallet/Core/App.swift b/UnstoppableWallet/UnstoppableWallet/Core/App.swift index 3719ea663f..5d18309bf1 100644 --- a/UnstoppableWallet/UnstoppableWallet/Core/App.swift +++ b/UnstoppableWallet/UnstoppableWallet/Core/App.swift @@ -69,7 +69,7 @@ class App { let btcBlockchainManager: BtcBlockchainManager let evmSyncSourceManager: EvmSyncSourceManager - let evmAccountRestoreStateManager: EvmAccountRestoreStateManager + let restoreStateManager: RestoreStateManager let evmBlockchainManager: EvmBlockchainManager let evmLabelManager: EvmLabelManager let binanceKitManager: BinanceKitManager @@ -195,10 +195,10 @@ class App { let evmSyncSourceStorage = EvmSyncSourceStorage(dbPool: dbPool) evmSyncSourceManager = EvmSyncSourceManager(testNetManager: testNetManager, blockchainSettingsStorage: blockchainSettingsStorage, evmSyncSourceStorage: evmSyncSourceStorage) - let evmAccountRestoreStateStorage = EvmAccountRestoreStateStorage(dbPool: dbPool) - evmAccountRestoreStateManager = EvmAccountRestoreStateManager(storage: evmAccountRestoreStateStorage) + let restoreStateStorage = RestoreStateStorage(dbPool: dbPool) + restoreStateManager = RestoreStateManager(storage: restoreStateStorage) - let evmAccountManagerFactory = EvmAccountManagerFactory(accountManager: accountManager, walletManager: walletManager, evmAccountRestoreStateManager: evmAccountRestoreStateManager, marketKit: marketKit) + let evmAccountManagerFactory = EvmAccountManagerFactory(accountManager: accountManager, walletManager: walletManager, restoreStateManager: restoreStateManager, marketKit: marketKit) evmBlockchainManager = EvmBlockchainManager(syncSourceManager: evmSyncSourceManager, testNetManager: testNetManager, marketKit: marketKit, accountManagerFactory: evmAccountManagerFactory) let hsLabelProvider = HsLabelProvider(networkManager: networkManager) @@ -208,9 +208,9 @@ class App { binanceKitManager = BinanceKitManager() let tronKitManager = TronKitManager(testNetManager: testNetManager) - tronAccountManager = TronAccountManager(accountManager: accountManager, walletManager: walletManager, marketKit: marketKit, tronKitManager: tronKitManager, evmAccountRestoreStateManager: evmAccountRestoreStateManager) + tronAccountManager = TronAccountManager(accountManager: accountManager, walletManager: walletManager, marketKit: marketKit, tronKitManager: tronKitManager, restoreStateManager: restoreStateManager) - tonKitManager = TonKitManager() + tonKitManager = TonKitManager(restoreStateManager: restoreStateManager, marketKit: marketKit, walletManager: walletManager) let restoreSettingsStorage = RestoreSettingsStorage(dbPool: dbPool) restoreSettingsManager = RestoreSettingsManager(storage: restoreSettingsStorage) diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Factories/EvmAccountManagerFactory.swift b/UnstoppableWallet/UnstoppableWallet/Core/Factories/EvmAccountManagerFactory.swift index 316704c6b6..abe3146377 100644 --- a/UnstoppableWallet/UnstoppableWallet/Core/Factories/EvmAccountManagerFactory.swift +++ b/UnstoppableWallet/UnstoppableWallet/Core/Factories/EvmAccountManagerFactory.swift @@ -4,13 +4,13 @@ import MarketKit class EvmAccountManagerFactory { private let accountManager: AccountManager private let walletManager: WalletManager - private let evmAccountRestoreStateManager: EvmAccountRestoreStateManager + private let restoreStateManager: RestoreStateManager private let marketKit: MarketKit.Kit - init(accountManager: AccountManager, walletManager: WalletManager, evmAccountRestoreStateManager: EvmAccountRestoreStateManager, marketKit: MarketKit.Kit) { + init(accountManager: AccountManager, walletManager: WalletManager, restoreStateManager: RestoreStateManager, marketKit: MarketKit.Kit) { self.accountManager = accountManager self.walletManager = walletManager - self.evmAccountRestoreStateManager = evmAccountRestoreStateManager + self.restoreStateManager = restoreStateManager self.marketKit = marketKit } } @@ -23,7 +23,7 @@ extension EvmAccountManagerFactory { walletManager: walletManager, marketKit: marketKit, evmKitManager: evmKitManager, - evmAccountRestoreStateManager: evmAccountRestoreStateManager + restoreStateManager: restoreStateManager ) } } diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Managers/EvmAccountManager.swift b/UnstoppableWallet/UnstoppableWallet/Core/Managers/EvmAccountManager.swift index f7166afdb1..45b333037b 100644 --- a/UnstoppableWallet/UnstoppableWallet/Core/Managers/EvmAccountManager.swift +++ b/UnstoppableWallet/UnstoppableWallet/Core/Managers/EvmAccountManager.swift @@ -16,19 +16,19 @@ class EvmAccountManager { private let walletManager: WalletManager private let marketKit: MarketKit.Kit private let evmKitManager: EvmKitManager - private let evmAccountRestoreStateManager: EvmAccountRestoreStateManager + private let restoreStateManager: RestoreStateManager private let disposeBag = DisposeBag() private var cancellables = Set() private var tasks = Set() - init(blockchainType: BlockchainType, accountManager: AccountManager, walletManager: WalletManager, marketKit: MarketKit.Kit, evmKitManager: EvmKitManager, evmAccountRestoreStateManager: EvmAccountRestoreStateManager) { + init(blockchainType: BlockchainType, accountManager: AccountManager, walletManager: WalletManager, marketKit: MarketKit.Kit, evmKitManager: EvmKitManager, restoreStateManager: RestoreStateManager) { self.blockchainType = blockchainType self.accountManager = accountManager self.walletManager = walletManager self.marketKit = marketKit self.evmKitManager = evmKitManager - self.evmAccountRestoreStateManager = evmAccountRestoreStateManager + self.restoreStateManager = restoreStateManager subscribe(ConcurrentDispatchQueueScheduler(qos: .userInitiated), disposeBag, evmKitManager.evmKitCreatedObservable) { [weak self] in self?.handleEvmKitCreated() } } @@ -62,7 +62,7 @@ class EvmAccountManager { return } - if initial, account.origin == .restored, !account.watchAccount, !evmAccountRestoreStateManager.isRestored(account: account, blockchainType: blockchainType) { + if initial, account.origin == .restored, !account.watchAccount, !restoreStateManager.shouldRestore(account: account, blockchainType: blockchainType) { return } diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Managers/EvmAccountRestoreStateManager.swift b/UnstoppableWallet/UnstoppableWallet/Core/Managers/EvmAccountRestoreStateManager.swift deleted file mode 100644 index 006d616ab9..0000000000 --- a/UnstoppableWallet/UnstoppableWallet/Core/Managers/EvmAccountRestoreStateManager.swift +++ /dev/null @@ -1,21 +0,0 @@ -import MarketKit - -class EvmAccountRestoreStateManager { - private let storage: EvmAccountRestoreStateStorage - - init(storage: EvmAccountRestoreStateStorage) { - self.storage = storage - } -} - -extension EvmAccountRestoreStateManager { - func isRestored(account: Account, blockchainType: BlockchainType) -> Bool { - let state = try? storage.evmAccountRestoreState(accountId: account.id, blockchainUid: blockchainType.uid) - return state?.restored ?? false - } - - func setRestored(account: Account, blockchainType: BlockchainType) { - let state = EvmAccountRestoreState(accountId: account.id, blockchainUid: blockchainType.uid, restored: true) - try? storage.save(evmAccountRestoreState: state) - } -} diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Managers/RestoreStateManager.swift b/UnstoppableWallet/UnstoppableWallet/Core/Managers/RestoreStateManager.swift new file mode 100644 index 0000000000..9c8e67d895 --- /dev/null +++ b/UnstoppableWallet/UnstoppableWallet/Core/Managers/RestoreStateManager.swift @@ -0,0 +1,35 @@ +import MarketKit + +class RestoreStateManager { + private let storage: RestoreStateStorage + + init(storage: RestoreStateStorage) { + self.storage = storage + } +} + +extension RestoreStateManager { + func restoreState(account: Account, blockchainType: BlockchainType) -> RestoreState { + (try? storage.restoreState(accountId: account.id, blockchainUid: blockchainType.uid)) ?? RestoreState(accountId: account.id, blockchainUid: blockchainType.uid) + } + + func shouldRestore(account: Account, blockchainType: BlockchainType) -> Bool { + restoreState(account: account, blockchainType: blockchainType).shouldRestore + } + + func initialRestored(account: Account, blockchainType: BlockchainType) -> Bool { + restoreState(account: account, blockchainType: blockchainType).initialRestored + } + + func setShouldRestore(account: Account, blockchainType: BlockchainType) { + var state = (try? storage.restoreState(accountId: account.id, blockchainUid: blockchainType.uid)) ?? RestoreState(accountId: account.id, blockchainUid: blockchainType.uid) + state.shouldRestore = true + try? storage.save(restoreState: state) + } + + func setInitialRestored(account: Account, blockchainType: BlockchainType) { + var state = (try? storage.restoreState(accountId: account.id, blockchainUid: blockchainType.uid)) ?? RestoreState(accountId: account.id, blockchainUid: blockchainType.uid) + state.initialRestored = true + try? storage.save(restoreState: state) + } +} diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Managers/TonKitManager.swift b/UnstoppableWallet/UnstoppableWallet/Core/Managers/TonKitManager.swift index b8c2801a0a..5af38e6145 100644 --- a/UnstoppableWallet/UnstoppableWallet/Core/Managers/TonKitManager.swift +++ b/UnstoppableWallet/UnstoppableWallet/Core/Managers/TonKitManager.swift @@ -1,21 +1,35 @@ +import Combine import Foundation import HdWalletKit +import MarketKit import TonKit import TonSwift import TweetNacl class TonKitManager { - private weak var _tonKit: Kit? + private let restoreStateManager: RestoreStateManager + private let marketKit: MarketKit.Kit + private let walletManager: WalletManager + private var jettonBalanceCancellable: AnyCancellable? + private var eventCancellable: AnyCancellable? + + private weak var _tonKit: TonKit.Kit? private var currentAccount: Account? private let queue = DispatchQueue(label: "\(AppConfig.label).ton-kit-manager", qos: .userInitiated) - private func _tonKit(account: Account) throws -> Kit { + init(restoreStateManager: RestoreStateManager, marketKit: MarketKit.Kit, walletManager: WalletManager) { + self.restoreStateManager = restoreStateManager + self.walletManager = walletManager + self.marketKit = marketKit + } + + private func _tonKit(account: Account) throws -> TonKit.Kit { if let _tonKit, let currentAccount, currentAccount == account { return _tonKit } - let type: Kit.WalletType + let type: TonKit.Kit.WalletType switch account.type { case .mnemonic: @@ -37,7 +51,7 @@ class TonKitManager { throw AdapterError.unsupportedAccount } - let tonKit = try Kit.instance( + let tonKit = try TonKit.Kit.instance( type: type, walletVersion: .v4, network: .mainNet, @@ -51,16 +65,111 @@ class TonKitManager { _tonKit = tonKit currentAccount = account + subscribe(tonKit: tonKit, account: account) + return tonKit } + + private func subscribe(tonKit: TonKit.Kit, account: Account) { + let restoreState = restoreStateManager.restoreState(account: account, blockchainType: .ton) + + // print("RESTORE STATE: shouldRestore: \(restoreState.shouldRestore), initialRestored: \(restoreState.initialRestored)") + + if restoreState.shouldRestore || account.watchAccount, !restoreState.initialRestored { + jettonBalanceCancellable = tonKit.jettonBalanceMapPublisher + .sink { [weak self, restoreStateManager] in + self?.handle(jettons: $0.values.map { $0.jetton }, account: account) + + restoreStateManager.setInitialRestored(account: account, blockchainType: .ton) + + self?.jettonBalanceCancellable?.cancel() + self?.jettonBalanceCancellable = nil + } + } + + let address = tonKit.receiveAddress + + eventCancellable = tonKit.eventPublisher(tagQuery: .init()) + .sink { [weak self] in self?.handle(events: $0.events, initial: $0.initial, address: address, account: account) } + } + + private func handle(events: [Event], initial: Bool, address: TonSwift.Address, account: Account) { + guard !initial else { + // print("ignore initial events: \(events.count)") + return + } + + // print("HANDLE EVENTS: \(events.count)") + + var jettons = Set() + + for event in events { + for action in event.actions { + switch action.type { + case let .jettonTransfer(action): + if action.recipient?.address == address { + jettons.insert(action.jetton) + } + case let .jettonMint(action): + if action.recipient.address == address { + jettons.insert(action.jetton) + } + case let .jettonSwap(action): + if let jetton = action.jettonMasterIn { + jettons.insert(jetton) + } + default: () + } + } + } + + handle(jettons: Array(jettons), account: account) + } + + private func handle(jettons: [Jetton], account: Account) { + // print("HANDLE JETTONS: \(jettons.map { $0.name })") + + guard !jettons.isEmpty else { + return + } + + let existingWallets = walletManager.activeWallets + let existingTokenTypeIds = existingWallets.map(\.token.type.id) + let newJettons = jettons.filter { !existingTokenTypeIds.contains($0.tokenType.id) } + + // print("new jettons: \(newJettons.map { $0.name })") + + guard !newJettons.isEmpty else { + return + } + + let enabledWallets = newJettons.map { jetton in + EnabledWallet( + tokenQueryId: TokenQuery(blockchainType: .ton, tokenType: jetton.tokenType).id, + accountId: account.id, + coinName: jetton.name, + coinCode: jetton.symbol, + coinImage: jetton.image, + tokenDecimals: jetton.decimals + ) + } + + walletManager.save(enabledWallets: enabledWallets) + } } extension TonKitManager { - var tonKit: Kit? { + var tonKit: TonKit.Kit? { queue.sync { _tonKit } } - func tonKit(account: Account) throws -> Kit { + func tonKit(account: Account) throws -> TonKit.Kit { try queue.sync { try _tonKit(account: account) } } } + +extension Jetton { + var tokenType: TokenType { + .jetton(address: address.toString(bounceable: true)) + } +} diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Managers/TronAccountManager.swift b/UnstoppableWallet/UnstoppableWallet/Core/Managers/TronAccountManager.swift index 00a691661a..1e064d05f7 100644 --- a/UnstoppableWallet/UnstoppableWallet/Core/Managers/TronAccountManager.swift +++ b/UnstoppableWallet/UnstoppableWallet/Core/Managers/TronAccountManager.swift @@ -9,17 +9,17 @@ class TronAccountManager { private let walletManager: WalletManager private let marketKit: MarketKit.Kit private let tronKitManager: TronKitManager - private let evmAccountRestoreStateManager: EvmAccountRestoreStateManager + private let restoreStateManager: RestoreStateManager private let disposeBag = DisposeBag() private var internalDisposeBag = DisposeBag() - init(accountManager: AccountManager, walletManager: WalletManager, marketKit: MarketKit.Kit, tronKitManager: TronKitManager, evmAccountRestoreStateManager: EvmAccountRestoreStateManager) { + init(accountManager: AccountManager, walletManager: WalletManager, marketKit: MarketKit.Kit, tronKitManager: TronKitManager, restoreStateManager: RestoreStateManager) { self.accountManager = accountManager self.walletManager = walletManager self.marketKit = marketKit self.tronKitManager = tronKitManager - self.evmAccountRestoreStateManager = evmAccountRestoreStateManager + self.restoreStateManager = restoreStateManager subscribe(ConcurrentDispatchQueueScheduler(qos: .userInitiated), disposeBag, tronKitManager.tronKitCreatedObservable) { [weak self] in self?.handleTronKitCreated() } } @@ -48,7 +48,7 @@ class TronAccountManager { return } - if initial, account.origin == .restored, !account.watchAccount, !evmAccountRestoreStateManager.isRestored(account: account, blockchainType: blockchainType) { + if initial, account.origin == .restored, !account.watchAccount, !restoreStateManager.shouldRestore(account: account, blockchainType: blockchainType) { return } diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Storage/EvmAccountRestoreStateStorage.swift b/UnstoppableWallet/UnstoppableWallet/Core/Storage/EvmAccountRestoreStateStorage.swift deleted file mode 100644 index ced52f5b4a..0000000000 --- a/UnstoppableWallet/UnstoppableWallet/Core/Storage/EvmAccountRestoreStateStorage.swift +++ /dev/null @@ -1,23 +0,0 @@ -import GRDB - -class EvmAccountRestoreStateStorage { - private let dbPool: DatabasePool - - init(dbPool: DatabasePool) { - self.dbPool = dbPool - } -} - -extension EvmAccountRestoreStateStorage { - func evmAccountRestoreState(accountId: String, blockchainUid: String) throws -> EvmAccountRestoreState? { - try dbPool.read { db in - try EvmAccountRestoreState.filter(EvmAccountRestoreState.Columns.accountId == accountId && EvmAccountRestoreState.Columns.blockchainUid == blockchainUid).fetchOne(db) - } - } - - func save(evmAccountRestoreState: EvmAccountRestoreState) throws { - _ = try dbPool.write { db in - try evmAccountRestoreState.insert(db) - } - } -} diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Storage/RestoreStateStorage.swift b/UnstoppableWallet/UnstoppableWallet/Core/Storage/RestoreStateStorage.swift new file mode 100644 index 0000000000..29dc2f6111 --- /dev/null +++ b/UnstoppableWallet/UnstoppableWallet/Core/Storage/RestoreStateStorage.swift @@ -0,0 +1,23 @@ +import GRDB + +class RestoreStateStorage { + private let dbPool: DatabasePool + + init(dbPool: DatabasePool) { + self.dbPool = dbPool + } +} + +extension RestoreStateStorage { + func restoreState(accountId: String, blockchainUid: String) throws -> RestoreState? { + try dbPool.read { db in + try RestoreState.filter(RestoreState.Columns.accountId == accountId && RestoreState.Columns.blockchainUid == blockchainUid).fetchOne(db) + } + } + + func save(restoreState: RestoreState) throws { + _ = try dbPool.write { db in + try restoreState.insert(db) + } + } +} diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Storage/StorageMigrator.swift b/UnstoppableWallet/UnstoppableWallet/Core/Storage/StorageMigrator.swift index 95cf4069f1..bc97572c77 100644 --- a/UnstoppableWallet/UnstoppableWallet/Core/Storage/StorageMigrator.swift +++ b/UnstoppableWallet/UnstoppableWallet/Core/Storage/StorageMigrator.swift @@ -827,6 +827,26 @@ enum StorageMigrator { } } + migrator.registerMigration("create restoreState") { db in + let oldStates = try EvmAccountRestoreState.fetchAll(db) + try db.drop(table: EvmAccountRestoreState.databaseTableName) + + try db.create(table: "restoreState") { t in + t.column(RestoreState.Columns.accountId.name, .text).notNull() + t.column(RestoreState.Columns.blockchainUid.name, .text).notNull() + t.column(RestoreState.Columns.shouldRestore.name, .boolean).notNull() + t.column(RestoreState.Columns.initialRestored.name, .boolean).notNull() + + t.primaryKey([RestoreState.Columns.accountId.name, RestoreState.Columns.blockchainUid.name], onConflict: .replace) + } + + let states = oldStates.map { RestoreState(accountId: $0.accountId, blockchainUid: $0.blockchainUid, shouldRestore: $0.restored) } + + for state in states { + try state.insert(db) + } + } + try migrator.migrate(dbPool) } diff --git a/UnstoppableWallet/UnstoppableWallet/Models/EvmAccountRestoreState.swift b/UnstoppableWallet/UnstoppableWallet/Models/Deprecated/EvmAccountRestoreState.swift similarity index 100% rename from UnstoppableWallet/UnstoppableWallet/Models/EvmAccountRestoreState.swift rename to UnstoppableWallet/UnstoppableWallet/Models/Deprecated/EvmAccountRestoreState.swift diff --git a/UnstoppableWallet/UnstoppableWallet/Models/RestoreState.swift b/UnstoppableWallet/UnstoppableWallet/Models/RestoreState.swift new file mode 100644 index 0000000000..1a6054db56 --- /dev/null +++ b/UnstoppableWallet/UnstoppableWallet/Models/RestoreState.swift @@ -0,0 +1,24 @@ +import GRDB + +struct RestoreState: Codable { + let accountId: String + let blockchainUid: String + var shouldRestore: Bool + var initialRestored: Bool + + init(accountId: String, blockchainUid: String, shouldRestore: Bool = false, initialRestored: Bool = false) { + self.accountId = accountId + self.blockchainUid = blockchainUid + self.shouldRestore = shouldRestore + self.initialRestored = initialRestored + } +} + +extension RestoreState: FetchableRecord, PersistableRecord { + enum Columns { + static let accountId = Column(CodingKeys.accountId) + static let blockchainUid = Column(CodingKeys.blockchainUid) + static let shouldRestore = Column(CodingKeys.shouldRestore) + static let initialRestored = Column(CodingKeys.initialRestored) + } +} diff --git a/UnstoppableWallet/UnstoppableWallet/Models/TransactionValue.swift b/UnstoppableWallet/UnstoppableWallet/Models/TransactionValue.swift index 28cee1c065..8746873b33 100644 --- a/UnstoppableWallet/UnstoppableWallet/Models/TransactionValue.swift +++ b/UnstoppableWallet/UnstoppableWallet/Models/TransactionValue.swift @@ -1,11 +1,12 @@ import BigInt import Foundation import MarketKit +import TonKit enum TransactionValue { case coinValue(token: Token, value: Decimal) case tokenValue(tokenName: String, tokenCode: String, tokenDecimals: Int, value: Decimal) - case jettonValue(name: String, symbol: String, decimals: Int, value: Decimal) + case jettonValue(jetton: Jetton, value: Decimal) case nftValue(nftUid: NftUid, value: Decimal, tokenName: String?, tokenSymbol: String?) case rawValue(value: BigUInt) @@ -13,7 +14,7 @@ enum TransactionValue { switch self { case let .coinValue(token, _): return token.coin.name case let .tokenValue(tokenName, _, _, _): return tokenName - case let .jettonValue(name, _, _, _): return name + case let .jettonValue(jetton, _): return jetton.name case let .nftValue(nftUid, _, tokenName, _): return tokenName.map { "\($0) #\(nftUid.tokenId)" } ?? "#\(nftUid.tokenId)" case .rawValue: return "" } @@ -23,7 +24,7 @@ enum TransactionValue { switch self { case let .coinValue(token, _): return token.coin.code case let .tokenValue(_, tokenCode, _, _): return tokenCode - case let .jettonValue(_, symbol, _, _): return symbol + case let .jettonValue(jetton, _): return jetton.symbol case let .nftValue(_, _, _, tokenSymbol): return tokenSymbol ?? "NFT" case .rawValue: return "" } @@ -64,7 +65,7 @@ enum TransactionValue { switch self { case let .coinValue(_, value): return value case let .tokenValue(_, _, _, value): return value - case let .jettonValue(_, _, _, value): return value + case let .jettonValue(_, value): return value case let .nftValue(_, value, _, _): return value case .rawValue: return nil } @@ -74,7 +75,7 @@ enum TransactionValue { switch self { case let .coinValue(_, value): return value == 0 case let .tokenValue(_, _, _, value): return value == 0 - case let .jettonValue(_, _, _, value): return value == 0 + case let .jettonValue(_, value): return value == 0 case let .nftValue(_, value, _, _): return value == 0 case let .rawValue(value): return value == 0 } @@ -84,7 +85,7 @@ enum TransactionValue { switch self { case let .coinValue(token, value): return value.isMaxValue(decimals: token.decimals) case let .tokenValue(_, _, tokenDecimals, value): return value.isMaxValue(decimals: tokenDecimals) - case let .jettonValue(_, _, decimals, value): return value.isMaxValue(decimals: decimals) + case let .jettonValue(jetton, value): return value.isMaxValue(decimals: jetton.decimals) default: return false } } @@ -95,8 +96,8 @@ enum TransactionValue { return ValueFormatter.instance.formatFull(value: value, decimalCount: token.decimals, symbol: token.coin.code, signType: signType) case let .tokenValue(_, tokenCode, tokenDecimals, value): return ValueFormatter.instance.formatFull(value: value, decimalCount: tokenDecimals, symbol: tokenCode, signType: signType) - case let .jettonValue(_, symbol, decimals, value): - return ValueFormatter.instance.formatFull(value: value, decimalCount: decimals, symbol: symbol, signType: signType) + case let .jettonValue(jetton, value): + return ValueFormatter.instance.formatFull(value: value, decimalCount: jetton.decimals, symbol: jetton.symbol, signType: signType) case let .nftValue(_, value, _, tokenSymbol): return "\(value.sign == .plus ? "+" : "")\(value) \(tokenSymbol ?? "NFT")" case .rawValue: @@ -110,8 +111,8 @@ enum TransactionValue { return ValueFormatter.instance.formatShort(value: value, decimalCount: token.decimals, symbol: token.coin.code, signType: signType) case let .tokenValue(_, tokenCode, tokenDecimals, value): return ValueFormatter.instance.formatShort(value: value, decimalCount: tokenDecimals, symbol: tokenCode, signType: signType) - case let .jettonValue(_, symbol, decimals, value): - return ValueFormatter.instance.formatShort(value: value, decimalCount: decimals, symbol: symbol, signType: signType) + case let .jettonValue(jetton, value): + return ValueFormatter.instance.formatShort(value: value, decimalCount: jetton.decimals, symbol: jetton.symbol, signType: signType) case let .nftValue(_, value, _, tokenSymbol): return "\(value.sign == .plus ? "+" : "")\(value) \(tokenSymbol ?? "NFT")" case .rawValue: @@ -125,7 +126,7 @@ extension TransactionValue: Equatable { switch (lhs, rhs) { case let (.coinValue(lhsToken, lhsValue), .coinValue(rhsToken, rhsValue)): return lhsToken == rhsToken && lhsValue == rhsValue case let (.tokenValue(lhsTokenName, lhsTokenCode, lhsTokenDecimals, lhsValue), .tokenValue(rhsTokenName, rhsTokenCode, rhsTokenDecimals, rhsValue)): return lhsTokenName == rhsTokenName && lhsTokenCode == rhsTokenCode && lhsTokenDecimals == rhsTokenDecimals && lhsValue == rhsValue - case let (.jettonValue(lhsName, lhsSymbol, lhsDecimals, lhsValue), .tokenValue(rhsName, rhsSymbol, rhsDecimals, rhsValue)): return lhsName == rhsName && lhsSymbol == rhsSymbol && lhsDecimals == rhsDecimals && lhsValue == rhsValue + case let (.jettonValue(lhsJetton, lhsValue), .jettonValue(rhsJetton, rhsValue)): return lhsJetton == rhsJetton && lhsValue == rhsValue case let (.nftValue(lhsNftUid, lhsValue, _, _), .nftValue(rhsNftUid, rhsValue, _, _)): return lhsNftUid == rhsNftUid && lhsValue == rhsValue case let (.rawValue(lhsValue), .rawValue(rhsValue)): return lhsValue == rhsValue default: return false diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/RestoreAccount/RestoreSelect/RestoreSelectModule.swift b/UnstoppableWallet/UnstoppableWallet/Modules/RestoreAccount/RestoreSelect/RestoreSelectModule.swift index 41e0d6795c..dd8a144d08 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/RestoreAccount/RestoreSelect/RestoreSelectModule.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/RestoreAccount/RestoreSelect/RestoreSelectModule.swift @@ -17,7 +17,7 @@ enum RestoreSelectModule { accountFactory: App.shared.accountFactory, accountManager: App.shared.accountManager, walletManager: App.shared.walletManager, - evmAccountRestoreStateManager: App.shared.evmAccountRestoreStateManager, + restoreStateManager: App.shared.restoreStateManager, marketKit: App.shared.marketKit, blockchainTokensService: blockchainTokensService, restoreSettingsService: restoreSettingsService diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/RestoreAccount/RestoreSelect/RestoreSelectService.swift b/UnstoppableWallet/UnstoppableWallet/Modules/RestoreAccount/RestoreSelect/RestoreSelectService.swift index 7f8f3d2c79..07d1730ea4 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/RestoreAccount/RestoreSelect/RestoreSelectService.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/RestoreAccount/RestoreSelect/RestoreSelectService.swift @@ -11,7 +11,7 @@ class RestoreSelectService { private let accountFactory: AccountFactory private let accountManager: AccountManager private let walletManager: WalletManager - private let evmAccountRestoreStateManager: EvmAccountRestoreStateManager + private let restoreStateManager: RestoreStateManager private let marketKit: MarketKit.Kit private let blockchainTokensService: BlockchainTokensService private let restoreSettingsService: RestoreSettingsService @@ -34,7 +34,7 @@ class RestoreSelectService { private let statPage: StatPage - init(accountName: String, accountType: AccountType, statPage: StatPage, isManualBackedUp: Bool, isFileBackedUp: Bool, accountFactory: AccountFactory, accountManager: AccountManager, walletManager: WalletManager, evmAccountRestoreStateManager: EvmAccountRestoreStateManager, marketKit: MarketKit.Kit, blockchainTokensService: BlockchainTokensService, restoreSettingsService: RestoreSettingsService) { + init(accountName: String, accountType: AccountType, statPage: StatPage, isManualBackedUp: Bool, isFileBackedUp: Bool, accountFactory: AccountFactory, accountManager: AccountManager, walletManager: WalletManager, restoreStateManager: RestoreStateManager, marketKit: MarketKit.Kit, blockchainTokensService: BlockchainTokensService, restoreSettingsService: RestoreSettingsService) { self.accountName = accountName self.accountType = accountType self.statPage = statPage @@ -43,7 +43,7 @@ class RestoreSelectService { self.accountFactory = accountFactory self.accountManager = accountManager self.walletManager = walletManager - self.evmAccountRestoreStateManager = evmAccountRestoreStateManager + self.restoreStateManager = restoreStateManager self.marketKit = marketKit self.blockchainTokensService = blockchainTokensService self.restoreSettingsService = restoreSettingsService @@ -213,7 +213,7 @@ extension RestoreSelectService { } for blockchainType in Set(enabledTokens.map(\.blockchainType)) { - evmAccountRestoreStateManager.setRestored(account: account, blockchainType: blockchainType) + restoreStateManager.setShouldRestore(account: account, blockchainType: blockchainType) } let wallets = enabledTokens.map { Wallet(token: $0, account: account) }