From 8261e72fec50d9ab804948b58c1936c571a9258d Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 8 Dec 2022 16:58:37 +0300 Subject: [PATCH 1/2] Updated on 2026-08-14 --- .../java/com/tangem/tap/TapApplication.kt | 2 +- .../tap/common/extensions/Navigation.kt | 3 +- core/datasource/build.gradle.kts | 2 + .../tangem/datasource/api/common}/Adapters.kt | 2 +- .../api/tangemTech/TangemTechService.kt | 3 +- .../com/tangem/datasource/di/NetworkModule.kt | 10 ++- features/swap/data/build.gradle.kts | 2 + .../tangem/feature/swap/SwapRepositoryImpl.kt | 13 ++-- .../swap/converters/ApproveConverter.kt | 2 +- .../swap/converters/QuotesConverter.kt | 5 +- .../feature/swap/converters/SwapConverter.kt | 28 +++++--- .../swap/converters/TokensConverter.kt | 15 ++++- .../tangem/feature/swap/di/SwapDataModule.kt | 44 +++++++++++++ .../feature/swap/domain/SwapInteractor.kt | 16 +++++ .../feature/swap/domain/SwapInteractorImpl.kt | 65 +++++++++++++++++++ .../feature/swap/domain/SwapRepository.kt | 11 ++-- .../swap/domain/models/SwapDataHolder.kt | 8 +++ .../swap/domain/models/SwapResultModel.kt | 14 ++++ .../domain/models/{ => data}/ApproveModel.kt | 2 +- .../swap/domain/models/{ => data}/Currency.kt | 2 +- .../domain/models/{ => data}/QuoteModel.kt | 2 +- .../swap/domain/models/data/SwapDataModel.kt | 17 +++++ .../TransactionModel.kt} | 15 +---- features/swap/presentation/build.gradle.kts | 1 + .../feature/swap/presentation/SwapFragment.kt | 33 ++++++++++ 25 files changed, 269 insertions(+), 48 deletions(-) rename {app/src/main/java/com/tangem/tap/common/moshi => core/datasource/src/main/java/com/tangem/datasource/api/common}/Adapters.kt (87%) create mode 100644 features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt create mode 100644 features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt create mode 100644 features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapDataHolder.kt create mode 100644 features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapResultModel.kt rename features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/{ => data}/ApproveModel.kt (88%) rename features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/{ => data}/Currency.kt (93%) rename features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/{ => data}/QuoteModel.kt (69%) create mode 100644 features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/SwapDataModel.kt rename features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/{SwapTransactionModel.kt => data/TransactionModel.kt} (57%) create mode 100644 features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index d17e83bd33..b3bc0a111a 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -11,6 +11,7 @@ import com.tangem.blockchain.common.BlockchainSdkConfig import com.tangem.blockchain.common.WalletManagerFactory import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder import com.tangem.common.json.MoshiJsonConverter +import com.tangem.datasource.api.common.BigDecimalAdapter import com.tangem.datasource.api.common.MoshiConverter import com.tangem.domain.DomainLayer import com.tangem.domain.common.LogConfig @@ -29,7 +30,6 @@ import com.tangem.tap.common.feedback.AdditionalFeedbackInfo import com.tangem.tap.common.feedback.FeedbackManager import com.tangem.tap.common.images.createCoilImageLoader import com.tangem.tap.common.log.TangemLogCollector -import com.tangem.tap.common.moshi.BigDecimalAdapter import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.appReducer import com.tangem.tap.common.redux.global.GlobalAction diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt index 3abbbac6d1..1d78d19e09 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt @@ -7,6 +7,7 @@ import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentManager import com.tangem.common.extensions.VoidCallback import com.tangem.feature.referral.ReferralFragment +import com.tangem.feature.swap.presentation.SwapFragment import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.FragmentShareTransition import com.tangem.tap.features.details.ui.appsettings.AppSettingsFragment @@ -105,7 +106,7 @@ private fun fragmentFactory(screen: AppScreen): Fragment { AppScreen.OnboardingOther -> OnboardingOtherCardsFragment() AppScreen.Wallet -> WalletFragment() AppScreen.Send -> SendFragment() - AppScreen.Details -> DetailsFragment() + AppScreen.Details -> SwapFragment()//DetailsFragment() AppScreen.DetailsSecurity -> SecurityModeFragment() AppScreen.CardSettings -> CardSettingsFragment() AppScreen.AppSettings -> AppSettingsFragment() diff --git a/core/datasource/build.gradle.kts b/core/datasource/build.gradle.kts index 082885c1d7..67563bfbb8 100644 --- a/core/datasource/build.gradle.kts +++ b/core/datasource/build.gradle.kts @@ -63,6 +63,8 @@ dependencies { implementation(Library.okHttp) implementation(Library.okHttpLogging) + kapt("com.squareup.moshi:moshi-kotlin-codegen:1.14.0") + /** Time */ implementation(Library.jodatime) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/moshi/Adapters.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/Adapters.kt similarity index 87% rename from app/src/main/java/com/tangem/tap/common/moshi/Adapters.kt rename to core/datasource/src/main/java/com/tangem/datasource/api/common/Adapters.kt index c0ec09ea9c..568b042179 100644 --- a/app/src/main/java/com/tangem/tap/common/moshi/Adapters.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/Adapters.kt @@ -1,4 +1,4 @@ -package com.tangem.tap.common.moshi +package com.tangem.datasource.api.common import com.squareup.moshi.FromJson import com.squareup.moshi.ToJson diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt index 50540a226e..00638342fc 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt @@ -15,7 +15,8 @@ class TangemTechService( private val logIsEnabled: Boolean = false, ) { - private val headerInterceptors = mutableListOf( + private val + headerInterceptors = mutableListOf( CacheControlHttpInterceptor(cacheMaxAge), ) diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt index d662a98721..c53b453f1b 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt @@ -3,6 +3,7 @@ package com.tangem.datasource.di import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import com.tangem.datasource.api.AuthHeaderInterceptor +import com.tangem.datasource.api.common.BigDecimalAdapter import com.tangem.datasource.api.oneinch.OneInchApi import com.tangem.datasource.api.referral.ReferralApi import com.tangem.datasource.api.tangemTech.TangemTechApi @@ -27,7 +28,12 @@ class NetworkModule { fun provideTangemTechApi(okHttpClient: OkHttpClient): TangemTechApi { return Retrofit.Builder() .addConverterFactory( - MoshiConverterFactory.create(), + MoshiConverterFactory.create( + Moshi.Builder() + .add(KotlinJsonAdapterFactory()) + .add(BigDecimalAdapter()) + .build(), + ), ) .baseUrl(DEV_TANGEM_TECH_BASE_URL) .client(okHttpClient) @@ -80,6 +86,6 @@ class NetworkModule { private companion object { const val PROD_TANGEM_TECH_BASE_URL = "https://api.tangem-tech.com/v1/" const val DEV_TANGEM_TECH_BASE_URL = "https://devapi.tangem-tech.com/v1/" - const val ONE_INCH_ETHER_BASE_URL = "" + const val ONE_INCH_ETHER_BASE_URL = "https://api.1inch.io/swagger/ethereum-json/" } } \ No newline at end of file diff --git a/features/swap/data/build.gradle.kts b/features/swap/data/build.gradle.kts index 298948e089..fff5731bd3 100644 --- a/features/swap/data/build.gradle.kts +++ b/features/swap/data/build.gradle.kts @@ -31,6 +31,8 @@ dependencies { implementation(project(":core:utils")) implementation(project(":features:swap:domain")) + kapt("com.squareup.moshi:moshi-kotlin-codegen:1.14.0") + /** DI */ implementation(Library.hilt) kapt(Library.hiltKapt) 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/SwapRepositoryImpl.kt index 2095876a1b..5424e1fd3d 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/SwapRepositoryImpl.kt @@ -7,9 +7,10 @@ import com.tangem.feature.swap.converters.QuotesConverter import com.tangem.feature.swap.converters.SwapConverter import com.tangem.feature.swap.converters.TokensConverter import com.tangem.feature.swap.domain.SwapRepository -import com.tangem.feature.swap.domain.models.ApproveModel -import com.tangem.feature.swap.domain.models.Currency -import com.tangem.feature.swap.domain.models.QuoteModel +import com.tangem.feature.swap.domain.models.data.ApproveModel +import com.tangem.feature.swap.domain.models.data.Currency +import com.tangem.feature.swap.domain.models.data.QuoteModel +import com.tangem.feature.swap.domain.models.data.SwapDataModel import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.withContext import javax.inject.Inject @@ -64,16 +65,16 @@ class SwapRepositoryImpl @Inject constructor( fromTokenAddress: String, toTokenAddress: String, amount: String, - fromAddress: String, + fromWalletAddress: String, slippage: Int, - ) { + ): SwapDataModel { return withContext(coroutineDispatcher.io) { swapConverter.convert( oneInchApi.swap( fromTokenAddress = fromTokenAddress, toTokenAddress = toTokenAddress, amount = amount, - fromAddress = fromAddress, + fromAddress = fromWalletAddress, slippage = slippage, ), ) diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ApproveConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ApproveConverter.kt index 4d3574869d..c5d5d0e600 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ApproveConverter.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/ApproveConverter.kt @@ -1,7 +1,7 @@ package com.tangem.feature.swap.converters import com.tangem.datasource.api.oneinch.models.ApproveCalldataResponse -import com.tangem.feature.swap.domain.models.ApproveModel +import com.tangem.feature.swap.domain.models.data.ApproveModel import com.tangem.utils.converter.Converter import javax.inject.Inject diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/QuotesConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/QuotesConverter.kt index 52723c6596..058a6a6159 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/QuotesConverter.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/QuotesConverter.kt @@ -1,10 +1,11 @@ package com.tangem.feature.swap.converters import com.tangem.datasource.api.oneinch.models.QuoteResponse -import com.tangem.feature.swap.domain.models.QuoteModel +import com.tangem.feature.swap.domain.models.data.QuoteModel import com.tangem.utils.converter.Converter +import javax.inject.Inject -class QuotesConverter : Converter { +class QuotesConverter @Inject constructor(): Converter { override fun convert(value: QuoteResponse): QuoteModel { return QuoteModel( diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SwapConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SwapConverter.kt index 244ae4f2a0..87dec263da 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SwapConverter.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SwapConverter.kt @@ -1,24 +1,32 @@ package com.tangem.feature.swap.converters import com.tangem.datasource.api.oneinch.models.SwapResponse -import com.tangem.feature.swap.domain.models.SwapTransactionModel +import com.tangem.datasource.api.oneinch.models.TransactionDto +import com.tangem.feature.swap.domain.models.data.SwapDataModel +import com.tangem.feature.swap.domain.models.data.TransactionModel import com.tangem.utils.converter.Converter import javax.inject.Inject -class SwapConverter @Inject constructor() : Converter { +class SwapConverter @Inject constructor() : Converter { - override fun convert(value: SwapResponse): SwapTransactionModel { - return SwapTransactionModel( + override fun convert(value: SwapResponse): SwapDataModel { + return SwapDataModel( fromTokenAddress = value.fromToken.address, toTokenAddress = value.toToken.address, toTokenAmount = value.fromTokenAmount, fromTokenAmount = value.toTokenAmount, - fromWalletAddress = value.transaction.fromAddress, - toWalletAddress = value.transaction.toAddress, - data = value.transaction.data, - value = value.transaction.value, - gasPrice = value.transaction.gasPrice, - gas = value.transaction.gas, + transaction = convertTransaction(value.transaction), + ) + } + + private fun convertTransaction(transactionDto: TransactionDto): TransactionModel { + return TransactionModel( + fromWalletAddress = transactionDto.fromAddress, + toWalletAddress = transactionDto.toAddress, + data = transactionDto.data, + value = transactionDto.value, + gasPrice = transactionDto.gasPrice, + gas = transactionDto.gas, ) } } \ No newline at end of file diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/TokensConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/TokensConverter.kt index c5414d666c..11596db8bc 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/TokensConverter.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/TokensConverter.kt @@ -1,7 +1,7 @@ package com.tangem.feature.swap.converters import com.tangem.datasource.api.tangemTech.CoinsResponse -import com.tangem.feature.swap.domain.models.Currency +import com.tangem.feature.swap.domain.models.data.Currency import com.tangem.utils.converter.Converter import javax.inject.Inject @@ -17,7 +17,7 @@ class TokensConverter @Inject constructor() : Converter + + suspend fun getTokenBalance(): String + + suspend fun findBestQuote( + fromTokenAddress: String, + toTokenAddress: String, + amount: String, + ): QuoteModel + + suspend fun onSwap(): SwapResultModel } \ No newline at end of file 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 new file mode 100644 index 0000000000..b057ac50f8 --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -0,0 +1,65 @@ +package com.tangem.feature.swap.domain + +import com.tangem.feature.swap.domain.models.SwapDataHolder +import com.tangem.feature.swap.domain.models.SwapResultModel +import com.tangem.feature.swap.domain.models.data.Currency +import com.tangem.feature.swap.domain.models.data.QuoteModel +import com.tangem.feature.swap.domain.models.data.TransactionModel + +//todo add @Inject after merge referral and add HiltCore +class SwapInteractorImpl( + private val repository: SwapRepository, +) : SwapInteractor { + + private var lastDataForSwap: SwapDataHolder? = null + + override suspend fun getTokensToSwap(networkId: String): List { + return repository.getExchangeableTokens(networkId) + } + + override suspend fun getTokenBalance(): String { + TODO("Not yet implemented") + } + + override suspend fun findBestQuote(fromTokenAddress: String, toTokenAddress: String, amount: String): QuoteModel { + repository.findBestQuote(fromTokenAddress, toTokenAddress, amount).let { + lastDataForSwap = SwapDataHolder(it, amount) + return it + } + } + + override suspend fun onSwap(): SwapResultModel { + val dataForSwap = lastDataForSwap + if (dataForSwap != null) { + val swapData = repository.prepareSwapTransaction( + fromTokenAddress = dataForSwap.quoteModel.fromTokenAmount, + toTokenAddress = dataForSwap.quoteModel.toTokenAmount, + amount = dataForSwap.amount, + slippage = DEFAULT_SLIPPAGE, + fromWalletAddress = getWalletAddress(), + ) + signTransactionData(swapData.transaction) //todo implement + return SwapResultModel.SwapSuccess( + dataForSwap.quoteModel.fromTokenAmount, + dataForSwap.quoteModel.toTokenAmount, + ) + } + return SwapResultModel.SwapError( + 0, + "", + ) + } + + //todo implement after merge referral + private fun getWalletAddress(): String { + return "" + } + + //todo implement after merge referral + private fun signTransactionData(transaction: TransactionModel) { + } + + companion object { + private const val DEFAULT_SLIPPAGE = 1 + } +} \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapRepository.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapRepository.kt index 963f87bfdb..cb2a2bf07a 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapRepository.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapRepository.kt @@ -1,8 +1,9 @@ package com.tangem.feature.swap.domain -import com.tangem.feature.swap.domain.models.ApproveModel -import com.tangem.feature.swap.domain.models.Currency -import com.tangem.feature.swap.domain.models.QuoteModel +import com.tangem.feature.swap.domain.models.data.ApproveModel +import com.tangem.feature.swap.domain.models.data.Currency +import com.tangem.feature.swap.domain.models.data.QuoteModel +import com.tangem.feature.swap.domain.models.data.SwapDataModel interface SwapRepository { @@ -46,7 +47,7 @@ interface SwapRepository { fromTokenAddress: String, toTokenAddress: String, amount: String, - fromAddress: String, + fromWalletAddress: String, slippage: Int, - ) + ): SwapDataModel } \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapDataHolder.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapDataHolder.kt new file mode 100644 index 0000000000..6216c6d4d5 --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapDataHolder.kt @@ -0,0 +1,8 @@ +package com.tangem.feature.swap.domain.models + +import com.tangem.feature.swap.domain.models.data.QuoteModel + +data class SwapDataHolder( + val quoteModel: QuoteModel, + val amount: String, +) \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapResultModel.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapResultModel.kt new file mode 100644 index 0000000000..014fb40127 --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapResultModel.kt @@ -0,0 +1,14 @@ +package com.tangem.feature.swap.domain.models + +sealed interface SwapResultModel { + + data class SwapSuccess( + val fromTokenAmount: String, + val toTokenAmount: String, + ) : SwapResultModel + + data class SwapError( + val errorCode: Int, + val errorMessage: String, + ) : SwapResultModel +} \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ApproveModel.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/ApproveModel.kt similarity index 88% rename from features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ApproveModel.kt rename to features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/ApproveModel.kt index 2fce5634f9..a553a8d4bf 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ApproveModel.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/ApproveModel.kt @@ -1,4 +1,4 @@ -package com.tangem.feature.swap.domain.models +package com.tangem.feature.swap.domain.models.data /** * Approve model diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/Currency.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/Currency.kt similarity index 93% rename from features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/Currency.kt rename to features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/Currency.kt index 05fe0cad3b..cc69440af7 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/Currency.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/Currency.kt @@ -1,4 +1,4 @@ -package com.tangem.feature.swap.domain.models +package com.tangem.feature.swap.domain.models.data sealed class Currency( open val id: String, diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/QuoteModel.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/QuoteModel.kt similarity index 69% rename from features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/QuoteModel.kt rename to features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/QuoteModel.kt index e71378fd22..4402e296b1 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/QuoteModel.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/QuoteModel.kt @@ -1,4 +1,4 @@ -package com.tangem.feature.swap.domain.models +package com.tangem.feature.swap.domain.models.data data class QuoteModel( val fromTokenAmount: String, diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/SwapDataModel.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/SwapDataModel.kt new file mode 100644 index 0000000000..d7b70ca338 --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/SwapDataModel.kt @@ -0,0 +1,17 @@ +package com.tangem.feature.swap.domain.models.data + +/** + * Swap transaction model + * + * @property fromTokenAddress token from which want to convert + * @property toTokenAddress token to want to convert + * @property toTokenAmount amount "target" token + * @property fromTokenAmount amount "initial" token + */ +data class SwapDataModel( + val fromTokenAddress: String, + val toTokenAddress: String, + val toTokenAmount: String, + val fromTokenAmount: String, + val transaction: TransactionModel +) \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapTransactionModel.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/TransactionModel.kt similarity index 57% rename from features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapTransactionModel.kt rename to features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/TransactionModel.kt index f36d74eb61..978c7e5ec7 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapTransactionModel.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/TransactionModel.kt @@ -1,25 +1,16 @@ -package com.tangem.feature.swap.domain.models +package com.tangem.feature.swap.domain.models.data /** - * Swap transaction model + * Transaction model * - * @property fromTokenAddress token from which want to convert - * @property toTokenAddress token to want to convert - * @property toTokenAmount amount "target" token - * @property fromTokenAmount amount "initial" token * @property fromWalletAddress wallet from address (transactions will be sent from this address) * @property toWalletAddress 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 Swap transaction model */ -data class SwapTransactionModel( - val fromTokenAddress: String, - val toTokenAddress: String, - val toTokenAmount: String, - val fromTokenAmount: String, +data class TransactionModel( val fromWalletAddress: String, val toWalletAddress: String, val data: String, diff --git a/features/swap/presentation/build.gradle.kts b/features/swap/presentation/build.gradle.kts index 8eac586d41..034079a92e 100644 --- a/features/swap/presentation/build.gradle.kts +++ b/features/swap/presentation/build.gradle.kts @@ -49,6 +49,7 @@ dependencies { /** Domain */ implementation(project(":features:swap:domain")) + implementation(project(":features:swap:data"))//todo remove, only for test /** Other libraries */ implementation(Library.composeShimmer) diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt new file mode 100644 index 0000000000..6e5a23dd82 --- /dev/null +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt @@ -0,0 +1,33 @@ +package com.tangem.feature.swap.presentation + +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.tangem.feature.swap.domain.SwapInteractorImpl +import com.tangem.feature.swap.domain.SwapRepository +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import javax.inject.Inject + +@AndroidEntryPoint +class SwapFragment : Fragment() { + + @Inject + lateinit var swapRepository: SwapRepository + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + //test + val swapInteractor = SwapInteractorImpl(swapRepository) + + CoroutineScope(Dispatchers.IO).launch { + Log.d("test", swapInteractor.getTokensToSwap("ethereum").toString()) + } + + return super.onCreateView(inflater, container, savedInstanceState) + } +} \ No newline at end of file From 361ac9508b9185ca93b6732d396b21dd6ddd9a3f Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 12 Dec 2022 16:26:33 +0300 Subject: [PATCH 2/2] Updated on 2026-08-14 --- .../tap/common/extensions/Navigation.kt | 5 +- .../tangem/tap/proxy/UserWalletManagerImpl.kt | 4 +- core/datasource/build.gradle.kts | 2 +- .../datasource/api/oneinch/OneInchApi.kt | 2 + .../api/tangemTech/TangemTechService.kt | 3 +- .../com/tangem/datasource/di/NetworkModule.kt | 52 +++++++++-------- .../referral/data/ReferralRepositoryImpl.kt | 3 +- .../referral/domain/ReferralInteractorImpl.kt | 2 +- features/swap/data/build.gradle.kts | 2 - .../tangem/feature/swap/SwapRepositoryImpl.kt | 2 +- features/swap/domain/build.gradle.kts | 12 ++++ .../feature/swap/domain/SwapInteractor.kt | 4 +- .../feature/swap/domain/SwapInteractorImpl.kt | 58 ++++++++++++------- .../swap/domain/cache/SwapDataCache.kt | 15 +++++ .../swap/domain/cache/SwapDataCacheImpl.kt | 39 +++++++++++++ .../swap/domain/di/SwapDomainModule.kt | 30 ++++++++++ .../swap/domain/models/SwapDataHolder.kt | 5 +- .../swap/domain/models/data/QuoteModel.kt | 3 +- .../feature/swap/presentation/SwapFragment.kt | 30 +++++----- .../feature/swap/viewmodels/SwapViewModel.kt | 15 +++++ .../tangem/lib/crypto/UserWalletManager.kt | 4 +- 21 files changed, 210 insertions(+), 82 deletions(-) create mode 100644 features/swap/domain/src/main/java/com/tangem/feature/swap/domain/cache/SwapDataCache.kt create mode 100644 features/swap/domain/src/main/java/com/tangem/feature/swap/domain/cache/SwapDataCacheImpl.kt create mode 100644 features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt create mode 100644 features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt index 1d78d19e09..36db926f06 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt @@ -7,7 +7,6 @@ import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentManager import com.tangem.common.extensions.VoidCallback import com.tangem.feature.referral.ReferralFragment -import com.tangem.feature.swap.presentation.SwapFragment import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.FragmentShareTransition import com.tangem.tap.features.details.ui.appsettings.AppSettingsFragment @@ -89,7 +88,7 @@ fun FragmentActivity.getPreviousScreen(): AppScreen? { fun FragmentActivity.addOnBackPressedDispatcher( isEnabled: Boolean = true, - onBackPressed: VoidCallback + onBackPressed: VoidCallback, ): OnBackPressedCallback = (object : OnBackPressedCallback(isEnabled) { override fun handleOnBackPressed() { onBackPressed() @@ -106,7 +105,7 @@ private fun fragmentFactory(screen: AppScreen): Fragment { AppScreen.OnboardingOther -> OnboardingOtherCardsFragment() AppScreen.Wallet -> WalletFragment() AppScreen.Send -> SendFragment() - AppScreen.Details -> SwapFragment()//DetailsFragment() + AppScreen.Details -> DetailsFragment() AppScreen.DetailsSecurity -> SecurityModeFragment() AppScreen.CardSettings -> CardSettingsFragment() AppScreen.AppSettings -> AppSettingsFragment() diff --git a/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt b/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt index 8856cdc80d..218bf19ae5 100644 --- a/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt +++ b/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt @@ -84,8 +84,8 @@ class UserWalletManagerImpl( mainStore.dispatch(action) } - override fun getWalletAddress(currency: Currency): String { - val blockchain = Blockchain.fromNetworkId(currency.networkId) + override fun getWalletAddress(networkId: String): String { + val blockchain = Blockchain.fromNetworkId(networkId) val card = appStateHolder.getActualCard() if (blockchain != null && card != null) { val blockchainNetwork = BlockchainNetwork(blockchain, card) diff --git a/core/datasource/build.gradle.kts b/core/datasource/build.gradle.kts index 67563bfbb8..1359125527 100644 --- a/core/datasource/build.gradle.kts +++ b/core/datasource/build.gradle.kts @@ -63,7 +63,7 @@ dependencies { implementation(Library.okHttp) implementation(Library.okHttpLogging) - kapt("com.squareup.moshi:moshi-kotlin-codegen:1.14.0") + // kapt("com.squareup.moshi:moshi-kotlin-codegen:1.14.0") /** Time */ implementation(Library.jodatime) 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 index 774d001e04..e230166425 100644 --- 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 @@ -114,6 +114,7 @@ interface OneInchApi { * * @return [QuoteResponse] */ + @GET("quote") suspend fun quote( @Query("fromTokenAddress") fromTokenAddress: String, @Query("toTokenAddress") toTokenAddress: String, @@ -174,6 +175,7 @@ interface OneInchApi { * * @return [SwapResponse] */ + @GET("swap") suspend fun swap( @Query("fromTokenAddress") fromTokenAddress: String, @Query("toTokenAddress") toTokenAddress: String, diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt index 00638342fc..50540a226e 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechService.kt @@ -15,8 +15,7 @@ class TangemTechService( private val logIsEnabled: Boolean = false, ) { - private val - headerInterceptors = mutableListOf( + private val headerInterceptors = mutableListOf( CacheControlHttpInterceptor(cacheMaxAge), ) diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt index c53b453f1b..94977976b0 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt @@ -15,6 +15,7 @@ import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Converter import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory import javax.inject.Singleton @@ -25,16 +26,12 @@ class NetworkModule { @Provides @Singleton - fun provideTangemTechApi(okHttpClient: OkHttpClient): TangemTechApi { + fun provideTangemTechApi( + okHttpClient: OkHttpClient, + converter: Converter.Factory, + ): TangemTechApi { return Retrofit.Builder() - .addConverterFactory( - MoshiConverterFactory.create( - Moshi.Builder() - .add(KotlinJsonAdapterFactory()) - .add(BigDecimalAdapter()) - .build(), - ), - ) + .addConverterFactory(converter) .baseUrl(DEV_TANGEM_TECH_BASE_URL) .client(okHttpClient) .build() @@ -44,28 +41,26 @@ class NetworkModule { @Provides @Singleton @OneInchEthereum - fun provideOneInchEthereumApi(): OneInchApi { + fun provideOneInchEthereumApi(converter: Converter.Factory): OneInchApi { return Retrofit.Builder() - .addConverterFactory( - MoshiConverterFactory.create(), - ) + .addConverterFactory(converter) .baseUrl(ONE_INCH_ETHER_BASE_URL) - .client(OkHttpClient()) + .client( + OkHttpClient.Builder() + .addInterceptor( + HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY), + ) + .build(), + ) .build() .create(OneInchApi::class.java) } @Provides @Singleton - fun provideReferralApi(okHttpClient: OkHttpClient): ReferralApi { + fun provideReferralApi(okHttpClient: OkHttpClient, converter: Converter.Factory): ReferralApi { return Retrofit.Builder() - .addConverterFactory( - MoshiConverterFactory.create( - Moshi.Builder() - .addLast(KotlinJsonAdapterFactory()) - .build(), - ), - ) + .addConverterFactory(converter) .baseUrl(DEV_TANGEM_TECH_BASE_URL) .client(okHttpClient) .build() @@ -83,9 +78,20 @@ class NetworkModule { .build() } + @Provides + @Singleton + fun provideMoshiConverter(): Converter.Factory { + return MoshiConverterFactory.create( + Moshi.Builder() + .add(KotlinJsonAdapterFactory()) + .add(BigDecimalAdapter()) + .build(), + ) + } + private companion object { const val PROD_TANGEM_TECH_BASE_URL = "https://api.tangem-tech.com/v1/" const val DEV_TANGEM_TECH_BASE_URL = "https://devapi.tangem-tech.com/v1/" - const val ONE_INCH_ETHER_BASE_URL = "https://api.1inch.io/swagger/ethereum-json/" + const val ONE_INCH_ETHER_BASE_URL = "https://api.1inch.io/v5.0/1/" } } \ No newline at end of file diff --git a/features/referral/data/src/main/java/com/tangem/feature/referral/data/ReferralRepositoryImpl.kt b/features/referral/data/src/main/java/com/tangem/feature/referral/data/ReferralRepositoryImpl.kt index 789d5d3bc8..bf2387f070 100644 --- a/features/referral/data/src/main/java/com/tangem/feature/referral/data/ReferralRepositoryImpl.kt +++ b/features/referral/data/src/main/java/com/tangem/feature/referral/data/ReferralRepositoryImpl.kt @@ -7,8 +7,9 @@ import com.tangem.feature.referral.domain.ReferralRepository import com.tangem.feature.referral.domain.models.ReferralData import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.withContext +import javax.inject.Inject -internal class ReferralRepositoryImpl( +internal class ReferralRepositoryImpl @Inject constructor( private val referralApi: ReferralApi, private val referralConverter: ReferralConverter, private val coroutineDispatcher: CoroutineDispatcherProvider, diff --git a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractorImpl.kt b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractorImpl.kt index bf17471c70..c7943b3cb6 100644 --- a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractorImpl.kt +++ b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/ReferralInteractorImpl.kt @@ -26,7 +26,7 @@ internal class ReferralInteractorImpl( if (tokensForReferral.isNotEmpty()) { val currency = tokensConverter.convert(tokensForReferral.first()) deriveOrAddTokens(currency) - val publicAddress = userWalletManager.getWalletAddress(currency) + val publicAddress = userWalletManager.getWalletAddress(currency.networkId) return repository.startReferral( walletId = userWalletManager.getWalletId(), networkId = currency.networkId, diff --git a/features/swap/data/build.gradle.kts b/features/swap/data/build.gradle.kts index fff5731bd3..298948e089 100644 --- a/features/swap/data/build.gradle.kts +++ b/features/swap/data/build.gradle.kts @@ -31,8 +31,6 @@ dependencies { implementation(project(":core:utils")) implementation(project(":features:swap:domain")) - kapt("com.squareup.moshi:moshi-kotlin-codegen:1.14.0") - /** DI */ implementation(Library.hilt) kapt(Library.hiltKapt) 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/SwapRepositoryImpl.kt index 5424e1fd3d..7ea4007b3f 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/SwapRepositoryImpl.kt @@ -15,7 +15,7 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.withContext import javax.inject.Inject -class SwapRepositoryImpl @Inject constructor( +internal class SwapRepositoryImpl @Inject constructor( private val tangemTechApi: TangemTechApi, private val oneInchApi: OneInchApi, private val tokensConverter: TokensConverter, diff --git a/features/swap/domain/build.gradle.kts b/features/swap/domain/build.gradle.kts index e8259cee84..0d5065fe21 100644 --- a/features/swap/domain/build.gradle.kts +++ b/features/swap/domain/build.gradle.kts @@ -1,6 +1,18 @@ plugins { id("java-library") id("org.jetbrains.kotlin.jvm") + kotlin("kapt") +} + +dependencies { + + /** Libs */ + implementation(project(":libs:crypto")) + implementation(project(":core:utils")) + + /** DI */ + implementation(Library.hiltCore) + kapt(Library.hiltKapt) } java { diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt index 5e2a5ea1aa..f75c0842ad 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt @@ -1,14 +1,14 @@ package com.tangem.feature.swap.domain +import com.tangem.feature.swap.domain.models.SwapResultModel import com.tangem.feature.swap.domain.models.data.Currency import com.tangem.feature.swap.domain.models.data.QuoteModel -import com.tangem.feature.swap.domain.models.SwapResultModel interface SwapInteractor { suspend fun getTokensToSwap(networkId: String): List - suspend fun getTokenBalance(): String + suspend fun getTokenBalance(tokenId: String): String suspend fun findBestQuote( fromTokenAddress: String, 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 b057ac50f8..87e05aa527 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 @@ -1,47 +1,62 @@ package com.tangem.feature.swap.domain -import com.tangem.feature.swap.domain.models.SwapDataHolder +import com.tangem.feature.swap.domain.cache.SwapDataCache import com.tangem.feature.swap.domain.models.SwapResultModel import com.tangem.feature.swap.domain.models.data.Currency import com.tangem.feature.swap.domain.models.data.QuoteModel import com.tangem.feature.swap.domain.models.data.TransactionModel +import com.tangem.lib.crypto.UserWalletManager +import javax.inject.Inject -//todo add @Inject after merge referral and add HiltCore -class SwapInteractorImpl( +internal class SwapInteractorImpl @Inject constructor( + private val userWalletManager: UserWalletManager, private val repository: SwapRepository, + private val cache: SwapDataCache, ) : SwapInteractor { - private var lastDataForSwap: SwapDataHolder? = null - override suspend fun getTokensToSwap(networkId: String): List { - return repository.getExchangeableTokens(networkId) + val availableTokens = cache.getAvailableTokens(networkId) + return availableTokens.ifEmpty { + val tokens = repository.getExchangeableTokens(networkId) + cache.cacheAvailableToSwapTokens(networkId, tokens) + cache.cacheNetworkId(networkId) + tokens + } } - override suspend fun getTokenBalance(): String { + override suspend fun getTokenBalance(tokenId: String): String { TODO("Not yet implemented") } override suspend fun findBestQuote(fromTokenAddress: String, toTokenAddress: String, amount: String): QuoteModel { - repository.findBestQuote(fromTokenAddress, toTokenAddress, amount).let { - lastDataForSwap = SwapDataHolder(it, amount) - return it + val networkId = cache.getNetworkId() + val isAllowedToSpend = if (networkId.isNullOrEmpty()) { + false + } else { + repository.checkTokensSpendAllowance(fromTokenAddress, userWalletManager.getWalletAddress(networkId)) != "0" + } + repository.findBestQuote(fromTokenAddress, toTokenAddress, amount).let { quotes -> + cache.cacheSwapParams(quotes.copy(isAllowedToSpend = isAllowedToSpend), amount) + return quotes } } override suspend fun onSwap(): SwapResultModel { - val dataForSwap = lastDataForSwap - if (dataForSwap != null) { + val quoteModel = cache.getLastQuote() + val amountToSwap = cache.getAmountToSwap() + val networkId = cache.getNetworkId() + if (quoteModel != null && amountToSwap != null && networkId != null) { val swapData = repository.prepareSwapTransaction( - fromTokenAddress = dataForSwap.quoteModel.fromTokenAmount, - toTokenAddress = dataForSwap.quoteModel.toTokenAmount, - amount = dataForSwap.amount, + fromTokenAddress = quoteModel.fromTokenAmount, + toTokenAddress = quoteModel.toTokenAmount, + amount = amountToSwap, slippage = DEFAULT_SLIPPAGE, - fromWalletAddress = getWalletAddress(), + fromWalletAddress = getWalletAddress(networkId), ) signTransactionData(swapData.transaction) //todo implement return SwapResultModel.SwapSuccess( - dataForSwap.quoteModel.fromTokenAmount, - dataForSwap.quoteModel.toTokenAmount, + quoteModel.fromTokenAmount, + quoteModel.toTokenAmount, ) } return SwapResultModel.SwapError( @@ -50,9 +65,8 @@ class SwapInteractorImpl( ) } - //todo implement after merge referral - private fun getWalletAddress(): String { - return "" + private fun getWalletAddress(networkId: String): String { + return userWalletManager.getWalletAddress(networkId) } //todo implement after merge referral @@ -60,6 +74,6 @@ class SwapInteractorImpl( } companion object { - private const val DEFAULT_SLIPPAGE = 1 + private const val DEFAULT_SLIPPAGE = 2 } } \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/cache/SwapDataCache.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/cache/SwapDataCache.kt new file mode 100644 index 0000000000..1f6d2373ef --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/cache/SwapDataCache.kt @@ -0,0 +1,15 @@ +package com.tangem.feature.swap.domain.cache + +import com.tangem.feature.swap.domain.models.data.Currency +import com.tangem.feature.swap.domain.models.data.QuoteModel + +interface SwapDataCache { + + fun cacheNetworkId(networkId: String) + fun cacheSwapParams(quoteModel: QuoteModel, amount: String) + fun cacheAvailableToSwapTokens(networkId: String, tokens: List) + fun getAvailableTokens(networkId: String): List + fun getLastQuote(): QuoteModel? + fun getAmountToSwap(): String? + fun getNetworkId(): String? +} \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/cache/SwapDataCacheImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/cache/SwapDataCacheImpl.kt new file mode 100644 index 0000000000..f4fd1cd174 --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/cache/SwapDataCacheImpl.kt @@ -0,0 +1,39 @@ +package com.tangem.feature.swap.domain.cache + +import com.tangem.feature.swap.domain.models.SwapDataHolder +import com.tangem.feature.swap.domain.models.data.Currency +import com.tangem.feature.swap.domain.models.data.QuoteModel + +class SwapDataCacheImpl : SwapDataCache { + + private var lastDataForSwap: SwapDataHolder = SwapDataHolder() + private val availableTokensForNetwork: MutableMap> = mutableMapOf() + + override fun cacheSwapParams(quoteModel: QuoteModel, amount: String) { + lastDataForSwap = lastDataForSwap.copy(quoteModel = quoteModel, amountToSwap = amount) + } + + override fun cacheAvailableToSwapTokens(networkId: String, tokens: List) { + availableTokensForNetwork[networkId] = tokens + } + + override fun cacheNetworkId(networkId: String) { + lastDataForSwap = lastDataForSwap.copy(networkId = networkId) + } + + override fun getNetworkId(): String? { + return lastDataForSwap.networkId + } + + override fun getAvailableTokens(networkId: String): List { + return availableTokensForNetwork.getOrElse(networkId) { emptyList() } + } + + override fun getLastQuote(): QuoteModel? { + return lastDataForSwap.quoteModel + } + + override fun getAmountToSwap(): String? { + return lastDataForSwap.amountToSwap + } +} \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt new file mode 100644 index 0000000000..ef7b8e44c8 --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt @@ -0,0 +1,30 @@ +package com.tangem.feature.swap.domain.di + +import com.tangem.feature.swap.domain.SwapInteractor +import com.tangem.feature.swap.domain.SwapInteractorImpl +import com.tangem.feature.swap.domain.SwapRepository +import com.tangem.feature.swap.domain.cache.SwapDataCacheImpl +import com.tangem.lib.crypto.UserWalletManager +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +class SwapDomainModule { + + @Provides + @Singleton + fun provideSwapInteractor( + referralRepository: SwapRepository, + userWalletManager: UserWalletManager, + ): SwapInteractor { + return SwapInteractorImpl( + userWalletManager = userWalletManager, + repository = referralRepository, + cache = SwapDataCacheImpl(), + ) + } +} \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapDataHolder.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapDataHolder.kt index 6216c6d4d5..60d62274de 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapDataHolder.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapDataHolder.kt @@ -3,6 +3,7 @@ package com.tangem.feature.swap.domain.models import com.tangem.feature.swap.domain.models.data.QuoteModel data class SwapDataHolder( - val quoteModel: QuoteModel, - val amount: String, + val quoteModel: QuoteModel? = null, + val amountToSwap: String? = null, + val networkId: String? = null, ) \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/QuoteModel.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/QuoteModel.kt index 4402e296b1..9a80b7c936 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/QuoteModel.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/QuoteModel.kt @@ -3,5 +3,6 @@ package com.tangem.feature.swap.domain.models.data data class QuoteModel( val fromTokenAmount: String, val toTokenAmount: String, - val estimatedGas: Int + val estimatedGas: Int, + val isAllowedToSpend: Boolean = false, ) \ No newline at end of file diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt index 6e5a23dd82..cc841afcb7 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt @@ -1,33 +1,29 @@ package com.tangem.feature.swap.presentation import android.os.Bundle -import android.util.Log +import android.transition.TransitionInflater import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.compose.ui.platform.ComposeView +import androidx.core.view.WindowCompat import androidx.fragment.app.Fragment -import com.tangem.feature.swap.domain.SwapInteractorImpl -import com.tangem.feature.swap.domain.SwapRepository +import androidx.fragment.app.viewModels +import com.tangem.feature.swap.viewmodels.SwapViewModel import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import javax.inject.Inject @AndroidEntryPoint class SwapFragment : Fragment() { - @Inject - lateinit var swapRepository: SwapRepository + private val viewModel by viewModels() - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - //test - val swapInteractor = SwapInteractorImpl(swapRepository) - - CoroutineScope(Dispatchers.IO).launch { - Log.d("test", swapInteractor.getTokensToSwap("ethereum").toString()) + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, true) } + viewModel + return ComposeView(inflater.context).apply { + setContent { + //todo add compose screen here + } } - - return super.onCreateView(inflater, container, savedInstanceState) } } \ No newline at end of file diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt new file mode 100644 index 0000000000..84f79dad22 --- /dev/null +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt @@ -0,0 +1,15 @@ +package com.tangem.feature.swap.viewmodels + +import androidx.lifecycle.ViewModel +import com.tangem.feature.swap.domain.SwapInteractor +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +internal class SwapViewModel @Inject constructor( + private val referralInteractor: SwapInteractor, + private val dispatchers: CoroutineDispatcherProvider, +) : ViewModel() { + +} \ No newline at end of file diff --git a/libs/crypto/src/main/java/com/tangem/lib/crypto/UserWalletManager.kt b/libs/crypto/src/main/java/com/tangem/lib/crypto/UserWalletManager.kt index 6df9887170..ef60119263 100644 --- a/libs/crypto/src/main/java/com/tangem/lib/crypto/UserWalletManager.kt +++ b/libs/crypto/src/main/java/com/tangem/lib/crypto/UserWalletManager.kt @@ -34,7 +34,7 @@ interface UserWalletManager { /** * Returns wallet public address for token * - * @param currency for which find address + * @param networkId for currency */ - fun getWalletAddress(currency: Currency): String + fun getWalletAddress(networkId: String): String } \ No newline at end of file