Когда пользователь переходит на другую учетную запись в метамаске, есть ли способ обнаружить это асинхронно в коде?
сейчас я использую
this.web3.eth.getAccounts((err, accs) => {
this.account = accs[0];
});
но при смене аккаунта все равно подхватывает предыдущий. Обновление страницы — не выход. Может кто сталкивался с этим и есть решение?
Как было предложено в FAQ по Metamask , это может быть вариант:
var account = web3.eth.accounts[0];
var accountInterval = setInterval(function() {
if (web3.eth.accounts[0] !== account) {
account = web3.eth.accounts[0];
updateInterface();
}
}, 100);
В более новой версии метамаска предоставляет событие, которое можно использовать для определения наличия изменения учетной записи в соответствии с новым документом :
window.ethereum.on('accountsChanged', function (accounts) {
// Time to reload your interface with accounts[0]!
})
Из документов 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
})
Как отметил @Sr.PEDRO , ethereum.publicConfigStore
в будущем работать не будет. На самом деле, он будет удален полностью. См. этот комментарий GitHub для деталей.
Вы также можете запретить MetaMask автоматически перезагружать веб-страницу:
window.onbeforeunload = function() {
return "Prevent reload"
}
Это применимо только в том случае, если вы используете window.web3
объект, введенный MetaMask, который также планируется удалить .
Используя web3 версии 1.0.0, поставщик метамаски предоставляет событие «обновление», которое вы можете прослушать в своем общедоступном хранилище ConfigStore.
web3.currentProvider.publicConfigStore.on('update', callback);
Ваш обратный вызов будет передавать объект с «selectedAddress» и «networkVersion» всякий раз, когда эти атрибуты изменяются.
web3.currentProvider._publicConfigStore.on('update', callback);
Но это, вероятно, не будет поддерживаться метамаской в будущем, поэтому я бы рекомендовал использовать события window.ethereum medium.com/metamask/…Вы можете использовать useEffect для listenEvent, как показано ниже:
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();
}, []);
Вы используете chainChanged
событие, но вы должны учитывать 3 вещи:
Вы должны установить слушателя глобально один раз. Либо в навигационной панели, либо при использовании провайдера в провайдере или в next.js в компоненте _app
При изменении цепочки необходимо перезагрузить страницу, рекомендованную метамаской:
Мы настоятельно рекомендуем перезагружать страницу при изменении цепочки, если у вас нет веских причин этого не делать.
chainChanged
события вы должны удалить прослушивательвот пример в реакции/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();
}
Обнаружение изменений в учетной записи Metamask
useEffect(() => {
if (window.ethereum) {
window.ethereum.on("accountsChanged", () => {
window.location.reload();
});
}
});
РейХейнс