Updated on 2026-08-14
This commit is contained in:
parent
d995d1dd21
commit
07bf6c376c
20 changed files with 386 additions and 174 deletions
|
|
@ -0,0 +1,156 @@
|
|||
package com.tangem.feature.wallet.presentation.deeplink
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.deeplink.DeepLink
|
||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
import com.tangem.core.deeplink.global.BuyCurrencyDeepLink
|
||||
import com.tangem.core.deeplink.global.SellCurrencyDeepLink
|
||||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyStatusSyncUseCase
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyUseCase
|
||||
import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase
|
||||
import com.tangem.domain.tokens.GetNetworkCoinStatusUseCase
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction.TransactionInfo
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.models.analytics.TokenScreenAnalyticsEvent
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class WalletDeepLinksHandler @Inject constructor(
|
||||
private val deepLinksRegistry: DeepLinksRegistry,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val getCryptoCurrencyUseCase: GetCryptoCurrencyUseCase,
|
||||
private val getCryptoCurrencyStatusSyncUseCase: GetCryptoCurrencyStatusSyncUseCase,
|
||||
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
|
||||
private val getNetworkCoinStatusUseCase: GetNetworkCoinStatusUseCase,
|
||||
private val reduxStateHolder: ReduxStateHolder,
|
||||
) {
|
||||
|
||||
private var deepLinks: List<DeepLink> = emptyList()
|
||||
|
||||
fun registerForSingleCurrencyWallets(viewModel: ViewModel, userWallet: UserWallet) {
|
||||
if (userWallet.isMultiCurrency) {
|
||||
deepLinksRegistry.unregister(deepLinks)
|
||||
} else {
|
||||
if (deepLinks.isEmpty()) {
|
||||
deepLinks = getDeepLinks(userWallet, viewModel.viewModelScope)
|
||||
}
|
||||
|
||||
deepLinksRegistry.register(deepLinks)
|
||||
}
|
||||
|
||||
viewModel.addCloseable {
|
||||
deepLinksRegistry.unregister(deepLinks)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDeepLinks(userWallet: UserWallet, scope: CoroutineScope): List<DeepLink> {
|
||||
val sellCurrencyDeepLink = SellCurrencyDeepLink(
|
||||
onReceive = { data ->
|
||||
scope.launch {
|
||||
onSellCurrencyDeepLink(userWallet, data)
|
||||
}
|
||||
},
|
||||
)
|
||||
val buyCurrencyDeepLink = BuyCurrencyDeepLink(
|
||||
onReceive = {
|
||||
scope.launch {
|
||||
onBuyCurrencyDeepLink(userWallet)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
return listOf(sellCurrencyDeepLink, buyCurrencyDeepLink)
|
||||
}
|
||||
|
||||
private suspend fun onSellCurrencyDeepLink(userWallet: UserWallet, data: SellCurrencyDeepLink.Data) {
|
||||
val cryptoCurrencyStatus = getCryptoCurrencyStatusSyncUseCase(userWallet.walletId)
|
||||
.getOrNull() ?: return
|
||||
val feeCurrencyStatus = getFeePaidCryptoCurrencyStatusSyncUseCase(
|
||||
userWallet.walletId,
|
||||
cryptoCurrencyStatus,
|
||||
).getOrNull()
|
||||
|
||||
val transactionInfo = data.let {
|
||||
TransactionInfo(
|
||||
amount = it.baseCurrencyAmount,
|
||||
destinationAddress = it.depositWalletAddress,
|
||||
transactionId = it.transactionId,
|
||||
)
|
||||
}
|
||||
|
||||
when (cryptoCurrencyStatus.currency) {
|
||||
is CryptoCurrency.Coin -> sendCoin(
|
||||
userWallet = userWallet,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
feeCurrencyStatus = feeCurrencyStatus,
|
||||
transactionInfo = transactionInfo,
|
||||
)
|
||||
is CryptoCurrency.Token -> sendToken(
|
||||
userWallet = userWallet,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
feeCurrencyStatus = feeCurrencyStatus,
|
||||
transactionInfo = transactionInfo,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun onBuyCurrencyDeepLink(userWallet: UserWallet) {
|
||||
val cryptoCurrency = getCryptoCurrencyUseCase(userWallet.walletId).getOrNull() ?: return
|
||||
|
||||
analyticsEventHandler.send(TokenScreenAnalyticsEvent.Bought(cryptoCurrency.symbol))
|
||||
}
|
||||
|
||||
private fun sendCoin(
|
||||
userWallet: UserWallet,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
feeCurrencyStatus: CryptoCurrencyStatus?,
|
||||
transactionInfo: TransactionInfo,
|
||||
) {
|
||||
reduxStateHolder.dispatch(
|
||||
action = TradeCryptoAction.SendCoin(
|
||||
userWallet = userWallet,
|
||||
coinStatus = cryptoCurrencyStatus,
|
||||
feeCurrencyStatus = feeCurrencyStatus,
|
||||
transactionInfo = transactionInfo,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun sendToken(
|
||||
userWallet: UserWallet,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
feeCurrencyStatus: CryptoCurrencyStatus?,
|
||||
transactionInfo: TransactionInfo,
|
||||
) {
|
||||
val cryptoCurrency = cryptoCurrencyStatus.currency as? CryptoCurrency.Token ?: return
|
||||
val coinStatus = getNetworkCoinStatusUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
networkId = cryptoCurrency.network.id,
|
||||
derivationPath = cryptoCurrency.network.derivationPath,
|
||||
isSingleWalletWithTokens = false,
|
||||
)
|
||||
.firstOrNull()
|
||||
?.getOrNull()
|
||||
?: return
|
||||
|
||||
reduxStateHolder.dispatch(
|
||||
action = TradeCryptoAction.SendToken(
|
||||
userWallet = userWallet,
|
||||
tokenCurrency = cryptoCurrency,
|
||||
tokenFiatRate = cryptoCurrencyStatus.value.fiatRate,
|
||||
coinFiatRate = coinStatus.value.fiatRate,
|
||||
feeCurrencyStatus = feeCurrencyStatus,
|
||||
transactionInfo = transactionInfo,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -609,7 +609,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
|
||||
showErrorIfDemoModeOrElse {
|
||||
reduxStateHolder.dispatch(
|
||||
TradeCryptoAction.New.Buy(
|
||||
TradeCryptoAction.Buy(
|
||||
userWallet = getWallet(index = state.walletsListConfig.selectedWalletIndex),
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
appCurrencyCode = selectedAppCurrencyFlow.value.code,
|
||||
|
|
@ -623,7 +623,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
event = TokenScreenAnalyticsEvent.ButtonExchange(cryptoCurrencyStatus.currency.symbol),
|
||||
)
|
||||
|
||||
reduxStateHolder.dispatch(TradeCryptoAction.New.Swap(cryptoCurrencyStatus.currency))
|
||||
reduxStateHolder.dispatch(TradeCryptoAction.Swap(cryptoCurrencyStatus.currency))
|
||||
}
|
||||
|
||||
override fun onSingleCurrencySendClick(cryptoCurrencyStatus: CryptoCurrencyStatus?) {
|
||||
|
|
@ -641,7 +641,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
val maybeFeeCurrencyStatus =
|
||||
getFeePaidCryptoCurrencyStatusSyncUseCase(userWallet.walletId, coinStatus).getOrNull()
|
||||
reduxStateHolder.dispatch(
|
||||
action = TradeCryptoAction.New.SendCoin(
|
||||
action = TradeCryptoAction.SendCoin(
|
||||
userWallet = userWallet,
|
||||
coinStatus = coinStatus,
|
||||
feeCurrencyStatus = maybeFeeCurrencyStatus,
|
||||
|
|
@ -665,7 +665,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
is CryptoCurrency.Coin -> {
|
||||
uiState = stateFactory.getStateWithClosedBottomSheet()
|
||||
reduxStateHolder.dispatch(
|
||||
action = TradeCryptoAction.New.SendCoin(
|
||||
action = TradeCryptoAction.SendCoin(
|
||||
userWallet = userWallet,
|
||||
coinStatus = cryptoCurrencyStatus,
|
||||
feeCurrencyStatus = maybeFeeCurrencyStatus,
|
||||
|
|
@ -694,7 +694,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
it.onRight { coinStatus ->
|
||||
uiState = stateFactory.getStateWithClosedBottomSheet()
|
||||
reduxStateHolder.dispatchWithMain(
|
||||
action = TradeCryptoAction.New.SendToken(
|
||||
action = TradeCryptoAction.SendToken(
|
||||
userWallet = userWallet,
|
||||
tokenCurrency = requireNotNull(cryptoCurrencyStatus.currency as? CryptoCurrency.Token),
|
||||
tokenFiatRate = cryptoCurrencyStatus.value.fiatRate,
|
||||
|
|
@ -772,7 +772,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
|
||||
showErrorIfDemoModeOrElse {
|
||||
reduxStateHolder.dispatch(
|
||||
action = TradeCryptoAction.New.Sell(
|
||||
action = TradeCryptoAction.Sell(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
appCurrencyCode = selectedAppCurrencyFlow.value.code,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.tangem.domain.walletconnect.WalletConnectActions
|
|||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
|
||||
import com.tangem.feature.wallet.presentation.deeplink.WalletDeepLinksHandler
|
||||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.SelectedWalletAnalyticsSender
|
||||
|
|
@ -57,6 +58,7 @@ internal class WalletViewModelV2 @Inject constructor(
|
|||
private val reduxStateHolder: ReduxStateHolder,
|
||||
private val screenLifecycleProvider: ScreenLifecycleProvider,
|
||||
private val selectedWalletAnalyticsSender: SelectedWalletAnalyticsSender,
|
||||
private val walletDeepLinksHandler: WalletDeepLinksHandler,
|
||||
) : ViewModel() {
|
||||
|
||||
val uiState: StateFlow<WalletScreenState> = stateHolder.uiState
|
||||
|
|
@ -157,6 +159,11 @@ internal class WalletViewModelV2 @Inject constructor(
|
|||
|
||||
selectedWalletAnalyticsSender.send(selectedWallet)
|
||||
}
|
||||
|
||||
walletDeepLinksHandler.registerForSingleCurrencyWallets(
|
||||
viewModel = this,
|
||||
userWallet = selectedWallet,
|
||||
)
|
||||
}
|
||||
.flowOn(dispatchers.main)
|
||||
.launchIn(viewModelScope)
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
feeCurrencyStatus: CryptoCurrencyStatus?,
|
||||
) {
|
||||
reduxStateHolder.dispatch(
|
||||
action = TradeCryptoAction.New.SendCoin(
|
||||
action = TradeCryptoAction.SendCoin(
|
||||
userWallet = userWallet,
|
||||
coinStatus = cryptoCurrencyStatus,
|
||||
feeCurrencyStatus = feeCurrencyStatus,
|
||||
|
|
@ -135,7 +135,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
.collectLatest {
|
||||
it.onRight { coinStatus ->
|
||||
reduxStateHolder.dispatch(
|
||||
action = TradeCryptoAction.New.SendToken(
|
||||
action = TradeCryptoAction.SendToken(
|
||||
userWallet = userWallet,
|
||||
tokenCurrency = cryptoCurrency,
|
||||
tokenFiatRate = cryptoCurrencyStatus.fiatRate,
|
||||
|
|
@ -281,7 +281,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
showErrorIfDemoModeOrElse {
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
reduxStateHolder.dispatch(
|
||||
action = TradeCryptoAction.New.Sell(
|
||||
action = TradeCryptoAction.Sell(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
appCurrencyCode = getSelectedAppCurrencyUseCase.unwrap().code,
|
||||
),
|
||||
|
|
@ -300,7 +300,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
showErrorIfDemoModeOrElse {
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
reduxStateHolder.dispatch(
|
||||
TradeCryptoAction.New.Buy(
|
||||
TradeCryptoAction.Buy(
|
||||
userWallet = userWallet,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
appCurrencyCode = getSelectedAppCurrencyUseCase.unwrap().code,
|
||||
|
|
@ -315,7 +315,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
event = TokenScreenAnalyticsEvent.ButtonExchange(cryptoCurrencyStatus.currency.symbol),
|
||||
)
|
||||
|
||||
reduxStateHolder.dispatch(TradeCryptoAction.New.Swap(cryptoCurrencyStatus.currency))
|
||||
reduxStateHolder.dispatch(TradeCryptoAction.Swap(cryptoCurrencyStatus.currency))
|
||||
}
|
||||
|
||||
override fun onExploreClick() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue