As we mentioned in our last post, Testing a DApp from First Principles, and as described in the original tutorial, we are using mist (0.8.10) as our client and geth (1.6.1) as our "back-end" for development purposes.
Mist normally connects to geth via inter-process communication (IPC) using a file on disk.
Mist <--(IPC)--> Geth
In a web browser, you are without the web3.js library and the IPC geth connection that Mist facilitates.
Browser <--(???)--> Geth
But what if we do want to run our DApp in a normal web browser? It would seem all that is stopping us is web3.js and a geth connection. But before we attemp such a feat, why might we want to run our DApp in a normal web browser? And conversely why does a DApp browser exist?
One part of the Mist browser is the web3.js functionality for accessing the blockchain. However, this is more of a convenience than a core piece of functionality. Anyone who wants to provide that capability can simply load the library. In fact, being chained to the Mist-provided web3 could be a liability for the zealous DApp developer who wants to use the latest version. And the Mist developers seem to agree: "From this version on Mist will not ship its own web3.js instance anymore."
The main reason that you have a special wallet-browser is to manage your Ethereum accounts. It provides some convenient UI components that will automagically prompt you to authorise transactions, create accounts etc. By default it also connects to geth at a standard location on startup.
So why develop in a normal browser?
- You may only need read access and not want to write or modify the blockchain
- You want to make your application as widely accessible as possible
- You hate security
- You want to control the UI around security
- You are running a browser on a different host than geth
- Because you can
Geth provides a remote procedure call (RPC) interface for access over the network. That is what we will use to connect our normal web browser.
Browser <--(RPC)--> Geth
To get things running we will need to do two things:
- Load and initialise web3.js
- Turn on RPC with Cross-origin resource sharing (CORS) configured correctly
1. Loading web3.js
If you run your Mist application in Chrome without any changes you will get the error:
Uncaught ReferenceError: web3 is not defined
You can install web3 as a package with Node, Meteor, Bower, or Component. The libary and documentation are at:
Include the file or load it with your favourite loader.
You will also need to initialise the library as follows. The port should match the port on which we start geth RPC which by default is 8545.
var Web3 = require('web3'); web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
2. Starting RPC
If you have correctly initialised web3 but do not have RPC running, or it is inaccessible from the application, you will get the following error in your browser:
Uncaught Error: CONNECTION ERROR: Couldn't connect to node http://localhost:8545.
By the documentation, you can start RPC and specify the CORS domain through the geth command line. It appears, however, that the RPC command line flags are incompatible with dev mode which we are using for development.
First create a file start-rpc.js containing the following:
admin.startRPC('localhost', 8545, 'http://localhost:8080', 'web3,eth,personal');
The parameters are:
admin.startRPC( host, portNumber, corsheader, modules )
host and portNumber are the host and port respectively that you want to run the geth RPC server on.
For corsheader, note that you have to specify the host and port precisely as above 'http://localhost:8080' with no trailing slash OR, use the wildcard '*' for this to work. I.e.:
admin.startRPC('localhost', 8545, '*', 'web3,eth,personal');
For security reasons, only load the modules you need. In this case web3, eth, and personal (which we can use to manage accounts in place of Mist's handling in the aforementioned tutorial).
geth --dev js start-rpc.js
If you failed to correctly configure CORS, you will get an error such as the following:
XMLHttpRequest cannot load http://localhost:8545/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
Otherwise with any luck you will be running web3 from a normal web page.
The second CORS example suggested a wildcard access list. That should not be done in production since it could give a malicious website the chance to access one of your user's accounts. But if you are having trouble getting things working, it is a reasonable configuration to test things out during development.
The other points on security using geth via RPC are more nuanced. On a permissioned chain, or when using a specially controlled environment, you may not have the same need for end users to be managing their identities or transactions directly. Or you may be delegating that to another part of the system.
If you are using the public Ethereum blockchain, especially if you are dealing with individuals' Ether in a financial way, you need to be very careful about what you do with those individuals' accounts. Recommendations about storing Ether is an ongoing discussion with remaining usability challenges.
We hope you found this useful. We are looking into the command line constraints that caused us to do the RPC workaround as well as checking out the latest version of Mist 0.9.0. In the meantime, happy coding and see you next time.