diff --git a/app/src/main/java/com/tangem/tap/common/CurrencyConverter.kt b/app/src/main/java/com/tangem/tap/common/CurrencyConverter.kt index 3f6b858b3b..d30c440661 100644 --- a/app/src/main/java/com/tangem/tap/common/CurrencyConverter.kt +++ b/app/src/main/java/com/tangem/tap/common/CurrencyConverter.kt @@ -29,8 +29,8 @@ class CurrencyConverter( fun toCrypto(fiat: BigDecimal): BigDecimal { if (fiat.isZero()) return fiat - val scaledRateValue = rateValue.setScale(decimals, roundingMode) - val scaledFiat = fiat.setScale(decimals, roundingMode) - return scaledFiat.divide(scaledRateValue, RoundingMode.UP) + val fiatValue = fiat.setScale(rateValue.scale(), RoundingMode.UP) + val cryptoValue = fiatValue.divide(rateValue, RoundingMode.UP) + return cryptoValue.setScale(decimals, roundingMode) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/models/AddCustomTokenViewsModels.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/models/AddCustomTokenViewsModels.kt index 71c369bcad..965525c83e 100644 --- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/models/AddCustomTokenViewsModels.kt +++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/models/AddCustomTokenViewsModels.kt @@ -300,9 +300,9 @@ internal sealed class AddCustomTokenWarning(val description: TextReference) { description = TextReference.Res(R.string.custom_token_validation_error_already_added), ) - /** Unsupported Solana token warning */ - object UnsupportedSolanaToken : AddCustomTokenWarning( - description = TextReference.Res(R.string.alert_manage_tokens_unsupported_message), + /** Unsupported token warning */ + data class UnsupportedToken(val networkName: String) : AddCustomTokenWarning( + description = TextReference.Res(R.string.alert_manage_tokens_unsupported_message, networkName), ) object WrongDerivationPath : AddCustomTokenWarning( diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenPreviewData.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenPreviewData.kt index ba881741b0..b5274e6d12 100644 --- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenPreviewData.kt +++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/ui/AddCustomTokenPreviewData.kt @@ -18,7 +18,7 @@ internal object AddCustomTokenPreviewData { return setOf( AddCustomTokenWarning.PotentialScamToken, AddCustomTokenWarning.TokenAlreadyAdded, - AddCustomTokenWarning.UnsupportedSolanaToken, + AddCustomTokenWarning.UnsupportedToken(networkName = "Solana"), ) } diff --git a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt index b1f939c0f6..484026d744 100644 --- a/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/customtoken/impl/presentation/viewmodels/AddCustomTokenViewModel.kt @@ -486,8 +486,12 @@ internal class AddCustomTokenViewModel @Inject constructor( } return buildSet { - if (!isSupportedToken && !isContractAddressFieldEmpty) add(AddCustomTokenWarning.UnsupportedSolanaToken) - if (isCustomTokenAlreadyAdded()) add(AddCustomTokenWarning.TokenAlreadyAdded) + if (!isSupportedToken && !isContractAddressFieldEmpty) { + add(AddCustomTokenWarning.UnsupportedToken(networkSelectorValue.fullName)) + } + if (isCustomTokenAlreadyAdded()) { + add(AddCustomTokenWarning.TokenAlreadyAdded) + } if (foundToken == null && isAnyTokenFieldsFilled() || foundToken?.isActive == false) { add(AddCustomTokenWarning.PotentialScamToken) } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt index 5a1c6150cf..b8af48c72b 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt @@ -147,7 +147,7 @@ internal object TangemSocialAccounts { SocialNetworkLink(SocialNetwork.GitHub, "https://github.com/tangem"), SocialNetworkLink(SocialNetwork.Facebook, "https://www.facebook.com/tangemwallet"), SocialNetworkLink(SocialNetwork.LinkedIn, "https://www.linkedin.com/company/tangem"), - SocialNetworkLink(SocialNetwork.YouTube, "https://youtube.com/@tangem3890"), + SocialNetworkLink(SocialNetwork.YouTube, "https://youtube.com/@tangem_official"), ) val accountsRu: ImmutableList = persistentListOf( SocialNetworkLink(SocialNetwork.Twitter, "https://x.com/tangem"), @@ -158,6 +158,6 @@ internal object TangemSocialAccounts { SocialNetworkLink(SocialNetwork.GitHub, "https://github.com/tangem"), SocialNetworkLink(SocialNetwork.Facebook, "https://www.facebook.com/tangemwallet"), SocialNetworkLink(SocialNetwork.LinkedIn, "https://www.linkedin.com/company/tangem"), - SocialNetworkLink(SocialNetwork.YouTube, "https://youtube.com/@tangem3890"), + SocialNetworkLink(SocialNetwork.YouTube, "https://youtube.com/@tangem_official"), ) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/models/SupportTokensState.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/models/SupportTokensState.kt index e815d5d1e7..0917dcb2f9 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/models/SupportTokensState.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/models/SupportTokensState.kt @@ -5,7 +5,7 @@ package com.tangem.tap.features.tokens.impl.presentation.models */ sealed class SupportTokensState { - object SolanaNetworkUnsupported : SupportTokensState() + object NetworkTokensUnsupported : SupportTokensState() object UnsupportedCurve : SupportTokensState() object SupportedToken : SupportTokensState() } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/router/DefaultTokensListRouter.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/router/DefaultTokensListRouter.kt index 68b277ea7e..8c763c93d6 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/router/DefaultTokensListRouter.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/router/DefaultTokensListRouter.kt @@ -51,11 +51,12 @@ internal class DefaultTokensListRouter : TokensListRouter { store.dispatchDialogShow(alert) } - override fun openSolanaTokensNotSupportAlert() { + override fun openNetworkTokensNotSupportAlert(networkName: String) { store.dispatchDialogShow( AppDialog.SimpleOkDialogRes( headerId = R.string.common_warning, messageId = R.string.alert_manage_tokens_unsupported_message, + args = listOf(networkName), ), ) } diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/router/TokensListRouter.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/router/TokensListRouter.kt index ee87445d1d..8347f59a2e 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/router/TokensListRouter.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/router/TokensListRouter.kt @@ -37,7 +37,7 @@ internal interface TokensListRouter { fun openUnsupportedNetworkAlert(blockchain: Blockchain) /** - * Open alert with Solana tokens error + * Open alert with unsupported networks tokens error */ - fun openSolanaTokensNotSupportAlert() + fun openNetworkTokensNotSupportAlert(networkName: String) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListViewModel.kt b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListViewModel.kt index a03a0aef85..f2046c81df 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/impl/presentation/viewmodels/TokensListViewModel.kt @@ -4,7 +4,10 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue -import androidx.lifecycle.* +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import androidx.paging.* import com.tangem.blockchain.common.Blockchain import com.tangem.core.analytics.api.AnalyticsEventHandler @@ -37,7 +40,9 @@ import com.tangem.utils.coroutines.Debouncer import com.tangem.wallet.R import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.toImmutableList -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.coroutines.plus import timber.log.Timber @@ -406,14 +411,20 @@ internal class TokensListViewModel @Inject constructor( } } else { when (isUnsupportedToken(token.blockchain)) { - SupportTokensState.SolanaNetworkUnsupported -> router.openSolanaTokensNotSupportAlert() + SupportTokensState.NetworkTokensUnsupported -> { + router.openNetworkTokensNotSupportAlert(token.blockchain.fullName) + } SupportTokensState.SupportedToken -> { analyticsSender.sendWhenTokenAdded(token.token) changedTokensList.add(token) toggledNetwork.changeToggleState() } - SupportTokensState.UnsupportedCurve -> router.openUnsupportedNetworkAlert(token.blockchain) - null -> Timber.e("Something went wrong in isUnsupportedToken (no scanResponse found)") + SupportTokensState.UnsupportedCurve -> { + router.openUnsupportedNetworkAlert(token.blockchain) + } + null -> { + Timber.e("Something went wrong in isUnsupportedToken (no scanResponse found)") + } } } } @@ -428,7 +439,7 @@ internal class TokensListViewModel @Inject constructor( // refactor this later by moving all this logic in card config if (blockchain == Blockchain.Solana && !supportedTokens.contains(Blockchain.Solana)) { - return SupportTokensState.SolanaNetworkUnsupported + return SupportTokensState.NetworkTokensUnsupported } val canHandleToken = it.scanResponse.card.canHandleToken( supportedTokens = supportedTokens, diff --git a/app/src/main/java/com/tangem/tap/network/auth/DefaultOneInchProvider.kt b/app/src/main/java/com/tangem/tap/network/auth/DefaultOneInchProvider.kt new file mode 100644 index 0000000000..ade4f48a0f --- /dev/null +++ b/app/src/main/java/com/tangem/tap/network/auth/DefaultOneInchProvider.kt @@ -0,0 +1,13 @@ +package com.tangem.tap.network.auth + +import com.tangem.datasource.config.ConfigManager +import com.tangem.lib.auth.AuthBearerProvider + +internal class DefaultOneInchProvider( + private val configManager: ConfigManager, +) : AuthBearerProvider { + + override fun getApiKey(): String { + return configManager.config.oneInchApiKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt b/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt index fa9aa920a1..d59b3f4792 100644 --- a/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt +++ b/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt @@ -2,10 +2,12 @@ package com.tangem.tap.network.auth.di import com.tangem.datasource.config.ConfigManager import com.tangem.datasource.local.userwallet.UserWalletsStore +import com.tangem.lib.auth.AuthBearerProvider import com.tangem.lib.auth.AuthProvider import com.tangem.lib.auth.ExpressAuthProvider import com.tangem.tap.network.auth.DefaultAuthProvider import com.tangem.tap.network.auth.DefaultExpressAuthProvider +import com.tangem.tap.network.auth.DefaultOneInchProvider import com.tangem.tap.proxy.AppStateHolder import dagger.Module import dagger.Provides @@ -34,4 +36,12 @@ class AuthModule { configManager = configManager, ) } + + @Provides + @Singleton + fun provideOneInchAuthProvider(configManager: ConfigManager): AuthBearerProvider { + return DefaultOneInchProvider( + configManager = configManager, + ) + } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt b/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt index 2c4b2b364f..3771cc18a6 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt @@ -107,6 +107,7 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager { walletConnectProjectId = configValues.walletConnectProjectId, tangemComAuthorization = configValues.tangemComAuthorization, tangemExpressApiKey = configValues.tangemExpressApiKey, + oneInchApiKey = configValues.oneInchApiKey, ) } diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt b/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt index d1f3e0848f..5ddc1a7187 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt @@ -20,4 +20,5 @@ data class Config( val walletConnectProjectId: String = "", val tangemComAuthorization: String? = null, val tangemExpressApiKey: String = "", + val oneInchApiKey: String = "", ) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt b/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt index a7b0d44453..d63f6527da 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt @@ -42,6 +42,7 @@ class ConfigValueModel( val chiaFireAcademyApiKey: String?, val chiaTangemApiKey: String?, val tangemExpressApiKey: String, + val oneInchApiKey: String, ) @JsonClass(generateAdapter = true) diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/OneInchApisModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/OneInchApisModule.kt index 341fd1a752..c1ffbe4e87 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/OneInchApisModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/OneInchApisModule.kt @@ -4,7 +4,10 @@ import android.content.Context import com.squareup.moshi.Moshi import com.tangem.datasource.api.oneinch.OneInchApi import com.tangem.datasource.api.oneinch.OneInchApiFactory +import com.tangem.datasource.utils.RequestHeader +import com.tangem.datasource.utils.addHeaders import com.tangem.datasource.utils.addLoggers +import com.tangem.lib.auth.AuthBearerProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -21,7 +24,11 @@ class OneInchApisModule { @Provides @Singleton - fun provideOneInchApiFactory(@NetworkMoshi moshi: Moshi, @ApplicationContext context: Context): OneInchApiFactory { + fun provideOneInchApiFactory( + @NetworkMoshi moshi: Moshi, + @ApplicationContext context: Context, + auth1Inch: AuthBearerProvider, + ): OneInchApiFactory { val networks = mapOf( ETH_NETWORK to ONE_INCH_ETH_PATH, BSC_NETWORK to ONE_INCH_BSC_PATH, @@ -38,14 +45,19 @@ class OneInchApisModule { for ((network, path) in networks) { apiFactory.putApi( networkId = network, - api = createOneInchApiWithUrl("$ONE_INCH_BASE_URL$path", moshi, context), + api = createOneInchApiWithUrl("$ONE_INCH_BASE_URL$path", moshi, context, auth1Inch), ) } return apiFactory } - private fun createOneInchApiWithUrl(url: String, moshi: Moshi, context: Context): OneInchApi { + private fun createOneInchApiWithUrl( + url: String, + moshi: Moshi, + context: Context, + auth1Inch: AuthBearerProvider, + ): OneInchApi { return Retrofit.Builder() .addConverterFactory( MoshiConverterFactory.create(moshi), @@ -53,6 +65,7 @@ class OneInchApisModule { .baseUrl(url) .client( OkHttpClient.Builder() + .addHeaders(RequestHeader.AuthBearerHeader(auth1Inch)) .addLoggers(context) .build(), ) @@ -61,7 +74,7 @@ class OneInchApisModule { } companion object { - private const val ONE_INCH_BASE_URL = "https://api-tangem.1inch.io/v5.2/" + private const val ONE_INCH_BASE_URL = "https://api.1inch.dev/swap/v5.2/" private const val ONE_INCH_ETH_PATH = "1/" private const val ONE_INCH_BSC_PATH = "56/" private const val ONE_INCH_POLYGON_PATH = "137/" diff --git a/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt b/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt index 6a5fde6a53..d84b00ac2e 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt @@ -1,5 +1,6 @@ package com.tangem.datasource.utils +import com.tangem.lib.auth.AuthBearerProvider import com.tangem.lib.auth.AuthProvider import com.tangem.lib.auth.ExpressAuthProvider @@ -25,4 +26,8 @@ sealed class RequestHeader(vararg pairs: Pair String>) { "user-id" to { expressAuthProvider.getUserId() }, "session-id" to { expressAuthProvider.getSessionId() }, ) + + class AuthBearerHeader(authBearerProvider: AuthBearerProvider) : RequestHeader( + "Authorization" to { "Bearer " + authBearerProvider.getApiKey() }, + ) } \ No newline at end of file diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 13ae7d8b04..6fe946df8b 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -97,7 +97,7 @@ По рынку Медленно Скорость и комиссия - Сгенерировать адреса + Получить адреса Импортировать Нравится Заблокирован @@ -658,10 +658,10 @@ Малое количество подписей Токены на разных сетях могут иметь разные адреса. Пожалуйста, убедитесь при переводе средств, что ваш адрес соответствует сети. - Используйте вашу карту, чтобы сгенерировать адрес для %d новой сети - Используйте вашу карту, чтобы сгенерировать адреса для %d новых сетей - Используйте вашу карту, чтобы сгенерировать адреса для %d новых сетей - Используйте вашу карту, чтобы сгенерировать адреса для %d новых сетей + Используйте вашу карту, чтобы получить адрес для %d сети + Используйте вашу карту, чтобы получить адреса для %d сетей + Используйте вашу карту, чтобы получить адреса для %d сетей + Используйте вашу карту, чтобы получить адреса для %d сетей Некоторые адреса отсутствуют В данный момент сеть недоступна. Пожалуйста, попробуйте позже. diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 44af8e6ed5..80dffcfc34 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -95,7 +95,7 @@ Market Slow Speed and fee - Generate addresses + Get addresses Import Learn & Earn Like @@ -689,8 +689,8 @@ Low signature count Tokens on different networks can have different addresses. Double-check that your address matches the network when you transfer funds. - Use your card to generate an address for %d new network - Use your card to generate an addresses for %d new networks + Use your card to get an address for %d network + Use your card to get an addresses for %d networks Some addresses are missing The network is currently unreachable. Please try again later. diff --git a/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt b/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt index 95a8e5e94e..92aa9d5a33 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt @@ -45,7 +45,7 @@ fun getActiveIconRes(blockchainId: String): Int { "octaspace", "octaspace/test" -> R.drawable.img_octaspace_22 "chia", "chia/test" -> R.drawable.img_chia_22 "NEAR", "NEAR/test" -> R.drawable.img_near_22 - "decimal", "decimal/testnet" -> R.drawable.img_decimal_22 + "decimal", "decimal/test" -> R.drawable.img_decimal_22 else -> R.drawable.ic_alert_24 } } diff --git a/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/DefaultAppCurrencyRepository.kt b/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/DefaultAppCurrencyRepository.kt index bce54591e8..b86e0bb03c 100644 --- a/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/DefaultAppCurrencyRepository.kt +++ b/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/DefaultAppCurrencyRepository.kt @@ -9,6 +9,7 @@ import com.tangem.datasource.local.appcurrency.AvailableAppCurrenciesStore import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.utils.getObject +import com.tangem.datasource.local.preferences.utils.getSyncOrNull import com.tangem.datasource.local.preferences.utils.storeObject import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.appcurrency.repository.AppCurrencyRepository @@ -42,7 +43,9 @@ internal class DefaultAppCurrencyRepository( } withContext(dispatchers.io) { - fetchDefaultAppCurrency() + if (appPreferencesStore.getSyncOrNull(PreferencesKeys.SELECTED_APP_CURRENCY_KEY) == null) { + fetchDefaultAppCurrency() + } } } } diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/UpdateWalletManagerResultFactory.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/UpdateWalletManagerResultFactory.kt index 4a67053404..e865fcc408 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/UpdateWalletManagerResultFactory.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/UpdateWalletManagerResultFactory.kt @@ -10,7 +10,6 @@ import com.tangem.domain.walletmanager.model.CryptoCurrencyTransaction import com.tangem.domain.walletmanager.model.UpdateWalletManagerResult import timber.log.Timber import java.math.BigDecimal -import java.util.concurrent.TimeUnit import com.tangem.blockchain.common.address.Address as SdkAddress internal class UpdateWalletManagerResultFactory { @@ -125,7 +124,7 @@ internal class UpdateWalletManagerResultFactory { return TxHistoryItem( txHash = hash, - timestampInMillis = TimeUnit.SECONDS.toMillis(millis), + timestampInMillis = millis, isOutgoing = isOutgoing, destinationType = TxHistoryItem.DestinationType.Single( TxHistoryItem.AddressType.User(data.destinationAddress), diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt index 0710f995f6..f34e750f13 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt @@ -13,7 +13,7 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsBalanceBlockState import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification -import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsTxHistoryToTransactionStateConverter +import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsPendingTxToTransactionStateConverter import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents import com.tangem.utils.converter.Converter import kotlinx.collections.immutable.persistentListOf @@ -29,7 +29,7 @@ internal class TokenDetailsLoadedBalanceConverter( ) : Converter, TokenDetailsState> { private val txHistoryItemConverter by lazy { - TokenDetailsTxHistoryToTransactionStateConverter(symbol, decimals, clickIntents) + TokenDetailsPendingTxToTransactionStateConverter(symbol, decimals, clickIntents) } override fun convert(value: Either): TokenDetailsState { diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryToTransactionStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsPendingTxToTransactionStateConverter.kt similarity index 96% rename from features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryToTransactionStateConverter.kt rename to features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsPendingTxToTransactionStateConverter.kt index 8ae9a9ac43..6ba156961c 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryToTransactionStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsPendingTxToTransactionStateConverter.kt @@ -15,7 +15,9 @@ import com.tangem.utils.toFormattedCurrencyString import org.joda.time.DateTime import org.joda.time.DateTimeZone -internal class TokenDetailsTxHistoryToTransactionStateConverter( +// FIXME: Refactoring needed +/** Same as [TokenDetailsTxHistoryTransactionStateConverter] but with other timestamp format */ +internal class TokenDetailsPendingTxToTransactionStateConverter( private val symbol: String, private val decimals: Int, private val clickIntents: TokenDetailsClickIntents, diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt index 3b19f5da71..22d68befc8 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt @@ -13,6 +13,8 @@ import com.tangem.utils.converter.Converter import com.tangem.utils.toBriefAddressFormat import com.tangem.utils.toFormattedCurrencyString +// FIXME: Refactoring needed +/** Same as [TokenDetailsPendingTxToTransactionStateConverter] but with other timestamp format */ internal class TokenDetailsTxHistoryTransactionStateConverter( private val symbol: String, private val decimals: Int, diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt index 7d2d6a2019..ccd48ffb88 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt @@ -489,17 +489,19 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onTransactionClick(txHash: String) { - val blockchain = Blockchain.fromId(cryptoCurrency.network.id.value) - // TODO: Fix ton tx urls [REDACTED_TASK_KEY] - if (blockchain == Blockchain.TON || blockchain == Blockchain.TONTestnet) { - return - } else { - router.openUrl( - url = getExplorerTransactionUrlUseCase( - txHash = txHash, - networkId = cryptoCurrency.network.id, - ), - ) + // TODO: Fix tx urls [REDACTED_TASK_KEY] + when (Blockchain.fromId(cryptoCurrency.network.id.value)) { + Blockchain.TON, Blockchain.TONTestnet, + Blockchain.Decimal, Blockchain.DecimalTestnet, + -> return + else -> { + router.openUrl( + url = getExplorerTransactionUrlUseCase( + txHash = txHash, + networkId = cryptoCurrency.network.id, + ), + ) + } } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletLoadingTxHistoryConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletLoadingTxHistoryConverter.kt index adb05dd819..7767ac6d66 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletLoadingTxHistoryConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletLoadingTxHistoryConverter.kt @@ -32,7 +32,7 @@ internal class WalletLoadingTxHistoryConverter( private val txHistoryItemConverter by lazy { val blockchain = currentCardTypeResolverProvider().getBlockchain() - WalletTxHistoryTransactionStateConverter( + WalletPendingTxToTransactionStateConverter( symbol = blockchain.currency, decimals = blockchain.decimals(), clickIntents = clickIntents, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletPendingTxToTransactionStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletPendingTxToTransactionStateConverter.kt new file mode 100644 index 0000000000..a3d2cfa92e --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletPendingTxToTransactionStateConverter.kt @@ -0,0 +1,109 @@ +package com.tangem.feature.wallet.presentation.wallet.state.factory.txhistory + +import com.tangem.core.ui.components.transactions.state.TransactionState +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.wrappedList +import com.tangem.core.ui.utils.DateTimeFormatters +import com.tangem.domain.txhistory.models.TxHistoryItem +import com.tangem.feature.wallet.impl.R +import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents +import com.tangem.utils.converter.Converter +import com.tangem.utils.toBriefAddressFormat +import com.tangem.utils.toFormattedCurrencyString +import org.joda.time.DateTime +import org.joda.time.DateTimeZone + +// FIXME: Refactoring needed +/** Same as [WalletTxHistoryTransactionStateConverter] but with other timestamp format */ +internal class WalletPendingTxToTransactionStateConverter( + private val symbol: String, + private val decimals: Int, + private val clickIntents: WalletClickIntents, +) : Converter { + + override fun convert(value: TxHistoryItem): TransactionState { + return createTransactionStateItem(item = value) + } + + private fun createTransactionStateItem(item: TxHistoryItem): TransactionState { + return TransactionState.Content( + txHash = item.txHash, + amount = item.getAmount(), + timestamp = item.timestampInMillis.toTimeFormat(), + status = item.status.tiUiStatus(), + direction = item.extractDirection(), + iconRes = item.extractIcon(), + title = item.extractTitle(), + subtitle = item.extractSubtitle(), + onClick = { clickIntents.onTransactionClick(item.txHash) }, + ) + } + + private fun TxHistoryItem.extractIcon(): Int = if (status == TxHistoryItem.TransactionStatus.Failed) { + R.drawable.ic_close_24 + } else { + when (type) { + is TxHistoryItem.TransactionType.Approve -> R.drawable.ic_doc_24 + is TxHistoryItem.TransactionType.Operation, + is TxHistoryItem.TransactionType.Swap, + is TxHistoryItem.TransactionType.Transfer, + is TxHistoryItem.TransactionType.UnknownOperation, + -> if (isOutgoing) R.drawable.ic_arrow_up_24 else R.drawable.ic_arrow_down_24 + } + } + + private fun TxHistoryItem.extractTitle(): TextReference = when (val type = type) { + is TxHistoryItem.TransactionType.Approve -> resourceReference(R.string.common_approval) + is TxHistoryItem.TransactionType.Operation -> stringReference(type.name) + is TxHistoryItem.TransactionType.Swap -> resourceReference(R.string.common_swap) + is TxHistoryItem.TransactionType.Transfer -> resourceReference(R.string.common_transfer) + is TxHistoryItem.TransactionType.UnknownOperation -> resourceReference(R.string.transaction_history_operation) + } + + private fun TxHistoryItem.extractSubtitle(): TextReference = + when (val interactionAddress = interactionAddressType) { + is TxHistoryItem.InteractionAddressType.Contract -> resourceReference( + id = R.string.transaction_history_contract_address, + formatArgs = wrappedList(interactionAddress.address.toBriefAddressFormat()), + ) + is TxHistoryItem.InteractionAddressType.Multiple -> resourceReference( + id = if (isOutgoing) { + R.string.transaction_history_transaction_to_address + } else { + R.string.transaction_history_transaction_from_address + }, + formatArgs = wrappedList(resourceReference(R.string.transaction_history_multiple_addresses)), + ) + is TxHistoryItem.InteractionAddressType.User -> resourceReference( + id = if (isOutgoing) { + R.string.transaction_history_transaction_to_address + } else { + R.string.transaction_history_transaction_from_address + }, + formatArgs = wrappedList(interactionAddress.address.toBriefAddressFormat()), + ) + } + + private fun TxHistoryItem.TransactionStatus.tiUiStatus() = when (this) { + TxHistoryItem.TransactionStatus.Confirmed -> TransactionState.Content.Status.Confirmed + TxHistoryItem.TransactionStatus.Failed -> TransactionState.Content.Status.Failed + TxHistoryItem.TransactionStatus.Unconfirmed -> TransactionState.Content.Status.Unconfirmed + } + + private fun Long.toTimeFormat(): String { + return DateTimeFormatters.formatTime(time = DateTime(this, DateTimeZone.getDefault())) + } + + private fun TxHistoryItem.extractDirection() = + if (isOutgoing) TransactionState.Content.Direction.OUTGOING else TransactionState.Content.Direction.INCOMING + + private fun TxHistoryItem.getAmount(): String { + val prefix = when (status) { + TxHistoryItem.TransactionStatus.Failed -> "" + else -> if (isOutgoing) "-" else "+" + } + return prefix + amount.toFormattedCurrencyString(currency = symbol, decimals = decimals) + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryTransactionStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryTransactionStateConverter.kt index 31621a3785..a7b4c8efa5 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryTransactionStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryTransactionStateConverter.kt @@ -12,6 +12,8 @@ import com.tangem.utils.converter.Converter import com.tangem.utils.toBriefAddressFormat import com.tangem.utils.toFormattedCurrencyString +// FIXME: Refactoring needed +/** Same as [WalletPendingTxToTransactionStateConverter] but with other timestamp format */ internal class WalletTxHistoryTransactionStateConverter( private val symbol: String, private val decimals: Int, diff --git a/features/wallet/impl/src/main/res/drawable/ill_tron_card2_120_106.webp b/features/wallet/impl/src/main/res/drawable/ill_tron_card2_120_106.webp index b838e8308b..d77e4131f1 100644 Binary files a/features/wallet/impl/src/main/res/drawable/ill_tron_card2_120_106.webp and b/features/wallet/impl/src/main/res/drawable/ill_tron_card2_120_106.webp differ diff --git a/features/wallet/impl/src/main/res/drawable/ill_tron_card3_120_106.webp b/features/wallet/impl/src/main/res/drawable/ill_tron_card3_120_106.webp index 8bbda73d2e..5ef294e0f5 100644 Binary files a/features/wallet/impl/src/main/res/drawable/ill_tron_card3_120_106.webp and b/features/wallet/impl/src/main/res/drawable/ill_tron_card3_120_106.webp differ diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index fb9f8dad5f..d4c8361ff8 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -88,7 +88,7 @@ spr-client = "3.6.2" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "develop-401" +tangemBlockchainSdk = "develop-408" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "develop-312" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ diff --git a/libs/auth/src/main/java/com/tangem/lib/auth/AuthBearerProvider.kt b/libs/auth/src/main/java/com/tangem/lib/auth/AuthBearerProvider.kt new file mode 100644 index 0000000000..dbeac3aebe --- /dev/null +++ b/libs/auth/src/main/java/com/tangem/lib/auth/AuthBearerProvider.kt @@ -0,0 +1,12 @@ +package com.tangem.lib.auth + +/** + * Provides auth for tangemTech API + */ +interface AuthBearerProvider { + + /** + * Returns api-key + */ + fun getApiKey(): String +} \ No newline at end of file