Updated on 2026-08-14
This commit is contained in:
parent
d1798a2c49
commit
6dee2eeed7
112 changed files with 2146 additions and 1562 deletions
|
|
@ -11,10 +11,6 @@ sealed class TotalFiatBalance {
|
|||
|
||||
object Loading : TotalFiatBalance()
|
||||
|
||||
data class Refreshing(
|
||||
override val amount: BigDecimal,
|
||||
) : TotalFiatBalance()
|
||||
|
||||
data class Error(
|
||||
override val amount: BigDecimal,
|
||||
) : TotalFiatBalance()
|
||||
|
|
|
|||
|
|
@ -6,22 +6,23 @@ import com.tangem.domain.common.util.UserWalletId
|
|||
|
||||
/**
|
||||
* Represents user's wallet which stored in app persistence
|
||||
* @param name User's wallet name
|
||||
* @param walletId User's wallet [UserWalletId]
|
||||
* @param name User wallet name
|
||||
* @param walletId User wallet [UserWalletId]
|
||||
* @param artworkUrl User wallet card artwork URL
|
||||
* @param cardsInWallet List of cards IDs assigned with this user's wallet
|
||||
* @param isMultiCurrency Indicates whether this user wallet can work with more than one currency
|
||||
* @param scanResponse [ScanResponse] of primary user's wallet card.
|
||||
* TODO: Replace with [com.tangem.domain.common.CardDTO]
|
||||
* @property cardId ID of user's wallet primary card
|
||||
* @property hasAccessCode Indicates if the user's wallet primary card has access code
|
||||
* @property isLocked Indicates if this primary card has no currency wallets
|
||||
* @property isSaved Indicates if this user wallet is saved
|
||||
* */
|
||||
data class UserWallet(
|
||||
val name: String,
|
||||
val walletId: UserWalletId,
|
||||
val artworkUrl: String,
|
||||
val cardsInWallet: Set<String>,
|
||||
val isMultiCurrency: Boolean,
|
||||
val scanResponse: ScanResponse,
|
||||
) {
|
||||
val cardId: String
|
||||
|
|
@ -32,17 +33,18 @@ data class UserWallet(
|
|||
|
||||
val isLocked: Boolean
|
||||
get() = scanResponse.card.wallets.isEmpty()
|
||||
|
||||
internal var isSaved: Boolean = true
|
||||
}
|
||||
|
||||
/**
|
||||
* !!! Workaround !!!
|
||||
*
|
||||
* Calculate same [UserWalletId] for twins instead
|
||||
*
|
||||
* TODO: Remove after [REDACTED_JIRA]
|
||||
* */
|
||||
fun UserWallet.isTwinnedWith(other: UserWallet): Boolean {
|
||||
if (!scanResponse.isTangemTwins()) return false
|
||||
if (!scanResponse.isTangemTwins() || !other.scanResponse.isTangemTwins()) return false
|
||||
if (scanResponse.secondTwinPublicKey == null || other.scanResponse.secondTwinPublicKey == null) return false
|
||||
if (other.scanResponse.secondTwinPublicKey == scanResponse.card.wallets.firstOrNull()?.publicKey?.toHexString()) {
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,12 +35,6 @@ data class WalletDataModel(
|
|||
open val pendingTransactions: List<PendingTransaction> = emptyList()
|
||||
open val errorMessage: String? = null
|
||||
open val isErrorStatus: Boolean = false
|
||||
|
||||
fun asRefreshing() = Refreshing(
|
||||
amount = amount,
|
||||
pendingTransactions = pendingTransactions,
|
||||
errorMessage = errorMessage,
|
||||
)
|
||||
}
|
||||
|
||||
object Loading : Status()
|
||||
|
|
@ -74,12 +68,4 @@ data class WalletDataModel(
|
|||
object MissedDerivation : Status() {
|
||||
override val isErrorStatus: Boolean = true
|
||||
}
|
||||
|
||||
data class Refreshing(
|
||||
override val amount: BigDecimal,
|
||||
override val pendingTransactions: List<PendingTransaction>,
|
||||
override val errorMessage: String?,
|
||||
) : Status() {
|
||||
override val isErrorStatus: Boolean = errorMessage != null
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
package com.tangem.tap.domain.model
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.common.hdWallet.DerivationPath
|
||||
import com.tangem.domain.common.util.UserWalletId
|
||||
import com.tangem.tap.domain.model.WalletStoreModel.WalletRent
|
||||
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
||||
|
|
@ -8,21 +10,28 @@ import java.math.BigDecimal
|
|||
|
||||
/**
|
||||
* Contains info about the blockchain and its currencies
|
||||
* @param userWalletId ID of the [UserWallet] which uses that store
|
||||
* @param blockchainNetwork Store's [BlockchainNetwork]
|
||||
* @param walletManager Store's [WalletManager], may be null if it fails to create this manager. TODO: Remove after
|
||||
* WalletMiddleware refactoring
|
||||
* @param userWalletId ID of the associated [UserWallet]
|
||||
* @param blockchain [Blockchain] of this WalletStore
|
||||
* @param derivationPath [DerivationPath] of this store, null if the card does not support the
|
||||
* [HD Wallet](https://coinsutra.com/hd-wallets-deterministic-wallet/)
|
||||
* @param walletsData List of [WalletDataModel] which represents store's blockchain currency and tokens currencies
|
||||
* @param walletRent Store's [WalletRent], null if store has no rent or currency balance is greater then
|
||||
* @param walletRent [WalletRent], null if store has no rent or currency balance is greater then
|
||||
* [WalletRent.exemptionAmount]
|
||||
* @param blockchainNetwork [BlockchainNetwork].
|
||||
* TODO: Remove after WalletMiddleware refactoring
|
||||
* @param walletManager [WalletManager], may be null if it fails to create this manager.
|
||||
* TODO: Remove after WalletMiddleware refactoring
|
||||
* */
|
||||
data class WalletStoreModel(
|
||||
val userWalletId: UserWalletId,
|
||||
val blockchain: Blockchain,
|
||||
val derivationPath: DerivationPath?,
|
||||
val walletsData: List<WalletDataModel>,
|
||||
val walletRent: WalletRent?,
|
||||
@Deprecated("Don't use it, will be removed")
|
||||
val blockchainNetwork: BlockchainNetwork,
|
||||
@Deprecated("Don't use it, will be removed")
|
||||
val walletManager: WalletManager?,
|
||||
val walletsData: List<WalletDataModel>,
|
||||
val walletRent: WalletRent?,
|
||||
) {
|
||||
|
||||
/**
|
||||
|
|
@ -35,4 +44,34 @@ data class WalletStoreModel(
|
|||
val rent: BigDecimal,
|
||||
val exemptionAmount: BigDecimal,
|
||||
)
|
||||
|
||||
// TODO: Remove the generated methods after blockchainNetwork and walletManager are removed from the model
|
||||
// region Generated
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is WalletStoreModel) return false
|
||||
|
||||
if (userWalletId != other.userWalletId) return false
|
||||
if (blockchain != other.blockchain) return false
|
||||
if (derivationPath != other.derivationPath) return false
|
||||
if (walletsData != other.walletsData) return false
|
||||
if (walletRent != other.walletRent) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = userWalletId.hashCode()
|
||||
result = 31 * result + blockchain.hashCode()
|
||||
result = 31 * result + (derivationPath?.hashCode() ?: 0)
|
||||
result = 31 * result + walletsData.hashCode()
|
||||
result = 31 * result + (walletRent?.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "WalletStoreModel(userWalletId=$userWalletId, blockchain=$blockchain, derivationPath=$derivationPath, " +
|
||||
"walletsData=$walletsData, walletRent=$walletRent)"
|
||||
}
|
||||
// endregion Generated
|
||||
}
|
||||
|
|
@ -1,15 +1,48 @@
|
|||
package com.tangem.tap.domain.model.builders
|
||||
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.common.services.Result
|
||||
import com.tangem.domain.common.CardDTO
|
||||
import com.tangem.domain.common.ProductType
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.domain.common.TwinCardNumber
|
||||
import com.tangem.domain.common.TwinsHelper
|
||||
import com.tangem.domain.common.util.userWalletId
|
||||
import com.tangem.tap.domain.extensions.getOrLoadCardArtworkUrl
|
||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||
import com.tangem.operations.attestation.TangemApi
|
||||
import com.tangem.tap.domain.model.UserWallet
|
||||
import com.tangem.tap.features.wallet.redux.Artwork
|
||||
|
||||
class UserWalletBuilder(
|
||||
private val scanResponse: ScanResponse,
|
||||
private val onlineCardVerifier: OnlineCardVerifier = OnlineCardVerifier(),
|
||||
) {
|
||||
private var backupCardsIds: Set<String> = emptySet()
|
||||
|
||||
private val CardDTO.isBackupNotAllowed: Boolean
|
||||
get() = !this.settings.isBackupAllowed
|
||||
|
||||
private val ScanResponse.userWalletName: String
|
||||
get() = when (productType) {
|
||||
ProductType.Note -> "Note"
|
||||
ProductType.Twins -> "Twin"
|
||||
ProductType.SaltPay -> "SaltPay"
|
||||
ProductType.Wallet -> when {
|
||||
card.isBackupNotAllowed -> "Tangem card"
|
||||
card.isStart2Coin -> "Start2Coin"
|
||||
else -> "Wallet"
|
||||
}
|
||||
}
|
||||
|
||||
private val ScanResponse.isMultiCurrency: Boolean
|
||||
get() = when (productType) {
|
||||
ProductType.Note -> false
|
||||
ProductType.Twins -> false
|
||||
ProductType.SaltPay -> false
|
||||
ProductType.Wallet -> !card.isStart2Coin
|
||||
}
|
||||
|
||||
fun backupCardsIds(backupCardsIds: Set<String>?) = this.apply {
|
||||
if (backupCardsIds != null) {
|
||||
this.backupCardsIds = backupCardsIds
|
||||
|
|
@ -20,11 +53,44 @@ class UserWalletBuilder(
|
|||
return with(scanResponse) {
|
||||
UserWallet(
|
||||
walletId = card.userWalletId,
|
||||
name = productType.name,
|
||||
artworkUrl = card.getOrLoadCardArtworkUrl(),
|
||||
name = userWalletName,
|
||||
artworkUrl = loadArtworkUrl(card.cardId, card.cardPublicKey),
|
||||
cardsInWallet = backupCardsIds.plus(card.cardId),
|
||||
scanResponse = this,
|
||||
isMultiCurrency = isMultiCurrency,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadArtworkUrl(cardId: String, cardPublicKey: ByteArray): String {
|
||||
return when (val result = onlineCardVerifier.getCardInfo(cardId, cardPublicKey)) {
|
||||
is Result.Success -> {
|
||||
val artworkId = result.data.artwork?.id
|
||||
if (artworkId.isNullOrEmpty()) {
|
||||
getFallbackArtworkUrl(cardId)
|
||||
} else {
|
||||
getUrlForArtwork(cardId, cardPublicKey.toHexString(), artworkId)
|
||||
}
|
||||
}
|
||||
|
||||
is Result.Failure -> getFallbackArtworkUrl(cardId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFallbackArtworkUrl(cardId: String): String {
|
||||
return when {
|
||||
cardId.startsWith(Artwork.SERGIO_CARD_ID) -> Artwork.SERGIO_CARD_URL
|
||||
cardId.startsWith(Artwork.MARTA_CARD_ID) -> Artwork.MARTA_CARD_URL
|
||||
else -> when (TwinsHelper.getTwinCardNumber(cardId)) {
|
||||
TwinCardNumber.First -> Artwork.TWIN_CARD_1
|
||||
TwinCardNumber.Second -> Artwork.TWIN_CARD_2
|
||||
else -> Artwork.DEFAULT_IMG_URL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getUrlForArtwork(cardId: String, cardPublicKeyHex: String, artworkId: String): String {
|
||||
return TangemApi.Companion.BaseUrl.VERIFY.url + TangemApi.ARTWORK +
|
||||
"?artworkId=${artworkId}&CID=${cardId}&publicKey=$cardPublicKeyHex"
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import com.tangem.blockchain.blockchains.polkadot.ExistentialDepositProvider
|
|||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.Token
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.common.hdWallet.DerivationPath
|
||||
import com.tangem.domain.common.util.UserWalletId
|
||||
import com.tangem.tap.domain.model.WalletDataModel
|
||||
import com.tangem.tap.domain.model.WalletStoreModel
|
||||
|
|
@ -54,10 +55,12 @@ private class BlockchainNetworkWalletStoreBuilderImpl(
|
|||
|
||||
return WalletStoreModel(
|
||||
userWalletId = userWalletId,
|
||||
blockchainNetwork = blockchainNetwork,
|
||||
walletManager = walletManager,
|
||||
blockchain = blockchainNetwork.blockchain,
|
||||
derivationPath = blockchainNetwork.derivationPath?.let { DerivationPath(it) },
|
||||
walletsData = (listOf(blockchainWalletData) + tokensWalletsData),
|
||||
walletRent = null,
|
||||
walletManager = walletManager,
|
||||
blockchainNetwork = blockchainNetwork,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -74,10 +77,12 @@ private class WalletMangerWalletStoreBuilderImpl(
|
|||
|
||||
return WalletStoreModel(
|
||||
userWalletId = userWalletId,
|
||||
blockchainNetwork = BlockchainNetwork.fromWalletManager(walletManager),
|
||||
walletManager = walletManager,
|
||||
blockchain = wallet.blockchain,
|
||||
derivationPath = wallet.publicKey.derivationPath,
|
||||
walletsData = (listOf(blockchainWalletData) + listOfNotNull(tokenWalletsData)),
|
||||
walletRent = null,
|
||||
walletManager = walletManager,
|
||||
blockchainNetwork = BlockchainNetwork.fromWalletManager(walletManager),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue