Skip to content

Commit

Permalink
chore(Activity): IOS-6714: Refactor BlockchainAccount.activity to Com…
Browse files Browse the repository at this point in the history
…bine and more. (#4281)

* STX: Activity Combine

* STX: Remove unused code
  • Loading branch information
paulo-bc committed Jul 18, 2022
1 parent e602606 commit 53202b6
Show file tree
Hide file tree
Showing 106 changed files with 1,211 additions and 3,343 deletions.
6 changes: 5 additions & 1 deletion Blockchain/Adapters/AccountsRouter.swift
Expand Up @@ -20,7 +20,11 @@ final class AccountsRouter: AccountsRouting {
routing: TabSwapping,
backupRouter: FeatureDashboardUI.BackupRouterAPI = resolve()
) {
custodyActionRouterAPI = CustodyActionRouter(backupRouterAPI: backupRouter, tabSwapping: routing)
let provider = CustodyActionRouterProvider()
custodyActionRouterAPI = provider.create(
backupRouterAPI: backupRouter,
tabSwapping: routing
)
}

private func routeToInterestAccount(for account: BlockchainAccount) {
Expand Down
24 changes: 0 additions & 24 deletions Blockchain/Adapters/FiatBalanceCellProvider.swift

This file was deleted.

2 changes: 1 addition & 1 deletion Blockchain/Announcements/AnnouncementInteractor.swift
Expand Up @@ -59,7 +59,7 @@ final class AnnouncementInteractor: AnnouncementInteracting {
.take(1)
.asSingle()
let isSimpleBuyEligible = simpleBuyEligibilityService.isEligible
let simpleBuyOrderDetails = pendingOrderDetailsService.pendingActionOrderDetails
let simpleBuyOrderDetails = pendingOrderDetailsService.pendingActionOrderDetails.asSingle()

let simpleBuy: Single<AnnouncementPreliminaryData.SimpleBuy> = Single
.zip(
Expand Down
11 changes: 4 additions & 7 deletions Blockchain/BuySell/BuySellSegmentedViewPresenter.swift
Expand Up @@ -40,13 +40,10 @@ final class BuySellSegmentedViewPresenter: SegmentedViewScreenPresenting {

private(set) lazy var items: [SegmentedViewScreenItem] = {
// Buy
let buyListViewController = PricesViewController(
presenter: PricesScreenPresenter(
drawerRouter: NoDrawer(),
interactor: PricesScreenInteractor(
showSupportedPairsOnly: true
)
),
let provider = PricesViewControllerProvider()
let buyListViewController = provider.create(
drawerRouter: NoDrawer(),
showSupportedPairsOnly: true,
customSelectionActionClosure: { [weak self] currency in
guard let self = self else { return }
self.coincore.cryptoAccounts(for: currency, filter: .custodial)
Expand Down
12 changes: 0 additions & 12 deletions Blockchain/DIKit.swift
Expand Up @@ -190,14 +190,6 @@ extension DependencyContainer {

factory { AnnouncementPresenter() as FeatureDashboardUI.AnnouncementPresenting }

factory { FiatBalanceCellProvider() as FiatBalanceCellProviding }

factory { FiatBalanceCollectionViewInteractor() as FiatBalancesInteracting }

factory { FiatBalanceCollectionViewPresenter(interactor: FiatBalanceCollectionViewInteractor())
as FiatBalanceCollectionViewPresenting
}

factory { SimpleBuyAnalyticsService() as PlatformKit.SimpleBuyAnalayticsServicing }

// MARK: - AppCoordinator
Expand Down Expand Up @@ -489,10 +481,6 @@ extension DependencyContainer {
EmailVerificationAdapter(settingsService: DIKit.resolve())
}

factory { () -> PlatformUIKit.TierUpgradeRouterAPI in
KYCAdapter()
}

// MARK: Onboarding Module

// this must be kept in memory because of how PlatformUIKit.Router works, otherwise the flow crashes.
Expand Down
7 changes: 3 additions & 4 deletions Blockchain/FeatureApp/RootView/Screen/PortfolioView.swift
Expand Up @@ -19,23 +19,22 @@ struct PortfolioView: UIViewControllerRepresentable {
self.store = store
}

private var fiatBalanceCellProvider: FiatBalanceCellProviding = resolve()
private var onboardingViewsFactory = OnboardingViewsFactory()
private var userAdapter: UserAdapterAPI = resolve()

func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}

func makeUIViewController(context: Context) -> some UIViewController {
let viewController = PortfolioViewController(
fiatBalanceCellProvider: fiatBalanceCellProvider,
let provider = PortfolioViewControllerProvider()
let viewController = provider.create(
userHasCompletedOnboarding: userAdapter
.onboardingUserState
.map { $0.kycStatus == .verified && $0.hasEverPurchasedCrypto }
.eraseToAnyPublisher(),
onboardingChecklistViewBuilder: { [onboardingViewsFactory] in
onboardingViewsFactory.makeOnboardingChecklistOverview()
},
presenter: PortfolioScreenPresenter(drawerRouter: NoDrawer())
drawerRouter: NoDrawer()
)
viewController.automaticallyApplyNavigationBarStyle = false
return viewController
Expand Down
10 changes: 3 additions & 7 deletions Blockchain/FeatureApp/RootView/Screen/PricesView.swift
Expand Up @@ -22,14 +22,10 @@ struct PricesView: UIViewControllerRepresentable {
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}

func makeUIViewController(context: Context) -> some UIViewController {
let presenter = PricesScreenPresenter(
let provider = PricesViewControllerProvider()
let viewController = provider.create(
drawerRouter: NoDrawer(),
interactor: PricesScreenInteractor(
showSupportedPairsOnly: false
)
)
let viewController = PricesViewController(
presenter: presenter
showSupportedPairsOnly: false
)
viewController.automaticallyApplyNavigationBarStyle = false
return viewController
Expand Down
77 changes: 37 additions & 40 deletions Modules/BlockchainNamespace/Package.resolved
@@ -1,43 +1,40 @@
{
"object": {
"pins": [
{
"package": "Lexicon",
"repositoryURL": "https://github.com/screensailor/Lexicon",
"state": {
"branch": null,
"revision": "160c4c417f8490658a8396d0283fb0d6fb98c327",
"version": null
}
},
{
"package": "swift-algorithms",
"repositoryURL": "https://github.com/apple/swift-algorithms.git",
"state": {
"branch": null,
"revision": "b14b7f4c528c942f121c8b860b9410b2bf57825e",
"version": "1.0.0"
}
},
{
"package": "swift-collections",
"repositoryURL": "https://github.com/apple/swift-collections",
"state": {
"branch": null,
"revision": "48254824bb4248676bf7ce56014ff57b142b77eb",
"version": "1.0.2"
}
},
{
"package": "swift-numerics",
"repositoryURL": "https://github.com/apple/swift-numerics",
"state": {
"branch": null,
"revision": "0a5bc04095a675662cf24757cc0640aa2204253b",
"version": "1.0.2"
}
"pins" : [
{
"identity" : "lexicon",
"kind" : "remoteSourceControl",
"location" : "https://github.com/screensailor/Lexicon",
"state" : {
"revision" : "160c4c417f8490658a8396d0283fb0d6fb98c327"
}
]
},
"version": 1
},
{
"identity" : "swift-algorithms",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-algorithms.git",
"state" : {
"revision" : "b14b7f4c528c942f121c8b860b9410b2bf57825e",
"version" : "1.0.0"
}
},
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections",
"state" : {
"revision" : "48254824bb4248676bf7ce56014ff57b142b77eb",
"version" : "1.0.2"
}
},
{
"identity" : "swift-numerics",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-numerics",
"state" : {
"revision" : "0a5bc04095a675662cf24757cc0640aa2204253b",
"version" : "1.0.2"
}
}
],
"version" : 2
}
17 changes: 12 additions & 5 deletions Modules/BlockchainNamespace/Package.swift
@@ -1,10 +1,15 @@
// swift-tools-version:5.5
// swift-tools-version: 5.6

import PackageDescription

let package = Package(
name: "BlockchainNamespace",
platforms: [.iOS(.v14), .macOS(.v11)],
platforms: [
.iOS(.v14),
.macOS(.v11),
.watchOS(.v7),
.tvOS(.v14)
],
products: [
.library(
name: "BlockchainNamespace",
Expand All @@ -20,9 +25,11 @@ let package = Package(
)
],
dependencies: [
.package(url: "https://github.com/screensailor/Lexicon", .revision("160c4c417f8490658a8396d0283fb0d6fb98c327")),
.package(
name: "swift-algorithms",
url: "https://github.com/screensailor/Lexicon",
revision: "160c4c417f8490658a8396d0283fb0d6fb98c327"
),
.package(
url: "https://github.com/apple/swift-algorithms.git",
from: "1.0.0"
)
Expand All @@ -38,9 +45,9 @@ let package = Package(
.target(
name: "BlockchainNamespace",
dependencies: [
.product(name: "Algorithms", package: "swift-algorithms"),
.target(name: "AnyCoding"),
.target(name: "FirebaseProtocol"),
.product(name: "Algorithms", package: "swift-algorithms"),
.product(name: "Lexicon", package: "Lexicon")
],
resources: [
Expand Down
Expand Up @@ -91,11 +91,13 @@ final class BitcoinCashCryptoAccount: BitcoinChainCryptoAccount {
.eraseToAnyPublisher()
}

var activity: Single<[ActivityItemEvent]> {
Single.zip(nonCustodialActivity, swapActivity.asSingle())
var activity: AnyPublisher<[ActivityItemEvent], Error> {
nonCustodialActivity.zip(swapActivity)
.map { nonCustodialActivity, swapActivity in
Self.reconcile(swapEvents: swapActivity, noncustodial: nonCustodialActivity)
}
.eraseError()
.eraseToAnyPublisher()
}

private var isInterestTransferAvailable: AnyPublisher<Bool, Never> {
Expand All @@ -111,14 +113,15 @@ final class BitcoinCashCryptoAccount: BitcoinChainCryptoAccount {
.eraseToAnyPublisher()
}

private var nonCustodialActivity: Single<[TransactionalActivityItemEvent]> {
private var nonCustodialActivity: AnyPublisher<[TransactionalActivityItemEvent], Never> {
transactionsService
.transactions(publicKeys: [xPub])
.map { response in
response
.map(\.activityItemEvent)
}
.catchAndReturn([])
.replaceError(with: [])
.eraseToAnyPublisher()
}

private var swapActivity: AnyPublisher<[SwapActivityItemEvent], Never> {
Expand Down
Expand Up @@ -29,8 +29,8 @@ final class BitcoinCashActivityItemEventDetailsFetcher: ActivityItemEventDetails
.map { accounts -> [XPub] in
accounts.map(\.publicKey)
}
.asSingle()
.flatMap { [transactionsService] publicKeys -> Single<BitcoinCashActivityItemEventDetails> in
.eraseError()
.flatMap { [transactionsService] publicKeys in
transactionsService
.transaction(publicKeys: publicKeys, identifier: identifier)
.map(BitcoinCashActivityItemEventDetails.init(transaction:))
Expand Down
@@ -1,14 +1,15 @@
// Copyright © Blockchain Luxembourg S.A. All rights reserved.

import BitcoinChainKit
import Combine
import DIKit
import Errors
import PlatformKit
import RxSwift
import ToolKit

protocol BitcoinCashHistoricalTransactionServiceAPI: AnyObject {
func transactions(publicKeys: [XPub]) -> Single<[BitcoinCashHistoricalTransaction]>
func transaction(publicKeys: [XPub], identifier: String) -> Single<BitcoinCashHistoricalTransaction>
func transactions(publicKeys: [XPub]) -> AnyPublisher<[BitcoinCashHistoricalTransaction], NetworkError>
func transaction(publicKeys: [XPub], identifier: String) -> AnyPublisher<BitcoinCashHistoricalTransaction, Error>
}

final class BitcoinCashHistoricalTransactionService: BitcoinCashHistoricalTransactionServiceAPI {
Expand All @@ -18,36 +19,45 @@ final class BitcoinCashHistoricalTransactionService: BitcoinCashHistoricalTransa
}

private let client: APIClientAPI
private let cache: Cache<[XPub], [BitcoinCashHistoricalTransaction]>
private let cachedValue: CachedValueNew<
Set<XPub>,
[BitcoinCashHistoricalTransaction],
NetworkError
>

init(with client: APIClientAPI = resolve()) {
self.client = client
cache = .init(entryLifetime: 60)
let cache: AnyCache<Set<XPub>, [BitcoinCashHistoricalTransaction]> = InMemoryCache(
configuration: .onLoginLogoutTransaction(),
refreshControl: PeriodicCacheRefreshControl(refreshInterval: 60)
).eraseToAnyCache()
cachedValue = CachedValueNew(
cache: cache,
fetch: { [client] xPubs in
client
.multiAddress(for: Array(xPubs))
.map(\.transactions)
.eraseToAnyPublisher()
}
)
}

func transactions(publicKeys: [XPub]) -> Single<[BitcoinCashHistoricalTransaction]> {
guard let response = cache.value(forKey: publicKeys) else {
return client
.multiAddress(for: publicKeys)
.map(\.transactions)
.asSingle()
.do(onSuccess: { [cache] transactions in
cache.set(transactions, forKey: publicKeys)
})
}
return .just(response)
func transactions(publicKeys: [XPub]) -> AnyPublisher<[BitcoinCashHistoricalTransaction], NetworkError> {
cachedValue
.get(key: Set(publicKeys))
}

// It is not possible to fetch a specific transaction detail from 'multiaddr' endpoints,
// so we fetch the first page and filter out the transaction from there.
// This may cause a edge case where a user opens the last transaction of the list, but
// in the mean time there was a new transaction added, making it 'drop' out of the first
// page. The fix for this is to have a properly paginated multiaddr/details endpoint.
func transaction(publicKeys: [XPub], identifier: String) -> Single<BitcoinCashHistoricalTransaction> {
func transaction(publicKeys: [XPub], identifier: String) -> AnyPublisher<BitcoinCashHistoricalTransaction, Error> {
transactions(publicKeys: publicKeys)
.map { items -> BitcoinCashHistoricalTransaction? in
items.first { $0.identifier == identifier }
}
.onNil(error: ServiceError.errorFetchingDetails)
.eraseError()
.onNil(ServiceError.errorFetchingDetails)
}
}

0 comments on commit 53202b6

Please sign in to comment.