Updated on 2026-08-14
This commit is contained in:
commit
ff282a1d7d
4 changed files with 171 additions and 144 deletions
|
|
@ -2,7 +2,6 @@ package com.tangem.tap.features.tokens.redux
|
||||||
|
|
||||||
import com.tangem.blockchain.common.Blockchain
|
import com.tangem.blockchain.common.Blockchain
|
||||||
import com.tangem.blockchain.common.DerivationParams
|
import com.tangem.blockchain.common.DerivationParams
|
||||||
import com.tangem.blockchain.common.DerivationStyle
|
|
||||||
import com.tangem.blockchain.common.Token
|
import com.tangem.blockchain.common.Token
|
||||||
import com.tangem.common.CompletionResult
|
import com.tangem.common.CompletionResult
|
||||||
import com.tangem.common.card.EllipticCurve
|
import com.tangem.common.card.EllipticCurve
|
||||||
|
|
@ -207,16 +206,10 @@ class TokensMiddleware {
|
||||||
is Currency.Blockchain -> {
|
is Currency.Blockchain -> {
|
||||||
val derivationPath = currency.derivationPath?.let { DerivationPath(it) }
|
val derivationPath = currency.derivationPath?.let { DerivationPath(it) }
|
||||||
|
|
||||||
val derivationParams = if (derivationStyle == null) {
|
val derivationParams = derivationStyle?.let {
|
||||||
null
|
when (derivationPath) {
|
||||||
} else {
|
null -> DerivationParams.Default(derivationStyle)
|
||||||
if (derivationPath == null) {
|
else -> DerivationParams.Custom(derivationPath)
|
||||||
DerivationParams.Default(derivationStyle)
|
|
||||||
} else {
|
|
||||||
when (derivationStyle) {
|
|
||||||
DerivationStyle.LEGACY -> DerivationParams.Custom(derivationPath)
|
|
||||||
DerivationStyle.NEW -> DerivationParams.Default(derivationStyle)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -236,8 +236,7 @@ class MultiWalletMiddleware {
|
||||||
token, blockchainNetwork.blockchain, blockchainNetwork.derivationPath
|
token, blockchainNetwork.blockchain, blockchainNetwork.derivationPath
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
// we can't add Solana token's - they are not supported now
|
if (tokens.isNotEmpty()) walletManager.addTokens(tokens)
|
||||||
if (walletManager !is SolanaWalletManager) walletManager.addTokens(tokens)
|
|
||||||
|
|
||||||
currenciesRepository.saveUpdatedCurrency(
|
currenciesRepository.saveUpdatedCurrency(
|
||||||
cardId = scanResponse.card.cardId,
|
cardId = scanResponse.card.cardId,
|
||||||
|
|
|
||||||
|
|
@ -56,9 +56,8 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
||||||
}
|
}
|
||||||
is OnDestroy -> cancelAll()
|
is OnDestroy -> cancelAll()
|
||||||
is OnTokenContractAddressChanged -> {
|
is OnTokenContractAddressChanged -> {
|
||||||
updateAddButton()
|
|
||||||
|
|
||||||
val address = action.contractAddress.value
|
val address = action.contractAddress.value
|
||||||
|
|
||||||
when (val error = ContractAddress.validateValue(address)) {
|
when (val error = ContractAddress.validateValue(address)) {
|
||||||
null -> {
|
null -> {
|
||||||
ContractAddress.removeError()
|
ContractAddress.removeError()
|
||||||
|
|
@ -66,7 +65,6 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
||||||
}
|
}
|
||||||
AddCustomTokenError.FieldIsEmpty -> {
|
AddCustomTokenError.FieldIsEmpty -> {
|
||||||
ContractAddress.removeError()
|
ContractAddress.removeError()
|
||||||
lockTokenFields()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
AddCustomTokenError.InvalidContractAddress -> {
|
AddCustomTokenError.InvalidContractAddress -> {
|
||||||
|
|
@ -78,42 +76,47 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!action.contractAddress.isUserInput) return
|
if (!action.contractAddress.isUserInput) return
|
||||||
|
|
||||||
manageFoundTokenChanges(requestInfoAboutToken(address))
|
manageFoundTokenChanges(requestInfoAboutToken(address))
|
||||||
}
|
}
|
||||||
|
is OnTokenNameChanged -> {
|
||||||
|
updateAddButton()
|
||||||
|
}
|
||||||
|
is OnTokenSymbolChanged -> {
|
||||||
|
updateAddButton()
|
||||||
|
}
|
||||||
|
is OnTokenDecimalsChanged -> {
|
||||||
|
updateAddButton()
|
||||||
|
}
|
||||||
is OnTokenNetworkChanged -> {
|
is OnTokenNetworkChanged -> {
|
||||||
if (!action.blockchainNetwork.isUserInput) return
|
if (!action.blockchainNetwork.isUserInput) return
|
||||||
|
|
||||||
updateAddButton()
|
|
||||||
// check the only ContractAddress without any side effects
|
|
||||||
val contractAddress = ContractAddress.getFieldValue<String>()
|
val contractAddress = ContractAddress.getFieldValue<String>()
|
||||||
val error = ContractAddress.validateValue(contractAddress)
|
val error = ContractAddress.validateValue(contractAddress)
|
||||||
if (contractAddress.isNotEmpty() && error == null) {
|
if (error == null && contractAddress.isNotEmpty()) {
|
||||||
|
// token branch
|
||||||
manageFoundTokenChanges(requestInfoAboutToken(contractAddress))
|
manageFoundTokenChanges(requestInfoAboutToken(contractAddress))
|
||||||
|
} else {
|
||||||
|
// blockchain branch
|
||||||
|
val isAlreadyAdded = isBlockchainPersistIntoAppSavedTokensList(
|
||||||
|
selectedNetwork = action.blockchainNetwork.value
|
||||||
|
)
|
||||||
|
updateWarningAlreadyAdded(isAlreadyAdded)
|
||||||
|
updateAddButton()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is OnTokenNameChanged -> {
|
|
||||||
Name.validateField(action.tokenName.value)
|
|
||||||
updateAddButton()
|
|
||||||
}
|
|
||||||
is OnTokenSymbolChanged -> {
|
|
||||||
Symbol.validateField(action.tokenSymbol.value)
|
|
||||||
updateAddButton()
|
|
||||||
}
|
|
||||||
is OnTokenDecimalsChanged -> {
|
|
||||||
Decimals.validateField(action.tokenDecimals.value)
|
|
||||||
updateAddButton()
|
|
||||||
}
|
|
||||||
is OnTokenDerivationPathChanged -> {
|
is OnTokenDerivationPathChanged -> {
|
||||||
DerivationPath.validateField(action.blockchainDerivationPath.value)
|
val isAlreadyAdded = if (ContractAddress.isFilled()) {
|
||||||
val alreadyAdded = isTokenPersistIntoAppSavedTokensList(
|
// token branch
|
||||||
selectedDerivationBlockchain = DerivationPath.getFieldValue()
|
isTokenPersistIntoAppSavedTokensList(
|
||||||
)
|
selectedDerivation = action.blockchainDerivationPath.value
|
||||||
if (alreadyAdded) {
|
)
|
||||||
dispatchOnMain(Warning.Add(setOf(AddCustomTokenWarning.TokenAlreadyAdded)))
|
|
||||||
} else {
|
} else {
|
||||||
dispatchOnMain(Warning.Remove(setOf(AddCustomTokenWarning.TokenAlreadyAdded)))
|
// blockchain branch
|
||||||
|
isBlockchainPersistIntoAppSavedTokensList(
|
||||||
|
selectedDerivation = action.blockchainDerivationPath.value
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
updateWarningAlreadyAdded(isAlreadyAdded)
|
||||||
updateAddButton()
|
updateAddButton()
|
||||||
}
|
}
|
||||||
is OnAddCustomTokenClicked -> {
|
is OnAddCustomTokenClicked -> {
|
||||||
|
|
@ -140,19 +143,11 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun updateAddButton() {
|
private suspend fun updateWarningAlreadyAdded(isInAppSavedList: Boolean) {
|
||||||
val state = hubState
|
if (isInAppSavedList) {
|
||||||
if (state.warnings.contains(AddCustomTokenWarning.TokenAlreadyAdded)) {
|
AddCustomTokenWarning.TokenAlreadyAdded.add()
|
||||||
lockAddButton()
|
} else {
|
||||||
return
|
AddCustomTokenWarning.TokenAlreadyAdded.remove()
|
||||||
}
|
|
||||||
when {
|
|
||||||
// token
|
|
||||||
state.tokensOneFieldsIsFilled() -> lockAddButton()
|
|
||||||
// token
|
|
||||||
state.tokensFieldsIsFilled() && state.networkIsSelected() -> unlockAddButton()
|
|
||||||
// blockchain
|
|
||||||
else -> if (state.networkIsSelected()) unlockAddButton() else lockAddButton()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -185,81 +180,76 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun manageFoundTokenChanges(foundTokens: List<Coins.CheckAddressResponse.Token>) {
|
private suspend fun manageFoundTokenChanges(foundTokens: List<Coins.CheckAddressResponse.Token>) {
|
||||||
val warningsAdd = mutableSetOf<AddCustomTokenWarning>()
|
if (foundTokens.isEmpty()) {
|
||||||
val warningsRemove = mutableSetOf<AddCustomTokenWarning>()
|
// token not found - it's completely custom
|
||||||
|
AddCustomTokenWarning.TokenAlreadyAdded.remove()
|
||||||
|
AddCustomTokenWarning.PotentialScamToken.add()
|
||||||
|
|
||||||
|
dispatchOnMain(SetFoundTokenId(null))
|
||||||
|
clearTokenFields()
|
||||||
|
unlockTokenFields()
|
||||||
|
updateAddButton()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// foundToken - contains all info about the token
|
||||||
|
val foundToken = foundTokens[0]
|
||||||
|
dispatchOnMain(SetFoundTokenId(foundToken.id))
|
||||||
when {
|
when {
|
||||||
foundTokens.isEmpty() -> {
|
foundToken.contracts.isEmpty() -> {
|
||||||
// token not found - it's completely custom
|
Timber.e("Unexpected state -> throw to FB")
|
||||||
dispatchOnMain(SetFoundTokenId(null))
|
|
||||||
warningsAdd.add(AddCustomTokenWarning.PotentialScamToken)
|
|
||||||
warningsRemove.add(AddCustomTokenWarning.TokenAlreadyAdded)
|
|
||||||
clearTokenFields()
|
|
||||||
unlockTokenFields()
|
|
||||||
}
|
}
|
||||||
else -> {
|
foundToken.contracts.size == 1 -> {
|
||||||
// foundToken - contains all info about the token
|
// token with single contract address
|
||||||
val foundToken = foundTokens[0]
|
val singleTokenContract = foundToken.contracts[0]
|
||||||
dispatchOnMain(SetFoundTokenId(foundToken.id))
|
fillTokenFields(foundToken, singleTokenContract)
|
||||||
|
|
||||||
when {
|
val isInAppSavedTokens = isTokenPersistIntoAppSavedTokensList()
|
||||||
foundToken.contracts.isEmpty() -> {
|
if (isInAppSavedTokens) {
|
||||||
Timber.e("Unexpected state -> throw to FB")
|
lockTokenFields()
|
||||||
}
|
lockAddButton()
|
||||||
foundToken.contracts.size == 1 -> {
|
AddCustomTokenWarning.PotentialScamToken.replace(AddCustomTokenWarning.TokenAlreadyAdded)
|
||||||
// token with single contract address
|
} else {
|
||||||
val singleTokenContract = foundToken.contracts[0]
|
// not in the saved tokens list
|
||||||
fillTokenFields(foundToken, singleTokenContract)
|
if (singleTokenContract.active) {
|
||||||
|
lockTokenFields()
|
||||||
val isInAppSavedTokens = isTokenPersistIntoAppSavedTokensList()
|
unlockAddButton()
|
||||||
if (isInAppSavedTokens) {
|
if (hubState.derivationPathIsSelected()) {
|
||||||
lockTokenFields()
|
AddCustomTokenWarning.PotentialScamToken.add()
|
||||||
warningsAdd.add(AddCustomTokenWarning.TokenAlreadyAdded)
|
|
||||||
warningsRemove.add(AddCustomTokenWarning.PotentialScamToken)
|
|
||||||
} else {
|
} else {
|
||||||
// not in the saved tokens list
|
AddCustomTokenWarning.TokenAlreadyAdded.remove()
|
||||||
if (singleTokenContract.active) {
|
AddCustomTokenWarning.PotentialScamToken.remove()
|
||||||
lockTokenFields()
|
|
||||||
if (hubState.derivationPathIsSelected()) {
|
|
||||||
warningsAdd.add(AddCustomTokenWarning.PotentialScamToken)
|
|
||||||
} else {
|
|
||||||
warningsRemove.add(AddCustomTokenWarning.TokenAlreadyAdded)
|
|
||||||
warningsRemove.add(AddCustomTokenWarning.PotentialScamToken)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warningsAdd.add(AddCustomTokenWarning.PotentialScamToken)
|
|
||||||
}
|
|
||||||
unlockAddButton()
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else -> {
|
unlockAddButton()
|
||||||
warningsRemove.add(AddCustomTokenWarning.TokenAlreadyAdded)
|
AddCustomTokenWarning.PotentialScamToken.add()
|
||||||
warningsRemove.add(AddCustomTokenWarning.PotentialScamToken)
|
|
||||||
|
|
||||||
val dialog = DomainDialog.SelectTokenDialog(
|
|
||||||
items = foundToken.contracts,
|
|
||||||
networkIdConverter = { networkId ->
|
|
||||||
val blockchain = Blockchain.fromNetworkId(networkId)
|
|
||||||
if (blockchain == null || blockchain == Blockchain.Unknown) {
|
|
||||||
throw DomainException.SelectTokeNetworkException(networkId)
|
|
||||||
}
|
|
||||||
hubState.blockchainToName(blockchain) ?: ""
|
|
||||||
},
|
|
||||||
onSelect = { selectedContract ->
|
|
||||||
hubScope.launch {
|
|
||||||
// find how to connect to the upper coroutineContext and dispatch through them
|
|
||||||
fillTokenFields(foundToken, selectedContract)
|
|
||||||
lockTokenFields()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
dispatchOnMain(DomainGlobalAction.ShowDialog(dialog))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else -> {
|
||||||
|
AddCustomTokenWarning.PotentialScamToken.replace(AddCustomTokenWarning.TokenAlreadyAdded)
|
||||||
|
|
||||||
replaceWarnings(warningsAdd, warningsRemove)
|
val dialog = DomainDialog.SelectTokenDialog(
|
||||||
|
items = foundToken.contracts,
|
||||||
|
networkIdConverter = { networkId ->
|
||||||
|
val blockchain = Blockchain.fromNetworkId(networkId)
|
||||||
|
if (blockchain == null || blockchain == Blockchain.Unknown) {
|
||||||
|
throw DomainException.SelectTokeNetworkException(networkId)
|
||||||
|
}
|
||||||
|
hubState.blockchainToName(blockchain) ?: ""
|
||||||
|
},
|
||||||
|
onSelect = { selectedContract ->
|
||||||
|
hubScope.launch {
|
||||||
|
// find how to connect to the upper coroutineContext and dispatch through them
|
||||||
|
fillTokenFields(foundToken, selectedContract)
|
||||||
|
lockTokenFields()
|
||||||
|
unlockAddButton()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
dispatchOnMain(DomainGlobalAction.ShowDialog(dialog))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun replaceWarnings(
|
private suspend fun replaceWarnings(
|
||||||
|
|
@ -271,16 +261,44 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private suspend fun validateUserTokenWithSavedTokensList(userToken: CustomCurrency.CustomToken) {
|
private suspend fun updateAddButton() {
|
||||||
// val isInAppSavedTokens = isTokenPersistIntoAppSavedTokensList(
|
val state = hubState
|
||||||
// userToken.token.id,
|
if (state.warnings.contains(AddCustomTokenWarning.TokenAlreadyAdded)) {
|
||||||
// userToken.token.contractAddress,
|
lockAddButton()
|
||||||
// userToken.network.toNetworkId(),
|
return
|
||||||
// )
|
}
|
||||||
// if (isInAppSavedTokens) {
|
when {
|
||||||
// replaceWarnings(mutableSetOf(AddCustomTokenWarning.TokenAlreadyAdded))
|
// token
|
||||||
// }
|
state.tokensOneFieldsIsFilled() -> {
|
||||||
// }
|
lockAddButton()
|
||||||
|
}
|
||||||
|
// token
|
||||||
|
state.tokensFieldsIsFilled() && state.networkIsSelected() -> {
|
||||||
|
unlockAddButton()
|
||||||
|
}
|
||||||
|
// blockchain
|
||||||
|
else -> {
|
||||||
|
if (state.networkIsSelected()) {
|
||||||
|
val alreadyAdded = isBlockchainPersistIntoAppSavedTokensList()
|
||||||
|
if (alreadyAdded) {
|
||||||
|
lockAddButton()
|
||||||
|
} else {
|
||||||
|
unlockAddButton()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lockAddButton()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun lockAddButton() {
|
||||||
|
dispatchOnMain(Screen.UpdateAddButton(ViewStates.AddButton(false)))
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun unlockAddButton() {
|
||||||
|
dispatchOnMain(Screen.UpdateAddButton(ViewStates.AddButton(true)))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These are helper functions.
|
* These are helper functions.
|
||||||
|
|
@ -289,11 +307,11 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
||||||
tokenId: String? = hubState.tokenId,
|
tokenId: String? = hubState.tokenId,
|
||||||
tokenContractAddress: String = ContractAddress.getFieldValue(),
|
tokenContractAddress: String = ContractAddress.getFieldValue(),
|
||||||
tokenNetworkId: String = Network.getFieldValue<Blockchain>().toNetworkId(),
|
tokenNetworkId: String = Network.getFieldValue<Blockchain>().toNetworkId(),
|
||||||
selectedDerivationBlockchain: Blockchain = DerivationPath.getFieldValue()
|
selectedDerivation: Blockchain = DerivationPath.getFieldValue()
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val savedCurrencies = hubState.appSavedCurrencies ?: return false
|
val savedCurrencies = hubState.appSavedCurrencies ?: return false
|
||||||
|
|
||||||
val derivationPath = getDerivationPathFromSelectedBlockchain(selectedDerivationBlockchain)
|
val derivationPath = getDerivationPathFromSelectedBlockchain(selectedDerivation)
|
||||||
savedCurrencies.forEach { wrappedCurrency ->
|
savedCurrencies.forEach { wrappedCurrency ->
|
||||||
when (wrappedCurrency) {
|
when (wrappedCurrency) {
|
||||||
is DomainWrapped.Currency.Blockchain -> {}
|
is DomainWrapped.Currency.Blockchain -> {}
|
||||||
|
|
@ -312,17 +330,17 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isBlockchainPersistIntoAppSavedTokensList(
|
private fun isBlockchainPersistIntoAppSavedTokensList(
|
||||||
selectedBlockchain: Blockchain,
|
selectedNetwork: Blockchain = Network.getFieldValue(),
|
||||||
selectedDerivationBlockchain: Blockchain,
|
selectedDerivation: Blockchain = DerivationPath.getFieldValue()
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val state = hubState
|
val state = hubState
|
||||||
val savedCurrencies = state.appSavedCurrencies ?: return false
|
val savedCurrencies = state.appSavedCurrencies ?: return false
|
||||||
|
|
||||||
val derivationPath = getDerivationPathFromSelectedBlockchain(selectedDerivationBlockchain)
|
val derivationPath = getDerivationPathFromSelectedBlockchain(selectedDerivation)
|
||||||
savedCurrencies.forEach { wrappedCurrency ->
|
savedCurrencies.forEach { wrappedCurrency ->
|
||||||
when (wrappedCurrency) {
|
when (wrappedCurrency) {
|
||||||
is DomainWrapped.Currency.Blockchain -> {
|
is DomainWrapped.Currency.Blockchain -> {
|
||||||
val isSameBlockchain = selectedBlockchain == wrappedCurrency.blockchain
|
val isSameBlockchain = selectedNetwork == wrappedCurrency.blockchain
|
||||||
val isSameDerivationPath = derivationPath?.rawPath == wrappedCurrency.derivationPath
|
val isSameDerivationPath = derivationPath?.rawPath == wrappedCurrency.derivationPath
|
||||||
if (isSameBlockchain && isSameDerivationPath) return true
|
if (isSameBlockchain && isSameDerivationPath) return true
|
||||||
}
|
}
|
||||||
|
|
@ -400,13 +418,22 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun CustomTokenFieldId.isFilled(): Boolean {
|
||||||
|
return when (this) {
|
||||||
|
ContractAddress -> getFieldValue<String>().isNotEmpty()
|
||||||
|
Network -> getFieldValue<Blockchain>() != Blockchain.Unknown
|
||||||
|
Name -> getFieldValue<String>().isNotEmpty()
|
||||||
|
Symbol -> getFieldValue<String>().isNotEmpty()
|
||||||
|
Decimals -> getFieldValue<String>().isNotEmpty()
|
||||||
|
DerivationPath -> getFieldValue<Blockchain>() != Blockchain.Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The field is being validated.
|
* The field is being validated.
|
||||||
* If there is an error, then it adds it to the field.
|
* If there is an error, then it adds it to the field.
|
||||||
* If not, then data is collected from other user token fields, a token is generated and checked
|
|
||||||
* for content in saved tokens and app tokens list
|
|
||||||
*/
|
*/
|
||||||
private suspend fun CustomTokenFieldId.validateField(value: Any): AddCustomTokenError? {
|
private suspend fun CustomTokenFieldId.validateAndUpdateError(value: Any): AddCustomTokenError? {
|
||||||
val error = this.validateValue(value)
|
val error = this.validateValue(value)
|
||||||
when (error) {
|
when (error) {
|
||||||
null -> this.removeError()
|
null -> this.removeError()
|
||||||
|
|
@ -456,14 +483,23 @@ internal class AddCustomTokenHub : BaseStoreHub<AddCustomTokenState>("AddCustomT
|
||||||
dispatchOnMain(action)
|
dispatchOnMain(action)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun lockAddButton() {
|
private suspend fun AddCustomTokenWarning.add() {
|
||||||
dispatchOnMain(Screen.UpdateAddButton(ViewStates.AddButton(false)))
|
dispatchOnMain(Warning.Add(setOf(this)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun unlockAddButton() {
|
private suspend fun AddCustomTokenWarning.remove() {
|
||||||
dispatchOnMain(Screen.UpdateAddButton(ViewStates.AddButton(true)))
|
dispatchOnMain(Warning.Remove(setOf(this)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun AddCustomTokenWarning.replace(to: AddCustomTokenWarning) {
|
||||||
|
dispatchOnMain(Warning.Replace(setOf(this), setOf(to)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// private suspend fun AddCustomTokenWarning.replace(replace: Boolean, to: AddCustomTokenWarning) {
|
||||||
|
// if (replace) dispatchOnMain(Warning.Replace(setOf(this), setOf(to)))
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
override fun reduceAction(action: Action, state: AddCustomTokenState): AddCustomTokenState {
|
override fun reduceAction(action: Action, state: AddCustomTokenState): AddCustomTokenState {
|
||||||
return when (action) {
|
return when (action) {
|
||||||
is Init.SetAddedCurrencies -> {
|
is Init.SetAddedCurrencies -> {
|
||||||
|
|
|
||||||
|
|
@ -63,11 +63,10 @@ data class AddCustomTokenState(
|
||||||
val idsToCheck = listOf(ContractAddress, Name, Symbol, Decimals)
|
val idsToCheck = listOf(ContractAddress, Name, Symbol, Decimals)
|
||||||
val fieldsToCheck = form.fieldList.filter { idsToCheck.contains(it.id) }
|
val fieldsToCheck = form.fieldList.filter { idsToCheck.contains(it.id) }
|
||||||
val validator = StringIsEmptyValidator()
|
val validator = StringIsEmptyValidator()
|
||||||
fieldsToCheck.forEach { field ->
|
val errorsList = fieldsToCheck.mapNotNull { field ->
|
||||||
val error = validator.validate(field.data.value?.toString())
|
validator.validate(field.data.value?.toString())
|
||||||
if (error != null) return false
|
|
||||||
}
|
}
|
||||||
return true
|
return errorsList.size == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fun networkIsSelected(): Boolean {
|
fun networkIsSelected(): Boolean {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue