How to use IPFS in your Dapp?

Using the interplanetary file system in your frontend and contracts

You may have heard about IPFS before, the Interplanetary File System. The concept has existed for quite some time now, but with IPFS you'll get a more reliable data storage, thanks to their internal use of blockchain technology. Filecoin is a new system that is incentivizing storage for IPFS nodes.

If you are participating in the HackFS, a current hackathon sponsored by ETHGlobal and Protocol Labs (the makers of IPFS), or not, knowing IPFS will be a useful skill for your Dapp developments.

Can't you just store all data in the Ethereum blockchain directly?

Excellent question and in theory yes. But remember that data in the Ethereum blockchain is shared between every single node. This is extremely inefficient for large sets of data. So really the only solution is to have only some nodes storing the data. That's exactly what IPFS is doing. Files are randomly allocated to a subset of nodes.

How does it work?

The whole system is quite complex and even the 11-pages whitepaper doesn't cover everything in detail. The core principle is a DHT (distributed hash table). It's using Kademlia to distribute files to nodes. We won't go into details about this here, but read the great article that I linked. In short, you want files to be distributed somewhat randomly, but with short paths for every file between the nodes (to reduce latency), while being DOS-resistant. And that's what Kademlia is achieving.

IPFS builds several services on top. The upcoming Filecoin will introduce a way to pay IPFS nodes for storing files. Currently IPFS is still free to use, but also less reliable, see the next question. You'll further get an IPNS naming system, a unique hash per file, file permissions and Bittorrent-like features.

Is it secure and reliable?

In short no, but it depends what we mean with 'reliable'. You cannot store a file in IPFS, then try to read it two years later and still expect it to be there. Nodes will garbage collect unused files. But it's very reliable for frequently used files. And is it secure? Data is all public, so if you are concerned about privacy, you need to encrypt the files.

Adding IPFS to Solidity contracts

The Solidity part will be very simple. We will only store the IPFS hash of users inside our contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.11;

contract IpfsStorage {
    mapping (address => string) public userFiles;

    function setFile(string memory file) external {
        userFiles[msg.sender] = file;
    }
}

Compile and deploy the contract, or if you're lazy use the one I deployed in the Kovan network: https://kovan.etherscan.io/address/0x8c700a5f78d61e350e7bd7d85a6e688bbbb8a7af.

Now let's go ahead and build the frontend. We will use the create-eth-app as starting point. Install it using yarn create eth-app my-eth-app. Next we can add IPFS to it:

yarn workspace @project/react-app add ipfs

The full Javascript IPFS documentation is available here. Be aware that it's still very much work in progress.

Okay, now let's initialize IPFS. It creates and connects an IPFS node that we can use to read and upload files.

import IPFS from "ipfs";

async function initIpfs() {
  node = await IPFS.create();
  const version = await node.version();
  console.log("IPFS Node Version:", version.version);
}

Now that we have the IPFS node, let's add a function to read the current file from the contract.

We use the ethers.js library with our current address.

async function readCurrentUserFile() {
  const result = await ipfsContract.userFiles(
    defaultProvider.getSigner().getAddress()
  );

  return result;
}


Let's upload a file to IPFS and store it in our contract.

  • uploadFile: This will be the function to take a file and upload it to IPFS using our IPFS node.
  • setFile: After a successful upload, we can store the IPFS hash inside our contract using this function.


async function setFile(hash) {
    const ipfsWithSigner = ipfsContract.connect(defaultProvider.getSigner());
    await ipfsWithSigner.setFile(hash);
    setIpfsHash(hash);
}

async function uploadFile(file) {
    const files = [{ path: file.name + file.path, content: file }];

    for await (const result of node.add(files)) {
        await setFile(result.cid.string);
    }
}

Now let's add a nice drag zone for the user to upload a file in the browser. And put it all together.

Please check out the live demo and repository for the full example.

Example IPFS App

Some alternatives

  • Swarm: Very similar to IPFS, you can use it the same way. It has a bigger focus on Ethereum relying on smart contract incentives. However, it's not quite as matured yet.
  • SKALE Filestorage: Side chains are effectively using a subset of Ethereum nodes allowing for more data to be stored inside them. Skale made use of that and introduced their own file-storage sytem. SKALE was launched to mainet only a few weeks ago, so you can go ahead and try it.

Markus Waas

Solidity Developer

More great blog posts from Markus Waas

© 2024 Solidity Dev Studio. All rights reserved.

This website is powered by Scrivito, the next generation React CMS.