Updated on 2026-08-14

This commit is contained in:
Tangem 2024-02-09 11:43:29 +03:00
parent f65dcebf65
commit 1771ce7847
7 changed files with 150 additions and 0 deletions

View file

@ -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)
}
}

View file

@ -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<String, VisaCurrency>(),
)
private val fetchedHistoryItems = MutableStateFlow(
value = emptyMap<String, List<VisaTxHistoryResponse.Transaction>>(),
)
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)

View file

@ -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),
)
}
}

View file

@ -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<Map<String, List<VisaTxHistoryResponse.Transaction>>>,
private val dispatchers: CoroutineDispatcherProvider,
) : PagingSource<Int, VisaTxHistoryItem>() {
@ -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)

View file

@ -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<Throwable, VisaTxDetails> {
return Either.catch { visaRepository.getTxDetails(userWalletId, transactionId) }
}
}

View file

@ -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<Request>,
) {
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,
)
}

View file

@ -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<PagingData<VisaTxHistoryItem>>
suspend fun getTxDetails(userWalletId: UserWalletId, txId: String): VisaTxDetails
}