[SOLVED] What is the correct ABI format for runContractFunction

I’m trying to call runContractFunction from https://docs.moralis.io/reference/runcontractfunction but the ABI format is making me input an ABI object.

The ABI is an array but I’m getting the error "message": "abi must contain at least 1 elements, abi must be an array, abi should not be empty":

[
  { inputs: [], stateMutability: 'nonpayable', type: 'constructor' },
  {
    anonymous: false,
    inputs: [
      {
        indexed: true,
        internalType: 'address',
        name: 'owner',
        type: 'address',
      },
      {
        indexed: true,
        internalType: 'address',
        name: 'spender',
        type: 'address',
      },
      {
        indexed: false,
        internalType: 'uint256',
        name: 'value',
        type: 'uint256',
      },
    ],
    name: 'Approval',
    type: 'event',
  },
 .......more
]

Here is the full request:

const options = {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    'X-API-Key': 'test'
  },
  body: JSON.stringify({
    abi: {
      abi: '[   { inputs: [], stateMutability: \'nonpayable\', type: \'constructor\' },   {     anonymous: false,     inputs: [       {         indexed: true,         internalType: \'address\',         name: \'owner\',         type: \'address\',       },       {         indexed: true,         internalType: \'address\',         name: \'spender\',         type: \'address\',       },       {         indexed: false,         internalType: \'uint256\',         name: \'value\',         type: \'uint256\',       },     ],     name: \'Approval\',     type: \'event\',   },   {     anonymous: false,     inputs: [       {         indexed: false,         internalType: \'address\',         name: \'userAddress\',         type: \'address\',       },       {         indexed: false,         internalType: \'address payable\',         name: \'relayerAddress\',         type: \'address\',       },       {         indexed: false,         internalType: \'bytes\',         name: \'functionSignature\',         type: \'bytes\',       },     ],     name: \'MetaTransactionExecuted\',     type: \'event\',   },   {     anonymous: false,     inputs: [       { indexed: true, internalType: \'bytes32\', name: \'role\', type: \'bytes32\' },       {         indexed: true,         internalType: \'bytes32\',         name: \'previousAdminRole\',         type: \'bytes32\',       },       {         indexed: true,         internalType: \'bytes32\',         name: \'newAdminRole\',         type: \'bytes32\',       },     ],     name: \'RoleAdminChanged\',     type: \'event\',   },   {     anonymous: false,     inputs: [       { indexed: true, internalType: \'bytes32\', name: \'role\', type: \'bytes32\' },       {         indexed: true,         internalType: \'address\',         name: \'account\',         type: \'address\',       },       {         indexed: true,         internalType: \'address\',         name: \'sender\',         type: \'address\',       },     ],     name: \'RoleGranted\',     type: \'event\',   },   {     anonymous: false,     inputs: [       { indexed: true, internalType: \'bytes32\', name: \'role\', type: \'bytes32\' },       {         indexed: true,         internalType: \'address\',         name: \'account\',         type: \'address\',       },       {         indexed: true,         internalType: \'address\',         name: \'sender\',         type: \'address\',       },     ],     name: \'RoleRevoked\',     type: \'event\',   },   {     anonymous: false,     inputs: [       { indexed: true, internalType: \'address\', name: \'from\', type: \'address\' },       { indexed: true, internalType: \'address\', name: \'to\', type: \'address\' },       {         indexed: false,         internalType: \'uint256\',         name: \'value\',         type: \'uint256\',       },     ],     name: \'Transfer\',     type: \'event\',   },   {     inputs: [],     name: \'CHILD_CHAIN_ID\',     outputs: [{ internalType: \'uint256\', name: \'\', type: \'uint256\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [],     name: \'CHILD_CHAIN_ID_BYTES\',     outputs: [{ internalType: \'bytes\', name: \'\', type: \'bytes\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [],     name: \'DEFAULT_ADMIN_ROLE\',     outputs: [{ internalType: \'bytes32\', name: \'\', type: \'bytes32\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [],     name: \'DEPOSITOR_ROLE\',     outputs: [{ internalType: \'bytes32\', name: \'\', type: \'bytes32\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [],     name: \'ERC712_VERSION\',     outputs: [{ internalType: \'string\', name: \'\', type: \'string\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [],     name: \'ROOT_CHAIN_ID\',     outputs: [{ internalType: \'uint256\', name: \'\', type: \'uint256\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [],     name: \'ROOT_CHAIN_ID_BYTES\',     outputs: [{ internalType: \'bytes\', name: \'\', type: \'bytes\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [       { internalType: \'address\', name: \'owner\', type: \'address\' },       { internalType: \'address\', name: \'spender\', type: \'address\' },     ],     name: \'allowance\',     outputs: [{ internalType: \'uint256\', name: \'\', type: \'uint256\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [       { internalType: \'address\', name: \'spender\', type: \'address\' },       { internalType: \'uint256\', name: \'amount\', type: \'uint256\' },     ],     name: \'approve\',     outputs: [{ internalType: \'bool\', name: \'\', type: \'bool\' }],     stateMutability: \'nonpayable\',     type: \'function\',   },   {     inputs: [{ internalType: \'address\', name: \'account\', type: \'address\' }],     name: \'balanceOf\',     outputs: [{ internalType: \'uint256\', name: \'\', type: \'uint256\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [{ internalType: \'string\', name: \'name_\', type: \'string\' }],     name: \'changeName\',     outputs: [],     stateMutability: \'nonpayable\',     type: \'function\',   },   {     inputs: [],     name: \'decimals\',     outputs: [{ internalType: \'uint8\', name: \'\', type: \'uint8\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [       { internalType: \'address\', name: \'spender\', type: \'address\' },       { internalType: \'uint256\', name: \'subtractedValue\', type: \'uint256\' },     ],     name: \'decreaseAllowance\',     outputs: [{ internalType: \'bool\', name: \'\', type: \'bool\' }],     stateMutability: \'nonpayable\',     type: \'function\',   },   {     inputs: [       { internalType: \'address\', name: \'user\', type: \'address\' },       { internalType: \'bytes\', name: \'depositData\', type: \'bytes\' },     ],     name: \'deposit\',     outputs: [],     stateMutability: \'nonpayable\',     type: \'function\',   },   {     inputs: [       { internalType: \'address\', name: \'userAddress\', type: \'address\' },       { internalType: \'bytes\', name: \'functionSignature\', type: \'bytes\' },       { internalType: \'bytes32\', name: \'sigR\', type: \'bytes32\' },       { internalType: \'bytes32\', name: \'sigS\', type: \'bytes32\' },       { internalType: \'uint8\', name: \'sigV\', type: \'uint8\' },     ],     name: \'executeMetaTransaction\',     outputs: [{ internalType: \'bytes\', name: \'\', type: \'bytes\' }],     stateMutability: \'payable\',     type: \'function\',   },   {     inputs: [],     name: \'getChainId\',     outputs: [{ internalType: \'uint256\', name: \'\', type: \'uint256\' }],     stateMutability: \'pure\',     type: \'function\',   },   {     inputs: [],     name: \'getDomainSeperator\',     outputs: [{ internalType: \'bytes32\', name: \'\', type: \'bytes32\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [{ internalType: \'address\', name: \'user\', type: \'address\' }],     name: \'getNonce\',     outputs: [{ internalType: \'uint256\', name: \'nonce\', type: \'uint256\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [{ internalType: \'bytes32\', name: \'role\', type: \'bytes32\' }],     name: \'getRoleAdmin\',     outputs: [{ internalType: \'bytes32\', name: \'\', type: \'bytes32\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [       { internalType: \'bytes32\', name: \'role\', type: \'bytes32\' },       { internalType: \'uint256\', name: \'index\', type: \'uint256\' },     ],     name: \'getRoleMember\',     outputs: [{ internalType: \'address\', name: \'\', type: \'address\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [{ internalType: \'bytes32\', name: \'role\', type: \'bytes32\' }],     name: \'getRoleMemberCount\',     outputs: [{ internalType: \'uint256\', name: \'\', type: \'uint256\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [       { internalType: \'bytes32\', name: \'role\', type: \'bytes32\' },       { internalType: \'address\', name: \'account\', type: \'address\' },     ],     name: \'grantRole\',     outputs: [],     stateMutability: \'nonpayable\',     type: \'function\',   },   {     inputs: [       { internalType: \'bytes32\', name: \'role\', type: \'bytes32\' },       { internalType: \'address\', name: \'account\', type: \'address\' },     ],     name: \'hasRole\',     outputs: [{ internalType: \'bool\', name: \'\', type: \'bool\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [       { internalType: \'address\', name: \'spender\', type: \'address\' },       { internalType: \'uint256\', name: \'addedValue\', type: \'uint256\' },     ],     name: \'increaseAllowance\',     outputs: [{ internalType: \'bool\', name: \'\', type: \'bool\' }],     stateMutability: \'nonpayable\',     type: \'function\',   },   {     inputs: [       { internalType: \'string\', name: \'name_\', type: \'string\' },       { internalType: \'string\', name: \'symbol_\', type: \'string\' },       { internalType: \'uint8\', name: \'decimals_\', type: \'uint8\' },       { internalType: \'address\', name: \'childChainManager\', type: \'address\' },     ],     name: \'initialize\',     outputs: [],     stateMutability: \'nonpayable\',     type: \'function\',   },   {     inputs: [],     name: \'name\',     outputs: [{ internalType: \'string\', name: \'\', type: \'string\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [       { internalType: \'bytes32\', name: \'role\', type: \'bytes32\' },       { internalType: \'address\', name: \'account\', type: \'address\' },     ],     name: \'renounceRole\',     outputs: [],     stateMutability: \'nonpayable\',     type: \'function\',   },   {     inputs: [       { internalType: \'bytes32\', name: \'role\', type: \'bytes32\' },       { internalType: \'address\', name: \'account\', type: \'address\' },     ],     name: \'revokeRole\',     outputs: [],     stateMutability: \'nonpayable\',     type: \'function\',   },   {     inputs: [],     name: \'symbol\',     outputs: [{ internalType: \'string\', name: \'\', type: \'string\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [],     name: \'totalSupply\',     outputs: [{ internalType: \'uint256\', name: \'\', type: \'uint256\' }],     stateMutability: \'view\',     type: \'function\',   },   {     inputs: [       { internalType: \'address\', name: \'recipient\', type: \'address\' },       { internalType: \'uint256\', name: \'amount\', type: \'uint256\' },     ],     name: \'transfer\',     outputs: [{ internalType: \'bool\', name: \'\', type: \'bool\' }],     stateMutability: \'nonpayable\',     type: \'function\',   },   {     inputs: [       { internalType: \'address\', name: \'sender\', type: \'address\' },       { internalType: \'address\', name: \'recipient\', type: \'address\' },       { internalType: \'uint256\', name: \'amount\', type: \'uint256\' },     ],     name: \'transferFrom\',     outputs: [{ internalType: \'bool\', name: \'\', type: \'bool\' }],     stateMutability: \'nonpayable\',     type: \'function\',   },   {     inputs: [{ internalType: \'uint256\', name: \'amount\', type: \'uint256\' }],     name: \'withdraw\',     outputs: [],     stateMutability: \'nonpayable\',     type: \'function\',   }, ]',
    },
    params: {account: '0xDaf02BC35B0eBa38744e046eA6314FDf7CE8A113'}
  })
};

fetch('https://deep-index.moralis.io/api/v2/0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa/function?chain=polygon&function_name=balanceOf', options)
  .then(response => response.json())
  .then(response => console.log(response))
  .catch(err => console.error(err));

Hey there you don’t need to include the whole array of ABI in the input there, just this for the input is enough and stringify it :raised_hands:

@YosephKS

Hmmm, it’s still giving me the same error.

I’m using this:

{
  inputs: [{ internalType: 'address', name: 'account', type: 'address' }],
  name: 'balanceOf',
  outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
  stateMutability: 'view',
  type: 'function',
}

Shouldn’t that ABI object be inside an array?

Ohh the one on docs has a bit of problem, but try to do it in SDKs directly it should have worked :raised_hands:

it may be easier to use the swagger interface directly:
https://deep-index.moralis.io/api-docs/#/native/runContractFunction

Still can’t get it to work with fetch. I’m assuming it’s just the ABI formatting.

I’m using:

const body = {
          abi: [
  {
    inputs: [{ internalType: 'address', name: 'account', type: 'address' }],
    name: 'balanceOf',
    outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
    stateMutability: 'view',
    type: 'function',
  },
],
          params: { account: '0xDaf02BC35B0eBa38744e046eA6314FDf7CE8A113' },
        };

then I add JSON.stringify(body) to the request.

This is the request being sent:

fetch("'https://deep-index.moralis.io/api/v2/0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa/function?chain=polygon&function_name=balanceOf'",  {
   body: "{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"params\":{\"account\":\"0xDaf02BC35B0eBa38744e046eA6314FDf7CE8A113\"}}"
   headers: {Accept: 'application/json', Content-Type: 'application/json', X-API-Key: 'my-web3api-key'}
   method: "POST"
})

It works with the react-moralis: Web3Api.native.runContractFunction(options) but I’m trying to migrate away from this package.

when you try it in the swagger interface, you will see a working example for CURL

Whatever I try with the body formatting I get "message": "Returned error: execution reverted"

I guess I’ll just keep using the web3 API for now and come back to this another day.

There doesn’t seem to be a balanceOf function on that contract address (0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa).

What options do you use with runContractFunction from react-moralis where it works?

@alex @cryptokid

I got it, I was making the request to polygon for that WETH address when I should’ve been using Mumbai.

I didn’t notice.

Thanks for checking everything!

:+1: :smiley:

1 Like