WEB3DEV

Cover image for Mãos à Obra: Iniciando com o Infura e o IPFS na Ethereum
Banana Labs
Banana Labs

Posted on

Mãos à Obra: Iniciando com o Infura e o IPFS na Ethereum

Capa

Por que Infura?

Existem muitos pontos problemáticos enfrentados pelo blockchain que podem ser resolvidos, até certo ponto, pela Infura e/ou pelo InterPlanetary File System (IPFS) Estes são os principais desafios:

  1. É caro armazenar dados na blockchain Ethereum
  2. É difícil configurar um cliente geth Ethereum
  3. É difícil escalar a infraestrutura

Se você usa a Infura, o acesso à rede Ethereum e ao IPFS se torna muito mais rápido. Não leva mais horas para sincronizar o cliente geth, que usa uma grande quantidade de memória e largura de banda enquanto toda a blockchain está sendo baixada.

Aqui estão algumas outras vantagens que vêm com o uso da Infura:

  • Grandes quantidades de dados podem ser armazenadas no IPFS, e apenas o hash do arquivo pode ser armazenado na Ethereum.
  • A Infura fornece APIs seguras, confiáveis, escaláveis e fáceis de usar para acessar a rede Ethereum e o IPFS. Os desenvolvedores não precisam se preocupar com a infraestrutura de um nó Ethereum ou um nó IPFS. Isso é cuidado pela Infura.
  • A Infura fornece endpoints públicos habilitados para TLS.
  • O código é portátil na interface da Ethereum usando JSON RPC, Web3.
  • A Infura é praticamente o canivete suíço de um desenvolvedor e também salva a equipe de implantação do inferno dos problemas de escalabilidade.
  • E, finalmente, a Infura é confiável:

Infura é confiável

Descrição do dApp

Nosso dApp recebe como entrada um arquivo do usuário e fará o upload para o IPFS invocando um contrato Ethereum. O hash do arquivo será armazenado na Ethereum.

Este é o processo pelo qual passaremos:

  1. Recebe arquivo como entrada
  2. Converter arquivo em buffer
  3. Carregar buffer para IPFS
  4. Armazenar hash do arquivo retornado pelo IPFS
  5. Obtenha o endereço da Ethereum na Metamask do usuário
  6. Usuário confirma transação para Ethereum via Metamask
  7. O hash IPFS é escrito na Ethereum

Arquitetura Dapp

Pilha de tecnologia envolvida

  • React — Biblioteca de front-end
  • Solidity — A linguagem usada para construir contratos inteligentes executados na Ethereum
  • IPFS — Armazenamento descentralizado
  • Infura — Aacesso API à rede Ethereum e IPFS

Vamos Codificar!

Verifique se você já tem a Metamask baixada. Se não, faça o download aqui.
Além disso, mantenha seu Node e NPM atualizados.

Instale as seguintes dependências:

$ npm i -g create-react-app$ npm install react-bootstrap$ npm install fs-extra$ npm install ipfs-api$ npm install web3
Enter fullscreen mode Exit fullscreen mode

Depois de terminar, execute o seguinte comando em sua CLI para criar um projeto React de amostra. Vou nomear meu projeto como ipfs.

$ create-react-app ipfs
Enter fullscreen mode Exit fullscreen mode

Implante o contrato inteligente na Rede de Teste Ropsten

Certifique-se de estar na rede de teste Ropsten na metamask.

Para implantar o contrato inteligente, precisamos de ether. Para obter o ether para a rede de teste Ropsten, acesse https://faucet.metamask.io/.

Para implantar o contrato inteligente, acesse https://remix.ethereum.org.

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

Remix

Salve o endereço do contrato inteligente. O meu é: 0x610DD75057738B73e3F17A9D607dB16A44f962F1

Além disso, salve a Application Binary Interface (ABI) em JSON. Ela pode ser encontrada na guia 'compilar', em 'detalhes'.

A minha é a seguinte:

[ {  "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" }]
Enter fullscreen mode Exit fullscreen mode

No diretório “ipfs/src”, crie os seguintes arquivos: web3.js, ipfs.js e storehash.js.

Arquivo 1 — Web3.js

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

Arquivo 2 — Storehash.js

import web3 from './web3';
Enter fullscreen mode Exit fullscreen mode
//Seu endereço do contrato 
const address = '0x610dd75057738b73e3f17a9d607db16a44f962f1';
Enter fullscreen mode Exit fullscreen mode
//A ABI de seu contrato 
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" }]
Enter fullscreen mode Exit fullscreen mode
export default new web3.eth.Contract(abi, address);
Enter fullscreen mode Exit fullscreen mode

Arquivo 3 — Ipfs.js

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

Editar — 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';
Enter fullscreen mode Exit fullscreen mode
ReactDOM.render(<App />, document.getElementById('root'));registerServiceWorker();
Enter fullscreen mode Exit fullscreen mode

Arquivo 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: ''    };

//Recebe arquivo como entrada do usuário 
usercaptureFile =(event) => {        event.stopPropagation()        event.preventDefault()        const file = event.target.files[0]        let reader = new window.FileReader()        reader.readAsArrayBuffer(file)        reader.onloadend = () => this.convertToBuffer(reader)      };

//Converte arquivo para o buffer e armazena no IPFS 
convertToBuffer = async(reader) => {      
//arquivo é convertido para o buffer para carregar no IPFS        
const buffer = await Buffer.from(reader.result);     
 //defina este buffer usando sintaxe es6      
this.setState({buffer});    };

//ES6 função async 
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();

//traz o endereço da conta Metamask do usuário     
const accounts = await web3.eth.getAccounts();   
//obtém o endereço do contrato a partir de storehash.js    
const ethAddress= await storehash.options.address;      this.setState({ethAddress});    
//salva o documento para IPFS, retornae seu hash# e defina o hash# para state      
await ipfs.add(this.state.buffer, (err, ipfsHash) => {        console.log(err,ipfsHash);        //setState definindo ipfsHash para ipfsHash[0].hash      
this.setState({ ipfsHash:ipfsHash[0].hash });        
// chama o método de contrato Ethereum "send Hash" e .send IPFS hash para contrato ethereum        
//retorna o hash da transação do contrato 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 and IPFS using Infura</h1>          </header>

<hr/><grid>          <h3> Choose file to send to IPFS </h3>          <form onSubmit={this.onSubmit}>            <input              type = "file"              onChange = {this.captureFile}            />             <Button             bsStyle="primary"             type="submit">             Send it             </Button>          </form><hr/> <Button onClick = {this.onClick}> Get Transaction Receipt </Button> <hr/>  <table bordered responsive>                <thead>                  <tr>                    <th>Tx Receipt Category</th>                    <th> </th>                    <th>Values</th>                  </tr>                </thead>

<tbody>                  <tr>                    <td>IPFS Hash stored on Ethereum</td>                    <td> : </td>                    <td>{this.state.ipfsHash}</td>                  </tr>                  <tr>                    <td>Ethereum Contract Address</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;
Enter fullscreen mode Exit fullscreen mode

E isso é tudo!

Acesse seu dApp em localhost:3000. Carregue um arquivo e você verá um hash gerado. Para certificar-se de que seu arquivo foi carregado, acesse-o através do gateway IPFS. Certifique-se de aceitar as solicitações da Metamask.

tela no navegador localhost

tela no navegador localhost

Acesse seu arquivo em: https://gateway.ipfs.io/ipfs/[seu_hash_IPFS]

O meu está em:
https://gateway.ipfs.io/ipfs/QmbyizSHLirDfZhms75tdrrdiVkaxKvbcLpXzjB5k34a31


Esse artigo é uma tradução de Niharika Singh feita por @bananlabs. Você pode encontrar o artigo original aqui

Latest comments (0)