Updated on 2026-08-14
This commit is contained in:
parent
c32507b283
commit
bed70c4dc8
10 changed files with 120 additions and 21 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<ExchangeServiceInitializationStatus>
|
||||
get() = _initializationStatus
|
||||
|
||||
private val _initializationStatus: MutableStateFlow<ExchangeServiceInitializationStatus> =
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -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<ExchangeService>,
|
||||
private val sellService: Provider<ExchangeService>,
|
||||
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<ExchangeServiceInitializationStatus> {
|
||||
return buyService.invoke().initializationStatus
|
||||
}
|
||||
|
||||
override fun getSellInitializationStatus(): Flow<ExchangeServiceInitializationStatus> {
|
||||
return sellService.invoke().initializationStatus
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Throwable, Any>
|
||||
|
||||
interface Exchanger {
|
||||
fun isBuyAllowed(): Boolean
|
||||
|
|
@ -12,10 +18,17 @@ interface Exchanger {
|
|||
}
|
||||
|
||||
interface ExchangeService : Exchanger, ExchangeUrlBuilder {
|
||||
|
||||
val initializationStatus: StateFlow<ExchangeServiceInitializationStatus>
|
||||
|
||||
suspend fun update()
|
||||
|
||||
companion object {
|
||||
fun dummy(): ExchangeService = object : ExchangeService {
|
||||
|
||||
override val initializationStatus: StateFlow<ExchangeServiceInitializationStatus> =
|
||||
MutableStateFlow(value = lceLoading())
|
||||
|
||||
override suspend fun update() {}
|
||||
override fun isBuyAllowed(): Boolean = false
|
||||
override fun isSellAllowed(): Boolean = false
|
||||
|
|
|
|||
|
|
@ -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<ExchangeServiceInitializationStatus>
|
||||
get() = _initializationStatus
|
||||
|
||||
private val _initializationStatus: MutableStateFlow<ExchangeServiceInitializationStatus> =
|
||||
MutableStateFlow(value = lceLoading())
|
||||
|
||||
private val api: MercuryoApi = environment.mercuryoApi
|
||||
|
||||
private val availableMercuryoCurrencies = CopyOnWriteArrayList<MercuryoCurrenciesResponse.MercuryoCryptoCurrency>()
|
||||
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -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<ExchangeServiceInitializationStatus>
|
||||
get() = _initializationStatus
|
||||
|
||||
private val _initializationStatus: MutableStateFlow<ExchangeServiceInitializationStatus> =
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<AppState>? = 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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue