Updated on 2026-08-14

This commit is contained in:
Tangem 2024-06-10 18:41:26 +01:00
commit 3fba2ae059
872 changed files with 17188 additions and 8108 deletions

View file

@ -9,16 +9,17 @@ android {
}
dependencies {
implementation(project(":core:datasource"))
implementation(project(":core:utils"))
implementation(project(":common"))
implementation(project(":libs:auth"))
implementation(projects.core.datasource)
implementation(projects.core.utils)
implementation(projects.common)
implementation(projects.libs.auth)
implementation(projects.libs.blockchainSdk)
implementation(projects.domain.demo)
implementation(projects.domain.models)
implementation(projects.domain.tokens.models)
implementation(projects.domain.transaction.models)
implementation(projects.domain.txhistory.models)
implementation(projects.domain.wallets.models)
/** Tangem libraries */
implementation(deps.tangem.blockchain) {
exclude(module = "joda-time")

View file

@ -20,6 +20,5 @@ object NetworkLogConfig {
object AnalyticsHandlersLogConfig {
const val firebase: Boolean = false
const val appsFlyer: Boolean = false
val amplitude: Boolean = BuildConfig.LOG_ENABLED
}

View file

@ -1,338 +0,0 @@
package com.tangem.domain.common.extensions
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.Token
import java.math.BigDecimal
@Suppress("ComplexMethod", "LongMethod")
fun Blockchain.Companion.fromNetworkId(networkId: String): Blockchain? {
return when (networkId) {
"arbitrum-one" -> Blockchain.Arbitrum
"arbitrum-one/test" -> Blockchain.ArbitrumTestnet
"avalanche", "avalanche-2" -> Blockchain.Avalanche
"avalanche/test", "avalanche-2/test" -> Blockchain.AvalancheTestnet
"binancecoin" -> Blockchain.Binance
"binancecoin/test" -> Blockchain.BinanceTestnet
"binance-smart-chain" -> Blockchain.BSC
"binance-smart-chain/test" -> Blockchain.BSCTestnet
"ethereum" -> Blockchain.Ethereum
"ethereum/test" -> Blockchain.EthereumTestnet
"ethereum-classic" -> Blockchain.EthereumClassic
"ethereum-classic/test" -> Blockchain.EthereumClassicTestnet
"polygon-pos", "matic-network" -> Blockchain.Polygon
"polygon-pos/test", "matic-network/test" -> Blockchain.PolygonTestnet
"solana" -> Blockchain.Solana
"solana/test" -> Blockchain.SolanaTestnet
"fantom" -> Blockchain.Fantom
"fantom/test" -> Blockchain.FantomTestnet
"bitcoin" -> Blockchain.Bitcoin
"bitcoin/test" -> Blockchain.BitcoinTestnet
"bitcoin-cash" -> Blockchain.BitcoinCash
"bitcoin-cash/test" -> Blockchain.BitcoinCashTestnet
"cardano" -> Blockchain.Cardano
"dogecoin" -> Blockchain.Dogecoin
"ducatus" -> Blockchain.Ducatus
"litecoin" -> Blockchain.Litecoin
"rootstock" -> Blockchain.RSK
"stellar" -> Blockchain.Stellar
"stellar/test" -> Blockchain.StellarTestnet
"tezos" -> Blockchain.Tezos
"tron" -> Blockchain.Tron
"tron/test" -> Blockchain.TronTestnet
"xrp", "ripple" -> Blockchain.XRP
"xdai" -> Blockchain.Gnosis
"ethereum-pow-iou" -> Blockchain.EthereumPow
"ethereum-pow-iou/test" -> Blockchain.EthereumPowTestnet
"ethereumfair", "dischain" -> Blockchain.Dischain // for old client compatibility
"polkadot" -> Blockchain.Polkadot
"polkadot/test" -> Blockchain.PolkadotTestnet
"kusama" -> Blockchain.Kusama
"optimistic-ethereum" -> Blockchain.Optimism
"optimistic-ethereum/test" -> Blockchain.OptimismTestnet
"dash" -> Blockchain.Dash
"kaspa" -> Blockchain.Kaspa
"the-open-network" -> Blockchain.TON
"the-open-network/test" -> Blockchain.TONTestnet
"kava" -> Blockchain.Kava
"kava/test" -> Blockchain.KavaTestnet
"ravencoin" -> Blockchain.Ravencoin
"ravencoin/test" -> Blockchain.RavencoinTestnet
"cosmos" -> Blockchain.Cosmos
"cosmos/test" -> Blockchain.CosmosTestnet
"terra" -> Blockchain.TerraV1
"terra-2" -> Blockchain.TerraV2
"cronos" -> Blockchain.Cronos
"telos" -> Blockchain.Telos
"telos/test" -> Blockchain.TelosTestnet
"aleph-zero" -> Blockchain.AlephZero
"aleph-zero/test" -> Blockchain.AlephZeroTestnet
"octaspace" -> Blockchain.OctaSpace
"octaspace/test" -> Blockchain.OctaSpaceTestnet
"chia" -> Blockchain.Chia
"chia/test" -> Blockchain.ChiaTestnet
"near-protocol" -> Blockchain.Near
"near-protocol/test" -> Blockchain.NearTestnet
"decimal" -> Blockchain.Decimal
"decimal/test" -> Blockchain.DecimalTestnet
"xdc-network" -> Blockchain.XDC
"xdc-network/test" -> Blockchain.XDCTestnet
"vechain" -> Blockchain.VeChain
"vechain/test" -> Blockchain.VeChainTestnet
"aptos" -> Blockchain.Aptos
"aptos/test" -> Blockchain.AptosTestnet
"playa3ull-games" -> Blockchain.Playa3ull
"shibarium" -> Blockchain.Shibarium
"shibarium/test" -> Blockchain.ShibariumTestnet
"algorand" -> Blockchain.Algorand
"algorand/test" -> Blockchain.AlgorandTestnet
"hedera-hashgraph" -> Blockchain.Hedera
"hedera-hashgraph/test" -> Blockchain.HederaTestnet
"aurora" -> Blockchain.Aurora
"aurora/test" -> Blockchain.AuroraTestnet
"areon-network" -> Blockchain.Areon
"areon-network/test" -> Blockchain.AreonTestnet
"pulsechain" -> Blockchain.PulseChain
"pulsechain/test" -> Blockchain.PulseChainTestnet
"zksync" -> Blockchain.ZkSyncEra
"zksync/test" -> Blockchain.ZkSyncEraTestnet
"moonbeam" -> Blockchain.Moonbeam
"moonbeam/test" -> Blockchain.MoonbeamTestnet
"manta-network" -> Blockchain.Manta
"manta-network/test" -> Blockchain.MantaTestnet
"polygon-zkevm" -> Blockchain.PolygonZkEVM
"polygon-zkevm/test" -> Blockchain.PolygonZkEVMTestnet
"nexa" -> Blockchain.Nexa // FIXME
"nexa/test" -> Blockchain.NexaTestnet // FIXME
"radiant" -> Blockchain.Radiant
"moonriver" -> Blockchain.Moonriver
"moonriver/test" -> Blockchain.MoonriverTestnet
"mantle" -> Blockchain.Mantle
"mantle/test" -> Blockchain.MantleTestnet
"flare-network" -> Blockchain.Flare
"flare-network/test" -> Blockchain.FlareTestnet
"taraxa" -> Blockchain.Taraxa
"taraxa/test" -> Blockchain.TaraxaTestnet
"base" -> Blockchain.Base
"base/test" -> Blockchain.BaseTestnet
else -> null
}
}
@Suppress("ComplexMethod", "LongMethod")
fun Blockchain.toNetworkId(): String {
return when (this) {
Blockchain.Unknown -> "unknown"
Blockchain.Arbitrum -> "arbitrum-one"
Blockchain.ArbitrumTestnet -> "arbitrum-one/test"
Blockchain.Avalanche -> "avalanche"
Blockchain.AvalancheTestnet -> "avalanche/test"
Blockchain.Binance -> "binancecoin"
Blockchain.BinanceTestnet -> "binancecoin/test"
Blockchain.BSC -> "binance-smart-chain"
Blockchain.BSCTestnet -> "binance-smart-chain/test"
Blockchain.Bitcoin -> "bitcoin"
Blockchain.BitcoinTestnet -> "bitcoin/test"
Blockchain.BitcoinCash -> "bitcoin-cash"
Blockchain.BitcoinCashTestnet -> "bitcoin-cash/test"
Blockchain.Cardano -> "cardano"
Blockchain.Dogecoin -> "dogecoin"
Blockchain.Ducatus -> "ducatus"
Blockchain.Ethereum -> "ethereum"
Blockchain.EthereumTestnet -> "ethereum/test"
Blockchain.EthereumClassic -> "ethereum-classic"
Blockchain.EthereumClassicTestnet -> "ethereum-classic/test"
Blockchain.Fantom -> "fantom"
Blockchain.FantomTestnet -> "fantom/test"
Blockchain.Litecoin -> "litecoin"
Blockchain.Polygon -> "polygon-pos"
Blockchain.PolygonTestnet -> "polygon-pos/test"
Blockchain.RSK -> "rootstock"
Blockchain.Stellar -> "stellar"
Blockchain.StellarTestnet -> "stellar/test"
Blockchain.Solana -> "solana"
Blockchain.SolanaTestnet -> "solana/test"
Blockchain.Tezos -> "tezos"
Blockchain.XRP -> "xrp"
Blockchain.Tron -> "tron"
Blockchain.TronTestnet -> "tron/test"
Blockchain.Gnosis -> "xdai"
Blockchain.EthereumPow -> "ethereum-pow-iou"
Blockchain.EthereumPowTestnet -> "ethereum-pow-iou/test"
Blockchain.Dischain -> "ethereumfair" // for backend compatibility
Blockchain.Polkadot -> "polkadot"
Blockchain.PolkadotTestnet -> "polkadot/test"
Blockchain.Kusama -> "kusama"
Blockchain.Optimism -> "optimistic-ethereum"
Blockchain.OptimismTestnet -> "optimistic-ethereum/test"
Blockchain.Dash -> "dash"
Blockchain.Kaspa -> "kaspa"
Blockchain.TON -> "the-open-network"
Blockchain.TONTestnet -> "the-open-network/test"
Blockchain.Kava -> "kava"
Blockchain.KavaTestnet -> "kava/test"
Blockchain.Ravencoin -> "ravencoin"
Blockchain.RavencoinTestnet -> "ravencoin/test"
Blockchain.Cosmos -> "cosmos"
Blockchain.CosmosTestnet -> "cosmos/test"
Blockchain.TerraV1 -> "terra"
Blockchain.TerraV2 -> "terra-2"
Blockchain.Cronos -> "cronos"
Blockchain.Telos -> "telos"
Blockchain.TelosTestnet -> "telos/test"
Blockchain.AlephZero -> "aleph-zero"
Blockchain.AlephZeroTestnet -> "aleph-zero/test"
Blockchain.OctaSpace -> "octaspace"
Blockchain.OctaSpaceTestnet -> "octaspace/test"
Blockchain.Chia -> "chia"
Blockchain.ChiaTestnet -> "chia/test"
Blockchain.Near -> "near-protocol"
Blockchain.NearTestnet -> "near-protocol/test"
Blockchain.Decimal -> "decimal"
Blockchain.DecimalTestnet -> "decimal/test"
Blockchain.XDC -> "xdc-network"
Blockchain.XDCTestnet -> "xdc-network/test"
Blockchain.VeChain -> "vechain"
Blockchain.VeChainTestnet -> "vechain/test"
Blockchain.Aptos -> "aptos"
Blockchain.AptosTestnet -> "aptos/test"
Blockchain.Playa3ull -> "playa3ull-games"
Blockchain.Shibarium -> "shibarium"
Blockchain.ShibariumTestnet -> "shibarium/test"
Blockchain.Algorand -> "algorand"
Blockchain.AlgorandTestnet -> "algorand/test"
Blockchain.Hedera -> "hedera-hashgraph"
Blockchain.HederaTestnet -> "hedera-hashgraph/test"
Blockchain.Aurora -> "aurora"
Blockchain.AuroraTestnet -> "aurora/test"
Blockchain.Areon -> "areon-network"
Blockchain.AreonTestnet -> "areon-network/test"
Blockchain.PulseChain -> "pulsechain"
Blockchain.PulseChainTestnet -> "pulsechain/test"
Blockchain.ZkSyncEra -> "zksync"
Blockchain.ZkSyncEraTestnet -> "zksync/test"
Blockchain.Moonbeam -> "moonbeam"
Blockchain.MoonbeamTestnet -> "moonbeam/test"
Blockchain.Manta -> "manta-network"
Blockchain.MantaTestnet -> "manta-network/test"
Blockchain.PolygonZkEVM -> "polygon-zkevm"
Blockchain.PolygonZkEVMTestnet -> "polygon-zkevm/test"
Blockchain.Nexa -> "nexa" // FIXME
Blockchain.NexaTestnet -> "nexa/test" // FIXME
Blockchain.Radiant -> "radiant"
Blockchain.Moonriver -> "moonriver"
Blockchain.MoonriverTestnet -> "moonriver/test"
Blockchain.Mantle -> "mantle"
Blockchain.MantleTestnet -> "mantle/test"
Blockchain.Flare -> "flare-network"
Blockchain.FlareTestnet -> "flare-network/test"
Blockchain.Taraxa -> "taraxa"
Blockchain.TaraxaTestnet -> "taraxa/test"
Blockchain.Base -> "base"
Blockchain.BaseTestnet -> "base/test"
}
}
@Suppress("ComplexMethod", "LongMethod")
fun Blockchain.toCoinId(): String {
return when (this) {
Blockchain.Binance, Blockchain.BinanceTestnet, Blockchain.BSC, Blockchain.BSCTestnet -> "binancecoin"
Blockchain.Bitcoin, Blockchain.BitcoinTestnet -> "bitcoin"
Blockchain.BitcoinCash, Blockchain.BitcoinCashTestnet -> "bitcoin-cash"
Blockchain.Ethereum, Blockchain.EthereumTestnet -> "ethereum"
Blockchain.EthereumClassic, Blockchain.EthereumClassicTestnet -> "ethereum-classic"
Blockchain.Stellar, Blockchain.StellarTestnet -> "stellar"
Blockchain.Cardano -> "cardano"
Blockchain.Polygon, Blockchain.PolygonTestnet -> "matic-network"
Blockchain.Arbitrum, Blockchain.ArbitrumTestnet -> "arbitrum-one"
Blockchain.Avalanche, Blockchain.AvalancheTestnet -> "avalanche-2"
Blockchain.Solana, Blockchain.SolanaTestnet -> "solana"
Blockchain.Fantom, Blockchain.FantomTestnet -> "fantom"
Blockchain.Tron, Blockchain.TronTestnet -> "tron"
Blockchain.Polkadot, Blockchain.PolkadotTestnet -> "polkadot"
Blockchain.Ducatus -> "ducatus"
Blockchain.Litecoin -> "litecoin"
Blockchain.RSK -> "rootstock"
Blockchain.Tezos -> "tezos"
Blockchain.XRP -> "ripple"
Blockchain.Dogecoin -> "dogecoin"
Blockchain.Gnosis -> "xdai"
Blockchain.EthereumPow, Blockchain.EthereumPowTestnet -> "ethereum-pow-iou"
Blockchain.Dischain -> "ethereumfair" // for backend compatibility
Blockchain.Kusama -> "kusama"
Blockchain.Optimism, Blockchain.OptimismTestnet -> "optimistic-ethereum"
Blockchain.Dash -> "dash"
Blockchain.Kaspa -> "kaspa"
Blockchain.TON, Blockchain.TONTestnet -> "the-open-network"
Blockchain.Kava, Blockchain.KavaTestnet -> "kava"
Blockchain.Ravencoin, Blockchain.RavencoinTestnet -> "ravencoin"
Blockchain.Cosmos, Blockchain.CosmosTestnet -> "cosmos"
Blockchain.TerraV1 -> "terra-luna"
Blockchain.TerraV2 -> "terra-luna-2"
Blockchain.Cronos -> "crypto-com-chain"
Blockchain.Telos, Blockchain.TelosTestnet -> "telos"
Blockchain.AlephZero, Blockchain.AlephZeroTestnet -> "aleph-zero"
Blockchain.OctaSpace, Blockchain.OctaSpaceTestnet -> "octaspace"
Blockchain.Chia, Blockchain.ChiaTestnet -> "chia"
Blockchain.Near -> "near"
Blockchain.NearTestnet -> "near/test"
Blockchain.Decimal, Blockchain.DecimalTestnet -> "decimal"
Blockchain.XDC, Blockchain.XDCTestnet -> "xdce-crowd-sale"
Blockchain.VeChain, Blockchain.VeChainTestnet -> "vechain"
Blockchain.Aptos -> "aptos"
Blockchain.AptosTestnet -> "aptos/test"
Blockchain.Playa3ull -> "playa3ull-games-2"
Blockchain.Shibarium -> "bone-shibaswap"
Blockchain.ShibariumTestnet -> "bone-shibaswap/test"
Blockchain.Algorand -> "algorand"
Blockchain.AlgorandTestnet -> "algorand/test"
Blockchain.Unknown -> "unknown"
Blockchain.Hedera -> "hedera-hashgraph"
Blockchain.HederaTestnet -> "hedera-hashgraph/test"
Blockchain.Aurora, Blockchain.AuroraTestnet -> "aurora-ethereum"
Blockchain.Areon, Blockchain.AreonTestnet -> "areon-network"
Blockchain.PulseChain, Blockchain.PulseChainTestnet -> "pulsechain"
Blockchain.ZkSyncEra, Blockchain.ZkSyncEraTestnet -> "zksync-ethereum"
Blockchain.Moonbeam, Blockchain.MoonbeamTestnet -> "moonbeam"
Blockchain.Manta, Blockchain.MantaTestnet -> "manta-network-ethereum"
Blockchain.PolygonZkEVM, Blockchain.PolygonZkEVMTestnet -> "polygon-zkevm-ethereum"
Blockchain.Nexa, Blockchain.NexaTestnet -> "nexa" // FIXME
Blockchain.Radiant -> "radiant"
Blockchain.Moonriver, Blockchain.MoonriverTestnet -> "moonriver"
Blockchain.Mantle, Blockchain.MantleTestnet -> "mantle"
Blockchain.Flare, Blockchain.FlareTestnet -> "flare-networks"
Blockchain.Taraxa, Blockchain.TaraxaTestnet -> "taraxa"
Blockchain.Base, Blockchain.BaseTestnet -> "base-ethereum"
}
}
fun Blockchain.isSupportedInApp(): Boolean {
return !excludedBlockchains.contains(this)
}
fun Blockchain.amountToCreateAccount(token: Token? = null): BigDecimal? {
return when (this) {
Blockchain.Stellar -> if (token?.symbol == NODL) BigDecimal(NODL_AMOUNT_TO_CREATE_ACCOUNT) else BigDecimal.ONE
Blockchain.XRP -> BigDecimal.TEN
Blockchain.Near, Blockchain.NearTestnet -> 0.00182.toBigDecimal()
Blockchain.Aptos, Blockchain.AptosTestnet -> BigDecimal.ZERO
else -> null
}
}
fun Blockchain.minimalAmount(): BigDecimal {
return BigDecimal.ONE.movePointLeft(decimals())
}
private const val NODL = "NODL"
private const val NODL_AMOUNT_TO_CREATE_ACCOUNT = 1.5
private val excludedBlockchains = listOf(
Blockchain.Unknown,
Blockchain.Nexa,
Blockchain.NexaTestnet,
Blockchain.Radiant,
Blockchain.Manta,
Blockchain.MantaTestnet,
Blockchain.Mantle,
Blockchain.MantleTestnet,
)

View file

@ -1,6 +1,7 @@
package com.tangem.domain.common.extensions
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchainsdk.utils.isSupportedInApp
import com.tangem.common.card.EllipticCurve
import com.tangem.common.card.FirmwareVersion
import com.tangem.domain.common.CardTypesResolver
@ -22,7 +23,7 @@ fun CardDTO.supportedBlockchains(cardTypesResolver: CardTypesResolver): List<Blo
wallets.flatMap { Blockchain.fromCurve(it.curve) }.distinct().toMutableList()
} else {
// multiwallet supports all blockchains, move this logic to config
Blockchain.values().toMutableList()
Blockchain.entries.toMutableList()
}
return supportedBlockchains
.filter { isTestCard == it.isTestnet() }

View file

@ -6,6 +6,8 @@ import com.tangem.domain.tokens.model.CryptoCurrency
* Manager that holds info about available actions as Sell and Buy
*/
interface RampStateManager {
fun availableForBuy(cryptoCurrency: CryptoCurrency): Boolean
fun availableForSell(cryptoCurrency: CryptoCurrency): Boolean
}

View file

@ -10,4 +10,6 @@ interface ReduxStateHolder {
suspend fun dispatchWithMain(action: Action)
suspend fun onUserWalletSelected(userWallet: UserWallet)
fun sendFeedbackEmail()
}

View file

@ -2,11 +2,11 @@ package com.tangem.domain.redux.global
import android.webkit.ValueCallback
import com.tangem.common.extensions.toHexString
import com.tangem.datasource.api.common.AuthProvider
import com.tangem.datasource.utils.RequestHeader
import com.tangem.domain.redux.BaseStoreHub
import com.tangem.domain.redux.DomainState
import com.tangem.domain.redux.ReStoreReducer
import com.tangem.lib.auth.AuthProvider
import org.rekotlin.Action
/**

View file

@ -1,14 +0,0 @@
package com.tangem.domain.userwallets
data class Artwork(val artworkId: String) {
companion object {
const val DEFAULT_IMG_URL = "https://app.tangem.com/cards/card_default.png"
const val SERGIO_CARD_URL = "https://app.tangem.com/cards/card_tg059.png"
const val MARTA_CARD_URL = "https://app.tangem.com/cards/card_tg083.png"
const val SERGIO_CARD_ID = "BC01"
const val MARTA_CARD_ID = "BC02"
const val TWIN_CARD_1 = "https://app.tangem.com/cards/card_tg085.png"
const val TWIN_CARD_2 = "https://app.tangem.com/cards/card_tg086.png"
}
}

View file

@ -1,56 +0,0 @@
package com.tangem.domain.userwallets
import com.tangem.common.extensions.toHexString
import com.tangem.common.services.Result
import com.tangem.domain.common.TwinCardNumber
import com.tangem.domain.common.TwinsHelper
import com.tangem.operations.attestation.OnlineCardVerifier
import com.tangem.operations.attestation.TangemApi
/**
* Use case for getting card image url
*
* @property verifier REST API
*
[REDACTED_AUTHOR]
*/
class GetCardImageUseCase(private val verifier: OnlineCardVerifier = OnlineCardVerifier()) {
/**
* Get card image url
*
* @param cardId card id
* @param cardPublicKey card public key
*/
suspend operator fun invoke(cardId: String, cardPublicKey: ByteArray): String {
return when (val result = verifier.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"
}
}

View file

@ -1,69 +0,0 @@
package com.tangem.domain.userwallets
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ProductType
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.models.UserWallet
class UserWalletBuilder(
private val scanResponse: ScanResponse,
private val getCardImageUseCase: GetCardImageUseCase = GetCardImageUseCase(),
) {
private var backupCardsIds: Set<String> = emptySet()
private var hasBackupError: Boolean = false
private val CardDTO.isBackupNotAllowed: Boolean
get() = !this.settings.isBackupAllowed
private val ScanResponse.userWalletName: String
get() = when (productType) {
ProductType.Note -> "Note"
ProductType.Twins -> "Twin"
ProductType.Start2Coin -> "Start2Coin"
ProductType.Visa -> "Tangem Visa"
ProductType.Wallet,
ProductType.Wallet2,
ProductType.Ring,
-> when {
card.isBackupNotAllowed -> "Tangem card"
cardTypesResolver.isStart2Coin() -> "Start2Coin"
else -> "Wallet"
}
}
/**
* DANGEROUS!!!
* [backupCardsIds] will be non-empty list if card is backed up on current device.
*/
fun backupCardsIds(backupCardsIds: Set<String>?) = this.apply {
if (backupCardsIds != null) {
this.backupCardsIds = backupCardsIds
}
}
/**
* Sets if UserWallet has any backup errors (wrong curves etc). Use in onboarding
*/
fun hasBackupError(hasBackupError: Boolean) = this.apply {
this.hasBackupError = hasBackupError
}
suspend fun build(): UserWallet? {
return with(scanResponse) {
UserWalletIdBuilder.scanResponse(scanResponse)
.build()
?.let {
UserWallet(
walletId = it,
name = userWalletName,
artworkUrl = getCardImageUseCase.invoke(card.cardId, card.cardPublicKey),
cardsInWallet = backupCardsIds.plus(card.cardId),
scanResponse = this,
isMultiCurrency = cardTypesResolver.isMultiwalletAllowed(),
hasBackupError = hasBackupError,
)
}
}
}
}

View file

@ -1,83 +0,0 @@
package com.tangem.domain.userwallets
import com.tangem.common.extensions.calculateSha256
import com.tangem.common.extensions.hexToBytes
import com.tangem.crypto.Secp256k1
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
import com.tangem.domain.common.extensions.calculateHmacSha256
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ProductType
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.wallets.models.UserWalletId
class UserWalletIdBuilder private constructor(
private val publicKey: ByteArray?,
private val pairTwinPublicKey: ByteArray? = null,
) {
fun build(): UserWalletId? {
val seed = if (publicKey != null) {
if (pairTwinPublicKey != null) {
Secp256k1.sum(publicKey, pairTwinPublicKey)
} else {
publicKey
}
} else {
null
}
return seed?.let {
UserWalletId(value = calculateUserWalletId(it))
}
}
private fun calculateUserWalletId(seed: ByteArray?): ByteArray? {
val message = MESSAGE_FOR_WALLET_ID.toByteArray()
val keyHash = seed?.calculateSha256()
return if (keyHash != null) {
message.calculateHmacSha256(keyHash)
} else {
null
}
}
companion object {
private const val MESSAGE_FOR_WALLET_ID = "UserWalletID"
@Throws(IllegalArgumentException::class)
fun card(card: CardDTO): UserWalletIdBuilder {
require(!card.isTangemTwins) {
"For twin cards use scanResponse to ID calculation"
}
return UserWalletIdBuilder(findPublicKey(card.wallets))
}
fun scanResponse(scanResponse: ScanResponse): UserWalletIdBuilder {
return UserWalletIdBuilder(
publicKey = findPublicKey(scanResponse.card.wallets),
pairTwinPublicKey = when (scanResponse.productType) {
ProductType.Twins -> scanResponse.secondTwinPublicKey?.hexToBytes()
ProductType.Note,
ProductType.Wallet,
ProductType.Wallet2,
ProductType.Ring,
ProductType.Start2Coin,
ProductType.Visa,
-> null
},
)
}
fun walletPublicKey(publicKey: ByteArray): UserWalletId {
return UserWalletIdBuilder(
publicKey = publicKey,
).build()!!
}
private fun findPublicKey(wallets: List<CardDTO.Wallet>): ByteArray? {
return wallets.firstOrNull()
?.publicKey
}
}
}

View file

@ -1,12 +0,0 @@
package com.tangem.domain.walletconnect
import com.tangem.domain.wallets.models.UserWallet
import org.rekotlin.Action
sealed class WalletConnectActions : Action {
sealed class New {
data class Initialize(val userWallet: UserWallet) : WalletConnectActions()
data class SetupUserChains(val userWallet: UserWallet) : WalletConnectActions()
}
}

View file

@ -4,41 +4,43 @@ import arrow.core.Either
import arrow.core.raise.either
import arrow.core.raise.ensureNotNull
import arrow.core.right
import com.squareup.moshi.Moshi
import com.tangem.blockchain.blockchains.solana.RentProvider
import com.tangem.blockchain.common.*
import com.tangem.blockchain.common.address.Address
import com.tangem.blockchain.common.address.AddressType
import com.tangem.blockchain.common.address.EstimationFeeAddressFactory
import com.tangem.blockchain.common.datastorage.BlockchainDataStorage
import com.tangem.blockchain.common.logging.BlockchainSDKLogger
import com.tangem.blockchain.common.pagination.Page
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.blockchain.common.transaction.TransactionFee
import com.tangem.blockchain.common.txhistory.TransactionHistoryRequest
import com.tangem.blockchain.common.trustlines.AssetRequirementsManager
import com.tangem.blockchain.extensions.Result
import com.tangem.blockchain.extensions.SimpleResult
import com.tangem.crypto.bip39.Mnemonic
import com.tangem.blockchain.transactionhistory.models.TransactionHistoryRequest
import com.tangem.blockchainsdk.BlockchainSDKFactory
import com.tangem.crypto.hdWallet.DerivationPath
import com.tangem.datasource.asset.AssetReader
import com.tangem.datasource.config.ConfigManager
import com.tangem.datasource.asset.loader.AssetLoader
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.datasource.local.walletmanager.WalletManagersStore
import com.tangem.domain.common.util.hasDerivation
import com.tangem.domain.demo.DemoConfig
import com.tangem.domain.feedback.FeedbackManagerFeatureToggles
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
import com.tangem.domain.transaction.models.AssetRequirementsCondition
import com.tangem.domain.txhistory.models.PaginationWrapper
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.domain.txhistory.models.TxHistoryState
import com.tangem.domain.walletmanager.model.SmartContractMethod
import com.tangem.domain.walletmanager.model.UpdateWalletManagerResult
import com.tangem.domain.walletmanager.utils.*
import com.tangem.domain.walletmanager.utils.WalletManagerFactory
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.math.BigDecimal
import java.util.EnumSet
@ -49,31 +51,22 @@ import java.util.EnumSet
class DefaultWalletManagersFacade(
private val walletManagersStore: WalletManagersStore,
private val userWalletsStore: UserWalletsStore,
mnemonic: Mnemonic,
assetReader: AssetReader,
moshi: Moshi,
configManager: ConfigManager,
blockchainDataStorage: BlockchainDataStorage,
accountCreator: AccountCreator,
blockchainSDKLogger: BlockchainSDKLogger,
feedbackManagerFeatureToggles: FeedbackManagerFeatureToggles,
private val assetLoader: AssetLoader,
private val dispatchers: CoroutineDispatcherProvider,
blockchainSDKFactory: BlockchainSDKFactory,
) : WalletManagersFacade {
private val demoConfig by lazy { DemoConfig() }
private val resultFactory by lazy { UpdateWalletManagerResultFactory() }
private val walletManagerFactory by lazy {
WalletManagerFactory(
configManager = configManager,
accountCreator = accountCreator,
blockchainDataStorage = blockchainDataStorage,
blockchainSDKLogger = if (feedbackManagerFeatureToggles.isLocalLogsEnabled) blockchainSDKLogger else null,
)
}
private val walletManagerFactory by lazy { WalletManagerFactory(blockchainSDKFactory) }
private val sdkTokenConverter by lazy { SdkTokenConverter() }
private val txHistoryStateConverter by lazy { SdkTransactionHistoryStateConverter() }
private val txHistoryItemConverter by lazy { SdkTransactionHistoryItemConverter(assetReader, moshi) }
private val sdkPageConverter by lazy { SdkPageConverter() }
private val estimationFeeAddressFactory by lazy { EstimationFeeAddressFactory(mnemonic) }
private val cryptoCurrencyTypeConverter by lazy { CryptoCurrencyTypeConverter() }
private val requirementsConditionConverter by lazy { SdkRequirementsConditionConverter() }
private val estimationFeeAddressFactory by lazy { EstimationFeeAddressFactory() }
private val initMutex = Mutex()
override suspend fun update(
userWalletId: UserWalletId,
@ -192,7 +185,16 @@ class DefaultWalletManagersFacade(
address = walletManager.wallet.address,
filterType = when (currency) {
is CryptoCurrency.Coin -> TransactionHistoryRequest.FilterType.Coin
is CryptoCurrency.Token -> TransactionHistoryRequest.FilterType.Contract(currency.contractAddress)
is CryptoCurrency.Token -> {
val blockchainToken = Token(
name = currency.name,
symbol = currency.symbol,
contractAddress = currency.contractAddress,
decimals = currency.decimals,
id = currency.id.rawCurrencyId,
)
TransactionHistoryRequest.FilterType.Contract(blockchainToken)
}
},
)
.let(txHistoryStateConverter::convert)
@ -221,7 +223,16 @@ class DefaultWalletManagersFacade(
pageSize = pageSize,
filterType = when (currency) {
is CryptoCurrency.Coin -> TransactionHistoryRequest.FilterType.Coin
is CryptoCurrency.Token -> TransactionHistoryRequest.FilterType.Contract(currency.contractAddress)
is CryptoCurrency.Token -> {
val blockchainToken = Token(
name = currency.name,
symbol = currency.symbol,
contractAddress = currency.contractAddress,
decimals = currency.decimals,
id = currency.id.rawCurrencyId,
)
TransactionHistoryRequest.FilterType.Contract(blockchainToken)
}
},
),
)
@ -230,7 +241,8 @@ class DefaultWalletManagersFacade(
is Result.Success -> PaginationWrapper(
currentPage = sdkPageConverter.convert(page),
nextPage = sdkPageConverter.convert(itemsResult.data.nextPage),
items = txHistoryItemConverter.convertList(itemsResult.data.items),
items = SdkTransactionHistoryItemConverter(smartContractMethods = readSmartContractMethods())
.convertList(itemsResult.data.items),
)
is Result.Failure -> error(itemsResult.error.message ?: itemsResult.error.customMessage)
}
@ -324,24 +336,25 @@ class DefaultWalletManagersFacade(
blockchain: Blockchain,
derivationPath: String?,
): WalletManager? {
val userWallet = getUserWallet(userWalletId)
var walletManager = walletManagersStore.getSyncOrNull(
userWalletId = userWalletId,
blockchain = blockchain,
derivationPath = derivationPath,
)
if (walletManager == null) {
walletManager = walletManagerFactory.createWalletManager(
scanResponse = userWallet.scanResponse,
initMutex.withLock {
val userWallet = getUserWallet(userWalletId)
var walletManager = walletManagersStore.getSyncOrNull(
userWalletId = userWalletId,
blockchain = blockchain,
derivationPath = derivationPath?.let { DerivationPath(rawPath = it) },
) ?: return null
derivationPath = derivationPath,
)
if (walletManager == null) {
walletManager = walletManagerFactory.createWalletManager(
scanResponse = userWallet.scanResponse,
blockchain = blockchain,
derivationPath = derivationPath?.let { DerivationPath(rawPath = it) },
)
walletManager ?: return null
walletManagersStore.store(userWalletId, walletManager)
walletManagersStore.store(userWalletId, walletManager)
}
return walletManager
}
return walletManager
}
@Deprecated("Will be removed in future")
@ -442,12 +455,12 @@ class DefaultWalletManagersFacade(
destination: String,
userWalletId: UserWalletId,
network: Network,
): Result<TransactionFee>? {
): Result<TransactionFee>? = withContext(dispatchers.io) {
val walletManager = getOrCreateWalletManager(
userWalletId = userWalletId,
network = network,
)
return (walletManager as? TransactionSender)?.getFee(
(walletManager as? TransactionSender)?.getFee(
amount = amount,
destination = destination,
)
@ -504,20 +517,6 @@ class DefaultWalletManagersFacade(
return walletManager?.createTransaction(amount, fee, destination)
}
@Deprecated("Will be removed in future")
override suspend fun sendTransaction(
txData: TransactionData,
signer: CommonSigner,
userWalletId: UserWalletId,
network: Network,
): SimpleResult {
val walletManager = getOrCreateWalletManager(
userWalletId = userWalletId,
network = network,
)
return (walletManager as TransactionSender).send(txData, signer)
}
override suspend fun getRecentTransactions(
userWalletId: UserWalletId,
currency: CryptoCurrency,
@ -573,6 +572,45 @@ class DefaultWalletManagersFacade(
)
}
override suspend fun getAssetRequirements(
userWalletId: UserWalletId,
currency: CryptoCurrency,
): AssetRequirementsCondition? {
val walletManager = getOrCreateWalletManager(userWalletId = userWalletId, network = currency.network)
val currencyType = cryptoCurrencyTypeConverter.convert(currency)
if (walletManager !is AssetRequirementsManager || !walletManager.hasRequirements(currencyType)) return null
val condition = walletManager.requirementsCondition(currencyType) ?: return null
return requirementsConditionConverter.convert(condition)
}
override suspend fun associateAsset(
userWalletId: UserWalletId,
currency: CryptoCurrency,
signer: CommonSigner,
): SimpleResult {
val walletManager = getOrCreateWalletManager(userWalletId = userWalletId, network = currency.network)
val currencyType = cryptoCurrencyTypeConverter.convert(currency)
if (walletManager !is AssetRequirementsManager) {
return SimpleResult.Failure(
BlockchainSdkError.CustomError("WalletManager is not implemented AssetRequirementsManager"),
)
}
return walletManager.fulfillRequirements(currencyType, signer)
}
override suspend fun checkUtxoConsolidationAvailability(userWalletId: UserWalletId, network: Network): Boolean {
val blockchain = Blockchain.fromId(network.id.value)
val walletManager = getOrCreateWalletManager(
userWalletId = userWalletId,
blockchain = blockchain,
derivationPath = network.derivationPath.value,
) ?: return false
return (walletManager as? UtxoBlockchainManager)?.allowConsolidation == true
}
private fun updateWalletManagerTokensIfNeeded(walletManager: WalletManager, tokens: Set<CryptoCurrency.Token>) {
if (tokens.isEmpty()) return
@ -582,4 +620,8 @@ class DefaultWalletManagersFacade(
walletManager.addTokens(tokensToAdd)
}
private suspend fun readSmartContractMethods(): Map<String, SmartContractMethod> {
return assetLoader.loadMap<SmartContractMethod>(fileName = "contract_methods")
}
}

View file

@ -13,6 +13,7 @@ import com.tangem.blockchain.extensions.SimpleResult
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
import com.tangem.domain.transaction.models.AssetRequirementsCondition
import com.tangem.domain.txhistory.models.PaginationWrapper
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.domain.txhistory.models.TxHistoryState
@ -211,22 +212,6 @@ interface WalletManagersFacade {
network: Network,
): TransactionData?
/**
* Sends transaction
*
* @param txData transaction data
* @param signer card signer
* @param userWalletId selected wallet id
* @param network network of currency
*/
@Deprecated("Will be removed in future")
suspend fun sendTransaction(
txData: TransactionData,
signer: CommonSigner,
userWalletId: UserWalletId,
network: Network,
): SimpleResult
/** Get recent transactions of [userWalletId] for [currency] */
suspend fun getRecentTransactions(userWalletId: UserWalletId, currency: CryptoCurrency): List<TxHistoryItem>
@ -240,4 +225,24 @@ interface WalletManagersFacade {
decimals: Int,
id: String? = null,
): BigDecimal
/**
* Get requirements for asset(currency)
* @return null if there's no requirement, otherwise [AssetRequirementsCondition].
*/
suspend fun getAssetRequirements(userWalletId: UserWalletId, currency: CryptoCurrency): AssetRequirementsCondition?
suspend fun associateAsset(
userWalletId: UserWalletId,
currency: CryptoCurrency,
signer: CommonSigner,
): SimpleResult
/**
* Indicates UTXO consolidation availability
*
* @param userWalletId selected user wallet
* @param network availability for network
*/
suspend fun checkUtxoConsolidationAvailability(userWalletId: UserWalletId, network: Network): Boolean
}

View file

@ -0,0 +1,23 @@
package com.tangem.domain.walletmanager.utils
import com.tangem.blockchain.common.CryptoCurrencyType
import com.tangem.blockchain.common.Token
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.utils.converter.Converter
internal class CryptoCurrencyTypeConverter : Converter<CryptoCurrency, CryptoCurrencyType> {
override fun convert(value: CryptoCurrency): CryptoCurrencyType {
return when (value) {
is CryptoCurrency.Coin -> CryptoCurrencyType.Coin
is CryptoCurrency.Token -> CryptoCurrencyType.Token(
info = Token(
name = value.name,
symbol = value.symbol,
contractAddress = value.contractAddress,
decimals = value.decimals,
id = value.id.rawCurrencyId,
),
)
}
}
}

View file

@ -0,0 +1,18 @@
package com.tangem.domain.walletmanager.utils
import com.tangem.domain.transaction.models.AssetRequirementsCondition
import com.tangem.utils.converter.Converter
import com.tangem.blockchain.common.trustlines.AssetRequirementsCondition as SdkRequirementsCondition
internal class SdkRequirementsConditionConverter : Converter<SdkRequirementsCondition, AssetRequirementsCondition> {
override fun convert(value: SdkRequirementsCondition): AssetRequirementsCondition {
return when (value) {
SdkRequirementsCondition.PaidTransaction -> AssetRequirementsCondition.PaidTransaction
is SdkRequirementsCondition.PaidTransactionWithFee -> AssetRequirementsCondition.PaidTransactionWithFee(
feeAmount = requireNotNull(value.feeAmount.value),
feeCurrencySymbol = value.feeAmount.currencySymbol,
decimals = value.feeAmount.decimals,
)
}
}
}

View file

@ -1,20 +1,16 @@
package com.tangem.domain.walletmanager.utils
import com.squareup.moshi.Moshi
import com.tangem.blockchain.common.txhistory.TransactionHistoryItem
import com.tangem.datasource.asset.AssetReader
import com.tangem.blockchain.transactionhistory.models.TransactionHistoryItem
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.domain.walletmanager.model.SmartContractMethod
import com.tangem.utils.converter.Converter
import com.tangem.blockchain.common.txhistory.TransactionHistoryItem as SdkTransactionHistoryItem
import com.tangem.blockchain.transactionhistory.models.TransactionHistoryItem as SdkTransactionHistoryItem
internal class SdkTransactionHistoryItemConverter(
assetReader: AssetReader,
moshi: Moshi,
smartContractMethods: Map<String, SmartContractMethod>,
) : Converter<SdkTransactionHistoryItem, TxHistoryItem> {
private val typeConverter by lazy {
SdkTransactionTypeConverter(assetReader, moshi)
}
private val typeConverter by lazy { SdkTransactionTypeConverter(smartContractMethods) }
override fun convert(value: SdkTransactionHistoryItem): TxHistoryItem = TxHistoryItem(
txHash = value.txHash,
@ -58,7 +54,9 @@ internal class SdkTransactionHistoryItemConverter(
} else {
mapToInteractionAddressType(sourceType = sourceType)
}
is SdkTransactionHistoryItem.TransactionType.ContractMethod -> mapToInteractionAddressType(destinationType)
is SdkTransactionHistoryItem.TransactionType.ContractMethod,
is SdkTransactionHistoryItem.TransactionType.ContractMethodName,
-> mapToInteractionAddressType(destinationType)
}
}

View file

@ -1,9 +1,9 @@
package com.tangem.domain.walletmanager.utils
import com.tangem.blockchain.common.txhistory.TransactionHistoryState
import com.tangem.blockchain.transactionhistory.TransactionHistoryState
import com.tangem.domain.txhistory.models.TxHistoryState
import com.tangem.utils.converter.Converter
import com.tangem.blockchain.common.txhistory.TransactionHistoryState as SdkTransactionHistoryState
import com.tangem.blockchain.transactionhistory.TransactionHistoryState as SdkTransactionHistoryState
internal class SdkTransactionHistoryStateConverter : Converter<SdkTransactionHistoryState, TxHistoryState> {

View file

@ -1,47 +1,30 @@
package com.tangem.domain.walletmanager.utils
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import com.tangem.blockchain.common.txhistory.TransactionHistoryItem
import com.tangem.datasource.asset.AssetReader
import com.tangem.blockchain.transactionhistory.models.TransactionHistoryItem
import com.tangem.domain.txhistory.models.TxHistoryItem
import com.tangem.domain.walletmanager.model.SmartContractMethod
import com.tangem.utils.converter.Converter
class SdkTransactionTypeConverter(
private val assetReader: AssetReader,
private val moshi: Moshi,
internal class SdkTransactionTypeConverter(
private val smartContractMethods: Map<String, SmartContractMethod>,
) : Converter<TransactionHistoryItem.TransactionType, TxHistoryItem.TransactionType> {
private val adapter: JsonAdapter<Map<String, SmartContractMethod>> by lazy {
moshi.adapter(
Types.newParameterizedType(
Map::class.java,
String::class.java,
SmartContractMethod::class.java,
),
)
}
private val smartContractMethods by lazy { readSmartContractMethods() }
override fun convert(value: TransactionHistoryItem.TransactionType): TxHistoryItem.TransactionType {
return when (value) {
TransactionHistoryItem.TransactionType.Transfer -> TxHistoryItem.TransactionType.Transfer
is TransactionHistoryItem.TransactionType.ContractMethod -> {
return when (val name = smartContractMethods[value.id]?.name) {
"transfer" -> TxHistoryItem.TransactionType.Transfer
"approve" -> TxHistoryItem.TransactionType.Approve
"swap" -> TxHistoryItem.TransactionType.Swap
null -> TxHistoryItem.TransactionType.UnknownOperation
else -> TxHistoryItem.TransactionType.Operation(name = name.replaceFirstChar { it.titlecase() })
}
}
is TransactionHistoryItem.TransactionType.ContractMethod ->
getTransactionType(methodName = smartContractMethods[value.id]?.name)
is TransactionHistoryItem.TransactionType.ContractMethodName -> getTransactionType(methodName = value.name)
is TransactionHistoryItem.TransactionType.Transfer -> TxHistoryItem.TransactionType.Transfer
}
}
private fun readSmartContractMethods(): Map<String, SmartContractMethod> {
val json = assetReader.readJson("contract_methods")
return adapter.fromJson(json) ?: emptyMap()
private fun getTransactionType(methodName: String?): TxHistoryItem.TransactionType {
return when (methodName) {
"transfer" -> TxHistoryItem.TransactionType.Transfer
"approve" -> TxHistoryItem.TransactionType.Approve
"swap" -> TxHistoryItem.TransactionType.Swap
null -> TxHistoryItem.TransactionType.UnknownOperation
else -> TxHistoryItem.TransactionType.Operation(name = methodName.replaceFirstChar { it.titlecase() })
}
}
}

View file

@ -66,6 +66,7 @@ internal class TransactionDataToTxHistoryItemConverter(
value
}
}
is FeePaidCurrency.FeeResource -> value
}
}

View file

@ -1,7 +1,7 @@
package com.tangem.domain.walletmanager.utils
import com.tangem.blockchain.common.*
import com.tangem.domain.common.extensions.amountToCreateAccount
import com.tangem.blockchainsdk.utils.amountToCreateAccount
import com.tangem.domain.walletmanager.model.Address
import com.tangem.domain.walletmanager.model.CryptoCurrencyAmount
import com.tangem.domain.walletmanager.model.CryptoCurrencyTransaction
@ -114,7 +114,9 @@ internal class UpdateWalletManagerResultFactory {
is AmountType.Coin -> CryptoCurrencyAmount.Coin(
value = getCurrencyAmountValue(amount) ?: return null,
)
is AmountType.Reserve -> null
is AmountType.FeeResource,
AmountType.Reserve,
-> null
}
}
@ -135,7 +137,9 @@ internal class UpdateWalletManagerResultFactory {
txHistoryItem = txHistoryItem,
)
}
is AmountType.Reserve -> null
is AmountType.FeeResource,
AmountType.Reserve,
-> null
}
}

View file

@ -1,37 +1,21 @@
package com.tangem.domain.walletmanager.utils
import com.tangem.blockchain.common.AccountCreator
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.DerivationParams
import com.tangem.blockchain.common.WalletManager
import com.tangem.blockchain.common.datastorage.BlockchainDataStorage
import com.tangem.blockchain.common.logging.BlockchainSDKLogger
import com.tangem.blockchainsdk.BlockchainSDKFactory
import com.tangem.crypto.hdWallet.DerivationPath
import com.tangem.datasource.config.ConfigManager
import com.tangem.domain.common.DerivationStyleProvider
import com.tangem.domain.common.extensions.makeWalletManagerForApp
import com.tangem.domain.common.util.derivationStyleProvider
import com.tangem.domain.models.scan.ScanResponse
import timber.log.Timber
import com.tangem.blockchain.common.WalletManagerFactory as BlockchainWalletManagerFactory
internal class WalletManagerFactory(
configManager: ConfigManager,
accountCreator: AccountCreator,
blockchainDataStorage: BlockchainDataStorage,
blockchainSDKLogger: BlockchainSDKLogger? = null,
private val blockchainSDKFactory: BlockchainSDKFactory,
) {
private val sdkWalletManagerFactory by lazy {
BlockchainWalletManagerFactory(
config = configManager.config.blockchainSdkConfig,
accountCreator = accountCreator,
blockchainDataStorage = blockchainDataStorage,
loggers = listOfNotNull(blockchainSDKLogger),
)
}
fun createWalletManager(
suspend fun createWalletManager(
scanResponse: ScanResponse,
blockchain: Blockchain,
derivationPath: DerivationPath?,
@ -39,7 +23,7 @@ internal class WalletManagerFactory(
val derivationParams = getDerivationParams(derivationPath, scanResponse.derivationStyleProvider)
return try {
sdkWalletManagerFactory.makeWalletManagerForApp(
blockchainSDKFactory.getWalletManagerFactorySync()?.makeWalletManagerForApp(
scanResponse = scanResponse,
blockchain = blockchain,
derivationParams = derivationParams,

View file

@ -2,14 +2,14 @@ package com.tangem.domain.features
import com.google.common.truth.Truth
import com.tangem.blockchain.common.Blockchain
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.blockchainsdk.utils.fromNetworkId
import com.tangem.blockchainsdk.utils.toNetworkId
import org.junit.Test
class BlockchainTests {
@Test
fun allNetworkIdsAreImplemented() {
val unimplementedIds = Blockchain.values()
val unimplementedIds = Blockchain.entries
.toMutableList()
.apply {
remove(Blockchain.Unknown)