Updated on 2026-08-14
This commit is contained in:
commit
e91c59c442
14 changed files with 116 additions and 49 deletions
|
|
@ -17,6 +17,7 @@ sealed class AppDialog : StateDialog {
|
|||
data class SimpleOkDialogRes(
|
||||
val headerId: Int,
|
||||
val messageId: Int,
|
||||
val args: List<String> = emptyList(),
|
||||
val onOk: VoidCallback? = null,
|
||||
) : AppDialog()
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class WalletConnectSessionsRepositoryImpl @Inject constructor(
|
|||
val fileContent = fileReader.readFile(getFileNameForUserWallet(userWallet))
|
||||
sessionsAdapter.fromJson(fileContent) ?: emptyList()
|
||||
} catch (exception: Exception) {
|
||||
Timber.e(exception)
|
||||
Timber.d(exception)
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import com.tangem.tap.domain.walletconnect.WalletConnectManager
|
|||
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
|
||||
import com.tangem.tap.features.intentHandler.IntentHandler
|
||||
import com.tangem.tap.store
|
||||
import timber.log.Timber
|
||||
import java.net.URLDecoder
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -23,10 +25,16 @@ class WalletConnectLinkIntentHandler : IntentHandler {
|
|||
else -> null
|
||||
}
|
||||
|
||||
return if (wcUri == null) {
|
||||
return if (wcUri.isNullOrBlank()) {
|
||||
false
|
||||
} else {
|
||||
store.dispatchWithMain(WalletConnectAction.HandleDeepLink(wcUri))
|
||||
val decodedWcUri = try {
|
||||
URLDecoder.decode(wcUri, DEFAULT_CHARSET_NAME)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
return false
|
||||
}
|
||||
store.dispatchWithMain(WalletConnectAction.HandleDeepLink(decodedWcUri))
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
@ -34,5 +42,6 @@ class WalletConnectLinkIntentHandler : IntentHandler {
|
|||
private companion object {
|
||||
private const val TANGEM_SCHEME = "tangem"
|
||||
private const val TANGEM_WC_PREFIX = "tangem://wc?uri="
|
||||
private const val DEFAULT_CHARSET_NAME = "UTF-8"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.features.tokens.impl.presentation.router
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
|
|
@ -49,12 +50,21 @@ internal class DefaultTokensListRouter(
|
|||
)
|
||||
}
|
||||
|
||||
override fun openUnsupportedSoltanaNetworkAlert() {
|
||||
store.dispatchDialogShow(
|
||||
AppDialog.SimpleOkDialogRes(
|
||||
override fun openUnsupportedNetworkAlert(blockchain: Blockchain) {
|
||||
val alert = when (blockchain) {
|
||||
Blockchain.Solana -> AppDialog.SimpleOkDialogRes(
|
||||
headerId = R.string.common_warning,
|
||||
messageId = R.string.alert_manage_tokens_unsupported_message,
|
||||
),
|
||||
)
|
||||
)
|
||||
Blockchain.Chia, Blockchain.ChiaTestnet -> AppDialog.SimpleOkDialogRes(
|
||||
headerId = R.string.common_warning,
|
||||
messageId = R.string.alert_manage_tokens_unsupported_curve_message,
|
||||
args = listOf(blockchain.fullName),
|
||||
)
|
||||
else -> null // there's no alerts for other blockchains yer
|
||||
}
|
||||
if (alert != null) {
|
||||
store.dispatchDialogShow(alert)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.features.tokens.impl.presentation.router
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
|
||||
/** Tokens list feature router */
|
||||
internal interface TokensListRouter {
|
||||
|
||||
|
|
@ -28,6 +30,9 @@ internal interface TokensListRouter {
|
|||
*/
|
||||
fun openRemoveWalletAlert(tokenName: String, onOkClick: () -> Unit)
|
||||
|
||||
/** Open alert if solana network is unsupported */
|
||||
fun openUnsupportedSoltanaNetworkAlert()
|
||||
/** Open alert if solana network is unsupported
|
||||
*
|
||||
* @param blockchain blockchain to show alert
|
||||
*/
|
||||
fun openUnsupportedNetworkAlert(blockchain: Blockchain)
|
||||
}
|
||||
|
|
@ -309,9 +309,13 @@ internal class TokensListViewModel @Inject constructor(
|
|||
toggledNetwork.changeToggleState()
|
||||
}
|
||||
} else {
|
||||
analyticsSender.sendWhenBlockchainAdded(blockchain)
|
||||
changedBlockchainList.add(blockchain)
|
||||
toggledNetwork.changeToggleState()
|
||||
if (isUnsupportedToken(blockchain)) {
|
||||
router.openUnsupportedNetworkAlert(blockchain)
|
||||
} else {
|
||||
analyticsSender.sendWhenBlockchainAdded(blockchain)
|
||||
changedBlockchainList.add(blockchain)
|
||||
toggledNetwork.changeToggleState()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -350,17 +354,8 @@ internal class TokensListViewModel @Inject constructor(
|
|||
toggledNetwork.changeToggleState()
|
||||
}
|
||||
} else {
|
||||
val scanResponse = reduxStateHolder.scanResponse
|
||||
val isUnsupportedToken =
|
||||
!(
|
||||
scanResponse?.card?.canHandleToken(
|
||||
blockchain = token.blockchain,
|
||||
cardTypesResolver = scanResponse.cardTypesResolver,
|
||||
) ?: false
|
||||
)
|
||||
|
||||
if (isUnsupportedToken) {
|
||||
router.openUnsupportedSoltanaNetworkAlert()
|
||||
if (isUnsupportedToken(token.blockchain)) {
|
||||
router.openUnsupportedNetworkAlert(token.blockchain)
|
||||
} else {
|
||||
analyticsSender.sendWhenTokenAdded(token.token)
|
||||
changedTokensList.add(token)
|
||||
|
|
@ -370,6 +365,15 @@ internal class TokensListViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun isUnsupportedToken(blockchain: Blockchain): Boolean {
|
||||
val scanResponse = reduxStateHolder.scanResponse
|
||||
val canHandleToken = scanResponse?.card?.canHandleToken(
|
||||
blockchain = blockchain,
|
||||
cardTypesResolver = scanResponse.cardTypesResolver,
|
||||
) ?: false
|
||||
return !canHandleToken
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val MAIN_NETWORK_LABEL = "MAIN"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.tap.features.wallet.redux.middlewares
|
|||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.data.source.preferences.model.DataSourceCurrency
|
||||
import com.tangem.data.source.preferences.model.DataSourceFiatCurrency
|
||||
import com.tangem.data.source.preferences.storage.FiatCurrenciesPrefStorage
|
||||
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
|
||||
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
|
||||
|
|
@ -52,21 +53,10 @@ class AppCurrencyMiddleware(
|
|||
}
|
||||
|
||||
private fun selectCurrency(action: WalletAction.AppCurrencyAction.SelectAppCurrency) {
|
||||
Analytics.send(MainScreen.MainCurrencyChanged(AnalyticsParam.CurrencyType.FiatCurrency(action.fiatCurrency)))
|
||||
|
||||
scope.launch {
|
||||
appCurrencyRepository.changeAppCurrency(action.fiatCurrency.code)
|
||||
|
||||
store.dispatchWithMain(GlobalAction.ChangeAppCurrency(action.fiatCurrency))
|
||||
store.dispatchWithMain(DetailsAction.ChangeAppCurrency(action.fiatCurrency))
|
||||
store.dispatchWithMain(WalletSelectorAction.ChangeAppCurrency(action.fiatCurrency))
|
||||
|
||||
val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard {
|
||||
Timber.e("Unable to select currency, no user wallet selected")
|
||||
return@launch
|
||||
}
|
||||
|
||||
tapWalletManager.loadData(selectedUserWallet, refresh = true)
|
||||
if (featureToggles.isRedesignedScreenEnabled) {
|
||||
selectCurrencyNew(action.fiatCurrency)
|
||||
} else {
|
||||
selectCurrencyLegacy(action.fiatCurrency)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -119,6 +109,42 @@ class AppCurrencyMiddleware(
|
|||
}
|
||||
}
|
||||
|
||||
private fun selectCurrencyNew(fiatCurrency: FiatCurrency) {
|
||||
Analytics.send(MainScreen.MainCurrencyChanged(AnalyticsParam.CurrencyType.FiatCurrency(fiatCurrency)))
|
||||
|
||||
scope.launch {
|
||||
appCurrencyRepository.changeAppCurrency(fiatCurrency.code)
|
||||
|
||||
store.dispatchWithMain(GlobalAction.ChangeAppCurrency(fiatCurrency))
|
||||
store.dispatchWithMain(DetailsAction.ChangeAppCurrency(fiatCurrency))
|
||||
store.dispatchWithMain(WalletSelectorAction.ChangeAppCurrency(fiatCurrency))
|
||||
|
||||
val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard {
|
||||
Timber.e("Unable to select currency, no user wallet selected")
|
||||
return@launch
|
||||
}
|
||||
|
||||
tapWalletManager.loadData(selectedUserWallet, refresh = true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun selectCurrencyLegacy(fiatCurrency: FiatCurrency) {
|
||||
Analytics.send(MainScreen.MainCurrencyChanged(AnalyticsParam.CurrencyType.FiatCurrency(fiatCurrency)))
|
||||
fiatCurrenciesPrefStorage.saveAppCurrency(
|
||||
with(fiatCurrency) { DataSourceFiatCurrency(code, name, symbol) },
|
||||
)
|
||||
store.dispatch(GlobalAction.ChangeAppCurrency(fiatCurrency))
|
||||
store.dispatch(DetailsAction.ChangeAppCurrency(fiatCurrency))
|
||||
store.dispatch(WalletSelectorAction.ChangeAppCurrency(fiatCurrency))
|
||||
val selectedUserWallet = userWalletsListManager.selectedUserWalletSync.guard {
|
||||
Timber.e("Unable to select currency, no user wallet selected")
|
||||
return
|
||||
}
|
||||
scope.launch {
|
||||
tapWalletManager.loadData(selectedUserWallet, refresh = true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<DataSourceCurrency>.mapToUiModel(): List<FiatCurrency> {
|
||||
return this.map {
|
||||
FiatCurrency(
|
||||
|
|
|
|||
|
|
@ -25,9 +25,14 @@ object SimpleOkDialog {
|
|||
}
|
||||
|
||||
fun create(dialog: AppDialog.SimpleOkDialogRes, context: Context): AlertDialog {
|
||||
val message = if (dialog.args.isEmpty()) {
|
||||
context.getString(dialog.messageId)
|
||||
} else {
|
||||
context.getString(dialog.messageId, *dialog.args.toTypedArray())
|
||||
}
|
||||
return AlertDialog.Builder(context).apply {
|
||||
setTitle(context.getString(dialog.headerId))
|
||||
setMessage(dialog.messageId)
|
||||
setMessage(message)
|
||||
setPositiveButton(R.string.common_ok) { _, _ -> }
|
||||
setOnDismissListener {
|
||||
store.dispatchDialogHide()
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
<string name="alert_failed_to_send_transaction_message">Причина: %s</string>
|
||||
<string name="alert_failed_to_send_transaction_title">Не могу отправить транзакцию</string>
|
||||
<string name="alert_manage_tokens_addresses_message">Внимание! Валюты на разных сетях имеют разные адреса. Убедитесь, что адрес соответствует сети, в которой вы отправляете средства.</string>
|
||||
<string name="alert_manage_tokens_unsupported_curve_message">Для активации криптографии сети %1$s необходимо сбросить кошелек до заводских настроек. Пожалуйста, выведите свои средства, чтобы не потерять их, после сброса доступ к текущему кошельку будет невозможен.</string>
|
||||
<string name="alert_manage_tokens_unsupported_message">Токены в сети Solana не поддерживаются этой картой из-за ограничений прошивки.</string>
|
||||
<string name="alert_signed_hashes_message">Эта карта не является платежным средством. В настоящее время мы не можем сопоставить количество подписей на карте с информацией в блокчейне. Это нормально, но в редких случаях может означать, что предыдущий владелец удерживает подписанную транзакцию от публикации, что является поводом для беспокойства.\nНе принимайте эту карту в качестве физического платежа от кого-то, кому вы не доверяете.\nВо всех остальных отношениях эта карта совершенно безопасна.\nTangem — единственный аппаратный кошелек, предлагающий защиту методом подсчета подписей.</string>
|
||||
<string name="alert_troubleshooting_scan_card_title">У вас возникли трудности со сканированием карты?</string>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
<string name="alert_failed_to_send_transaction_message">Reason: %s</string>
|
||||
<string name="alert_failed_to_send_transaction_title">Can\'t send a transaction</string>
|
||||
<string name="alert_manage_tokens_addresses_message">Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds.</string>
|
||||
<string name="alert_manage_tokens_unsupported_curve_message">To activate the %1$s blockchain\'s cryptographic encryption, you\'ll need to reset the wallet to factory settings. Please withdraw your funds before doing so to ensure that you don\'t lose them, and then complete the reset process. Access to the current wallet will not be possible after the reset.</string>
|
||||
<string name="alert_manage_tokens_unsupported_message">Tokens in Solana network are not supported by this card due to firmware limitation.</string>
|
||||
<string name="alert_signed_hashes_message">This card is not a bearer note. We can\'t currently match the signature count on the card with the information on the blockchain. This is normal but in rare cases can mean a previous holder is holding back an offline signature, which is a security concern.\nDo not accept this card as physical payment from someone you don\'t trust.\nIt\'s perfectly safe in all other respects.\nTangem is the only hardware wallet to offer signature count protection.</string>
|
||||
<string name="alert_troubleshooting_scan_card_title">Are you having difficulty scanning your card?</string>
|
||||
|
|
|
|||
|
|
@ -18,13 +18,14 @@ object Wallet2CardConfig : CardConfig {
|
|||
* Logic to determine primary curve for blockchain in TangemWallet 2.0
|
||||
*/
|
||||
override fun primaryCurve(blockchain: Blockchain): EllipticCurve? {
|
||||
// order is important, new curve is preferred for wallet 2
|
||||
return when {
|
||||
blockchain.getSupportedCurves().contains(EllipticCurve.Secp256k1) -> {
|
||||
EllipticCurve.Secp256k1
|
||||
}
|
||||
blockchain.getSupportedCurves().contains(EllipticCurve.Ed25519Slip0010) -> {
|
||||
EllipticCurve.Ed25519Slip0010
|
||||
}
|
||||
blockchain.getSupportedCurves().contains(EllipticCurve.Secp256k1) -> {
|
||||
EllipticCurve.Secp256k1
|
||||
}
|
||||
blockchain.getSupportedCurves().contains(EllipticCurve.Bls12381G2Aug) -> {
|
||||
EllipticCurve.Bls12381G2Aug
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,10 +15,13 @@ val FirmwareVersion.Companion.SolanaTokensAvailable
|
|||
|
||||
fun CardDTO.supportedBlockchains(cardTypesResolver: CardTypesResolver): List<Blockchain> {
|
||||
val supportedBlockchains = if (firmwareVersion < FirmwareVersion.MultiWalletAvailable) {
|
||||
Blockchain.fromCurve(EllipticCurve.Secp256k1)
|
||||
Blockchain.fromCurve(EllipticCurve.Secp256k1).toMutableList()
|
||||
} else if (!cardTypesResolver.isWallet2() && !cardTypesResolver.isTangemWallet()) {
|
||||
// need for old multiwallet that supports only secp256k1
|
||||
wallets.flatMap { Blockchain.fromCurve(it.curve) }.distinct().toMutableList()
|
||||
} else {
|
||||
wallets.flatMap { Blockchain.fromCurve(it.curve) }.distinct()
|
||||
}.toMutableList()
|
||||
Blockchain.values().toMutableList()
|
||||
}
|
||||
// disabled Cardano for wallet 2 for now, should be enabled after key processed
|
||||
// ([REDACTED_JIRA])
|
||||
if (cardTypesResolver.isWallet2()) {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import java.io.Serializable
|
|||
* @property derivationPath Optional path used for key derivation. `null` if the wallet does not support the
|
||||
* [HD Wallet](https://coinsutra.com/hd-wallets-deterministic-wallet/) feature.
|
||||
*/
|
||||
// TODO: [REDACTED_JIRA] delete serializable
|
||||
sealed class CryptoCurrency : Serializable {
|
||||
|
||||
abstract val id: ID
|
||||
|
|
@ -82,7 +83,7 @@ sealed class CryptoCurrency : Serializable {
|
|||
private val prefix: Prefix,
|
||||
private val networkId: Network.ID,
|
||||
private val suffix: Suffix,
|
||||
) {
|
||||
) : Serializable {
|
||||
|
||||
val value: String = buildString {
|
||||
append(prefix.value)
|
||||
|
|
@ -113,7 +114,7 @@ sealed class CryptoCurrency : Serializable {
|
|||
*
|
||||
* The suffix can either be a raw ID or a contract address.
|
||||
*/
|
||||
sealed class Suffix {
|
||||
sealed class Suffix : Serializable {
|
||||
|
||||
/** The value of the suffix, which could be either a raw ID or a contract address. */
|
||||
abstract val value: String
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ okHttp-prettyLogging = "3.1.0"
|
|||
# endregion Other libraries
|
||||
|
||||
# region Tangem
|
||||
tangemBlockchainSdk = "develop-318"
|
||||
tangemBlockchainSdk = "develop-322"
|
||||
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
||||
tangemCardSdk = "develop-289"
|
||||
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue