Updated on 2026-08-14

This commit is contained in:
Tangem 2023-07-31 19:44:09 +03:00
parent 160153bfa3
commit 68f5cef7b5
5 changed files with 93 additions and 62 deletions

View file

@ -67,7 +67,7 @@ internal class DefaultTokensRepository(
"Unable to find a user wallet with provided ID: $userWalletId"
}
}
require(!userWallet.isMultiCurrency) {
require(userWallet.isMultiCurrency) {
"Multi currency wallet excepted, but single currency wallet was found: $userWalletId"
}

View file

@ -6,7 +6,6 @@ import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.demo.DemoConfig
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.tokens.model.Network
import timber.log.Timber
import com.tangem.blockchain.common.Token as SdkToken
import com.tangem.domain.tokens.model.Token as DomainToken
@ -49,11 +48,11 @@ internal class CardTokensFactory(private val demoConfig: DemoConfig) {
}
return DomainToken(
id = getTokenId(sdkToken, blockchain),
networkId = Network.ID(blockchain.id),
id = getTokenId(blockchain, sdkToken),
networkId = getNetworkId(blockchain),
name = sdkToken.name,
symbol = sdkToken.symbol,
iconUrl = getCoinOrTokenIconUrl(sdkToken, blockchain),
iconUrl = getTokenIconUrl(blockchain, sdkToken),
decimals = sdkToken.decimals,
isCustom = false,
contractAddress = sdkToken.contractAddress,
@ -69,10 +68,10 @@ internal class CardTokensFactory(private val demoConfig: DemoConfig) {
return DomainToken(
id = getCoinId(blockchain),
networkId = Network.ID(blockchain.id),
networkId = getNetworkId(blockchain),
name = blockchain.fullName,
symbol = blockchain.currency,
iconUrl = getCoinIconId(blockchain),
iconUrl = getCoinIconUrl(blockchain),
decimals = blockchain.decimals(),
isCustom = false,
contractAddress = null,

View file

@ -2,11 +2,9 @@ package com.tangem.data.tokens.utils
import com.tangem.blockchain.common.Blockchain
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.domain.common.TapWorkarounds.derivationStyle
import com.tangem.domain.common.extensions.fromNetworkId
import com.tangem.domain.demo.DemoConfig
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.model.Token
import timber.log.Timber
import com.tangem.blockchain.common.Token as SdkToken
@ -29,17 +27,22 @@ internal class ResponseTokensFactory(private val demoConfig: DemoConfig) {
}
val sdkToken = createSdkToken(token)
val (tokenId, iconUrl) = if (sdkToken == null) {
getCoinId(blockchain) to getCoinIconUrl(blockchain)
} else {
getTokenId(blockchain, sdkToken) to getTokenIconUrl(blockchain, sdkToken)
}
return Token(
id = getTokenId(sdkToken, blockchain),
networkId = Network.ID(blockchain.id),
id = tokenId,
networkId = getNetworkId(blockchain),
name = token.name,
symbol = token.symbol,
decimals = token.decimals,
iconUrl = getCoinOrTokenIconUrl(sdkToken, blockchain),
iconUrl = iconUrl,
contractAddress = token.contractAddress,
derivationPath = token.derivationPath,
isCustom = isCustomToken(token.id, token.derivationPath, card.derivationStyle, blockchain),
isCustom = isCustomToken(tokenId),
)
}

View file

@ -1,59 +1,26 @@
package com.tangem.data.tokens.utils
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.DerivationStyle
import com.tangem.blockchain.common.IconsUtil
import com.tangem.domain.common.TapWorkarounds.derivationStyle
import com.tangem.domain.common.extensions.toCoinId
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.tokens.model.Token
import com.tangem.domain.tokens.model.Network
import com.tangem.blockchain.common.Token as SdkToken
import com.tangem.domain.tokens.model.Token as DomainToken
private const val DEFAULT_TOKENS_ICONS_HOST = "https://s3.eu-central-1.amazonaws.com/tangem.api/coins"
private const val TOKEN_ICON_SIZE = "large"
private const val TOKEN_ICON_EXT = "png"
internal fun isCustomToken(
tokenId: String?,
tokenDerivationPath: String?,
cardDerivationStyle: DerivationStyle?,
blockchain: Blockchain,
): Boolean {
if (tokenId == null) return true
private const val COIN_ID_PREFIX = "coin_"
private const val TOKEN_ID_PREFIX = "token_"
private const val CUSTOM_TOKEN_ID_PREFIX = "custom_token_"
private const val TOKEN_ID_DELIMITER = '#'
if (tokenDerivationPath == null || cardDerivationStyle == null) return false
return tokenDerivationPath != blockchain.derivationPath(cardDerivationStyle)?.rawPath
}
internal fun getTokenId(token: SdkToken?, blockchain: Blockchain): Token.ID {
val tokenId = token?.id
return when {
token == null -> getCoinId(blockchain)
tokenId == null -> getCustomTokenId(token.contractAddress, blockchain)
else -> Token.ID(tokenId)
}
}
internal fun getCoinId(blockchain: Blockchain): Token.ID {
val value = blockchain.toCoinId()
return Token.ID(value)
}
internal fun getCoinOrTokenIconUrl(token: SdkToken?, blockchain: Blockchain): String? {
val tokenId = token?.id
return when {
token == null -> getCoinIconId(blockchain)
tokenId == null -> IconsUtil.getTokenIconUri(blockchain, token)?.toString()
else -> getTokenIconUrlFromDefaultHost(tokenId)
}
}
internal fun getCoinIconId(blockchain: Blockchain): String {
return getTokenIconUrlFromDefaultHost(blockchain.toCoinId())
internal fun isCustomToken(tokenId: DomainToken.ID): Boolean {
return tokenId.value.startsWith(CUSTOM_TOKEN_ID_PREFIX)
}
internal fun getDerivationPath(blockchain: Blockchain, card: CardDTO): String? {
@ -64,12 +31,75 @@ internal fun getDerivationPath(blockchain: Blockchain, card: CardDTO): String? {
}
}
private fun getCustomTokenId(contractAddress: String, blockchain: Blockchain): Token.ID {
val value = "custom_${blockchain.id}_$contractAddress"
internal fun getBlockchain(networkId: Network.ID): Blockchain {
return Blockchain.fromId(networkId.value)
}
return Token.ID(value)
internal fun getNetworkId(blockchain: Blockchain): Network.ID {
val value = blockchain.id
return Network.ID(value)
}
internal fun getCoinId(blockchain: Blockchain): DomainToken.ID {
return getTokenOrCoinId(blockchain, token = null)
}
internal fun getTokenId(blockchain: Blockchain, token: SdkToken): DomainToken.ID {
return getTokenOrCoinId(blockchain, token)
}
internal fun getResponseTokenId(token: DomainToken): String? {
return token.id.value.substringAfter(TOKEN_ID_DELIMITER)
.takeUnless { token.isCustom }
}
internal fun getTokenIconUrl(blockchain: Blockchain, token: SdkToken): String? {
val tokenId = token.id
return if (tokenId == null) {
IconsUtil.getTokenIconUri(blockchain, token)?.toString()
} else {
getTokenIconUrlFromDefaultHost(tokenId)
}
}
internal fun getCoinIconUrl(blockchain: Blockchain): String? {
val coinId = when (blockchain) {
Blockchain.Unknown -> null
Blockchain.TerraV1, Blockchain.TerraV2 -> blockchain.toCoinId()
else -> blockchain.toNetworkId()
}
return coinId?.let(::getTokenIconUrlFromDefaultHost)
}
private fun getTokenOrCoinId(blockchain: Blockchain, token: SdkToken?): DomainToken.ID {
val sdkTokenId = token?.id
val (prefix, suffix) = when {
token == null -> COIN_ID_PREFIX to blockchain.toCoinId()
sdkTokenId == null -> CUSTOM_TOKEN_ID_PREFIX to token.contractAddress
else -> TOKEN_ID_PREFIX to sdkTokenId
}
val value = buildString {
append(prefix)
append(blockchain.id)
append(TOKEN_ID_DELIMITER)
append(suffix.lowercase())
}
return DomainToken.ID(value)
}
private fun getTokenIconUrlFromDefaultHost(tokenId: String): String {
return "$DEFAULT_TOKENS_ICONS_HOST/$TOKEN_ICON_SIZE/$tokenId.$TOKEN_ICON_EXT"
return buildString {
append(DEFAULT_TOKENS_ICONS_HOST)
append('/')
append(TOKEN_ICON_SIZE)
append('/')
append(tokenId)
append('.')
append(TOKEN_ICON_EXT)
}
}

View file

@ -1,6 +1,5 @@
package com.tangem.data.tokens.utils
import com.tangem.blockchain.common.Blockchain
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
import com.tangem.domain.common.extensions.toNetworkId
import com.tangem.domain.tokens.model.Token
@ -28,10 +27,10 @@ internal class UserTokensResponseFactory {
}
private fun createResponseToken(domainToken: Token): UserTokensResponse.Token {
val blockchain = Blockchain.fromId(domainToken.networkId.value)
val blockchain = getBlockchain(domainToken.networkId)
return UserTokensResponse.Token(
id = domainToken.id.value.takeUnless { domainToken.isCustom },
id = getResponseTokenId(domainToken),
networkId = blockchain.toNetworkId(),
derivationPath = domainToken.derivationPath,
name = domainToken.name,