Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Back-merge fix from master #5240

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -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 */; };
Expand Down Expand Up @@ -3768,6 +3770,7 @@
ABC9A950663B76424B1761B3 /* EventHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventHandler.swift; sourceTree = "<group>"; };
ABC9A9628A708749A31EEA70 /* ProFeaturesAuthorizationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProFeaturesAuthorizationManager.swift; sourceTree = "<group>"; };
ABC9A99184EE1D5D052C52E9 /* ContactBookSettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactBookSettingsViewController.swift; sourceTree = "<group>"; };
ABC9A9B35C58F6525F3B2D5C /* FullCoin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullCoin.swift; sourceTree = "<group>"; };
ABC9A9C09ECB9B0CCBAD8C21 /* SendEip1155ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendEip1155ViewController.swift; sourceTree = "<group>"; };
ABC9A9E0190FAD212E2E007F /* RestoreCloudPassphraseModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreCloudPassphraseModule.swift; sourceTree = "<group>"; };
ABC9A9E2C039C005650491D2 /* WalletConnectAppShowModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletConnectAppShowModule.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4413,6 +4416,7 @@
2FA5D1C0A43841C61C61E3AF /* CurrencyValue.swift */,
ABC9A8CE84FA36438BE4D6B5 /* FileManager.swift */,
11B3593FBD158050C9FEF6B9 /* Misc.swift */,
ABC9A9B35C58F6525F3B2D5C /* FullCoin.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -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;
};
Expand Down Expand Up @@ -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;
};
Expand Down
7 changes: 7 additions & 0 deletions UnstoppableWallet/UnstoppableWallet/Extensions/FullCoin.swift
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Combine
import Foundation
import MarketKit
import Combine

class ReceiveService {
private let account: Account
Expand All @@ -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)
Expand All @@ -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 {
Expand All @@ -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)
}
}
Expand All @@ -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: ()
Expand All @@ -95,13 +95,11 @@ class ReceiveService {
case .derived, .addressType: return true
default: return false
}
})
}
}

}

extension ReceiveService {

var showTokenPublisher: AnyPublisher<Wallet, Never> {
showTokenSubject.eraseToAnyPublisher()
}
Expand Down Expand Up @@ -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 ?? []
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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? {
Expand Down
Loading
Loading