Updated on 2026-08-14
This commit is contained in:
commit
3fba2ae059
872 changed files with 17188 additions and 8108 deletions
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -20,6 +20,5 @@ object NetworkLogConfig {
|
|||
|
||||
object AnalyticsHandlersLogConfig {
|
||||
const val firebase: Boolean = false
|
||||
const val appsFlyer: Boolean = false
|
||||
val amplitude: Boolean = BuildConfig.LOG_ENABLED
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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() }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -10,4 +10,6 @@ interface ReduxStateHolder {
|
|||
suspend fun dispatchWithMain(action: Action)
|
||||
|
||||
suspend fun onUserWalletSelected(userWallet: UserWallet)
|
||||
|
||||
fun sendFeedbackEmail()
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
||||
|
|
|
|||
|
|
@ -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() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -66,6 +66,7 @@ internal class TransactionDataToTxHistoryItemConverter(
|
|||
value
|
||||
}
|
||||
}
|
||||
is FeePaidCurrency.FeeResource -> value
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue