Storage DApp using Solidity and IPFS

Faucet Consumer
ITNEXT
Published in
6 min readApr 14, 2022

--

Imagine a decentralized storage application where we share our disks to each other without any server in the middle. Imagine now, that each file in this decentralized application can be easily shared and found with a simple hash. Sounds promising right? well, that’s a project in progress at this very moment and I’m going to explain how it works.

Photo by Shubham Dhage on Unsplash

Introduction

TL;DR: You can access the code from the Github repository (and leave a star 😉).

All started with a single problem that came out when I was trying to figure out how to store large files in a dApp without loosing the definition of dApp. If the app stores files in a centralized storage service then the application is not decentralized anymore by definition.

So after a little research I found a mind blowing solution: IPFS 🤯.

IPFS in a paragraph

IPFS is a peer-to-peer hypermedia protocol, which means a protocol to share media across computers. By using this protocol you can easily build p2p networks sharing information across nodes (where a node can be your very computer).

Fortunately, there exists a high level Javascript package for accessing and interacting with this protocol, which means that you can build a Frontend application that uses your computer as a node for sharing and accessing files across the network. I guess you have a clue of how this app is going to work 😉.

But then the problem is about how to organize files, users, reference the files metadata in a decentralized way and creating universally accesible information. Here is where blockchain and smart contracts come to help us.

Smart Contract

A smart contract is a simple program identified with an address that runs transactions in a blockchain network. I am not going to dig too deep in this concept, but in short, we can use a smart contract as a tiny database due to their inmutable nature.

Building the application

Creating the Smart Contract with Solidity

The first part consist on creating a smart contract on Solidity language for storing information of the files uploaded to the app. We are going to save general information about them such as filename, type, size, etc.

As you can see the code is pretty concise and direct, we only have three variables, one function, one event and one struct that represents a file in the system. The code is self-explanatory but I added some comments for better understanding.

Smart Contract deployment using Truffle and Ganache

The most programmer-friendly way to debug and test smart contracts, is by using a local development environment such as Truffle to easily create good pipeline for our project.

Another very important tool for debugging smart contracts is Ganache (Part of the Truffle Suite), that is a local Blockchain that you can run to deploy and debug your contracts, they provide a set of accounts and configurations out of the box with enough ether to do pretty much anything you want in your projects.

So the next step is to set up truffle on our project, for doing so we can simpy install it with npm.

npm install -g truffle

Then you can create your frontend project with any framework/library you want, in my case is next js. Once you created it you can initialize a truffle environment on it positioning the console on the root folder of the project and typing:

truffle init

This will create a basic configuration for your project, among other files will create a truffle-config.js, this file will be especially important during the project.

You can check the project configuration here.

For actually setting our smart contract up in the project, we should run a migration, you can do it following these steps.

Testing the contract

This part is one of the most important practices in Smart Contract development, a Smart Contract should be tested as well as possible in order to deploy it confidently. Since the nature of Smart Contracts is inmutable, the cost of deploying a buggy contract is very high.

For testing the contract, Truffle comes with mocha and chai, which makes it much easier the testing.

Let’s see some basic examples of smart contract testing, you can see the full suit of test in this testing file.

Testing contract correctly deployed:

Testing uploading a valid file:

Authenticating with Metamask

Once we finished the basic configuration for the app, we can start working on users authentication with Metamask, for doing so, we have a js API to connect the application with the extension without any library required.

In order to create a smooth user experience we can create one method for connecting automatically when there are existing accounts.

And another method for forcing the request, opening up a Metamask pop up for authentication.

Connect Frontend with Smart Contract

At this stage, we already have a frontend application connected with Metamask extension and a smart contract running with Ganache, now we need to find a way to interact with the Solidity contract as an API.

For this, we will need some library such as Web3.js or Ethers.js. In my case I choose Web3.js.

Importing web3 and creating the contract object

Note: there is a special file called ‘Persssist’, this is the abi. A representation of the smart contract in JSON format that works as the interface between Javascript and Solidity.

Connecting Smart Contract with IPFS

Once we have the contract object, we can start using IPFS to upload the files. The trick here is that we can reference a file in IPFS using the unique path that works as an Id for each file created in the IPFS filesystem.

Each file in the smart contract state will reference a path in the IPFS filesystem, creating this way a reliable connection between the contract and the storage system.

The only element in the middle is the frontend application running on the local browser for each user, creating this way a decentralized storage application.

Uploading a file

This task is composed by 2 steps:

  1. Upload the file to IPFS obtaining its unique path.
  2. Create the file record in the smart contract with the result.

First we create the IPFS connection, this is not necessary each time the user uploads a file, but I did it in this function just to make it clearer.

Then we upload the file just using the buffer and the filetype, and as a result we obtain the file path on the IPFS filesystem.

The second step is to actually store the file information in the smart contract to easily download the file in the future.

Fetching and downloading files

For this step, we are going to do the inverse process. We need to fetch the files stored in the smart contract and then, using the unique path, download the files from the IPFS filesystem.

In order to create a user friendly interaction, we can fetch all the files and only download the ones selected by the user.

After the user selects a file for download, we can start the downloading process. This is one of the most difficult parts, because IPFS only downloads the file in compressed format, so we need to do some kind of workaround to get the right file format, in this case by adding the untar library.

Conclusion

The decentralized applications are a great opportunity to empower the internet users and developers from web 2.0. There is no need to have something in the middle of two people to create a trusted and fluid interaction, and this is just one of the infinite examples of the decentralized internet that (I hope) we are going to have in the near future.

If you are here I’m sure you love programming as I do, so I strongly recommend you to check out the code and, if you dare to, to contribute and make something bigger and better from it. Thanks a lot for reading!

Note: You can access the code from the Github repository (and leave a star 😉).

--

--

I just enjoy building non-tangible things, and writing about it