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:

  1. $ swarm version
  2. Version: 0.3
  3. Git Commit: 37685930d953bcbe023f9bc65b135a8d8b8f1488
  4. Go Version: go1.10.1
  5. 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:

  1. Maximum peer count ETH=25 LES=0 total=25
  2. Starting peer-to-peer node instance=swarm/v0.3.1-225171a4/linux...
  3. connecting to ENS API url=http://127.0.0.1:8545
  4. swarm[5955]: [189B blob data]
  5. Starting P2P networking
  6. UDP listener up self=enode://f50c8e19ff841bcd5ce7d2d...
  7. Updated bzz local addr oaddr=9c40be8b83e648d50f40ad3... uaddr=e
  8. Starting Swarm service
  9. 9c40be8b hive starting
  10. detected an existing store. trying to load peers
  11. hive 9c40be8b: peers loaded
  12. Swarm network started on bzz address: 9c40be8b83e648d50f40ad3d35f...
  13. Pss started
  14. Streamer started
  15. IPC endpoint opened url=/home/ubuntu/.ethereum/bzzd.ipc
  16. 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.

Swarm gateway on localhost

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:

  1. $ swarm up code/auction_dapp/README.md
  2. 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:

  1. $ cd code/auction_dapp/frontend
  2. $ npm run build
  3. > frontend@1.0.0 build /home/aantonop/Dev/ethereumbook/code/auction_dapp/frontend
  4. > node build/build.js
  5. Hash: 9ee134d8db3c44dd574d
  6. Version: webpack 3.10.0
  7. Time: 25665ms
  8. Asset Size
  9. static/js/vendor.77913f316aaf102cec11.js 1.25 MB
  10. static/js/app.5396ead17892922422d4.js 502 kB
  11. static/js/manifest.87447dd4f5e60a5f9652.js 1.54 kB
  12. static/css/app.0e50d6a1d2b1ed4daa03d306ced779cc.css 1.13 kB
  13. static/css/app.0e50d6a1d2b1ed4daa03d306ced779cc.css.map 2.54 kB
  14. static/js/vendor.77913f316aaf102cec11.js.map 4.74 MB
  15. static/js/app.5396ead17892922422d4.js.map 893 kB
  16. static/js/manifest.87447dd4f5e60a5f9652.js.map 7.86 kB
  17. index.html 1.15 kB
  18. 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:

  1. dist/
  2. |-- index.html
  3. `-- static
  4. |-- css
  5. | |-- app.0e50d6a1d2b1ed4daa03d306ced779cc.css
  6. | `-- app.0e50d6a1d2b1ed4daa03d306ced779cc.css.map
  7. `-- js
  8. |-- app.5396ead17892922422d4.js
  9. |-- app.5396ead17892922422d4.js.map
  10. |-- manifest.87447dd4f5e60a5f9652.js
  11. |-- manifest.87447dd4f5e60a5f9652.js.map
  12. |-- vendor.77913f316aaf102cec11.js
  13. `-- 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:

  1. $ swarm --bzzapi http://localhost:8500 --recursive \
  2. --defaultpath dist/index.html up dist/
  3. 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.