A tecnologia Blockchain tem aumentado nos últimos dez anos e deu vida a um bom número de produtos e plataformas, como Chainalysis (tecnologia de finanças), Burstiq (tecnologia de saúde), Filamento (IoT), Opus (streaming de música) e Ocular (cibersegurança).

A partir desses exemplos, podemos ver que o blockchain atravessa muitos produtos e casos de uso-tornando-o muito essencial e útil. Em fintech (tecnologia de finanças), é usado como livros-razão descentralizados para segurança e transparência em lugares como Chain, Chainalysis, e também é útil em tecnologia de saúde para a segurança de dados de saúde confidenciais em Burstiq e Robomed-sem esquecer a tecnologia de mídia como Opus e Audius que também usam blockchain para transparência de royalties e, portanto, obtêm royalties integrais.

O Ocular usa a segurança que vem com o blockchain para gerenciamento de identidade para sistemas biométricos, enquanto o Filament usa livros-razão do blockchain para comunicação criptografada em tempo real. Isso mostra como o blockchain se tornou essencial para nós ao tornar nossas vidas melhores. Mas o que exatamente é um blockchain?

Um blockchain é um banco de dados que é compartilhado por uma rede de computadores. Depois que um registro é adicionado à cadeia, é muito difícil alterá-lo. Para garantir que todas as cópias do banco de dados sejam iguais, a rede faz verificações constantes.

Então, por que precisamos do blockchain? Blockchain é uma maneira segura de registrar atividades e manter os dados atualizados enquanto mantém um registro de seu histórico em comparação com os registros ou bancos de dados tradicionais onde hacks, erros e tempos de inatividade são muito possíveis. Os dados não podem ser corrompidos por ninguém ou excluídos acidentalmente, e você se beneficia tanto de uma trilha histórica de dados quanto de um registro atualizado instantaneamente que não pode ser apagado ou se tornar inacessível devido ao tempo de inatividade de um servidor.

Como todo o blockchain está duplicado em muitos computadores, qualquer usuário pode ver o blockchain inteiro. As transações ou registros são processados ​​não por um administrador central, mas por uma rede de usuários que trabalham para verificar os dados e chegar a um consenso.

Os aplicativos que usam blockchain são chamados de dApps (aplicativos descentralizados). Olhando ao redor hoje, vamos encontrar principalmente aplicativos descentralizados em fintech, mas blockchain vai além de finanças descentralizadas. Temos plataformas de saúde, plataformas de streaming/compartilhamento de música, plataformas de comércio eletrônico, plataformas de segurança cibernética e IOTs em direção a aplicativos descentralizados (dApps), conforme citado acima.

Então, quando faria sentido considerar o uso de blockchain para nossos aplicativos, em vez de um banco de dados ou registro padrão?

Aplicações comuns de blockchain

  • Gerenciando e protegendo relacionamentos digitais
    Sempre que você quiser manter um registro transparente e de longo prazo dos ativos (por exemplo, para registrar direitos de propriedade ou apartamento), o blockchain pode ser o ideal solução. Os ‘contratos inteligentes’ da Ethereum, em particular, são ótimos para facilitar as relações digitais. Com um contrato inteligente, os pagamentos automatizados podem ser liberados quando as partes em uma transação concordam que suas condições foram atendidas.
  • Eliminando intermediários/porteiros
    Por exemplo, a maioria dos provedores atualmente tem que interagir com os hóspedes por meio de uma plataforma agregadora centralizada, como Airbnb ou Uber (que, por sua vez, leva uma parte em cada transação). O Blockchain poderia mudar tudo isso.
    Por exemplo, a TUI está tão convencida do poder do blockchain que é formas pioneiras de conectar hoteleiros e clientes diretamente . Dessa forma, eles podem realizar transações via blockchain de maneira fácil, segura e consistente, em vez de por meio de uma plataforma central de reservas.
  • Registre transações seguras entre parceiros para garantir confiança
    Um banco de dados tradicional pode ser bom para registrar transações simples entre duas partes, mas quando as coisas ficam mais complicadas, o blockchain pode ajudar a reduzir gargalos e simplificar relacionamentos. Além do mais, a segurança adicional de um sistema descentralizado torna o blockchain ideal para transações em geral.
    Um exemplo é a Universidade de Melbourne que começou a armazenar seus registros em blockchain . O caso de uso mais promissor para blockchain no ensino superior é transformar a “manutenção de registros” de graus, certificados e diplomas. Isso economiza muito custo de servidores dedicados para armazenamento ou registros.
  • Mantendo registros de ações anteriores para aplicativos em que os dados estão em fluxo constante
    Blockchain é a maneira melhor e mais segura de registrar a atividade e manter os dados atualizados, mantendo um registro de seu histórico. Os dados não podem ser corrompidos por ninguém ou excluídos acidentalmente, e você se beneficia tanto de um rastro histórico de dados, quanto de um registro atualizado instantaneamente. Um exemplo de um bom caso de uso é o blockchain em e-commerce, tanto blockchain quanto e-commerce envolvem transações.
    Blockchain torna essas transações mais seguras e rápidas, enquanto as atividades de e-commerce dependem delas. A tecnologia Blockchain permite que os usuários compartilhem e armazenem ativos digitais com segurança de forma automática e manualmente. Essa tecnologia tem a capacidade de lidar com as atividades do usuário, como processamento de pagamentos, pesquisas de produtos, compras de produtos e atendimento ao cliente. Também reduz as despesas com gerenciamento de estoque e processamento de pagamentos.
  • A descentralização torna possível o uso em qualquer lugar
    Ao contrário de antes, onde temos que nos restringir a uma região específica devido a vários motivos, como políticas de câmbio, as limitações dos gateways de pagamento tornam o acesso a recursos financeiros de muitos países não em sua região ou continente difícil. Com a ascensão e o poder da descentralização do blockchain ou do sistema peer-to-peer, fica mais fácil trabalhar com outros países.
    Por exemplo, uma loja de comércio eletrônico na Europa pode ter consumidores na África e não exigir um intermediário para processar seus pedidos de pagamento. Além disso, essas tecnologias estão abrindo portas para os varejistas online fazerem uso dos mercados de consumo em países distantes com bitcoin, ou seja, uma criptomoeda.
  • Blockhain é neutro em tecnologia
    Blockchain funciona com toda e qualquer tecnologia em uso por um desenvolvedor. Você não precisa aprender Node como um desenvolvedor Python para usar blockchain ou aprender Golang. Isso torna o blockchain muito fácil de usar.
    Podemos realmente usá-lo diretamente com nossos aplicativos front-end em Vue/React com o blockchain atuando como nosso único banco de dados para tarefas simples e descomplicadas e casos de uso como upload de dados ou obtenção de hashes exibindo registros para nossos usuários ou criando jogos front-end como jogos de cassino e jogos de apostas (nos quais é necessária uma grande quantidade de confiança). Além disso, com o poder da web3, podemos armazenar dados na cadeia diretamente.

Agora, vimos várias vantagens de usar blockchain, mas quando não devemos nos preocupar em usar um blockchain?

Desvantagens do Blockchain

  • Velocidade reduzida para transações digitais
    Blockchains requerem grandes quantidades de poder de computação, o que tende a reduzir a velocidade das transações digitais, embora existam soluções alternativas para o uso de bancos de dados centralizados quando em necessidade de transações de alta velocidade em milissegundos.
  • Imutabilidade de dados
    A imutabilidade de dados sempre foi uma das maiores desvantagens do blockchain. É claro que vários sistemas se beneficiam disso, incluindo cadeia de suprimentos, sistemas financeiros e assim por diante. No entanto, sofre do fato de que uma vez que os dados são gravados, eles não podem ser removidos. Cada pessoa na Terra tem direito à privacidade. No entanto, se a mesma pessoa utiliza uma plataforma digital que roda em tecnologia blockchain, então ela não será capaz de remover seu traço do sistema quando não o quiser lá. Em palavras simples, não há como ele remover seus vestígios-deixando os direitos de privacidade em pedaços.
  • Requer conhecimento especializado
    Implementar e gerenciar um projeto de blockchain é difícil. Requer conhecimento profundo para percorrer todo o processo. É por isso que é difícil encontrar especialistas ou especialistas em blockchain porque é preciso muito tempo e esforço para treinar um especialista em blockchain. Portanto, este artigo é um bom lugar para começar e um bom guia se você já tiver começado.
  • Interoperabilidade
    Múltiplas redes de blockchain trabalhando duro para resolver o problema do livro razão distribuído de maneira exclusiva torna difícil relacioná-las ou integrá-las umas às outras. Isso dificulta a comunicação entre diferentes cadeias.
  • Integração de aplicativos legados
    Muitos negócios e aplicativos ainda usam sistemas e arquitetura legados; adotar a tecnologia blockchain requer uma revisão completa desses sistemas, o que devo dizer que não é viável para muitos deles.

O Blockchain ainda está evoluindo e amadurecendo o tempo todo, então não se surpreenda se esses contras mencionados hoje se transformarem em profissionais mais tarde. Bitcoin, que é uma criptomoeda, é um exemplo popular de blockchain, um blockchain popular que vem crescendo além da criptomoeda bitcoin é o blockchain Ethereum. Bitcoin se concentra em criptomoedas, enquanto Ethereum se concentra mais em contratos inteligentes, que têm sido a principal força motriz para as novas plataformas de tecnologia.

Leitura recomendada : Bitcoin x Ethereum: qual é a diferença?

Vamos começar a construir nossa API

Com um conhecimento sólido de blockchain, agora vamos ver como construir um blockchain Ethereum e integrá-lo a uma API padrão em Node.js. O objetivo final é obter um bom entendimento de como as plataformas dApps e Blockchain estão sendo construídas.

A maioria dos dApps tem arquitetura e estrutura semelhantes. Basicamente, temos um usuário que interage com o front-end dApp-seja web ou móvel-que então interage com as APIs de back-end. O back-end, então, a pedido, interage com o (s) contrato (s) inteligente (s) ou blockchain por meio de nós públicos; eles executam aplicativos Node.js ou o back-end usa blockchain executando diretamente o software Node.js. Ainda há muitas coisas entre esses processos, desde a escolha de construir um aplicativo totalmente descentralizado ou semi-descentralizado até a escolha do que deve ser descentralizado e como armazenar com segurança as chaves privadas.

Leitura recomendada : Arquitetura de aplicativos descentralizados: back-end, segurança e padrões de design

Coisas que devemos saber primeiro

Para este tutorial, vamos tentar construir o back-end de um aplicativo de loja de música descentralizado que usa o poder do blockchain Ethereum para armazenar música e compartilhá-la para download ou streaming.

A estrutura básica do aplicativo que estamos tentando construir tem três partes:

  1. Autenticação , que é feita por e-mail; é claro que precisamos adicionar uma senha criptografada ao aplicativo.
  2. Armazenamento de dados , com os dados da música primeiro são armazenados em ipfs e o endereço de armazenamento é armazenado no blockchain para recuperação.
  3. Recuperação , com qualquer usuário autenticado podendo acessar os dados armazenados em nossa plataforma e usá-los.

Estaremos construindo isso com Node.js, mas você também pode construir com Python ou qualquer outra linguagem de programação. Também veremos como armazenar dados de mídia em IPFS , obter o endereço e escrever funções para armazenar este endereço-e recuperar este endereço de um blockchain com a linguagem de programação Solidity.

Aqui estão algumas ferramentas que devemos ter à nossa disposição para construir ou trabalhar com Ethereum e Node.js.

  • Node.js
    O primeiro requisito é um aplicativo Node. Estamos tentando construir um aplicativo Node.js, então precisamos de um compilador. Certifique-se de ter Node.js instalado-e faça download do binário de suporte de longo prazo mais recente ( LTS ).
  • Truffle Suite
    Truffle é um ambiente de desenvolvimento e teste de contrato, bem como um pipeline de ativos para blockchain Ethereum. Ele fornece um ambiente para compilar, canalizar e executar scripts. Quando você estiver falando sobre o desenvolvimento de blockchain, Truffle é uma parada popular para visitar. Confira o Truffle Suite em Truffle Suite: Sweet Tools for Smart Contracts .
  • Ganache CLI
    Outra ferramenta que funciona bem com o Truffle é o Ganache-CLI. É construído e mantido pela equipe Truffle Suite. Depois de construir e compilar, você precisa de um emulador para desenvolver e executar aplicativos blockchain e, em seguida, implantar contratos inteligentes para serem usados. O Ganache facilita a implantação de um contrato em um emulador sem usar dinheiro real para custos de transação, contas recicláveis ​​e muito mais. Leia mais sobre Ganache CLI em Ganache CLI e Ganache .
  • Remix
    O Remix é como uma alternativa ao Ganache, mas também vem com uma GUI para ajudar a navegar, implantar e testar os contratos inteligentes Ethereum. Você pode aprender mais sobre isso em Remix-Ethereum IDE & community . Tudo que você precisa fazer é visitar https://remix.ethereum.org e usar a GUI para escrever e implantar contratos inteligentes.
  • Web3
    Web3 é uma coleção de bibliotecas que permite que você interaja com um nó Ethereum. Podem ser nós locais ou remotos do contrato por meio de HTTP, IPC ou Web Sockets. Introdução ao Web3.js · Curso intensivo de desenvolvedor Ethereum Blockchain é um bom lugar para aprender um pouco sobre Web3.
  • IPFS
    Um protocolo central que está sendo usado na construção de dApps. O Sistema de Arquivo InterPlanetário (IPFS) é um protocolo e rede ponto a ponto para armazenar e compartilhar dados em um sistema de arquivo distribuído. IPFS Capacita a Web Distribuída explica mais sobre IPFS e como ele é normalmente usado.

Criando uma API de back-end do zero

Portanto, primeiro temos que criar um back-end a ser usado, e estamos usando Node.js. Quando queremos criar uma nova API Node.js, a primeira coisa que faremos é inicializar um pacote npm. Como você provavelmente sabe, npm significa Node Package Manager e vem pré-empacotado com o binário Node.js.. Portanto, criamos uma nova pasta e a chamamos de “blockchain-music” . Abrimos o terminal nesse diretório de pasta e, em seguida, executamos o seguinte comando:

  $ npm init-y && touch server.js routes.js
 

Isso inicia o projeto com um arquivo package.json e responde sim a todos os prompts. Em seguida, também criamos um arquivo server.js e um arquivo routes.js para escrever as funções routes na API.

Depois de tudo isso, você terá que instalar os pacotes de que precisamos para tornar nossa construção fácil e direta. Este processo é contínuo, ou seja, você pode instalar um pacote a qualquer momento durante o desenvolvimento do seu projeto.

Vamos instalar os mais importantes de que precisamos agora:

Você também terá que instalar o Truffle.js globalmente , para que possa usá-lo em qualquer lugar em seu ambiente local. Se você deseja instalar todos eles de uma vez, execute o seguinte código em seu Terminal:

  $ npm install nodemon truffle-contract dotenv mongodb shortid express web3-salvar && npm install truffle-g
 

O sinalizador --save serve para salvar o nome do pacote no arquivo package.json . O sinalizador -g é para armazenar este pacote específico globalmente, para que possamos usá-lo em qualquer projeto em que vamos trabalhar.

Em seguida, criamos um arquivo .env onde podemos armazenar nosso URI secreto do banco de dados MongoDB para uso. Fazemos isso executando touch.env no Terminal. Se você ainda não tem uma conta de banco de dados no MongoDB, comece com a página do MongoDB .

O pacote dotenv exporta nossa variável armazenada para o ambiente de processo Node.js. Certifique-se de não enviar o arquivo .env ao enviar para repositórios públicos para evitar vazar suas senhas e dados privados.

A seguir, temos que adicionar scripts para as fases de construção e desenvolvimento de nosso projeto em nosso arquivo package.json . Atualmente, nosso package.json se parece com isto:

  { "nome":"teste", "versão":"1.0.0", "descrição":"", "main":"server.js", "scripts": { "test":"echo \"Erro: nenhum teste especificado \"&& exit 1" }, "palavras-chave": [], "autor":"", "licença":"ISC", "dependências": { "expresso":"^ 4.17.1", "socket.io":"^ 2.3.0", "contrato de trufa":"^ 4.0.31", "web3":"^ 1.3.0" }
}
 

Em seguida, vamos adicionar um script de início ao arquivo package.json para usar o servidor nodemon para que, sempre que fizermos alterações, ele reinicie o próprio servidor e um script de construção que use o servidor de nó diretamente, poderia ser assim:

  { "nome":"teste", "versão":"1.0.0", "descrição":"", "main":"server.js", "scripts": { "test":"echo \"Erro: nenhum teste especificado \"&& exit 1", "start":"nodemon server.js", "build":"node server.js" }, "palavras-chave": [], "autor":"", "licença":"ISC", "dependências": { "expresso":"^ 4.17.1", "socket.io":"^ 2.3.0", "contrato de trufa":"^ 4.0.31", "web3":"^ 1.3.0" }
}
 

Em seguida, temos que inicializar o Truffle para uso em nosso contrato inteligente usando o pacote Truffle que instalamos globalmente anteriormente. Na mesma pasta de nossos projetos, rodamos o seguinte comando abaixo em nosso terminal:

  $ truffle init
 

Então, podemos começar a escrever nosso código em nosso arquivo server.js . Novamente, estamos tentando construir um aplicativo de loja de música descentralizado simples, onde os clientes podem fazer upload de músicas para que todos os outros usuários acessem e ouçam.

Nosso server.js deve ser limpo para facilitar o acoplamento e desacoplamento de componentes, então as rotas e outras funcionalidades serão colocadas em outros arquivos como routes.js . Nosso exemplo server.js poderia ser:

  require ('dotenv'). config ();
const express=require ('express')
const app=express ()
const routes=require ('./routes')
const Web3=requer ('web3');
const mongodb=require ('mongodb'). MongoClient
contrato const=requer ('contrato de trufa');
app.use (express.json ()) mongodb.connect (process.env.DB, {useUnifiedTopology: true}, (errar, cliente)=> { const db=client.db ('Cluster0') //casa rotas (app, db) app.listen (process.env.PORT || 8082, ()=> { console.log ('ouvindo na porta 8082'); })
})
 

Basicamente, acima, importamos as bibliotecas que precisamos com require , em seguida, adicionamos um middleware que permite o uso de JSON em nossa API usando app.use e, em seguida, conectamos ao nosso banco de dados MongoDB e obter o acesso ao banco de dados, e então especificamos qual cluster de banco de dados estamos tentando acessar (para este tutorial é “Cluster0” ). Depois disso, chamamos a função e a importamos do arquivo de rotas . Por fim, ouvimos qualquer tentativa de conexão na porta 8082 .

Este arquivo server.js é apenas um barebone para iniciar o aplicativo. Observe que importamos routes.js . Este arquivo conterá os endpoints da rota para nossa API. Também importamos os pacotes que precisávamos usar no arquivo server.js e os inicializamos.

Vamos criar cinco endpoints para consumo do usuário:

  1. Endpoint de registro para registrar usuários apenas por e-mail. Idealmente, faríamos isso com um e-mail e senha, mas como queremos apenas identificar cada usuário, não vamos nos aventurar na segurança de senha e hash para a brevidade deste tutorial.
      POST/registro
    Requisitos: email
     
  2. Endpoint de login para usuários por e-mail.
      POST/login
    Requisitos: email
     
  3. Endpoint de upload para usuários-a API que obtém os dados do arquivo de música. O frontend irá converter os arquivos MP3/WAV para um buffer de áudio e enviar esse buffer para a API.
      POST/upload
    Requisitos: nome, título da música, buffer de arquivo de música ou URL armazenado
     
  4. Endpoint de acesso que fornecerá os dados do buffer de música a qualquer usuário registrado que os solicite e registra quem os acessou.
      GET/access/{email}/{id}
    Requisitos: email, id
     
  5. Também queremos fornecer acesso a toda a biblioteca de música e retornar os resultados para um usuário registrado.
      GET/access/{email}
    Requisitos: email
     

Em seguida, escrevemos nossas funções de rota em nosso arquivo routes.js . Utilizamos os recursos de armazenamento e recuperação do banco de dados e, em seguida, exportamos a função de rota no final do arquivo para possibilitar a importação em outro arquivo ou pasta.

  const shortid=require ('short-id')
rotas de função (app, db) { app.post ('/register', (req, res)=> { let email=req.body.email let idd=shortid.generate () if (email) { db.findOne ({email}, (err, doc)=> { if (doc) { res.status (400).json ({"status":"Falha","motivo":"Já registrado"}) }outro{ db.insertOne ({email}) res.json ({"status":"sucesso","id": idd}) } }) }outro{ res.status (400).json ({"status":"Falha","motivo":"entrada errada"}) } }) app.post ('/login', (req, res)=> { let email=req.body.email if (email) { db.findOne ({email}, (err, doc)=> { if (doc) { res.json ({"status":"sucesso","id": doc.id}) }outro{ res.status (400).json ({"status":"Falha","motivo":"Não reconhecido"}) } }) }outro{ res.status (400).json ({"status":"Falha","motivo":"entrada errada"}) } }) app.post ('/upload', (req, res)=> { let buffer=req.body.buffer deixe name=req.body.name let title=req.body.title if (buffer && title) { }outro{ res.status (400).json ({"status":"Falha","motivo":"entrada errada"}) } }) app.get ('/access/: email/: id', (req, res)=> { if (req.params.id && req.params.email) { }outro{ res.status (400).json ({"status":"Falha","motivo":"entrada errada"}) } })
}
module.exports=routes
 

Dentro desta função rota , temos muitas outras funções chamadas nos parâmetros app e db . Estas são as funções de terminal da API que permitem aos usuários especificar um terminal na URL. Por fim, escolhemos uma dessas funções para ser executada e fornecemos resultados como resposta às solicitações recebidas.

Temos quatro funções principais de endpoint:

  1. get : para ler operações de registro
  2. post : para criar operações de registro
  3. put : para atualizar as operações de registro
  4. delete : para excluir operações de registro

Nesta função routes , usamos as operações get e post . Usamos post para operações de registro, login e upload, e get para acessar as operações de dados. Para obter mais explicações sobre isso, leia o artigo de Jamie Corkhill em “ Como Para começar com o Node: uma introdução às APIs, HTTP e ES6 + JavaScript ”.

No código acima, também podemos ver algumas operações de banco de dados como na rota de registro . Armazenamos o e-mail de um novo usuário com db.createa e verificamos o e-mail na função de login com db.findOne . Agora, antes de fazermos tudo isso, precisamos nomear uma coleção ou tabela com o método db.collection . É exatamente isso que abordaremos a seguir.

Observação : para saber mais sobre as operações de banco de dados no MongoDB, verifique documentação dos métodos mongo Shell .

Construindo um contrato simples de Blockchain inteligente com solidez

Agora vamos escrever um contrato Blockchain no Solidity (essa é a linguagem em que os contratos inteligentes são escritos) para simplesmente armazenar nossos dados e recuperá-los quando precisarmos. Os dados que queremos armazenar são os dados do arquivo de música, o que significa que temos que fazer o upload da música para IPFS e, em seguida, armazenar o endereço do buffer em um blockchain.

Primeiro, criamos um novo arquivo na pasta do contrato com o nome Inbox.sol . Para escrever um contrato inteligente, é útil ter um bom entendimento do Solidity, mas não é difícil, pois é semelhante ao JavaScript.

Observação : se você estiver interessado em aprender mais sobre o Solidity, adicionei alguns recursos no final do artigo para você começar.

  solidez do pragma ^ 0,5.0; contrato Inbox { //Estrutura mapeamento (string=> string) public ipfsInbox; //Eventos evento ipfsSent (string _ipfsHash, string _address); evento inboxResponse (resposta de string); //Modificadores modificador notFull (string memory _string) { bytes memória stringTest=bytes (_string); requer (stringTest.length==0); _; } //Um ​​construtor vazio que cria uma instância do conteact construtor () public {} //obtém o endereço do receptor e o hash IPFS. Coloca o IPFSadress na caixa de entrada do receptor function sendIPFS (string memory _address, string memory _ipfsHash) notFull (ipfsInbox [_address]) public { ipfsInbox [_address]=_ipfsHash; emitir ipfsSent (_ipfsHash, _address); } //recupera o hash function getHash (string memory _address) retornos de exibição pública (string memory) { string memory ipfs_hash=ipfsInbox [_address]; //emite inboxResponse (ipfs_hash); return ipfs_hash; }
}
 

Em nosso contrato, temos duas funções principais: as funções sendIPFS e getHash . Antes de falarmos sobre as funções, podemos ver que primeiro tivemos que definir um contrato chamado Caixa de entrada . Dentro desta classe, temos estruturas usadas no objeto ipfsInbox (primeiro eventos, depois modificadores).

Depois de definir as estruturas e eventos, temos que inicializar o contrato chamando a função construtor . Em seguida, definimos três funções. (A função checkInbox foi usada no teste para os resultados do teste.)

O sendIPFS é onde o usuário insere o identificador e o endereço hash após o qual é armazenado no blockchain. A função getHash recupera o endereço hash quando recebe o identificador. Novamente, a lógica por trás disso é que, em última análise, queremos armazenar a música no IPFS. Para testar como funciona, você pode acessar um Remix IDE , copiar, colar e testar seu contrato, bem como depurar quaisquer erros e execute novamente (espero que não seja necessário!).

Depois de testar se nosso código funciona corretamente no remix, vamos prosseguir para compilá-lo localmente com o pacote Truffle. Mas primeiro, precisamos fazer algumas alterações em nossos arquivos e configurar nosso emulador usando ganache-cli :

Primeiro, vamos instalar o ganache-cli . No mesmo diretório, execute o seguinte comando em seu terminal:

  $ npm install ganache-cli-g
 

Então, vamos abrir outro Terminal e executar outro comando na mesma pasta:

  $ ganache-cli
 

Isso inicia o emulador para que nosso contrato de blockchain se conecte e funcione. Minimize o Terminal e continue com o outro Terminal que você está usando.

Agora vá para o arquivo truffle.js se estiver usando um Linux/Mac OS ou truffle-config.js no Windows e modifique este arquivo para parecer assim:

  const path=require ("path");
module.exports={ //para personalizar a configuração do Truffle! contract_build_directory: path.join (__ dirname,"/build"), redes: { desenvolvimento: { host:"127.0.0.1", porta: 8545, network_id:"*"//Corresponde a qualquer id de rede } }
};
 

Basicamente, o que fizemos foi adicionar o caminho da pasta de construção onde o contrato inteligente é convertido em arquivos JSON. Em seguida, também especificamos a rede que Truffle deve usar para a migração.

Em seguida, também na pasta migrações , crie um novo arquivo chamado 2_migrate_inbox.js e adicione o seguinte código dentro dos arquivos:

  var IPFSInbox=artifacts.require ("./Inbox.sol");
module.exports=function (implantador) { deployer.deploy (IPFSInbox);
};
 

Fizemos isso para obter o arquivo do contrato e implantá-lo automaticamente em um JSON, usando a função implantador durante a migração do Truffle.

Após as alterações acima, executamos:

  $ truffle compile
 

Devemos ver algumas mensagens no final que mostram uma compilação bem-sucedida, como:

 > Compilado com sucesso usando: -solc: 0.5.16 + commit.9c3226ce.Emscripten.clang
 

A seguir, migramos nosso contrato executando:

  $ truffle migrar
 

Depois de migrar com sucesso nossos contratos, devemos ter algo assim no final:

  Resumo
=======
> Total de implantações: 1
> Custo final: 0,00973432 ETH
 

E estamos quase terminando! Construímos nossa API com Node.js e também configuramos e construímos nosso contrato inteligente.

We should also write tests for our contract to test the behaviour of our contract and ensure it is the desired behaviour. The tests are usually written and placed in the test folder. An example test written in a file named InboxTest.js created in the test folder is:

const IPFSInbox=artifacts.require("./Inbox.sol")
contract("IPFSInbox", accounts=>{ it("emit event when you send a ipfs address", async()=>{ //ait for the contract const ipfsInbox=await IPFSInbox.deployed() //set a variable to false and get event listener eventEmitted=false //var event=() await ipfsInbox.ipfsSent((err,res)=>{ eventEmitted=true }) //call the contract function which sends the ipfs address await ipfsInbox.sendIPFS(accounts[1],"sampleAddress", {from: accounts[0]}) assert.equal(eventEmitted, true,"sending an IPFS request does not emit an event") })
})

So we run our test by running the following:

$ truffle test

It tests our contract with the files in the test folder and shows the number of passed and failed tests. For this tutorial, we should get:

$ truffle test
Using network'development'.
Compiling your contracts...
===============================
> Compiling.\contracts\Inbox.sol
> Artifacts written to C:\Users\Ademola\AppData\Local\Temp\test--2508-n0vZ513BXz4N
> Compiled successfully using: — solc: 0.5.16+commit.9c3226ce.Emscripten.clang Contract: IPFSInbox √ emit event when you send an ipfs address (373ms) 1 passing (612ms)

Integrating The Smart Contract To The Backend API Using Web3

Most times when you see tutorials, you see decentralized apps built to integrate the frontend directly to the blockchain. But there are times when the integration to the backend is needed as well, for example when using third-party backend APIs and services, or when using blockchain to build a CMS.

The use of Web3 is very important to this cause, as it helps us access remote or local Ethereum nodes and use them in our applications. Before we go on, we’ll discuss the local and remote Ethereum nodes. The local nodes are the nodes deployed on our system with emulators like ganache-cli but a remote node is one that is deployed on online faucets/platforms like ropsten or rinkeby. To dive in deeper, you can follow a tutorial on how to deploy on ropsten 5-minute guide to deploying smart contracts with Truffle and Ropsten or you could use truffle wallet provider and deploy via An Easier Way to Deploy Your Smart Contracts.

We are using ganache-cli in this tutorial, but if we were deploying on ropsten, we should have copied or stored our contract address somewhere like in our.env file, then move on to update the server.js file, import web3, import the migrated contract and set up a Web3 instance.

require('dotenv').config();
const express=require('express')
const app=express()
const routes=require('./routes')
const Web3=require('web3');
const mongodb=require('mongodb').MongoClient
const contract=require('truffle-contract');
const artifacts=require('./build/Inbox.json');
app.use(express.json())
if (typeof web3 !=='undefined') { var web3=new Web3(web3.currentProvider) } outro { var web3=new Web3(new Web3.providers.HttpProvider('http://localhost:8545'))
}
const LMS=contract(artifacts)
LMS.setProvider(web3.currentProvider)
mongodb.connect(process.env.DB,{ useUnifiedTopology: true }, async(err,client)=>{ const db=client.db('Cluster0') const accounts=await web3.eth.getAccounts(); const lms=await LMS.deployed(); //const lms=LMS.at(contract_address) for remote nodes deployed on ropsten or rinkeby routes(app,db, lms, accounts) app.listen(process.env.PORT || 8082, ()=> { console.log('listening on port'+ (process.env.PORT || 8082)); })
})

In the server.js file, we check if the web3 instance is initialized already. If not, we initialize it on the network port which we defined earlier (8545). Then we build a contract based on the migrated JSON file and truffle-contract package, and set the contract provider to the Web3 instance provider which must have been initialized by now.

We then get accounts by web3.eth.getAccounts. For the development stage, we call the deployed function in our contract class that asks ganache-cli — which is still running — to give us a contract address to use. But if we’ve already deployed our contract to a remote node, we call a function inputting the address as an argument. The sample function is commented below the defined lms variable in our code above. Then we call the routes function inputting the app instance, database instance, contract instance (lms), and accounts data as arguments. Finally, we listen for requests on port 8082.

Also, by now, we should have installed the MongoDB package, because we are using it in our API as our database. Once we have that, we move onto the routes page where we use the methods defined in the contract to accomplish tasks like saving and retrieving the music data.

In the end, our routes.js should look like this:

const shortid=require('short-id')
const IPFS=require('ipfs-api');
const ipfs=IPFS({ host:'ipfs.infura.io', port: 5001,protocol:'https'}); function routes(app, dbe, lms, accounts){ let db=dbe.collection('music-users') let music=dbe.collection('music-store') app.post('/register', (req,res)=>{ let email=req.body.email let idd=shortid.generate() if(email){ db.findOne({email}, (err, doc)=>{ if(doc){ res.status(400).json({"status":"Failed","reason":"Already registered"}) }else{ db.insertOne({email}) res.json({"status":"success","id":idd}) } }) }else{ res.status(400).json({"status":"Failed","reason":"wrong input"}) } }) app.post('/login', (req,res)=>{ let email=req.body.email if(email){ db.findOne({email}, (err, doc)=>{ if(doc){ res.json({"status":"success","id":doc.id}) }else{ res.status(400).json({"status":"Failed","reason":"Not recognised"}) } }) }else{ res.status(400).json({"status":"Failed","reason":"wrong input"}) } }) app.post('/upload', async (req,res)=>{ let buffer=req.body.buffer let name=req.body.name let title=req.body.title let id=shortid.generate() + shortid.generate() if(buffer && title){ let ipfsHash=await ipfs.add(buffer) let hash=ipfsHash[0].hash lms.sendIPFS(id, hash, {from: accounts[0]}) .then((_hash, _address)=>{ music.insertOne({id,hash, title,name}) res.json({"status":"success", id}) }) .catch(err=>{ res.status(500).json({"status":"Failed","reason":"Upload error occured"}) }) }else{ res.status(400).json({"status":"Failed","reason":"wrong input"}) } }) app.get('/access/:email', (req,res)=>{ if(req.params.email){ db.findOne({email: req.body.email}, (err,doc)=>{ if(doc){ let data=music.find().toArray() res.json({"status":"success", data}) } }) }else{ res.status(400).json({"status":"Failed","reason":"wrong input"}) } }) app.get('/access/:email/:id', (req,res)=>{ let id=req.params.id if(req.params.id && req.params.email){ db.findOne({email:req.body.email},(err,doc)=>{ if(doc){ lms.getHash(id, {from: accounts[0]}) .then(async(hash)=>{ let data=await ipfs.files.get(hash) res.json({"status":"success", data: data.content}) }) }else{ res.status(400).json({"status":"Failed","reason":"wrong input"}) } }) }else{ res.status(400).json({"status":"Failed","reason":"wrong input"}) } })
} module.exports=routes

At the beginning of the routes file, we imported the short-id package and ipfs-http-client and then initialized IPFS with the HTTP client using the backend URL ipfs.infura.io and port 5001. This allowed us to use the IPFS methods to upload and retrieve data from IPFS (check out more here).

In the upload route, we save the audio buffer to IPFS which is better compared to just storing it on the blockchain for anyone registered or unregistered to use. Then we saved the address of the buffer in the blockchain by generating an ID and using it as an identifier in the sendIFPS function. Finally, then we save all the other data associated with the music file to our database. We should not forget to update our argument in the routes function since we changed it in the server.js file.

In the access route using id, we then retrieve our data by getting the id from the request, using the id to access the IPFS hash address, and then access the audio buffer using the address. But this requires authentication of a user by email which is done before anything else.

Phew, we’re done! Right now we have an API that can receive requests from users, access a database, and communicate to a node that has the software running on them. We shouldn’t forget that we have to export our function with module.exports though!

As we have noticed, our app is a decentralized app. However, it’s not fully decentralized as we only stored our address data on the blockchain and every other piece of data was stored securely in a centralized database which is the basis for semi-dApps. So the consumption of data can be done directly via request or using a frontend application in JavaScript to send fetch requests.

Our music store backend app can now safely store music data and provide access to anyone who needs to access it, provided it is a registered user. Using blockchain for music sharing makes it cheaper to store music data while focusing on connecting artists directly with users, and perhaps it could help them generate revenue that way. This wouldn’t require a middleman that uses royalty; instead, all of the revenue would go to the artist as users request their music to either download or stream. A good example of a music streaming application that uses blockchain just like this is Opus OPUS: Decentralized music sharing platform. However, there are also a few others like Musicoin, Audius, and Resonate.

What Next?

The final thing after coding is to start our server by running npm run start or npm run build and test our backend endpoints on either the browser or with Postman. After running and testing our API we could add more features to our backend and blockchain smart contract. If you’d like to get more guidance on that, please check the further reading section for more articles.

It’s worth mentioning that it is critical to write unit and integration tests for our API to ensure correct and desirable behaviors. Once we have all of that done, we can deploy our application on the cloud for public use. This can be done on its own with or without adding a frontend (microservices) on Heroku, GCP, or AWS for public use. Happy coding!

Note: You can always check my repo for reference. Also, please note that the.env file containing the MongoDB database URI is included for security reasons.

Further Reading And Related Resources

Categories: Wordpress