trufflesuite / drizzle

Reactive Ethereum dapp UI suite
906 stars 238 forks source link

AccountData not updating when the user switches accounts in Metamask #85

Closed jmlon closed 4 years ago

jmlon commented 4 years ago

When I switch accounts in Metamask, the information in both, AccountData and drizzleState still reflect the information of the moment the page was rendered for the first time. The following component shows how to reproduce the problem and see the right values as returned by the web3 API.

import React, { useState, useEffect } from "react";
import { newContextComponents } from "@drizzle/react-components";

const { AccountData } = newContextComponents;

const AccountChangeDetection = ({ drizzle, drizzleState }) => {

  const [ drizzleAcc, setDrizzleAcc ] = useState(drizzleState.accounts[0]);
  const [ drizzleBal, setDrizzleBal ] = useState(drizzleState.accountBalances[drizzleState.accounts[0]]);

  const [ web3Acc, setWeb3Acc ] = useState(null);
  const [ web3Bal, setWeb3Bal ] = useState(null);

  useEffect(() => {

    function loadWeb3Data(web3) {
      web3.eth.getAccounts()
      .then( accounts => {
        setWeb3Acc(accounts[0]);
        web3.eth.getBalance(accounts[0])
        .then(setWeb3Bal);
      } );
    }

    async function listenMMAccount() {
      window.ethereum.on("accountsChanged", async function () {
        // console.log("Account changed");
        // console.log(drizzleState.accountBalances[drizzleState.accounts[0]]);
        setDrizzleAcc(drizzleState.accounts[0]);
        setDrizzleBal(drizzleState.accountBalances[drizzleState.accounts[0]]);
        loadWeb3Data(drizzle.web3);
      });
    }

    loadWeb3Data(drizzle.web3);
    listenMMAccount();
  });

  return (
    <div>

      <strong>AccountData</strong>
      <AccountData
        drizzle={drizzle}
        drizzleState={drizzleState}
        accountIndex={0}
        units="ether"
        precision={3}
      />

      <table>
        <tbody>
          <tr>
            <td>Drizzle</td>
            <td>{drizzleAcc}</td>
            <td>{drizzleBal}</td>
          </tr>
          <tr>
            <td>Web3</td>
            <td>{web3Acc}</td>
            <td>{web3Bal}</td>
          </tr>
        </tbody>
      </table>
    </div>
  );
};

export default AccountChangeDetection;
alexfisher commented 4 years ago

Just familiarizing myself with Drizzle box over the last week and it looks like it just makes a direct web socket connection to the local blockchain and doesn't check for another web3 provider that's already existing?

alexfisher commented 4 years ago

This led me to discover the LoadingContainer, but it looks like it's still not available outside of the legacy version of Drizzle? :-(

alexfisher commented 4 years ago

Wow, so the lockdown must have me brain dead or this just wasn't obvious. I had to comment out the customProvider line in drizzleOptions.js to get it to start attempting to connect to Metamask.

cds-amal commented 4 years ago

No worries @alexfisher . I was doing that before the lockdown :) I'm going to go ahead and close this issue.

charlower commented 3 years ago

Wow, so the lockdown must have me brain dead or this just wasn't obvious. I had to comment out the customProvider line in drizzleOptions.js to get it to start attempting to connect to Metamask.

Thanks @alexfisher this took me an embarrassingly long time to figure out aswell