Updated on 2026-08-14
This commit is contained in:
commit
8dec159cd3
126 changed files with 3168 additions and 996 deletions
|
|
@ -23,9 +23,9 @@ import androidx.lifecycle.flowWithLifecycle
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import arrow.core.getOrElse
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.tangem.feature.qrscanning.QrScanningRouter
|
||||
import com.google.android.material.snackbar.BaseTransientBottomBar
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.core.ui.event.StateEvent
|
||||
|
|
@ -36,6 +36,7 @@ import com.tangem.domain.apptheme.model.AppThemeMode
|
|||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.feature.qrscanning.QrScanningRouter
|
||||
import com.tangem.features.managetokens.navigation.ManageTokensRouter
|
||||
import com.tangem.features.send.api.navigation.SendRouter
|
||||
import com.tangem.features.tester.api.TesterRouter
|
||||
|
|
@ -57,8 +58,6 @@ import com.tangem.tap.domain.userWalletList.implementation.BiometricUserWalletsL
|
|||
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
|
||||
import com.tangem.tap.features.intentHandler.IntentProcessor
|
||||
import com.tangem.tap.features.intentHandler.handlers.BackgroundScanIntentHandler
|
||||
import com.tangem.tap.features.intentHandler.handlers.BuyCurrencyIntentHandler
|
||||
import com.tangem.tap.features.intentHandler.handlers.SellCurrencyIntentHandler
|
||||
import com.tangem.tap.features.intentHandler.handlers.WalletConnectLinkIntentHandler
|
||||
import com.tangem.tap.features.main.MainViewModel
|
||||
import com.tangem.tap.features.main.model.Toast
|
||||
|
|
@ -138,6 +137,9 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
@Inject
|
||||
lateinit var qrScanningRouter: QrScanningRouter
|
||||
|
||||
@Inject
|
||||
lateinit var deepLinksRegistry: DeepLinksRegistry
|
||||
|
||||
internal val viewModel: MainViewModel by viewModels()
|
||||
|
||||
private lateinit var appThemeModeFlow: SharedFlow<AppThemeMode?>
|
||||
|
|
@ -167,6 +169,10 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
|
||||
checkForNotificationPermission()
|
||||
observeStateUpdates()
|
||||
|
||||
if (intent != null) {
|
||||
deepLinksRegistry.launch(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeStateUpdates() {
|
||||
|
|
@ -293,8 +299,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
val hasSavedWalletsProvider = { store.state.globalState.userWalletsListManager?.hasUserWallets == true }
|
||||
intentProcessor.addHandler(BackgroundScanIntentHandler(hasSavedWalletsProvider, lifecycleScope))
|
||||
intentProcessor.addHandler(WalletConnectLinkIntentHandler())
|
||||
intentProcessor.addHandler(BuyCurrencyIntentHandler())
|
||||
intentProcessor.addHandler(SellCurrencyIntentHandler())
|
||||
}
|
||||
|
||||
private fun updateAppTheme(appThemeMode: AppThemeMode) {
|
||||
|
|
@ -332,6 +336,10 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
lifecycleScope.launch {
|
||||
intentProcessor.handleIntent(intent)
|
||||
}
|
||||
|
||||
if (intent != null) {
|
||||
deepLinksRegistry.launch(intent)
|
||||
}
|
||||
}
|
||||
|
||||
override fun showSnackbar(
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.common.redux.legacy
|
|||
|
||||
import com.tangem.domain.redux.LegacyAction
|
||||
import com.tangem.tap.common.feedback.RateCanBeBetterEmail
|
||||
import com.tangem.tap.common.feedback.SendTransactionFailedEmail
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.store
|
||||
|
|
@ -20,6 +21,11 @@ internal object LegacyMiddleware {
|
|||
GlobalAction.Onboarding.Start(action.scanResponse, canSkipBackup = action.canSkipBackup),
|
||||
)
|
||||
}
|
||||
is LegacyAction.SendEmailTransactionFailed -> {
|
||||
store.state.globalState.feedbackManager?.sendEmail(
|
||||
SendTransactionFailedEmail(action.errorMessage),
|
||||
)
|
||||
}
|
||||
}
|
||||
next(action)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -310,4 +310,22 @@ internal object TokensDomainModule {
|
|||
): GetNetworksSupportedByWallet {
|
||||
return GetNetworksSupportedByWallet(repository = repository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideGetBalanceNotEnoughForFeeWarningUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): GetBalanceNotEnoughForFeeWarningUseCase {
|
||||
return GetBalanceNotEnoughForFeeWarningUseCase(currenciesRepository, dispatchers)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideIsAmountSubtractAvailableUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): IsAmountSubtractAvailableUseCase {
|
||||
return IsAmountSubtractAvailableUseCase(currenciesRepository, dispatchers)
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,6 @@ import com.tangem.domain.transaction.usecase.CreateTransactionUseCase
|
|||
import com.tangem.domain.transaction.usecase.GetFeeUseCase
|
||||
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -20,24 +19,21 @@ internal object TransactionDomainModule {
|
|||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideGetFeeUseCase(
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): GetFeeUseCase {
|
||||
return GetFeeUseCase(walletManagersFacade, dispatchers)
|
||||
fun provideGetFeeUseCase(walletManagersFacade: WalletManagersFacade): GetFeeUseCase {
|
||||
return GetFeeUseCase(walletManagersFacade)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideSendTransactionUseCase(
|
||||
isDemoCardUseCase: IsDemoCardUseCase,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
transactionRepository: TransactionRepository,
|
||||
): SendTransactionUseCase {
|
||||
return SendTransactionUseCase(
|
||||
isDemoCardUseCase = isDemoCardUseCase,
|
||||
cardSdkConfigRepository = cardSdkConfigRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
transactionRepository = transactionRepository,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
package com.tangem.tap.features.intentHandler.handlers
|
||||
|
||||
import android.content.Intent
|
||||
import com.tangem.tap.features.intentHandler.IntentHandler
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class BuyCurrencyIntentHandler : IntentHandler {
|
||||
|
||||
override fun handleIntent(intent: Intent?): Boolean {
|
||||
// FIXME: [REDACTED_JIRA]
|
||||
// val data = intent?.data ?: return false
|
||||
// val currency = store.state.walletState.selectedCurrency ?: return false
|
||||
//
|
||||
// val successUri = Uri.parse(ExchangeUrlBuilder.SUCCESS_URL)
|
||||
// return if (data.host == successUri.host && data.authority == successUri.authority) {
|
||||
// val currencyType = AnalyticsParam.CurrencyType.Currency(currency)
|
||||
// Analytics.send(TokenScreenAnalyticsEvent.Bought(currencyType.value))
|
||||
// true
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
package com.tangem.tap.features.intentHandler.handlers
|
||||
|
||||
import android.content.Intent
|
||||
import com.tangem.tap.features.intentHandler.IntentHandler
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class SellCurrencyIntentHandler : IntentHandler {
|
||||
|
||||
override fun handleIntent(intent: Intent?): Boolean {
|
||||
// FIXME: [REDACTED_JIRA]
|
||||
// return try {
|
||||
// val intentData = intent?.data ?: return false
|
||||
// val transactionID = intentData.getQueryParameter(TRANSACTION_ID_PARAM) ?: return false
|
||||
// val currency = intentData.getQueryParameter(CURRENCY_CODE_PARAM) ?: return false
|
||||
// val amount = intentData.getQueryParameter(CURRENCY_AMOUNT_PARAM) ?: return false
|
||||
// val destinationAddress = intentData.getQueryParameter(DEPOSIT_WALLET_ADDRESS_PARAM) ?: return false
|
||||
//
|
||||
// Timber.d("MoonPay Sell: $amount $currency to $destinationAddress")
|
||||
// store.dispatchOnMain(
|
||||
// TradeCryptoAction.SendCrypto(
|
||||
// currencyId = currency,
|
||||
// amount = amount,
|
||||
// destinationAddress = destinationAddress,
|
||||
// transactionId = transactionID,
|
||||
// ),
|
||||
// )
|
||||
// true
|
||||
// } catch (exception: Exception) {
|
||||
// Timber.d("Not MoonPay URL")
|
||||
// false
|
||||
// }
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// private companion object {
|
||||
// private const val TRANSACTION_ID_PARAM = "transactionId"
|
||||
// private const val CURRENCY_CODE_PARAM = "baseCurrencyCode"
|
||||
// private const val CURRENCY_AMOUNT_PARAM = "baseCurrencyAmount"
|
||||
// private const val DEPOSIT_WALLET_ADDRESS_PARAM = "depositWalletAddress"
|
||||
// }
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ import com.tangem.tap.domain.TapError
|
|||
import com.tangem.tap.features.demo.DemoHelper
|
||||
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
|
||||
import com.tangem.tap.features.send.redux.PrepareSendScreen
|
||||
import com.tangem.tap.features.send.redux.SendAction
|
||||
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
|
||||
import com.tangem.tap.network.exchangeServices.buyErc20TestnetTokens
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
|
|
@ -50,19 +51,18 @@ object TradeCryptoMiddleware {
|
|||
if (DemoHelper.tryHandle(state, action)) return
|
||||
|
||||
when (action) {
|
||||
is TradeCryptoAction.SendCrypto -> preconfigureAndOpenSendScreen()
|
||||
is TradeCryptoAction.FinishSelling -> openReceiptUrl(action.transactionId)
|
||||
is TradeCryptoAction.New.Buy -> proceedNewBuyAction(state, action)
|
||||
is TradeCryptoAction.New.Sell -> proceedNewSellAction(action)
|
||||
is TradeCryptoAction.New.Swap -> openSwap(
|
||||
is TradeCryptoAction.Buy -> proceedBuyAction(state, action)
|
||||
is TradeCryptoAction.Sell -> proceedSellAction(action)
|
||||
is TradeCryptoAction.Swap -> openSwap(
|
||||
currency = action.cryptoCurrency,
|
||||
)
|
||||
is TradeCryptoAction.New.SendToken -> handleNewSendToken(action = action)
|
||||
is TradeCryptoAction.New.SendCoin -> handleNewSendCoin(action = action)
|
||||
is TradeCryptoAction.SendToken -> handleSendToken(action = action)
|
||||
is TradeCryptoAction.SendCoin -> handleSendCoin(action = action)
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedNewBuyAction(state: () -> AppState?, action: TradeCryptoAction.New.Buy) {
|
||||
private fun proceedBuyAction(state: () -> AppState?, action: TradeCryptoAction.Buy) {
|
||||
val networkAddress = action.cryptoCurrencyStatus.value.networkAddress
|
||||
?.defaultAddress
|
||||
?.let(NetworkAddress.Address::value)
|
||||
|
|
@ -119,7 +119,7 @@ object TradeCryptoMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
private fun proceedNewSellAction(action: TradeCryptoAction.New.Sell) {
|
||||
private fun proceedSellAction(action: TradeCryptoAction.Sell) {
|
||||
val networkAddress = action.cryptoCurrencyStatus.value.networkAddress
|
||||
?.defaultAddress
|
||||
?.let(NetworkAddress.Address::value)
|
||||
|
|
@ -139,33 +139,6 @@ object TradeCryptoMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
private fun preconfigureAndOpenSendScreen() = scope.launch {
|
||||
// FIXME: [REDACTED_JIRA]
|
||||
// val selectedWalletData = store.state.walletState.selectedWalletData ?: return
|
||||
//
|
||||
// Analytics.send(Token.ButtonSend(AnalyticsParam.CurrencyType.Currency(selectedWalletData.currency)))
|
||||
// val walletManager = store.state.walletState.getWalletManager(selectedWalletData.currency).guard {
|
||||
// FirebaseCrashlytics.getInstance().recordException(IllegalStateException("WalletManager is null"))
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// store.dispatchOnMain(
|
||||
// PrepareSendScreen(
|
||||
// walletManager = walletManager,
|
||||
// coinAmount = walletManager.wallet.amounts[AmountType.Coin],
|
||||
// coinRate = selectedWalletData.fiatRate,
|
||||
// ),
|
||||
// )
|
||||
// store.dispatchOnMain(
|
||||
// SendAction.SendSpecificTransaction(
|
||||
// sendAmount = action.amount,
|
||||
// destinationAddress = action.destinationAddress,
|
||||
// transactionId = action.transactionId,
|
||||
// ),
|
||||
// )
|
||||
// store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Send))
|
||||
}
|
||||
|
||||
private fun openReceiptUrl(transactionId: String) {
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo())
|
||||
store.state.globalState.exchangeManager.getSellCryptoReceiptUrl(
|
||||
|
|
@ -182,7 +155,7 @@ object TradeCryptoMiddleware {
|
|||
store.dispatchOnMain(NavigationAction.NavigateTo(screen = AppScreen.Swap, bundle = bundle))
|
||||
}
|
||||
|
||||
private fun handleNewSendToken(action: TradeCryptoAction.New.SendToken) {
|
||||
private fun handleSendToken(action: TradeCryptoAction.SendToken) {
|
||||
val currency = action.tokenCurrency
|
||||
val blockchain = Blockchain.fromId(currency.network.id.value)
|
||||
|
||||
|
|
@ -221,6 +194,17 @@ object TradeCryptoMiddleware {
|
|||
),
|
||||
)
|
||||
|
||||
val txInfo = action.transactionInfo
|
||||
if (txInfo != null) {
|
||||
store.dispatchOnMain(
|
||||
SendAction.SendSpecificTransaction(
|
||||
sendAmount = txInfo.amount,
|
||||
destinationAddress = txInfo.destinationAddress,
|
||||
transactionId = txInfo.transactionId,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val bundle = bundleOf(
|
||||
SendRouter.CRYPTO_CURRENCY_KEY to currency,
|
||||
SendRouter.USER_WALLET_ID_KEY to action.userWallet.walletId.stringValue,
|
||||
|
|
@ -229,7 +213,7 @@ object TradeCryptoMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleNewSendCoin(action: TradeCryptoAction.New.SendCoin) {
|
||||
private fun handleSendCoin(action: TradeCryptoAction.SendCoin) {
|
||||
val cryptoStatus = action.coinStatus
|
||||
val currency = cryptoStatus.currency
|
||||
val blockchain = Blockchain.fromId(currency.network.id.value)
|
||||
|
|
@ -278,6 +262,17 @@ object TradeCryptoMiddleware {
|
|||
is CryptoCurrency.Token -> error("Action.tokenStatus.currency is Token")
|
||||
}
|
||||
|
||||
val txInfo = action.transactionInfo
|
||||
if (txInfo != null) {
|
||||
store.dispatchOnMain(
|
||||
SendAction.SendSpecificTransaction(
|
||||
sendAmount = txInfo.amount,
|
||||
destinationAddress = txInfo.destinationAddress,
|
||||
transactionId = txInfo.transactionId,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val bundle = bundleOf(
|
||||
SendRouter.CRYPTO_CURRENCY_KEY to currency,
|
||||
SendRouter.USER_WALLET_ID_KEY to action.userWallet.walletId.stringValue,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.tap.proxy.redux
|
||||
|
||||
import com.tangem.feature.qrscanning.QrScanningRouter
|
||||
import com.tangem.datasource.connection.NetworkConnectionManager
|
||||
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
|
||||
import com.tangem.domain.apptheme.repository.AppThemeModeRepository
|
||||
|
|
@ -13,6 +12,7 @@ import com.tangem.domain.tokens.repository.CurrenciesRepository
|
|||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.feature.qrscanning.QrScanningRouter
|
||||
import com.tangem.features.managetokens.featuretoggles.ManageTokensFeatureToggles
|
||||
import com.tangem.features.managetokens.navigation.ManageTokensRouter
|
||||
import com.tangem.features.send.api.featuretoggles.SendFeatureToggles
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue