diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index 6ef8ce45d1..0be5650f8f 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit 6ef8ce45d183905b5752e2d33c1d8bf2f4bcace6 +Subproject commit 0be5650f8fbcdff22c23fe2e2c7d754c4275a6f6 diff --git a/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt b/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt index 70d580f3c7..6cd26d788e 100644 --- a/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt +++ b/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt @@ -15,7 +15,7 @@ internal class DefaultExpressAuthProvider( private var uuid = AtomicReference(UUID.randomUUID()) override fun getApiKey(): String { - return configManager.config.tangemExpressApiKey + return configManager.config.express?.apiKey ?: "" } override fun getUserId(): String { diff --git a/app/src/main/java/com/tangem/tap/network/auth/DefaultOneInchProvider.kt b/app/src/main/java/com/tangem/tap/network/auth/DefaultOneInchProvider.kt deleted file mode 100644 index ade4f48a0f..0000000000 --- a/app/src/main/java/com/tangem/tap/network/auth/DefaultOneInchProvider.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.tangem.tap.network.auth - -import com.tangem.datasource.config.ConfigManager -import com.tangem.lib.auth.AuthBearerProvider - -internal class DefaultOneInchProvider( - private val configManager: ConfigManager, -) : AuthBearerProvider { - - override fun getApiKey(): String { - return configManager.config.oneInchApiKey - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt b/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt index d59b3f4792..fa9aa920a1 100644 --- a/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt +++ b/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt @@ -2,12 +2,10 @@ package com.tangem.tap.network.auth.di import com.tangem.datasource.config.ConfigManager import com.tangem.datasource.local.userwallet.UserWalletsStore -import com.tangem.lib.auth.AuthBearerProvider import com.tangem.lib.auth.AuthProvider import com.tangem.lib.auth.ExpressAuthProvider import com.tangem.tap.network.auth.DefaultAuthProvider import com.tangem.tap.network.auth.DefaultExpressAuthProvider -import com.tangem.tap.network.auth.DefaultOneInchProvider import com.tangem.tap.proxy.AppStateHolder import dagger.Module import dagger.Provides @@ -36,12 +34,4 @@ class AuthModule { configManager = configManager, ) } - - @Provides - @Singleton - fun provideOneInchAuthProvider(configManager: ConfigManager): AuthBearerProvider { - return DefaultOneInchProvider( - configManager = configManager, - ) - } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt index b78d485fa6..61c2a6c25a 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt @@ -49,6 +49,7 @@ interface TangemExpressApi { @Query("providerId") providerId: String, @Query("rateType") rateType: String, @Query("toAddress") toAddress: String, + @Query("requestId") requestId: String, ): ApiResponse @GET("exchange-status") diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeDataResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeDataResponse.kt index b44fa2a019..40c3483f16 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeDataResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeDataResponse.kt @@ -3,6 +3,10 @@ package com.tangem.datasource.api.express.models.response import com.squareup.moshi.Json import java.math.BigDecimal +data class ExchangeDataResponseWithTxDetails( + val dataResponse: ExchangeDataResponse, + val txDetails: TxDetails, +) data class ExchangeDataResponse( @Json(name = "fromAmount") val fromAmount: String, @@ -16,12 +20,23 @@ data class ExchangeDataResponse( @Json(name = "toDecimals") val toDecimals: Int, - @Json(name = "txType") - val txType: TxType, - @Json(name = "txId") val txId: String, // inner tangem-express transaction id + @Json(name = "txDetailsJson") + val txDetailsJson: String, + + @Json(name = "signature") + val signature: String, +) + +data class TxDetails( + @Json(name = "requestId") + val requestId: String, + + @Json(name = "txType") + val txType: TxType, + @Json(name = "txFrom") val txFrom: String?, // account for debiting tokens (same as toAddress) if DEX, null if CEX diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/OneInchApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/OneInchApi.kt deleted file mode 100644 index cf950a0f66..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/OneInchApi.kt +++ /dev/null @@ -1,205 +0,0 @@ -package com.tangem.datasource.api.oneinch - -import com.tangem.datasource.api.oneinch.models.AllowanceResponse -import com.tangem.datasource.api.oneinch.models.ApproveCalldataResponse -import com.tangem.datasource.api.oneinch.models.ApproveSpenderResponse -import com.tangem.datasource.api.oneinch.models.ProtocolsResponse -import com.tangem.datasource.api.oneinch.models.QuoteResponse -import com.tangem.datasource.api.oneinch.models.StatusResponse -import com.tangem.datasource.api.oneinch.models.SwapResponse -import com.tangem.datasource.api.oneinch.models.TokensResponse -import retrofit2.Response -import retrofit2.http.GET -import retrofit2.http.Query - -interface OneInchApi { - - /** - * Healthcheck return 200 if service is available - * - * @return [StatusResponse] - */ - @GET("healthcheck") - suspend fun healthcheck(): StatusResponse - - //region Approve - /** - * Address of the 1inch router that must be trusted to spend funds for the exchange - * - * @return [ApproveSpenderResponse] - */ - @GET("approve/spender") - suspend fun approveSpender(): ApproveSpenderResponse - - /** - * Generate data for calling the contract in order to allow the 1inch router to spend funds - * - * @param tokenAddress Token address you want to exchange - * @param amount The number of tokens that the 1inch router is allowed to spend. - * If not specified, it will be allowed to spend an infinite amount of tokens. - * - * @return [ApproveCalldataResponse] Transaction body to allow the exchange with the 1inch router - */ - @GET("approve/transaction") - suspend fun approveTransaction( - @Query("tokenAddress") tokenAddress: String, - @Query("amount") amount: String? = null, - ): ApproveCalldataResponse - - /** - * Get the number of tokens that the 1inch router is allowed to spend - * - * @param tokenAddress Token address you want to exchange - * @param walletAddress Wallet address for which you want to check - * - * @return [AllowanceResponse] - */ - @GET("approve/allowance") - suspend fun approveAllowance( - @Query("tokenAddress") tokenAddress: String, - @Query("walletAddress") walletAddress: String, - ): Response - //endregion Approve - - //region Info - /** - * List of tokens that are available for swap in the 1inch Aggregation protocol - * - * @return [TokensResponse] - */ - @GET("tokens") - suspend fun tokensAvailable(): TokensResponse - - /** - * List of liquidity sources that are available for routing in the 1inch Aggregation protocol - * - * @return - */ - @GET("liquidity-sources") - suspend fun liquiditySources(): ProtocolsResponse - //endregion Info - - //region Swap - /** - * Find the best quote to exchange via 1inch router - * - * @param fromTokenAddress Example : 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE - * @param toTokenAddress Example : 0x111111111117dc0aa78b770fa6a738034120c302 - * @param amount amount of a token to sell, set in minimal divisible units e.g.: - * 1.00 DAI set as 1000000000000000000 - * 51.03 USDC set as 51030000 - * - * @param protocols default: all - * @param fee this percentage of fromTokenAddress token amount will be sent to referrerAddress, - * the rest will be used as input for a swap - * Min: 0; max: 3; Max: 0; max: 3; default: 0; !should be the same for quote and swap! - * - * @param gasLimit maximum amount of gas for a swap; - * @param connectorTokens token-connectors can be specified via this parameter. - * The more is set — the longer route estimation will take. - * If not set, default token-connectors will be usedmax: 5; !should be the same for quote and swap! - * - * @param complexityLevel maximum number of token-connectors to be used in a transaction. - * The more is used — the longer route estimation will take - * min: 0; max: 3; default: 2; !should be the same for quote and swap! - * - * @param mainRouteParts default: 10; max: 50 !should be the same for quote and swap! - * @param parts limit maximum number of parts each main route parts can be split into; - * should be the same for a quote and swap - * default: 20; max: 100 - * - * @param gasPrice 1inch takes in account gas expenses to determine exchange route. - * It is important to use the same gas price on the quote and swap methods. - * Gas price set in wei: 12.5 GWEI set as 12500000000 - * default: fast from network - * - * @return [QuoteResponse] - */ - @GET("quote") - suspend fun quote( - @Query("src") fromTokenAddress: String, - @Query("dst") toTokenAddress: String, - @Query("amount") amount: String, - @Query("protocols") protocols: String? = null, - @Query("fee") fee: String? = null, - @Query("gasLimit") gasLimit: String? = null, - @Query("connectorTokens") connectorTokens: String? = null, - @Query("complexityLevel") complexityLevel: String? = null, - @Query("mainRouteParts") mainRouteParts: String? = null, - @Query("parts") parts: String? = null, - @Query("gasPrice") gasPrice: String? = null, - @Query("includeTokensInfo") includeTokensInfo: Boolean = true, - ): Response - - /** - * Generate data for calling the 1inch router for exchange - * - * @param fromTokenAddress Example : 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE - * @param toTokenAddress Example : 0x111111111117dc0aa78b770fa6a738034120c302 - * @param amount amount of a token to sell, set in minimal divisible units e.g.: - * 1.00 DAI set as 1000000000000000000 - * 51.03 USDC set as 51030000 - * - * @param fromAddress The address that calls the 1inch contract - * @param slippage limit of price slippage you are willing to accept in percentage, may be set with decimals. - * &slippage=0.5 means 0.5% slippage is acceptable. Low values increase chances that transaction will fail, - * high values increase chances of front running. min: 0; max: 50; - * - * @param protocols default: all - * @param destinationAddress Receiver of destination currency. default: fromAddress - * @param fee this percentage of fromTokenAddress token amount will be sent to referrerAddress, - * the rest will be used as input for a swap - * Min: 0; max: 3; Max: 0; max: 3; default: 0; !should be the same for quote and swap! - * - * @param permit https://eips.ethereum.org/EIPS/eip-2612 - * @param compatibilityMode Allows to build calldata without optimized routers - * @param burnChi If true, CHI will be burned from fromAddress to compensate gas. - * Check CHI balance and allowance before turning that on. CHI should be approved for the spender address - * - * @param connectorTokens token-connectors can be specified via this parameter. - * The more is set — the longer route estimation will take. - * If not set, default token-connectors will be usedmax: 5; !should be the same for quote and swap! - * - * @param complexityLevel maximum number of token-connectors to be used in a transaction. - * The more is used — the longer route estimation will take - * min: 0; max: 3; default: 2; !should be the same for quote and swap! - * - * @param mainRouteParts default: 10; max: 50 !should be the same for quote and swap! - * @param parts limit maximum number of parts each main route parts can be split into; - * should be the same for a quote and swap - * default: 20; max: 100 - * - * @param gasLimit maximum amount of gas for a swap; - * @param gasPrice 1inch takes in account gas expenses to determine exchange route. - * It is important to use the same gas price on the quote and swap methods. - * Gas price set in wei: 12.5 GWEI set as 12500000000 - * default: fast from network - * - * @return [SwapResponse] - */ - @GET("swap") - suspend fun swap( - @Query("src") fromTokenAddress: String, - @Query("dst") toTokenAddress: String, - @Query("amount") amount: String, - @Query("from") fromAddress: String, - @Query("slippage") slippage: Int, - @Query("protocols") protocols: String? = null, - @Query("receiver") destinationAddress: String? = null, - @Query("referrer") referrerAddress: String? = null, - @Query("fee") fee: String? = null, - @Query("disableEstimate") disableEstimate: Boolean? = null, - @Query("permit") permit: String? = null, - @Query("compatibility") compatibilityMode: Boolean? = null, - @Query("burnChi") burnChi: Boolean? = null, - @Query("allowPartialFill") allowPartialFill: Boolean? = null, - @Query("parts") parts: String? = null, - @Query("mainRouteParts") mainRouteParts: String? = null, - @Query("connectorTokens") connectorTokens: String? = null, - @Query("complexityLevel") complexityLevel: String? = null, - @Query("gasLimit") gasLimit: String? = null, - @Query("gasPrice") gasPrice: String? = null, - @Query("includeTokensInfo") includeTokensInfo: Boolean = true, - ): Response - //endregion Swap -} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/OneInchApiFactory.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/OneInchApiFactory.kt deleted file mode 100644 index da21f86558..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/OneInchApiFactory.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.tangem.datasource.api.oneinch - -class OneInchApiFactory { - - private val oneInchApiMap = mutableMapOf() - - fun putApi(networkId: String, api: OneInchApi) { - oneInchApiMap[networkId] = api - } - - fun getApi(networkId: String): OneInchApi { - return oneInchApiMap[networkId] ?: error("no api found for networkId $networkId") - } -} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/OneInchErrorsHandler.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/OneInchErrorsHandler.kt deleted file mode 100644 index 4fdc784ecb..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/OneInchErrorsHandler.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.tangem.datasource.api.oneinch - -import com.squareup.moshi.Moshi -import com.tangem.datasource.api.oneinch.errors.OneIncResponseException -import com.tangem.datasource.api.oneinch.models.SwapErrorDto -import com.tangem.datasource.di.NetworkMoshi -import retrofit2.HttpException -import retrofit2.Response -import javax.inject.Inject - -class OneInchErrorsHandler @Inject constructor(@NetworkMoshi moshi: Moshi) { - - private val errorMoshiAdapter = moshi.adapter(SwapErrorDto::class.java) - - @Throws(OneIncResponseException::class) - fun handleOneInchResponse(response: Response): T { - return if (response.isSuccessful) { - response.body() ?: error("response body is null") - } else { - when (response.code()) { - HTTP_CODE_400 -> { - val swapErrorDto = errorMoshiAdapter.fromJson(response.errorBody()?.string() ?: "") - throw OneIncResponseException(swapErrorDto ?: throw HttpException(response)) - } - else -> { - throw HttpException(response) - } - } - } - } - - companion object { - private const val HTTP_CODE_400 = 400 - } -} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/errors/OneIncResponseException.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/errors/OneIncResponseException.kt deleted file mode 100644 index 94c94f6e32..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/errors/OneIncResponseException.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.tangem.datasource.api.oneinch.errors - -import com.tangem.datasource.api.oneinch.models.SwapErrorDto - -class OneIncResponseException(val data: SwapErrorDto) : Exception() \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/AllowanceResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/AllowanceResponse.kt deleted file mode 100644 index 16956f907e..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/AllowanceResponse.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.tangem.datasource.api.oneinch.models - -import com.squareup.moshi.Json - -data class AllowanceResponse( - @Json(name = "allowance") val allowance: String, -) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/ApproveCalldataResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/ApproveCalldataResponse.kt deleted file mode 100644 index f57fab94fd..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/ApproveCalldataResponse.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.tangem.datasource.api.oneinch.models - -import com.squareup.moshi.Json - -/** - * Approve calldata response - * - * @property data The encoded data to call the approve method on the swapped token contract - * @property gasPrice Gas price for fast transaction processing - * @property toAddress Token address that will be allowed to exchange through 1inch router - * @property value Native token value in WEI (for approve is always 0) - */ -data class ApproveCalldataResponse( - @Json(name = "data") val data: String, - @Json(name = "gasPrice") val gasPrice: String, - @Json(name = "to") val toAddress: String, - @Json(name = "value") val value: String, -) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/ApproveSpenderResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/ApproveSpenderResponse.kt deleted file mode 100644 index 0ee9d5b2ac..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/ApproveSpenderResponse.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.tangem.datasource.api.oneinch.models - -import com.squareup.moshi.Json - -/** - * Approve spender response - * - * @property address Address of the 1inch router that must be trusted to spend funds for the exchange - */ -data class ApproveSpenderResponse( - @Json(name = "address") val address: String, -) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/PathViewDto.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/PathViewDto.kt deleted file mode 100644 index 03c23155ff..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/PathViewDto.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.tangem.datasource.api.oneinch.models - -import com.squareup.moshi.Json - -/** - * Path view dto - */ -data class PathViewDto( - @Json(name = "name") val name: String, - @Json(name = "part") val part: Int, - @Json(name = "fromTokenAddress") val fromTokenAddress: String, - @Json(name = "toTokenAddress") val toTokenAddress: String, -) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/ProtocolsResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/ProtocolsResponse.kt deleted file mode 100644 index b083cd1ce8..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/ProtocolsResponse.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.tangem.datasource.api.oneinch.models - -import com.squareup.moshi.Json - -/** - * Protocols response - * - * @property protocols List of protocols that are available for routing in the 1inch Aggregation protocol - */ -data class ProtocolsResponse( - @Json(name = "protocols") val protocols: List, -) - -/** - * Protocol image - * - * @property id Protocol id - * @property title Protocol title - * @property image Protocol logo image - * @property imageColor Protocol logo image in color - */ -data class ProtocolImageDto( - @Json(name = "id") val id: String, - @Json(name = "title") val title: String, - @Json(name = "img") val image: String, - @Json(name = "img_color") val imageColor: String, -) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/QuoteResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/QuoteResponse.kt deleted file mode 100644 index 692f036f24..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/QuoteResponse.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.tangem.datasource.api.oneinch.models - -import com.squareup.moshi.Json - -/** - * Quote response - * - * @property toToken Destination token info - * @property toTokenAmount Expected amount of destination token - */ -data class QuoteResponse( - @Json(name = "toToken") val toToken: TokenOneInchDto, - @Json(name = "toAmount") val toTokenAmount: String, -) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/StatusResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/StatusResponse.kt deleted file mode 100644 index 576851a3b5..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/StatusResponse.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.tangem.datasource.api.oneinch.models - -import com.squareup.moshi.Json - -data class StatusResponse( - @Json(name = "status") val status: String, - @Json(name = "provider") val provider: String, -) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/SwapErrorDto.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/SwapErrorDto.kt deleted file mode 100644 index fe342de231..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/SwapErrorDto.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.tangem.datasource.api.oneinch.models - -import com.squareup.moshi.Json - -/** - * Swap error dto - * - * One of the following errors: - * - * -Insufficient liquidity - * -Cannot estimate - * -You may not have enough ETH balance for gas fee - * -FromTokenAddress cannot be equals to toTokenAddress - * -Cannot estimate. Don't forget about miner fee. Try to leave the buffer of ETH for gas - * -Not enough balance - * -Not enough allowance - * - * @property statusCode HTTP code - * @property error Error code description - * @property description Error description (one of the following) - * @property requestId Request id - * @property meta Meta information - * @constructor Create empty Swap error dto - */ -data class SwapErrorDto( - @Json(name = "statusCode") val statusCode: Int, - @Json(name = "error") val error: String, - @Json(name = "description") val description: String, - @Json(name = "requestId") val requestId: String, - @Json(name = "meta") val meta: List, -) - -/** - * Nest error meta - * - * @property type Type of field - * @property value Value of field - */ -data class NestErrorMeta( - @Json(name = "type") val type: String, - @Json(name = "value") val value: String, -) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/SwapResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/SwapResponse.kt deleted file mode 100644 index bc1f668360..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/SwapResponse.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.tangem.datasource.api.oneinch.models - -import com.squareup.moshi.Json - -data class SwapResponse( - @Json(name = "fromToken") val fromToken: TokenOneInchDto, - @Json(name = "toToken") val toToken: TokenOneInchDto, - @Json(name = "toAmount") val toTokenAmount: String, - @Json(name = "tx") val transaction: TransactionDto, -) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/TokenOneInchDto.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/TokenOneInchDto.kt deleted file mode 100644 index 0c06f15d84..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/TokenOneInchDto.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.tangem.datasource.api.oneinch.models - -import com.squareup.moshi.Json - -/** - * Token one inch - * - * @property symbol token symbol - * @property name token name - * @property address token address - * @property decimals token decimals - * @property logoURI token logo image url - */ -data class TokenOneInchDto( - @Json(name = "symbol") val symbol: String, - @Json(name = "name") val name: String, - @Json(name = "address") val address: String, - @Json(name = "decimals") val decimals: Int, - @Json(name = "logoURI") val logoURI: String, -) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/TokensResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/TokensResponse.kt deleted file mode 100644 index ca1b369949..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/TokensResponse.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.tangem.datasource.api.oneinch.models - -import com.squareup.moshi.Json - -/** - * Tokens response - * - * @property tokens List of supported tokens - */ -data class TokensResponse( - @Json(name = "tokens") val tokens: Map, -) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/TransactionDto.kt b/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/TransactionDto.kt deleted file mode 100644 index a32e827601..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/oneinch/models/TransactionDto.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.tangem.datasource.api.oneinch.models - -import com.squareup.moshi.Json - -/** - * Transaction dto - * - * @property fromAddress transactions will be sent from this address - * @property toAddress transactions will be sent to our(1inch) contract address - * @property data The encoded data to call the approve method on the swapped token contract - * @property value Native token value in WEI (for approve is always 0) - * @property gasPrice maximum amount of gas for a swap default: 11500000; max: 11500000 - * @property gas estimated amount of the gas limit, increase this value by 25% - * @constructor Create empty Transaction dto - */ -data class TransactionDto( - @Json(name = "from") val fromAddress: String, - @Json(name = "to") val toAddress: String, - @Json(name = "data") val data: String, - @Json(name = "value") val value: String, - @Json(name = "gasPrice") val gasPrice: String, - @Json(name = "gas") val gas: String, -) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt b/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt index 3771cc18a6..4ac0edf918 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt @@ -103,11 +103,9 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager { amplitudeApiKey = configValues.amplitudeApiKey, shopify = configValues.shopifyShop, sprinklr = configValues.sprinklr, - swapReferrerAccount = configValues.swapReferrerAccount, walletConnectProjectId = configValues.walletConnectProjectId, tangemComAuthorization = configValues.tangemComAuthorization, - tangemExpressApiKey = configValues.tangemExpressApiKey, - oneInchApiKey = configValues.oneInchApiKey, + express = configValues.express, ) } diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt b/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt index 5ddc1a7187..8490f44237 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt @@ -16,9 +16,7 @@ data class Config( val isCreatingTwinCardsAllowed: Boolean = false, val shopify: ShopifyShop? = null, val sprinklr: SprinklrConfig? = null, - val swapReferrerAccount: SwapReferrerAccount? = null, val walletConnectProjectId: String = "", val tangemComAuthorization: String? = null, - val tangemExpressApiKey: String = "", - val oneInchApiKey: String = "", + val express: ExpressModel? = null, ) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/models/ExpressModel.kt b/core/datasource/src/main/java/com/tangem/datasource/config/models/ExpressModel.kt new file mode 100644 index 0000000000..19f97e4d8e --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/config/models/ExpressModel.kt @@ -0,0 +1,12 @@ +package com.tangem.datasource.config.models + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class ExpressModel( + @Json(name = "apiKey") + val apiKey: String, + @Json(name = "signVerifierPublicKey") + val signVerifierPublicKey: String, +) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt b/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt index d63f6527da..e953742589 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt @@ -35,14 +35,12 @@ class ConfigValueModel( val sprinklr: SprinklrConfig?, val tronGridApiKey: String, val amplitudeApiKey: String, - val swapReferrerAccount: SwapReferrerAccount?, val kaspaSecondaryApiUrl: String, val walletConnectProjectId: String, val tangemComAuthorization: String?, val chiaFireAcademyApiKey: String?, val chiaTangemApiKey: String?, - val tangemExpressApiKey: String, - val oneInchApiKey: String, + val express: ExpressModel?, ) @JsonClass(generateAdapter = true) @@ -84,11 +82,6 @@ data class AppsFlyer( val appsFlyerAppID: String, ) -data class SwapReferrerAccount( - val address: String, - val fee: String, -) - class ConfigModel( val features: FeatureModel?, val configValues: ConfigValueModel?, diff --git a/core/datasource/src/main/java/com/tangem/datasource/crypto/DataSignatureVerifier.kt b/core/datasource/src/main/java/com/tangem/datasource/crypto/DataSignatureVerifier.kt new file mode 100644 index 0000000000..1c3a8b68df --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/crypto/DataSignatureVerifier.kt @@ -0,0 +1,6 @@ +package com.tangem.datasource.crypto + +interface DataSignatureVerifier { + + fun verifySignature(signature: String, data: String): Boolean +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/crypto/Sha256SignatureVerifier.kt b/core/datasource/src/main/java/com/tangem/datasource/crypto/Sha256SignatureVerifier.kt new file mode 100644 index 0000000000..dc2c197c50 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/crypto/Sha256SignatureVerifier.kt @@ -0,0 +1,17 @@ +package com.tangem.datasource.crypto + +import com.tangem.common.extensions.hexToBytes +import com.tangem.crypto.CryptoUtils +import com.tangem.datasource.config.ConfigManager + +internal class Sha256SignatureVerifier(private val configManager: ConfigManager) : DataSignatureVerifier { + + override fun verifySignature(signature: String, data: String): Boolean { + val pubKey = configManager.config.express?.signVerifierPublicKey ?: return false + return CryptoUtils.verify( + publicKey = pubKey.hexToBytes().takeLast(n = 65).toByteArray(), + message = data.toByteArray(), + signature = signature.hexToBytes(), + ) + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/OneInchApisModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/OneInchApisModule.kt deleted file mode 100644 index c1ffbe4e87..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/di/OneInchApisModule.kt +++ /dev/null @@ -1,96 +0,0 @@ -package com.tangem.datasource.di - -import android.content.Context -import com.squareup.moshi.Moshi -import com.tangem.datasource.api.oneinch.OneInchApi -import com.tangem.datasource.api.oneinch.OneInchApiFactory -import com.tangem.datasource.utils.RequestHeader -import com.tangem.datasource.utils.addHeaders -import com.tangem.datasource.utils.addLoggers -import com.tangem.lib.auth.AuthBearerProvider -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent -import okhttp3.OkHttpClient -import retrofit2.Retrofit -import retrofit2.converter.moshi.MoshiConverterFactory -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -class OneInchApisModule { - - @Provides - @Singleton - fun provideOneInchApiFactory( - @NetworkMoshi moshi: Moshi, - @ApplicationContext context: Context, - auth1Inch: AuthBearerProvider, - ): OneInchApiFactory { - val networks = mapOf( - ETH_NETWORK to ONE_INCH_ETH_PATH, - BSC_NETWORK to ONE_INCH_BSC_PATH, - POLYGON_NETWORK to ONE_INCH_POLYGON_PATH, - OPTIMISM_NETWORK to ONE_INCH_OPTIMISM_PATH, - ARBITRUM_NETWORK to ONE_INCH_ARBITRUM_PATH, - GNOSIS_NETWORK to ONE_INCH_GNOSIS_PATH, - AVALANCHE_NETWORK to ONE_INCH_AVALANCHE_PATH, - FANTOM_NETWORK to ONE_INCH_FANTOM_PATH, - ) - - val apiFactory = OneInchApiFactory() - - for ((network, path) in networks) { - apiFactory.putApi( - networkId = network, - api = createOneInchApiWithUrl("$ONE_INCH_BASE_URL$path", moshi, context, auth1Inch), - ) - } - - return apiFactory - } - - private fun createOneInchApiWithUrl( - url: String, - moshi: Moshi, - context: Context, - auth1Inch: AuthBearerProvider, - ): OneInchApi { - return Retrofit.Builder() - .addConverterFactory( - MoshiConverterFactory.create(moshi), - ) - .baseUrl(url) - .client( - OkHttpClient.Builder() - .addHeaders(RequestHeader.AuthBearerHeader(auth1Inch)) - .addLoggers(context) - .build(), - ) - .build() - .create(OneInchApi::class.java) - } - - companion object { - private const val ONE_INCH_BASE_URL = "https://api.1inch.dev/swap/v5.2/" - private const val ONE_INCH_ETH_PATH = "1/" - private const val ONE_INCH_BSC_PATH = "56/" - private const val ONE_INCH_POLYGON_PATH = "137/" - private const val ONE_INCH_OPTIMISM_PATH = "10/" - private const val ONE_INCH_ARBITRUM_PATH = "42161/" - private const val ONE_INCH_GNOSIS_PATH = "100/" - private const val ONE_INCH_AVALANCHE_PATH = "43114/" - private const val ONE_INCH_FANTOM_PATH = "250/" - - private const val ETH_NETWORK = "ethereum" - private const val BSC_NETWORK = "binance-smart-chain" - private const val POLYGON_NETWORK = "polygon-pos" - private const val OPTIMISM_NETWORK = "optimistic-ethereum" - private const val ARBITRUM_NETWORK = "arbitrum-one" - private const val GNOSIS_NETWORK = "xdai" - private const val AVALANCHE_NETWORK = "avalanche" - private const val FANTOM_NETWORK = "fantom" - } -} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/SecurityModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/SecurityModule.kt new file mode 100644 index 0000000000..b5c2f07c49 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/di/SecurityModule.kt @@ -0,0 +1,21 @@ +package com.tangem.datasource.di + +import com.tangem.datasource.config.ConfigManager +import com.tangem.datasource.crypto.DataSignatureVerifier +import com.tangem.datasource.crypto.Sha256SignatureVerifier +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +internal object SecurityModule { + + @Provides + @Singleton + fun provideDataSignatureVerifier(configManager: ConfigManager): DataSignatureVerifier { + return Sha256SignatureVerifier(configManager) + } +} \ No newline at end of file diff --git a/features/swap/data/build.gradle.kts b/features/swap/data/build.gradle.kts index a2b37ee319..12693598d2 100644 --- a/features/swap/data/build.gradle.kts +++ b/features/swap/data/build.gradle.kts @@ -37,6 +37,9 @@ dependencies { /** Tangem SDKs */ implementation(deps.tangem.blockchain) + /** Others */ + implementation(deps.timber) + /** DI */ implementation(deps.hilt.android) diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt similarity index 89% rename from features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt rename to features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt index c95e9b4ddf..7a4c0df381 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt @@ -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 { 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" } diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExpressDataConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExpressDataConverter.kt index 86a75abcb7..d260ec0ef8 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExpressDataConverter.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ExpressDataConverter.kt @@ -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 { +internal class ExpressDataConverter : Converter { - 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), diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt index 83ddab6b62..f48ab71c3a 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt @@ -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, ) } diff --git a/features/swap/domain/api/src/main/java/com/tangem/feature/swap/domain/api/SwapRepository.kt b/features/swap/domain/api/src/main/java/com/tangem/feature/swap/domain/api/SwapRepository.kt index c1310c961c..e0182e8a5e 100644 --- a/features/swap/domain/api/src/main/java/com/tangem/feature/swap/domain/api/SwapRepository.kt +++ b/features/swap/domain/api/src/main/java/com/tangem/feature/swap/domain/api/SwapRepository.kt @@ -33,19 +33,6 @@ interface SwapRepository { rateType: RateType, ): Either - /** - * Returns address of 1inch router that must be trusted - * - * @return address - */ - suspend fun addressForTrust(networkId: String): String - - /** - * Returns a tangem fee for swap in percents - * Example: 0.35% - */ - fun getTangemFee(): Double - @Suppress("LongParameterList") @Throws(IllegalStateException::class) suspend fun getAllowance( diff --git a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt index 829cb5e7e4..9c0ca6b268 100644 --- a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt +++ b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/DataError.kt @@ -32,6 +32,10 @@ sealed class DataError { data class UnknownErrorWithCode(override val code: Int) : DataError() + data class InvalidSignatureError(override val code: Int = 990) : DataError() + + data class InvalidRequestIdError(override val code: Int = 991) : DataError() + object UnknownError : DataError() { override val code: Int = -1 } diff --git a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt index 6711df346c..ae50b2dd38 100644 --- a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt +++ b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt @@ -25,7 +25,6 @@ sealed interface SwapState { val permissionState: PermissionDataState = PermissionDataState.Empty, val swapDataModel: SwapDataModel? = null, val txFee: TxFeeState, - val tangemFee: Double, ) : SwapState data class EmptyAmountState( diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index 34c9756d26..19a88c1d4a 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -653,11 +653,6 @@ internal class SwapInteractorImpl @Inject constructor( return repository.getNativeTokenForNetwork(networkId) } - @Deprecated("used in old swap mechanism") - private fun getTangemFee(): Double { - return repository.getTangemFee() - } - private fun getTokenDecimals(token: CryptoCurrency): Int { return if (token is CryptoCurrency.Token) { token.decimals @@ -1013,7 +1008,6 @@ internal class SwapInteractorImpl @Inject constructor( ), networkCurrency = userWalletManager.getNetworkCurrency(networkId), swapDataModel = swapData, - tangemFee = getTangemFee(), txFee = txFeeState, ) } diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt index 5452767ef8..f02e5006fe 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt @@ -99,7 +99,7 @@ internal class StateBuilder( return uiStateHolder.copy( sendCardData = SwapCardState.SwapCardData( type = TransactionCardType.ReadOnly( - headerResId = R.string.exchange_send_view_header + headerResId = R.string.exchange_send_view_header, ), amountTextFieldValue = TextFieldValue( text = "0",