NFT Ownership

Ownership of digital assets on chain is one of the most fundamental principles underpinning the Web3 economy. Yet, reliably verifiying ownership and obtaining information about the assets a wallet address owns at any given point in time is a daunting task for anyone who's building a proof of ownership applications (like tickets and access to all kinds of special events), a wallet, a marketplace, analytics and trading tools, or any other application that requires ownership data.

It requires aggregating massive amounts of data from the chain and counting all transfers that occur between all addresses in real-time. Missing a single transfer due to the network issues, chain instability, or a reorg will lead to incorrect data and a failure to verify if a wallet truly owns a particular asset.

Mnemonic solves this problem by providing accurate real-time ownership data and statistics about every address on the blockchain with a single call to the API.

Ownership by address

Mnemonic provides ownership data about every address on the blockchain.

To obtain all NFTs that are owned by an address, simply use the NFTs by Owner endpoint.

The response provides a list of all NFTs held by a given address with the basic NFT metadata (which includes the name, description, and an image if the NFT implements any of the recognized metadata standards).

curlpython
Copy
Copied
curl -i -X GET \
'https://ethereum.rest.mnemonichq.com/tokens/v1beta1/by_owner/0x3eb4b12127EdC81A4d2fD49658db07005bcAd065' \
-H 'X-API-Key: YOUR_API_KEY_HERE'
Copy
Copied
import requests # requires `pip install requests`

result = requests.get(
    'https://ethereum.rest.mnemonichq.com/tokens/v1beta1/by_owner/0x3eb4b12127EdC81A4d2fD49658db07005bcAd065',
    headers={'x-api-key': 'YOUR_API_KEY_HERE'}
).json()

This would return a response similar to the following:

Copy
Copied
{
    "tokens": [
        {
            "contractAddress": "0x3e6046b4d127179f0a421f3148b43cf52c08fc41",
            "tokenId": "8526",
            "type": "TOKEN_TYPE_ERC721",
            "metadata": {
                "metadataUri": {
                    "uri": "ipfs://QmVbZhfYHDyttyPjHQokVHVPYe7Bd5RdUrhxHoE6QimyYs/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": "ipfs://QmZkkoNaKp6PMv6wwy5YqsHvk3EkigUMvhgrmo3SaohZbP/8526.png",
                    "mimeType": "image/png"
                }
            },
            "quantity": "1"
        },
        {
            "contractAddress": "0x495f947276749ce646f68ac8c248420045cb7b5e",
            "tokenId": "36879996169960578461403022214606499702494133366280062521859522885222909607937",
            "type": "TOKEN_TYPE_ERC1155",
            "metadata": {
                "metadataUri": {
                    "uri": "https://api.opensea.io/api/v1/metadata/0x495f947276749Ce646f68AC8c248420045cb7b5e/0x5189568e4f38fb1c86e7288f016c8d3f9474c1dc000000000000030000000001",
                    "mimeType": "application/json"
                },
                "name": "Cryptokyo One",
                "description": "A figure seen by many but understood by few. Cryptokyo is an offshoot of my Tokyo Ginza gallery show.",
                "image": {
                    "uri": "https://lh3.googleusercontent.com/ULMtzdTiFQ4rJwlngj0Q4XuQlt7PR20dUwJ9ygL-ScNNjLJMuHUGeQBnj4tM-0mdl7VAopLUtZxg1Sy0K2pS8ql-V4o-yncOBHfsRw",
                    "mimeType": "image/png"
                }
            },
            "quantity": "1"
        },

        ...
        <trimmed>
    ]
}

There are more filters available to help refine the search results

  • contractAddress – filters the result based on a particular collection;
  • tokenTypes – filters the result based on specific token types (i.e. erc721, erc1155 etc);
  • limit and offset – controls the pagination;

NFT Owners

Some NFTs may have more than a single owner, especially if the token implements an ERC1155 standard. However, ERC721 is not limited to a single owner, and based on the contract's implementation may allow multiple owners of the same token.

With that in mind, Mnemonic provides a convenient way to find owners of a particular NFT using NFT Owners endpoint.

Single owner

curlpython
Copy
Copied
curl -i -X GET \
  'https://ethereum.rest.mnemonichq.com/tokens/v1beta1/token/0x4b10701bfd7bfedc47d50562b76b436fbb5bdb3b/2215/owners' \
  -H 'X-API-Key: YOUR_API_KEY_HERE'
Copy
Copied
import requests # requires `pip install requests`

result = requests.get(
    'https://ethereum.rest.mnemonichq.com/tokens/v1beta1/token/0x4b10701bfd7bfedc47d50562b76b436fbb5bdb3b/2215/owners',
    headers={'x-api-key': 'YOUR_API_KEY_HERE'}
).json()

The call above returns a list of all owners of an NFT along with the quantity owned. In this case it is just a single owner of a standard ERC721 token.

Copy
Copied
{
    "owners": [
        {
            "address": "0x3eb4b12127edc81a4d2fd49658db07005bcad065",
            "quantity": "1"
        }
    ]
}

Multiple owners

The following example demonstrates the case when multiple wallets own the same token ()

curlpython
Copy
Copied
curl -i -X GET \
  'https://ethereum.rest.mnemonichq.com/tokens/v1beta1/token/0x341a1c534248966c4b6afad165b98daed4b964ef/0/owners' \
  -H 'X-API-Key: YOUR_API_KEY_HERE'
Copy
Copied
import requests # requires `pip install requests`

result = requests.get(
    'https://ethereum.rest.mnemonichq.com/tokens/v1beta1/token/0x341a1c534248966c4b6afad165b98daed4b964ef/0/owners',
    headers={'x-api-key': 'YOUR_API_KEY_HERE'}
).json()

The response contains multiple paginated results:

Copy
Copied
{
    "owners": [
        {
            "address": "0x42d4fbb73d2529c11ddef10185dc6c25bf774a18",
            "quantity": "112"
        },
        {
            "address": "0x5a7ca6864fbc2debcef14533dc23a9aa2588b617",
            "quantity": "84"
        },
        {
            "address": "0xf4bec96417a11fd7daf57672ba7004ef536b4bd5",
            "quantity": "65"
        },
        {
            "address": "0x752b405ea444937e027a5a5d5e35514d9b5fd40c",
            "quantity": "52"
        },
        {
            "address": "0xa0697f3d5daef064e57cfdde5b31665decd99fbd",
            "quantity": "52"
        },
        ...
        <trimmed>
    ]
}

Ownership statistics

Ownership statistics provide a holistic view of all the owners at the collection level, and include the quantities owned by each address just like in the previous example.

List of owners

Every 5 minutes Mnemonic updates the ownership statistics on all contracts and wallet addresses on the supported blockchains and provides a convenient way to query this data using List of current owners by contract endpoint.

curlpython
Copy
Copied
curl -i -X GET \
  'https://ethereum.rest.mnemonichq.com/collections/v1beta1/current_owners/0x341a1c534248966c4b6afad165b98daed4b964ef' \
  -H 'X-API-Key: YOUR_API_KEY_HERE'
Copy
Copied
import requests # requires `pip install requests`

result = requests.get(
    'https://ethereum.rest.mnemonichq.com/collections/v1beta1/current_owners/0x341a1c534248966c4b6afad165b98daed4b964ef',
    headers={'x-api-key': 'YOUR_API_KEY_HERE'}
).json()

The response contains all owners of CryptoPunks with the quantities owned by each address.

Note: The following result contains all addresses, which may be other contracts as well.

Copy
Copied
{
    "owner": [
        {
            "address": "0xa858ddc0445d8131dac4d1de01f834ffcba52ef1",
            "ownedCount": "423"
        },
        {
            "address": "0xb7f7f6c52f2e2fdb1963eab30438024864c313f6",
            "ownedCount": "369"
        },
        {
            "address": "0xa25803ab86a327786bb59395fc0164d826b98298",
            "ownedCount": "231"
        },
        {
            "address": "0xb88f61e6fbda83fbfffabe364112137480398018",
            "ownedCount": "215"
        },
        {
            "address": "0x577ebc5de943e35cdf9ecb5bbe1f7d7cb6c7c647",
            "ownedCount": "165"
        },
        {
            "address": "0x269616d549d7e8eaa82dfb17028d0b212d11232a",
            "ownedCount": "149"
        },
        ...
        <trimmed>
    ]
}

There are additional parameters available to help refine the search result:

  • sortDirection – allows to sort results based on the owned quantities in a ascending or descending order;
  • limit and offset – allow to control the pagination;

Owners counts (current & historical)

Sometimes, however, it is not enough to obtain just a snapshot of all owners.

Mnemonic is the only solution on the market that provides accurate ownership statistics on every collection across all supported blockchains.

As the data gets updated every 5 minutes it unlocks use cases such as:

  • Tracking the "speed" of minting;
  • Holding distribution over time;
  • Tracking the frequency and trends of NFTs exchanging hands over time;

All this combined unlocks deeper insight into each collection, its performance, and its value.

Below is an example of owner counts over the last 30 days grouped by 1 day using the Owners count by contract endpoint.

curlpython
Copy
Copied
curl -i -X GET \
  'https://ethereum.rest.mnemonichq.com/collections/v1beta1/owners_count/0x4b10701bfd7bfedc47d50562b76b436fbb5bdb3b?duration=DURATION_30_DAYS&groupByPeriod=GROUP_BY_PERIOD_1_DAY' \
  -H 'X-API-Key: YOUR_API_KEY_HERE'
Copy
Copied
import requests # requires `pip install requests`

result = requests.get(
    'https://ethereum.rest.mnemonichq.com/collections/v1beta1/owners_count/0x4b10701bfd7bfedc47d50562b76b436fbb5bdb3b?duration=DURATION_30_DAYS&groupByPeriod=GROUP_BY_PERIOD_1_DAY',
    headers={'x-api-key': 'YOUR_API_KEY_HERE'}
).json()

THe response holds exactly 30 data points with the count of owners on each day.

Copy
Copied
{
    "dataPoints": [
        {
            "timestamp": "2022-05-20T00:00:00Z",
            "count": "307"
        },
        {
            "timestamp": "2022-05-21T00:00:00Z",
            "count": "330"
        },
        {
            "timestamp": "2022-05-22T00:00:00Z",
            "count": "337"
        },
        {
            "timestamp": "2022-05-23T00:00:00Z",
            "count": "361"
        },
        {
            "timestamp": "2022-05-24T00:00:00Z",
            "count": "407"
        },
        {
            "timestamp": "2022-05-25T00:00:00Z",
            "count": "445"
        },
        ...
        <trimmed>
    ]
}

There are additional parameters available to help refine the search result:

  • duration – the duration of the query, with values ranging from 1 day to 365 days;
  • timestampLt – the start timestamp for the analyses;
  • groupByPeriod – the aggregation period for the analyses;