diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/App.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/App.kt index 5eeab7171ad..5d9590896ca 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/App.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/App.kt @@ -55,6 +55,7 @@ import io.horizontalsystems.bankwallet.core.managers.RestoreSettingsManager import io.horizontalsystems.bankwallet.core.managers.SolanaKitManager import io.horizontalsystems.bankwallet.core.managers.SolanaRpcSourceManager import io.horizontalsystems.bankwallet.core.managers.SolanaWalletManager +import io.horizontalsystems.bankwallet.core.managers.SpamManager import io.horizontalsystems.bankwallet.core.managers.SubscriptionManager import io.horizontalsystems.bankwallet.core.managers.SystemInfoManager import io.horizontalsystems.bankwallet.core.managers.TermsManager @@ -191,6 +192,7 @@ class App : CoreApp(), WorkConfiguration.Provider, ImageLoaderFactory { lateinit var cexAssetManager: CexAssetManager lateinit var chartIndicatorManager: ChartIndicatorManager lateinit var backupProvider: BackupProvider + lateinit var spamManager: SpamManager } override fun onCreate() { @@ -438,6 +440,8 @@ class App : CoreApp(), WorkConfiguration.Provider, ImageLoaderFactory { contactsRepository = contactsRepository ) + spamManager = SpamManager(marketKit) + startTasks() } diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/Eip20Adapter.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/Eip20Adapter.kt index cdd8429b907..c6fd5527096 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/Eip20Adapter.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/Eip20Adapter.kt @@ -31,7 +31,7 @@ class Eip20Adapter( evmLabelManager: EvmLabelManager ) : BaseEvmAdapter(evmKitWrapper, wallet.decimal, coinManager) { - private val transactionConverter = EvmTransactionConverter(coinManager, evmKitWrapper, wallet.transactionSource, baseToken, evmLabelManager) + private val transactionConverter = EvmTransactionConverter(coinManager, evmKitWrapper, wallet.transactionSource, App.spamManager, baseToken, evmLabelManager) private val contractAddress: Address = Address(contractAddress) val eip20Kit: Erc20Kit = Erc20Kit.getInstance(context, this.evmKit, this.contractAddress) diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/EvmTransactionConverter.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/EvmTransactionConverter.kt index 7177ca94c27..82d7d84bd66 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/EvmTransactionConverter.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/EvmTransactionConverter.kt @@ -3,6 +3,7 @@ package io.horizontalsystems.bankwallet.core.adapters import io.horizontalsystems.bankwallet.core.ICoinManager import io.horizontalsystems.bankwallet.core.managers.EvmKitWrapper import io.horizontalsystems.bankwallet.core.managers.EvmLabelManager +import io.horizontalsystems.bankwallet.core.managers.SpamManager import io.horizontalsystems.bankwallet.core.tokenIconPlaceholder import io.horizontalsystems.bankwallet.entities.TransactionValue import io.horizontalsystems.bankwallet.entities.nft.NftUid @@ -49,6 +50,7 @@ class EvmTransactionConverter( private val coinManager: ICoinManager, private val evmKitWrapper: EvmKitWrapper, private val source: TransactionSource, + private val spamManager: SpamManager, private val baseToken: Token, private val evmLabelManager: EvmLabelManager ) { @@ -184,7 +186,7 @@ class EvmTransactionConverter( } transaction.from != address && transaction.to != address -> { ExternalContractCallTransactionRecord( - transaction, baseToken, source, + transaction, baseToken, source, spamManager, getInternalEvents(internalTransactions) + getIncomingEip20Events(incomingEip20Transfers) + getIncomingEip721Events(incomingEip721Transfers) + diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/EvmTransactionsAdapter.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/EvmTransactionsAdapter.kt index 61f2da42d52..d28b26185b9 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/EvmTransactionsAdapter.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/EvmTransactionsAdapter.kt @@ -1,6 +1,7 @@ package io.horizontalsystems.bankwallet.core.adapters import io.horizontalsystems.bankwallet.core.AdapterState +import io.horizontalsystems.bankwallet.core.App import io.horizontalsystems.bankwallet.core.ICoinManager import io.horizontalsystems.bankwallet.core.ITransactionsAdapter import io.horizontalsystems.bankwallet.core.managers.EvmKitWrapper @@ -27,7 +28,7 @@ class EvmTransactionsAdapter( ) : ITransactionsAdapter { private val evmKit = evmKitWrapper.evmKit - private val transactionConverter = EvmTransactionConverter(coinManager, evmKitWrapper, source, baseToken, evmLabelManager) + private val transactionConverter = EvmTransactionConverter(coinManager, evmKitWrapper, source, App.spamManager, baseToken, evmLabelManager) override val explorerTitle: String get() = evmTransactionSource.name diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/TronTransactionConverter.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/TronTransactionConverter.kt index 1dfa0a66a0c..bb4200a089c 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/TronTransactionConverter.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/TronTransactionConverter.kt @@ -1,5 +1,6 @@ package io.horizontalsystems.bankwallet.core.adapters +import io.horizontalsystems.bankwallet.core.App import io.horizontalsystems.bankwallet.core.ICoinManager import io.horizontalsystems.bankwallet.core.managers.EvmLabelManager import io.horizontalsystems.bankwallet.core.managers.TronKitWrapper @@ -121,7 +122,7 @@ class TronTransactionConverter( decoration.fromAddress != address && decoration.toAddress != address -> { TronExternalContractCallTransactionRecord( - transaction, baseToken, source, + transaction, baseToken, source, App.spamManager, getInternalEvents(internalTransactions) + getIncomingEip20Events(incomingEip20Transfers), getOutgoingEip20Events(outgoingEip20Transfers) diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/SpamManager.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/SpamManager.kt new file mode 100644 index 00000000000..18e05756b9f --- /dev/null +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/SpamManager.kt @@ -0,0 +1,48 @@ +package io.horizontalsystems.bankwallet.core.managers + +import io.horizontalsystems.bankwallet.entities.TransactionValue +import io.horizontalsystems.bankwallet.entities.transactionrecords.evm.TransferEvent +import java.math.BigDecimal + +class SpamManager( + private val marketKitWrapper: MarketKitWrapper +) { + private val negligibleValue = BigDecimal("0.01") + private var cachedUsdPrices = mutableMapOf() + + fun isSpam( + incomingEvents: List, + outgoingEvents: List + ): Boolean { + val allEvents = incomingEvents + outgoingEvents + return allEvents.all { spamEvent(it) } + } + + private fun spamEvent(event: TransferEvent): Boolean { + return when (val eventValue = event.value) { + is TransactionValue.CoinValue -> { + spamValue(eventValue.coinUid, eventValue.value) + } + + is TransactionValue.NftValue -> { + spamValue(eventValue.coinUid, eventValue.value) + } + + else -> true + } + } + + private fun spamValue(coinUid: String, value: BigDecimal): Boolean { + return cachedUsdPrice(coinUid)?.let { usdPrice -> + usdPrice * value < negligibleValue + } ?: run { + value <= BigDecimal.ZERO + } + } + + private fun cachedUsdPrice(coinUid: String): BigDecimal? { + return cachedUsdPrices.getOrPut(coinUid) { + marketKitWrapper.coinPrice(coinUid, "USD")?.value + } + } +} diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/entities/transactionrecords/evm/ExternalContractCallTransactionRecord.kt b/app/src/main/java/io/horizontalsystems/bankwallet/entities/transactionrecords/evm/ExternalContractCallTransactionRecord.kt index fcb710d147a..1b01bc0a6a7 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/entities/transactionrecords/evm/ExternalContractCallTransactionRecord.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/entities/transactionrecords/evm/ExternalContractCallTransactionRecord.kt @@ -1,15 +1,16 @@ package io.horizontalsystems.bankwallet.entities.transactionrecords.evm +import io.horizontalsystems.bankwallet.core.managers.SpamManager import io.horizontalsystems.bankwallet.entities.TransactionValue import io.horizontalsystems.bankwallet.modules.transactions.TransactionSource import io.horizontalsystems.ethereumkit.models.Transaction import io.horizontalsystems.marketkit.models.Token -import java.math.BigDecimal class ExternalContractCallTransactionRecord( transaction: Transaction, baseToken: Token, source: TransactionSource, + spamManager: SpamManager, val incomingEvents: List, val outgoingEvents: List ) : EvmTransactionRecord( @@ -17,7 +18,7 @@ class ExternalContractCallTransactionRecord( baseToken = baseToken, source = source, foreignTransaction = true, - spam = isSpam(incomingEvents, outgoingEvents) + spam = spamManager.isSpam(incomingEvents, outgoingEvents) ) { override val mainValue: TransactionValue? @@ -30,22 +31,4 @@ class ExternalContractCallTransactionRecord( else -> null } } - - companion object { - fun isSpam( - incomingEvents: List, - outgoingEvents: List - ): Boolean { - for (event in (incomingEvents + outgoingEvents)) { - val value = event.value - if ( - value is TransactionValue.CoinValue && value.value > BigDecimal.ZERO || - value is TransactionValue.NftValue && value.value > BigDecimal.ZERO - ) { - return false - } - } - return true - } - } } diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/entities/transactionrecords/tron/TronExternalContractCallTransactionRecord.kt b/app/src/main/java/io/horizontalsystems/bankwallet/entities/transactionrecords/tron/TronExternalContractCallTransactionRecord.kt index 8d69c200ed4..c28a55c9f28 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/entities/transactionrecords/tron/TronExternalContractCallTransactionRecord.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/entities/transactionrecords/tron/TronExternalContractCallTransactionRecord.kt @@ -1,8 +1,8 @@ package io.horizontalsystems.bankwallet.entities.transactionrecords.tron +import io.horizontalsystems.bankwallet.core.managers.SpamManager import io.horizontalsystems.bankwallet.entities.TransactionValue import io.horizontalsystems.bankwallet.entities.transactionrecords.evm.EvmTransactionRecord -import io.horizontalsystems.bankwallet.entities.transactionrecords.evm.ExternalContractCallTransactionRecord import io.horizontalsystems.bankwallet.entities.transactionrecords.evm.TransferEvent import io.horizontalsystems.bankwallet.modules.transactions.TransactionSource import io.horizontalsystems.marketkit.models.Token @@ -12,6 +12,7 @@ class TronExternalContractCallTransactionRecord( transaction: Transaction, baseToken: Token, source: TransactionSource, + spamManager: SpamManager, val incomingEvents: List, val outgoingEvents: List ) : TronTransactionRecord( @@ -19,7 +20,7 @@ class TronExternalContractCallTransactionRecord( baseToken = baseToken, source = source, foreignTransaction = true, - spam = ExternalContractCallTransactionRecord.isSpam(incomingEvents, outgoingEvents) + spam = spamManager.isSpam(incomingEvents, outgoingEvents) ) { override val mainValue: TransactionValue?