Updated on 2026-08-14

This commit is contained in:
Tangem 2022-11-18 18:06:25 +03:00
parent 62a032e3d1
commit ebcf2f40e5
13 changed files with 222 additions and 81 deletions

View file

@ -2,10 +2,12 @@ package com.tangem.tap.proxy
import com.tangem.common.card.Card
import com.tangem.domain.common.ScanResponse
import com.tangem.tap.features.wallet.redux.WalletState
class CardStateHolder {
class AppStateHolder {
val scanResponse: ScanResponse? = null
val walletState: WalletState? = null
fun getActualCard(): Card? {
return scanResponse?.card

View file

@ -1,31 +1,55 @@
package com.tangem.tap.proxy
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.Token
import com.tangem.domain.common.TapWorkarounds.derivationStyle
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.lib.crypto.DerivationManager
import com.tangem.lib.crypto.models.Currency
import com.tangem.lib.crypto.models.NonNativeToken
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
import com.tangem.tap.features.tokens.redux.TokensMiddleware
import kotlin.coroutines.suspendCoroutine
class DerivationManagerImpl(
val tokesMiddleware: TokensMiddleware,
val cardStateHolder: CardStateHolder,
private val tokesMiddleware: TokensMiddleware,
private val appStateHolder: AppStateHolder,
) : DerivationManager {
override suspend fun deriveMissingBlockchains(networkId: String) {
if (cardStateHolder.scanResponse != null) { //todo how to get Currency list from token
tokesMiddleware.deriveMissingBlockchains(
cardStateHolder.scanResponse, emptyList(),
) {
override suspend fun deriveMissingBlockchains(currency: Currency) = suspendCoroutine<Boolean> { continuation ->
val blockchain = Blockchain.fromNetworkId(currency.networkId)
val card = appStateHolder.getActualCard()
if (blockchain != null && card != null) {
val appToken = if (currency is NonNativeToken) {
Token(
symbol = currency.symbol,
contractAddress = currency.contractAddress,
decimals = currency.decimalCount,
)
} else null
val blockchainNetwork = BlockchainNetwork(blockchain, card)
val appCurrency = com.tangem.tap.features.wallet.models.Currency.fromBlockchainNetwork(
blockchainNetwork,
appToken,
)
if (appStateHolder.scanResponse != null) {
tokesMiddleware.deriveMissingBlockchains(
scanResponse = appStateHolder.scanResponse,
listOf(appCurrency),
) {
continuation.resumeWith(Result.success(true))
}
}
} else {
continuation.resumeWith(Result.failure(IllegalStateException("no blockchain or card found")))
}
}
override fun hasDerivation(networkId: String): Boolean {
val scanResponse = cardStateHolder.scanResponse
val scanResponse = appStateHolder.scanResponse
val blockchain = Blockchain.fromNetworkId(networkId)
if (scanResponse != null && blockchain != null) {
val derivationPath = blockchain.derivationPath(cardStateHolder.getActualCard()?.derivationStyle)?.rawPath
val derivationPath = blockchain.derivationPath(appStateHolder.getActualCard()?.derivationStyle)?.rawPath
if (derivationPath.isNullOrEmpty()) return false
return scanResponse.hasDerivation(
blockchain,

View file

@ -1,68 +1,140 @@
package com.tangem.tap.proxy
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.DerivationParams
import com.tangem.blockchain.common.DerivationStyle
import com.tangem.blockchain.common.WalletManagerFactory
import com.tangem.common.card.Card
import com.tangem.domain.common.TapWorkarounds.derivationStyle
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.lib.crypto.UserWalletManager
import com.tangem.lib.crypto.models.Token
import com.tangem.lib.crypto.models.Currency
import com.tangem.lib.crypto.models.NativeToken
import com.tangem.lib.crypto.models.NonNativeToken
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.domain.extensions.getUserWalletId
import com.tangem.tap.domain.extensions.makeWalletManagerForApp
import com.tangem.tap.domain.tokens.UserTokensRepository
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
import com.tangem.tap.features.wallet.redux.WalletAction
import org.rekotlin.Action
import org.rekotlin.Store
class UserWalletManagerImpl(
private val userTokensRepository: UserTokensRepository,
private val cardStateHolder: CardStateHolder,
private val appStateHolder: AppStateHolder,
private val mainStore: Store<AppState>,
private val walletManagerFactory: WalletManagerFactory,
) : UserWalletManager {
override suspend fun getUserTokens(): List<Token> {
val card = cardStateHolder.getActualCard()
override suspend fun getUserTokens(): List<Currency> {
val card = appStateHolder.getActualCard()
if (card != null) {
userTokensRepository.getUserTokens(card)
.filter { it.isToken() }
.map {
Token(
id = it.coinId ?: "",
name = it.currencyName,
symbol = it.currencySymbol,
networkId = it.blockchain.toNetworkId(),
contractAddress = null,
decimalCount = it.decimals,
)
if (it is com.tangem.tap.features.wallet.models.Currency.Token) {
NonNativeToken(
id = it.coinId ?: "",
name = it.currencyName,
symbol = it.currencySymbol,
networkId = it.blockchain.toNetworkId(),
contractAddress = it.token.contractAddress,
decimalCount = it.token.decimals,
)
} else {
NativeToken(
id = it.coinId ?: "",
name = it.currencyName,
symbol = it.currencySymbol,
networkId = it.blockchain.toNetworkId(),
)
}
}
}
return emptyList()
}
override fun getWalletId(): String {
return cardStateHolder.getActualCard()?.getUserWalletId() ?: ""
return appStateHolder.getActualCard()?.getUserWalletId() ?: ""
}
override suspend fun isTokenAdded(token: Token): Boolean {
val card = cardStateHolder.getActualCard()
override suspend fun isTokenAdded(currency: Currency): Boolean {
val card = appStateHolder.getActualCard()
if (card != null) {
return userTokensRepository.getUserTokens(card)
.any { it.coinId.equals(token.id) } //todo ensure that its the same ids
.any { it.coinId.equals(currency.id) } //todo ensure that its the same ids
}
return false
}
//todo check is it sync operation
override fun addToken(token: Token) {
val card = cardStateHolder.getActualCard()
override fun addToken(currency: Currency) {
val action = if (currency is NativeToken) {
val card = appStateHolder.getActualCard()
if (card != null) {
addNativeTokenToWalletAction(currency, card)
} else {
throw IllegalStateException("card not found")
}
} else {
addNonNativeTokenToWalletAction(currency as NonNativeToken)
}
mainStore.dispatch(action)
}
override fun getWalletAddress(currency: Currency): String {
val blockchain = Blockchain.fromNetworkId(currency.networkId)
val card = appStateHolder.getActualCard()
if (blockchain != null && card != null) {
val blockchainNetwork = BlockchainNetwork(blockchain, card)
val walletManager = appStateHolder.walletState?.getWalletManager(blockchainNetwork)
if (walletManager != null) {
return walletManager.wallet.address
} else {
throw IllegalStateException("no wallet manager found")
}
} else {
throw IllegalStateException("no blockchain or card found")
}
}
private fun addNativeTokenToWalletAction(token: NativeToken, card: Card): Action {
val blockchain = Blockchain.fromNetworkId(token.networkId)
val scanResponse = appStateHolder.scanResponse
if (blockchain != null && scanResponse != null) {
val blockchainNetwork = BlockchainNetwork(blockchain, card)
var walletManager = appStateHolder.walletState?.getWalletManager(blockchainNetwork)
if (walletManager == null) {
walletManager = walletManagerFactory.makeWalletManagerForApp(
scanResponse = scanResponse,
blockchain = blockchain,
derivationParams = createDerivationParams(card.derivationStyle),
)
}
return WalletAction.MultiWallet.AddBlockchain(
blockchain = blockchainNetwork,
walletManager = walletManager,
save = true,
)
} else {
throw IllegalStateException("blockchain is not supported")
}
}
private fun addNonNativeTokenToWalletAction(token: NonNativeToken): Action {
val card = appStateHolder.getActualCard()
val blockchain = Blockchain.fromNetworkId(token.networkId)
if (card != null && blockchain != null) {
val addAction = WalletAction.MultiWallet.AddToken(
return WalletAction.MultiWallet.AddToken(
token = com.tangem.blockchain.common.Token(
id = token.id,
name = token.name,
symbol = token.symbol,
contractAddress = token.contractAddress
?: "", //todo clarify where to find that if data from back null
decimals = token.decimalCount ?: 0, //todo clarify where to find that if data from back null
contractAddress = token.contractAddress,
decimals = token.decimalCount,
),
blockchain = BlockchainNetwork(
blockchain,
@ -70,11 +142,12 @@ class UserWalletManagerImpl(
),
save = true,
)
mainStore.dispatch(addAction)
} else {
throw IllegalStateException("no card or blockchain found")
}
}
override fun getWalletAddress(token: Token): String {
return ""
private fun createDerivationParams(derivationStyle: DerivationStyle?): DerivationParams? {
return derivationStyle?.let { DerivationParams.Default(derivationStyle) } //todo clarify if its need to add Custom
}
}