Updated on 2026-08-14
This commit is contained in:
commit
00e4779a40
12 changed files with 96 additions and 68 deletions
|
|
@ -11,6 +11,7 @@ import com.tangem.common.doOnFailure
|
|||
import com.tangem.common.doOnSuccess
|
||||
import com.tangem.common.services.Result
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.datasource.config.ConfigManager
|
||||
import com.tangem.domain.common.CardDTO
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.domain.common.TapWorkarounds.isTestCard
|
||||
|
|
@ -21,7 +22,6 @@ import com.tangem.tap.common.extensions.dispatchOnMain
|
|||
import com.tangem.tap.common.extensions.safeUpdate
|
||||
import com.tangem.tap.common.extensions.setContext
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.datasource.config.ConfigManager
|
||||
import com.tangem.tap.domain.extensions.makePrimaryWalletManager
|
||||
import com.tangem.tap.domain.extensions.makeWalletManagersForApp
|
||||
import com.tangem.tap.domain.model.UserWallet
|
||||
|
|
@ -29,6 +29,8 @@ import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
|||
import com.tangem.tap.domain.walletStores.WalletStoresError
|
||||
import com.tangem.tap.features.demo.isDemoCard
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
|
||||
import com.tangem.tap.features.disclaimer.createDisclaimer
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerAction
|
||||
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction
|
||||
import com.tangem.tap.features.wallet.models.toBlockchainNetworks
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
|
|
@ -110,8 +112,8 @@ class TapWalletManager {
|
|||
tangemSdkManager.changeDisplayedCardIdNumbersCount(scanResponse)
|
||||
store.state.globalState.feedbackManager?.infoHolder?.setCardInfo(scanResponse)
|
||||
updateConfigManager(scanResponse)
|
||||
|
||||
withMainContext {
|
||||
store.dispatch(DisclaimerAction.SetDisclaimer(card.createDisclaimer()))
|
||||
store.dispatch(WalletAction.UserWalletChanged(userWallet))
|
||||
store.dispatch(TwinCardsAction.IfTwinsPrepareState(scanResponse))
|
||||
store.dispatch(WalletConnectAction.ResetState)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import com.tangem.tap.common.extensions.setContext
|
|||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.features.disclaimer.DisclaimerType
|
||||
import com.tangem.tap.features.disclaimer.createDisclaimer
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerAction
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerCallback
|
||||
|
|
@ -150,7 +149,7 @@ object ScanCardProcessor {
|
|||
crossinline nextHandler: suspend (ScanResponse) -> Unit,
|
||||
crossinline onFailure: suspend (error: TangemError) -> Unit,
|
||||
) {
|
||||
val disclaimer = DisclaimerType.get(scanResponse.card).createDisclaimer(scanResponse.card)
|
||||
val disclaimer = scanResponse.card.createDisclaimer()
|
||||
store.dispatchOnMain(DisclaimerAction.SetDisclaimer(disclaimer))
|
||||
|
||||
if (disclaimer.isAccepted()) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.tap.domain.walletCurrencies.implementation
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.DerivationStyle
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.flatMap
|
||||
|
|
@ -69,7 +68,7 @@ internal class DefaultWalletCurrenciesManager(
|
|||
.flatMap {
|
||||
updateWalletStoresAmounts(
|
||||
userWallet = userWallet,
|
||||
updatedBlockchains = currenciesToAdd.map { it.blockchain }.distinct(),
|
||||
updatedCurrencies = currenciesToAddWithMissingBlockchains,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -220,11 +219,13 @@ internal class DefaultWalletCurrenciesManager(
|
|||
|
||||
private suspend fun updateWalletStoresAmounts(
|
||||
userWallet: UserWallet,
|
||||
updatedBlockchains: List<Blockchain>,
|
||||
updatedCurrencies: List<Currency>,
|
||||
): CompletionResult<Unit> {
|
||||
val updatedBlockchains = updatedCurrencies
|
||||
.filterIsInstance<Currency.Blockchain>()
|
||||
val updatedWalletStores = walletStoresRepository.get(userWallet.walletId)
|
||||
.firstOrNull()
|
||||
?.filter { it.blockchain in updatedBlockchains }
|
||||
?.filter { it.blockchainWalletData.currency in updatedBlockchains }
|
||||
?: return CompletionResult.Success(Unit)
|
||||
|
||||
return walletAmountsRepository.updateAmountsForWalletStores(
|
||||
|
|
|
|||
|
|
@ -142,8 +142,8 @@ internal class DefaultWalletAmountsRepository(
|
|||
Timber.e(
|
||||
error,
|
||||
"""
|
||||
Unable to fetch fiat rates
|
||||
|- Coins ids: $coinsIds
|
||||
Unable to fetch fiat rates
|
||||
|- Coins ids: $coinsIds
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
|
|
@ -278,6 +278,7 @@ internal class DefaultWalletAmountsRepository(
|
|||
Unable to fetch amounts
|
||||
|- User wallet id: ${walletStore.userWalletId}
|
||||
|- Blockchain: ${walletStore.blockchain}
|
||||
|- Derivation path: ${walletStore.derivationPath?.rawPath}
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
|
|
@ -310,6 +311,7 @@ internal class DefaultWalletAmountsRepository(
|
|||
Fetched amounts
|
||||
|- User wallet id: ${walletStore.userWalletId}
|
||||
|- Blockchain: ${walletStore.blockchain}
|
||||
|- Derivation path: ${walletStore.derivationPath?.rawPath}
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
|
|
@ -337,6 +339,7 @@ internal class DefaultWalletAmountsRepository(
|
|||
Missed derivation
|
||||
|- User wallet id: ${walletStore.userWalletId}
|
||||
|- Blockchain: ${walletStore.blockchain}
|
||||
|- Derivation path: ${walletStore.derivationPath?.rawPath}
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
|
|
@ -360,6 +363,7 @@ internal class DefaultWalletAmountsRepository(
|
|||
Wallet manager is null
|
||||
|- User wallet id: ${walletStore.userWalletId}
|
||||
|- Blockchain: ${walletStore.blockchain}
|
||||
|- Derivation path: ${walletStore.derivationPath?.rawPath}
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
|
|
@ -405,6 +409,7 @@ internal class DefaultWalletAmountsRepository(
|
|||
Fetched wallet rent
|
||||
|- User wallet id: ${walletStore.userWalletId}
|
||||
|- Blockchain: ${walletStore.blockchain}
|
||||
|- Derivation path: ${walletStore.derivationPath?.rawPath}
|
||||
|- Rent: $rent
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ internal class DefaultWalletManagersRepository(
|
|||
val foundWalletManager = findWalletManager(
|
||||
userWalletId = userWallet.walletId,
|
||||
blockchain = blockchainNetwork?.blockchain,
|
||||
derivationPath = blockchainNetwork?.derivationPath,
|
||||
)
|
||||
|
||||
foundWalletManager?.updateTokens(
|
||||
|
|
@ -85,7 +86,13 @@ internal class DefaultWalletManagersRepository(
|
|||
return when {
|
||||
blockchain == Blockchain.Unknown || blockchain == null -> {
|
||||
val error = WalletStoresError.UnknownBlockchain()
|
||||
Timber.e(error)
|
||||
Timber.e(
|
||||
error,
|
||||
"""
|
||||
Unknown blockchain while creating wallet manager
|
||||
|- User wallet ID: ${userWallet.walletId}
|
||||
""".trimIndent(),
|
||||
)
|
||||
CompletionResult.Failure(error)
|
||||
}
|
||||
walletManager != null -> {
|
||||
|
|
@ -97,7 +104,15 @@ internal class DefaultWalletManagersRepository(
|
|||
}
|
||||
else -> {
|
||||
val error = WalletStoresError.WalletManagerNotCreated(blockchain)
|
||||
Timber.e(error)
|
||||
Timber.e(
|
||||
error,
|
||||
"""
|
||||
Unable to create wallet manager
|
||||
|- User wallet ID: ${userWallet.walletId}
|
||||
|- Blockchain: $blockchain
|
||||
|- Derivation path: ${blockchainNetwork?.derivationPath}
|
||||
""".trimIndent(),
|
||||
)
|
||||
CompletionResult.Failure(error)
|
||||
}
|
||||
}
|
||||
|
|
@ -178,15 +193,19 @@ internal class DefaultWalletManagersRepository(
|
|||
private suspend fun findWalletManager(
|
||||
userWalletId: UserWalletId,
|
||||
blockchain: Blockchain?,
|
||||
derivationPath: String?,
|
||||
): WalletManager? {
|
||||
return walletManagersStorage.getAll()
|
||||
.firstOrNull()
|
||||
?.get(userWalletId)
|
||||
?.let { userWalletManagers ->
|
||||
if (blockchain == null) {
|
||||
if (blockchain == null || derivationPath == null) {
|
||||
userWalletManagers.firstOrNull()
|
||||
} else {
|
||||
userWalletManagers.firstOrNull { it.wallet.blockchain == blockchain }
|
||||
userWalletManagers.firstOrNull {
|
||||
it.wallet.blockchain == blockchain &&
|
||||
it.wallet.publicKey.derivationPath?.rawPath == derivationPath
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,9 +121,10 @@ private inline fun List<WalletStoreModel>.replaceWalletStores(
|
|||
if (currentWalletStore != updatedWalletStore) {
|
||||
Timber.d(
|
||||
"""
|
||||
Update wallet store in storage
|
||||
|- User wallet ID: ${updatedWalletStore.userWalletId}
|
||||
|- Blockchain: ${updatedWalletStore.blockchain}
|
||||
Update wallet store in storage
|
||||
|- User wallet ID: ${updatedWalletStore.userWalletId}
|
||||
|- Blockchain: ${updatedWalletStore.blockchain}
|
||||
|- Derivation path: ${updatedWalletStore.derivationPath?.rawPath}
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ fun DisclaimerType.createDisclaimer(cardDTO: CardDTO): Disclaimer {
|
|||
}
|
||||
}
|
||||
|
||||
fun CardDTO.createDisclaimer(): Disclaimer = DisclaimerType.get(this).createDisclaimer(this)
|
||||
|
||||
private fun provideDisclaimerDataProvider(cardId: String): DisclaimerDataProvider {
|
||||
return object : DisclaimerDataProvider {
|
||||
override fun getLanguage(): String = Locale.getDefault().language
|
||||
|
|
|
|||
|
|
@ -77,36 +77,35 @@ data class WalletData(
|
|||
if (currencyData.status == BalanceStatus.SameCurrencyTransactionInProgress) {
|
||||
walletWarnings.add(WalletWarning.TransactionInProgress(currency.currencyName))
|
||||
}
|
||||
}
|
||||
|
||||
private fun assembleBlockchainWarnings(walletWarnings: MutableList<WalletWarning>) {
|
||||
if (!currency.isBlockchain()) return
|
||||
|
||||
if (existentialDepositString != null) {
|
||||
val warning = WalletWarning.ExistentialDeposit(
|
||||
currencyName = currency.currencyName,
|
||||
edStringValueWithSymbol = "$existentialDepositString ${currency.currencySymbol}",
|
||||
)
|
||||
walletWarnings.add(warning)
|
||||
}
|
||||
if (walletRent != null) {
|
||||
walletWarnings.add(WalletWarning.Rent(walletRent))
|
||||
}
|
||||
}
|
||||
|
||||
private fun assembleTokenWarnings(walletWarnings: MutableList<WalletWarning>) {
|
||||
with(currency) {
|
||||
if (!isToken()) return
|
||||
private fun assembleBlockchainWarnings(walletWarnings: MutableList<WalletWarning>) = with(currency) {
|
||||
if (!isBlockchain()) return
|
||||
|
||||
if (blockchainAmountIsEmpty() && !tokenAmountIsEmpty()) {
|
||||
walletWarnings.add(
|
||||
WalletWarning.BalanceNotEnoughForFee(
|
||||
currencyName = currencyName,
|
||||
blockchainFullName = blockchain.fullName,
|
||||
blockchainSymbol = blockchain.currency,
|
||||
),
|
||||
)
|
||||
}
|
||||
if (existentialDepositString != null) {
|
||||
val warning = WalletWarning.ExistentialDeposit(
|
||||
currencyName = currencyName,
|
||||
edStringValueWithSymbol = "$existentialDepositString $currencySymbol",
|
||||
)
|
||||
walletWarnings.add(warning)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun assembleTokenWarnings(walletWarnings: MutableList<WalletWarning>) = with(currency) {
|
||||
if (!isToken()) return
|
||||
|
||||
if (blockchainAmountIsEmpty() && !tokenAmountIsEmpty()) {
|
||||
walletWarnings.add(
|
||||
WalletWarning.BalanceNotEnoughForFee(
|
||||
currencyName = currencyName,
|
||||
blockchainFullName = blockchain.fullName,
|
||||
blockchainSymbol = blockchain.currency,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -144,7 +144,9 @@ class UserWalletManagerImpl(
|
|||
val card = requireNotNull(appStateHolder.getActualCard()) { "card not found" }
|
||||
val blockchainNetwork = BlockchainNetwork(blockchain, card)
|
||||
val walletManager = appStateHolder.walletState?.getWalletManager(blockchainNetwork)
|
||||
return walletManager?.wallet?.recentTransactions?.lastOrNull()?.hash?.let { HEX_PREFIX + it }
|
||||
return walletManager?.wallet?.recentTransactions
|
||||
?.lastOrNull { it.hash?.isNotEmpty() == true }
|
||||
?.hash?.let { HEX_PREFIX + it }
|
||||
}
|
||||
|
||||
override suspend fun getCurrentWalletTokensBalance(
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="42dp">
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="42dp">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline_horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.5" />
|
||||
android:id="@+id/guideline_horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.5" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_currency"
|
||||
|
|
@ -64,16 +64,19 @@
|
|||
android:id="@+id/tv_status"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/text_tertiary"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/tv_amount"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/guideline_horizontal"
|
||||
app:lineHeight="20dp"
|
||||
tools:text="Unreachable..." />
|
||||
tools:text="Transaction in progress and it very long text with some strange status"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_exchange_rate"
|
||||
|
|
@ -86,5 +89,7 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/guideline_horizontal"
|
||||
app:lineHeight="20dp"
|
||||
tools:text="46 908 $" />
|
||||
tools:text="46 908 $"
|
||||
tools:visibility="gone" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ object Versions {
|
|||
// const val tangemBlockchainSdk = "0.0.1" // Keep it! - used for local builds
|
||||
|
||||
const val tangemCardSdk = "develop-191"
|
||||
// const val tangemCardSgk = "0.0.1" // Keep it! - used for local builds
|
||||
// const val tangemCardSdk = "0.0.1" // Keep it! - used for local builds
|
||||
// endregion Tangem
|
||||
|
||||
// region Tools
|
||||
|
|
|
|||
|
|
@ -13,15 +13,12 @@ val FirmwareVersion.Companion.SolanaTokensAvailable
|
|||
get() = FirmwareVersion(4, 52)
|
||||
|
||||
fun CardDTO.supportedBlockchains(): List<Blockchain> {
|
||||
val supportedBlockchains = when {
|
||||
firmwareVersion < FirmwareVersion.MultiWalletAvailable -> {
|
||||
Blockchain.fromCurve(EllipticCurve.Secp256k1)
|
||||
}
|
||||
|
||||
else -> {
|
||||
(Blockchain.fromCurve(EllipticCurve.Secp256k1) + Blockchain.fromCurve(EllipticCurve.Ed25519)).distinct()
|
||||
}
|
||||
val supportedBlockchains = if (firmwareVersion < FirmwareVersion.MultiWalletAvailable) {
|
||||
Blockchain.fromCurve(EllipticCurve.Secp256k1)
|
||||
} else {
|
||||
wallets.flatMap { Blockchain.fromCurve(it.curve) }.distinct()
|
||||
}
|
||||
|
||||
return supportedBlockchains
|
||||
.filter { isTestCard == it.isTestnet() }
|
||||
.filter { it.isSupportedInApp() }
|
||||
|
|
@ -38,12 +35,8 @@ fun CardDTO.supportedTokens(): List<Blockchain> {
|
|||
}
|
||||
}
|
||||
}
|
||||
val filtered = tokensSupportedByCard.filter { isTestCard == it.isTestnet() }
|
||||
return filtered
|
||||
}
|
||||
|
||||
fun CardDTO.canHandleBlockchain(blockchain: Blockchain): Boolean {
|
||||
return this.supportedBlockchains().contains(blockchain)
|
||||
return tokensSupportedByCard.filter { isTestCard == it.isTestnet() }
|
||||
}
|
||||
|
||||
fun CardDTO.canHandleToken(blockchain: Blockchain): Boolean {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue