diff --git a/data/txhistory/src/main/kotlin/com/tangem/data/txhistory/repository/DefaultTxHistoryRepository.kt b/data/txhistory/src/main/kotlin/com/tangem/data/txhistory/repository/DefaultTxHistoryRepository.kt index dba0ed594a..64268e3c0c 100644 --- a/data/txhistory/src/main/kotlin/com/tangem/data/txhistory/repository/DefaultTxHistoryRepository.kt +++ b/data/txhistory/src/main/kotlin/com/tangem/data/txhistory/repository/DefaultTxHistoryRepository.kt @@ -9,6 +9,7 @@ import com.tangem.data.common.cache.CacheRegistry import com.tangem.data.txhistory.repository.paging.TxHistoryPagingSource import com.tangem.datasource.local.txhistory.TxHistoryItemsStore import com.tangem.datasource.local.userwallet.UserWalletsStore +import com.tangem.domain.common.extensions.fromNetworkId import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.Network import com.tangem.domain.txhistory.models.Page @@ -69,6 +70,7 @@ class DefaultTxHistoryRepository( return pager.flow } + @Deprecated("Replace with getTxExploreUrl [UserWalletId, Network] instead") override fun getTxExploreUrl(txHash: String, networkId: Network.ID): String { val blockchain = Blockchain.fromId(networkId.value) return when (val txExploreState = blockchain.getExploreTxUrl(txHash)) { @@ -77,6 +79,19 @@ class DefaultTxHistoryRepository( } } + override suspend fun getTxExploreUrl(userWalletId: UserWalletId, network: Network): String { + val blockchain = Blockchain.fromNetworkId(network.id.value) + val walletManager = walletManagersFacade.getOrCreateWalletManager( + userWalletId = userWalletId, + network = network, + ) + val lastTxHash = walletManager?.wallet?.recentTransactions?.last()?.hash.orEmpty() + return when (val txExploreState = blockchain?.getExploreTxUrl(lastTxHash)) { + is TxExploreState.Url -> txExploreState.url + else -> "" + } + } + override suspend fun getFixedSizeTxHistoryItems( userWalletId: UserWalletId, currency: CryptoCurrency, diff --git a/domain/txhistory/src/main/kotlin/com/tangem/domain/txhistory/repository/TxHistoryRepository.kt b/domain/txhistory/src/main/kotlin/com/tangem/domain/txhistory/repository/TxHistoryRepository.kt index b010a54db4..652b15c85b 100644 --- a/domain/txhistory/src/main/kotlin/com/tangem/domain/txhistory/repository/TxHistoryRepository.kt +++ b/domain/txhistory/src/main/kotlin/com/tangem/domain/txhistory/repository/TxHistoryRepository.kt @@ -24,6 +24,9 @@ interface TxHistoryRepository { fun getTxExploreUrl(txHash: String, networkId: Network.ID): String + /** Get transaction url in explorer via last transaction from wallet's recentTransactions list */ + suspend fun getTxExploreUrl(userWalletId: UserWalletId, network: Network): String + @Throws(TxHistoryListError::class) suspend fun getFixedSizeTxHistoryItems( userWalletId: UserWalletId, diff --git a/domain/txhistory/src/main/kotlin/com/tangem/domain/txhistory/usecase/GetExplorerTransactionUrlUseCase.kt b/domain/txhistory/src/main/kotlin/com/tangem/domain/txhistory/usecase/GetExplorerTransactionUrlUseCase.kt index 974d439c7e..cedb309901 100644 --- a/domain/txhistory/src/main/kotlin/com/tangem/domain/txhistory/usecase/GetExplorerTransactionUrlUseCase.kt +++ b/domain/txhistory/src/main/kotlin/com/tangem/domain/txhistory/usecase/GetExplorerTransactionUrlUseCase.kt @@ -6,10 +6,12 @@ import arrow.core.raise.either import com.tangem.domain.tokens.model.Network import com.tangem.domain.txhistory.models.TxStatusError import com.tangem.domain.txhistory.repository.TxHistoryRepository +import com.tangem.domain.wallets.models.UserWalletId class GetExplorerTransactionUrlUseCase( private val repository: TxHistoryRepository, ) { + @Deprecated("Replace with invoke [UserWalletId, Network]") operator fun invoke(txHash: String, networkId: Network.ID): Either { return either { catch( @@ -22,4 +24,17 @@ class GetExplorerTransactionUrlUseCase( ) } } + + suspend operator fun invoke(userWalletId: UserWalletId, network: Network): Either { + return either { + catch( + block = { + repository.getTxExploreUrl(userWalletId, network).ifEmpty { + raise(TxStatusError.EmptyUrlError) + } + }, + catch = { raise(TxStatusError.DataError(it)) }, + ) + } + } } \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt index 7a5c113219..6861d18b0f 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt @@ -8,7 +8,6 @@ import com.tangem.core.ui.extensions.resourceReference import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.txhistory.models.TxHistoryItem -import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.usecase.ValidateWalletMemoUseCase import com.tangem.features.send.impl.R @@ -36,7 +35,6 @@ internal class SendStateFactory( private val feeCryptoCurrencyStatusProvider: Provider, private val isTapHelpPreviewEnabledProvider: Provider, private val validateWalletMemoUseCase: ValidateWalletMemoUseCase, - private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, ) { private val iconStateConverter by lazy(::CryptoCurrencyToIconStateConverter) @@ -92,7 +90,7 @@ internal class SendStateFactory( event = consumedEvent(), isEditingDisabled = false, isBalanceHidden = false, - cryptoCurrencySymbol = "", + cryptoCurrencyName = "", ) fun getReadyState(): SendUiState { @@ -103,7 +101,7 @@ internal class SendStateFactory( ?: recipientStateConverter.convert(SendRecipientStateConverter.Data("", null)), feeState = state.feeState ?: feeStateConverter.convert(Unit), sendState = confirmStateConverter.convert(Unit), - cryptoCurrencySymbol = cryptoCurrencyStatusProvider().currency.symbol, + cryptoCurrencyName = cryptoCurrencyStatusProvider().currency.name, ) } @@ -115,7 +113,7 @@ internal class SendStateFactory( ?: recipientStateConverter.convert(SendRecipientStateConverter.Data(destinationAddress, memo)), feeState = state.feeState ?: feeStateConverter.convert(Unit), isEditingDisabled = true, - cryptoCurrencySymbol = cryptoCurrencyStatusProvider().currency.symbol, + cryptoCurrencyName = cryptoCurrencyStatusProvider().currency.name, ) } @@ -251,14 +249,9 @@ internal class SendStateFactory( ) } - fun getTransactionSendState(txData: TransactionData): SendUiState { + fun getTransactionSendState(txData: TransactionData, txUrl: String): SendUiState { val state = currentStateProvider() - val cryptoCurrency = cryptoCurrencyStatusProvider().currency val sendState = state.sendState ?: return state - val txUrl = getExplorerTransactionUrlUseCase( - txHash = txData.hash.orEmpty(), - networkId = cryptoCurrency.network.id, - ).getOrElse { "" } return state.copy( sendState = sendState.copy( transactionDate = txData.date?.timeInMillis ?: System.currentTimeMillis(), diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt index e49450d38b..586c55c978 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt @@ -23,7 +23,7 @@ import java.math.BigDecimal internal data class SendUiState( val clickIntents: SendClickIntents, val isEditingDisabled: Boolean, - val cryptoCurrencySymbol: String, + val cryptoCurrencyName: String, val amountState: SendStates.AmountState? = null, val recipientState: SendStates.RecipientState? = null, val feeState: SendStates.FeeState? = null, diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt index 6a4e8a383e..fb65e2a8b5 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt @@ -8,6 +8,7 @@ import com.tangem.core.ui.extensions.networkIconResId import com.tangem.core.ui.utils.BigDecimalFormatter import com.tangem.core.ui.utils.parseToBigDecimal import com.tangem.domain.common.extensions.fromNetworkId +import com.tangem.domain.common.extensions.minimalAmount import com.tangem.domain.tokens.GetBalanceNotEnoughForFeeWarningUseCase import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus @@ -225,13 +226,14 @@ internal class SendNotificationFactory( val cryptoCurrencyStatus = cryptoCurrencyStatusProvider() val balance = cryptoCurrencyStatus.value.amount ?: BigDecimal.ZERO val isTezos = cryptoCurrencyStatus.currency.network.id.value == Blockchain.Tezos.id + val threshold = Blockchain.Tezos.minimalAmount() val isTotalBalance = feeAmount.plus(sendAmount) >= balance if (!ignoreAmountReduce && isTotalBalance && isTezos) { add( SendNotification.Warning.HighFeeError( - amount = TEZOS_FEE_THRESHOLD.toPlainString(), + amount = threshold.toPlainString(), onConfirmClick = { - val reduceTo = sendAmount.minus(TEZOS_FEE_THRESHOLD).toPlainString() + val reduceTo = sendAmount.minus(threshold).toPlainString() clickIntents.onAmountReduceClick(reduceTo, SendNotification.Warning.HighFeeError::class.java) }, onCloseClick = { @@ -372,7 +374,6 @@ internal class SendNotificationFactory( companion object { private const val DOGECOIN_MINIMUM = "0.01" - private val TEZOS_FEE_THRESHOLD = BigDecimal("0.01") internal val FEE_MAX_DIFF = BigInteger("5") } } \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt index 2dcff9830c..0294fefa3b 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendScreen.kt @@ -43,7 +43,7 @@ internal fun SendScreen(uiState: SendUiState, currentState: SendUiCurrentScreen) SendUiStateType.Recipient -> resourceReference(R.string.send_recipient_label) SendUiStateType.Fee -> resourceReference(R.string.common_fee_selector_title) SendUiStateType.Send -> if (!sendState.isSuccess) { - resourceReference(R.string.send_summary_title, wrappedList(uiState.cryptoCurrencySymbol)) + resourceReference(R.string.send_summary_title, wrappedList(uiState.cryptoCurrencyName)) } else { null } diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/SendContent.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/SendContent.kt index 0c92c24fd5..78809756c4 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/SendContent.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/SendContent.kt @@ -35,11 +35,7 @@ internal fun SendContent(uiState: SendUiState) { LazyColumn( modifier = Modifier .fillMaxSize() - .padding( - start = TangemTheme.dimens.spacing16, - end = TangemTheme.dimens.spacing16, - bottom = TangemTheme.dimens.spacing16, - ), + .padding(horizontal = TangemTheme.dimens.spacing16), ) { blocks(uiState) tapHelp(isDisplay = sendState.showTapHelp) diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt index 8564920606..9f1089fccf 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt @@ -89,9 +89,9 @@ internal class SendViewModel @Inject constructor( private val parseQrCodeUseCase: ParseQrCodeUseCase, private val isSendTapHelpEnabledUseCase: IsSendTapHelpEnabledUseCase, private val neverShowTapHelpUseCase: NeverShowTapHelpUseCase, + private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, currencyChecksRepository: CurrencyChecksRepository, isFeeApproximateUseCase: IsFeeApproximateUseCase, - getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, validateWalletMemoUseCase: ValidateWalletMemoUseCase, getBalanceNotEnoughForFeeWarningUseCase: GetBalanceNotEnoughForFeeWarningUseCase, savedStateHandle: SavedStateHandle, @@ -123,7 +123,6 @@ internal class SendViewModel @Inject constructor( cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus }, feeCryptoCurrencyStatusProvider = Provider { feeCryptoCurrencyStatus }, validateWalletMemoUseCase = validateWalletMemoUseCase, - getExplorerTransactionUrlUseCase = getExplorerTransactionUrlUseCase, isTapHelpPreviewEnabledProvider = Provider { isTapHelpPreviewEnabled }, ) @@ -647,8 +646,7 @@ internal class SendViewModel @Inject constructor( private fun autoNextFromRecipient(type: EnterAddressSource?, isValidAddress: Boolean) { val isRecent = type == EnterAddressSource.RecentAddress - val isAddressOnly = uiState.recipientState?.memoTextField == null - if (isRecent && isAddressOnly && isValidAddress) onNextClick() + if (isRecent && isValidAddress) onNextClick() } // endregion @@ -846,13 +844,21 @@ internal class SendViewModel @Inject constructor( }, ifRight = { uiState = stateFactory.getSendingStateUpdate(isSending = false) - uiState = stateFactory.getTransactionSendState(txData) + updateTransactionStatus(txData) scheduleBalanceUpdate() analyticsEventHandler.send(SendAnalyticEvents.TransactionScreenOpened) }, ) } + private suspend fun updateTransactionStatus(txData: TransactionData) { + val txUrl = getExplorerTransactionUrlUseCase( + userWalletId = userWalletId, + network = cryptoCurrency.network, + ).getOrElse { "" } + uiState = stateFactory.getTransactionSendState(txData, txUrl) + } + private fun scheduleBalanceUpdate() { viewModelScope.launch(dispatchers.io) { delay(BALANCE_UPDATE_DELAY) diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index 966b619bf8..0b77da443d 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -10,6 +10,7 @@ import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.extenstions.unwrap import com.tangem.domain.appcurrency.repository.AppCurrencyRepository +import com.tangem.domain.common.extensions.minimalAmount import com.tangem.domain.tokens.GetCryptoCurrencyStatusesSyncUseCase import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus @@ -433,7 +434,7 @@ internal class SwapInteractorImpl @Inject constructor( ) { val isTezos = fromTokenStatus.currency.network.id.value == Blockchain.Tezos.id if (isTezos && amount.value == fromTokenStatus.value.amount) { - warnings.add(Warning.ReduceAmountWarning(TEZOS_FEE_THRESHOLD)) + warnings.add(Warning.ReduceAmountWarning(Blockchain.Tezos.minimalAmount())) } } @@ -1595,6 +1596,5 @@ internal class SwapInteractorImpl @Inject constructor( private const val INCREASE_GAS_LIMIT_BY = 112 // 12% private const val INCREASE_GAS_LIMIT_FOR_SEND = 105 // 5% private const val INFINITY_SYMBOL = "∞" - private val TEZOS_FEE_THRESHOLD = BigDecimal("0.01") } } \ No newline at end of file