Updated on 2026-08-14
This commit is contained in:
commit
f7fb77fa70
10 changed files with 57 additions and 28 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<TxStatusError, String> {
|
||||
return either {
|
||||
catch(
|
||||
|
|
@ -22,4 +24,17 @@ class GetExplorerTransactionUrlUseCase(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend operator fun invoke(userWalletId: UserWalletId, network: Network): Either<TxStatusError, String> {
|
||||
return either {
|
||||
catch(
|
||||
block = {
|
||||
repository.getTxExploreUrl(userWalletId, network).ifEmpty {
|
||||
raise(TxStatusError.EmptyUrlError)
|
||||
}
|
||||
},
|
||||
catch = { raise(TxStatusError.DataError(it)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<CryptoCurrencyStatus?>,
|
||||
private val isTapHelpPreviewEnabledProvider: Provider<Boolean>,
|
||||
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(),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue