From 6eaae15abac5480ded1405e8336b7810c5104a30 Mon Sep 17 00:00:00 2001 From: Esenbek Date: Thu, 14 Sep 2023 12:29:34 +0600 Subject: [PATCH 1/2] Disable swap function --- .../WalletTokenBalanceViewItemFactory.swift | 6 +----- .../Modules/Wallet/WalletViewItemFactory.swift | 3 +-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceViewItemFactory.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceViewItemFactory.swift index 7776682656..399158f2d1 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceViewItemFactory.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceViewItemFactory.swift @@ -14,7 +14,7 @@ class WalletTokenBalanceViewItemFactory { var buttons = [WalletModule.Button: ButtonState]() switch item.element { - case .wallet(let wallet): + case .wallet: if item.watchAccount { buttons[.address] = .enabled } else { @@ -22,10 +22,6 @@ class WalletTokenBalanceViewItemFactory { buttons[.send] = sendButtonState buttons[.receive] = .enabled - - if wallet.token.swappable { - buttons[.swap] = sendButtonState - } } case .cexAsset(let cexAsset): buttons[.withdraw] = cexAsset.withdrawEnabled ? .enabled : .disabled diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/WalletViewItemFactory.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/WalletViewItemFactory.swift index da6e27e4a6..cd654bdb2c 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/WalletViewItemFactory.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/WalletViewItemFactory.swift @@ -143,8 +143,7 @@ class WalletViewItemFactory { case .evmPrivateKey, .hdExtendedKey, .mnemonic: return [ .send: .enabled, - .receive: .enabled, - .swap: .enabled + .receive: .enabled ] case .evmAddress, .tronAddress: return [:] } From 4b8677cfc50f68db24693b165ef6746e27717ade Mon Sep 17 00:00:00 2001 From: ant013 Date: Fri, 15 Sep 2023 09:47:14 +0600 Subject: [PATCH 2/2] Fix showing custom tokens in receive coin list module --- .../project.pbxproj | 6 ++ .../Extensions/FullCoin.swift | 7 ++ .../Wallet/Receive/ReceiveModule.swift | 4 +- .../Wallet/Receive/ReceiveService.swift | 60 +++----------- .../Receive/SelectCoin/CoinProvider.swift | 83 ++++++++++++++----- .../SelectCoin/ReceiveSelectCoinService.swift | 56 +++++++------ 6 files changed, 119 insertions(+), 97 deletions(-) create mode 100644 UnstoppableWallet/UnstoppableWallet/Extensions/FullCoin.swift diff --git a/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj b/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj index c98d7a71ac..7d4df193ea 100644 --- a/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj +++ b/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj @@ -2023,6 +2023,7 @@ ABC9A3CC73251E7F83A94181 /* UniswapV3TradeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9ACF418357FF7AFC64B3F /* UniswapV3TradeService.swift */; }; ABC9A3D46AA7356763213BA6 /* FeePriceScale.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AF8E8DE67732371A00E0 /* FeePriceScale.swift */; }; ABC9A3D48A3E0E1733F70686 /* SendBinanceService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A3F41BDCD5F4146E6E06 /* SendBinanceService.swift */; }; + ABC9A3EA19771B14B0502A0A /* FullCoin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A9B35C58F6525F3B2D5C /* FullCoin.swift */; }; ABC9A3FCFC46EC73A7E57EA3 /* WalletConnectPairingModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A4BA46EDEEAB6CD9B25C /* WalletConnectPairingModule.swift */; }; ABC9A3FEF48388A60B8BACB5 /* DataSourceChain.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A22311B6AA64B7D93CB4 /* DataSourceChain.swift */; }; ABC9A4045F498EE345B998D8 /* IntegerFormAmountInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AB9077A6A0ABE4909B76 /* IntegerFormAmountInputView.swift */; }; @@ -2276,6 +2277,7 @@ ABC9AE042D6A3D70CA64F959 /* ContactBookModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A5518367F0DDDB94D320 /* ContactBookModule.swift */; }; ABC9AE0D23A7B54521E77052 /* ECashAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A4C563432A34A634B82A /* ECashAdapter.swift */; }; ABC9AE18DE62E4DDDD44916D /* SwapInputModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AAD55B8932EE75E3C037 /* SwapInputModule.swift */; }; + ABC9AE1E60CABA0101D62738 /* FullCoin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A9B35C58F6525F3B2D5C /* FullCoin.swift */; }; ABC9AE223619E13A296BED51 /* MarketCardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A2B7FBA735A76083990C /* MarketCardCell.swift */; }; ABC9AE2C026D04B679644279 /* IntegerAmountInputCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AA527E63E18179CB689A /* IntegerAmountInputCell.swift */; }; ABC9AE3D64AF3981A68D9913 /* SendConfirmationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A3AB799024C8FC2C7DD8 /* SendConfirmationViewModel.swift */; }; @@ -3768,6 +3770,7 @@ ABC9A950663B76424B1761B3 /* EventHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventHandler.swift; sourceTree = ""; }; ABC9A9628A708749A31EEA70 /* ProFeaturesAuthorizationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProFeaturesAuthorizationManager.swift; sourceTree = ""; }; ABC9A99184EE1D5D052C52E9 /* ContactBookSettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactBookSettingsViewController.swift; sourceTree = ""; }; + ABC9A9B35C58F6525F3B2D5C /* FullCoin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullCoin.swift; sourceTree = ""; }; ABC9A9C09ECB9B0CCBAD8C21 /* SendEip1155ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendEip1155ViewController.swift; sourceTree = ""; }; ABC9A9E0190FAD212E2E007F /* RestoreCloudPassphraseModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreCloudPassphraseModule.swift; sourceTree = ""; }; ABC9A9E2C039C005650491D2 /* WalletConnectAppShowModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletConnectAppShowModule.swift; sourceTree = ""; }; @@ -4413,6 +4416,7 @@ 2FA5D1C0A43841C61C61E3AF /* CurrencyValue.swift */, ABC9A8CE84FA36438BE4D6B5 /* FileManager.swift */, 11B3593FBD158050C9FEF6B9 /* Misc.swift */, + ABC9A9B35C58F6525F3B2D5C /* FullCoin.swift */, ); path = Extensions; sourceTree = ""; @@ -9104,6 +9108,7 @@ 11B359425D03F504ECA51B1A /* BlockchainSettingsView.swift in Sources */, 11B35FFD159D864F6D914F08 /* AppearanceView.swift in Sources */, 11B350CA618DD7BBA452FC33 /* AppearanceViewModel.swift in Sources */, + ABC9AE1E60CABA0101D62738 /* FullCoin.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -10380,6 +10385,7 @@ 11B35B6E11AE440A79D53E0F /* BlockchainSettingsView.swift in Sources */, 11B35245CD0D5B0E44E413F4 /* AppearanceView.swift in Sources */, 11B35A18AA61F8C06AB1C15B /* AppearanceViewModel.swift in Sources */, + ABC9A3EA19771B14B0502A0A /* FullCoin.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/UnstoppableWallet/UnstoppableWallet/Extensions/FullCoin.swift b/UnstoppableWallet/UnstoppableWallet/Extensions/FullCoin.swift new file mode 100644 index 0000000000..e88fcfd3b3 --- /dev/null +++ b/UnstoppableWallet/UnstoppableWallet/Extensions/FullCoin.swift @@ -0,0 +1,7 @@ +import MarketKit + +extension FullCoin: Equatable { + public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.coin == rhs.coin && lhs.tokens == rhs.tokens + } +} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveModule.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveModule.swift index 4c283f0405..e428f8c271 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveModule.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveModule.swift @@ -20,8 +20,8 @@ struct ReceiveModule { let coinProvider = CoinProvider( marketKit: App.shared.marketKit, - accountType: account.type, - predefined: service.predefinedCoins + walletManager: App.shared.walletManager, + accountType: account.type ) let selectCoinService = ReceiveSelectCoinService(provider: coinProvider) diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveService.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveService.swift index 87f19341b1..df6aa6419a 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveService.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/ReceiveService.swift @@ -1,6 +1,6 @@ +import Combine import Foundation import MarketKit -import Combine class ReceiveService { private let account: Account @@ -24,8 +24,8 @@ class ReceiveService { private func showReceive(token: Token) { // check if wallet already exist let wallet = walletManager - .activeWallets - .first { $0.token == token } + .activeWallets + .first { $0.token == token } if let wallet { showTokenSubject.send(wallet) @@ -50,11 +50,11 @@ class ReceiveService { // check if has existed wallets let wallets = walletManager - .activeWallets - .filter { wallet in tokens.contains(wallet.token) } + .activeWallets + .filter { wallet in tokens.contains(wallet.token) } switch wallets.count { - case 0: // create wallet and show deposit + case 0: // create wallet and show deposit switch first.blockchainType { case .bitcoin, .litecoin, .bitcoinCash: guard let defaultToken = try? marketKit.token(query: first.blockchainType.defaultTokenQuery) else { @@ -64,12 +64,12 @@ class ReceiveService { let wallet = createWallet(token: defaultToken) showTokenSubject.send(wallet) case .zcash: - showZcashRestoreSelectSubject.send(first) // we must enable zcash wallet and ask for birthday + showZcashRestoreSelectSubject.send(first) // we must enable zcash wallet and ask for birthday default: () } - case 1: // just show deposit. When unique token and it's restored + case 1: // just show deposit. When unique token and it's restored showTokenSubject.send(wallets[0]) - default: // show choose derivation, addressFormat or other (when token is unique, but many wallets) + default: // show choose derivation, addressFormat or other (when token is unique, but many wallets) chooseTokenType(blockchainType: first.blockchainType, wallets: wallets) } } @@ -86,7 +86,7 @@ class ReceiveService { } private func hasSettings(_ tokens: [Token]) -> Bool { - tokens.allSatisfy({ token in + tokens.allSatisfy { token in switch token.blockchainType { case .zcash: return true default: () @@ -95,13 +95,11 @@ class ReceiveService { case .derived, .addressType: return true default: return false } - }) + } } - } extension ReceiveService { - var showTokenPublisher: AnyPublisher { showTokenSubject.eraseToAnyPublisher() } @@ -151,44 +149,10 @@ extension ReceiveService { restoreSettingsService.save(settings: tokenWithSettings.settings, account: account, blockchainType: token.blockchainType) showReceive(token: token) } - } -extension ReceiveService { +extension ReceiveService { func isEnabled(coin: Coin) -> Bool { walletManager.activeWallets.contains { $0.coin == coin } } - - var predefinedCoins: [FullCoin] { - // get all restored coins - let activeWallets = walletManager.activeWallets - let walletCoins = activeWallets.map { - $0.coin - } - // get all native coins for supported blockchains - let nativeCoins = CoinProvider.nativeCoins(marketKit: marketKit) - let predefinedCoins = (walletCoins + nativeCoins).removeDuplicates() - - // found all full coins - let fullCoins = try? marketKit.fullCoins(coinUids: predefinedCoins.map { - $0.uid - }) - - // filter not supported by current account - let predefined = fullCoins?.filter { fullCoin in - fullCoin.tokens.contains { account.type.supports(token: $0) } - }.sorted { lhsCoin, rhsCoin in - let lhsEnabled = isEnabled(coin: lhsCoin.coin) - let rhsEnabled = isEnabled(coin: rhsCoin.coin) - - if lhsEnabled != rhsEnabled { - return lhsEnabled - } - - return lhsCoin.coin.marketCapRank ?? Int.max < rhsCoin.coin.marketCapRank ?? Int.max - } - - return predefined ?? [] - } - } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/CoinProvider.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/CoinProvider.swift index 37d7b2f8bb..d385315d28 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/CoinProvider.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/CoinProvider.swift @@ -3,50 +3,91 @@ import MarketKit class CoinProvider { private let marketKit: MarketKit.Kit + private let walletManager: WalletManager private let accountType: AccountType - var filter: String = "" - let predefined: [FullCoin] + var custom: [FullCoin] = [] + var predefined: [FullCoin] = [] - init(marketKit: MarketKit.Kit, accountType: AccountType, predefined: [FullCoin]) { + init(marketKit: MarketKit.Kit, walletManager: WalletManager, accountType: AccountType) { self.marketKit = marketKit + self.walletManager = walletManager self.accountType = accountType - self.predefined = predefined + + custom = walletManager.activeWallets + .filter { wallet in wallet.token.isCustom } + .map { FullCoin(coin: $0.coin, tokens: [$0.token]) } + + predefined = predefinedCoins + } + + private var nativeFullCoins: [FullCoin] { + do { + let blockchainTypes = BlockchainType.supported.sorted() + let queries = blockchainTypes.map { $0.nativeTokenQueries }.flatMap { $0 } + let coinUids = try marketKit + .tokens(queries: queries) + .map { $0.coin.uid } + + return try marketKit.fullCoins(coinUids: coinUids) + } catch { + return [] + } + } + + private func customCoins(filter: String) -> [FullCoin] { + custom.filter { fullCoin in + fullCoin.coin.code.localizedCaseInsensitiveContains(filter) || fullCoin.coin.name.localizedCaseInsensitiveContains(filter) + } } } extension CoinProvider { - func fetch() -> [FullCoin] { + func fetch(filter: String) -> [FullCoin] { + guard !filter.isEmpty else { + return predefined + } + do { - if !filter.isEmpty { - let fullCoins = try marketKit.fullCoins(filter: filter) - - return fullCoins.filter { fullCoin in - fullCoin.tokens.contains { accountType.supports(token: $0) } - } - } else { - return predefined + var fullCoins = try marketKit.fullCoins(filter: filter) + fullCoins.append(contentsOf: customCoins(filter: filter)) + + return fullCoins.filter { fullCoin in + fullCoin.tokens.contains { accountType.supports(token: $0) } } } catch { return [] } + + return predefined } } extension CoinProvider { - static func nativeCoins(marketKit: MarketKit.Kit) -> [Coin] { - do { - let blockchainTypes = BlockchainType.supported.sorted() - let queries = blockchainTypes.map { $0.nativeTokenQueries }.flatMap { $0 } - let nativeTokens = try marketKit.tokens(queries: queries) - return nativeTokens.map { $0.coin } - } catch { - return [] + var predefinedCoins: [FullCoin] { + // get all restored coins + let activeWallets = walletManager.activeWallets + let walletCoins = activeWallets.map { $0.coin } + + // found account full coins + var walletFullCoins = (try? marketKit.fullCoins(coinUids: walletCoins.map { $0.uid })) ?? [] + walletFullCoins.append(contentsOf: custom) + + // get all native coins for supported blockchains + let nativeFullCoins = nativeFullCoins + + + // filter not supported by current account + let predefined = (walletFullCoins + nativeFullCoins).removeDuplicates() + .filter { fullCoin in + fullCoin.tokens.contains { accountType.supports(token: $0) } } + + return predefined } } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/ReceiveSelectCoinService.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/ReceiveSelectCoinService.swift index d4f0520c2e..6b4e8aeac6 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/ReceiveSelectCoinService.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/ReceiveSelectCoinService.swift @@ -5,6 +5,12 @@ import MarketKit class ReceiveSelectCoinService { private let provider: CoinProvider + private var filter: String = "" { + didSet { + sync() + } + } + @PostPublished private(set) var coins = [FullCoin]() init(provider: CoinProvider) { @@ -14,47 +20,45 @@ class ReceiveSelectCoinService { } private func sync() { - let filter = provider.filter + let coins = provider.fetch(filter: filter) - let coins = provider.fetch() - if !filter.isEmpty { - self.coins = coins.sorted { lhsFullCoin, rhsFullCoin in - let filter = filter.lowercased() + if filter.isEmpty { + self.coins = coins + return + } - let lhsExactCode = lhsFullCoin.coin.code.lowercased() == filter - let rhsExactCode = rhsFullCoin.coin.code.lowercased() == filter + self.coins = coins.sorted { lhsFullCoin, rhsFullCoin in + let filter = filter.lowercased() - if lhsExactCode != rhsExactCode { - return lhsExactCode - } + let lhsExactCode = lhsFullCoin.coin.code.lowercased() == filter + let rhsExactCode = rhsFullCoin.coin.code.lowercased() == filter - let lhsStartsWithCode = lhsFullCoin.coin.code.lowercased().starts(with: filter) - let rhsStartsWithCode = rhsFullCoin.coin.code.lowercased().starts(with: filter) + if lhsExactCode != rhsExactCode { + return lhsExactCode + } - if lhsStartsWithCode != rhsStartsWithCode { - return lhsStartsWithCode - } + let lhsStartsWithCode = lhsFullCoin.coin.code.lowercased().starts(with: filter) + let rhsStartsWithCode = rhsFullCoin.coin.code.lowercased().starts(with: filter) - let lhsStartsWithName = lhsFullCoin.coin.name.lowercased().starts(with: filter) - let rhsStartsWithName = rhsFullCoin.coin.name.lowercased().starts(with: filter) + if lhsStartsWithCode != rhsStartsWithCode { + return lhsStartsWithCode + } - if lhsStartsWithName != rhsStartsWithName { - return lhsStartsWithName - } + let lhsStartsWithName = lhsFullCoin.coin.name.lowercased().starts(with: filter) + let rhsStartsWithName = rhsFullCoin.coin.name.lowercased().starts(with: filter) - return lhsFullCoin.coin.name.lowercased() < rhsFullCoin.coin.name.lowercased() + if lhsStartsWithName != rhsStartsWithName { + return lhsStartsWithName } - } else { - self.coins = coins + + return lhsFullCoin.coin.name.lowercased() < rhsFullCoin.coin.name.lowercased() } } } extension ReceiveSelectCoinService { func set(filter: String) { - provider.filter = filter - - sync() + self.filter = filter } func fullCoin(uid: String) -> FullCoin? {