Article original : Hands On: Get Started With Infura and the IPFS on Ethereum

Par Niharika Singh

Pourquoi Infura ?

Il y a beaucoup de points douloureux rencontrés par la blockchain qui peuvent être résolus par Infura et/ou le InterPlanetary File System (IPFS), dans une certaine mesure. Voici les principaux défis :

  1. Il est coûteux de stocker des données sur la blockchain Ethereum
  2. Il est difficile de configurer un client Ethereum geth
  3. Il est difficile de mettre à l'échelle l'infrastructure

Si vous utilisez Infura, l'accès au réseau Ethereum et à l'IPFS devient beaucoup plus rapide. Cela ne prend plus des heures pour synchroniser le client geth qui utilise une énorme quantité de mémoire et de bande passante pendant que toute la blockchain est téléchargée.

Voici quelques autres avantages qui viennent avec l'utilisation d'Infura :

  • De grandes quantités de données peuvent être stockées sur l'IPFS, et seul le hash du fichier peut être stocké sur Ethereum.
  • Infura fournit des API sécurisées, fiables, scalables et faciles à utiliser pour accéder au réseau Ethereum et à l'IPFS. Les développeurs n'ont pas à se soucier de l'infrastructure d'un nœud Ethereum ou d'un nœud IPFS. Cela est pris en charge par Infura.
  • Infura fournit des endpoints publics avec TLS activé.
  • Le code est portable sur l'interface d'Ethereum en utilisant JSON RPC, Web3.
  • Infura est pratiquement le couteau suisse du développeur, et sauve également l'équipe de déploiement de l'enfer des problèmes de scalabilité.

Image

Image

  • Et enfin, Infura est de confiance :

Image

Description de la dApp

Notre dApp prendra un fichier en entrée d'un utilisateur et le téléchargera sur l'IPFS en invoquant un contrat Ethereum. Le hash du fichier sera stocké sur Ethereum.

Voici le processus que nous allons suivre :

  1. Prendre un fichier en entrée
  2. Convertir le fichier en buffer
  3. Télécharger le buffer sur IPFS
  4. Stocker le hash du fichier retourné par IPFS
  5. Obtenir l'adresse Ethereum de l'utilisateur via Metamask
  6. L'utilisateur confirme la transaction vers Ethereum via Metamask
  7. Le hash IPFS est écrit sur Ethereum

Image Architecture de la dApp

Pile technologique impliquée

  • React — Bibliothèque front-end
  • Solidity — Le langage utilisé pour construire des contrats intelligents qui s'exécutent sur Ethereum
  • IPFS — Stockage décentralisé
  • Infura — Accès API au réseau Ethereum et IPFS

Codons !

Assurez-vous d'avoir déjà téléchargé Metamask. Si ce n'est pas le cas, téléchargez-le depuis ici.

Assurez-vous également que votre Node et NPM sont à jour.

Installez les dépendances suivantes :

$ npm i -g create-react-app
$ npm install react-bootstrap
$ npm install fs-extra
$ npm install ipfs-api
$ npm install web3

Une fois terminé, exécutez la commande suivante sur votre CLI pour créer un projet React exemple. Je vais nommer mon projet ipfs.

$ create-react-app ipfs

Déployez le contrat intelligent sur le réseau de test Ropsten

Assurez-vous d'être sur le réseau de test Ropsten dans Metamask.

Pour déployer le contrat intelligent, nous avons besoin d'ether. Pour obtenir de l'ether pour le réseau de test Ropsten, allez sur https://faucet.metamask.io/.

Pour déployer le contrat intelligent, allez sur https://remix.ethereum.org.

pragma solidity ^0.4.17;
contract Contract {
  string ipfsHash;
  function setHash(string x) public {
    ipfsHash = x;
  }
  function getHash() public view returns (string x) {
    return ipfsHash;
  }
}

Image

Enregistrez l'adresse du contrat intelligent. La mienne est : 0x610DD75057738B73e3F17A9D607dB16A44f962F1

Enregistrez également l'Interface Binaire d'Application (ABI) en JSON. Elle peut être trouvée dans l'onglet "compile", sous "details".

La mienne est la suivante :

[ {
  "constant": false,
  "inputs": [
    {
      "name": "x",
      "type": "string"
    }
  ],
  "name": "sendHash",
  "outputs": [],
  "payable": false,
  "stateMutability": "nonpayable",
  "type": "function"
},
{
  "constant": true,
  "inputs": [],
  "name": "getHash",
  "outputs": [
    {
      "name": "x",
      "type": "string"
    }
  ],
  "payable": false,
  "stateMutability": "view",
  "type": "function"
}
]

Dans le répertoire "ipfs/src", créez les fichiers suivants : web3.js, ipfs.js, et storehash.js.

Fichier 1 — Web3.js

import Web3 from 'web3';
const web3 = new Web3(window.web3.currentProvider);
export default web3;

Fichier 2 — Storehash.js

import web3 from './web3';
//Votre adresse de contrat
const address = '0x610dd75057738b73e3f17a9d607db16a44f962f1';
//Votre ABI de contrat
const abi = [
  {
    "constant": false,
    "inputs": [
      {
        "name": "x",
        "type": "string"
      }
    ],
    "name": "sendHash",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "getHash",
    "outputs": [
      {
        "name": "x",
        "type": "string"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  }
]
export default new web3.eth.Contract(abi, address);

Fichier 3 — Ipfs.js

const IPFS = require('ipfs-api');
const ipfs = new IPFS({ host: 'ipfs.infura.io', port: 5001, protocol: 'https' });
export default ipfs;

Édition — Index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import 'bootstrap/dist/css/bootstrap.min.css';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();

Fichier 4 — App.js

import React, { Component } from 'react';
import web3 from './web3';
import ipfs from './ipfs';
import storehash from './storehash';
import { Button } from 'reactstrap';
class App extends Component {
state = {
  ipfsHash:null,
  buffer:'',
  ethAddress:'',
  transactionHash:'',
  txReceipt: ''
};
//Prendre le fichier en entrée de l'utilisateur
captureFile =(event) => {
  event.stopPropagation()
  event.preventDefault()
  const file = event.target.files[0]
  let reader = new window.FileReader()
  reader.readAsArrayBuffer(file)
  reader.onloadend = () => this.convertToBuffer(reader)
};
//Convertir le fichier en buffer pour le stocker sur IPFS
convertToBuffer = async(reader) => {
  //le fichier est converti en buffer pour le téléchargement sur IPFS
  const buffer = await Buffer.from(reader.result);
  //définir ce buffer en utilisant la syntaxe es6
  this.setState({buffer});
};
//Fonction asynchrone ES6
onClick = async () => {
  try{
    this.setState({blockNumber:"waiting.."});
    this.setState({gasUsed:"waiting..."});

    await web3.eth.getTransactionReceipt(this.state.transactionHash, (err, txReceipt)=>{
      console.log(err,txReceipt);
      this.setState({txReceipt});
    });
  }catch(error){
    console.log(error);
  }
}
onSubmit = async (event) => {
  event.preventDefault();
//apporter l'adresse du compte metamask de l'utilisateur
const accounts = await web3.eth.getAccounts();
//obtenir l'adresse du contrat depuis storehash.js
const ethAddress= await storehash.options.address;
this.setState({ethAddress});
//sauvegarder le document sur IPFS, retourner son hash#, et définir le hash# à l'état
await ipfs.add(this.state.buffer, (err, ipfsHash) => {
  console.log(err,ipfsHash);
  //définir l'état en définissant ipfsHash à ipfsHash[0].hash
  this.setState({ ipfsHash:ipfsHash[0].hash });
  //appeler la méthode du contrat Ethereum "sendHash" et .send le hash IPFS au contrat ethereum
  //retourner le hash de transaction du contrat ethereum
  storehash.methods.sendHash(this.state.ipfsHash).send({
    from: accounts[0]
  }, (error, transactionHash) => {
    console.log(transactionHash);
    this.setState({transactionHash});
  });
})
};
render() {
return (
  <div className="App">
    <header className="App-header">
      <h1>Ethereum et IPFS utilisant Infura</h1>
    </header>
<hr/><grid>
  <h3> Choisissez le fichier à envoyer à IPFS </h3>
  <form onSubmit={this.onSubmit}>
    <input
      type = "file"
      onChange = {this.captureFile}
    />
    <Button
      bsStyle="primary"
      type="submit">
      Envoyez-le
    </Button>
  </form>
  <hr/> 
  <Button onClick = {this.onClick}> Obtenir le reçu de transaction </Button> 
  <hr/> 
  <table bordered responsive>
    <thead>
      <tr>
        <th>Catégorie de reçu de transaction</th>
        <th> </th>
        <th>Valeurs</th>
      </tr>
    </thead>
<tbody>
  <tr>
    <td>Hash IPFS stocké sur Ethereum</td>
    <td> : </td>
    <td>{this.state.ipfsHash}</td>
  </tr>
  <tr>
    <td>Adresse du contrat Ethereum</td>
    <td> : </td>
    <td>{this.state.ethAddress}</td>
  </tr>
  <tr>
    <td>Tx # </td>
    <td> : </td>
    <td>{this.state.transactionHash}</td>
  </tr>
</tbody>
</table>
</grid>
</div>
);
}
}
export default App;

Et c'est tout !

Accédez à votre dApp sur localhost:3000. Téléchargez un fichier et vous verrez un hash généré. Pour vous assurer que votre fichier est téléchargé, accédez-y via la passerelle IPFS. Assurez-vous d'accepter les demandes de Metamask.

Image

Image

Accédez à votre fichier à l'adresse : https://gateway.ipfs.io/ipfs/votre hash IPFS

Le mien est à l'adresse : https://gateway.ipfs.io/ipfs/QmbyizSHLirDfZhms75tdrrdiVkaxKvbcLpXzjB5k34a31

Pour en savoir plus sur l'IPFS, consultez mes autres articles :

Apprendre en faisant : une introduction agréable et facile au Inter Planetary File System _Primer on IPFS_medium.freecodecamp.org IPFS ? et Merkle Forest ? Wh_at is IPFS?ha_ckernoon.com

Merci d'avoir lu. Si vous avez aimé cela, applaudissez ! Suivez-moi sur Twitter @Niharika3297