How to get enriched NFTs balances

Whether you’re building a wallet, investing from smart contracts, or building out tax-solutions, accessing high-quality financial-accounting data is critical to ensuring you’re accurately capturing both yours and your users activity and performance.
With OpenPool’s API’s you can seamlessly access comprehensive contract & wallet accounting and reporting data for all your applications

This article will walk through how you can pull in NFT balances and performance for a given address(es). With these requests, you will be able to see extremely detailed financial-accounting breakdowns and summaries that include fields such as cost-basis to help power what you’re building.

Before we get started

You will need an API key to start making requests, so let’s first generate one from the OpenPool Dev Portal:

  1. Visit the Dev Portal at https://dev.openpool.co/

  2. Sign up or log in to your account

Untitled
  1. Create a Project and give it a name

Untitled

Awesome! Now that we have this covered, we’ll need to register the 0x address before you can start making any API calls. We covered this in a separate article and you can find [here] or in the docs.

Retrieving Enriched Balances & Performance

This request is a straightforward GET request that utilizes query parameters to specify the given addresses and timeframes a request should be made for.

This endpoint returns Current NFT Balances, Cost,s and Floor Prices for one or multiple wallets. NFT Floor Price is sourced from Opensea or LooksRare.

  • The NFT Cost Basis includes any gas fees paid in the minting process. Or, if the NFT was obtained via a Swap, the Cost Basis reflects the token value exchanged for the NFT at the time of purchase, inclusive of gas fees paid in the swap transaction.
  • For Floor Price, OpenPool looks across both Opensea and LooksRare. To be conservative, if an NFT is listed on both marketplaces, OpenPool returns the lower Floor Price.
  • NFT Balances & Performance can be returned for a single wallet or multiple wallets. For multiple wallets, the aggregated Cost Basis and Floor Price for the group of wallets queried will be returned in addition to the Cost and Floor Price for each individual NFT.

These requests are all straightforward GET requests that utilize query parameters to specify the given addresses and timeframes a request should be made for.

Now that we have that covered, let’s go through each of them and start setting up requests!

Making Requests

For this example, we’ll be utilizing Javascript to set up and make this request. This process will follow the same steps we took for getting the token balances

First let’s get our request url

const baseUrl = 'https://api.openpool.co/wallet/nft_balance/'

Now let’s set up the request headers

  • Make sure you store your API key as an environment variable for security purposes.
const headers = {
    accept: 'application/json',
    'X-API-KEY': process.env.OPENPOOL_API_KEY
  }

Let’s now specify the addresses and timeframes for a given request

  • This process will be done through the use of query parameters appended to the request url that are defined as wallet (for addresses), and period (for timeframes)
  • Addresses used here must be hexadecimal 0x strings
  • For example, to filter by address we’d utilize an address query param like so:
const addressToSearch = '0x59a5493513ba2378ed57ae5ecfb8a027e9d80365'
const baseUrlWithAddress = `https://api.openpool.co/wallet/balance/?wallet=${addressToSearch}`
  • To lookup multiple addresses, we’d just use a comma separated string for the respective addresses:
const address1ToSearch = '0x59a5493513ba2378ed57ae5ecfb8a027e9d80365'
const address2ToSearch = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'
const stringOfCommaSeperatedAddresses = `${address1ToSearch}, ${address2ToSearch}`
const baseUrlWithAddresses = `https://api.openpool.co/wallet/nft_balance/?wallet=`${stringOfCommaSeperatedAddresses}`
  • The default timeframe is set to be 1 Week, and if we want to change that filter, we’d structure the request as:
const addressToSearch = '0x59a5493513ba2378ed57ae5ecfb8a027e9d80365'
const timeframe = 'YTD'
const baseUrlWithAddress = `https://api.openpool.co/wallet/nft_balance/?wallet=${addressToSearch}&period=${timeframe}`

Now that we have all this down, let’s put together our request

  • In practice, you will likely want to use a more robust validation check here for the address
const retrieveNFTBalancesAndPerformance = async (address: string, timeframe = "W") => {
  if (!address || typeof address !== 'string' || address && typeof address === 'string' && !address.includes('0x')) {
    throw new Error('A valid address is required for making requests');
    return
  }
  try {
     let request = `https://api.openpool.co/wallet/nft_balance/?wallet=${address}&period=${timeframe}`
     const headers = {
       accept: 'application/json',
      'X-API-KEY': '<YOUR_API_KEY>'
     }
    const requestOptions = {
      method: 'GET',
      headers: headers
    };
    const response = await fetch(url, requestOptions)
        const parsedResponse = await response.json()
        return parsedResponse
      }
  catch(e){
      console.error(`The error trying to retrieve NFT balances`, ${e})
  }
}

Reading from the response

When you receive a successful response, you will receive back an Object with two properties:

  • Data: An array of objects representing the NFT positions and metadata that has the following shape:
[
   {
          "id": 15227698,
          "balance": 1,
          "cost": {
            "value": "0.16",
            "currency": "ETH",
            "fiat": "419.99",
            "fiat_currency": "USD"
          },
          "floor": {
            "value": 0.0377,
            "currency": "ETH",
            "fiat": 69.589299,
            "fiat_currency": "USD"
          },
          "nft": {
            "id": 94,
            "collection": {
              "floor": [
                {
                  "venue": {
                    "id": 1,
                    "name": "openSea",
                    "image_url": "https://storage.googleapis.com/opensea-static/Logomark/Logomark-Blue.png"
                  },
                  "floor": "0.03770000",
                  "currency": "ETH",
                  "timestamp": "2023-04-03T01:50:46.593000Z"
                }
              ],
              "blockchain": {
                "id": 12,
                "name": "Ethereum",
                "slug": "ethereum",
                "image_url": "https://openpool.s3.amazonaws.com/landingImages/eth.png"
              },
              "address": "0x25ed58c027921e14d86380ea2646e3a1b5c55a8b",
              "name": "Devs for Revolution",
              "symbol": "DEVS",
              "description": "Devs for Revolution grants token holders official Developer DAO membership.\n\nhttps://developerdao.notion.site/Getting-Started-with-Developer-DAO-2bddd332c51a4957b0b83f60f9fa4ebe",
              "image_url": "https://i.seadn.io/gae/6Jbode0t_bTO9MHYoYvjIW9nHENCxOs40EGg3Z5ptg4lLlD2z2WXEAIrjyV929aQnIi94hPL4VZ3Pl2NWOO_tSaO6gdjdrcMHrF9?w=500&auto=format",
              "opensea_status": null,
              "is_spam": false
            },
            "token_id": "1223",
            "name": "Dev #1223",
            "image": "https://openseauserdata.com/files/69acdb304a8ab5038eff1c0f29c9af0b.svg",
            "preview": "https://openseauserdata.com/files/69acdb304a8ab5038eff1c0f29c9af0b.svg",
            "thumbnail": "https://openseauserdata.com/files/69acdb304a8ab5038eff1c0f29c9af0b.svg",
            "original": null,
            "animation_image": null,
            "animation_original": null,
            "description": "Developers around the world are tired of working and contributing their time and effort to enrich the top 1%. Join the movement that is community owned, building the future from the bottom up.",
            "external_url": null
          },
          "wallet": "0x9c21a04468e028f9b7215392bbe5171f634bc76a"
        },
  ],
  • Summary: An object comprised of a summary view of NFTs
{
        "total_value": 106.4800630959,
        "total_cost": 708.1395942600001,
        "count": 100
      }

Next Steps

Look at us! Now we’re now we can retrieve detailed financial-accounting balances and performance values! Next up we’ll cover how to pull enriched transactions with financial-accounting metrics.