diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index 0d483b43ee..a11b02cef2 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 @@ -30,7 +31,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 711e7ed172..0e167cdcca 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 @@ -88,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() 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 082885c1d7..1359125527 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/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/di/NetworkModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt index d662a98721..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 @@ -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 @@ -14,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 @@ -24,11 +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(), - ) + .addConverterFactory(converter) .baseUrl(DEV_TANGEM_TECH_BASE_URL) .client(okHttpClient) .build() @@ -38,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() @@ -77,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 = "" + 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/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt index 2095876a1b..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 @@ -7,14 +7,15 @@ 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 -class SwapRepositoryImpl @Inject constructor( +internal class SwapRepositoryImpl @Inject constructor( private val tangemTechApi: TangemTechApi, private val oneInchApi: OneInchApi, private val tokensConverter: TokensConverter, @@ -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(tokenId: String): 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..87e05aa527 --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -0,0 +1,79 @@ +package com.tangem.feature.swap.domain + +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 + +internal class SwapInteractorImpl @Inject constructor( + private val userWalletManager: UserWalletManager, + private val repository: SwapRepository, + private val cache: SwapDataCache, +) : SwapInteractor { + + override suspend fun getTokensToSwap(networkId: String): List { + 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(tokenId: String): String { + TODO("Not yet implemented") + } + + override suspend fun findBestQuote(fromTokenAddress: String, toTokenAddress: String, amount: String): QuoteModel { + 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 quoteModel = cache.getLastQuote() + val amountToSwap = cache.getAmountToSwap() + val networkId = cache.getNetworkId() + if (quoteModel != null && amountToSwap != null && networkId != null) { + val swapData = repository.prepareSwapTransaction( + fromTokenAddress = quoteModel.fromTokenAmount, + toTokenAddress = quoteModel.toTokenAmount, + amount = amountToSwap, + slippage = DEFAULT_SLIPPAGE, + fromWalletAddress = getWalletAddress(networkId), + ) + signTransactionData(swapData.transaction) //todo implement + return SwapResultModel.SwapSuccess( + quoteModel.fromTokenAmount, + quoteModel.toTokenAmount, + ) + } + return SwapResultModel.SwapError( + 0, + "", + ) + } + + private fun getWalletAddress(networkId: String): String { + return userWalletManager.getWalletAddress(networkId) + } + + //todo implement after merge referral + private fun signTransactionData(transaction: TransactionModel) { + } + + companion object { + 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/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/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/QuoteModel.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/QuoteModel.kt deleted file mode 100644 index e71378fd22..0000000000 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/QuoteModel.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.tangem.feature.swap.domain.models - -data class QuoteModel( - val fromTokenAmount: String, - val toTokenAmount: String, - val estimatedGas: Int -) \ 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..60d62274de --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/SwapDataHolder.kt @@ -0,0 +1,9 @@ +package com.tangem.feature.swap.domain.models + +import com.tangem.feature.swap.domain.models.data.QuoteModel + +data class SwapDataHolder( + 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/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/data/QuoteModel.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/QuoteModel.kt new file mode 100644 index 0000000000..9a80b7c936 --- /dev/null +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/data/QuoteModel.kt @@ -0,0 +1,8 @@ +package com.tangem.feature.swap.domain.models.data + +data class QuoteModel( + val fromTokenAmount: String, + val toTokenAmount: String, + val estimatedGas: Int, + val isAllowedToSpend: Boolean = false, +) \ No newline at end of file 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..cc841afcb7 --- /dev/null +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt @@ -0,0 +1,29 @@ +package com.tangem.feature.swap.presentation + +import android.os.Bundle +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 androidx.fragment.app.viewModels +import com.tangem.feature.swap.viewmodels.SwapViewModel +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class SwapFragment : Fragment() { + + private val viewModel by viewModels() + + 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 + } + } + } +} \ 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