diff --git a/app/src/main/java/com/tangem/tap/di/domain/VisaDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/VisaDomainModule.kt index 2795fe2a8c..479be1cc3c 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/VisaDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/VisaDomainModule.kt @@ -1,6 +1,7 @@ package com.tangem.tap.di.domain import com.tangem.domain.visa.GetVisaCurrencyUseCase +import com.tangem.domain.visa.GetVisaTxDetailsUseCase import com.tangem.domain.visa.GetVisaTxHistoryUseCase import com.tangem.domain.visa.repository.VisaRepository import dagger.Module @@ -24,4 +25,10 @@ internal object VisaDomainModule { fun provideGetVisaTxHistoryUseCase(visaRepository: VisaRepository): GetVisaTxHistoryUseCase { return GetVisaTxHistoryUseCase(visaRepository) } + + @Provides + @ViewModelScoped + fun provideGetVisaTxDetailsUseCase(visaRepository: VisaRepository): GetVisaTxDetailsUseCase { + return GetVisaTxDetailsUseCase(visaRepository) + } } \ No newline at end of file diff --git a/data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaRepository.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaRepository.kt index e2e0bc5567..d14a201a2b 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaRepository.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaRepository.kt @@ -11,22 +11,26 @@ import com.tangem.common.extensions.toHexString import com.tangem.data.common.cache.CacheRegistry import com.tangem.data.visa.utils.VisaConfig import com.tangem.data.visa.utils.VisaCurrencyFactory +import com.tangem.data.visa.utils.VisaTxDetailsFactory import com.tangem.data.visa.utils.VisaTxHistoryPagingSource import com.tangem.datasource.api.common.response.getOrThrow import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.visa.model.VisaCurrency +import com.tangem.domain.visa.model.VisaTxDetails import com.tangem.domain.visa.model.VisaTxHistoryItem import com.tangem.domain.visa.repository.VisaRepository import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWalletId import com.tangem.lib.visa.VisaContractInfoProvider import com.tangem.lib.visa.api.VisaApi +import com.tangem.lib.visa.model.VisaTxHistoryResponse import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update +import kotlinx.coroutines.withContext import java.math.BigDecimal internal class DefaultVisaRepository( @@ -41,10 +45,16 @@ internal class DefaultVisaRepository( private val currencyFactory by lazy(mode = LazyThreadSafetyMode.NONE) { VisaCurrencyFactory() } + private val txDetailsFactory by lazy(mode = LazyThreadSafetyMode.NONE) { + VisaTxDetailsFactory() + } private val fetchedCurrencies = MutableStateFlow( value = hashMapOf(), ) + private val fetchedHistoryItems = MutableStateFlow( + value = emptyMap>(), + ) override suspend fun getVisaCurrency(userWalletId: UserWalletId, isRefresh: Boolean): VisaCurrency { val address = makeAddress(userWalletId) @@ -102,6 +112,7 @@ internal class DefaultVisaRepository( ), cacheRegistry = cacheRegistry, visaApi = visaApi, + fetchedItems = fetchedHistoryItems, dispatchers = dispatchers, ) }, @@ -110,6 +121,23 @@ internal class DefaultVisaRepository( return pager.flow } + override suspend fun getTxDetails(userWalletId: UserWalletId, txId: String): VisaTxDetails { + return withContext(dispatchers.io) { + val userWallet = findVisaUserWallet(userWalletId) + val cardPubKey = getCardPubKey(userWallet).toHexString() + // val cardPubKey = "03DEF02B1FECC8BD3CFD52CE93235194479E1DE931EF0F55DC194967E7CCC3D12C" // for testing + val transaction = fetchedHistoryItems.value[cardPubKey]?.firstOrNull { + it.transactionId.toString() == txId + } + requireNotNull(transaction) { "Transaction not found: $txId" } + + txDetailsFactory.create( + transaction = transaction, + walletBlockchain = userWallet.scanResponse.cardTypesResolver.getBlockchain(), + ) + } + } + private suspend fun makeAddress(userWalletId: UserWalletId): String { val userWallet = findVisaUserWallet(userWalletId) val walletAddresses = makeWalletAddresses(userWallet) diff --git a/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxDetailsFactory.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxDetailsFactory.kt new file mode 100644 index 0000000000..ad0bbf4fb3 --- /dev/null +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxDetailsFactory.kt @@ -0,0 +1,49 @@ +package com.tangem.data.visa.utils + +import com.tangem.blockchain.common.Blockchain +import com.tangem.domain.visa.model.VisaTxDetails +import com.tangem.lib.visa.model.VisaTxHistoryResponse + +internal class VisaTxDetailsFactory { + + fun create(transaction: VisaTxHistoryResponse.Transaction, walletBlockchain: Blockchain): VisaTxDetails { + return VisaTxDetails( + id = transaction.transactionId.toString(), + type = transaction.transactionType, + status = transaction.transactionStatus, + blockchainAmount = transaction.blockchainAmount, + blockchainFee = transaction.blockchainFee, + transactionAmount = transaction.transactionAmount, + transactionCurrencyCode = transaction.transactionCurrencyCode, + merchantName = transaction.merchantName, + merchantCity = transaction.merchantCity, + merchantCountryCode = transaction.merchantCountryCode, + merchantCategoryCode = transaction.merchantCategoryCode, + fiatCurrency = findCurrencyByNumericCode(transaction.transactionCurrencyCode), + requests = transaction.requests.map { createRequest(it, walletBlockchain) }, + ) + } + + private fun createRequest( + request: VisaTxHistoryResponse.Transaction.Request, + walletBlockchain: Blockchain, + ): VisaTxDetails.Request { + return VisaTxDetails.Request( + billingAmount = request.billingAmount, + billingCurrencyCode = request.billingCurrencyCode, + blockchainAmount = request.blockchainAmount, + blockchainFee = request.blockchainFee, + errorCode = request.errorCode, + requestDate = request.requestDt, + requestStatus = request.requestStatus, + requestType = request.requestType, + transactionAmount = request.transactionAmount, + txCurrencyCode = request.transactionCurrencyCode, + id = request.transactionRequestId.toString(), + txHash = request.txHash, + txStatus = request.txStatus, + fiatCurrency = findCurrencyByNumericCode(request.transactionCurrencyCode), + exploreUrl = request.txHash?.let(walletBlockchain::getExploreTxUrl), + ) + } +} \ No newline at end of file diff --git a/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxHistoryPagingSource.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxHistoryPagingSource.kt index 1c54f97d8d..4af82f3014 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxHistoryPagingSource.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxHistoryPagingSource.kt @@ -6,6 +6,7 @@ import com.tangem.data.common.cache.CacheRegistry import com.tangem.datasource.api.common.response.getOrThrow import com.tangem.domain.visa.model.VisaTxHistoryItem import com.tangem.lib.visa.api.VisaApi +import com.tangem.lib.visa.model.VisaTxHistoryResponse import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update @@ -16,6 +17,7 @@ internal class VisaTxHistoryPagingSource( params: Params, private val cacheRegistry: CacheRegistry, private val visaApi: VisaApi, + private val fetchedItems: MutableStateFlow>>, private val dispatchers: CoroutineDispatcherProvider, ) : PagingSource() { @@ -77,6 +79,12 @@ internal class VisaTxHistoryPagingSource( offset = offset, ).getOrThrow() + fetchedItems.update { + it.toMutableMap().apply { + this[cardPublicKey] = this[cardPublicKey].orEmpty() + response.transactions + } + } + pagedItems.update { it.toMutableMap().apply { this[offset] = response.transactions.map(itemsFactory::create) diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/visa/GetVisaTxDetailsUseCase.kt b/domain/visa/src/main/kotlin/com/tangem/domain/visa/GetVisaTxDetailsUseCase.kt new file mode 100644 index 0000000000..3ff945017f --- /dev/null +++ b/domain/visa/src/main/kotlin/com/tangem/domain/visa/GetVisaTxDetailsUseCase.kt @@ -0,0 +1,15 @@ +package com.tangem.domain.visa + +import arrow.core.Either +import com.tangem.domain.visa.model.VisaTxDetails +import com.tangem.domain.visa.repository.VisaRepository +import com.tangem.domain.wallets.models.UserWalletId + +class GetVisaTxDetailsUseCase( + private val visaRepository: VisaRepository, +) { + + suspend operator fun invoke(userWalletId: UserWalletId, transactionId: String): Either { + return Either.catch { visaRepository.getTxDetails(userWalletId, transactionId) } + } +} \ No newline at end of file diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/visa/model/VisaTxDetails.kt b/domain/visa/src/main/kotlin/com/tangem/domain/visa/model/VisaTxDetails.kt new file mode 100644 index 0000000000..1e833b7c16 --- /dev/null +++ b/domain/visa/src/main/kotlin/com/tangem/domain/visa/model/VisaTxDetails.kt @@ -0,0 +1,40 @@ +package com.tangem.domain.visa.model + +import org.joda.time.DateTime +import java.math.BigDecimal +import java.util.Currency + +data class VisaTxDetails( + val id: String, + val type: String, + val status: String, + val blockchainAmount: BigDecimal, + val blockchainFee: BigDecimal, + val transactionAmount: BigDecimal, + val transactionCurrencyCode: Int, + val merchantName: String?, + val merchantCity: String?, + val merchantCountryCode: String?, + val merchantCategoryCode: String?, + val fiatCurrency: Currency, + val requests: List, +) { + + data class Request( + val id: String, + val billingAmount: BigDecimal, + val billingCurrencyCode: Int, + val blockchainAmount: BigDecimal, + val blockchainFee: BigDecimal, + val errorCode: Int, + val requestDate: DateTime, + val requestStatus: String, + val requestType: String, + val transactionAmount: BigDecimal, + val txCurrencyCode: Int, + val txHash: String?, + val txStatus: String?, + val exploreUrl: String?, + val fiatCurrency: Currency, + ) +} \ No newline at end of file diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/visa/repository/VisaRepository.kt b/domain/visa/src/main/kotlin/com/tangem/domain/visa/repository/VisaRepository.kt index bd3860aa2b..dac5f4cf72 100644 --- a/domain/visa/src/main/kotlin/com/tangem/domain/visa/repository/VisaRepository.kt +++ b/domain/visa/src/main/kotlin/com/tangem/domain/visa/repository/VisaRepository.kt @@ -2,6 +2,7 @@ package com.tangem.domain.visa.repository import androidx.paging.PagingData import com.tangem.domain.visa.model.VisaCurrency +import com.tangem.domain.visa.model.VisaTxDetails import com.tangem.domain.visa.model.VisaTxHistoryItem import com.tangem.domain.wallets.models.UserWalletId import kotlinx.coroutines.flow.Flow @@ -15,4 +16,6 @@ interface VisaRepository { pageSize: Int, isRefresh: Boolean = false, ): Flow> + + suspend fun getTxDetails(userWalletId: UserWalletId, txId: String): VisaTxDetails } \ No newline at end of file