Updated on 2026-08-14
This commit is contained in:
parent
e561cac009
commit
c28d80cb18
91 changed files with 178 additions and 5792 deletions
|
|
@ -4,39 +4,27 @@ 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.toNetworkId
|
||||
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.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.walletStores.WalletStoresError
|
||||
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.Account
|
||||
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.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
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 org.rekotlin.Store
|
||||
import timber.log.Timber
|
||||
|
||||
class TapWalletManager(
|
||||
private val dispatchers: CoroutineDispatcherProvider = AppCoroutineDispatcherProvider(),
|
||||
|
|
@ -55,15 +43,15 @@ class TapWalletManager(
|
|||
val walletManagerFactory: WalletManagerFactory
|
||||
by lazy { WalletManagerFactory(blockchainSdkConfig) }
|
||||
|
||||
suspend fun onWalletSelected(userWallet: UserWallet, refresh: Boolean, sendAnalyticsEvent: Boolean) {
|
||||
suspend fun onWalletSelected(userWallet: UserWallet, 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) }
|
||||
.launch { loadUserWalletData(userWallet, sendAnalyticsEvent) }
|
||||
.also { it.join() }
|
||||
}
|
||||
|
||||
private suspend fun loadUserWalletData(userWallet: UserWallet, refresh: Boolean, sendAnalyticsEvent: Boolean) {
|
||||
private suspend fun loadUserWalletData(userWallet: UserWallet, sendAnalyticsEvent: Boolean) {
|
||||
Analytics.setContext(userWallet.scanResponse)
|
||||
if (sendAnalyticsEvent) {
|
||||
Analytics.send(Basic.WalletOpened())
|
||||
|
|
@ -78,114 +66,11 @@ class TapWalletManager(
|
|||
withMainContext {
|
||||
// Order is important
|
||||
store.dispatch(DisclaimerAction.SetDisclaimer(card.createDisclaimer()))
|
||||
store.dispatchWalletAction(action = WalletAction.UserWalletChanged(userWallet))
|
||||
store.dispatchWalletAction(
|
||||
action = WalletAction.UpdateCanSaveUserWallets(
|
||||
canSaveUserWallets = store.state.daggerGraphState.get(DaggerGraphState::walletsRepository)
|
||||
.shouldSaveUserWalletsSync(),
|
||||
),
|
||||
)
|
||||
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.dispatchWalletAction(action = WalletAction.Warnings.CheckIfNeeded)
|
||||
}
|
||||
|
||||
val walletFeatureToggles = store.state.daggerGraphState.get(DaggerGraphState::walletFeatureToggles)
|
||||
if (!walletFeatureToggles.isRedesignedScreenEnabled) {
|
||||
setupWalletConnectV2(userWallet)
|
||||
loadData(userWallet = userWallet, refresh = refresh)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Store<AppState>.dispatchWalletAction(action: WalletAction) {
|
||||
val walletFeatureToggles = state.daggerGraphState.get(DaggerGraphState::walletFeatureToggles)
|
||||
|
||||
if (!walletFeatureToggles.isRedesignedScreenEnabled) {
|
||||
dispatch(action = action)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
val wcInteractor = store.state.daggerGraphState.walletConnectInteractor ?: return@launch
|
||||
wcInteractor.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)
|
||||
|
||||
val wcInteractor = store.state.daggerGraphState.walletConnectInteractor
|
||||
wcInteractor?.setUserChains(getAccountsForWc(wcInteractor))
|
||||
}
|
||||
.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)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getAccountsForWc(wcInteractor: WalletConnectInteractor): List<Account> {
|
||||
val walletManagerToggles = store.state.daggerGraphState
|
||||
.get(DaggerGraphState::walletFeatureToggles)
|
||||
val walletManagers = if (walletManagerToggles.isRedesignedScreenEnabled) {
|
||||
val walletManagerFacade = store.state.daggerGraphState
|
||||
.get(DaggerGraphState::walletManagersFacade)
|
||||
val userWallet = userWalletsListManager.selectedUserWalletSync ?: return emptyList()
|
||||
walletManagerFacade.getStoredWalletManagers(userWallet.walletId)
|
||||
} else {
|
||||
store.state.walletState.walletManagers
|
||||
}
|
||||
|
||||
return walletManagers.mapNotNull {
|
||||
val wallet = it.wallet
|
||||
val chainId = wcInteractor.blockchainHelper.networkIdToChainIdOrNull(
|
||||
wallet.blockchain.toNetworkId(),
|
||||
)
|
||||
chainId?.let {
|
||||
Account(
|
||||
chainId,
|
||||
wallet.address,
|
||||
wallet.publicKey.derivationPath?.rawPath,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ import com.tangem.domain.common.BlockchainNetwork
|
|||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.common.util.derivationStyleProvider
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.tap.common.extensions.createAddressesData
|
||||
import com.tangem.tap.domain.model.WalletDataModel
|
||||
import com.tangem.tap.domain.model.WalletStoreModel
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.redux.reducers.createAddressesData
|
||||
import java.math.BigDecimal
|
||||
|
||||
interface WalletStoreBuilder {
|
||||
|
|
|
|||
|
|
@ -1,68 +0,0 @@
|
|||
package com.tangem.tap.domain.statePrinter
|
||||
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.common.json.MoshiJsonConverter
|
||||
import com.tangem.domain.redux.state.StringStateConverter
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.store
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class WalletStateConverter : StringStateConverter<AppState> {
|
||||
private val converter = MoshiJsonConverter.INSTANCE
|
||||
|
||||
override fun convert(stateHolder: AppState): String {
|
||||
val walletState = stateHolder.walletState
|
||||
|
||||
val walletManagers = mutableListOf<Map<String, Any?>>()
|
||||
walletState.walletManagers.forEach {
|
||||
val wallet = it.wallet
|
||||
|
||||
val walletManagerMap = mutableMapOf<String, Any?>()
|
||||
walletManagerMap["walletManager"] = mapOf<String, Any>(
|
||||
"wallet" to convertWallet(it.wallet),
|
||||
)
|
||||
|
||||
walletManagers.add(walletManagerMap)
|
||||
}
|
||||
val json = converter.prettyPrint(walletManagers)
|
||||
return json
|
||||
}
|
||||
|
||||
private fun convertWallet(wallet: Wallet): MutableMap<String, Any> {
|
||||
val walletMap = mutableMapOf<String, Any>()
|
||||
val amounts = mutableMapOf<String, Any>()
|
||||
wallet.amounts.forEach { (type, amount) ->
|
||||
val amountMap = mapOf<String, Any?>(
|
||||
"value" to amount.value?.toPlainString(),
|
||||
"currencySymbol" to amount.currencySymbol,
|
||||
"decimals" to amount.decimals,
|
||||
"type" to amount.type::class.java.simpleName,
|
||||
)
|
||||
amounts[type::class.java.simpleName] = amountMap
|
||||
}
|
||||
|
||||
val publicKeyMap = mapOf(
|
||||
"seedKey" to wallet.publicKey.seedKey,
|
||||
"derivedKey" to wallet.publicKey.derivedKey,
|
||||
"derivationPath" to wallet.publicKey.derivationPath?.rawPath,
|
||||
"blockchainKey" to wallet.publicKey.blockchainKey,
|
||||
)
|
||||
|
||||
walletMap["address"] = wallet.address
|
||||
walletMap["blockchain"] = wallet.blockchain.name
|
||||
walletMap["curve"] = wallet.blockchain.getSupportedCurves()[0].curve
|
||||
walletMap["publicKey"] = publicKeyMap
|
||||
walletMap["amounts"] = amounts
|
||||
walletMap["addresses"] = wallet.addresses.toString()
|
||||
|
||||
return walletMap
|
||||
}
|
||||
}
|
||||
|
||||
fun printWalletState() {
|
||||
val stringState = WalletStateConverter().convert(store.state)
|
||||
Timber.d(stringState)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue