Updated on 2026-08-14
This commit is contained in:
parent
0c56df0075
commit
535bb9b8c3
44 changed files with 128 additions and 1038 deletions
|
|
@ -1,31 +0,0 @@
|
|||
package com.tangem.tap.network.exchangeServices
|
||||
|
||||
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.domain.model.Currency
|
||||
import com.tangem.tap.features.demo.isDemoCard
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class CardExchangeRules(
|
||||
val cardProvider: () -> CardDTO?,
|
||||
) : ExchangeRules {
|
||||
|
||||
override fun availableForBuy(scanResponse: ScanResponse, currency: Currency): Boolean {
|
||||
val card = scanResponse.card
|
||||
|
||||
return when {
|
||||
card.isDemoCard() -> true
|
||||
card.isStart2Coin -> false
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
||||
override fun availableForSell(currency: Currency): Boolean {
|
||||
val card = cardProvider() ?: return false
|
||||
|
||||
return !card.isStart2Coin
|
||||
}
|
||||
}
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
package com.tangem.tap.network.exchangeServices
|
||||
|
||||
import com.tangem.Message
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
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.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.extensions.safeUpdate
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.TangemSigner
|
||||
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
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class CurrencyExchangeManager(
|
||||
private val buyService: ExchangeService,
|
||||
private val sellService: ExchangeService,
|
||||
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()
|
||||
|
||||
if (!store.inject(DaggerGraphState::onrampFeatureToggles).isFeatureEnabled) {
|
||||
buyService.update()
|
||||
}
|
||||
|
||||
sellService.update()
|
||||
|
||||
_initializationStatus.value = lceContent()
|
||||
}
|
||||
|
||||
override fun availableForBuy(scanResponse: ScanResponse, currency: Currency): Boolean {
|
||||
return primaryRules.availableForBuy(scanResponse, currency) &&
|
||||
buyService.availableForBuy(scanResponse, currency)
|
||||
}
|
||||
|
||||
override fun availableForSell(currency: Currency): Boolean {
|
||||
return primaryRules.availableForSell(currency) && sellService.availableForSell(currency)
|
||||
}
|
||||
|
||||
override fun getUrl(
|
||||
action: Action,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
fiatCurrencyName: String,
|
||||
walletAddress: String,
|
||||
isDarkTheme: Boolean,
|
||||
): String? {
|
||||
val blockchain = cryptoCurrency.network.toBlockchain()
|
||||
if (blockchain.isTestnet()) return blockchain.getTestnetTopUpUrl()
|
||||
|
||||
val urlBuilder = getExchangeUrlBuilder(action)
|
||||
return urlBuilder.getUrl(
|
||||
action,
|
||||
cryptoCurrency,
|
||||
fiatCurrencyName,
|
||||
walletAddress,
|
||||
isDarkTheme,
|
||||
)
|
||||
}
|
||||
|
||||
override fun getSellCryptoReceiptUrl(action: Action, transactionId: String): String? {
|
||||
val urlBuilder = getExchangeUrlBuilder(action)
|
||||
return urlBuilder.getSellCryptoReceiptUrl(action, transactionId)
|
||||
}
|
||||
|
||||
private fun getExchangeUrlBuilder(action: Action): ExchangeUrlBuilder {
|
||||
return when (action) {
|
||||
Action.Buy -> buyService
|
||||
Action.Sell -> sellService
|
||||
}
|
||||
}
|
||||
|
||||
enum class Action { Buy, Sell }
|
||||
|
||||
companion object {
|
||||
fun dummy(): CurrencyExchangeManager = CurrencyExchangeManager(
|
||||
buyService = ExchangeService.dummy(),
|
||||
sellService = ExchangeService.dummy(),
|
||||
primaryRules = ExchangeRules.dummy(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Useless")
|
||||
suspend fun buyErc20TestnetTokens(card: CardDTO, walletManager: EthereumWalletManager, destinationAddress: String) {
|
||||
walletManager.safeUpdate(card.isDemoCard())
|
||||
|
||||
val amountToSend = Amount(walletManager.wallet.blockchain)
|
||||
|
||||
val feeResult = walletManager.getFee(amountToSend, destinationAddress) as? Result.Success ?: return
|
||||
val fee = when (val feeForTx = feeResult.data) {
|
||||
is TransactionFee.Choosable -> feeForTx.minimum
|
||||
is TransactionFee.Single -> feeForTx.normal
|
||||
}
|
||||
|
||||
val coinValue = walletManager.wallet.amounts[AmountType.Coin]?.value ?: BigDecimal.ZERO
|
||||
if (coinValue < fee.amount.value) return
|
||||
|
||||
val isCardNotBackedUp = card.backupStatus?.isActive != true && !card.isTangemTwins
|
||||
val signer = TangemSigner(
|
||||
cardId = card.cardId.takeIf { isCardNotBackedUp },
|
||||
tangemSdk = store.inject(DaggerGraphState::cardSdkConfigRepository).sdk,
|
||||
initialMessage = Message(),
|
||||
twinKey = null,
|
||||
) { signResponse ->
|
||||
store.dispatch(
|
||||
GlobalAction.UpdateWalletSignedHashes(
|
||||
walletSignedHashes = signResponse.totalSignedHashes,
|
||||
walletPublicKey = walletManager.wallet.publicKey.seedKey,
|
||||
remainingSignatures = signResponse.remainingSignatures,
|
||||
),
|
||||
)
|
||||
|
||||
store.dispatch(action = GlobalAction.IsSignWithRing(signResponse.isRing))
|
||||
}
|
||||
|
||||
walletManager.send(
|
||||
transactionData = walletManager.createTransaction(
|
||||
amount = amountToSend,
|
||||
fee = fee,
|
||||
destination = destinationAddress,
|
||||
),
|
||||
signer = signer,
|
||||
)
|
||||
}
|
||||
|
|
@ -20,7 +20,6 @@ import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason
|
|||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.onramp.OnrampFeatureToggles
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.runCatching
|
||||
|
|
@ -30,14 +29,11 @@ import kotlinx.coroutines.flow.firstOrNull
|
|||
|
||||
@Suppress("LongParameterList")
|
||||
internal class DefaultRampManager(
|
||||
private val exchangeService: ExchangeService?,
|
||||
private val buyService: Provider<ExchangeService>,
|
||||
private val sellService: Provider<ExchangeService>,
|
||||
private val expressServiceLoader: ExpressServiceLoader,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val getNetworkCoinStatusUseCase: GetNetworkCoinStatusUseCase,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val onrampFeatureToggles: OnrampFeatureToggles,
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
) : RampStateManager {
|
||||
|
||||
|
|
@ -48,9 +44,9 @@ internal class DefaultRampManager(
|
|||
userWalletId: UserWalletId,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
): ScenarioUnavailabilityReason {
|
||||
val availabilityState = runCatching {
|
||||
getOnrampAvailableState(scanResponse, userWalletId, cryptoCurrency)
|
||||
}.getOrNull() ?: ExpressAvailabilityState.Error
|
||||
val availabilityState = runCatching { getOnrampAvailableState(userWalletId, cryptoCurrency) }
|
||||
.getOrNull()
|
||||
?: ExpressAvailabilityState.Error
|
||||
|
||||
return availabilityState.toReason(cryptoCurrency.name)
|
||||
}
|
||||
|
|
@ -64,7 +60,7 @@ internal class DefaultRampManager(
|
|||
block = {
|
||||
val serviceCurrency = cryptoCurrencyConverter.convertBack(status.currency)
|
||||
|
||||
exchangeService?.availableForSell(currency = serviceCurrency) ?: false
|
||||
sellService().availableForSell(currency = serviceCurrency)
|
||||
},
|
||||
catch = { raise(ScenarioUnavailabilityReason.NotSupportedBySellService(status.currency.name)) },
|
||||
)
|
||||
|
|
@ -101,16 +97,6 @@ internal class DefaultRampManager(
|
|||
return availabilityState.toReason(cryptoCurrency.name)
|
||||
}
|
||||
|
||||
override fun getBuyInitializationStatus(): Flow<ExchangeServiceInitializationStatus> {
|
||||
return buyService.invoke().initializationStatus
|
||||
}
|
||||
|
||||
override suspend fun fetchBuyServiceData() {
|
||||
runCatching(dispatchers.io) {
|
||||
buyService.invoke().update()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSellInitializationStatus(): Flow<ExchangeServiceInitializationStatus> {
|
||||
return sellService.invoke().initializationStatus
|
||||
}
|
||||
|
|
@ -143,31 +129,20 @@ internal class DefaultRampManager(
|
|||
}
|
||||
|
||||
private suspend fun getOnrampAvailableState(
|
||||
scanResponse: ScanResponse,
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
): ExpressAvailabilityState {
|
||||
return when {
|
||||
onrampFeatureToggles.isFeatureEnabled -> {
|
||||
val asset = expressServiceLoader.getInitializationStatus(userWalletId).firstOrNull()
|
||||
?: return ExpressAvailabilityState.Loading
|
||||
return when (asset) {
|
||||
is Lce.Error -> ExpressAvailabilityState.Error
|
||||
is Lce.Loading -> ExpressAvailabilityState.Loading
|
||||
is Lce.Content -> {
|
||||
val foundAsset = asset.getOrNull()?.find { cryptoCurrency.findAssetPredicate(it) }
|
||||
foundAsset?.onrampAvailable?.toOnrampAvailabilityState()
|
||||
?: ExpressAvailabilityState.AssetNotFound
|
||||
}
|
||||
}
|
||||
val asset = expressServiceLoader.getInitializationStatus(userWalletId).firstOrNull()
|
||||
?: return ExpressAvailabilityState.Loading
|
||||
|
||||
return when (asset) {
|
||||
is Lce.Error -> ExpressAvailabilityState.Error
|
||||
is Lce.Loading -> ExpressAvailabilityState.Loading
|
||||
is Lce.Content -> {
|
||||
val foundAsset = asset.getOrNull()?.find { cryptoCurrency.findAssetPredicate(it) }
|
||||
foundAsset?.onrampAvailable?.toOnrampAvailabilityState()
|
||||
?: ExpressAvailabilityState.AssetNotFound
|
||||
}
|
||||
exchangeService != null -> {
|
||||
exchangeService.availableForBuy(
|
||||
scanResponse = scanResponse,
|
||||
currency = cryptoCurrencyConverter.convertBack(cryptoCurrency),
|
||||
).toOnrampAvailabilityState()
|
||||
}
|
||||
else -> ExpressAvailabilityState.Error
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,75 +1,26 @@
|
|||
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.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
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 availableForBuy(scanResponse: ScanResponse, currency: Currency): Boolean
|
||||
fun availableForSell(currency: Currency): Boolean
|
||||
}
|
||||
|
||||
interface ExchangeService : Exchanger, ExchangeUrlBuilder {
|
||||
interface ExchangeService {
|
||||
|
||||
val initializationStatus: StateFlow<ExchangeServiceInitializationStatus>
|
||||
|
||||
suspend fun update()
|
||||
|
||||
companion object {
|
||||
fun dummy(): ExchangeService = object : ExchangeService {
|
||||
fun availableForSell(currency: Currency): Boolean
|
||||
|
||||
override val initializationStatus: StateFlow<ExchangeServiceInitializationStatus> =
|
||||
MutableStateFlow(value = lceLoading())
|
||||
|
||||
override suspend fun update() {}
|
||||
override fun availableForBuy(scanResponse: ScanResponse, currency: Currency): Boolean = false
|
||||
override fun availableForSell(currency: Currency): Boolean = false
|
||||
override fun getUrl(
|
||||
action: CurrencyExchangeManager.Action,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
fiatCurrencyName: String,
|
||||
walletAddress: String,
|
||||
isDarkTheme: Boolean,
|
||||
): String? = null
|
||||
|
||||
override fun getSellCryptoReceiptUrl(
|
||||
action: CurrencyExchangeManager.Action,
|
||||
transactionId: String,
|
||||
): String? = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ExchangeRules : Exchanger {
|
||||
|
||||
companion object {
|
||||
fun dummy(): ExchangeRules = object : ExchangeRules {
|
||||
override fun availableForBuy(scanResponse: ScanResponse, currency: Currency): Boolean = false
|
||||
override fun availableForSell(currency: Currency): Boolean = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ExchangeUrlBuilder {
|
||||
@Suppress("LongParameterList")
|
||||
fun getUrl(
|
||||
action: CurrencyExchangeManager.Action,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
fiatCurrencyName: String,
|
||||
walletAddress: String,
|
||||
isDarkTheme: Boolean,
|
||||
): String?
|
||||
|
||||
fun getSellCryptoReceiptUrl(action: CurrencyExchangeManager.Action, transactionId: String): String?
|
||||
|
||||
companion object {
|
||||
const val SCHEME = "https"
|
||||
const val SUCCESS_URL = "https://tangem.com/success"
|
||||
}
|
||||
fun getSellCryptoReceiptUrl(transactionId: String): String?
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
package com.tangem.tap.network.exchangeServices.mercuryo
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Path
|
||||
|
||||
|
||||
interface MercuryoApi {
|
||||
|
||||
@GET("{apiVersion}/lib/currencies")
|
||||
suspend fun currencies(@Path("apiVersion") apiVersion: String): MercuryoCurrenciesResponse
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class MercuryoCurrenciesResponse(
|
||||
@Json(name = "status") val status: Int,
|
||||
@Json(name = "data") val data: Data,
|
||||
) {
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Data(
|
||||
@Json(name = "fiat") val fiat: List<String>,
|
||||
@Json(name = "crypto") val crypto: List<String>,
|
||||
@Json(name = "config") val config: Config,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Config(
|
||||
@Json(name = "crypto_currencies")
|
||||
val cryptoCurrencies: List<MercuryoCryptoCurrency>,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class MercuryoCryptoCurrency(
|
||||
@Json(name = "currency")
|
||||
val currencySymbol: String,
|
||||
@Json(name = "network")
|
||||
val network: String,
|
||||
@Json(name = "contract")
|
||||
val contractAddress: String,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
package com.tangem.tap.network.exchangeServices.mercuryo
|
||||
|
||||
import com.tangem.datasource.api.common.createRetrofitInstance
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
data class MercuryoEnvironment(
|
||||
val baseUrl: String,
|
||||
val apiVersion: String,
|
||||
val widgetId: String,
|
||||
val secret: String,
|
||||
val mercuryoApi: MercuryoApi,
|
||||
) {
|
||||
companion object {
|
||||
private const val BASE_URL = "https://api.mercuryo.io/"
|
||||
private const val API_VERSION = "v1.6"
|
||||
|
||||
fun prod(widgetId: String, secret: String, apiVersion: String = API_VERSION): MercuryoEnvironment {
|
||||
return MercuryoEnvironment(
|
||||
baseUrl = BASE_URL,
|
||||
apiVersion = apiVersion,
|
||||
widgetId = widgetId,
|
||||
secret = secret,
|
||||
mercuryoApi = createRetrofitInstance(
|
||||
baseUrl = BASE_URL,
|
||||
logEnabled = false,
|
||||
).create(MercuryoApi::class.java),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
package com.tangem.tap.network.exchangeServices.mercuryo
|
||||
|
||||
import android.net.Uri
|
||||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
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.data.onramp.legacy.mercuryoNetwork
|
||||
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.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
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
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
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 availableForBuy(scanResponse: ScanResponse, currency: Currency): Boolean {
|
||||
val mercuryoNetwork = currency.blockchain.mercuryoNetwork
|
||||
val contractAddress = (currency as? Currency.Token)?.token?.contractAddress ?: ""
|
||||
val availableCurrency = availableMercuryoCurrencies.firstOrNull {
|
||||
it.currencySymbol == currency.currencySymbol &&
|
||||
it.network == mercuryoNetwork &&
|
||||
it.contractAddress.equals(contractAddress, ignoreCase = true)
|
||||
}
|
||||
return availableCurrency != null
|
||||
}
|
||||
|
||||
override fun availableForSell(currency: Currency): Boolean = false
|
||||
|
||||
override fun getUrl(
|
||||
action: CurrencyExchangeManager.Action,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
fiatCurrencyName: String,
|
||||
walletAddress: String,
|
||||
isDarkTheme: Boolean,
|
||||
): String {
|
||||
if (action == CurrencyExchangeManager.Action.Sell) throw UnsupportedOperationException()
|
||||
|
||||
val blockchain = cryptoCurrency.network.toBlockchain()
|
||||
|
||||
val builder = Uri.Builder()
|
||||
.scheme(ExchangeUrlBuilder.SCHEME)
|
||||
.authority("exchange.mercuryo.io")
|
||||
.appendQueryParameter("widget_id", environment.widgetId)
|
||||
.appendQueryParameter("type", action.name.lowercase())
|
||||
.appendQueryParameter("currency", cryptoCurrency.symbol)
|
||||
.appendQueryParameter("address", walletAddress)
|
||||
.appendQueryParameter("signature", signature(walletAddress))
|
||||
.appendQueryParameter("fix_currency", "true")
|
||||
.appendQueryParameter("redirect_url", ExchangeUrlBuilder.SUCCESS_URL)
|
||||
if (isDarkTheme) builder.appendQueryParameter("theme", "1inch")
|
||||
|
||||
blockchain.mercuryoNetwork?.let {
|
||||
builder.appendQueryParameter("network", it)
|
||||
}
|
||||
|
||||
return builder.build().toString()
|
||||
}
|
||||
|
||||
override fun getSellCryptoReceiptUrl(action: CurrencyExchangeManager.Action, transactionId: String): String? = null
|
||||
|
||||
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()
|
||||
|
||||
private companion object {
|
||||
const val RESPONSE_SUCCESS_STATUS_CODE = 200
|
||||
}
|
||||
}
|
||||
|
|
@ -6,17 +6,16 @@ import com.tangem.blockchainsdk.utils.toBlockchain
|
|||
import com.tangem.common.services.Result
|
||||
import com.tangem.common.services.performRequest
|
||||
import com.tangem.datasource.api.common.createRetrofitInstance
|
||||
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
||||
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.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
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
|
||||
|
|
@ -28,6 +27,7 @@ class MoonPayService(
|
|||
private val apiKey: String,
|
||||
private val secretKey: String,
|
||||
private val logEnabled: Boolean,
|
||||
private val cardProvider: () -> CardDTO?,
|
||||
) : ExchangeService {
|
||||
|
||||
override val initializationStatus: StateFlow<ExchangeServiceInitializationStatus>
|
||||
|
|
@ -102,9 +102,12 @@ class MoonPayService(
|
|||
}
|
||||
}
|
||||
|
||||
override fun availableForBuy(scanResponse: ScanResponse, currency: Currency): Boolean = false
|
||||
|
||||
override fun availableForSell(currency: Currency): Boolean {
|
||||
val card = cardProvider() ?: return false
|
||||
val checkCardExchange = !card.isStart2Coin
|
||||
|
||||
if (!checkCardExchange) return false
|
||||
|
||||
if (!isSellAllowed()) return false
|
||||
|
||||
val availableForSell = status?.availableForSell ?: return false
|
||||
|
|
@ -125,15 +128,14 @@ class MoonPayService(
|
|||
}
|
||||
|
||||
override fun getUrl(
|
||||
action: CurrencyExchangeManager.Action,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
fiatCurrencyName: String,
|
||||
walletAddress: String,
|
||||
isDarkTheme: Boolean,
|
||||
): String? {
|
||||
if (action == CurrencyExchangeManager.Action.Buy) throw UnsupportedOperationException()
|
||||
|
||||
val blockchain = cryptoCurrency.network.toBlockchain()
|
||||
if (blockchain.isTestnet()) return blockchain.getTestnetTopUpUrl()
|
||||
|
||||
val supportedCurrency = blockchain.moonPaySupportedCurrency ?: return null
|
||||
val moonpayCurrency = status?.availableForSell?.firstOrNull {
|
||||
when (cryptoCurrency) {
|
||||
|
|
@ -165,7 +167,7 @@ class MoonPayService(
|
|||
return uri.build().toString()
|
||||
}
|
||||
|
||||
override fun getSellCryptoReceiptUrl(action: CurrencyExchangeManager.Action, transactionId: String): String {
|
||||
override fun getSellCryptoReceiptUrl(transactionId: String): String {
|
||||
return Uri.Builder()
|
||||
.scheme(SCHEME)
|
||||
.authority(URL_SELL)
|
||||
|
|
@ -185,8 +187,9 @@ class MoonPayService(
|
|||
return status?.responseUserStatus?.isSellAllowed ?: false
|
||||
}
|
||||
|
||||
companion object {
|
||||
private companion object {
|
||||
const val URL_SELL = "sell.moonpay.com"
|
||||
const val SCHEME = "https"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue