Updated on 2026-08-14
This commit is contained in:
commit
bdf42f778f
32 changed files with 244 additions and 53 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ internal object AddCustomTokenPreviewData {
|
|||
return setOf(
|
||||
AddCustomTokenWarning.PotentialScamToken,
|
||||
AddCustomTokenWarning.TokenAlreadyAdded,
|
||||
AddCustomTokenWarning.UnsupportedSolanaToken,
|
||||
AddCustomTokenWarning.UnsupportedToken(networkName = "Solana"),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<SocialNetworkLink> = 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"),
|
||||
)
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -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),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -107,6 +107,7 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager {
|
|||
walletConnectProjectId = configValues.walletConnectProjectId,
|
||||
tangemComAuthorization = configValues.tangemComAuthorization,
|
||||
tangemExpressApiKey = configValues.tangemExpressApiKey,
|
||||
oneInchApiKey = configValues.oneInchApiKey,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,4 +20,5 @@ data class Config(
|
|||
val walletConnectProjectId: String = "",
|
||||
val tangemComAuthorization: String? = null,
|
||||
val tangemExpressApiKey: String = "",
|
||||
val oneInchApiKey: String = "",
|
||||
)
|
||||
|
|
@ -42,6 +42,7 @@ class ConfigValueModel(
|
|||
val chiaFireAcademyApiKey: String?,
|
||||
val chiaTangemApiKey: String?,
|
||||
val tangemExpressApiKey: String,
|
||||
val oneInchApiKey: String,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
|
|
|
|||
|
|
@ -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/"
|
||||
|
|
|
|||
|
|
@ -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, () -> String>) {
|
|||
"user-id" to { expressAuthProvider.getUserId() },
|
||||
"session-id" to { expressAuthProvider.getSessionId() },
|
||||
)
|
||||
|
||||
class AuthBearerHeader(authBearerProvider: AuthBearerProvider) : RequestHeader(
|
||||
"Authorization" to { "Bearer " + authBearerProvider.getApiKey() },
|
||||
)
|
||||
}
|
||||
|
|
@ -97,7 +97,7 @@
|
|||
<string name="common_fee_selector_option_market">По рынку</string>
|
||||
<string name="common_fee_selector_option_slow">Медленно</string>
|
||||
<string name="common_fee_selector_title">Скорость и комиссия</string>
|
||||
<string name="common_generate_addresses">Сгенерировать адреса</string>
|
||||
<string name="common_generate_addresses">Получить адреса</string>
|
||||
<string name="common_import">Импортировать</string>
|
||||
<string name="common_like">Нравится</string>
|
||||
<string name="common_locked">Заблокирован</string>
|
||||
|
|
@ -658,10 +658,10 @@
|
|||
<string name="warning_low_signatures_title">Малое количество подписей</string>
|
||||
<string name="warning_manage_tokens_legacy_derivation_message">Токены на разных сетях могут иметь разные адреса. Пожалуйста, убедитесь при переводе средств, что ваш адрес соответствует сети.</string>
|
||||
<plurals name="warning_missing_derivation_message">
|
||||
<item quantity="one">Используйте вашу карту, чтобы сгенерировать адрес для %d новой сети</item>
|
||||
<item quantity="few">Используйте вашу карту, чтобы сгенерировать адреса для %d новых сетей</item>
|
||||
<item quantity="many">Используйте вашу карту, чтобы сгенерировать адреса для %d новых сетей</item>
|
||||
<item quantity="other">Используйте вашу карту, чтобы сгенерировать адреса для %d новых сетей</item>
|
||||
<item quantity="one">Используйте вашу карту, чтобы получить адрес для %d сети</item>
|
||||
<item quantity="few">Используйте вашу карту, чтобы получить адреса для %d сетей</item>
|
||||
<item quantity="many">Используйте вашу карту, чтобы получить адреса для %d сетей</item>
|
||||
<item quantity="other">Используйте вашу карту, чтобы получить адреса для %d сетей</item>
|
||||
</plurals>
|
||||
<string name="warning_missing_derivation_title">Некоторые адреса отсутствуют</string>
|
||||
<string name="warning_network_unreachable_message">В данный момент сеть недоступна. Пожалуйста, попробуйте позже.</string>
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@
|
|||
<string name="common_fee_selector_option_market">Market</string>
|
||||
<string name="common_fee_selector_option_slow">Slow</string>
|
||||
<string name="common_fee_selector_title">Speed and fee</string>
|
||||
<string name="common_generate_addresses">Generate addresses</string>
|
||||
<string name="common_generate_addresses">Get addresses</string>
|
||||
<string name="common_import">Import</string>
|
||||
<string name="common_learn_and_earn">Learn & Earn</string>
|
||||
<string name="common_like">Like</string>
|
||||
|
|
@ -689,8 +689,8 @@
|
|||
<string name="warning_low_signatures_title">Low signature count</string>
|
||||
<string name="warning_manage_tokens_legacy_derivation_message">Tokens on different networks can have different addresses. Double-check that your address matches the network when you transfer funds.</string>
|
||||
<plurals name="warning_missing_derivation_message">
|
||||
<item quantity="one">Use your card to generate an address for %d new network</item>
|
||||
<item quantity="other">Use your card to generate an addresses for %d new networks</item>
|
||||
<item quantity="one">Use your card to get an address for %d network</item>
|
||||
<item quantity="other">Use your card to get an addresses for %d networks</item>
|
||||
</plurals>
|
||||
<string name="warning_missing_derivation_title">Some addresses are missing</string>
|
||||
<string name="warning_network_unreachable_message">The network is currently unreachable. Please try again later.</string>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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<Either<CurrencyStatusError, CryptoCurrencyStatus>, TokenDetailsState> {
|
||||
|
||||
private val txHistoryItemConverter by lazy {
|
||||
TokenDetailsTxHistoryToTransactionStateConverter(symbol, decimals, clickIntents)
|
||||
TokenDetailsPendingTxToTransactionStateConverter(symbol, decimals, clickIntents)
|
||||
}
|
||||
|
||||
override fun convert(value: Either<CurrencyStatusError, CryptoCurrencyStatus>): TokenDetailsState {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<TxHistoryItem, TransactionState> {
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 77 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 90 KiB |
|
|
@ -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 ^
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.lib.auth
|
||||
|
||||
/**
|
||||
* Provides auth for tangemTech API
|
||||
*/
|
||||
interface AuthBearerProvider {
|
||||
|
||||
/**
|
||||
* Returns api-key
|
||||
*/
|
||||
fun getApiKey(): String
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue