Metamask 429 Error from React Moralis

Iā€™m using react-moralis to enabled web3 access on my Dapp. For the application to function, we are constantly reading from the blockchain and, of course, often writing to it as well. We have tried to limit our calls to the blockchain, but the reality is we can only limit it to once or twice every time the state changes on the blockchain. As a result, when purposely triggering these state changes 50-60 times, our application breaks with the error:

MetaMask - RPC Error: Non-200 status code: '429' 

So Iā€™m pretty sure this has to do with the Metamask RPC url I have for the current network Iā€™m connected to (Arbitrum Goerli atm) having a request limit of approx 60 a minute. My question is, how can I best avoid this as a Dapp developer? Must I rely on a centralized database to store my data and retrieve data from the blockchain using an independent node or is there a way to avoid this Metamask error and from the blockchain regularly without issue?

If you think you need that amount of requests per minute you shouldnt rely on public rpc nodes.

hey @slenn22 we recommend if you are using RPC node instead of public ones which is shared with other users, you should use a private one that is guaranteed to be more reliable. For our recommendation, you can use https://moralis.io/largenodes

But wouldnā€™t it be based on what RPC url the user has configured in their Metamask?

Well if you connect your etherjs provider to an RPC node it will use that instead of the Metamask provider

If you just have Metamask as the provider, then it will use whatever RPC nodes is set by the user there

That sounds like exactly what I need. Is there a way to do that while using the react-moralis library? Some sort of configuration I can set up?

I see now that I can provide a rpc to the MoralisProvider. It looks like thatā€™s how I should do it

With this certainly, you will just need to initialize the SDK and use etherjs under the hood to set the provider to the RPC node and that should work :raised_hands:

To get the etherjs web3 provider instance you can do:

const web3Provider = await Moralis.enableWeb3();

I think that one is a different provider, thatā€™s more like a React provider wrap the app so that you can use all Moralis functionality

Iā€™m a little confused about this. Where exactly am I setting up this provider? Is there some centralized location like maybe in _app.js in that I need to call it or do I call it whenever I need to use web3 functions like whenever I call useMoralis. Additionally, where do I set the RPC Url in this case? Am I supposed to use the enabledWeb3 function from useMoralis?

I understand Iā€™m supposed to use

const { enableWeb3 } = useMoralis()

But I canā€™t for the life of me figure out where I feed the enableWeb3 function the RPC URL. There doesnā€™t seem to be any mention of that in any docs I can find. Additionally, Iā€™m not even entirely sure where to call enableWeb3 in the first place.

Hey, it is not mentioned as usually it is not necessary to set custom RPC node in there

Here I just checked that I cannot find an equivalent function to set custom provider with ethersjs, so Iā€™m going to give you the example in web3js:

  1. First install web3js
npm install web3
  1. Then in your code add this:
import Web3 from "web3"; // Only when using npm/yarn

// Enable web3 and get the initialized web3 instance from Web3.js
await Moralis.enableWeb3();
const web3 = new Web3(Moralis.provider);
web3.setProvider(new Web3.providers.HttpProvider('YOUR_RPC_NODE_URL'))

Do you know if this is possible in typescript? My code is:

import Web3 from "web3"
import { useMoralis } from "react-moralis"

const { enableWeb3, provider } = useMoralis()

await enableWeb3();
const web3 = new Web3(provider);
web3.setProvider(new Web3.providers.HttpProvider('YOUR_RPC_NODE_URL'))

But I am getting the error: ā€œArgument of type ā€˜unknownā€™ is not assignable to parameter of type ā€˜providerā€™ā€

If I try to do import Moralis from "moralis" and await Moralis.enabledWeb3 I am getting an issue of ā€œProperty ā€˜enableWeb3ā€™ does not exist on type ā€˜{ Core: Core; Auth: Auth; Streams: Streams; EvmApi: EvmApi; SolApi: SolApi; start: (config?: Partial | undefined) => Promise<ā€¦>; }ā€™ā€

You shouldnā€™t put provider in useMoralis :raised_hands:, useMoralis() is not necessarily equivalent to Moralis itself

Ok, well now with this code Iā€™m getting the error ā€œArgument of type ā€˜unknownā€™ is not assignable to parameter of type ā€˜providerā€™.ā€

import Web3 from "web3"
import Moralis from 'moralis-v1'

async function enableWeb3WithCustomProvider() {
    await Moralis.enableWeb3();
    const web3 = new Web3(Moralis.provider)
    web3.setProvider(new Web3.providers.HttpProvider('YOUR_RPC_NODE_URL'))
}

Did it mention which line does the error occur?

Yes sorry, itā€™s on the const web3 = new Web3(Moralis.provider) line

From what url you get that rate limit error? You should see it in the network tab of the browser

Iā€™m using this public URL ā€œhttps://goerli-rollup.arbitrum.io/rpcā€ but my concern is that users of my site will probably also be using public RPC URLs for the most part and might run into rate limiting errors with them which will lead to bad UX. So, if I could set my own private RPC Url to handle most read requests to the blockchain, that would help mitigate the issue.

Even if you manage to do that, they will need MetaMask to sign a transaction.