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?
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);
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]!
})
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.publicConfigStore
wird 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.web3
von MetaMask eingefügte Objekt verwenden, das ebenfalls entfernt werden soll .
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.
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 chainChanged
event, 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.
chainChanged
das Ereignis festgelegt haben, sollten Sie den Listener entfernenHier 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();
});
}
});
ReyHaynes