Moralis JS SDK v1.0 (migration to Ethers.js)

SDK v1 does not affect cloud functions

Where did you get ethers from? Did you import that library yourself?

In the latest version you can use:

const ethers = Moralis.web3Library

That will give you access to the complete ethersJs library

const web3Provider = await Moralis.enableWeb3()

Will only give you an ethers web3Provier instance.

Hope this helps, otherwise can you share your code? As I can not see how you initialise ethers from your message

1 Like

Thank you Erno !! I’m going to try.
I also discover today that the Moralis’ doc has been updated regarding the Web3 Provider. I’m going to make new tests.

1 Like

I assume you updated both moralis and react-moralis, right?
If so than it should work. Also note that read-only functions do return the data directly, without the need to use data.wait() (see https://docs.moralis.io/moralis-server/web3/web3#executefunction)

If you use a “write” function, and use moralis v1 and react-moralis v1, and still have this issue, can you then share your code-snippet?

One more thing:
in the doc article i mentioned just in my previuous post, for paragraph " Web3.js", it is stated that this code should be in the frontend index.html :
<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>
Does it mean that if i want to use Ethers.js, i must remove this code ? Thank you for your advices.

Correct. You only need to include that code if you want to use web3.js

If you are using ethers.js, then you don’t need to include it (and you can remove it if you had it like that from before the v1 update)

1 Like
  1. I enabled Web3 with walletconnect to ethereum mainnet.
  2. Switch network to avalanche testnet.
  3. Deposit Lp
  4. Error pop up:
Error: underlying network changed (event="changed", network={"chainId":43114,"name":"unknown"}, detectedNetwork={"chainId":43113,"name":"unknown"}, code=NETWORK_ERROR, version=providers/5.5.2)
    at Logger.makeError (index.ts:225:1)
    at Web3Provider.<anonymous> (base-provider.ts:973:1)
    at Generator.next (<anonymous>)
    at fulfilled (base-provider.ts:2:1)

Enable Web3

  const connectAccount = (walletId: WalletId) => {
    let provider: MoralisType.Web3ProviderType = 'metamask'
    switch (walletId) {
      case WalletId.WALLETCONNECT:
        provider = 'walletconnect'
        break
      default:
        break
    }
    const onError = () => {
      showMessage(`Error happened on connecting to ${walletId}`, 'warning')
    }
    const onSuccess = () => {
      showMessage(`Successfully connected to ${walletId}`)
    }
    enableWeb3({ provider, onError, onSuccess })
  }


Deposit Lp

import { Contract } from 'ethers'
import { useMoralis } from 'react-moralis'
const { chainId, web3 } = useMoralis()
const handleClickSupply = async () => {
    const signer = web3.getSigner()
    const pool = new Contract(poolAddress, poolAbi, signer)
    pool.connect(signer)
    try {
      const amount = utils.parseUnits(
        depositLiquidity.token.amount,
        depositLiquidity.token.decimals,
      )
      const transaction = await pool.deposit(
        depositLiquidity.token.address,
        depositLiquidity.token.amount,
        account,
      )
      if (transaction) {
        await transaction.wait()
      }
    } catch (err) {
      console.log(err)
    }
  }
}
1 Like

@RedCabbage I encounter same error when I updated the package. What I did was to run ‘yarn install’ or do ‘npm install’ again whichever package manager you are using, and it was solved. So you can try that.

For my use case I’m trying to get a private key to sign transactions on the cloud. Is there any difference in how that’s done in v1.x now?

The v1 update in the sdk does not affect on how web3 works in the cloud-code. The web3 interaction in cloud-code remains the same, as described in https://docs.moralis.io/moralis-server/cloud-code/cloud-functions#web3

1 Like

Can you test with the latest version of moralis and react-moralis?

We now update the provider every time the chain is changed.

It is still not work,
I found the solution here. But I cannot set network: ‘any’ to call moralis provider


“ethers”: “^5.4.1”,
“moralis”: “1.2.3”,
“react-moralis”: “1.2.1”,

I’m having the same issue, any updates on this? I’m building a bridging app and need to be able to switch networks without reloading the page. Is there some way to validate if the provider has changed, or some way to force it?

I’ve found a couple of options that seem to work. The first is a bit of a hack, and may be fragile.
Once you get your provider handle with
web3Provider = await Moralis.enableWeb3();
do
web3Provider.anyNetwork = true;

While this did appear to work in some of my tests, it was not consistent when multiple changes happened. It did seem to tolerate the first change though.

A better solution, I think, is to manually force a refresh of your handle whenever you expect a network change.

	await Moralis.switchNetwork(newNetwork);
	web3Provider = await Moralis.enableWeb3();

you might be able to handle the refresh using the network changed event listener, but I have not tried that.

Hope this helps

@oscar, @mloit

Fixed in v1.2.5

Added the option to set ‘any’ network by using anyNetwork param when calling enableWeb3/authenticate:

enableWeb3({anyNetwork: true})

Please not the warning found in the linked github ( Discussion: Provider will fail if the backend network changes except for “any”

This only affects backends that can change their network, such as MetaMask or using your own Geth instance; to get the legacy functionality, pass the string "any" as the network parameter, but please be aware that there are many edge cases your dapp should be handling that you may not be. Not using the "any" network might help flush out parts of your dapp which were previously unsafe in cases you hadn’t even thought of. :slight_smile:

Alternatively, depending on your dapp, when you use react, you can also use useEffect/useMemo to update the contract instance when the web3 instance updates (for example when the chain changes)

  const { Moralis, web3 } = useMoralis();

  const contract = useMemo(() => {
    if (!web3) {
      return null;
    }

    return new Moralis.web3Library.Contract(
      "0x123456",
      ABI,
      web3
    );
  }, [Moralis.web3Library, web3]);

Thanks for the quick work. It broke my “fix” above, but that’s fine. It has created a new problem though, specific to the Binance Test Network [and is tied to a bug in Metamask] where we get a web3 disconnection on a switch into the network. I was working around this by forcing a reconnect on the disconnection notice, and that worked fine until this update. Now when I switch into the test network I get an uncaught exception inside moralis.js

Uncaught TypeError: Cannot read properties of null (reading 'web3')
    at Function.value (moralis.js:5874:45)
    at InternalWeb3Provider.<anonymous> (moralis.js:5924:32)
    at InternalWeb3Provider.emit (moralis.js:70661:5)
    at InternalWeb3Provider.value (moralis.js:1572:12)
    at InjectedWeb3Connector.emit (moralis.js:70661:5)
    at InjectedWeb3Connector.value (moralis.js:27341:12)
    at i (inpage.js:1:54958)
    at l.emit (inpage.js:1:55353)
    at l._handleChainChanged (inpage.js:1:40315)
    at l._handleChainChanged (inpage.js:1:45320)

Once this error occurs, any calls to change the network return immediately with a failure because web3 no longer exists. The exception seems to be thrown after my successful reconnection happens in the ondisconnect handler. This now leaves the web3 provider handle unreliable.

I see, same happens to me, but only for the binance testnet, that is really weird.

You can set the rpc url in metamask (via settings > network) to https://data-seed-prebsc-2-s3.binance.org:8545
They have multiple rpcs, seems that not all of them are working nice with chain changes.

Will see what we can do about it, it might out of our control, but I will check.

When this situation happens, a disconnect event is fired. You could check for this event in your app and account for it.

 Moralis.onDisconnect((args) => console.log("onDisconnect", args));

Also, do you have a link to the related metamask issue?

here is my onDisconnect handler… it does re register a listener on the new instance, but I am not seeing a disconnect event being fired, only the uncaught exception coming out of ‘inpage’. The exception seems to come about a second after the new instance is created in the old onDisconnect handler.

	unsubDisconnect = Moralis.onDisconnect(async function(error) {
		console.log("onDisconnect:",error)
		if(loggedIn === true) {
			endSession();
			console.log("Attempting to reconnect Web3");
			await Moralis.enableWeb3({anyNetwork: true}).then(function(result) {
				console.log('web3() enabled');
				web3Provider = result;
				beginSession();
			}).catch(async function() {
				await Moralis.enableWeb3({ provider: "walletconnect", anyNetwork: true }).then(function(result) {
					console.log('web3(walletconnect) enabled');
					web3Provider = result;
					beginSession();
				}).catch(function(error) {
					console.log('web3 failed', error);
				});
			});
		}
	});

and here is the sequence of events I see on the console when it happens. Note that the Registering Listeners comes from beginSession(), and is where the onDisconnect listener is registered to the new instance.

onDisconnect: Error: MetaMask: Disconnected from chain. Attempting to connect.
    at l._handleDisconnect (inpage.js:1:39598)
    at l._handleDisconnect (inpage.js:1:43404)
    at l._handleChainChanged (inpage.js:1:40205)
    at l._handleChainChanged (inpage.js:1:45320)
    at o.<anonymous> (inpage.js:1:37771)
    at i (inpage.js:1:54958)
    at o.emit (inpage.js:1:55498)
    at inpage.js:1:54022
    at f.write [as _write] (inpage.js:1:54045)
    at w (inpage.js:17:29414)
main.js:842 Deregestering Event Listeners
main.js:822 Attempting to reconnect Web3
main.js:824 web3() enabled
main.js:781 Regestering Event Listeners
inpage.js:1 Uncaught TypeError: Cannot read properties of null (reading 'web3')
    at Function.value (moralis.js:5874:45)
    at InternalWeb3Provider.<anonymous> (moralis.js:5924:32)
    at InternalWeb3Provider.emit (moralis.js:70661:5)
    at InternalWeb3Provider.value (moralis.js:1572:12)
    at InjectedWeb3Connector.emit (moralis.js:70661:5)
    at InjectedWeb3Connector.value (moralis.js:27341:12)
    at i (inpage.js:1:54958)
    at l.emit (inpage.js:1:55353)
    at l._handleChainChanged (inpage.js:1:40315)
    at l._handleChainChanged (inpage.js:1:45320)
value @ moralis.js:5874
(anonymous) @ moralis.js:5924
emit @ moralis.js:70661
value @ moralis.js:1572
emit @ moralis.js:70661
value @ moralis.js:27341
i @ inpage.js:1
emit @ inpage.js:1
_handleChainChanged @ inpage.js:1
_handleChainChanged @ inpage.js:1
(anonymous) @ inpage.js:1
i @ inpage.js:1
emit @ inpage.js:1
(anonymous) @ inpage.js:1
write @ inpage.js:1
w @ inpage.js:17
(anonymous) @ inpage.js:17
y.write @ inpage.js:17
g @ inpage.js:17
d @ inpage.js:8
s.emit @ inpage.js:8
_ @ inpage.js:17
v @ inpage.js:17
w.push @ inpage.js:17
_write @ inpage.js:1
w @ inpage.js:17
(anonymous) @ inpage.js:17
y.write @ inpage.js:17
g @ inpage.js:1
d @ inpage.js:8
s.emit @ inpage.js:8
_ @ inpage.js:1
v @ inpage.js:1
w.push @ inpage.js:1
_onData @ inpage.js:1
_onMessage @ inpage.js:1
setTimeout (async)
i @ inpage.js:1
emit @ inpage.js:1
_handleChainChanged @ inpage.js:1
_handleChainChanged @ inpage.js:1
(anonymous) @ inpage.js:1
i @ inpage.js:1
emit @ inpage.js:1
(anonymous) @ inpage.js:1
write @ inpage.js:1
w @ inpage.js:17
(anonymous) @ inpage.js:17
y.write @ inpage.js:17
g @ inpage.js:17
d @ inpage.js:8
s.emit @ inpage.js:8
_ @ inpage.js:17
v @ inpage.js:17
w.push @ inpage.js:17
_write @ inpage.js:1
w @ inpage.js:17
(anonymous) @ inpage.js:17
y.write @ inpage.js:17
g @ inpage.js:1
d @ inpage.js:8
s.emit @ inpage.js:8
_ @ inpage.js:1
v @ inpage.js:1
w.push @ inpage.js:1
_onData @ inpage.js:1
_onMessage @ inpage.js:1
postMessage (async)
_postMessage @ contentscript.js:1
_write @ contentscript.js:1
w @ contentscript.js:1
(anonymous) @ contentscript.js:1
y.write @ contentscript.js:1
g @ contentscript.js:17
h @ contentscript.js:8
s.emit @ contentscript.js:8
_ @ contentscript.js:17
v @ contentscript.js:17
w.push @ contentscript.js:17
_write @ contentscript.js:17
w @ contentscript.js:17
(anonymous) @ contentscript.js:17
y.write @ contentscript.js:17
g @ contentscript.js:17
h @ contentscript.js:8
s.emit @ contentscript.js:8
_ @ contentscript.js:17
v @ contentscript.js:17
w.push @ contentscript.js:17
_write @ contentscript.js:17
w @ contentscript.js:17
(anonymous) @ contentscript.js:17
y.write @ contentscript.js:17
g @ contentscript.js:17
h @ contentscript.js:8
s.emit @ contentscript.js:8
_ @ contentscript.js:17
v @ contentscript.js:17
w.push @ contentscript.js:17
_onMessage @ contentscript.js:8
(anonymous) @ contentscript.js:8
Show 39 more frames

here is the Metamask report, it’s not the exact issue, but I suspect it stems from the same root cause. My post is at the end mentioning this issue specifically.

1 Like

Seems that metamask is atleast reaconnecting, if it fails on the binance rpc. Now we check for this specific error. If so, we will not fire a disconnect event. That should do the trick.

Update to 1.2.6 for this fix

At least in my test environment it works perfectly with the binance testnet. It does take a bit longer than a ‘normal’ change of networks though it seems