Updated on 2026-08-14
This commit is contained in:
parent
ddf5f8af9f
commit
6558188794
10 changed files with 0 additions and 242 deletions
|
|
@ -46,7 +46,6 @@ import com.tangem.tap.common.analytics.handlers.BlockchainExceptionHandler
|
|||
import com.tangem.tap.common.analytics.handlers.amplitude.AmplitudeAnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.handlers.appsFlyer.AppsFlyerAnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.topup.TopUpController
|
||||
import com.tangem.tap.common.chat.ChatManager
|
||||
import com.tangem.tap.common.feedback.AdditionalFeedbackInfo
|
||||
import com.tangem.tap.common.feedback.FeedbackManager
|
||||
|
|
@ -61,8 +60,6 @@ import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
|
|||
import com.tangem.tap.domain.tasks.product.DerivationsFinder
|
||||
import com.tangem.tap.domain.tokens.UserTokensRepository
|
||||
import com.tangem.tap.domain.tokens.UserTokensStorageService
|
||||
import com.tangem.tap.domain.totalBalance.TotalFiatBalanceCalculator
|
||||
import com.tangem.tap.domain.totalBalance.di.provideDefaultImplementation
|
||||
import com.tangem.tap.domain.userWalletList.di.provideBiometricImplementation
|
||||
import com.tangem.tap.domain.userWalletList.di.provideRuntimeImplementation
|
||||
import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager
|
||||
|
|
@ -132,9 +129,6 @@ val walletCurrenciesManager by lazy {
|
|||
appCurrencyProvider = { store.state.globalState.appCurrency },
|
||||
)
|
||||
}
|
||||
val totalFiatBalanceCalculator by lazy {
|
||||
TotalFiatBalanceCalculator.provideDefaultImplementation()
|
||||
}
|
||||
|
||||
@HiltAndroidApp
|
||||
internal class TapApplication : Application(), ImageLoaderFactory {
|
||||
|
|
@ -282,7 +276,6 @@ internal class TapApplication : Application(), ImageLoaderFactory {
|
|||
appStateHolder.userTokensRepository = userTokensRepository
|
||||
appStateHolder.walletStoresManager = walletStoresManager
|
||||
|
||||
initTopUpController()
|
||||
walletConnect2Repository.init(projectId = configManager.config.walletConnectProjectId)
|
||||
}
|
||||
|
||||
|
|
@ -315,18 +308,6 @@ internal class TapApplication : Application(), ImageLoaderFactory {
|
|||
)
|
||||
}
|
||||
|
||||
private fun initTopUpController() {
|
||||
val topUpController = TopUpController(
|
||||
scanResponseProvider = {
|
||||
store.state.globalState.scanResponse
|
||||
?: store.state.globalState.onboardingState.onboardingManager?.scanResponse
|
||||
},
|
||||
walletStoresManagerProvider = { walletStoresManager },
|
||||
topupWalletStorage = preferencesStorage.toppedUpWalletStorage,
|
||||
)
|
||||
store.dispatch(GlobalAction.SetTopUpController(topUpController))
|
||||
}
|
||||
|
||||
override fun newImageLoader(): ImageLoader {
|
||||
return createCoilImageLoader(
|
||||
context = this,
|
||||
|
|
|
|||
|
|
@ -1,207 +0,0 @@
|
|||
package com.tangem.tap.common.analytics.topup
|
||||
|
||||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.data.source.preferences.model.DataSourceTopupInfo
|
||||
import com.tangem.data.source.preferences.storage.ToppedUpWalletStorage
|
||||
import com.tangem.domain.common.BlockchainNetwork
|
||||
import com.tangem.domain.common.CardTypesResolver
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.userwallets.UserWalletIdBuilder
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.tap.common.analytics.converters.TopUpEventConverter
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||
import com.tangem.tap.domain.model.WalletDataModel
|
||||
import com.tangem.tap.domain.model.WalletStoreModel
|
||||
import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager
|
||||
import com.tangem.tap.domain.walletStores.WalletStoresManager
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.utils.extensions.copy
|
||||
import kotlinx.coroutines.launch
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class TopUpController(
|
||||
var scanResponseProvider: (() -> ScanResponse?)? = null,
|
||||
var walletStoresManagerProvider: (() -> WalletStoresManager)? = null,
|
||||
private val topupWalletStorage: ToppedUpWalletStorage,
|
||||
) : WalletCurrenciesManager.Listener {
|
||||
|
||||
private var hadMissedDerivations: Boolean = false
|
||||
private val addedCurrencies = mutableListOf<Currency>()
|
||||
|
||||
override fun didUpdate(userWallet: UserWallet, currency: Currency) {
|
||||
tryToSend()
|
||||
}
|
||||
|
||||
override fun willCurrenciesAdd(userWallet: UserWallet, currenciesToAdd: List<Currency>) {
|
||||
addedCurrencies.addAll(currenciesToAdd.distinct())
|
||||
}
|
||||
|
||||
fun walletStoresChanged(walletStores: List<WalletStoreModel>) {
|
||||
val missedDerivations = walletStores
|
||||
.flatMap { it.walletsData }
|
||||
.map { it.status }
|
||||
.filterIsInstance<WalletDataModel.MissedDerivation>()
|
||||
|
||||
hadMissedDerivations = missedDerivations.isNotEmpty()
|
||||
}
|
||||
|
||||
fun scanToGetDerivations() {
|
||||
hadMissedDerivations = true
|
||||
}
|
||||
|
||||
fun addMissingDerivations(blockchains: List<BlockchainNetwork>) {
|
||||
hadMissedDerivations = blockchains.isNotEmpty()
|
||||
}
|
||||
|
||||
fun totalBalanceStateChanged(totalFiatBalance: TotalFiatBalance) {
|
||||
if (totalFiatBalance is TotalFiatBalance.Loaded) tryToSend()
|
||||
}
|
||||
|
||||
fun loadDataSuccess() {
|
||||
tryToSend()
|
||||
}
|
||||
|
||||
private fun tryToSend() {
|
||||
if (hadMissedDerivations) return
|
||||
val scanResponse = scanResponseProvider?.invoke() ?: return
|
||||
val userWalletId = UserWalletIdBuilder.scanResponse(scanResponse).build() ?: return
|
||||
val walletStoresManager = walletStoresManagerProvider?.invoke() ?: return
|
||||
|
||||
scope.launch {
|
||||
val walletDataModels = walletStoresManager.getSync(userWalletId).flatMap { it.walletsData }
|
||||
if (walletDataModels.isEmpty()) return@launch
|
||||
|
||||
val isCorrectStatus = walletDataModels.any {
|
||||
it.status is WalletDataModel.Loading ||
|
||||
it.status is WalletDataModel.NoAccount ||
|
||||
it.status is WalletDataModel.Unreachable ||
|
||||
it.status is WalletDataModel.MissedDerivation ||
|
||||
it.status.isErrorStatus
|
||||
}
|
||||
if (isCorrectStatus) return@launch
|
||||
|
||||
val isToppedUpInPast = findToppedUpCurrenciesInPast(walletDataModels).isNotEmpty()
|
||||
if (isToppedUpInPast) {
|
||||
val newWalletInfo = DataSourceTopupInfo(
|
||||
walletId = userWalletId.stringValue,
|
||||
cardBalanceState = DataSourceTopupInfo.CardBalanceState.Full,
|
||||
)
|
||||
topupWalletStorage.save(newWalletInfo)
|
||||
return@launch
|
||||
}
|
||||
|
||||
val cardBalanceState = BalanceCalculator(walletDataModels).calculate().toCardBalanceState()
|
||||
send(userWalletId, cardBalanceState, scanResponse.cardTypesResolver)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A UserWalletId registration should be after creating wallets
|
||||
*/
|
||||
fun registerEmptyWallet(scanResponse: ScanResponse) {
|
||||
UserWalletIdBuilder.scanResponse(scanResponse).build()?.let {
|
||||
topupWalletStorage.save(
|
||||
DataSourceTopupInfo(
|
||||
walletId = it.stringValue,
|
||||
cardBalanceState = DataSourceTopupInfo.CardBalanceState.Empty,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun send(scanResponse: ScanResponse, cardBalanceState: AnalyticsParam.CardBalanceState) {
|
||||
UserWalletIdBuilder.scanResponse(scanResponse).build()?.let {
|
||||
send(it, cardBalanceState, scanResponse.cardTypesResolver)
|
||||
}
|
||||
}
|
||||
|
||||
fun send(
|
||||
userWalletId: UserWalletId,
|
||||
cardBalanceState: AnalyticsParam.CardBalanceState,
|
||||
cardTypesResolver: CardTypesResolver,
|
||||
) {
|
||||
val topupInfo = topupWalletStorage.restore(userWalletId.stringValue).guard {
|
||||
val topupInfo = DataSourceTopupInfo(
|
||||
walletId = userWalletId.stringValue,
|
||||
cardBalanceState = when (cardBalanceState) {
|
||||
AnalyticsParam.CardBalanceState.BlockchainError ->
|
||||
DataSourceTopupInfo.CardBalanceState.BlockchainError
|
||||
AnalyticsParam.CardBalanceState.CustomToken ->
|
||||
DataSourceTopupInfo.CardBalanceState.CustomToken
|
||||
AnalyticsParam.CardBalanceState.Empty ->
|
||||
DataSourceTopupInfo.CardBalanceState.Empty
|
||||
AnalyticsParam.CardBalanceState.Full ->
|
||||
DataSourceTopupInfo.CardBalanceState.Full
|
||||
AnalyticsParam.CardBalanceState.NoRate ->
|
||||
DataSourceTopupInfo.CardBalanceState.NoRate
|
||||
},
|
||||
)
|
||||
topupWalletStorage.save(topupInfo)
|
||||
return
|
||||
}
|
||||
|
||||
val isToppedUp = topupInfo.cardBalanceState == DataSourceTopupInfo.CardBalanceState.Full
|
||||
if (isToppedUp) return
|
||||
|
||||
if (cardBalanceState.isToppedUp()) {
|
||||
topupWalletStorage.save(topupInfo.copy(cardBalanceState = DataSourceTopupInfo.CardBalanceState.Full))
|
||||
TopUpEventConverter().convert(value = userWalletId to cardTypesResolver)?.let {
|
||||
Analytics.send(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun findToppedUpCurrenciesInPast(walletDataModels: List<WalletDataModel>): List<WalletDataModel> {
|
||||
val currenciesToppedUpInPast = addedCurrencies.copy()
|
||||
.mapNotNull { currency ->
|
||||
val foundCurrencyModel = walletDataModels
|
||||
.find { it.currency == currency }
|
||||
?: return@mapNotNull null
|
||||
|
||||
if (foundCurrencyModel.status.amount.isZero()) null else foundCurrencyModel
|
||||
}
|
||||
addedCurrencies.clear()
|
||||
|
||||
return currenciesToppedUpInPast
|
||||
}
|
||||
|
||||
private fun BigDecimal.toCardBalanceState(): AnalyticsParam.CardBalanceState = when {
|
||||
isZero() -> AnalyticsParam.CardBalanceState.Empty
|
||||
else -> AnalyticsParam.CardBalanceState.Full
|
||||
}
|
||||
|
||||
private fun AnalyticsParam.CardBalanceState.isToppedUp(): Boolean = this == AnalyticsParam.CardBalanceState.Full
|
||||
}
|
||||
|
||||
private interface IBalanceCalculator {
|
||||
fun calculate(): BigDecimal
|
||||
}
|
||||
|
||||
private class BalanceCalculator(
|
||||
private val walletDataModels: List<WalletDataModel>,
|
||||
) : IBalanceCalculator {
|
||||
|
||||
override fun calculate(): BigDecimal {
|
||||
val singleToken = walletDataModels
|
||||
.filter { it.currency.isToken() }
|
||||
.firstOrNull { it.isCardSingleToken }
|
||||
|
||||
val totalAmount = singleToken?.status?.amount
|
||||
?: walletDataModels.calculateTotalCryptoAmount()
|
||||
|
||||
return totalAmount
|
||||
}
|
||||
|
||||
private fun List<WalletDataModel>.calculateTotalCryptoAmount(): BigDecimal = this
|
||||
.map { it.status.amount }
|
||||
.reduce(BigDecimal::plus)
|
||||
}
|
||||
|
|
@ -8,7 +8,6 @@ import com.tangem.datasource.config.models.ChatConfig
|
|||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.tap.common.analytics.topup.TopUpController
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.tap.common.feedback.FeedbackData
|
||||
import com.tangem.tap.common.feedback.FeedbackManager
|
||||
|
|
@ -78,7 +77,6 @@ sealed class GlobalAction : Action {
|
|||
data class SetConfigManager(val configManager: ConfigManager) : GlobalAction()
|
||||
data class SetWarningManager(val warningManager: WarningMessagesManager) : GlobalAction()
|
||||
data class SetFeedbackManager(val feedbackManager: FeedbackManager) : GlobalAction()
|
||||
data class SetTopUpController(val topUpController: TopUpController) : GlobalAction()
|
||||
|
||||
data class SendEmail(val feedbackData: FeedbackData) : GlobalAction()
|
||||
data class OpenChat(val feedbackData: FeedbackData, val chatConfig: ChatConfig? = null) : GlobalAction()
|
||||
|
|
|
|||
|
|
@ -164,9 +164,6 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
|
|||
}
|
||||
}
|
||||
}
|
||||
is GlobalAction.SetTopUpController -> {
|
||||
walletCurrenciesManager.addListener(action.topUpController)
|
||||
}
|
||||
is GlobalAction.UpdateUserWalletsListManager -> {
|
||||
val walletManagersFacade = store.state.daggerGraphState.get(DaggerGraphState::walletManagersFacade)
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde
|
|||
globalState.copy(configManager = action.configManager)
|
||||
}
|
||||
is GlobalAction.SetWarningManager -> globalState.copy(warningManager = action.warningManager)
|
||||
is GlobalAction.SetTopUpController -> globalState.copy(topUpController = action.topUpController)
|
||||
is GlobalAction.UpdateWalletSignedHashes -> {
|
||||
val card = globalState.scanResponse?.card ?: return globalState
|
||||
val wallet = card.wallets
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import com.tangem.datasource.config.ConfigManager
|
|||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.tap.common.analytics.topup.TopUpController
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.tap.common.feedback.FeedbackManager
|
||||
import com.tangem.tap.domain.TapWalletManager
|
||||
|
|
@ -29,7 +28,6 @@ data class GlobalState(
|
|||
val exchangeManager: CurrencyExchangeManager = CurrencyExchangeManager.dummy(),
|
||||
val userCountryCode: String? = null,
|
||||
val userWalletsListManager: UserWalletsListManager? = null,
|
||||
val topUpController: TopUpController? = null,
|
||||
val appThemeMode: AppThemeMode = AppThemeMode.DEFAULT,
|
||||
) : StateType
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,6 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch
|
|||
val updatedResponse = scanResponse.copy(card = result.data.card)
|
||||
onboardingManager.scanResponse = updatedResponse
|
||||
onboardingManager.activationStarted(updatedResponse.card.cardId)
|
||||
store.state.globalState.topUpController?.registerEmptyWallet(updatedResponse)
|
||||
store.dispatch(OnboardingNoteAction.SetStepOfScreen(OnboardingNoteStep.TopUpWallet))
|
||||
}
|
||||
is CompletionResult.Failure -> Unit
|
||||
|
|
@ -151,8 +150,6 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch
|
|||
is OnboardingNoteAction.Balance.Set -> {
|
||||
if (action.balance.balanceIsToppedUp()) {
|
||||
OnboardingHelper.sendToppedUpEvent(scanResponse)
|
||||
|
||||
store.state.globalState.topUpController?.send(scanResponse, AnalyticsParam.CardBalanceState.Full)
|
||||
store.dispatch(OnboardingNoteAction.SetStepOfScreen(OnboardingNoteStep.Done))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,6 @@ private fun handleOtherCardsAction(action: Action) {
|
|||
val updatedCard = updatedResponse.card
|
||||
onboardingManager.scanResponse = updatedResponse
|
||||
onboardingManager.activationStarted(updatedCard.cardId)
|
||||
store.state.globalState.topUpController?.registerEmptyWallet(updatedResponse)
|
||||
|
||||
val primaryBlockchain = updatedResponse.cardTypesResolver.getBlockchain()
|
||||
val blockchainNetworks = if (primaryBlockchain != Blockchain.Unknown) {
|
||||
|
|
|
|||
|
|
@ -200,7 +200,6 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
is Result.Success -> {
|
||||
Analytics.send(Onboarding.Twins.SetupFinished())
|
||||
updateScanResponse(result.data)
|
||||
store.state.globalState.topUpController?.registerEmptyWallet(result.data)
|
||||
|
||||
delay(DELAY_SDK_DIALOG_CLOSE)
|
||||
withMainContext {
|
||||
|
|
@ -259,8 +258,6 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
is TwinCardsAction.Balance.Set -> {
|
||||
if (action.balance.balanceIsToppedUp()) {
|
||||
OnboardingHelper.sendToppedUpEvent(getScanResponse())
|
||||
|
||||
store.state.globalState.topUpController?.send(getScanResponse(), AnalyticsParam.CardBalanceState.Full)
|
||||
store.dispatchOnMain(TwinCardsAction.SetStepOfScreen(TwinCardsStep.Done))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,7 +142,6 @@ private fun handleWalletAction(action: Action) {
|
|||
primaryCard = result.data.primaryCard,
|
||||
)
|
||||
onboardingManager.scanResponse = updatedResponse
|
||||
store.state.globalState.topUpController?.registerEmptyWallet(updatedResponse)
|
||||
|
||||
val blockchainNetworks = if (DemoHelper.isDemoCardId(result.data.card.cardId)) {
|
||||
DemoHelper.config.demoBlockchains
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue