Spam Filtering

Spam collections are a significant problem plaguing NFT collectors and builders alike. Identifying spam (and, often filtering it out) is an important step developers can take to keep users safe from scams while also providing the best possible user experience. That said, it is increasingly difficult to accurately and comprehensively identify spam, especially given how many NFT collections there are and how sophisticated some of the tactics employed by bad actors and spammy collections are today.

Our team has developed proprietary spam detection capabilities powered by machine learning that detect even the sneakiest of spam collections and spam NFTs. We’ve brought our spam detection capabilities to Ethereum and Polygon chains to help you create safer, even more delightful user experiences by flagging, or even filtering out completely, NFTs from spam collections.

At the time of writing our models detected the following number of spam NFTs and collections, across all wallets:

ChainSpam collectionsSpam NFTs
Ethereum13,2628,843,369
Polygon85,16958,839,626

We are constantly monitoring other chains for potential spam issues to be added to our platform.

How Mnemonic approaches spam detection

Mnemonic stands out as the sole data platform that brings a wallet-centric spam filtering solution to the table.

What's the deal with a wallet-centric solution? It's all about personalization at the wallet level, emphasizing relevance to individual wallet behavior history. Think of it like email spam filtering; it's based on each user's interactions with various online entities. In our context, our wallet-centric spam filtering corresponds to a wallet's transactions and interactions with various blockchain elements, including smart contracts and other wallets.

Let's paint a clearer picture with an example: suppose a wallet receives an airdrop from an address that's also sending out thousands of airdrops to other wallets.

The straightforward approach might be to flag this as spam. However, that's too simplistic and risks misclassifying situations like reward payouts, quest completions, in-game events, and more.

A more nuanced approach is to delve into the history of the wallet's on-chain interactions with other entities and pinpoint those with a high degree of similarity (for instance, a series of comparable in-game activities, or participation in various reward programs).

This unique approach sets Mnemonic apart as a top choice for wallets and marketplaces aiming to deliver personalized, safe, wallet-centric user experiences. It's all about context, accuracy, and understanding the intricacies of on-chain behavior.

Removing spam NFTs from a wallet

If you are creating a wallet experience, you may want to allow your users to see all of their NFTs, but you may also want to flag any spam NFTs or exclude them entirely. We have made this easy to do with our get NFTs Owned endpoint. This endpoint returns a list of all the NFTs in a wallet, and it also labels NFTs from spam collections.

The response includes a field indicating whether each token returned is spam. You can use this information to flag spam in your end user experience.

In order to make this even easier, we included spam filtering capability into this endpoint. Simply provide SPAM_FILTER_EXCLUDE in the request to remove spam all at once.

curl --request GET \
     --url 'https://ethereum-rest.api.mnemonichq.com/wallets/v1beta2/yasik.eth/nfts?spam=SPAM_FILTER_EXCLUDE' \
     --header 'X-API-Key: <YOUR API KEY>' \
     --header 'accept: application/json'

The result will look something like this:

{
  "nfts": [
    {
      "nft": {
        "contractAddress": "0x259cf26dd6172728c6f8e0e6ae5b16e1b9d65df6",
        "tokenId": "360",
        "type": "TYPE_ERC721",
        "metadata": {
          "metadataUri": {
            "uri": "ipfs://QmV2Dy4Mbh1VT7Z1w11VDheQLhyx8oqkgh7LmpwDNGJRPK/2276.json",
            "mimeType": "application/json"
          },
          "name": "",
          "description": "",
          "image": {
            "uri": "https://ethereum.cdn.mnemonichq.com/0x259cf26dd6172728c6f8e0e6ae5b16e1b9d65df6/360/fdc78293e161f512851d7e0009b7e146b9294a284184517d0f89248bf74e5a00.png",
            "uriOriginal": "ipfs://QmSSMXfQ7REEf2Ju18XyZtbWb5EwdTakujv9Wc8oZ1Sj4X/2276.png",
            "mimeType": "image/png"
          }
        },
        "mintEvent": {
          "txHash": "0x3ff84beaea1e87701ab3dbad6aa52a02802eafeb74bbeeafffae75f470d14445",
          "logIndex": "23",
          "blockTimestamp": "2021-12-10T22:00:56Z"
        },
        "collection": {
          "name": "Medusa Collection"
        }
      },
      "quantity": "1",
      "spam": false
    },
    {
      "nft": {
        "contractAddress": "0x259cf26dd6172728c6f8e0e6ae5b16e1b9d65df6",
        "tokenId": "363",
        "type": "TYPE_ERC721",
        "metadata": {
          "metadataUri": {
            "uri": "ipfs://QmV2Dy4Mbh1VT7Z1w11VDheQLhyx8oqkgh7LmpwDNGJRPK/2279.json",
            "mimeType": "application/json"
          },
          "name": "",
          "description": "",
          "image": {
            "uri": "https://ethereum.cdn.mnemonichq.com/0x259cf26dd6172728c6f8e0e6ae5b16e1b9d65df6/363/f5451f69035e8281e94be068ff8ab4695fee143f8f7bc9cde2c775853e882214.png",
            "uriOriginal": "ipfs://QmSSMXfQ7REEf2Ju18XyZtbWb5EwdTakujv9Wc8oZ1Sj4X/2279.png",
            "mimeType": "image/png"
          }
        },
        "mintEvent": {
          "txHash": "0xbc8e2125f297e283a153a7e2e4fc55a39b80597099e48d5673ee52acb5587f06",
          "logIndex": "2",
          "blockTimestamp": "2021-12-11T01:44:45Z"
        },
        "collection": {
          "name": "Medusa Collection"
        }
      },
      "quantity": "1",
      "spam": false
    },
    {
      "nft": {
        "contractAddress": "0x259cf26dd6172728c6f8e0e6ae5b16e1b9d65df6",
        "tokenId": "375",
        "type": "TYPE_ERC721",
        "metadata": {
          "metadataUri": {
            "uri": "ipfs://QmV2Dy4Mbh1VT7Z1w11VDheQLhyx8oqkgh7LmpwDNGJRPK/2291.json",
            "mimeType": "application/json"
          },
          "name": "",
          "description": "",
          "image": {
            "uri": "https://ethereum.cdn.mnemonichq.com/0x259cf26dd6172728c6f8e0e6ae5b16e1b9d65df6/375/44d8f6e0fdda7ab94edfa38d7bd8c02329822d3c039782ed50bfcc87dbfc7b51.png",
            "uriOriginal": "ipfs://QmSSMXfQ7REEf2Ju18XyZtbWb5EwdTakujv9Wc8oZ1Sj4X/2291.png",
            "mimeType": "image/png"
          }
        },
        "mintEvent": {
          "txHash": "0x6c9f4b0b73ad0c9c437f27c044aebba85179fee0c59e424654e00ac79e533693",
          "logIndex": "220",
          "blockTimestamp": "2021-12-11T17:36:41Z"
        },
        "collection": {
          "name": "Medusa Collection"
        }
      },
      "quantity": "1",
      "spam": false
    },
    {
      "nft": {
        "contractAddress": "0x31ceae7a1beedcd15f5af6882f36018cf634969c",
        "tokenId": "849",
        "type": "TYPE_ERC721",
        "metadata": {
          "metadataUri": {
            "uri": "https://api.deusxnft.com/metadata/nfts/849-Valks",
            "mimeType": "application/json"
          },
          "name": "DeusX #849 (Valks)",
          "description": "",
          "image": {
            "uri": "https://ethereum.cdn.mnemonichq.com/0x31ceae7a1beedcd15f5af6882f36018cf634969c/849/4a7785f4121f345b68029bb0d581ebe64d8fd0ee784d5c93f71407f49145784d.png",
            "uriOriginal": "https://api.deusxnft.com/images/nfts/849-Valks.png",
            "mimeType": "image/png"
          }
        },
        "mintEvent": {
          "txHash": "0xf5ff6a0f6cf96ebbe699de41db08b59c96ed4f7c5d41f6820052c3130b7e2a15",
          "logIndex": "318",
          "blockTimestamp": "2021-10-15T15:03:32Z"
        },
        "collection": {
          "name": "DeusX"
        }
      },
      "quantity": "1",
      "spam": false
    },
    {
      "nft": {
        "contractAddress": "0x3e6046b4d127179f0a421f3148b43cf52c08fc41",
        "tokenId": "8526",
        "type": "TYPE_ERC721",
        "metadata": {
          "metadataUri": {
            "uri": "ipfs://QmVViezSMbqenwbPbgYp9uAa3GhrFkKdJiCjQeKapY7iHd/8526",
            "mimeType": "application/json"
          },
          "name": "You #8526",
          "description": "BFF's inaugural collection \"You\" celebrates the uniqueness of women and non-binary friends across our community and the world. Every NFT has unique perks built in, plus utility within the BFF universe.",
          "image": {
            "uri": "https://ethereum.cdn.mnemonichq.com/0x3e6046b4d127179f0a421f3148b43cf52c08fc41/8526/e912989bd1d57c778c6814a24513c9d73deae0f3a097bd03bda0e09a94a8b3dd.png",
            "uriOriginal": "ipfs://QmZkkoNaKp6PMv6wwy5YqsHvk3EkigUMvhgrmo3SaohZbP/8526.png",
            "mimeType": "image/png"
          }
        },
        "mintEvent": {
          "txHash": "0xedca2ff6f7dfda3b7ddeeeab21e53a3c769126ad614c6ff17a750c8e984d52e8",
          "logIndex": "356",
          "blockTimestamp": "2022-04-25T00:11:30Z"
        },
        "collection": {
          "name": "You"
        }
      },
      "quantity": "1",
      "spam": false
    }
  ]
}

Finding spam NFTs in a wallet

Similarly, we have made it easy to find spam NFTs in a given wallet. Just use SPAM_FILTER_ONLY value to get only spam NFTs. The semantics and the response format are the same as in the above example.

Reporting spam classification errors

As developers integrating with our NFT API, we've made it easy for you to handle NFT spam within digital wallets. In addition to our spam filtering mechanism, we've implemented a feedback loop that allows you to report instances where our system might have misclassified NFTs, either as false-positives (legitimate NFTs marked as spam) or false-negatives (spam NFTs not flagged).

By reporting these misclassifications, you contribute to the continuous improvement of our spam detection models, which ultimately leads to a more precise and reliable spam detection.

Here's how you can participate in this feedback loop:

Reporting Misclassifications

  1. False-Positive Reporting: If you encounter a legitimate NFT that our system mistakenly flagged as spam, use the Report Not Spam endpoint to report the error. Provide the walletAddress and the contractAddress of the collection. Optionally, you can also provide a tokenId of a specific NFT and a free form feedback string.
  2. False-Negative Reporting: Conversely, if our system has overlooked a spam NFT, report it through the Report Spam endpoint. The semantics of this endpoint is the same as the above.
curl --request GET \
     --url 'https://ethereum-rest.api.mnemonichq.com/wallets/v1beta2/0x3eb4b12127EdC81A4d2fD49658db07005bcAd065/report_spam/0x0ded8542fc8b2b4e781b96e99fee6406550c9b7c?tokenId=9213' \
     --header 'X-API-Key: <YOUR API KEY>' \
     --header 'accept: application/json'

We greatly appreciate your contribution to improving our spam detection mechanism. Your feedback is invaluable in ensuring that our API remains accurate and efficient.