From 337b9908c4ce1bfced6b301b11d1b6b387c66739 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 14 Aug 2024 10:49:59 +0400 Subject: [PATCH 1/3] Updated on 2026-08-14 --- .../domain/DefaultCustomTokenInteractor.kt | 2 +- .../note/redux/OnboardingNoteMiddleware.kt | 2 +- .../twins/redux/TwinCardsMiddleware.kt | 2 +- .../viewmodels/TokensListMigration.kt | 2 +- .../CryptoCurrencyConverter.kt | 2 +- .../tap/domain/card/CryptoCurrenciesMocks.kt | 2 +- data/common/build.gradle.kts | 19 ++++++++++--- .../common/currency}/CryptoCurrencyFactory.kt | 2 +- .../common/currency}/NetworkOperations.kt | 16 ++++++----- .../ResponseCryptoCurrenciesFactory.kt | 2 +- .../data/common/currency}/TokensOperations.kt | 27 +++++++++++-------- .../currency}/UserTokensResponseFactory.kt | 2 +- .../tokens/paging/CoinsResponseConverter.kt | 2 +- .../repository/DefaultCurrenciesRepository.kt | 5 +++- .../DefaultNetworksCompatibilityRepository.kt | 2 +- .../repository/DefaultNetworksRepository.kt | 2 +- .../utils/CardCryptoCurrenciesFactory.kt | 1 + features/referral/data/build.gradle.kts | 2 +- .../referral/data/ReferralRepositoryImpl.kt | 2 +- features/swap/data/build.gradle.kts | 2 +- .../feature/swap/DefaultSwapRepository.kt | 2 +- .../SavedSwapTransactionListConverter.kt | 4 +-- 22 files changed, 65 insertions(+), 39 deletions(-) rename data/{tokens/src/main/kotlin/com/tangem/data/tokens/utils => common/src/main/kotlin/com/tangem/data/common/currency}/CryptoCurrencyFactory.kt (99%) rename data/{tokens/src/main/kotlin/com/tangem/data/tokens/utils => common/src/main/kotlin/com/tangem/data/common/currency}/NetworkOperations.kt (85%) rename data/{tokens/src/main/kotlin/com/tangem/data/tokens/utils => common/src/main/kotlin/com/tangem/data/common/currency}/ResponseCryptoCurrenciesFactory.kt (99%) rename data/{tokens/src/main/kotlin/com/tangem/data/tokens/utils => common/src/main/kotlin/com/tangem/data/common/currency}/TokensOperations.kt (78%) rename data/{tokens/src/main/kotlin/com/tangem/data/tokens/utils => common/src/main/kotlin/com/tangem/data/common/currency}/UserTokensResponseFactory.kt (97%) diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/domain/DefaultCustomTokenInteractor.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/domain/DefaultCustomTokenInteractor.kt index ad210d7625..bd9cc89301 100644 --- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/domain/DefaultCustomTokenInteractor.kt +++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/domain/DefaultCustomTokenInteractor.kt @@ -4,7 +4,7 @@ import arrow.core.getOrElse import arrow.core.raise.result import com.tangem.blockchain.common.Blockchain import com.tangem.blockchainsdk.utils.toNetworkId -import com.tangem.data.tokens.utils.CryptoCurrencyFactory +import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.domain.card.DerivePublicKeysUseCase import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.features.addCustomToken.CustomCurrency diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt index ef320383b2..52af2f7d66 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt @@ -5,7 +5,7 @@ import com.tangem.common.extensions.guard import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.Analytics -import com.tangem.data.tokens.utils.CryptoCurrencyFactory +import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.domain.common.extensions.makePrimaryWalletManager import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.common.util.derivationStyleProvider diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt index 19d77c509e..047a5caaa8 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt @@ -7,7 +7,7 @@ import com.tangem.common.routing.AppRoute import com.tangem.common.routing.utils.popTo import com.tangem.core.analytics.Analytics -import com.tangem.data.tokens.utils.CryptoCurrencyFactory +import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.domain.common.extensions.makePrimaryWalletManager import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.common.util.derivationStyleProvider diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListMigration.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListMigration.kt index 41495924b3..5b6249b760 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListMigration.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListMigration.kt @@ -5,7 +5,7 @@ import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token import com.tangem.common.routing.AppRoute import com.tangem.common.routing.utils.popTo -import com.tangem.data.tokens.utils.CryptoCurrencyFactory +import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.domain.card.DerivePublicKeysUseCase import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/CryptoCurrencyConverter.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CryptoCurrencyConverter.kt index 041b9561ee..d7a9569c4c 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/CryptoCurrencyConverter.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CryptoCurrencyConverter.kt @@ -2,7 +2,7 @@ package com.tangem.tap.network.exchangeServices import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token -import com.tangem.data.tokens.utils.CryptoCurrencyFactory +import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.tap.common.extensions.inject diff --git a/app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt b/app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt index 6cb075061a..5ecd65378b 100644 --- a/app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt +++ b/app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt @@ -2,7 +2,7 @@ package com.tangem.tap.domain.card import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token -import com.tangem.data.tokens.utils.CryptoCurrencyFactory +import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.model.CryptoCurrency diff --git a/data/common/build.gradle.kts b/data/common/build.gradle.kts index f1a67e77a3..5a5b6c1d85 100644 --- a/data/common/build.gradle.kts +++ b/data/common/build.gradle.kts @@ -10,13 +10,26 @@ android { } dependencies { + /* Core */ implementation(projects.core.datasource) + /* Domain */ + implementation(projects.domain.models) + implementation(projects.domain.legacy) + implementation(projects.domain.tokens.models) + + /* Libs - SDK */ + implementation(deps.tangem.blockchain) + implementation(deps.tangem.card.core) + implementation(projects.libs.blockchainSdk) + + /* DI */ + implementation(deps.hilt.android) + kapt(deps.hilt.kapt) + + /* Libs - Other */ implementation(deps.kotlin.coroutines) implementation(deps.jodatime) implementation(deps.timber) implementation(deps.arrow.core) - - implementation(deps.hilt.android) - kapt(deps.hilt.kapt) } \ No newline at end of file diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/CryptoCurrencyFactory.kt b/data/common/src/main/kotlin/com/tangem/data/common/currency/CryptoCurrencyFactory.kt similarity index 99% rename from data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/CryptoCurrencyFactory.kt rename to data/common/src/main/kotlin/com/tangem/data/common/currency/CryptoCurrencyFactory.kt index b1e215ed19..9af9e67943 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/CryptoCurrencyFactory.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/currency/CryptoCurrencyFactory.kt @@ -1,4 +1,4 @@ -package com.tangem.data.tokens.utils +package com.tangem.data.common.currency import com.tangem.blockchain.common.Blockchain import com.tangem.blockchainsdk.utils.fromNetworkId diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/NetworkOperations.kt b/data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt similarity index 85% rename from data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/NetworkOperations.kt rename to data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt index c7986bd414..8f2e5b60ac 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/NetworkOperations.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt @@ -1,4 +1,4 @@ -package com.tangem.data.tokens.utils +package com.tangem.data.common.currency import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.FeePaidCurrency @@ -7,14 +7,14 @@ import com.tangem.domain.common.DerivationStyleProvider import com.tangem.domain.tokens.model.Network import timber.log.Timber -internal fun getBlockchain(networkId: Network.ID): Blockchain { +fun getBlockchain(networkId: Network.ID): Blockchain { return Blockchain.fromId(networkId.value) } -internal fun getNetwork( +fun getNetwork( blockchain: Blockchain, extraDerivationPath: String?, - derivationStyleProvider: DerivationStyleProvider, + derivationStyleProvider: DerivationStyleProvider?, ): Network? { if (blockchain == Blockchain.Unknown) { Timber.e("Unable to convert Unknown blockchain to the domain network model") @@ -36,8 +36,12 @@ internal fun getNetwork( private fun getNetworkDerivationPath( blockchain: Blockchain, extraDerivationPath: String?, - cardDerivationStyleProvider: DerivationStyleProvider, + cardDerivationStyleProvider: DerivationStyleProvider?, ): Network.DerivationPath { + if (cardDerivationStyleProvider == null) { + return Network.DerivationPath.None + } + val defaultDerivationPath = getDefaultDerivationPath(blockchain, cardDerivationStyleProvider) return if (extraDerivationPath.isNullOrBlank()) { @@ -55,7 +59,7 @@ private fun getNetworkDerivationPath( } } -internal fun getNetworkStandardType(blockchain: Blockchain): Network.StandardType { +fun getNetworkStandardType(blockchain: Blockchain): Network.StandardType { return when (blockchain) { Blockchain.Ethereum, Blockchain.EthereumTestnet -> Network.StandardType.ERC20 Blockchain.BSC, Blockchain.BSCTestnet -> Network.StandardType.BEP20 diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/ResponseCryptoCurrenciesFactory.kt b/data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt similarity index 99% rename from data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/ResponseCryptoCurrenciesFactory.kt rename to data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt index 0ad1df2428..9bbdfb7fed 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/ResponseCryptoCurrenciesFactory.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt @@ -1,4 +1,4 @@ -package com.tangem.data.tokens.utils +package com.tangem.data.common.currency import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/TokensOperations.kt b/data/common/src/main/kotlin/com/tangem/data/common/currency/TokensOperations.kt similarity index 78% rename from data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/TokensOperations.kt rename to data/common/src/main/kotlin/com/tangem/data/common/currency/TokensOperations.kt index a944703601..72018fc4ed 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/TokensOperations.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/currency/TokensOperations.kt @@ -1,4 +1,4 @@ -package com.tangem.data.tokens.utils +package com.tangem.data.common.currency import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.IconsUtil @@ -18,30 +18,35 @@ private const val DEFAULT_TOKENS_ICONS_HOST = "https://s3.eu-central-1.amazonaws private const val TOKEN_ICON_SIZE = "large" private const val TOKEN_ICON_EXT = "png" -internal fun isCustomToken(tokenId: ID, network: Network): Boolean { +fun isCustomToken(tokenId: ID, network: Network): Boolean { return network.derivationPath is Network.DerivationPath.Custom || tokenId.rawCurrencyId == null } -internal fun isCustomCoin(network: Network): Boolean { +fun isCustomCoin(network: Network): Boolean { return network.derivationPath is Network.DerivationPath.Custom } -internal fun getCoinId(network: Network, coinId: String): ID { +fun getCoinId(network: Network, coinId: String): ID { return ID(COIN_ID_PREFIX, getCurrencyIdBody(network), CurrencyIdSuffix(rawId = coinId)) } -internal fun getTokenId(network: Network, sdkToken: SdkToken): ID { +fun getTokenId(network: Network, sdkToken: SdkToken): ID { val sdkTokenId = sdkToken.id - val suffix = if (sdkTokenId == null) { - CustomCurrencyIdSuffix(contractAddress = sdkToken.contractAddress) + + return getTokenId(network, sdkTokenId, sdkToken.contractAddress) +} + +fun getTokenId(network: Network, rawTokenId: String?, contractAddress: String): ID { + val suffix = if (rawTokenId == null) { + CustomCurrencyIdSuffix(contractAddress) } else { - CurrencyIdSuffix(rawId = sdkTokenId, contractAddress = sdkToken.contractAddress) + CurrencyIdSuffix(rawTokenId, contractAddress) } return ID(TOKEN_ID_PREFIX, getCurrencyIdBody(network), suffix) } -internal fun getTokenIconUrl(blockchain: Blockchain, token: SdkToken): String? { +fun getTokenIconUrl(blockchain: Blockchain, token: SdkToken): String? { val tokenId = token.id return if (tokenId == null) { @@ -51,7 +56,7 @@ internal fun getTokenIconUrl(blockchain: Blockchain, token: SdkToken): String? { } } -internal fun getCoinIconUrl(blockchain: Blockchain): String? { +fun getCoinIconUrl(blockchain: Blockchain): String? { val coinId = when (blockchain) { Blockchain.Unknown -> null else -> blockchain.toCoinId() @@ -60,7 +65,7 @@ internal fun getCoinIconUrl(blockchain: Blockchain): String? { return coinId?.let(::getTokenIconUrlFromDefaultHost) } -internal fun List.hasCoinForToken(token: CryptoCurrency.Token): Boolean { +fun List.hasCoinForToken(token: CryptoCurrency.Token): Boolean { return any { val blockchain = getBlockchain(networkId = token.network.id) val tokenDerivation = token.network.derivationPath.value diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/UserTokensResponseFactory.kt b/data/common/src/main/kotlin/com/tangem/data/common/currency/UserTokensResponseFactory.kt similarity index 97% rename from data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/UserTokensResponseFactory.kt rename to data/common/src/main/kotlin/com/tangem/data/common/currency/UserTokensResponseFactory.kt index 7e8372da6c..4ba8bbd2a2 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/UserTokensResponseFactory.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/currency/UserTokensResponseFactory.kt @@ -1,4 +1,4 @@ -package com.tangem.data.tokens.utils +package com.tangem.data.common.currency import com.tangem.blockchainsdk.utils.toNetworkId import com.tangem.datasource.api.tangemTech.models.UserTokensResponse diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/paging/CoinsResponseConverter.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/paging/CoinsResponseConverter.kt index a1a8018cab..611ccafe2b 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/paging/CoinsResponseConverter.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/paging/CoinsResponseConverter.kt @@ -2,7 +2,7 @@ package com.tangem.data.tokens.paging import com.tangem.blockchain.common.Blockchain import com.tangem.blockchainsdk.utils.fromNetworkId -import com.tangem.data.tokens.utils.getNetworkStandardType +import com.tangem.data.common.currency.getNetworkStandardType import com.tangem.datasource.api.tangemTech.models.CoinsResponse import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.Token diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt index 238ab2676a..ec3720fe1b 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultCurrenciesRepository.kt @@ -6,7 +6,10 @@ import com.tangem.blockchainsdk.utils.toCoinId import com.tangem.blockchainsdk.utils.toNetworkId import com.tangem.data.common.api.safeApiCall import com.tangem.data.common.cache.CacheRegistry -import com.tangem.data.tokens.utils.* +import com.tangem.data.common.currency.* +import com.tangem.data.tokens.utils.CardCryptoCurrenciesFactory +import com.tangem.data.tokens.utils.CustomTokensMerger +import com.tangem.data.tokens.utils.UserTokensBackwardCompatibility import com.tangem.datasource.api.common.response.ApiResponseError import com.tangem.datasource.api.common.response.getOrThrow import com.tangem.datasource.api.express.TangemExpressApi diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksCompatibilityRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksCompatibilityRepository.kt index 02fdef2739..c0ea21218c 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksCompatibilityRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksCompatibilityRepository.kt @@ -3,7 +3,7 @@ package com.tangem.data.tokens.repository import com.tangem.blockchain.common.Blockchain import com.tangem.blockchainsdk.utils.fromNetworkId import com.tangem.common.card.EllipticCurve -import com.tangem.data.tokens.utils.getNetwork +import com.tangem.data.common.currency.getNetwork import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.common.configs.CardConfig import com.tangem.domain.common.extensions.* diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksRepository.kt index 58aa0a6dd6..de6ad111ab 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksRepository.kt @@ -5,9 +5,9 @@ import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.address.AddressType import com.tangem.blockchainsdk.utils.fromNetworkId import com.tangem.data.common.cache.CacheRegistry +import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory import com.tangem.data.tokens.utils.CardCryptoCurrenciesFactory import com.tangem.data.tokens.utils.NetworkStatusFactory -import com.tangem.data.tokens.utils.ResponseCryptoCurrenciesFactory import com.tangem.datasource.local.network.NetworksStatusesStore import com.tangem.datasource.local.token.UserTokensStore import com.tangem.datasource.local.userwallet.UserWalletsStore diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/CardCryptoCurrenciesFactory.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/CardCryptoCurrenciesFactory.kt index a2993452d9..4d6056cbb0 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/CardCryptoCurrenciesFactory.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/CardCryptoCurrenciesFactory.kt @@ -1,6 +1,7 @@ package com.tangem.data.tokens.utils import com.tangem.blockchain.common.Blockchain +import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.domain.common.TapWorkarounds.isTestCard import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.common.util.derivationStyleProvider diff --git a/features/referral/data/build.gradle.kts b/features/referral/data/build.gradle.kts index 5ca72579ad..954bac9c2e 100644 --- a/features/referral/data/build.gradle.kts +++ b/features/referral/data/build.gradle.kts @@ -17,7 +17,7 @@ dependencies { implementation(projects.core.utils) /** Data modules */ - implementation(projects.data.tokens) + implementation(projects.data.common) /** Domain modules */ implementation(projects.domain.legacy) 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 2d44c137ff..9a901c1b69 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 @@ -3,7 +3,7 @@ package com.tangem.feature.referral.data import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token import com.tangem.blockchainsdk.utils.fromNetworkId -import com.tangem.data.tokens.utils.CryptoCurrencyFactory +import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.datasource.api.common.AuthProvider import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.api.tangemTech.models.StartReferralBody diff --git a/features/swap/data/build.gradle.kts b/features/swap/data/build.gradle.kts index 5998ddafd0..f9d6ff0013 100644 --- a/features/swap/data/build.gradle.kts +++ b/features/swap/data/build.gradle.kts @@ -37,7 +37,7 @@ dependencies { implementation(projects.domain.wallets.models) /** Data */ - implementation(projects.data.tokens) + implementation(projects.data.common) /** Tangem SDKs */ implementation(deps.tangem.blockchain) diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt index 48724f9b77..31b1659a73 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt @@ -8,7 +8,7 @@ import arrow.core.right import com.squareup.moshi.Moshi import com.tangem.blockchain.common.* import com.tangem.blockchainsdk.utils.fromNetworkId -import com.tangem.data.tokens.utils.CryptoCurrencyFactory +import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.datasource.api.common.response.ApiResponse import com.tangem.datasource.api.common.response.ApiResponseError import com.tangem.datasource.api.common.response.getOrThrow diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SavedSwapTransactionListConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SavedSwapTransactionListConverter.kt index 8e41921960..33112a9591 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SavedSwapTransactionListConverter.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SavedSwapTransactionListConverter.kt @@ -1,7 +1,7 @@ package com.tangem.feature.swap.converters -import com.tangem.data.tokens.utils.ResponseCryptoCurrenciesFactory -import com.tangem.data.tokens.utils.UserTokensResponseFactory +import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory +import com.tangem.data.common.currency.UserTokensResponseFactory import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWalletId From 292d895c4a74709d54963fb8c515c3d5b8bdf4cd Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 15 Aug 2024 13:22:59 +0400 Subject: [PATCH 2/3] Updated on 2026-08-14 --- .../kotlin/com/tangem/data/common}/utils/RequestUtils.kt | 9 ++++++--- .../tangem/data/markets/DefaultMarketsTokenRepository.kt | 7 +++++-- .../com/tangem/data/markets/MarketsBatchUpdateFetcher.kt | 6 ++++-- 3 files changed, 15 insertions(+), 7 deletions(-) rename data/{markets/src/main/java/com/tangem/data/markets => common/src/main/kotlin/com/tangem/data/common}/utils/RequestUtils.kt (77%) diff --git a/data/markets/src/main/java/com/tangem/data/markets/utils/RequestUtils.kt b/data/common/src/main/kotlin/com/tangem/data/common/utils/RequestUtils.kt similarity index 77% rename from data/markets/src/main/java/com/tangem/data/markets/utils/RequestUtils.kt rename to data/common/src/main/kotlin/com/tangem/data/common/utils/RequestUtils.kt index 18f4e1fda0..e7f3fbfe45 100644 --- a/data/markets/src/main/java/com/tangem/data/markets/utils/RequestUtils.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/utils/RequestUtils.kt @@ -1,4 +1,4 @@ -package com.tangem.data.markets.utils +package com.tangem.data.common.utils import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.delay @@ -8,7 +8,7 @@ import timber.log.Timber import kotlin.coroutines.cancellation.CancellationException @Suppress("UnconditionalJumpStatementInLoop") -internal suspend fun retryOnError(priority: Boolean = false, call: suspend () -> T): T { +suspend fun retryOnError(priority: Boolean = false, call: suspend () -> T): T { while (true) { return try { call() @@ -16,11 +16,14 @@ internal suspend fun retryOnError(priority: Boolean = false, call: suspend ( if (e is CancellationException) { currentCoroutineContext().ensureActive() } - Timber.e(e) + + Timber.e(e, "Error occurred during retryOnError block") + if (priority.not()) { yield() delay(timeMillis = 500) } + continue } } diff --git a/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt b/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt index e850d1ed35..de9edf3b4b 100644 --- a/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt +++ b/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt @@ -1,7 +1,10 @@ package com.tangem.data.markets -import com.tangem.data.markets.converters.* -import com.tangem.data.markets.utils.retryOnError +import com.tangem.data.common.utils.retryOnError +import com.tangem.data.markets.converters.TokenChartConverter +import com.tangem.data.markets.converters.TokenMarketInfoConverter +import com.tangem.data.markets.converters.TokenMarketListConverter +import com.tangem.data.markets.converters.toRequestParam import com.tangem.datasource.api.common.response.getOrThrow import com.tangem.datasource.api.markets.TangemTechMarketsApi import com.tangem.datasource.api.tangemTech.TangemTechApi diff --git a/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt b/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt index d1db77b24e..3a377ab901 100644 --- a/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt +++ b/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt @@ -1,9 +1,9 @@ package com.tangem.data.markets +import com.tangem.data.common.utils.retryOnError import com.tangem.data.markets.converters.TokenMarketChartsConverter import com.tangem.data.markets.converters.TokenQuotesShortConverter import com.tangem.data.markets.converters.toRequestParam -import com.tangem.data.markets.utils.retryOnError import com.tangem.datasource.api.common.response.getOrThrow import com.tangem.datasource.api.markets.TangemTechMarketsApi import com.tangem.datasource.api.markets.models.response.TokenMarketChartListResponse @@ -13,7 +13,9 @@ import com.tangem.domain.markets.TokenMarketUpdateRequest import com.tangem.pagination.Batch import com.tangem.pagination.BatchUpdateFetcher import com.tangem.pagination.BatchUpdateResult -import kotlinx.coroutines.* +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch internal class MarketsBatchUpdateFetcher( private val marketsApi: TangemTechMarketsApi, From 8dc8119970253bf86dded5fe72f64fb088c8617a Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 15 Aug 2024 13:25:20 +0400 Subject: [PATCH 3/3] Updated on 2026-08-14 --- app/build.gradle.kts | 1 + data/manage-tokens/.gitignore | 1 + data/manage-tokens/build.gradle.kts | 44 +++++ .../DefaultManageTokensRepository.kt | 138 ++++++++++++++ .../managetokens/di/ManageTokensDataModule.kt | 40 +++++ .../utils/ManageTokensUpdateFetcher.kt | 68 +++++++ .../utils/ManagedCryptoCurrencyFactory.kt | 168 ++++++++++++++++++ settings.gradle.kts | 1 + 8 files changed, 461 insertions(+) create mode 100644 data/manage-tokens/.gitignore create mode 100644 data/manage-tokens/build.gradle.kts create mode 100644 data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt create mode 100644 data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt create mode 100644 data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManageTokensUpdateFetcher.kt create mode 100644 data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManagedCryptoCurrencyFactory.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 968acfe32e..01c88fedd1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -104,6 +104,7 @@ dependencies { implementation(projects.data.staking) implementation(projects.data.walletConnect) implementation(projects.data.markets) + implementation(projects.data.manageTokens) /** Features */ implementation(projects.features.onboarding) diff --git a/data/manage-tokens/.gitignore b/data/manage-tokens/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/data/manage-tokens/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/data/manage-tokens/build.gradle.kts b/data/manage-tokens/build.gradle.kts new file mode 100644 index 0000000000..137a893c81 --- /dev/null +++ b/data/manage-tokens/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + alias(deps.plugins.android.library) + alias(deps.plugins.kotlin.android) + alias(deps.plugins.kotlin.kapt) + id("configuration") +} + +android { + namespace = "com.example.data.managetokens" +} + +dependencies { + + /** Project - Domain */ + implementation(projects.domain.models) + implementation(projects.domain.manageTokens) + implementation(projects.domain.tokens.models) + implementation(projects.domain.wallets.models) + + /** Project - Data */ + implementation(projects.core.datasource) + implementation(projects.data.common) + + /** Project - Utils */ + implementation(projects.core.utils) + implementation(projects.core.pagination) + implementation(projects.domain.legacy) + implementation(projects.libs.blockchainSdk) + + /** Tangem SDKs */ + implementation(deps.tangem.blockchain) + implementation(deps.tangem.card.core) + + /** AndroidX */ + implementation(deps.androidx.datastore) + + /** DI */ + implementation(deps.hilt.core) + kapt(deps.hilt.kapt) + + /** Other */ + implementation(deps.moshi.kotlin) + implementation(deps.timber) +} \ No newline at end of file diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt new file mode 100644 index 0000000000..bb45239024 --- /dev/null +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt @@ -0,0 +1,138 @@ +package com.tangem.data.managetokens + +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchainsdk.utils.isSupportedInApp +import com.tangem.blockchainsdk.utils.toNetworkId +import com.tangem.data.common.utils.retryOnError +import com.tangem.data.managetokens.utils.ManageTokensUpdateFetcher +import com.tangem.data.managetokens.utils.ManagedCryptoCurrencyFactory +import com.tangem.datasource.api.common.response.getOrThrow +import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.datasource.api.tangemTech.models.UserTokensResponse +import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.preferences.PreferencesKeys +import com.tangem.datasource.local.preferences.utils.getObjectSyncOrNull +import com.tangem.datasource.local.userwallet.UserWalletsStore +import com.tangem.domain.common.extensions.supportedBlockchains +import com.tangem.domain.common.util.cardTypesResolver +import com.tangem.domain.common.util.derivationStyleProvider +import com.tangem.domain.managetokens.model.ManageTokensListBatchFlow +import com.tangem.domain.managetokens.model.ManageTokensListBatchingContext +import com.tangem.domain.managetokens.model.ManageTokensListConfig +import com.tangem.domain.managetokens.model.ManagedCryptoCurrency +import com.tangem.domain.managetokens.repository.ManageTokensRepository +import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.pagination.BatchFetchResult +import com.tangem.pagination.BatchListSource +import com.tangem.pagination.fetcher.LimitOffsetBatchFetcher +import com.tangem.pagination.toBatchFlow +import com.tangem.utils.coroutines.CoroutineDispatcherProvider + +internal class DefaultManageTokensRepository( + private val tangemTechApi: TangemTechApi, + private val userWalletsStore: UserWalletsStore, + private val managedCryptoCurrencyFactory: ManagedCryptoCurrencyFactory, + private val manageTokensUpdateFetcher: ManageTokensUpdateFetcher, + private val appPreferencesStore: AppPreferencesStore, + private val dispatchers: CoroutineDispatcherProvider, +) : ManageTokensRepository { + + override fun getTokenListBatchFlow( + context: ManageTokensListBatchingContext, + batchSize: Int, + ): ManageTokensListBatchFlow { + return BatchListSource( + fetchDispatcher = dispatchers.io, + context = context, + generateNewKey = { it.size.inc() }, + batchFetcher = createFetcher(batchSize), + updateFetcher = manageTokensUpdateFetcher, + ).toBatchFlow() + } + + @Suppress("ComplexCondition") + private fun createFetcher( + batchSize: Int, + ): LimitOffsetBatchFetcher> = LimitOffsetBatchFetcher( + prefetchDistance = batchSize, + batchSize = batchSize, + subFetcher = { request, _, isFirstBatchFetching -> + val userWallet = getUserWallet(request.params.userWalletId) + val supportedBlockchains = getSupportedBlockchains(userWallet) + val searchText = request.params.searchText?.takeIf { it.isNotBlank() } + + val call = suspend { + tangemTechApi.getCoins( + networkIds = supportedBlockchains.joinToString( + separator = ",", + transform = Blockchain::toNetworkId, + ), + active = true, + searchText = searchText, + offset = request.offset * request.limit, + limit = request.limit, + ).getOrThrow() + } + + val coinsResponse = if (isFirstBatchFetching) { + call() + } else { + retryOnError(call = call) + } + + val tokensResponse = getStoredUserTokens(request.params.userWalletId) + val items = if (isFirstBatchFetching && + tokensResponse != null && + userWallet != null && + request.params.searchText.isNullOrBlank() + ) { + managedCryptoCurrencyFactory.createWithCustomTokens( + coinsResponse = coinsResponse, + tokensResponse = tokensResponse, + derivationStyleProvider = userWallet.scanResponse.derivationStyleProvider, + ) + } else { + managedCryptoCurrencyFactory.create( + coinsResponse = coinsResponse, + tokensResponse = tokensResponse, + derivationStyleProvider = userWallet?.scanResponse?.derivationStyleProvider, + ) + } + + BatchFetchResult.Success( + data = items, + empty = items.isEmpty(), + last = items.size < request.limit, + ) + }, + ) + + private suspend fun getStoredUserTokens(userWalletId: UserWalletId?): UserTokensResponse? { + return if (userWalletId != null) { + appPreferencesStore.getObjectSyncOrNull( + key = PreferencesKeys.getUserTokensKey(userWalletId.stringValue), + ) + } else { + null + } + } + + private suspend fun getUserWallet(userWalletId: UserWalletId?): UserWallet? { + if (userWalletId == null) { + return null + } + + return requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) { + "User wallet not found" + } + } + + private fun getSupportedBlockchains(userWallet: UserWallet?): List { + return userWallet?.scanResponse?.let { + it.card.supportedBlockchains(it.cardTypesResolver) + } ?: Blockchain.entries.filter { + !it.isTestnet() && it.isSupportedInApp() + } + } +} \ No newline at end of file diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt new file mode 100644 index 0000000000..5cb10e4936 --- /dev/null +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/di/ManageTokensDataModule.kt @@ -0,0 +1,40 @@ +package com.tangem.data.managetokens.di + +import com.tangem.data.managetokens.DefaultManageTokensRepository +import com.tangem.data.managetokens.utils.ManageTokensUpdateFetcher +import com.tangem.data.managetokens.utils.ManagedCryptoCurrencyFactory +import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.userwallet.UserWalletsStore +import com.tangem.domain.managetokens.repository.ManageTokensRepository +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +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 ManageTokensDataModule { + + @Provides + @Singleton + fun provideManageTokensRepository( + tangemTechApi: TangemTechApi, + userWalletsStore: UserWalletsStore, + managedCryptoCurrencyFactory: ManagedCryptoCurrencyFactory, + manageTokensUpdateFetcher: ManageTokensUpdateFetcher, + appPreferencesStore: AppPreferencesStore, + dispatchers: CoroutineDispatcherProvider, + ): ManageTokensRepository { + return DefaultManageTokensRepository( + tangemTechApi, + userWalletsStore, + managedCryptoCurrencyFactory, + manageTokensUpdateFetcher, + appPreferencesStore, + dispatchers, + ) + } +} \ No newline at end of file diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManageTokensUpdateFetcher.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManageTokensUpdateFetcher.kt new file mode 100644 index 0000000000..6c23f37b0b --- /dev/null +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManageTokensUpdateFetcher.kt @@ -0,0 +1,68 @@ +package com.tangem.data.managetokens.utils + +import com.tangem.domain.managetokens.model.ManageTokensUpdateAction +import com.tangem.domain.managetokens.model.ManagedCryptoCurrency +import com.tangem.pagination.Batch +import com.tangem.pagination.BatchUpdateFetcher +import com.tangem.pagination.BatchUpdateResult +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +internal class ManageTokensUpdateFetcher @Inject constructor() : + BatchUpdateFetcher, ManageTokensUpdateAction> { + + override suspend fun BatchUpdateFetcher.UpdateContext>.fetchUpdateAsync( + toUpdate: List>>, + updateRequest: ManageTokensUpdateAction, + ) { + when (updateRequest) { + is ManageTokensUpdateAction.AddCurrency -> coroutineScope { + val tasks = toUpdate.map { (key, data) -> + async { + val currencyIndex = data.indexOfFirst { it.id == updateRequest.currencyId } + .takeIf { it != -1 } + ?: error("Currency '${updateRequest.currencyId}' not found in batch #$key") + val updatedCurrency = when (val currency = data[currencyIndex]) { + is ManagedCryptoCurrency.Custom -> error("Can't add custom currency '${currency.id}'") + is ManagedCryptoCurrency.Token -> { + currency.copy( + addedIn = if (updateRequest.isSelected) { + currency.addedIn + updateRequest.networkId + } else { + currency.addedIn - updateRequest.networkId + }, + ) + } + } + + data.toMutableList().apply { + set(currencyIndex, updatedCurrency) + } + } + } + + tasks.forEachIndexed { index, task -> + launch { + val updatedItems = task.await() + + update { + BatchUpdateResult.Success( + data = mapNotNull { + if (it.key == toUpdate[index].key) { + Batch(it.key, updatedItems) + } else { + null + } + }, + ) + } + } + } + } + } + } +} \ No newline at end of file diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManagedCryptoCurrencyFactory.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManagedCryptoCurrencyFactory.kt new file mode 100644 index 0000000000..de239a1f09 --- /dev/null +++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/utils/ManagedCryptoCurrencyFactory.kt @@ -0,0 +1,168 @@ +package com.tangem.data.managetokens.utils + +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchainsdk.utils.fromNetworkId +import com.tangem.blockchainsdk.utils.isSupportedInApp +import com.tangem.blockchainsdk.utils.toCoinId +import com.tangem.data.common.currency.getCoinId +import com.tangem.data.common.currency.getNetwork +import com.tangem.data.common.currency.getTokenId +import com.tangem.datasource.api.tangemTech.models.CoinsResponse +import com.tangem.datasource.api.tangemTech.models.UserTokensResponse +import com.tangem.domain.common.DerivationStyleProvider +import com.tangem.domain.managetokens.model.ManagedCryptoCurrency +import com.tangem.domain.managetokens.model.ManagedCryptoCurrency.SourceNetwork +import com.tangem.domain.tokens.model.Network +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +internal class ManagedCryptoCurrencyFactory @Inject constructor() { + + fun create( + coinsResponse: CoinsResponse, + tokensResponse: UserTokensResponse?, + derivationStyleProvider: DerivationStyleProvider?, + ): List { + return coinsResponse.coins.mapNotNull { coin -> + createToken(coin, tokensResponse, coinsResponse.imageHost, derivationStyleProvider) + } + } + + fun createWithCustomTokens( + coinsResponse: CoinsResponse, + tokensResponse: UserTokensResponse, + derivationStyleProvider: DerivationStyleProvider, + ): List { + val customTokens = tokensResponse.tokens + .mapNotNull { token -> + maybeCreateCustomToken(token, coinsResponse.imageHost, derivationStyleProvider) + } + + val tokens = create(coinsResponse, tokensResponse, derivationStyleProvider) + + return customTokens + tokens + } + + private fun maybeCreateCustomToken( + token: UserTokensResponse.Token, + imageHost: String?, + derivationStyleProvider: DerivationStyleProvider, + ): ManagedCryptoCurrency? { + val blockchain = Blockchain.fromNetworkId(token.networkId) + ?.takeIf { it.isSupportedInApp() } + ?: return null + + if (!checkIsCustomToken(token, blockchain, derivationStyleProvider)) { + return null + } + + val network = getNetwork( + blockchain = blockchain, + extraDerivationPath = token.derivationPath, + derivationStyleProvider = derivationStyleProvider, + ) ?: return null + val contractAddress = token.contractAddress + + return if (contractAddress.isNullOrBlank()) { + ManagedCryptoCurrency.Custom.Coin( + currencyId = getCoinId(network, blockchain.toCoinId()), + name = token.name, + symbol = token.symbol, + iconUrl = getIconUrl(blockchain.id, imageHost), + network = network, + ) + } else { + ManagedCryptoCurrency.Custom.Token( + currencyId = getTokenId(network, token.id, contractAddress), + name = token.name, + symbol = token.symbol, + iconUrl = token.id?.let { getIconUrl(it, imageHost) }, + contractAddress = contractAddress, + network = network, + ) + } + } + + private fun createToken( + coinResponse: CoinsResponse.Coin, + tokensResponse: UserTokensResponse?, + imageHost: String?, + derivationStyleProvider: DerivationStyleProvider?, + ): ManagedCryptoCurrency? { + if (coinResponse.networks.isEmpty() || !coinResponse.active) return null + + return ManagedCryptoCurrency.Token( + id = ManagedCryptoCurrency.ID(coinResponse.id), + name = coinResponse.name, + symbol = coinResponse.symbol, + iconUrl = getIconUrl(coinResponse.id, imageHost), + availableNetworks = coinResponse.networks.mapNotNull { network -> + createSource(network, derivationStyleProvider) + }, + addedIn = findAddedInNetworksIds(coinResponse.id, tokensResponse), + ) + } + + private fun createSource( + networkResponse: CoinsResponse.Coin.Network, + derivationStyleProvider: DerivationStyleProvider?, + extraDerivationPath: String? = null, + ): SourceNetwork? { + val blockchain = Blockchain.fromNetworkId(networkResponse.networkId) + ?.takeIf { it.isSupportedInApp() } + ?: return null + + val network = getNetwork(blockchain, extraDerivationPath, derivationStyleProvider) ?: return null + val contractAddress = networkResponse.contractAddress + + return if (contractAddress.isNullOrBlank()) { + SourceNetwork.Main( + network = network, + ) + } else { + SourceNetwork.Default( + network = network, + contractAddress = contractAddress, + ) + } + } + + private fun findAddedInNetworksIds(currencyId: String, tokensResponse: UserTokensResponse?): Set { + if (tokensResponse == null) return emptySet() + + return tokensResponse.tokens + .filter { it.id == currencyId } + .map { it.networkId } + .mapNotNullTo(mutableSetOf()) { networkId -> + val blockchain = Blockchain.fromNetworkId(networkId) + + if (blockchain != null && blockchain.isSupportedInApp()) { + Network.ID(blockchain.id) + } else { + null + } + } + } + + private fun getIconUrl(id: String, imageHost: String?): String { + return "${imageHost ?: DEFAULT_IMAGE_HOST}large/$id.png" + } + + private fun checkIsCustomToken( + token: UserTokensResponse.Token, + blockchain: Blockchain, + derivationStyleProvider: DerivationStyleProvider, + ): Boolean = token.id.isNullOrBlank() || + checkIsCustomDerivationPath(token.derivationPath, blockchain, derivationStyleProvider) + + private fun checkIsCustomDerivationPath( + derivationPath: String?, + blockchain: Blockchain, + derivationStyleProvider: DerivationStyleProvider, + ): Boolean = derivationPath != blockchain.derivationPath(derivationStyleProvider.getDerivationStyle())?.rawPath + + private companion object { + const val DEFAULT_IMAGE_HOST = "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/" + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index a4720852bf..4af0388ca6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -250,4 +250,5 @@ include(":data:qr-scanning") include(":data:staking") include(":data:wallet-connect") include(":data:markets") +include(":data:manage-tokens") // endregion Data modules \ No newline at end of file