Updated on 2026-08-14
This commit is contained in:
parent
a4beb2cafc
commit
bd62089c12
39 changed files with 149 additions and 664 deletions
|
|
@ -5,6 +5,7 @@ import arrow.core.left
|
|||
import arrow.core.raise.catch
|
||||
import arrow.core.raise.either
|
||||
import arrow.core.right
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.data.tokens.utils.CryptoCurrencyFactory
|
||||
|
|
@ -13,12 +14,12 @@ import com.tangem.datasource.api.common.response.ApiResponseError
|
|||
import com.tangem.datasource.api.common.response.getOrThrow
|
||||
import com.tangem.datasource.api.express.TangemExpressApi
|
||||
import com.tangem.datasource.api.express.models.request.PairsRequestBody
|
||||
import com.tangem.datasource.api.express.models.response.ExchangeDataResponseWithTxDetails
|
||||
import com.tangem.datasource.api.express.models.response.SwapPair
|
||||
import com.tangem.datasource.api.express.models.response.SwapPairsWithProviders
|
||||
import com.tangem.datasource.api.oneinch.OneInchApi
|
||||
import com.tangem.datasource.api.oneinch.OneInchApiFactory
|
||||
import com.tangem.datasource.api.express.models.response.TxDetails
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.config.ConfigManager
|
||||
import com.tangem.datasource.crypto.DataSignatureVerifier
|
||||
import com.tangem.domain.common.extensions.fromNetworkId
|
||||
import com.tangem.domain.common.util.derivationStyleProvider
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
|
|
@ -34,20 +35,23 @@ import com.tangem.feature.swap.domain.models.domain.*
|
|||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
import java.math.BigDecimal
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
import com.tangem.datasource.api.express.models.request.LeastTokenInfo as NetworkLeastTokenInfo
|
||||
|
||||
@Suppress("LongParameterList", "LargeClass")
|
||||
internal class SwapRepositoryImpl @Inject constructor(
|
||||
internal class DefaultSwapRepository @Inject constructor(
|
||||
private val tangemTechApi: TangemTechApi,
|
||||
private val tangemExpressApi: TangemExpressApi,
|
||||
private val oneInchApiFactory: OneInchApiFactory,
|
||||
private val coroutineDispatcher: CoroutineDispatcherProvider,
|
||||
private val configManager: ConfigManager,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val walletsStateHolder: WalletsStateHolder,
|
||||
private val errorsDataConverter: ErrorsDataConverter,
|
||||
private val dataSignatureVerifier: DataSignatureVerifier,
|
||||
moshi: Moshi,
|
||||
) : SwapRepository {
|
||||
|
||||
private val tokensConverter = TokensConverter()
|
||||
|
|
@ -56,6 +60,7 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
private val swapPairInfoConverter = SwapPairInfoConverter()
|
||||
private val cryptoCurrencyFactory = CryptoCurrencyFactory()
|
||||
private val exchangeStatusConverter = ExchangeStatusConverter()
|
||||
private val txDetailsMoshiAdapter = moshi.adapter(TxDetails::class.java)
|
||||
|
||||
override suspend fun getPairs(
|
||||
initialCurrency: LeastTokenInfo,
|
||||
|
|
@ -253,12 +258,6 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun addressForTrust(networkId: String): String {
|
||||
return withContext(coroutineDispatcher.io) {
|
||||
getOneInchApi(networkId).approveSpender().address
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getExchangeData(
|
||||
fromContractAddress: String,
|
||||
fromNetwork: String,
|
||||
|
|
@ -273,6 +272,7 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
): Either<DataError, SwapDataModel> {
|
||||
return withContext(coroutineDispatcher.io) {
|
||||
try {
|
||||
val requestId = UUID.randomUUID().toString()
|
||||
val response = tangemExpressApi.getExchangeData(
|
||||
fromContractAddress = fromContractAddress,
|
||||
fromNetwork = fromNetwork,
|
||||
|
|
@ -284,16 +284,36 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
providerId = providerId,
|
||||
rateType = rateType.name.lowercase(),
|
||||
toAddress = toAddress,
|
||||
requestId = requestId,
|
||||
).getOrThrow()
|
||||
expressDataConverter.convert(response).right()
|
||||
if (dataSignatureVerifier.verifySignature(response.signature, response.txDetailsJson)) {
|
||||
val txDetails = parseTxDetails(response.txDetailsJson)
|
||||
?: return@withContext DataError.UnknownError.left()
|
||||
if (txDetails.requestId != requestId) {
|
||||
return@withContext DataError.InvalidRequestIdError().left()
|
||||
}
|
||||
expressDataConverter.convert(
|
||||
ExchangeDataResponseWithTxDetails(
|
||||
dataResponse = response,
|
||||
txDetails = txDetails,
|
||||
),
|
||||
).right()
|
||||
} else {
|
||||
DataError.InvalidSignatureError().left()
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
getDataError(ex).left()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTangemFee(): Double {
|
||||
return configManager.config.swapReferrerAccount?.fee?.toDoubleOrNull() ?: 0.0
|
||||
private fun parseTxDetails(txDetailsJson: String): TxDetails? {
|
||||
return try {
|
||||
txDetailsMoshiAdapter.fromJson(txDetailsJson)
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e, "error parsing txDetailsJson")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getAllowance(
|
||||
|
|
@ -367,10 +387,6 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun getOneInchApi(networkId: String): OneInchApi {
|
||||
return oneInchApiFactory.getApi(networkId)
|
||||
}
|
||||
|
||||
override fun getNativeTokenForNetwork(networkId: String): CryptoCurrency {
|
||||
val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" }
|
||||
|
||||
|
|
@ -1,36 +1,42 @@
|
|||
package com.tangem.feature.swap.converters
|
||||
|
||||
import com.tangem.datasource.api.express.models.response.ExchangeDataResponse
|
||||
import com.tangem.datasource.api.express.models.response.ExchangeDataResponseWithTxDetails
|
||||
import com.tangem.datasource.api.express.models.response.TxDetails
|
||||
import com.tangem.datasource.api.express.models.response.TxType
|
||||
import com.tangem.feature.swap.domain.models.createFromAmountWithOffset
|
||||
import com.tangem.feature.swap.domain.models.domain.ExpressTransactionModel
|
||||
import com.tangem.feature.swap.domain.models.domain.SwapDataModel
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
class ExpressDataConverter : Converter<ExchangeDataResponse, SwapDataModel> {
|
||||
internal class ExpressDataConverter : Converter<ExchangeDataResponseWithTxDetails, SwapDataModel> {
|
||||
|
||||
override fun convert(value: ExchangeDataResponse): SwapDataModel {
|
||||
override fun convert(value: ExchangeDataResponseWithTxDetails): SwapDataModel {
|
||||
val data = value.dataResponse
|
||||
return SwapDataModel(
|
||||
toTokenAmount = createFromAmountWithOffset(value.toAmount, value.toDecimals),
|
||||
transaction = convertTransaction(value),
|
||||
toTokenAmount = createFromAmountWithOffset(data.toAmount, data.toDecimals),
|
||||
transaction = convertTransaction(value.txDetails, data),
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertTransaction(transactionDto: ExchangeDataResponse): ExpressTransactionModel {
|
||||
private fun convertTransaction(
|
||||
transactionDto: TxDetails,
|
||||
dataResponse: ExchangeDataResponse,
|
||||
): ExpressTransactionModel {
|
||||
return if (transactionDto.txType == TxType.SWAP) {
|
||||
ExpressTransactionModel.DEX(
|
||||
fromAmount = createFromAmountWithOffset(transactionDto.fromAmount, transactionDto.fromDecimals),
|
||||
toAmount = createFromAmountWithOffset(transactionDto.toAmount, transactionDto.toDecimals),
|
||||
txId = transactionDto.txId,
|
||||
fromAmount = createFromAmountWithOffset(dataResponse.fromAmount, dataResponse.fromDecimals),
|
||||
toAmount = createFromAmountWithOffset(dataResponse.toAmount, dataResponse.toDecimals),
|
||||
txId = dataResponse.txId,
|
||||
txTo = transactionDto.txTo,
|
||||
txFrom = requireNotNull(transactionDto.txFrom),
|
||||
txData = requireNotNull(transactionDto.txData),
|
||||
)
|
||||
} else {
|
||||
ExpressTransactionModel.CEX(
|
||||
fromAmount = createFromAmountWithOffset(transactionDto.fromAmount, transactionDto.fromDecimals),
|
||||
toAmount = createFromAmountWithOffset(transactionDto.toAmount, transactionDto.toDecimals),
|
||||
txId = transactionDto.txId,
|
||||
fromAmount = createFromAmountWithOffset(dataResponse.fromAmount, dataResponse.fromDecimals),
|
||||
toAmount = createFromAmountWithOffset(dataResponse.toAmount, dataResponse.toDecimals),
|
||||
txId = dataResponse.txId,
|
||||
txTo = transactionDto.txTo,
|
||||
externalTxId = requireNotNull(transactionDto.externalTxId),
|
||||
externalTxUrl = requireNotNull(transactionDto.externalTxUrl),
|
||||
|
|
|
|||
|
|
@ -3,18 +3,17 @@ package com.tangem.feature.swap.di
|
|||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.datasource.api.express.TangemExpressApi
|
||||
import com.tangem.datasource.api.express.models.response.ExpressErrorResponse
|
||||
import com.tangem.datasource.api.oneinch.OneInchApiFactory
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.config.ConfigManager
|
||||
import com.tangem.datasource.crypto.DataSignatureVerifier
|
||||
import com.tangem.datasource.di.NetworkMoshi
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.WalletsStateHolder
|
||||
import com.tangem.feature.swap.SwapRepositoryImpl
|
||||
import com.tangem.feature.swap.converters.ErrorsDataConverter
|
||||
import com.tangem.feature.swap.DefaultSwapTransactionRepository
|
||||
import com.tangem.feature.swap.domain.api.SwapRepository
|
||||
import com.tangem.feature.swap.DefaultSwapRepository
|
||||
import com.tangem.feature.swap.converters.ErrorsDataConverter
|
||||
import com.tangem.feature.swap.domain.SwapTransactionRepository
|
||||
import com.tangem.feature.swap.domain.api.SwapRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
|
@ -31,22 +30,22 @@ internal class SwapDataModule {
|
|||
internal fun provideSwapRepository(
|
||||
tangemTechApi: TangemTechApi,
|
||||
tangemExpressApi: TangemExpressApi,
|
||||
oneInchApiFactory: OneInchApiFactory,
|
||||
coroutineDispatcher: CoroutineDispatcherProvider,
|
||||
configManager: ConfigManager,
|
||||
dataSignature: DataSignatureVerifier,
|
||||
walletManagerFacade: WalletManagersFacade,
|
||||
walletsStateHolder: WalletsStateHolder,
|
||||
errorsDataConverter: ErrorsDataConverter,
|
||||
@NetworkMoshi moshi: Moshi,
|
||||
): SwapRepository {
|
||||
return SwapRepositoryImpl(
|
||||
return DefaultSwapRepository(
|
||||
tangemTechApi = tangemTechApi,
|
||||
tangemExpressApi = tangemExpressApi,
|
||||
oneInchApiFactory = oneInchApiFactory,
|
||||
coroutineDispatcher = coroutineDispatcher,
|
||||
configManager = configManager,
|
||||
walletManagersFacade = walletManagerFacade,
|
||||
walletsStateHolder = walletsStateHolder,
|
||||
errorsDataConverter = errorsDataConverter,
|
||||
dataSignatureVerifier = dataSignature,
|
||||
moshi = moshi,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue