From bed70c4dc843bd3cb0202fde995982b9282ba996 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 5 Nov 2024 16:29:41 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../common/redux/global/GlobalMiddleware.kt | 8 +++- .../java/com/tangem/tap/di/ActivityModule.kt | 3 ++ .../CurrencyExchangeManager.kt | 14 ++++++ .../exchangeServices/DefaultRampManager.kt | 13 ++++++ .../exchangeServices/ExchangeService.kt | 13 ++++++ .../mercuryo/MercuryoService.kt | 46 ++++++++++++++----- .../moonpay/MoonPayService.kt | 30 +++++++++++- .../com/tangem/tap/proxy/AppStateHolder.kt | 7 +-- domain/legacy/build.gradle.kts | 1 + .../domain/exchange/RampStateManager.kt | 6 +++ 10 files changed, 120 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt index c4366e8215..b8865305c5 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt @@ -64,12 +64,16 @@ private fun handleAction(action: Action, appState: () -> AppState?) { } val cardProvider: () -> CardDTO? = { scanResponseProvider.invoke()?.card } + val buyService = makeBuyExchangeService(config) + val sellService = makeSellExchangeService(config) val exchangeManager = CurrencyExchangeManager( - buyService = makeBuyExchangeService(config), - sellService = makeSellExchangeService(config), + buyService = buyService, + sellService = sellService, primaryRules = CardExchangeRules(cardProvider), ) // TODO: for refactoring (after remove old design refactor CurrencyExchangeManager and use 1 instance) + store.inject(DaggerGraphState::appStateHolder).buyService = buyService + store.inject(DaggerGraphState::appStateHolder).sellService = sellService store.inject(DaggerGraphState::appStateHolder).exchangeService = exchangeManager store.dispatchOnMain(GlobalAction.ExchangeManager.Init.Success(exchangeManager)) store.dispatchOnMain(GlobalAction.ExchangeManager.Update) diff --git a/app/src/main/java/com/tangem/tap/di/ActivityModule.kt b/app/src/main/java/com/tangem/tap/di/ActivityModule.kt index 3908c30790..9e18be5306 100644 --- a/app/src/main/java/com/tangem/tap/di/ActivityModule.kt +++ b/app/src/main/java/com/tangem/tap/di/ActivityModule.kt @@ -11,6 +11,7 @@ import com.tangem.sdk.api.TangemSdkManager import com.tangem.tap.domain.scanCard.repository.DefaultScanCardRepository import com.tangem.tap.network.exchangeServices.DefaultRampManager import com.tangem.tap.proxy.AppStateHolder +import com.tangem.utils.Provider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -46,6 +47,8 @@ internal object ActivityModule { ): RampStateManager { return DefaultRampManager( exchangeService = appStateHolder.exchangeService, + buyService = Provider { requireNotNull(appStateHolder.buyService) }, + sellService = Provider { requireNotNull(appStateHolder.sellService) }, marketsCryptoCurrencyRepository = marketCryptoCurrencyRepository, ) } diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt index 71c317e080..0e9092a1fa 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt @@ -8,6 +8,8 @@ import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.blockchain.extensions.Result import com.tangem.domain.common.TapWorkarounds.isTangemTwins +import com.tangem.domain.core.utils.lceContent +import com.tangem.domain.core.utils.lceLoading import com.tangem.domain.models.scan.CardDTO import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.model.CryptoCurrency @@ -19,6 +21,8 @@ import com.tangem.tap.domain.model.Currency import com.tangem.tap.features.demo.isDemoCard import com.tangem.tap.proxy.redux.DaggerGraphState import com.tangem.tap.store +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import java.math.BigDecimal /** @@ -30,9 +34,19 @@ class CurrencyExchangeManager( private val primaryRules: ExchangeRules, ) : ExchangeService { + override val initializationStatus: StateFlow + get() = _initializationStatus + + private val _initializationStatus: MutableStateFlow = + MutableStateFlow(value = lceLoading()) + override suspend fun update() { + _initializationStatus.value = lceLoading() + buyService.update() sellService.update() + + _initializationStatus.value = lceContent() } override fun isBuyAllowed(): Boolean = primaryRules.isBuyAllowed() && buyService.isBuyAllowed() diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt index 5d6d7c5b2b..2ce18c2fe0 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/DefaultRampManager.kt @@ -5,13 +5,18 @@ import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.repository.MarketCryptoCurrencyRepository import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.utils.Provider +import kotlinx.coroutines.flow.Flow class DefaultRampManager( private val exchangeService: ExchangeService?, + private val buyService: Provider, + private val sellService: Provider, private val marketsCryptoCurrencyRepository: MarketCryptoCurrencyRepository, ) : RampStateManager { private val cryptoCurrencyConverter = CryptoCurrencyConverter() + override fun availableForBuy(scanResponse: ScanResponse, cryptoCurrency: CryptoCurrency): Boolean { return exchangeService?.availableForBuy( scanResponse, @@ -28,4 +33,12 @@ class DefaultRampManager( override suspend fun availableForSwap(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Boolean { return marketsCryptoCurrencyRepository.isExchangeable(userWalletId, cryptoCurrency) } + + override fun getBuyInitializationStatus(): Flow { + return buyService.invoke().initializationStatus + } + + override fun getSellInitializationStatus(): Flow { + return sellService.invoke().initializationStatus + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt index 495bcec410..e49b386c9d 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt @@ -1,8 +1,14 @@ package com.tangem.tap.network.exchangeServices +import com.tangem.domain.core.lce.Lce +import com.tangem.domain.core.utils.lceLoading import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.tap.domain.model.Currency +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow + +typealias ExchangeServiceInitializationStatus = Lce interface Exchanger { fun isBuyAllowed(): Boolean @@ -12,10 +18,17 @@ interface Exchanger { } interface ExchangeService : Exchanger, ExchangeUrlBuilder { + + val initializationStatus: StateFlow + suspend fun update() companion object { fun dummy(): ExchangeService = object : ExchangeService { + + override val initializationStatus: StateFlow = + MutableStateFlow(value = lceLoading()) + override suspend fun update() {} override fun isBuyAllowed(): Boolean = false override fun isSellAllowed(): Boolean = false diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt index 50b558907b..bd46579044 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt @@ -6,12 +6,19 @@ import com.tangem.common.extensions.calculateSha512 import com.tangem.common.extensions.toHexString import com.tangem.common.services.Result import com.tangem.common.services.performRequest +import com.tangem.domain.core.utils.lceContent +import com.tangem.domain.core.utils.lceError +import com.tangem.domain.core.utils.lceLoading import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.tap.domain.model.Currency import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager import com.tangem.tap.network.exchangeServices.ExchangeService +import com.tangem.tap.network.exchangeServices.ExchangeServiceInitializationStatus import com.tangem.tap.network.exchangeServices.ExchangeUrlBuilder +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import timber.log.Timber import java.util.concurrent.CopyOnWriteArrayList /** @@ -19,10 +26,34 @@ import java.util.concurrent.CopyOnWriteArrayList */ internal class MercuryoService(private val environment: MercuryoEnvironment) : ExchangeService { + override val initializationStatus: StateFlow + get() = _initializationStatus + + private val _initializationStatus: MutableStateFlow = + MutableStateFlow(value = lceLoading()) + private val api: MercuryoApi = environment.mercuryoApi private val availableMercuryoCurrencies = CopyOnWriteArrayList() + override suspend fun update() { + Timber.i("Start updating") + _initializationStatus.value = lceLoading() + + val result = performRequest { api.currencies(environment.apiVersion) } + when { + result is Result.Success && result.data.status == RESPONSE_SUCCESS_STATUS_CODE -> { + handleSuccessfullyUpdatedData(data = result.data.data) + } + result is Result.Failure -> { + availableMercuryoCurrencies.clear() + + Timber.e("Failed to load currencies", result.error) + _initializationStatus.value = result.error.lceError() + } + } + } + override fun isBuyAllowed(): Boolean = true override fun isSellAllowed(): Boolean = false @@ -42,18 +73,6 @@ internal class MercuryoService(private val environment: MercuryoEnvironment) : E override fun availableForSell(currency: Currency): Boolean = false - override suspend fun update() { - val result = performRequest { api.currencies(environment.apiVersion) } - when { - result is Result.Success && result.data.status == RESPONSE_SUCCESS_STATUS_CODE -> { - handleSuccessfullyUpdatedData(data = result.data.data) - } - result is Result.Failure -> { - availableMercuryoCurrencies.clear() - } - } - } - override fun getUrl( action: CurrencyExchangeManager.Action, cryptoCurrency: CryptoCurrency, @@ -89,6 +108,9 @@ internal class MercuryoService(private val environment: MercuryoEnvironment) : E private fun handleSuccessfullyUpdatedData(data: MercuryoCurrenciesResponse.Data) { availableMercuryoCurrencies.clear() availableMercuryoCurrencies.addAll(data.config.cryptoCurrencies) + + Timber.i("Successfully updated") + _initializationStatus.value = lceContent() } private fun signature(address: String) = (address + environment.secret).calculateSha512().toHexString().lowercase() diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt index 26b26f0b61..90011a2d77 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt @@ -7,13 +7,20 @@ import com.tangem.common.services.Result import com.tangem.common.services.performRequest import com.tangem.datasource.api.common.createRetrofitInstance import com.tangem.domain.common.extensions.withIOContext +import com.tangem.domain.core.utils.lceContent +import com.tangem.domain.core.utils.lceError +import com.tangem.domain.core.utils.lceLoading import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.tap.domain.model.Currency import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager import com.tangem.tap.network.exchangeServices.ExchangeService +import com.tangem.tap.network.exchangeServices.ExchangeServiceInitializationStatus import com.tangem.tap.network.exchangeServices.ExchangeUrlBuilder.Companion.SCHEME import com.tangem.tap.network.exchangeServices.moonpay.models.MoonPayAvailableCurrency +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import timber.log.Timber import javax.crypto.Mac import javax.crypto.spec.SecretKeySpec @@ -23,6 +30,12 @@ class MoonPayService( private val logEnabled: Boolean, ) : ExchangeService { + override val initializationStatus: StateFlow + get() = _initializationStatus + + private val _initializationStatus: MutableStateFlow = + MutableStateFlow(value = lceLoading()) + private val api: MoonPayApi by lazy { createRetrofitInstance( baseUrl = MoonPayApi.MOOONPAY_BASE_URL, @@ -34,14 +47,25 @@ class MoonPayService( override suspend fun update() { withIOContext { + Timber.i("Start updating") + _initializationStatus.value = lceLoading() + performRequest { val userStatus = when (val result = performRequest { api.getUserStatus(apiKey) }) { - is Result.Failure -> return@performRequest + is Result.Failure -> { + Timber.e("Failed to load user status", result.error) + _initializationStatus.value = result.error.lceError() + return@performRequest + } is Result.Success -> result.data } val currencies = when (val result = performRequest { api.getCurrencies(apiKey) }) { - is Result.Failure -> return@performRequest + is Result.Failure -> { + Timber.e("Failed to load currencies", result.error) + _initializationStatus.value = result.error.lceError() + return@performRequest + } is Result.Success -> result.data } @@ -58,6 +82,8 @@ class MoonPayService( ) } + Timber.i("Successfully updated") + _initializationStatus.value = lceContent() status = MoonPayStatus(currenciesToSell, userStatus, currencies) } } diff --git a/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt b/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt index f626aa4238..18c616034a 100644 --- a/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt +++ b/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt @@ -1,6 +1,5 @@ package com.tangem.tap.proxy -import com.tangem.domain.models.scan.CardDTO import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.redux.ReduxStateHolder import com.tangem.domain.redux.StateDialog @@ -26,10 +25,8 @@ class AppStateHolder @Inject constructor() : ReduxStateHolder { var mainStore: Store? = null var tangemSdkManager: TangemSdkManager? = null var exchangeService: ExchangeService? = null - - fun getActualCard(): CardDTO? { - return scanResponse?.card - } + var buyService: ExchangeService? = null + var sellService: ExchangeService? = null override fun dispatch(action: Action) { mainStore?.dispatch(action) diff --git a/domain/legacy/build.gradle.kts b/domain/legacy/build.gradle.kts index f01a2e6a96..ab9922a279 100644 --- a/domain/legacy/build.gradle.kts +++ b/domain/legacy/build.gradle.kts @@ -14,6 +14,7 @@ dependencies { implementation(projects.common) implementation(projects.libs.auth) implementation(projects.libs.blockchainSdk) + implementation(projects.domain.core) implementation(projects.domain.demo) implementation(projects.domain.models) implementation(projects.domain.tokens.models) diff --git a/domain/legacy/src/main/java/com/tangem/domain/exchange/RampStateManager.kt b/domain/legacy/src/main/java/com/tangem/domain/exchange/RampStateManager.kt index b7a3bde7fc..423ecdc390 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/exchange/RampStateManager.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/exchange/RampStateManager.kt @@ -1,8 +1,10 @@ package com.tangem.domain.exchange +import com.tangem.domain.core.lce.Lce import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWalletId +import kotlinx.coroutines.flow.Flow /** * Manager that holds info about available actions as Sell and Buy @@ -14,4 +16,8 @@ interface RampStateManager { fun availableForSell(cryptoCurrency: CryptoCurrency): Boolean suspend fun availableForSwap(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): Boolean + + fun getBuyInitializationStatus(): Flow> + + fun getSellInitializationStatus(): Flow> } \ No newline at end of file