Updated on 2026-08-14
This commit is contained in:
parent
1a12b1bdf9
commit
2f7ed460ff
19 changed files with 160 additions and 252 deletions
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.domain
|
||||
|
||||
import com.tangem.common.extensions.VoidCallback
|
||||
import com.tangem.network.api.tangemTech.Coins
|
||||
import com.tangem.network.api.tangemTech.CoinsResponse
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -11,9 +11,9 @@ sealed interface DomainDialog {
|
|||
data class DialogError(val error: DomainError) : DomainDialog
|
||||
|
||||
data class SelectTokenDialog(
|
||||
val items: List<Coins.CheckAddressResponse.Token.Contract>,
|
||||
val items: List<CoinsResponse.Coin.Network>,
|
||||
val networkIdConverter: (String) -> String,
|
||||
val onSelect: (Coins.CheckAddressResponse.Token.Contract) -> Unit,
|
||||
val onSelect: (CoinsResponse.Coin.Network) -> Unit,
|
||||
val onClose: VoidCallback = {}
|
||||
) : DomainDialog
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.domain.features.addCustomToken
|
||||
|
||||
import com.tangem.common.services.Result
|
||||
import com.tangem.network.api.tangemTech.Coins
|
||||
import com.tangem.network.api.tangemTech.CoinsResponse
|
||||
import com.tangem.network.api.tangemTech.TangemTechService
|
||||
|
||||
/**
|
||||
|
|
@ -11,41 +11,31 @@ class AddCustomTokenService(
|
|||
private val tangemTechService: TangemTechService
|
||||
) {
|
||||
|
||||
suspend fun checkAddress(
|
||||
suspend fun findToken(
|
||||
contractAddress: String,
|
||||
networkId: String? = null
|
||||
): Result<List<Coins.CheckAddressResponse.Token>> {
|
||||
val result = tangemTechService.coins.checkAddress(contractAddress, networkId)
|
||||
networkId: String? = null,
|
||||
active: Boolean? = null,
|
||||
): Result<List<CoinsResponse.Coin>> {
|
||||
val result = tangemTechService.coins(contractAddress, networkId, active)
|
||||
return when (result) {
|
||||
is Result.Success -> {
|
||||
val resultTokens = result.data.tokens
|
||||
var tokensList = mutableListOf<Coins.CheckAddressResponse.Token>()
|
||||
resultTokens.forEach { token ->
|
||||
val contractsWithTheSameAddress = token.contracts
|
||||
var coinsList = mutableListOf<CoinsResponse.Coin>()
|
||||
result.data.coins.forEach { coin ->
|
||||
val networksWithTheSameAddress = coin.networks
|
||||
.filter { it.address != null || it.decimalCount != null }
|
||||
.filter { it.address == contractAddress }
|
||||
.filter { it.decimalCount != null }
|
||||
if (contractsWithTheSameAddress.isNotEmpty()) {
|
||||
val newToken = token.copy(contracts = contractsWithTheSameAddress)
|
||||
tokensList.add(newToken)
|
||||
if (networksWithTheSameAddress.isNotEmpty()) {
|
||||
val newToken = coin.copy(networks = networksWithTheSameAddress)
|
||||
coinsList.add(newToken)
|
||||
}
|
||||
}
|
||||
if (tokensList.size > 1) {
|
||||
if (coinsList.size > 1) {
|
||||
// https://tangem.slack.com/archives/GMXC6PP71/p1649672562078679
|
||||
tokensList = mutableListOf(tokensList[0])
|
||||
coinsList = mutableListOf(coinsList[0])
|
||||
}
|
||||
Result.Success(tokensList)
|
||||
Result.Success(coinsList)
|
||||
}
|
||||
is Result.Failure -> result
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun tokens(): List<Coins.TokensResponse.Token> {
|
||||
return when (val result = tangemTechService.coins.tokens()) {
|
||||
is Result.Success -> {
|
||||
val tokens = result.data.tokens
|
||||
tokens.filter { it.contracts.isNullOrEmpty() }
|
||||
}
|
||||
is Result.Failure -> emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ import com.tangem.domain.redux.DomainState
|
|||
import com.tangem.domain.redux.dispatchOnMain
|
||||
import com.tangem.domain.redux.domainStore
|
||||
import com.tangem.domain.redux.global.DomainGlobalAction
|
||||
import com.tangem.network.api.tangemTech.Coins
|
||||
import com.tangem.network.api.tangemTech.CoinsResponse
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -153,7 +153,7 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
|||
}
|
||||
|
||||
/**
|
||||
* This feature is only needed until Solana tokens are added.
|
||||
* 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.
|
||||
*/
|
||||
|
|
@ -197,7 +197,7 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
|||
|
||||
private suspend fun requestInfoAboutToken(
|
||||
contractAddress: String,
|
||||
): List<Coins.CheckAddressResponse.Token> {
|
||||
): List<CoinsResponse.Coin> {
|
||||
val tangemTechServiceManager = requireNotNull(hubState.tangemTechServiceManager)
|
||||
dispatchOnMain(Screen.UpdateTokenFields(listOf(ContractAddress to ViewStates.TokenField(isLoading = true))))
|
||||
|
||||
|
|
@ -210,7 +210,7 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
|||
// got the result faster than 500ms and the delay would only be the difference between them.
|
||||
delay(500)
|
||||
|
||||
val foundTokensResult = tangemTechServiceManager.checkAddress(contractAddress, selectedNetworkId)
|
||||
val foundTokensResult = tangemTechServiceManager.findToken(contractAddress, selectedNetworkId)
|
||||
val result = when (foundTokensResult) {
|
||||
is Result.Success -> foundTokensResult.data
|
||||
is Result.Failure -> {
|
||||
|
|
@ -223,7 +223,7 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
|||
return result
|
||||
}
|
||||
|
||||
private suspend fun manageFoundTokenChanges(foundTokens: List<Coins.CheckAddressResponse.Token>) {
|
||||
private suspend fun manageFoundTokenChanges(foundTokens: List<CoinsResponse.Coin>) {
|
||||
if (foundTokens.isEmpty()) {
|
||||
// token not found - it's completely custom
|
||||
TokenAlreadyAdded.remove()
|
||||
|
|
@ -240,12 +240,12 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
|||
val foundToken = foundTokens[0]
|
||||
dispatchOnMain(SetFoundTokenId(foundToken.id))
|
||||
when {
|
||||
foundToken.contracts.isEmpty() -> {
|
||||
foundToken.networks.isEmpty() -> {
|
||||
Timber.e("Unexpected state -> throw to FB")
|
||||
}
|
||||
foundToken.contracts.size == 1 -> {
|
||||
foundToken.networks.size == 1 -> {
|
||||
// token with single contract address
|
||||
val singleTokenContract = foundToken.contracts[0]
|
||||
val singleTokenContract = foundToken.networks[0]
|
||||
fillTokenFields(foundToken, singleTokenContract)
|
||||
|
||||
val isInAppSavedTokens = isTokenPersistIntoAppSavedTokensList()
|
||||
|
|
@ -254,8 +254,8 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
|||
lockAddButton()
|
||||
PotentialScamToken.replace(TokenAlreadyAdded)
|
||||
} else {
|
||||
// not in the saved tokens list
|
||||
if (singleTokenContract.active) {
|
||||
// not in the saved coins list
|
||||
if (foundToken.active) {
|
||||
lockTokenFields()
|
||||
unlockAddButton()
|
||||
if (hubState.derivationPathIsSelected()) {
|
||||
|
|
@ -274,7 +274,7 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
|||
PotentialScamToken.replace(TokenAlreadyAdded)
|
||||
|
||||
val dialog = DomainDialog.SelectTokenDialog(
|
||||
items = foundToken.contracts,
|
||||
items = foundToken.networks,
|
||||
networkIdConverter = { networkId ->
|
||||
val blockchain = Blockchain.fromNetworkId(networkId)
|
||||
if (blockchain == null || blockchain == Blockchain.Unknown) {
|
||||
|
|
@ -490,14 +490,14 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
|||
}
|
||||
|
||||
private suspend fun fillTokenFields(
|
||||
token: Coins.CheckAddressResponse.Token,
|
||||
contract: Coins.CheckAddressResponse.Token.Contract,
|
||||
token: CoinsResponse.Coin,
|
||||
coinNetwork: CoinsResponse.Coin.Network,
|
||||
) {
|
||||
val blockchain = Blockchain.fromNetworkId(contract.networkId) ?: Blockchain.Unknown
|
||||
val blockchain = Blockchain.fromNetworkId(coinNetwork.networkId) ?: Blockchain.Unknown
|
||||
Network.setFieldValue(Field.Data(blockchain, false))
|
||||
Name.setFieldValue(Field.Data(token.name, false))
|
||||
Symbol.setFieldValue(Field.Data(token.symbol, false))
|
||||
Decimals.setFieldValue(Field.Data(contract.decimalCount.toString(), false))
|
||||
Decimals.setFieldValue(Field.Data(coinNetwork.decimalCount.toString(), false))
|
||||
dispatchOnMain(UpdateForm(hubState))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ data class AddCustomTokenState(
|
|||
Blockchain.Polygon,
|
||||
Blockchain.Avalanche,
|
||||
Blockchain.Fantom,
|
||||
Blockchain.Solana, // should be unsupported for tokens until they are added to the Blockchain SDK
|
||||
Blockchain.Solana, // should be unsupported for coins until they are added to the Blockchain SDK
|
||||
)
|
||||
if (type == CustomTokenType.Token) networks.remove(Blockchain.Solana)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue