Skip to content

Commit

Permalink
Merge pull request #3134 from tangem/IOS-5193_refactor_scanner
Browse files Browse the repository at this point in the history
IOS-5193 Refactor scanning
  • Loading branch information
tureck1y authored Apr 16, 2024
2 parents 4408339 + d92dd69 commit 3f5e7c9
Show file tree
Hide file tree
Showing 20 changed files with 262 additions and 65 deletions.
2 changes: 1 addition & 1 deletion Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use_frameworks!
inhibit_all_warnings!

def tangem_sdk_pod
pod 'TangemSdk', :git => 'https://github.com/Tangem/tangem-sdk-ios.git', :tag => 'develop-286'
pod 'TangemSdk', :git => 'https://github.com/Tangem/tangem-sdk-ios.git', :tag => 'develop-287'
#pod 'TangemSdk', :path => '../tangem-sdk-ios'
end

Expand Down
8 changes: 4 additions & 4 deletions Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ DEPENDENCIES:
- Kingfisher (~> 7.9.0)
- Moya
- Solana.Swift (from `https://github.com/tangem/Solana.Swift`, tag `1.2.0-tangem5`)
- TangemSdk (from `https://github.com/Tangem/tangem-sdk-ios.git`, tag `develop-286`)
- TangemSdk (from `https://github.com/Tangem/tangem-sdk-ios.git`, tag `develop-287`)
- WalletConnectSwiftV2 (from `https://github.com/WalletConnect/WalletConnectSwiftV2`, tag `1.8.4`)

SPEC REPOS:
Expand Down Expand Up @@ -283,7 +283,7 @@ EXTERNAL SOURCES:
:tag: 1.2.0-tangem5
TangemSdk:
:git: https://github.com/Tangem/tangem-sdk-ios.git
:tag: develop-286
:tag: develop-287
WalletConnectSwiftV2:
:git: https://github.com/WalletConnect/WalletConnectSwiftV2
:tag: 1.8.4
Expand All @@ -306,7 +306,7 @@ CHECKOUT OPTIONS:
:tag: 1.2.0-tangem5
TangemSdk:
:git: https://github.com/Tangem/tangem-sdk-ios.git
:tag: develop-286
:tag: develop-287
WalletConnectSwiftV2:
:git: https://github.com/WalletConnect/WalletConnectSwiftV2
:tag: 1.8.4
Expand Down Expand Up @@ -353,6 +353,6 @@ SPEC CHECKSUMS:
TweetNacl: 3abf4d1d2082b0114e7a67410e300892448951e6
WalletConnectSwiftV2: c1c2c2fbd0495860baf71515be1b943f0c5dce0c

PODFILE CHECKSUM: 9273bb591099a90fdb1441fc62bae396bf3f6a17
PODFILE CHECKSUM: ee5d8c57b7a9691ef7c2d62484eec83355e27f07

COCOAPODS: 1.15.2
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import TangemSdk
struct OnboardingInput { // TODO: Split to coordinator options and input
let backupService: BackupService
let primaryCardId: String
let cardInitializer: CardInitializable?
let cardInitializer: CardInitializer?
let steps: OnboardingSteps
let cardInput: CardInput
let twinData: TwinData?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ class CommonUserWalletRepository: UserWalletRepository {

private let minimizedAppTimer = MinimizedAppTimer(interval: 5 * 60)

private var sdk: TangemSdk?

private var bag: Set<AnyCancellable> = .init()

init() {
Expand All @@ -83,7 +81,26 @@ class CommonUserWalletRepository: UserWalletRepository {
}

private func scanPublisher() -> AnyPublisher<UserWalletRepositoryResult?, Never> {
scanInternal()
var config = TangemSdkConfigFactory().makeDefaultConfig()

if AppSettings.shared.saveUserWallets {
config.accessCodeRequestPolicy = .alwaysWithBiometrics
}

let scannerParameters = CardScannerParameters(
shouldAskForAccessCodes: false,
performDerivations: true,
sessionFilter: nil
)

let scanner = CommonCardScanner(
tangemSdk: TangemSdkDefaultFactory().makeTangemSdk(with: config),
parameters: scannerParameters
)

sendEvent(.scan(isScanning: true))

return scanner.scanCardPublisher()
.eraseError()
.flatMap { [weak self] response -> AnyPublisher<UserWalletRepositoryResult?, Error> in
guard let self else {
Expand Down Expand Up @@ -142,22 +159,9 @@ class CommonUserWalletRepository: UserWalletRepository {
return Just(nil)
}
}
.eraseToAnyPublisher()
}

private func scanInternal() -> AnyPublisher<AppScanTaskResponse, TangemSdkError> {
var config = TangemSdkConfigFactory().makeDefaultConfig()

if AppSettings.shared.saveUserWallets {
config.accessCodeRequestPolicy = .alwaysWithBiometrics
}

let sdk = TangemSdkDefaultFactory().makeTangemSdk(with: config)
self.sdk = sdk
sendEvent(.scan(isScanning: true))

return sdk
.startSessionPublisher(with: AppScanTask())
.handleEvents(receiveCompletion: { _ in
withExtendedLifetime(scanner) {}
})
.eraseToAnyPublisher()
}

Expand Down
15 changes: 15 additions & 0 deletions Tangem/Common/TangemSdk/CardInitializer/CardInitializer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// CardInitializer.swift
// Tangem
//
// Created by Alexander Osokin on 11.04.2024.
// Copyright © 2024 Tangem AG. All rights reserved.
//

import Foundation
import TangemSdk

protocol CardInitializer {
var shouldReset: Bool { get set }
func initializeCard(mnemonic: Mnemonic?, passphrase: String?, completion: @escaping (Result<CardInfo, TangemSdkError>) -> Void)
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@
//
// CardInitializer.swift
// CommonCardInitializer.swift
// Tangem
//
// Created by Alexander Osokin on 22.05.2023.
// Copyright © 2023 Tangem AG. All rights reserved.
// Copyright © 2024 Tangem AG. All rights reserved.
//

import Foundation
import Combine
import CombineExt
import TangemSdk

protocol CardInitializable {
var shouldReset: Bool { get set }
func initializeCard(mnemonic: Mnemonic?, passphrase: String?, completion: @escaping (Result<CardInfo, TangemSdkError>) -> Void)
}

class CardInitializer {
class CommonCardInitializer {
var shouldReset: Bool = false

private let tangemSdk: TangemSdk
private var cardInfo: CardInfo
private var runnableBag: (any CardSessionRunnable)?
private var cancellable: AnyCancellable?

internal init(tangemSdk: TangemSdk, cardInfo: CardInfo) {
Expand All @@ -30,12 +23,11 @@ class CardInitializer {
}
}

extension CardInitializer: CardInitializable {
extension CommonCardInitializer: CardInitializer {
func initializeCard(mnemonic: Mnemonic?, passphrase: String?, completion: @escaping (Result<CardInfo, TangemSdkError>) -> Void) {
let config = UserWalletConfigFactory(cardInfo).makeConfig()
let task = PreparePrimaryCardTask(curves: config.mandatoryCurves, mnemonic: mnemonic, passphrase: passphrase, shouldReset: shouldReset)
let initialMessage = Message(header: nil, body: Localization.initialMessageCreateWalletBody)
runnableBag = task

// Ring onboarding. Set custom image
if let customOnboardingImage = config.customScanImage {
Expand All @@ -61,9 +53,6 @@ extension CardInitializer: CardInitializable {
return mutableCardInfo
}
.sink(receiveCompletion: { [weak self] completionResult in
self?.runnableBag = nil
self?.cancellable = nil

// Ring onboarding. Reset the image
self?.tangemSdk.config.style.scanTagImage = .genericCard

Expand All @@ -76,6 +65,9 @@ extension CardInitializer: CardInitializable {
case .failure(let error):
completion(.failure(error))
}

withExtendedLifetime(task) {}
self?.cancellable = nil
}, receiveValue: { [weak self] newCardInfo in
self?.cardInfo = newCardInfo
})
Expand Down
21 changes: 21 additions & 0 deletions Tangem/Common/TangemSdk/CardScanner/CardScanner.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// CardScanner.swift
// Tangem
//
// Created by Alexander Osokin on 11.04.2024.
// Copyright © 2024 Tangem AG. All rights reserved.
//

import Foundation
import Combine
import TangemSdk

protocol CardScanner {
init(
tangemSdk: TangemSdk,
parameters: CardScannerParameters
)

func scanCard(completion: @escaping (Result<AppScanTaskResponse, TangemSdkError>) -> Void)
func scanCardPublisher() -> AnyPublisher<AppScanTaskResponse, TangemSdkError>
}
16 changes: 16 additions & 0 deletions Tangem/Common/TangemSdk/CardScanner/CardScannerParameters.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// CardScannerParameters.swift
// Tangem
//
// Created by Alexander Osokin on 12.04.2024.
// Copyright © 2024 Tangem AG. All rights reserved.
//

import Foundation
import TangemSdk

struct CardScannerParameters {
let shouldAskForAccessCodes: Bool
let performDerivations: Bool
let sessionFilter: SessionFilter?
}
62 changes: 62 additions & 0 deletions Tangem/Common/TangemSdk/CardScanner/CommonCardScanner.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// CommonCardScanner.swift
// Tangem
//
// Created by Alexander Osokin on 11.04.2024.
// Copyright © 2024 Tangem AG. All rights reserved.
//

import Foundation
import Combine
import CombineExt
import TangemSdk

class CommonCardScanner: CardScanner {
private let tangemSdk: TangemSdk
private let parameters: CardScannerParameters
private var cancellable: AnyCancellable?

required init(
tangemSdk: TangemSdk,
parameters: CardScannerParameters
) {
self.tangemSdk = tangemSdk
self.parameters = parameters
}

func scanCardPublisher() -> AnyPublisher<AppScanTaskResponse, TangemSdkError> {
let task = AppScanTask(
shouldAskForAccessCode: parameters.shouldAskForAccessCodes,
performDerivations: parameters.performDerivations
)

let didBecomeActivePublisher = NotificationCenter.didBecomeActivePublisher
.mapError { $0.toTangemSdkError() }
.mapToVoid()
.first()

return tangemSdk.startSessionPublisher(with: task, filter: parameters.sessionFilter)
.combineLatest(didBecomeActivePublisher)
.map { $0.0 }
.handleEvents(receiveCompletion: { _ in
withExtendedLifetime(task) {}
})
.eraseToAnyPublisher()
}

func scanCard(completion: @escaping (Result<AppScanTaskResponse, TangemSdkError>) -> Void) {
cancellable = scanCardPublisher()
.sink(receiveCompletion: { [weak self] completionResult in
switch completionResult {
case .finished:
break
case .failure(let error):
completion(.failure(error))
}

self?.cancellable = nil
}, receiveValue: {
completion(.success($0))
})
}
}
11 changes: 9 additions & 2 deletions Tangem/Common/TangemSdk/Tasks/AppScanTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,17 @@ struct AppScanTaskResponse {
final class AppScanTask: CardSessionRunnable {
let shouldAskForAccessCode: Bool

private let performDerivations: Bool
private var walletData: DefaultWalletData = .none
private var primaryCard: PrimaryCard?
private var linkingCommand: StartPrimaryCardLinkingCommand?

init(shouldAskForAccessCode: Bool = false) {
init(
shouldAskForAccessCode: Bool = false,
performDerivations: Bool = true
) {
self.shouldAskForAccessCode = shouldAskForAccessCode
self.performDerivations = performDerivations
}

deinit {
Expand Down Expand Up @@ -215,7 +220,9 @@ final class AppScanTask: CardSessionRunnable {
return
}

guard !plainCard.wallets.isEmpty, plainCard.settings.isHDWalletAllowed else {
guard performDerivations,
!plainCard.wallets.isEmpty,
plainCard.settings.isHDWalletAllowed else {
runScanTask(session, completion)
return
}
Expand Down
5 changes: 2 additions & 3 deletions Tangem/Modules/Details/DetailsCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import Foundation
import UIKit
import TangemSdk

class DetailsCoordinator: CoordinatorObject {
// MARK: - Dependencies
Expand Down Expand Up @@ -91,8 +90,8 @@ extension DetailsCoordinator: DetailsRoutable {
disclaimerViewModel = .init(url: url, style: .details)
}

func openScanCardSettings(with sessionFilter: SessionFilter, sdk: TangemSdk) {
scanCardSettingsViewModel = ScanCardSettingsViewModel(sessionFilter: sessionFilter, sdk: sdk, coordinator: self)
func openScanCardSettings(with cardScanner: CardScanner) {
scanCardSettingsViewModel = ScanCardSettingsViewModel(cardScanner: cardScanner, coordinator: self)
}

func openAppSettings() {
Expand Down
3 changes: 1 addition & 2 deletions Tangem/Modules/Details/DetailsRoutable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@
//

import Foundation
import TangemSdk

protocol DetailsRoutable: AnyObject {
func openOnboardingModal(with input: OnboardingInput)
func openMail(with dataCollector: EmailDataCollector, recipient: String, emailType: EmailType)
func openWalletConnect(with disabledLocalizedReason: String?)
func openDisclaimer(at url: URL)
func openScanCardSettings(with sessionFilter: SessionFilter, sdk: TangemSdk)
func openScanCardSettings(with cardScanner: CardScanner)
func openAppSettings()
func openSupportChat(input: SupportChatInputModel)
func openInSafari(url: URL)
Expand Down
15 changes: 13 additions & 2 deletions Tangem/Modules/Details/DetailsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import Foundation
import SwiftUI
import Combine
import TangemSdk
import BlockchainSdk

class DetailsViewModel: ObservableObject {
Expand Down Expand Up @@ -115,7 +114,19 @@ extension DetailsViewModel {

func openCardSettings() {
Analytics.log(.buttonCardSettings)
coordinator?.openScanCardSettings(with: userWalletModel.config.cardSessionFilter, sdk: userWalletModel.config.makeTangemSdk()) // TODO: refactor.

let scanParameters = CardScannerParameters(
shouldAskForAccessCodes: true,
performDerivations: false,
sessionFilter: userWalletModel.config.cardSessionFilter
)

let scanner = CommonCardScanner(
tangemSdk: userWalletModel.config.makeTangemSdk(),
parameters: scanParameters
)

coordinator?.openScanCardSettings(with: scanner)
}

func openAppSettings() {
Expand Down
Loading

0 comments on commit 3f5e7c9

Please sign in to comment.