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:
- É caro armazenar dados na blockchain Ethereum
- É difícil configurar um cliente geth Ethereum
- É 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:
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:
- Recebe arquivo como entrada
- Converter arquivo em buffer
- Carregar buffer para IPFS
- Armazenar hash do arquivo retornado pelo IPFS
- Obtenha o endereço da Ethereum na Metamask do usuário
- Usuário confirma transação para Ethereum via Metamask
- O hash IPFS é escrito na Ethereum
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
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
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;
contract Contract { string ipfsHash; function setHash(string x) public { ipfsHash = x; } function getHash() public view returns (string x) { return ipfsHash; }
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" }]
No diretório “ipfs/src”, crie os seguintes arquivos: web3.js, ipfs.js e storehash.js.
Arquivo 1 — Web3.js
import Web3 from 'web3';
const web3 = new Web3(window.web3.currentProvider);
export default web3;
Arquivo 2 — Storehash.js
import web3 from './web3';
//Seu endereço do contrato
const address = '0x610dd75057738b73e3f17a9d607db16a44f962f1';
//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" }]
export default new web3.eth.Contract(abi, address);
Arquivo 3 — Ipfs.js
const IPFS = require('ipfs-api');const ipfs = new IPFS({ host: 'ipfs.infura.io', port: 5001, protocol: 'https' });
export default ipfs;
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';
ReactDOM.render(<App />, document.getElementById('root'));registerServiceWorker();
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;
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.
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)