Changes in WEB3 API parameters from June 1, 2022

Changes in default limit values

All WEB3 API endpoints that support pagination will change the default page size from 500 to 100.
Along with this, there will also be a fixed max limit of 100 (you can still select a lower limit than 100 if you wish).

What can break?

If your application relies on the default page size being 500 or if your explicit limit of the API calls are higher than 100, then your pagination logic might break.

What you need to do

If you rely on the assumption that the page size will be 500 if no limit is specified, you need to make changes to either fetch 5 pages (to get the same amount), or adjust the page size in your application.
See examples below:

Example: NodeJS SDK

The following example demonstrates a polyfill if your application needs to emulate a page size higher than 100

import Moralis from "moralis/node";
const serverUrl = "https://yoursubdomain.usemoralis.com:2053/server";
const appId = "yourAppId";
const contractAddress = "someContractAddress";

let owners: any

async function start(){
  await Moralis.start({ serverUrl: serverUrl, appId: appId });

  // Get first 500
  await getOwners();

  // Simulate old page size by dividing page by 5
  console.log(Math.floor(owners.page / 5))

  // Get next 500
  await getOwners()
  console.log(Math.floor(owners.page / 5))
}

async function includeNextNPages(previous: any, numPages: number){

  // Define results for the remaining pages 
  const result = previous.result || [];

  // Always keep the latest response around
  let response = previous;

  // Loop through the remaining pages
  for (let i = 0; i < numPages; i++) {
  
    // Get the next page
    response = await response.next(); //Best Practice: Always use next() to get the next page

    // Exit if we are on the last page already
    if (response.result.length == 0) break

    // Add the results to the previous results
    result.push(...response.result);
  }

  // Apply the results to the last page
  response.result = result

  // Return the response
  return response
}

async function getOwners() {

  owners = await Moralis.Web3API.token.getNFTOwners({
    address: contractAddress,
    chain: "eth", // Best Practice: Always specify chain
    limit: 100, // Best Practice: Always specify limit. (use the lowest limit you need for faster response)
    cursor: owners ? owners.cursor : null, // Optional
  }).then((response) => includeNextNPages(response, 4));
}

start()

Example: NodeJS API Calls


import axios from 'axios'

let owners: any
let cursor: string = '';
let page = 0;
const apiKey = 'youApiKey'
const contractAddress = "someContractAddress";
const url = `https://deep-index.moralis.io/api/v2/nft/${contractAddress}/owners?chain=eth&format=decimal&limit=100` // Best Practice: Always specify chain and limit
const options = { headers: { 'Accept': 'application/json', 'x-api-key': apiKey }}

async function fetchOwners() {
  const response = await axios.get(`${url}${cursor.length > 0 ? `&cursor=${cursor}`: ''}`, options).then(response => response.data);
  cursor = response.cursor;
  return response;
}
async function getOwners() {
  owners = await fetchOwners().then((response) => includeNextNPages(response, 4));

  // Simulate old page size by dividing page by 5
  page = Math.floor(owners.page / 5);
}

async function includeNextNPages(previous: any, numPages: number){

  //Define results for the remaining pages 
  const result = previous.result || [];

  // Always keep the latest response around
  let response = previous;

  // Loop through the remaining pages
  for (let i = 0; i < numPages; i++) {
  
    // Get the next page
    response = await fetchOwners();

    // Exit if we are on the last page already
    if (response.result.length == 0) break

    // Add the results to the previous results
    result.push(...response.result);
  }

  // Apply the results to the last page
  response.result = result

  // Return the response
  return response
}

async function start() {

  // Get first 500
  await getOwners();
  console.log(page);

  // Get next 500
  await getOwners();
  console.log(page);
}

start()

Changes in offset parameter

All WEB3 API endpoints that support cursor pagination will remove the possibility to use the offset parameter as means of pagination.

What can break?

If your application uses offset to implement pagination, you will have to refactor to use cursor pagination instead.
If your application is build to be able to instantly “jump” to a page futher ahead, this will no longer be possible.
Instead you can work with other “constraints” to “jump ahead”. For example: many endpoints allows you to specify to_block or to_date. By using these you can “jump” ahead instead of using offset

What you need to do

If you are manually using offset to paginate and use the SDK, you can easily just switch to use next().
You can read more here: https://docs.moralis.io/moralis-dapp/web3-api#web3-api-pagination-examples-with-.next
If your application is built to be able to jump to a page further away, you need to work with constraints instead.
If you work with the API directly, you will need to work with cursor instead of offset.
You can read more about cursor here: https://docs.moralis.io/misc/rate-limit#example-of-how-to-use-cursor-nodejs

Best Practices in Pagination

  • Always specify chain explicitly
  • Always specify limit explicitly
  • Use the smallest limit you need. i.e if you only display 20 items on a page, use 20 as limit
  • Use constraints where you need. i.e if you are only interested in the NFT transfers of the latest week, use the from_date parameter to narrow down the result. this will decrease network traffic and lower response time.
3 Likes

It’s not a backward compatible change! This change has broken my service! You should never deprecate API in a manner like this unitil you make sure that no one uses it!

3 Likes

I use the getNFTOwners endpoint to iterate through Nfts owner to get all owners of a certain smart contract, and the limit change from 500 to 100 made the requests take a really long time to finish. Is their any way to make this faster? Am I missing something?
This change really impacted my web service, and this happened on my service launch date :frowning:

Hi,
You can create a separate forum thread for this, it shouldn’t be too much slower as the requests with limit 100 should run faster now.