Storing the Auction DApp on Swarm
We introduced Swarm in Swarm, earlier in this chapter. Our Auction DApp already uses Swarm to store the icon image for each auction. This is a much more efficient solution than attempting to store data on Ethereum, which is expensive. It is also a lot more resilient than if these images were stored in a centralized service like a web server or file server.
But we can take things one step further. We can store the entire frontend of the DApp itself in Swarm and run it from a Swarm node directly, instead of running a web server.
Preparing Swarm
To get started, you need to install Swarm and initialize your Swarm node. Swarm is part of the Ethereum Foundation’s Go-Ethereum suite of tools. Refer to the instructions for installing Go-Ethereum in [go_ethereum_geth], or to install a Swarm binary release, follow the instructions in the Swarm documentation.
Once you have installed Swarm, you can check that it is working correctly by running it with the version command:
$ swarm version
Version: 0.3
Git Commit: 37685930d953bcbe023f9bc65b135a8d8b8f1488
Go Version: go1.10.1
OS: linux
To start running Swarm, you must tell it how to connect to an instance of Geth, to access the JSON-RPC API. Get it started by following the instructions in the Getting Started guide.
When you start Swarm, you should see something like this:
Maximum peer count ETH=25 LES=0 total=25
Starting peer-to-peer node instance=swarm/v0.3.1-225171a4/linux...
connecting to ENS API url=http://127.0.0.1:8545
swarm[5955]: [189B blob data]
Starting P2P networking
UDP listener up self=enode://f50c8e19ff841bcd5ce7d2d...
Updated bzz local addr oaddr=9c40be8b83e648d50f40ad3... uaddr=e
Starting Swarm service
9c40be8b hive starting
detected an existing store. trying to load peers
hive 9c40be8b: peers loaded
Swarm network started on bzz address: 9c40be8b83e648d50f40ad3d35f...
Pss started
Streamer started
IPC endpoint opened url=/home/ubuntu/.ethereum/bzzd.ipc
RLPx listener up self=enode://f50c8e19ff841bcd5ce7d2d...
You can confirm that your Swarm node is running correctly by connecting to the local Swarm gateway web interface: http://localhost:8500.
You should see a screen like the one in Swarm gateway on localhost and be able to query any Swarm hash or ENS name.
Figure 4. Swarm gateway on localhost
Uploading Files to Swarm
Once you have your local Swarm node and gateway running, you can upload to Swarm and the files will be accessible on any Swarm node, simply by reference to the file hash.
Let’s test this by uploading a file:
$ swarm up code/auction_dapp/README.md
ec13042c83ffc2fb5cb0aa8c53f770d36c9b3b35d0468a0c0a77c97016bb8d7c
Swarm has uploaded the README.md file and returned a hash that you can use to access the file from any Swarm node. For example, you could use the public Swarm gateway.
While uploading one file is relatively straightforward, it is a bit more complex to upload an entire DApp frontend. That’s because the various DApp resources (HTML, CSS, JavaScript, libraries, etc.) have embedded references to each other. Normally, a web server translates URLs to local files and serves the correct resources. We can achieve the same for Swarm by packaging our DApp.
In the Auction DApp, there’s a script for packaging all the resources:
$ cd code/auction_dapp/frontend
$ npm run build
> frontend@1.0.0 build /home/aantonop/Dev/ethereumbook/code/auction_dapp/frontend
> node build/build.js
Hash: 9ee134d8db3c44dd574d
Version: webpack 3.10.0
Time: 25665ms
Asset Size
static/js/vendor.77913f316aaf102cec11.js 1.25 MB
static/js/app.5396ead17892922422d4.js 502 kB
static/js/manifest.87447dd4f5e60a5f9652.js 1.54 kB
static/css/app.0e50d6a1d2b1ed4daa03d306ced779cc.css 1.13 kB
static/css/app.0e50d6a1d2b1ed4daa03d306ced779cc.css.map 2.54 kB
static/js/vendor.77913f316aaf102cec11.js.map 4.74 MB
static/js/app.5396ead17892922422d4.js.map 893 kB
static/js/manifest.87447dd4f5e60a5f9652.js.map 7.86 kB
index.html 1.15 kB
Build complete.
The result of this command will be a new directory, code/auction_dapp/frontend/dist, that contains the entire Auction DApp frontend, packed together:
dist/
|-- index.html
`-- static
|-- css
| |-- app.0e50d6a1d2b1ed4daa03d306ced779cc.css
| `-- app.0e50d6a1d2b1ed4daa03d306ced779cc.css.map
`-- js
|-- app.5396ead17892922422d4.js
|-- app.5396ead17892922422d4.js.map
|-- manifest.87447dd4f5e60a5f9652.js
|-- manifest.87447dd4f5e60a5f9652.js.map
|-- vendor.77913f316aaf102cec11.js
`-- vendor.77913f316aaf102cec11.js.map
Now you can upload the entire DApp to Swarm, by using the up command and the —recursive option. Here, we also tell Swarm that index.html is the defaultpath for loading this DApp:
$ swarm --bzzapi http://localhost:8500 --recursive \
--defaultpath dist/index.html up dist/
ab164cf37dc10647e43a233486cdeffa8334b026e32a480dd9cbd020c12d4581
Now, our entire Auction DApp is hosted on Swarm and accessible by the Swarm URL:
- bzz://ab164cf37dc10647e43a233486cdeffa8334b026e32a480dd9cbd020c12d4581
We’ve made some progress in decentralizing our DApp, but we’ve made it harder to use. A URL like that is much less user-friendly than a nice name like auction_dapp.com. Are we forced to sacrifice usability in order to gain decentralization? Not necessarily. In the next section we will examine Ethereum’s name service, which allows us to use easy-to-read names but still preserves the decentralized nature of our application.