Wie kann ich Kontoänderungen in Metamask erkennen?

Wenn ein Benutzer in der Metamaske zu einem anderen Konto wechselt, gibt es eine Möglichkeit, dies asynchron im Code zu erkennen?

verwende ich derzeit

this.web3.eth.getAccounts((err, accs) => {   
  this.account = accs[0];
});  

aber wenn das Konto geändert wird, nimmt es immer noch das vorherige auf. Das Aktualisieren der Seite ist nicht der richtige Weg. Ist jemand damit konfrontiert worden und hat eine Lösung?

Leider ist die von den meisten Leuten verwendete Methode das Abfragen von Änderungen mit setIntervals. Die einzige andere Möglichkeit besteht darin, vor jedem Anruf zu prüfen, ob die Konten übereinstimmen.

Antworten (6)

Wie in den Metamask-FAQs vorgeschlagen , könnte dies eine Option sein:

var account = web3.eth.accounts[0];
var accountInterval = setInterval(function() {
  if (web3.eth.accounts[0] !== account) {
    account = web3.eth.accounts[0];
    updateInterface();
  }
}, 100);

bearbeiten

In der neueren Version stellt metamask ein Ereignis bereit, das verwendet werden könnte, um zu erkennen, ob es eine Kontoänderung gemäß dem neuen Dokument gibt :

window.ethereum.on('accountsChanged', function (accounts) {
  // Time to reload your interface with accounts[0]!
})
Leider ist im Moment das Einchecken einer Schleife die einzige unterstützte Methode.
Seien Sie jedoch vorsichtig, ich hatte ein Problem, bei dem ich immer die if-Bedingung abgleichte, weil das Konto, das ich bekomme, immer in Kleinbuchstaben war.
Ich verwende und schlage vor, das onFocus-Ereignis zu verwenden, um dieses Problem zu lösen.
Gibt es eine ähnliche Lösung für die TronLink-Erweiterung (tronWeb)?

Aus den MetaMask-Dokumenten :

window.ethereum.on('accountsChanged', function (accounts) {
  // Time to reload your interface with accounts[0]!
})

window.ethereum.on('networkChanged', function (networkId) {
  // Time to reload your interface with the new networkId
})

Wie @Sr.PEDRO angemerkt hat, ethereum.publicConfigStorewird es in Zukunft nicht funktionieren. Tatsächlich wird es vollständig entfernt. Weitere Informationen finden Sie in diesem GitHub-Kommentar .

Sie können auch verhindern, dass MetaMask Webseiten automatisch neu lädt:

window.onbeforeunload = function() {
  return "Prevent reload"
}

Dies gilt nur, wenn Sie das window.web3von MetaMask eingefügte Objekt verwenden, das ebenfalls entfernt werden soll .

Gibt es eine ähnliche Lösung für die TronLink-Erweiterung (tronWeb)?
Die Dokument-URL hat sich geändert, gehen Sie zu docs.metamask.io/guide/ethereum-provider.html#table-of-contents

Unter Verwendung von web3 Version 1.0.0 stellt der Metamaskenanbieter ein „Update“-Ereignis bereit, das Sie in seinem publicConfigStore abhören können.

web3.currentProvider.publicConfigStore.on('update', callback);

Ihrem Rückruf wird ein Objekt mit „s selectedAddress“ und „networkVersion“ übergeben, wenn sich diese Attribute ändern.

Hallo Brian, wo finde ich Dokumentation über das Update-Ereignis? Habe die web3 1.0-Dokumentation durchsucht. Vielen Dank.
In der neuen Metamask-Version hat sich der Name geändert, jetzt müssen Sie verwenden, web3.currentProvider._publicConfigStore.on('update', callback);aber dies wird wahrscheinlich in Zukunft nicht mehr von Metamask unterstützt, daher würde ich empfehlen, window.ethereum events medium.com/metamask/… zu verwenden.

Sie könnten in useEffect ein listenEvent wie folgt einfügen:

useEffect(() => {
    async function listenMMAccount() {
      window.ethereum.on("accountsChanged", async function() {
        // Time to reload your interface with accounts[0]!
        accounts = await web3.eth.getAccounts();
        // accounts = await web3.eth.getAccounts();
        console.log(accounts);
      });
    }
    listenMMAccount();
  }, []);

Sie verwenden chainChangedevent, müssen aber 3 Dinge beachten:

  • Sie müssen Listener einmal global festlegen. Entweder in der Navigationsleiste oder bei Verwendung von provider in provider oder in next.js in der _app-Komponente

  • Wenn sich die Kette geändert hat, sollten Sie die Seite neu laden, empfohlen von metamask:

Wir empfehlen dringend, die Seite bei Kettenänderungen neu zu laden, es sei denn, Sie haben gute Gründe, dies nicht zu tun.

  • Nachdem Sie einen Listener für chainChangeddas Ereignis festgelegt haben, sollten Sie den Listener entfernen

Hier ist ein Beispiel in „react/next.js“.

  useEffect(() => {
   async function initWeb3() {
     try {
      const provider = new ethers.providers.Web3Provider(
        window.ethereum );
      setListener(window.ethereum);
      // then add logic here
    } catch (error: any) {
      // handle error
    }
  }
   initWeb3();
   return () => removeListener(window.ethereum);
  }, []);

  // this has to be set once globally. metamask suggests
  const setListener = (ethereum) => {
     ethereum.on("chainChanged", pageReload);
  };
  const removeListener = (ethereum) => {
    ethereum.removeListener("chainChanged", pageReload);
  };

  function pageReload() {
    window.location.reload();
  }

Änderung im Metamask-Konto erkennen

 useEffect(() => {
    if (window.ethereum) {
   
      window.ethereum.on("accountsChanged", () => {
        window.location.reload();
      });
    }
  });