Cuando un usuario cambia a una cuenta diferente en metamask, ¿hay alguna forma de detectarlo de forma asíncrona en el código?
actualmente uso
this.web3.eth.getAccounts((err, accs) => {
this.account = accs[0];
});
pero cuando se cambia la cuenta, sigue recogiendo la anterior. Actualizar la página no es un camino a seguir. ¿Alguien se enfrentó a esto y tiene una solución?
Como lo sugieren las preguntas frecuentes de Metamask , esta podría ser una opción:
var account = web3.eth.accounts[0];
var accountInterval = setInterval(function() {
if (web3.eth.accounts[0] !== account) {
account = web3.eth.accounts[0];
updateInterface();
}
}, 100);
En la versión más nueva, metamask expone un evento que podría usarse para detectar si hay un cambio de cuenta según el nuevo documento :
window.ethereum.on('accountsChanged', function (accounts) {
// Time to reload your interface with accounts[0]!
})
De los documentos de MetaMask :
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
})
Como ha señalado @Sr.PEDROethereum.publicConfigStore
, no funcionará en el futuro. De hecho, se eliminará por completo. Vea este comentario de GitHub para más detalles.
También puede evitar que MetaMask vuelva a cargar automáticamente la página web:
window.onbeforeunload = function() {
return "Prevent reload"
}
Esto solo se aplica si usa el window.web3
objeto inyectado por MetaMask, que también está programado para ser eliminado .
Usando web3 versión 1.0.0, el proveedor de metamask expone un evento de 'actualización' que puede escuchar en su publicConfigStore.
web3.currentProvider.publicConfigStore.on('update', callback);
Su devolución de llamada pasará a un objeto con 'selectedAddress' y 'networkVersion' cada vez que esos atributos cambien.
web3.currentProvider._publicConfigStore.on('update', callback);
Pero esto probablemente no sea compatible con metamask en el futuro, por lo que recomendaría usar window.ethereum events medium.com/metamask/…Podría poner en usoEfecto un evento de escucha como el siguiente:
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();
}, []);
Usas chainChanged
event pero tienes que considerar 3 cosas:
Tienes que configurar el oyente globalmente una vez. Ya sea en la barra de navegación, o si usa el proveedor en el proveedor o en next.js en el componente _app
Cuando cambia la cadena, debe volver a cargar la página, recomendado por metamask:
Recomendamos encarecidamente volver a cargar la página en los cambios de cadena, a menos que tenga una buena razón para no hacerlo.
chainChanged
evento, debe eliminar el oyenteaquí hay un ejemplo en 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();
}
Detectar cambio en la cuenta de Metamask
useEffect(() => {
if (window.ethereum) {
window.ethereum.on("accountsChanged", () => {
window.location.reload();
});
}
});
reyhaynes