Skip to content

Commit

Permalink
Allow to edit manually added tokens (#1059)
Browse files Browse the repository at this point in the history
  • Loading branch information
valentunn authored Aug 11, 2023
1 parent 4d15cfa commit 8dbeead
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 30 deletions.
5 changes: 4 additions & 1 deletion common/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="TypographyEllipsis">
<string name="asset_add_evm_token_already_exist_title">This token already exists</string>
<!-- <string name="asset_add_evm_token_already_exist_title">This token already exist</string>-->
<string name="asset_add_evm_token_already_exist_modifiable_message">The entered contract address is present in Nova as a %s token. Are you sure you want to modify it?</string>

<string name="account_parity_signer_sign_qr_code_expired_descrition">For security reasons generated operations valid for only %s.\nPlease generate new QR code and sign it with %s</string>
<string name="account_parity_signer_import_scan_invalid_qr">Invalid QR code, please make sure you are scanning QR code from %s</string>
<string name="account_parity_signer_sign_have_error">I have an error in %s</string>
Expand Down Expand Up @@ -356,7 +360,6 @@

<string name="manage_assets_add_token">Add token</string>

<string name="asset_add_evm_token_already_exist_title">This token already exist</string>
<string name="asset_add_evm_token_already_exist_message">The entered contract address is present in Nova as a %s token.</string>

<string name="asset_add_evm_token_invalid_contract_address_title">Invalid contract address</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import io.novafoundation.nova.common.address.format.EthereumAddressFormat
import io.novafoundation.nova.common.validation.ValidationSystem
import io.novafoundation.nova.feature_assets.domain.tokens.add.validations.AddEvmTokenValidationSystem
import io.novafoundation.nova.feature_assets.domain.tokens.add.validations.CoinGeckoLinkValidationFactory
import io.novafoundation.nova.feature_assets.domain.tokens.add.validations.evmAssetNotExist
import io.novafoundation.nova.feature_assets.domain.tokens.add.validations.evmAssetNotExists
import io.novafoundation.nova.feature_assets.domain.tokens.add.validations.validCoinGeckoLink
import io.novafoundation.nova.feature_assets.domain.tokens.add.validations.validErc20Contract
import io.novafoundation.nova.feature_assets.domain.tokens.add.validations.validTokenDecimals
Expand Down Expand Up @@ -94,7 +94,7 @@ class RealAddTokensInteractor(

override fun getValidationSystem(): AddEvmTokenValidationSystem {
return ValidationSystem {
evmAssetNotExist(chainAssetRepository)
evmAssetNotExists(chainRegistry)
validErc20Contract(ethereumAddressFormat, erc20Standard, chainRegistry)
validTokenDecimals()
validCoinGeckoLink(coinGeckoLinkValidationFactory)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import io.novafoundation.nova.common.address.format.EthereumAddressFormat
import io.novafoundation.nova.common.validation.ValidationSystem
import io.novafoundation.nova.common.validation.ValidationSystemBuilder
import io.novafoundation.nova.feature_assets.domain.tokens.add.CustomErc20Token
import io.novafoundation.nova.feature_wallet_api.domain.interfaces.ChainAssetRepository
import io.novafoundation.nova.feature_wallet_api.domain.validation.evmAssetNotExist
import io.novafoundation.nova.feature_wallet_api.domain.validation.evmAssetNotExists
import io.novafoundation.nova.feature_wallet_api.domain.validation.validErc20Contract
import io.novafoundation.nova.feature_wallet_api.domain.validation.validTokenDecimals
import io.novafoundation.nova.runtime.ethereum.contract.erc20.Erc20Standard
Expand All @@ -18,7 +17,7 @@ typealias AddEvmTokenValidationSystemBuilder = ValidationSystemBuilder<AddEvmTok
sealed interface AddEvmTokensValidationFailure {
class InvalidTokenContractAddress(val chainName: String) : AddEvmTokensValidationFailure

class AssetExist(val alreadyExistingSymbol: String) : AddEvmTokensValidationFailure
class AssetExist(val alreadyExistingSymbol: String, val canModify: Boolean) : AddEvmTokensValidationFailure

object InvalidDecimals : AddEvmTokensValidationFailure

Expand All @@ -38,8 +37,8 @@ fun AddEvmTokenValidationSystemBuilder.validErc20Contract(
error = { AddEvmTokensValidationFailure.InvalidTokenContractAddress(it.chain.name) }
)

fun AddEvmTokenValidationSystemBuilder.evmAssetNotExist(chainAssetRepository: ChainAssetRepository) = evmAssetNotExist(
assetRepository = chainAssetRepository,
fun AddEvmTokenValidationSystemBuilder.evmAssetNotExists(chainRegistry: ChainRegistry) = evmAssetNotExists(
chainRegistry = chainRegistry,
chain = { it.chain },
address = { it.customErc20Token.contract },
assetNotExistError = AddEvmTokensValidationFailure::AssetExist,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,14 @@ fun mapAddEvmTokensValidationFailureToUI(
): TitleAndMessage {
return when (failure) {
is AddEvmTokensValidationFailure.AssetExist -> {
resourceManager.getString(R.string.asset_add_evm_token_already_exist_title) to
val title = resourceManager.getString(R.string.asset_add_evm_token_already_exist_title)
val message = if (failure.canModify) {
resourceManager.getString(R.string.asset_add_evm_token_already_exist_modifiable_message, failure.alreadyExistingSymbol)
} else {
resourceManager.getString(R.string.asset_add_evm_token_already_exist_message, failure.alreadyExistingSymbol)
}

title to message
}
is AddEvmTokensValidationFailure.InvalidTokenContractAddress -> {
resourceManager.getString(R.string.asset_add_evm_token_invalid_contract_address_title) to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,5 @@ interface ChainAssetRepository {

suspend fun insertCustomAsset(chainAsset: Chain.Asset)

suspend fun getAssetSymbol(id: FullChainAssetId): String?

suspend fun getEnabledAssets(): List<Chain.Asset>
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,54 @@ import io.novafoundation.nova.common.validation.ValidationStatus
import io.novafoundation.nova.common.validation.ValidationSystemBuilder
import io.novafoundation.nova.common.validation.valid
import io.novafoundation.nova.common.validation.validationError
import io.novafoundation.nova.feature_wallet_api.domain.interfaces.ChainAssetRepository
import io.novafoundation.nova.common.validation.validationWarning
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
import io.novafoundation.nova.runtime.multiNetwork.assetOrNull
import io.novafoundation.nova.runtime.multiNetwork.chain.mappers.chainAssetIdOfErc20Token
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain.Asset.Source
import io.novafoundation.nova.runtime.multiNetwork.chain.model.FullChainAssetId

typealias AssetNotExistError<E> = (existingSymbol: String) -> E
typealias AssetNotExistError<E> = (existingSymbol: String, canModify: Boolean) -> E

class EvmAssetExistenceValidation<P, E>(
private val assetRepository: ChainAssetRepository,
private val chainRegistry: ChainRegistry,
private val chain: (P) -> Chain,
private val contractAddress: (P) -> String,
private val assetNotExistError: AssetNotExistError<E>,
private val assetAlreadyExists: AssetNotExistError<E>,
private val addressMappingError: (P) -> E,
) : Validation<P, E> {

override suspend fun validate(value: P): ValidationStatus<E> {
return try {
val assetId = chainAssetIdOfErc20Token(contractAddress(value))
val fullAssetId = FullChainAssetId(chain(value).id, assetId)
val alreadyExistingSymbol = assetRepository.getAssetSymbol(fullAssetId)
val alreadyExistingAsset = chainRegistry.assetOrNull(fullAssetId)

if (alreadyExistingSymbol != null) {
validationError(assetNotExistError(alreadyExistingSymbol))
} else {
valid()
when {
alreadyExistingAsset == null -> valid()
// we only allow to modify manually added tokens. Default tokens should remain unchanged
alreadyExistingAsset.source == Source.MANUAL -> assetAlreadyExists(alreadyExistingAsset.symbol, true).validationWarning()
else -> assetAlreadyExists(alreadyExistingAsset.symbol, false).validationError()
}
} catch (e: Exception) {
validationError(addressMappingError(value))
}
}
}

fun <P, E> ValidationSystemBuilder<P, E>.evmAssetNotExist(
assetRepository: ChainAssetRepository,
fun <P, E> ValidationSystemBuilder<P, E>.evmAssetNotExists(
chainRegistry: ChainRegistry,
chain: (P) -> Chain,
address: (P) -> String,
assetNotExistError: AssetNotExistError<E>,
addressMappingError: (P) -> E
) = validate(
EvmAssetExistenceValidation(
assetRepository = assetRepository,
chainRegistry = chainRegistry,
chain = chain,
contractAddress = address,
assetNotExistError = assetNotExistError,
assetAlreadyExists = assetNotExistError,
addressMappingError = addressMappingError
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,6 @@ class RealChainAssetRepository(
chainAssetDao.insertAsset(localAsset)
}

override suspend fun getAssetSymbol(id: FullChainAssetId): String? {
val existingAsset = chainAssetDao.getAsset(id.assetId, id.chainId)

return existingAsset?.symbol
}

override suspend fun getEnabledAssets(): List<Chain.Asset> {
return chainAssetDao.getEnabledAssets().map { mapChainAssetLocalToAsset(it, gson) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ suspend fun ChainRegistry.chainWithAssetOrNull(chainId: String, assetId: Int): C
return ChainWithAsset(chain, chainAsset)
}

suspend fun ChainRegistry.assetOrNull(fullChainAssetId: FullChainAssetId): Chain.Asset? {
val chain = getChainOrNull(fullChainAssetId.chainId) ?: return null

return chain.assetsById[fullChainAssetId.assetId]
}

suspend fun ChainRegistry.chainWithAsset(chainId: String, assetId: Int): ChainWithAsset {
val chain = chainsById.first().getValue(chainId)

Expand Down

0 comments on commit 8dbeead

Please sign in to comment.