Kontext: Ich möchte Blockies verwenden, um ein Identicon auf der Seite zu rendern, ich bekomme den defaultAccount von web3, dazu muss der Benutzer mit einer ausgewählten Adresse aus seinem Wallet bei Metamask angemeldet sein.
Das Problem: Die Web-App scheint das web3-Objekt beim Ladeereignis der Seite nicht zu erkennen, was der empfohlene Ort ist, um es zu erkennen.
Der folgende Code ist inspiriert von Empfehlungen unter:
https://github.com/MetaMask/metamask-plugin/issues/1158
Ich habe ständig intermittierendes Verhalten, manchmal ist web3 da und manchmal nicht, die einzige Lösung, die mir einfällt, ist, einen Timer zu haben, aber das scheint mir etwas zu einfach zu sein, ich würde etwas Eleganteres bevorzugen.
Frage: Gibt es eine bessere Lösung, um das defaultAccount von web3 zu erkennen, wenn die Seite geladen wird?
function startApp() {
GenerateIdenticon();
}
window.addEventListener('load', function () {
// Checking if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined') {
// Use Mist/MetaMask's provider
window.web3 = new Web3(web3.currentProvider);
if (web3.currentProvider.isMetaMask === true) {
if (typeof web3.eth.defaultAccount === 'undefined') {
document.body.innerHTML = '<body><h1>Oops! Your browser does not support Ethereum Ðapps.</h1></body>';
}
else {
startApp();
}
}
else {
alert('No web3? Please use google chrome and metamask plugin to enter this Dapp!', null, null);
// fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}
Die eine Methode, die zuverlässiger ist als das In-Page- accounts
Array, ist web3.eth.getAccounts(accounts => console.log(accounts[0]))
.
Dadurch wird das Konten-Array asynchron angefordert und zurückgerufen, wenn es verfügbar ist.
Folgendes verwende ich in meinem Dapp. Es scheint ziemlich gut zu funktionieren.
function getWeb3(callback) {
if (typeof window.web3 === 'undefined') {
// no web3, use fallback
console.error("Please use a web3 browser");
} else {
// window.web3 == web3 most of the time. Don't override the provided,
// web3, just wrap it in your Web3.
var myWeb3 = new Web3(window.web3.currentProvider);
// the default account doesn't seem to be persisted, copy it to our
// new instance
myWeb3.eth.defaultAccount = window.web3.eth.defaultAccount;
callback(myWeb3);
}
}
So verwendet:
function startApp(web3) {
// ...
}
window.addEventListener('load', function() {
getWeb3(startApp);
});
Der Hauptunterschied besteht darin, dass ich die defaultAccount
von der ursprünglichen window.web3
Instanz kopiere. Sie werden feststellen, dass kein MetaMask-spezifischer Code web3.eth.defaultAccount
Teil der Javascript-API ist. MetaMask scheint sich zu füllen, defaultAccount
sobald Sie Ihre Brieftasche entsperren.
Die Überprüfung web3.eth.accounts[0]
alle 100 Millisekunden ist in einigen Fällen viel schneller als web3.eth.getAccounts()
:
// Option 1:
web3.eth.getAccounts(console.log);
// Option 2:
(function loop() {
if (web3.eth.accounts[0]) {
console.log(web3.eth.accounts[0]);
} else {
setTimeout(loop, 100);
}
}());
Bei Verwendung eines Proxys Option 2
war es bei mir bis zu 35 Sekunden (!) schneller als Option 1
.
In Bezug auf web3.eth.defaultAccount
sagt die MetaMask-Dokumentation , dass sie nicht verwendet werden sollte, um zu erkennen, welches Konto derzeit vom Benutzer ausgewählt ist.
Übrigens, laut MetaMask-Dokumentation müssen Sie setTimeout
/ trotzdem verwenden, um auf ausgewähltesetInterval
Kontoänderungen zu hören :
var account = web3.eth.accounts[0];
setInterval(function () {
if (web3.eth.accounts[0] !== account) {
account = web3.eth.accounts[0];
updateInterface();
}
}, 100);
Ein paar Dinge, die mir bei der Verwendung von MetaMask aufgefallen sind.
defaultAccount
ist nicht immer besetzt. Es ist sicherer, es web3.eth.accounts[0]
als Überprüfung zu verwenden, um festzustellen, ob ein Konto ausgewählt ist oder nicht. Sie müssen diesen Wert regelmäßig abrufen, wenn Sie wissen möchten, ob sich das ausgewählte Konto ebenfalls ändert.
Das load
Ereignis scheint auch in einigen meiner Erfahrungen nicht immer zuverlässig zu sein. Ich habe das schließlich gelöst, aber ich habe meinen Code nicht zur Hand, um zu demonstrieren, wie. Ich werde diesen Beitrag später damit aktualisieren, wenn das accounts[0]
Stück nicht ausreicht.
Wenn Sie React verwenden und auf dieses Problem stoßen, müssen Sie nur Folgendes tun:
1. web3 installieren:
npm install web3 --save
2. Überprüfen Sie, ob MetaMask vorhanden ist:
import 'Web3' from 'web3';
// ...
componentDidMount() {
// Check if Web3 has been injected by the browser (MetaMask).
// (since 'web3' is global, we need to use 'window')
if (window.web3 && window.web3.currentProvider.isMetaMask) {
window.web3.eth.getAccounts((error, accounts) => {
// Do whatever you need to.
this.setState({wallet: accounts[0]});
});
} else {
console.log('MetaMask account not detected :(');
}
}
null
wenn Sie Metamask entsperrt haben?Kein schamloser Stecker.
Kürzlich angefangen zu verwenden: https://www.blocknative.com/
Sie bieten gute Onboarding-Muster mit MetaMask.
Jörg Alvarado
Danyal Aytekin
web3.eth.getAccounts().then(...)
.Jobsamuel
getAccounts
Methode zwei (2) Argumente zurückgibt undaccounts
das zweite ist. Mit anderen Worten:web3.eth.getAccounts((error, accounts) => console.log(accounts[0]))
.Eduard Pereira
DanF
Wjachaslaw Gerchicov