diff --git a/app/src/main/java/com/tangem/tap/di/domain/OnrampDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/OnrampDomainModule.kt index 1b04e8f513..2c276a7117 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/OnrampDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/OnrampDomainModule.kt @@ -3,6 +3,7 @@ package com.tangem.tap.di.domain import com.tangem.domain.onramp.* import com.tangem.domain.onramp.repositories.OnrampErrorResolver import com.tangem.domain.onramp.repositories.OnrampRepository +import com.tangem.domain.onramp.repositories.OnrampTransactionRepository import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -63,4 +64,36 @@ internal object OnrampDomainModule { fun provideGetOnrampCurrencyUseCase(onrampRepository: OnrampRepository): GetOnrampCurrencyUseCase { return GetOnrampCurrencyUseCase(onrampRepository) } + + @Provides + @Singleton + fun provideGetOnrampTransactionsUseCase( + onrampTransactionRepository: OnrampTransactionRepository, + ): GetOnrampTransactionsUseCase { + return GetOnrampTransactionsUseCase(onrampTransactionRepository) + } + + @Provides + @Singleton + fun provideGetOnrampTransactionUseCase( + onrampTransactionRepository: OnrampTransactionRepository, + ): GetOnrampTransactionUseCase { + return GetOnrampTransactionUseCase(onrampTransactionRepository) + } + + @Provides + @Singleton + fun provideOnrampRemoveTransactionUseCase( + onrampTransactionRepository: OnrampTransactionRepository, + ): OnrampRemoveTransactionUseCase { + return OnrampRemoveTransactionUseCase(onrampTransactionRepository) + } + + @Provides + @Singleton + fun provideOnrampSaveTransactionUseCase( + onrampTransactionRepository: OnrampTransactionRepository, + ): OnrampSaveTransactionUseCase { + return OnrampSaveTransactionUseCase(onrampTransactionRepository) + } } \ No newline at end of file diff --git a/data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt b/data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt index fb9ff22adb..047150c42e 100644 --- a/data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt @@ -14,15 +14,11 @@ import com.tangem.blockchain.common.Token as SdkToken class ResponseCryptoCurrenciesFactory { - fun createCurrency( - currencyId: CryptoCurrency.ID, - response: UserTokensResponse, - scanResponse: ScanResponse, - ): CryptoCurrency { + fun createCurrency(currencyId: String, response: UserTokensResponse, scanResponse: ScanResponse): CryptoCurrency { return response.tokens .asSequence() .mapNotNull { createCurrency(it, scanResponse) } - .first { it.id == currencyId } + .first { it.id.value == currencyId } } fun createCurrencies(response: UserTokensResponse, scanResponse: ScanResponse): List { diff --git a/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampTransactionRepository.kt b/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampTransactionRepository.kt index 85fb0b94f9..eaaad04a78 100644 --- a/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampTransactionRepository.kt +++ b/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampTransactionRepository.kt @@ -47,12 +47,12 @@ internal class DefaultOnrampTransactionRepository( override fun getTransactions( userWalletId: UserWalletId, - toCryptoCurrency: CryptoCurrency.ID, + cryptoCurrencyId: CryptoCurrency.ID, ): Flow> = appPreferencesStore .getObjectSet(PreferencesKeys.ONRAMP_TRANSACTIONS_STATUSES_KEY) .map { transactions -> transactions.filter { - it.userWalletId == userWalletId && it.toCurrency.id == toCryptoCurrency + it.userWalletId == userWalletId && it.toCurrencyId == cryptoCurrencyId.value } } diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt index 31282f6f34..1d25e1ea81 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt @@ -293,23 +293,28 @@ internal class DefaultCurrenciesRepository( userWalletId: UserWalletId, id: CryptoCurrency.ID, ): CryptoCurrency = withContext(dispatchers.io) { - val userWallet = getUserWallet(userWalletId) - ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = true) - - val response = requireNotNull( - value = getSavedUserTokensResponseSync(key = userWalletId), - lazyMessage = { - "Unable to find tokens response for user wallet with provided ID: $userWalletId" - }, - ) - - responseCurrenciesFactory.createCurrency( - currencyId = id, - response = response, - scanResponse = userWallet.scanResponse, - ) + getMultiCurrencyWalletCurrency(userWalletId, id.value) } + override suspend fun getMultiCurrencyWalletCurrency(userWalletId: UserWalletId, id: String): CryptoCurrency = + withContext(dispatchers.io) { + val userWallet = getUserWallet(userWalletId) + ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = true) + + val response = requireNotNull( + value = getSavedUserTokensResponseSync(key = userWalletId), + lazyMessage = { + "Unable to find tokens response for user wallet with provided ID: $userWalletId" + }, + ) + + responseCurrenciesFactory.createCurrency( + currencyId = id, + response = response, + scanResponse = userWallet.scanResponse, + ) + } + override suspend fun getNetworkCoin( userWalletId: UserWalletId, networkId: Network.ID, diff --git a/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/OnrampStatus.kt b/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/OnrampStatus.kt index eec20f05f7..69ecefb695 100644 --- a/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/OnrampStatus.kt +++ b/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/OnrampStatus.kt @@ -23,16 +23,32 @@ data class OnrampStatus( val paymentMethod: String, val countryCode: String, ) { - enum class Status { - Created, - Expired, - Paused, - WaitingForPayment, - PaymentProcessing, - Verifying, - Failed, - Paid, - Sending, - Finished, + enum class Status(val order: Int) { + Created(order = 1), + Expired(order = 2), + Paused(order = 3), + WaitingForPayment(order = 4), + PaymentProcessing(order = 5), + Verifying(order = 6), + Failed(order = 7), + Paid(order = 8), + Sending(order = 9), + Finished(order = 10), + ; + + fun isTerminal(): Boolean = when (this) { + Expired, + Failed, + Paused, + Finished, + -> true + Created, + WaitingForPayment, + PaymentProcessing, + Verifying, + Paid, + Sending, + -> false + } } } \ No newline at end of file diff --git a/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/cache/OnrampTransaction.kt b/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/cache/OnrampTransaction.kt index 9753bc85e7..96f069b02f 100644 --- a/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/cache/OnrampTransaction.kt +++ b/domain/onramp/models/src/main/kotlin/com/tangem/domain/onramp/model/cache/OnrampTransaction.kt @@ -2,7 +2,6 @@ package com.tangem.domain.onramp.model.cache import com.tangem.domain.core.serialization.SerializedBigDecimal import com.tangem.domain.onramp.model.OnrampCurrency -import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWalletId import kotlinx.serialization.Serializable @@ -13,8 +12,7 @@ data class OnrampTransaction( val fromAmount: SerializedBigDecimal, val fromCurrency: OnrampCurrency, val toAmount: SerializedBigDecimal, - val toCurrency: CryptoCurrency, - val timestamp: Long, + val toCurrencyId: String, val providerName: String, val providerImageUrl: String, ) \ No newline at end of file diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/GetOnrampTransactionUseCase.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/GetOnrampTransactionUseCase.kt new file mode 100644 index 0000000000..0e33b2e91a --- /dev/null +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/GetOnrampTransactionUseCase.kt @@ -0,0 +1,21 @@ +package com.tangem.domain.onramp + +import arrow.core.Either +import com.tangem.domain.onramp.model.OnrampError +import com.tangem.domain.onramp.model.cache.OnrampTransaction +import com.tangem.domain.onramp.repositories.OnrampTransactionRepository + +class GetOnrampTransactionUseCase( + private val onrampTransactionRepository: OnrampTransactionRepository, +) { + + suspend operator fun invoke(txId: String): Either { + return Either.catch { + requireNotNull( + onrampTransactionRepository.getTransactionById(txId), + ) + }.mapLeft { + OnrampError.UnknownError + } + } +} \ No newline at end of file diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/GetOnrampTransactionsUseCase.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/GetOnrampTransactionsUseCase.kt new file mode 100644 index 0000000000..af51320013 --- /dev/null +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/GetOnrampTransactionsUseCase.kt @@ -0,0 +1,28 @@ +package com.tangem.domain.onramp + +import arrow.core.Either +import com.tangem.domain.onramp.model.OnrampError +import com.tangem.domain.onramp.model.cache.OnrampTransaction +import com.tangem.domain.onramp.repositories.OnrampTransactionRepository +import com.tangem.domain.tokens.model.CryptoCurrency +import com.tangem.domain.wallets.models.UserWalletId +import kotlinx.coroutines.flow.Flow + +class GetOnrampTransactionsUseCase( + private val onrampTransactionRepository: OnrampTransactionRepository, +) { + + operator fun invoke( + userWalletId: UserWalletId, + cryptoCurrencyId: CryptoCurrency.ID, + ): Either>> { + return Either.catch { + onrampTransactionRepository.getTransactions( + userWalletId = userWalletId, + cryptoCurrencyId = cryptoCurrencyId, + ) + }.mapLeft { + OnrampError.UnknownError + } + } +} \ No newline at end of file diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampRemoveTransactionUseCase.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampRemoveTransactionUseCase.kt new file mode 100644 index 0000000000..4a6062ece8 --- /dev/null +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampRemoveTransactionUseCase.kt @@ -0,0 +1,18 @@ +package com.tangem.domain.onramp + +import arrow.core.Either +import com.tangem.domain.onramp.model.OnrampError +import com.tangem.domain.onramp.repositories.OnrampTransactionRepository + +class OnrampRemoveTransactionUseCase( + private val onrampTransactionRepository: OnrampTransactionRepository, +) { + + suspend operator fun invoke(txId: String): Either { + return Either.catch { + onrampTransactionRepository.removeTransaction(txId) + }.mapLeft { + OnrampError.UnknownError + } + } +} \ No newline at end of file diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampSaveTransactionUseCase.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampSaveTransactionUseCase.kt new file mode 100644 index 0000000000..d939933d9c --- /dev/null +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampSaveTransactionUseCase.kt @@ -0,0 +1,16 @@ +package com.tangem.domain.onramp + +import arrow.core.Either +import com.tangem.domain.onramp.model.OnrampError +import com.tangem.domain.onramp.model.cache.OnrampTransaction +import com.tangem.domain.onramp.repositories.OnrampTransactionRepository + +class OnrampSaveTransactionUseCase( + private val onrampTransactionRepository: OnrampTransactionRepository, +) { + + suspend operator fun invoke(transaction: OnrampTransaction): Either { + return Either.catch { onrampTransactionRepository.storeTransaction(transaction) } + .mapLeft { OnrampError.UnknownError } + } +} \ No newline at end of file diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampTransactionRepository.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampTransactionRepository.kt index 5796bec18e..24105314b1 100644 --- a/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampTransactionRepository.kt +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampTransactionRepository.kt @@ -11,7 +11,7 @@ interface OnrampTransactionRepository { suspend fun getTransactionById(txId: String): OnrampTransaction? - fun getTransactions(userWalletId: UserWalletId, toCryptoCurrency: CryptoCurrency.ID): Flow> + fun getTransactions(userWalletId: UserWalletId, cryptoCurrencyId: CryptoCurrency.ID): Flow> suspend fun removeTransaction(txId: String) } \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyUseCase.kt index d0e47c2b62..b24eb525ae 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyUseCase.kt @@ -27,6 +27,22 @@ class GetCryptoCurrencyUseCase( return either { getCurrency(userWalletId, id) } } + /** + * Returns specific cryptocurrency for a given user wallet. + * + * !!! Important Use only [CryptoCurrency.ID.value] as cryptoCurrencyId + * + * @param userWalletId The ID of the user's wallet. + * @param cryptoCurrencyId String representation of the [CryptoCurrency.ID.value] of the cryptocurrency. + * @return An [Either] representing success (Right) or an error (Left) in fetching the status. + */ + suspend operator fun invoke( + userWalletId: UserWalletId, + cryptoCurrencyId: String, + ): Either { + return either { getCurrency(userWalletId, cryptoCurrencyId) } + } + /** * Returns the primary cryptocurrency for a given user wallet. * @@ -49,6 +65,18 @@ class GetCryptoCurrencyUseCase( ) } + private suspend fun Raise.getCurrency( + userWalletId: UserWalletId, + id: String, + ): CryptoCurrency { + return catch( + block = { + currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId, id) + }, + catch = { raise(CurrencyStatusError.DataError(it)) }, + ) + } + private suspend fun Raise.getPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency { return catch( block = { currenciesRepository.getSingleCurrencyWalletPrimaryCurrency(userWalletId) }, diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt index bda0e8fdbd..27691a8495 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/CurrenciesRepository.kt @@ -167,6 +167,17 @@ interface CurrenciesRepository { */ suspend fun getMultiCurrencyWalletCurrency(userWalletId: UserWalletId, id: CryptoCurrency.ID): CryptoCurrency + /** + * Retrieves the cryptocurrency for a specific multi-currency user wallet. + * + * @param userWalletId The unique identifier of the user wallet. + * @param id The unique identifier of the cryptocurrency to be retrieved. + * @return The cryptocurrency associated with the user wallet and ID. + * @throws DataError.UserWalletError.WrongUserWallet If single-currency user wallet + * ID provided. + */ + suspend fun getMultiCurrencyWalletCurrency(userWalletId: UserWalletId, id: String): CryptoCurrency + /** * Get the coin for a specific network. *