Updated on 2026-08-14

This commit is contained in:
Tangem 2022-05-17 16:33:42 +03:00
parent f6f8e7d2bb
commit 15b5d45d35
5 changed files with 81 additions and 65 deletions

View file

@ -93,7 +93,8 @@ dependencies {
implementation 'com.google.android.play:core-ktx:1.8.1'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
implementation 'com.tangem:blockchain:develop-77'
implementation 'com.tangem:blockchain:develop-78'
// implementation 'com.tangem:blockchain:0.0.1'
implementation 'com.tangem.tangem-sdk-kotlin:core:develop-142'
implementation 'com.tangem.tangem-sdk-kotlin:android:develop-142'

View file

@ -60,7 +60,8 @@ dependencies {
implementation implementation(project(path: ':common'))
// Tangem sdk's
implementation 'com.tangem:blockchain:develop-77'
implementation 'com.tangem:blockchain:develop-78'
// implementation 'com.tangem:blockchain:0.0.1'
implementation 'com.tangem.tangem-sdk-kotlin:core:develop-142'
implementation 'com.tangem.tangem-sdk-kotlin:android:develop-142'

View file

@ -1,12 +1,50 @@
package com.tangem.domain.common.extensions
import com.tangem.blockchain.common.Blockchain
import com.tangem.common.card.Card
import com.tangem.common.card.EllipticCurve
import com.tangem.common.card.FirmwareVersion
import com.tangem.domain.common.TapWorkarounds.isTestCard
/**
[REDACTED_AUTHOR]
*/
val FirmwareVersion.Companion.SolanaAvailable
get() = FirmwareVersion(4, 12)
val FirmwareVersion.Companion.SolanaTokensAvailable
get() = FirmwareVersion(4, 52)
get() = FirmwareVersion(4, 52)
fun Card.supportedBlockchains(): List<Blockchain> {
val supportedBlockchains = when {
firmwareVersion < FirmwareVersion.MultiWalletAvailable -> {
Blockchain.fromCurve(EllipticCurve.Secp256k1)
}
else -> {
Blockchain.fromCurve(EllipticCurve.Secp256k1) +
Blockchain.fromCurve(EllipticCurve.Ed25519)
}
}
val filtered = supportedBlockchains.filter { isTestCard == it.isTestnet() }
return filtered
}
fun Card.supportedTokens(): List<Blockchain> {
val tokensSupportedByBlockchain = supportedBlockchains().filter { it.canHandleTokens() }.toMutableList()
val tokensSupportedByCard = when {
firmwareVersion >= FirmwareVersion.SolanaTokensAvailable -> tokensSupportedByBlockchain
else -> {
tokensSupportedByBlockchain.apply {
remove(Blockchain.Solana)
remove(Blockchain.SolanaTestnet)
}
}
}
val filtered = tokensSupportedByCard.filter { isTestCard == it.isTestnet() }
return filtered
}
fun Card.canHandleBlockchain(blockchain: Blockchain): Boolean {
return this.supportedBlockchains().contains(blockchain)
}
fun Card.canHandleToken(blockchain: Blockchain): Boolean {
return this.supportedTokens().contains(blockchain)
}

View file

@ -13,6 +13,7 @@ import com.tangem.domain.DomainDialog
import com.tangem.domain.DomainWrapped
import com.tangem.domain.common.TapWorkarounds.derivationStyle
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.domain.common.extensions.supportedTokens
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.domain.common.form.*
import com.tangem.domain.features.addCustomToken.*
@ -141,16 +142,11 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
}
}
//TODO: Solana token
/**
* This feature is only needed until Solana coins are added.
* While they are not there - this function excludes the Solana blockchain if the user has
* filled in at least one field of the token.
*/
private suspend fun changeBlockchainNetworkList() {
val state = hubState
val networkBlockchainList = Network.getField<TokenBlockchainField>().itemList
val newNetworkBlockchainList: List<Blockchain> = state.getNetworks(state.getCustomTokenType())
val card = requireNotNull(globalState.scanResponse?.card)
val newNetworkBlockchainList: List<Blockchain> = state.getNetworks(card, state.getCustomTokenType())
val listsIdentical = newNetworkBlockchainList.toSet() == networkBlockchainList.toSet()
if (listsIdentical) return
@ -537,9 +533,7 @@ private class AddCustomTokenReducer(
}
is OnCreate -> {
val card = requireNotNull(globalState.scanResponse?.card)
val supportedTokenNetworkIds = AddCustomTokenState.getSupportedTokensBlockchain().map {
it.toNetworkId()
}
val supportedTokenNetworkIds = card.supportedTokens().map { it.toNetworkId() }
val tangemTechServiceManager = AddCustomTokenService(
tangemTechService = globalState.networkServices.tangemTechService,
supportedTokenNetworkIds = supportedTokenNetworkIds
@ -550,7 +544,7 @@ private class AddCustomTokenReducer(
DerivationStyle.LEGACY -> derivationPathState.copy(isVisible = true)
null, DerivationStyle.NEW -> derivationPathState.copy(isVisible = false)
}
val form = Form(AddCustomTokenState.createFormFields(CustomTokenType.Blockchain))
val form = Form(AddCustomTokenState.createFormFields(card, CustomTokenType.Blockchain))
state.copy(
cardDerivationStyle = card.derivationStyle,
form = form,
@ -558,7 +552,10 @@ private class AddCustomTokenReducer(
screenState = state.screenState.copy(derivationPath = derivationPathState)
)
}
is OnDestroy -> state.reset()
is OnDestroy -> {
val card = requireNotNull(globalState.scanResponse?.card)
state.reset(card)
}
is UpdateForm -> {
updateFormState(action.state)
}

View file

@ -2,17 +2,17 @@ package com.tangem.domain.features.addCustomToken.redux
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.DerivationStyle
import com.tangem.common.card.FirmwareVersion
import com.tangem.common.card.Card
import com.tangem.common.json.MoshiJsonConverter
import com.tangem.domain.AddCustomTokenError
import com.tangem.domain.DomainWrapped
import com.tangem.domain.common.extensions.SolanaAvailable
import com.tangem.domain.common.extensions.SolanaTokensAvailable
import com.tangem.domain.common.TapWorkarounds.isTestCard
import com.tangem.domain.common.extensions.supportedBlockchains
import com.tangem.domain.common.extensions.supportedTokens
import com.tangem.domain.common.form.*
import com.tangem.domain.features.addCustomToken.*
import com.tangem.domain.features.addCustomToken.CustomTokenFieldId.*
import com.tangem.domain.redux.DomainState
import com.tangem.domain.redux.domainStore
import com.tangem.domain.redux.state.StringActionStateConverter
import org.rekotlin.Action
import org.rekotlin.StateType
@ -109,12 +109,12 @@ data class AddCustomTokenState(
null
}
fun reset(): AddCustomTokenState {
fun reset(card: Card): AddCustomTokenState {
return this.copy(
appSavedCurrencies = null,
onTokenAddCallback = null,
cardDerivationStyle = null,
form = Form(createFormFields(CustomTokenType.Blockchain)),
form = Form(createFormFields(card, CustomTokenType.Blockchain)),
formErrors = emptyMap(),
tokenId = null,
warnings = emptySet(),
@ -135,8 +135,8 @@ data class AddCustomTokenState(
.getConvertedData()
}
fun getNetworks(type: CustomTokenType): List<Blockchain> {
return getNetworksList(type)
fun getNetworks(card: Card, type: CustomTokenType): List<Blockchain> {
return getNetworksList(card, type)
}
companion object {
@ -154,66 +154,45 @@ data class AddCustomTokenState(
else -> derivationNetwork
}.derivationPath(derivationStyle)
internal fun createFormFields(type: CustomTokenType): List<DataField<*>> {
internal fun createFormFields(card: Card, type: CustomTokenType): List<DataField<*>> {
return listOf(
TokenField(ContractAddress),
TokenBlockchainField(Network, getNetworksList(type)),
TokenBlockchainField(Network, getNetworksList(card, type)),
TokenField(Name),
TokenField(Symbol),
TokenField(Decimals),
TokenDerivationPathField(DerivationPath, getSupportedDerivations()),
TokenDerivationPathField(DerivationPath, getSupportedDerivations(card)),
)
}
/**
* Serves to determine the tokens that can be received from the TangemTech service
*/
internal fun getSupportedTokensBlockchain(): List<Blockchain> {
return Blockchain.values()
.filter { !it.isTestnet() }
.filter { it.canHandleTokens() }
}
/**
* Serves to determine the networks (blockchains & tokens) that can be selected by Form.Networks.
* Blockchain.Unknown - is the default selection
*/
private fun getNetworksList(type: CustomTokenType): List<Blockchain> {
private fun getNetworksList(card: Card, type: CustomTokenType): List<Blockchain> {
val evmBlockchains = Blockchain.values()
.filter { it.isEvm() }
.filter { !it.isTestnet() }
.filter { card.isTestCard == it.isTestnet() }
val additionalBlockchains = listOf(
Blockchain.Binance,
Blockchain.Solana,
Blockchain.Binance, Blockchain.BinanceTestnet,
Blockchain.Solana, Blockchain.SolanaTestnet,
)
val networks = (evmBlockchains + additionalBlockchains).toMutableList()
//life hack
val fwCardVersion = domainStore.state.globalState.scanResponse?.card?.firmwareVersion
?: FirmwareVersion(0, 0)
val solanaUnsupportedByCard = fwCardVersion < FirmwareVersion.SolanaAvailable
val solanaTokensUnsupportedByCard = fwCardVersion < FirmwareVersion.SolanaTokensAvailable
if (solanaUnsupportedByCard || solanaTokensUnsupportedByCard) networks.remove(Blockchain.Solana)
if (type == CustomTokenType.Token) networks.removeAll(getUnsupportedTokensBlockchain())
val supportedByCard = when (type) {
CustomTokenType.Blockchain -> card.supportedBlockchains()
CustomTokenType.Token -> card.supportedTokens()
}
val typedNetworksList = (evmBlockchains + additionalBlockchains)
.filter { supportedByCard.contains(it) }
.toMutableList()
val default = Blockchain.Unknown
networks.add(0, default)
typedNetworksList.add(0, default)
return networks
return typedNetworksList
}
private fun getUnsupportedTokensBlockchain(): List<Blockchain> {
return Blockchain.values()
.filter { !it.isTestnet() }
.filter { !it.canHandleTokens() }
.toMutableList()
}
private fun createFormValidators(): Map<CustomTokenFieldId, CustomTokenValidator<out Any>> {
return mapOf(
ContractAddress to TokenContractAddressValidator(),
@ -224,9 +203,9 @@ data class AddCustomTokenState(
)
}
private fun getSupportedDerivations(): List<Blockchain> {
private fun getSupportedDerivations(card: Card): List<Blockchain> {
val evmBlockchains = Blockchain.values().filter {
!it.isTestnet() && it.getChainId() != null
card.isTestCard == it.isTestnet() && it.getChainId() != null
}
return listOf(Blockchain.Unknown) + evmBlockchains
}