149 lines
No EOL
6.8 KiB
Kotlin
149 lines
No EOL
6.8 KiB
Kotlin
package com.tangem.tap.domain
|
|
|
|
import com.tangem.blockchain.common.BlockchainSdkConfig
|
|
import com.tangem.blockchain.common.Token
|
|
import com.tangem.blockchain.common.Wallet
|
|
import com.tangem.blockchain.common.WalletManagerFactory
|
|
import com.tangem.common.doOnFailure
|
|
import com.tangem.common.doOnSuccess
|
|
import com.tangem.core.analytics.Analytics
|
|
import com.tangem.datasource.config.ConfigManager
|
|
import com.tangem.domain.common.extensions.withMainContext
|
|
import com.tangem.domain.common.util.cardTypesResolver
|
|
import com.tangem.domain.models.scan.ScanResponse
|
|
import com.tangem.domain.wallets.models.UserWallet
|
|
import com.tangem.operations.attestation.Attestation
|
|
import com.tangem.tap.*
|
|
import com.tangem.tap.common.analytics.events.Basic
|
|
import com.tangem.tap.common.extensions.dispatchOnMain
|
|
import com.tangem.tap.common.extensions.dispatchWithMain
|
|
import com.tangem.tap.common.extensions.setContext
|
|
import com.tangem.tap.common.redux.global.GlobalAction
|
|
import com.tangem.tap.domain.walletStores.WalletStoresError
|
|
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
|
|
import com.tangem.tap.features.disclaimer.createDisclaimer
|
|
import com.tangem.tap.features.disclaimer.redux.DisclaimerAction
|
|
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction
|
|
import com.tangem.tap.features.wallet.redux.WalletAction
|
|
import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider
|
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.Job
|
|
import kotlinx.coroutines.launch
|
|
import timber.log.Timber
|
|
|
|
class TapWalletManager(
|
|
private val dispatchers: CoroutineDispatcherProvider = AppCoroutineDispatcherProvider(),
|
|
) {
|
|
|
|
private val blockchainSdkConfig by lazy {
|
|
store.state.globalState.configManager?.config?.blockchainSdkConfig ?: BlockchainSdkConfig()
|
|
}
|
|
|
|
private var loadUserWalletDataJob: Job? = null
|
|
set(value) {
|
|
field?.cancel()
|
|
field = value
|
|
}
|
|
|
|
val walletManagerFactory: WalletManagerFactory
|
|
by lazy { WalletManagerFactory(blockchainSdkConfig) }
|
|
|
|
suspend fun onWalletSelected(userWallet: UserWallet, refresh: Boolean, sendAnalyticsEvent: Boolean) {
|
|
// If a previous job was running, it gets cancelled before the new one starts,
|
|
// ensuring that only one job is active at any given time.
|
|
loadUserWalletDataJob = CoroutineScope(dispatchers.io)
|
|
.launch { loadUserWalletData(userWallet, refresh, sendAnalyticsEvent) }
|
|
.also { it.join() }
|
|
}
|
|
|
|
private suspend fun loadUserWalletData(userWallet: UserWallet, refresh: Boolean, sendAnalyticsEvent: Boolean) {
|
|
Analytics.setContext(userWallet.scanResponse)
|
|
if (sendAnalyticsEvent) {
|
|
Analytics.send(Basic.WalletOpened())
|
|
}
|
|
val scanResponse = userWallet.scanResponse
|
|
val card = scanResponse.card
|
|
val attestationFailed = card.attestation.status == Attestation.Status.Failed
|
|
|
|
tangemSdkManager.changeDisplayedCardIdNumbersCount(scanResponse)
|
|
store.state.globalState.feedbackManager?.infoHolder?.setCardInfo(scanResponse)
|
|
updateConfigManager(scanResponse)
|
|
withMainContext {
|
|
// Order is important
|
|
store.dispatch(DisclaimerAction.SetDisclaimer(card.createDisclaimer()))
|
|
store.dispatch(WalletAction.UserWalletChanged(userWallet))
|
|
store.dispatch(WalletAction.UpdateCanSaveUserWallets(preferencesStorage.shouldSaveUserWallets))
|
|
store.dispatch(TwinCardsAction.IfTwinsPrepareState(scanResponse))
|
|
store.dispatch(WalletConnectAction.ResetState)
|
|
store.dispatch(GlobalAction.SaveScanResponse(scanResponse))
|
|
store.dispatch(WalletConnectAction.RestoreSessions(scanResponse))
|
|
store.dispatch(GlobalAction.SetIfCardVerifiedOnline(!attestationFailed))
|
|
store.dispatch(WalletAction.Warnings.CheckIfNeeded)
|
|
}
|
|
setupWalletConnectV2(userWallet)
|
|
loadData(userWallet, refresh)
|
|
}
|
|
|
|
private fun setupWalletConnectV2(userWallet: UserWallet) {
|
|
val cardId = if (userWallet.scanResponse.card.backupStatus?.isActive != true) {
|
|
userWallet.cardId
|
|
} else { // if wallet has backup, any card from wallet can be used to sign
|
|
null
|
|
}
|
|
scope.launch {
|
|
store.state.daggerGraphState.walletConnectInteractor?.startListening(
|
|
userWalletId = userWallet.walletId.stringValue,
|
|
cardId = cardId,
|
|
)
|
|
}
|
|
}
|
|
|
|
suspend fun loadData(userWallet: UserWallet, refresh: Boolean = false) {
|
|
walletStoresManager.fetch(userWallet, refresh)
|
|
.doOnSuccess {
|
|
Timber.d("Wallet stores fetched for ${userWallet.walletId}")
|
|
store.dispatchOnMain(WalletAction.LoadData.Success)
|
|
store.state.globalState.topUpController?.loadDataSuccess()
|
|
store.dispatchWithMain(WalletAction.Warnings.CheckHashesCount.VerifyOnlineIfNeeded)
|
|
}
|
|
.doOnFailure { error ->
|
|
val errorAction = when (error) {
|
|
is WalletStoresError -> when (error) {
|
|
is WalletStoresError.FetchFiatRatesError -> WalletAction.LoadData.Failure(error = null)
|
|
is WalletStoresError.UpdateWalletManagerTokensError -> WalletAction.LoadData.Failure(
|
|
error = TapError.WalletManager.InternalError(
|
|
message = error.cause.localizedMessage ?: error.customMessage,
|
|
),
|
|
)
|
|
is WalletStoresError.WalletManagerNotCreated -> WalletAction.LoadData.Failure(
|
|
error = TapError.WalletManager.CreationError,
|
|
)
|
|
is WalletStoresError.UnknownBlockchain -> WalletAction.LoadData.Failure(
|
|
error = TapError.UnknownBlockchain,
|
|
)
|
|
is WalletStoresError.NoInternetConnection -> WalletAction.LoadData.Failure(
|
|
error = TapError.NoInternetConnection,
|
|
)
|
|
}
|
|
else -> WalletAction.LoadData.Failure(error = null)
|
|
}
|
|
|
|
Timber.e(error, "Wallet stores fetching failed for ${userWallet.walletId}")
|
|
|
|
store.dispatchOnMain(errorAction)
|
|
}
|
|
}
|
|
|
|
fun updateConfigManager(data: ScanResponse) {
|
|
val configManager = store.state.globalState.configManager
|
|
|
|
if (data.cardTypesResolver.isStart2Coin()) {
|
|
configManager?.turnOff(ConfigManager.IS_TOP_UP_ENABLED)
|
|
} else {
|
|
configManager?.resetToDefault(ConfigManager.IS_TOP_UP_ENABLED)
|
|
}
|
|
}
|
|
}
|
|
|
|
fun Wallet.getFirstToken(): Token? = getTokens().toList().getOrNull(index = 0) |