Over the last few weeks I’ve been developing an that uses for user management, just like I . Overall, this has been a painless experience, but I have found a few gotchas that I want to share. Hopefully this will save some developers time in the future. Ethereum app metamask said I would 1. Make sure your Ethereum client is up to date My first roadblock came from an error that I discovered in the transaction popup window. For some reason, when I hit “accept” to send my transaction, I was greeted by an endlessly spinning orange circle. Upon expanding the popup’s console, I saw: AssertionError: The field v must have byte length of 1 at FakeTransaction.setter [as v] Hmmm… what does that mean? I pinged Kumavis on slack and he told me it was related to , which was just recently supported. Any older version of testrpc would lack this support, so I upgraded and things worked fine: EIP155 npm i -g ethereumjs-testrpc 2. Reset your network every time you reboot testrpc Another testrpc problem! Once you open up and type in your password, you are connected to that provider. If you switch providers (e.g. from main net to kovan) and refresh the page, it will reset your connection and you will need to enter your password again. metamask But what happens if you reset testrpc? You should still be listening to , but you’ll find that once you refresh the page, things won’t look right. In fact, things will look very, very wrong. localhost:8545 This is because metamask is tracking the block number and when you reboot testrpc that number resets to zero. This is a recipe for disaster. Fortunately, there’s a relatively easy way to avoid this: whenever you reboot testrpc, open up metamask and re-select as your provider. Now refresh your page, click on metamask, and type your password. Voila! You’re connected to the new testrpc instance. localhost:8545 3. Always check for typeof web3 Your app will probably run into a race condition if you don’t properly check for web3. If you try to render your actual app before web3 is injected, everything will break. So I highly recommend something like the following for your app’s landing component (I’m assuming you’re using react): if (typeof web3 == 'undefined') {return (<NoMetamask/>);} else if (web3.version.network == 'loading') {return (<WrongNetwork/>);} else {return (<Landing/>);} Note that checking or or anything equivalent . You need to compare the the injected web3 object. if (web3 !== undefined) if (web3) will not work typeof 4. Pack all your metamask calls into a util file This is may be more of a developer’s preference than the other ones, but I strongly recommend abstracting all your metamask calls into one file because you will find yourself reusing metamask calls a lot. Rather than collapsing a bunch of copypasta versions of the same function later, why don’t you just start with one metamask file in your directory? And don’t worry about not having access to : it’s just a javascript object that you can pass around like a hot potato — it can go anywhere! util web3 // metamask.jsexports.doSomething = function(web3, param) { // I have access to web3, even though I'm not in the DOM!const user = web3.eth.accounts[0]; // Do stuff} 5. Don’t wait to advance the UX! I can’t believe I still see this in production. As an ecosystem, we’ve gotten better about this, but I want to extinguish it like smallpox. Please, people. has a ~15s block time. That may seem fast in the blockchain world, but it is a lifetime in the world of fast, reactive web applications. And if you’re using testrpc for development, you will probably find yourself forgetting how slow blockchains are. . Say it out loud every day: “Waiting for Ethereum transactions is a bad user experience.” Ethereum Do not forget how slow blockchains are Please please don’t make your users sit around twiddling their thumbs after submitting a transaction. It’s so easy to handle a callback (which is a transaction hash) by dispatching that hash to a queue and periodically checking for a receipt on it. Consider the following: please sendTransaction // metamask.jsexports.doSomething = function(web3, param) {const user = web3.eth.accounts[0];web3.eth.getTransactionCount(owner, (err, nonce) => {// Form your tx object...web3.eth.sendTransaction(obj, (err, res) => {if (err) { cb(err); }else { cb(null, res); }})} // component.jsxcallMetamask() {metamask.doSomething(web3, 'something', (err, result) => {if (err) { console.log('Error doing something.') }else { dispatch({ type: 'QUEUE_TXHASH', result: result }) }})} With that hash in your queue, you can display it in the toolbar and the user can happily continue with your app while waiting for the transaction to go through. If it really is critical that the transaction is processed before advancing your UI (and you can honestly tell me this is the best UX flow you can think of), please give your users something exciting to look at — maybe the Ethereum whitepaper or this cat with a shower cap . 6. Yes, it’s really this easy Three weeks of heavy metamask development and these are really the only gripes I can come up with. Really, metamask is marvelous and easy to set up. Generally speaking, you should be good to go if you follow the rules/suggestions outlined above and properly reference the (remember to always use asynchronous calls — synchronous ones won’t work in metamask). web3 API If you have a question, but it wasn’t answered here, I recommend checking out the . Ethereum stack exchange — If you like my articles, or check out my company, , because we do awesome stuff. follow me on twitter ConsenSys And, as always, there is an open invitation to join the and help us conquer the world. Ethereum community