How to get NFT prices with Mnemonic's APIs

The NFT pricing problem

What happens in the transaction stays in the transaction!

When NFTs first appeared, it was relatively easy to properly attribute NFT prices because most transactions involved the transfer of just a single NFT. As a result, we could be confident all payments that occured within a given transaction were related to the same NFT transfer.

However as time goes by, NFT transactions are becoming increasingly complicated with the emergence of things like bundle mints and sales, swaps, circular trades and so on. In addition to multiple tokens being transfered back and forth in single transactions, we also are seeing more parties participating in a single transaction aside from the initial owner and the final recipient. All of these practices make price attribution for individual NFTs an increasingly complicated task.

For example, in June 2022, there were 13.38 million NFT transfers on Ethereum. Only 29.6% of those were single NFT transfers. The rest of these transfers were "bundles" where multiple NFTs were transfered in a single transaction. For comparison, in June 2019 68% of NFT transfers were single token transfers.

How Mnemonic approaches price attribution

Mnemonic indexes various transfers on the blockchain, detects payments, exchanges, and other types of transactions between accounts involving fungible and non-fungible tokens. As a next step Mnemonic applies pricing attribution algorithms to that data, enabling us to provide our end users with accurate and easy-to-use pricing data for individual NFT tokens.

Our algorithm accounts for the following unique transaction edge cases to name just a few:

  • Batch mints of NFTs;
  • Bundle sales (both single- and multi-contract);
  • Transfers via intermediate addresses;
  • ERC-1155 tokens with multiple quantities;
  • Bi-directional payments;
  • and many others...

In the vast majority of cases, we are able to provide accurate pricing attribution for NFTs. We also provide a dedicated endpoint that returns a full, detailed breakdown of all NFTs and payments involved in any given transaction.

Using Mnemonic's Transfer Insights endpoints to get NFT prices

Our Transfer Insights endpoints provide the ability to get a list of NFT transfers filtered by various fields. For the GetNftTransfers endpoint, the response aside from the regular information about transfers will contain details related to pricing attribution. At the same time GetAllTransfersByTxHash endpoint will allow you to get a full breakdown.

Pricing details

Field names provided are for Ethereum and may differ for other blockchains.

For each NFT transfer returned, the response contains the senderReceived and recipientPaid sub-objects with the following structure:

  • totalEth - total amount attributed to this transfer, converted to ETH (if the payment or part of the payment has been made by non-eth fungilbe tokens);
  • totalUsd - total amount converted to USD according to the exchange rate at the transfer time;
  • ethTransfersTotal - total for the portion of payments made natively in ETH;
  • erc20TransfersTotal - total for the portion of payments made native in ERC20 and converted to ETH.

Basically the totalEth field is a sum of ethTransfersTotal and erc20TransfersTotal, the latter is provided solely for your convenience.

It is worth noting that if the pricing attribution was impossible for either the sender or recipient of a transfer, the whole object will be equal to null. Such cases include, for example, a zero-quantity ERC-1155 transfer or transfers where multiple tokens are being burned at the same time.

Another possible case is if the erc20TransfersTotal field (and as a result also totalEth and totalUsd) begins equal to null, which means that the transfer included fungible tokens, that either do not fully conform to the ERC20 standard or do not have an exchange rate to ETH.

Example with a mixed payment

Let's take a look at a sample transfer which illustrates the fields mentioned above. In this case, you can see that the seller has been paid in solely in ERC-20 tokens, while the purchaser paid partially in ERC-20 and partially in native ETH.

Copy
Copied
{
  "blockchainEvent": {
    "txHash": "0x0ca31a30b9a828d5e8022f925db13ce220d067acc9e882e189c1fca628ee6620",
    "logIndex": 427,
    "seqIndex": 0,
    "blockNumber": 15129373,
    "blockTimestamp": "2022-07-12 18:05:44+00"
  },
  "contractAddress": "0x2ee6af0dff3a1ce3f7e3414c52c48fd50d73691e",
  "tokenId": "4802",
  "tokenType": "TOKEN_TYPE_ERC721",
  "transferType": "TRANSFER_TYPE_REGULAR",
  "quantity": "1",
  "sender": {
    "address": "0x910baeba92c30a1bf3d9a23d9eb0e645a88135fd",
    "type": "TYPE_OWNER"
  },
  "senderReceived": {
    "totalEth": "0.13636656005335413952",
    "totalUsd": "146.80918416606025558869750243225024",
    "ethTransfersTotal": "0",
    "erc20TransfersTotal": "0.13636656005335413952"
  },
  "recipient": {
    "address": "0x512a966f39775225850f447b87e36699a12dd516",
    "type": "TYPE_OWNER"
  },
  "recipientPaid": {
    "totalEth": "0.1549743640150963025024",
    "totalUsd": "166.8419291269694475347252231256271488",
    "ethTransfersTotal": "0.050432",
    "erc20TransfersTotal": "0.1045423640150963025024"
  }
}

Sender/recipient Types

Another helpful field returned in the response is type within the sender and recipient objects. This field helps to detect transfers via intermediate contracts. It can take one of the following values:

  • TYPE_OWNER - the address is either the initial owner or the final recipient of the NFT;
  • TYPE_INTERMEDIATE - the address is an intermediary and neither the initial owner nor the final recipient.

In cases where either the sender or recipient is marked as intermediate, respective pricing details object will be equal to null because the above mentioned entity does not buy or sell NFTs in the transaction.

Example

Let's take a look at another example where an NFT transfer occurs via intermediate party (GemSwap).

Copy
Copied
[
  {
    "blockchainEvent": {
      "txHash": "0xa9ac922d5816b4575ba91f833429ca952a70b9df824c55ba784cf70dbdf01d74",
      "logIndex": 136,
      "seqIndex": 0,
      "blockNumber": 15129929,
      "blockTimestamp": "2022-07-12 20:11:01+00"
    },
    "contractAddress": "0xeccae88ff31e9f823f25beb404cbf2110e81f1fa",
    "tokenId": "7254",
    "tokenType": "TOKEN_TYPE_ERC721",
    "transferType": "TRANSFER_TYPE_TRANSFER",
    "quantity": "1",
    "sender": {
      "address": "0x3b267a2664256a0102ad2d4d182e80ff797d991c",
      "type": "TYPE_OWNER"
    },
    "senderReceived": {
      "totalEth": "0.028855",
      "totalUsd": "30.043725466467958947",
      "ethTransfersTotal": "0.028855",
      "erc20TransfersTotal": "0"
    },
    "recipient": {
      "address": "0x83c8f28c26bf6aaca652df1dbbe0e1b56f8baba2",
      "type": "TYPE_INTERMEDIATE"
    },
    "recipientPaid": null
  },
  {
    "blockchainEvent": {
      "txHash": "0xa9ac922d5816b4575ba91f833429ca952a70b9df824c55ba784cf70dbdf01d74",
      "logIndex": 140,
      "seqIndex": 0,
      "blockNumber": 15129929,
      "blockTimestamp": "2022-07-12 20:11:01+00"
    },
    "contractAddress": "0xeccae88ff31e9f823f25beb404cbf2110e81f1fa",
    "tokenId": "7254",
    "tokenType": "TOKEN_TYPE_ERC721",
    "transferType": "TRANSFER_TYPE_TRANSFER",
    "quantity": "1",
    "sender": {
      "address": "0x83c8f28c26bf6aaca652df1dbbe0e1b56f8baba2",
      "type": "TYPE_INTERMEDIATE"
    },
    "senderReceived": null,
    "recipient": {
      "address": "0x0e6bb4218c44668051fda95c94fcbf11f3fca08f",
      "type": "TYPE_OWNER"
    },
    "recipientPaid": {
      "totalEth": "0.029",
      "totalUsd": "30.1946989612743306",
      "ethTransfersTotal": "0.029",
      "erc20TransfersTotal": "0"
    }
  }
]

All transfers by transaction

In addition to returning attributed prices, our Transfer Insights endpoints allow you to get a full breakdown of all transfers (NFT, ERC20, ETH, and/or others depending on the blockchain) within a transaction — via GetAllTransfersByTxHash endpoint.

This endpoint returns txHash as input and returns a set of lists for each type of transfer within to the requested transaction.

Example

Let's take a look at the following example:

Copy
Copied
{
  "nftTransfers": [
    {
      "blockchainEvent": {
        "txHash": "0x4441fe5daceeb0a10d7682a445abdd5b6c4806d43fc6def186575a882f9f599c",
        "logIndex": 271,
        "seqIndex": 0,
        "blockNumber": 15120950,
        "blockTimestamp": "2022-07-11 10:51:17+00"
      },
      "contractAddress": "0xd46c8648f2ac4ce1a1aace620460fbd24f640853",
      "tokenId": "5779",
      "tokenType": "TOKEN_TYPE_ERC721",
      "transferType": "TRANSFER_TYPE_BURN",
      "quantity": "1",
      "sender": {
        "address": "0x962871224822525c963d2d397b728a2aead83a1b",
        "type": "TYPE_OWNER"
      },
      "senderReceived": null,
      "recipient": {
        "address": "0x0000000000000000000000000000000000000000",
        "type": "TYPE_OWNER"
      },
      "recipientPaid": null
    }
    # ...more transfers...
  ],
  "ethTransfers": [
    {
      "fromAddress": "0x962871224822525c963d2d397b728a2aead83a1b",
      "toAddress": "0x3b968d2d299b895a5fcf3bba7a64ad0f566e6f88",
      "valueRaw": "2941445554065432573",
      "valueNormalized": "2.941445554065432573"
    }
    # ...more transfers...
  ],
  "erc20Transfers": [
    {
      "fromAddress": "0x0000000000000000000000000000000000000000",
      "toAddress": "0x43078abfb76bd24885fd64effb22049f92a8c495",
      "contractAddress": "0xed1840223484483c0cb050e6fc344d1ebf0778a9",
      "valueRaw": "340841025061864773",
      "valueNormalized": "0.3408410250618648",
      "valueEth": null
    }
    # ...more transfers...
  ]
}

Using the Collection Analytics API to get pricing data

Mnemonic is the only NFT data solution on the market that provides accurate pricing information for all existing collections on the blockchain as a time-series. The data is updated every 15 minutes for every collection on the blockchain (ERC721 and ERC1155) and is aggregated into 1h time periods.

The provided data covers all transactions from across the entire blockchain regardless of which marketplace the trade was executed on.

There is no limit to how far back the historical data can be retrieved.

All price values are converted into ETH according to the exchange rate at the time of the transaction if payments were made in ERC20 tokens.

Below is an example of pricing time-series data returned for the BAYC contract for the last 7 days aggregated into 1h time periods (trimmed for the purpose of this example).

The data is zero-padded to make charting the graph easier.

Copy
Copied
{
    "dataPoints": [
        {
            "timestamp": "2022-05-25T05:00:00Z",
            "min": "95",
            "max": "105",
            "avg": "98.6666666666666667"
        },
        {
            "timestamp": "2022-05-25T06:00:00Z",
            "min": "",
            "max": "",
            "avg": ""
        },
        {
            "timestamp": "2022-05-25T07:00:00Z",
            "min": "109",
            "max": "109",
            "avg": "109"
        },
        {
            "timestamp": "2022-05-25T08:00:00Z",
            "min": "",
            "max": "",
            "avg": ""
        },
        {
            "timestamp": "2022-05-25T09:00:00Z",
            "min": "",
            "max": "",
            "avg": ""
        },
        {
            "timestamp": "2022-05-25T10:00:00Z",
            "min": "",
            "max": "",
            "avg": ""
        },
        {
            "timestamp": "2022-05-25T11:00:00Z",
            "min": "86.0901233378872304",
            "max": "86.0901233378872304",
            "avg": "86.0901233378872304"
        }
        ...
        <trimmed>
    ]
}

Try using Mnemonic's Collection Analytics API to get the accurate time-series data for you project.

ERC20 Conversion

Mnemonic automatically converts ERC-20 token values into native ETH value according to the exchange rate at the time of the transaction.

The following ERC-20 tokens are currently converted automatically:

Symbol Token address
WETH 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
LINK 0x514910771af9ca656af840dff83e8264ecf986ca
USDC 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
SAND 0x3845badade8e6dff049820680d1f14bd3903a5d0
SUSHI 0x6b3595068778dd592e39a122f4f5a5cf09c90fe2
DAI 0x6b175474e89094c44da98b954eedeac495271d0f
USDT 0xdac17f958d2ee523a2206206994597c13d831ec7
ENJ 0xf629cbd94d3791c9250152bd8dfbdf380e2a3b9c
COVAL 0x3d658390460295fb963f54dc0899cfb1c30776df
DEGO 0x88ef27e69108b2633f8e1c184cc37940a075cc02
SHIB 0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce
WBTC 0x2260fac5e5542a773aa44fbcfedf7c193bc2c599
CRO 0xa0b73e1ff0b80914ab6fe0444e65848c4c34450b
APE 0x4d224452801aced8b2f0aebe155379bb5d594381
GALA 0x15d4c048f83bd7e37d49ea4c83a07267ec4203da