Fermer

janvier 19, 2021

Comment créer une API Node.js pour la blockchain Ethereum


À propos de l'auteur

John Agbanusi est un développeur full stack passionné, un développeur chez Meet Kumba et un contributeur open source actif aux logiciels libres open source. Son majeur…
En savoir plus sur
John

Dans cet article, John Agbanusi explique comment créer une API Node.js à partir de zéro en créant et en déployant une blockchain Ethereum pour la décentralisation. Il vous montre également un processus étape par étape d'intégration à la fois de l'API et de la blockchain dans une seule API appelée «API d'application décentralisée».

La technologie de la blockchain a connu un essor au cours des dix dernières années et a apporté un bon nombre de produits et de plates-formes à la vie tels que Chainalysis (finance tech), Burstiq (health-tech), Filament (IoT), Opus (musique en streaming) et Ocular (cybersécurité).

À partir de ces exemples, nous pouvons voir que la blockchain recoupe de nombreux produits et cas d'utilisation – ce qui la rend très essentielle et utile. Dans la fintech (technologie financière), il est utilisé comme registres décentralisés pour la sécurité et la transparence dans des endroits tels que Chain, Chainalysis, et est également utile dans la technologie de la santé pour la sécurité des données de santé sensibles dans Burstiq et Robomed – sans oublier la technologie des médias comme Opus et Audius qui utilisent également la blockchain pour la transparence des redevances et obtiennent ainsi l'intégralité des redevances.

Ocular utilise la sécurité fournie avec la blockchain pour la gestion des identités pour les systèmes biométriques, tandis que Filament utilise des registres blockchain pour la communication cryptée en temps réel. Cela montre à quel point la blockchain est devenue essentielle pour nous en améliorant nos vies. Mais qu'est-ce qu'une exactement une blockchain?

Une blockchain est une base de données qui est partagée sur un réseau d'ordinateurs. Une fois qu'un enregistrement a été ajouté à la chaîne, il est assez difficile de le modifier. Pour s'assurer que toutes les copies de la base de données sont identiques, le réseau effectue des vérifications constantes.

Alors pourquoi avons-nous besoin de blockchain? La blockchain est un moyen sûr d'enregistrer les activités et de garder les données à jour tout en conservant un enregistrement de son histoire par rapport aux archives ou bases de données traditionnelles où les piratages, les erreurs et les temps d'arrêt sont très possibles. Les données ne peuvent être corrompues par personne ou supprimées accidentellement, et vous bénéficiez à la fois d'un historique des données et d'un enregistrement instantanément mis à jour qui ne peut pas être effacé ou devenir inaccessible en raison des temps d'arrêt d'un serveur. [19659006] Parce que toute la blockchain est dupliquée sur de nombreux ordinateurs, n'importe quel utilisateur peut visualiser l'intégralité de la blockchain. Les transactions ou les enregistrements ne sont pas traités par un administrateur central, mais par un réseau d'utilisateurs qui travaillent pour vérifier les données et parvenir à un consensus.

Les applications qui utilisent la blockchain sont appelées dApps (applications décentralisées). En regardant autour de nous aujourd'hui, nous trouverons principalement des applications décentralisées dans la fintech, mais la blockchain va au-delà de la finance décentralisée. Nous avons des plates-formes de santé, des plates-formes de streaming / partage de musique, des plates-formes de commerce électronique, des plates-formes de cybersécurité et des IOT qui s'orientent vers des applications décentralisées (dApps) comme indiqué ci-dessus. plutôt qu'une base de données ou un enregistrement standard?

Applications courantes de la blockchain

  • Gestion et sécurisation des relations numériques
    Chaque fois que vous souhaitez conserver un enregistrement transparent à long terme des actifs (par exemple, pour enregistrer les droits de propriété ou d'appartement ), la blockchain pourrait être la solution idéale. Les «contrats intelligents» Ethereum, en particulier, sont parfaits pour faciliter les relations numériques. Avec un contrat intelligent, les paiements automatisés peuvent être libérés lorsque les parties à une transaction conviennent que leurs conditions ont été remplies.
  • Élimination des intermédiaires / portiers
    Par exemple, la plupart des fournisseurs doivent actuellement interagir avec les clients via une plate-forme d'agrégation centralisée, comme Airbnb ou Uber (qui, à son tour, prend une coupe sur chaque transaction). La blockchain pourrait changer tout cela.
    Par exemple, TUI est tellement convaincue de la puissance de la blockchain qu'elle est des moyens pionniers pour connecter directement les hôteliers et les clients . De cette façon, ils peuvent effectuer des transactions via la blockchain de manière simple, sûre et cohérente, plutôt que via une plate-forme de réservation centrale.
  • Enregistrer des transactions sécurisées entre partenaires pour assurer la confiance
    Une base de données traditionnelle peut être utile pour enregistrer des transactions simples entre deux parties, mais lorsque les choses se compliquent, la blockchain peut aider à réduire les goulots d'étranglement et à simplifier les relations. De plus, la sécurité supplémentaire d’un système décentralisé rend la blockchain idéale pour les transactions en général.
    Un exemple est l’Université de Melbourne qui a commencé à stocker ses enregistrements dans la blockchain . Le cas d'utilisation le plus prometteur de la blockchain dans l'enseignement supérieur est de transformer la «tenue de registres» des diplômes, certificats et diplômes. Cela permet d'économiser beaucoup de frais sur les serveurs dédiés pour le stockage ou les enregistrements.
  • Conservation des enregistrements des actions passées pour les applications où les données sont en flux constant
    La blockchain est un meilleur moyen plus sûr d'enregistrer l'activité et de conserver les données à jour tout en maintenant un enregistrement de son histoire. Les données ne peuvent être corrompues par personne ou supprimées accidentellement, et vous bénéficiez à la fois d'un historique des données et d'un enregistrement instantanément mis à jour. Un exemple d'un bon cas d'utilisation est la blockchain dans le commerce électronique, la blockchain et le commerce électronique impliquent des transactions.
    La blockchain rend ces transactions plus sûres et plus rapides alors que les activités de commerce électronique en dépendent. La technologie blockchain permet aux utilisateurs de partager et de stocker en toute sécurité des actifs numériques à la fois automatiquement et manuellement. Cette technologie a la capacité de gérer les activités des utilisateurs telles que le traitement des paiements, la recherche de produits, les achats de produits et le service client. Cela réduit également les dépenses consacrées à la gestion des stocks et au traitement des paiements.
  • La décentralisation permet de l'utiliser n'importe où
    Contrairement à la situation où nous devons nous limiter à une région particulière pour diverses raisons comme les politiques de change, les limitations de les passerelles de paiement rendent difficile l'accès aux ressources financières de nombreux pays n'appartenant pas à votre région ou à votre continent. Avec l'essor et la puissance de la décentralisation de la blockchain ou du système peer-to-peer, il devient plus facile de travailler avec d'autres pays.
    Par exemple, un magasin de commerce électronique en Europe peut avoir des consommateurs en Afrique et ne pas nécessiter d'intermédiaire pour traiter leurs demandes de paiement. En outre, ces technologies ouvrent les portes aux détaillants en ligne pour qu'ils utilisent les marchés de consommation des pays lointains avec le bitcoin, c'est-à-dire une crypto-monnaie.
  • Blockhain Is Technology-Neutral
    Blockchain fonctionne avec toutes les piles technologiques utilisées par un développeur. Vous n'avez pas besoin d'apprendre Node en tant que développeur Python pour utiliser la blockchain ou apprendre Golang. Cela rend la blockchain très facile à utiliser.
    Nous pouvons en fait l'utiliser directement avec nos applications frontales dans Vue / React, la blockchain servant de base de données unique pour des tâches simples et simples et des cas d'utilisation comme le téléchargement de données ou l'obtention de hachages pour l'affichage les enregistrements pour nos utilisateurs, ou la création de jeux frontaux comme les jeux de casino et les jeux de paris (dans lesquels une grande confiance est nécessaire). De plus, avec la puissance du web3, nous pouvons stocker des données directement dans la chaîne.

Maintenant, nous avons vu un certain nombre des avantages de l'utilisation de la blockchain, mais quand ne devrions-nous pas du tout se soucier d'utiliser une blockchain?

Inconvénients de la blockchain

  • Vitesse réduite pour les transactions numériques
    Les blockchains nécessitent d'énormes quantités de puissance de calcul, ce qui tend à réduire la vitesse des transactions numériques, bien qu'il existe des solutions de contournement, il est conseillé d'utiliser des bases de données centralisées en cas de besoin de haute vitesse transactions en millisecondes.
  • Immuabilité des données
    L'immuabilité des données a toujours été l'un des plus gros inconvénients de la blockchain. Il est clair que plusieurs systèmes en bénéficient, notamment la chaîne d'approvisionnement, les systèmes financiers, etc. Cependant, il souffre du fait qu'une fois les données écrites, elles ne peuvent pas être supprimées. Chaque personne sur terre a droit à la vie privée. Cependant, si la même personne utilise une plate-forme numérique fonctionnant sur la technologie blockchain, elle ne pourra pas supprimer sa trace du système quand elle ne le souhaite pas. En termes simples, il n'y a aucun moyen qu'il puisse supprimer sa trace – laissant les droits à la vie privée en morceaux.
  • Nécessite des connaissances spécialisées
    La mise en œuvre et la gestion d'un projet blockchain est difficile. Cela nécessite des connaissances approfondies pour parcourir l'ensemble du processus. C'est pourquoi il est difficile de trouver des spécialistes ou des experts de la blockchain, car il faut beaucoup de temps et d'efforts pour former un expert de la blockchain. Par conséquent, cet article est un bon point de départ et un bon guide si vous avez déjà commencé.
  • Interopérabilité
    Plusieurs réseaux de blockchain travaillant dur pour résoudre le problème du grand livre distribué rendent difficile leur relation ou leur intégration les uns avec les autres. . Cela rend la communication entre les différentes chaînes difficile.
  • Intégration des applications héritées
    De nombreuses entreprises et applications utilisent encore des systèmes et une architecture hérités; L'adoption de la technologie blockchain nécessite une refonte complète de ces systèmes, ce qui, je dois le dire, n'est pas faisable pour beaucoup d'entre eux.

La blockchain évolue et mûrit tout le temps, alors ne soyez pas surpris si ces inconvénients mentionnés aujourd'hui se transforment en pro plus tard. Le Bitcoin, qui est une crypto-monnaie, est un exemple populaire de blockchain, une blockchain populaire qui a augmenté en dehors de la crypto-monnaie Bitcoin est la blockchain Ethereum. Bitcoin se concentre sur les crypto-monnaies tandis qu'Ethereum se concentre davantage sur les contrats intelligents qui ont été la principale force motrice des nouvelles plates-formes technologiques.

Lecture recommandée : Bitcoin vs Ethereum: quelle est la différence?

] Commençons à construire notre API

Avec une solide compréhension de la blockchain, voyons maintenant comment construire une blockchain Ethereum et l'intégrer dans une API standard dans Node.js. Le but ultime est de bien comprendre comment les plates-formes dApps et Blockchain sont construites.

La plupart des dApps ont une architecture et une structure similaires. Fondamentalement, nous avons un utilisateur qui interagit avec le frontend dApp – web ou mobile – qui interagit ensuite avec les API backend. Le backend, alors, sur demande interagit avec le (s) contrat (s) intelligent (s) ou blockchain via des nœuds publics; ceux-ci exécutent des applications Node.js ou le backend utilise la blockchain en exécutant directement le logiciel Node.js. Il y a encore tellement de choses entre ces processus, du choix de créer une application entièrement décentralisée ou semi-décentralisée au choix de ce qui doit être décentralisé et comment stocker en toute sécurité les clés privées.

Lecture recommandée : [19659045] Architecture d'applications décentralisées: modèles d'arrière-plan, de sécurité et de conception

Ce que nous devons savoir en premier

Pour ce didacticiel, nous allons essayer de créer le backend d'une application de magasin de musique décentralisée qui utilise la puissance de la blockchain Ethereum pour stocker de la musique et la partager pour les téléchargements ou la diffusion en continu.

La structure de base de l'application que nous essayons de créer comprend trois parties:

  1. Authentification qui se fait par e-mail ; bien sûr, nous devons ajouter un mot de passe crypté à l'application.
  2. Stockage des données les données musicales étant d'abord stockées dans ipfs et l'adresse de stockage est stockée dans la blockchain pour la récupération.
  3. Récupération avec tout utilisateur authentifié pouvant accéder aux données stockées sur notre plate-forme et les utiliser.

Nous allons construire cela avec Node.js, mais vous pouvez également construire avec Python ou toute autre programmation Langue. Nous verrons également comment stocker les données multimédias dans IPFS obtenir l'adresse et les fonctions d'écriture dans lesquelles stocker cette adresse – et récupérer cette adresse à partir d'une blockchain avec le langage de programmation Solidity.

En voici quelques-unes. outils dont nous devrions disposer pour construire ou travailler avec Ethereum et Node.js.

  • Node.js
    La première exigence est une application Node. Nous essayons de créer une application Node.js, nous avons donc besoin d'un compilateur. Veuillez vous assurer que Node.js est installé – et téléchargez le dernier binaire de support à long terme ( LTS ).
  • Truffle Suite
    Truffle est un contrat de développement et de test environnement, ainsi qu'un pipeline d'actifs pour la blockchain Ethereum. Il fournit un environnement pour la compilation, le pipelining et l'exécution de scripts. Une fois que vous parlez de développement de la blockchain, Truffle est un arrêt populaire où aller. Découvrez Truffle Suite sur Truffle Suite: des outils doux pour les contrats intelligents .
  • Ganache CLI
    Un autre outil qui fonctionne bien avec Truffle est Ganache-CLI. Il est construit et entretenu par l'équipe de Truffle Suite. Après la création et la compilation, vous avez besoin d'un émulateur pour développer et exécuter des applications blockchain, puis déployer des contrats intelligents à utiliser. Ganache vous permet de déployer plus facilement un contrat dans un émulateur sans utiliser d'argent réel pour le coût de transaction, les comptes recyclables et bien plus encore. Pour en savoir plus sur Ganache CLI Ganache CLI et Ganache .
  • Remix
    Remix est comme une alternative à Ganache, mais est également livré avec une interface graphique pour vous aider à naviguer dans le déploiement et les tests des contrats intelligents Ethereum. Vous pouvez en savoir plus sur Remix – Ethereum IDE & communauté . Tout ce que vous avez à faire est de visiter https://remix.ethereum.org et d'utiliser l'interface graphique pour écrire et déployer des contrats intelligents.
  • Web3
    Web3 est une collection de bibliothèques qui vous permet pour interagir avec un nœud Ethereum. Il peut s'agir de nœuds locaux ou distants du contrat via HTTP, IPC ou Web Sockets. Introduction à Web3.js · Ethereum Blockchain Developer Crash Course est un bon endroit pour en apprendre un peu plus sur Web3.
  • IPFS
    Un protocole de base qui est utilisé dans la construction de dApps. Le InterPlanetary File System (IPFS) est un protocole et un réseau peer-to-peer pour stocker et partager des données dans un système de fichiers distribué. IPFS alimente le Web distribué explique plus sur IPFS et comment il est habituellement utilisé.

Création d'une API backend à partir de zéro

Nous devons donc d'abord créer un backend à utiliser, et nous utilisons Node.js. Lorsque nous voulons créer une nouvelle API Node.js, la première chose que nous allons faire est d'initialiser un package npm. Comme vous le savez probablement, npm signifie Node Package Manager et il est livré avec le binaire Node.js. Nous créons donc un nouveau dossier et l'appelons «blockchain-music» . Nous ouvrons le terminal dans ce répertoire de dossier, puis exécutons la commande suivante:

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

Ceci démarre le projet avec un fichier package.json et répond yes à toutes les invites. Ensuite, nous créons également un fichier server.js et un fichier routes.js pour écrire les fonctions routes dans l'API.

Après tout cela, vous devra installer les packages dont nous avons besoin pour rendre notre compilation simple et directe. Ce processus est continu, c'est-à-dire que vous pouvez installer un paquet à tout moment pendant le développement de votre projet.

Installons les plus importants dont nous avons besoin maintenant:

Vous devrez également installer Truffle.js globalement vous pouvez donc l'utiliser partout dans votre environnement local. Si vous voulez les installer tous en même temps, exécutez le code suivant dans votre terminal:

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

L’indicateur - save permet d’enregistrer le nom du package dans le fichier package.json . L'indicateur -g sert à stocker globalement ce package particulier, afin que nous puissions l'utiliser dans n'importe quel projet sur lequel nous allons travailler.

Nous créons ensuite un fichier .env où nous pouvons stocker notre URI secret de base de données MongoDB pour une utilisation. Nous le faisons en exécutant touch.env dans le terminal. Si vous n’avez pas encore de compte de base de données avec MongoDB, commencez par la page MongoDB .

Le package dotenv exporte notre variable stockée vers l’environnement de processus Node.js. Assurez-vous de ne pas envoyer le fichier .env lors de la transmission vers des référentiels publics pour éviter de divulguer vos mots de passe et vos données privées.

Ensuite, nous devons ajouter des scripts pour les phases de construction et de développement de notre projet dans notre fichier package.json . Actuellement, notre package.json ressemble à ceci:

 {
  "nom": "test",
  "version": "1.0.0",
  "la description": "",
  "main": "server.js",
  "scripts": {
    "test": "echo " Erreur: aucun test spécifié  "&& exit 1"
  },
  "mots clés": [],
  "auteur": "",
  "licence": "ISC",
  "dépendances": {
    "express": "^ 4.17.1",
    "socket.io": "^ 2.3.0",
    "contrat-truffe": "^ 4.0.31",
    "web3": "^ 1.3.0"
  }
}

Nous allons ensuite ajouter un script de démarrage au fichier package.json pour utiliser le serveur nodemon afin que chaque fois que nous apportons une modification, il redémarre le serveur lui-même, et un script de construction qui utilise le nœud serveur directement, cela pourrait ressembler à ceci:

 {
  "nom": "test",
  "version": "1.0.0",
  "la description": "",
  "main": "server.js",
  "scripts": {
    "test": "echo " Erreur: aucun test spécifié  "&& exit 1",
    "start": "nodemon server.js",
    "build": "node server.js"

  },
  "mots clés": [],
  "auteur": "",
  "licence": "ISC",
  "dépendances": {
    "express": "^ 4.17.1",
    "socket.io": "^ 2.3.0",
    "contrat-truffe": "^ 4.0.31",
    "web3": "^ 1.3.0"
  }
}

Ensuite, nous devons initialiser Truffle pour une utilisation dans notre contrat intelligent en utilisant le package Truffle que nous avons installé globalement plus tôt. Dans le même dossier de nos projets, nous exécutons la commande suivante ci-dessous dans notre terminal:

 $ truffle init

Ensuite, nous pouvons commencer à écrire notre code dans notre fichier server.js . Encore une fois, nous essayons de créer une application de magasin de musique décentralisée simple, où les clients peuvent télécharger de la musique pour que tous les autres utilisateurs puissent y accéder et l'écouter.

Notre server.js doit être propre pour un couplage facile et découplage des composants, donc les routes et autres fonctionnalités seront placées dans d'autres fichiers comme le routes.js . Notre exemple server.js pourrait être:

 require ('dotenv'). Config ();
const express = require ('express')
const app = express ()
const routes = require ('./ routes')
const Web3 = require ('web3');
const mongodb = require ('mongodb'). MongoClient
contrat const = exiger ('contrat-truffe');
app.use (express.json ())

mongodb.connect (process.env.DB, {useUnifiedTopology: true}, (err, client) => {
    const db = client.db ('Cluster0')
    //domicile
    itinéraires (app, db)
    app.listen (process.env.PORT || 8082, () => {
        console.log ('écoute sur le port 8082');
     })
})

Fondamentalement, ci-dessus, nous importons les bibliothèques dont nous avons besoin avec nécessitent puis ajoutons un middleware qui permet l'utilisation de JSON dans notre API en utilisant app.use puis connectez-vous à notre MongoDB et obtenez l'accès à la base de données, puis nous spécifions à quel cluster de base de données nous essayons d'accéder (pour ce tutoriel, il s'agit de «Cluster0» ). Après cela, nous appelons la fonction et l'importons depuis le fichier de routes . Enfin, nous écoutons toute tentative de connexion sur le port 8082 .

Ce fichier server.js est juste un barebone pour démarrer l'application. Notez que nous avons importé routes.js . Ce fichier contiendra les points de terminaison de route pour notre API. Nous avons également importé les packages que nous devions utiliser dans le fichier server.js et les avons initialisés.

Nous allons créer cinq terminaux pour la consommation des utilisateurs:

  1. Enregistrement point de terminaison pour enregistrer les utilisateurs uniquement par e-mail. Idéalement, nous le ferions avec un e-mail et un mot de passe, mais comme nous voulons simplement identifier chaque utilisateur, nous n'allons pas nous aventurer dans la sécurité des mots de passe et le hachage par souci de brièveté de ce tutoriel.
     POST / S'inscrire
    Exigences: email
    
  2. Point de terminaison de connexion pour les utilisateurs par e-mail.
     POST / login
    Exigences: email
    
  3. Téléchargez le point de terminaison pour les utilisateurs – l'API qui récupère les données du fichier musical. L'interface convertira les fichiers MP3 / WAV en une mémoire tampon audio et enverra cette mémoire tampon à l'API.
     POST / upload
    Exigences: nom, titre de la musique, mémoire tampon du fichier musical ou URL stockée
    
  4. Point de terminaison d'accès qui fournira les données de la mémoire tampon de musique à tout utilisateur enregistré qui en fait la demande et enregistre les personnes qui y ont accédé.
     GET / access / {email} / {id}
    Exigences: email, identifiant
    
  5. Nous voulons également donner accès à toute la bibliothèque musicale et renvoyer les résultats à un utilisateur enregistré.
     GET / access / {email}
    Exigences: email
     

Ensuite, nous écrivons nos fonctions d'itinéraire dans notre fichier routes.js . Nous utilisons les fonctionnalités de stockage et de récupération de la base de données, puis nous nous assurons d'exporter la fonction de route à la fin du fichier pour permettre son importation dans un autre fichier ou dossier.

 const shortid = require ('short-id' )
routes de fonction (app, db) {
    app.post ('/ register', (req, res) => {
        laissez email = req.body.email
        laissez idd = shortid.generate ()
        if (email) {
            db.findOne ({email}, (err, doc) => {
                if (doc) {
                    res.status (400) .json ({"status": "Failed", "reason": "Déjà enregistré"})
                }autre{
                    db.insertOne ({email})
                    res.json ({"status": "success", "id": idd})
                }
            })
        }autre{
            res.status (400) .json ({"status": "Failed", "reason": "Incorrect input"})
        }
    })
    app.post ('/ login', (req, res) => {
        laissez email = req.body.email
        if (email) {
            db.findOne ({email}, (err, doc) => {
                if (doc) {
                    res.json ({"status": "success", "id": doc.id})
                }autre{
                    res.status (400) .json ({"status": "Failed", "reason": "Not known"})
                }
            })
        }autre{
            res.status (400) .json ({"status": "Failed", "reason": "Incorrect input"})
        }
    })
    app.post ('/ upload', (req, res) => {
        laissez buffer = req.body.buffer
        laissez name = req.body.name
        laissez title = req.body.title
        if (tampon && titre) {

        }autre{
            res.status (400) .json ({"status": "Failed", "reason": "Incorrect input"})
        }
    })
    app.get ('/ access /: email /: id', (req, res) => {
        if (req.params.id && req.params.email) {


        }autre{
            res.status (400) .json ({"status": "Failed", "reason": "Incorrect input"})
        }
    })
}
module.exports = routes

Dans cette fonction route nous avons de nombreuses autres fonctions appelées à la fois dans les paramètres app et db . Ce sont les fonctions de point de terminaison d'API qui permettent aux utilisateurs de spécifier un point de terminaison dans l'URL. En fin de compte, nous choisissons l'une de ces fonctions à exécuter et fournissons des résultats en réponse aux demandes entrantes.

Nous avons quatre principales fonctions d'extrémité:

  1. get : pour lire les opérations d'enregistrement
  2. post ]: pour créer des opérations d'enregistrement
  3. mettre : pour mettre à jour les opérations d'enregistrement
  4. delete : pour supprimer des opérations d'enregistrement

Dans cette fonction routes nous avons utilisé la get et après les opérations . Nous utilisons post pour les opérations d'enregistrement, de connexion et de téléchargement, et get pour accéder aux opérations de données. Pour un peu plus d'explications à ce sujet, vous pouvez consulter l'article de Jamie Corkhill sur « Comment démarrer avec Node: une introduction aux API, HTTP et ES6 + JavaScript ».

Dans le code ci-dessus, nous pouvons également voir certaines opérations de base de données comme dans la route register . Nous avons stocké l'email d'un nouvel utilisateur avec db.createa et vérifié l'email dans la fonction de connexion avec db.findOne . Maintenant, avant de pouvoir tout faire, nous devons nommer une collection ou une table avec la méthode db.collection . C'est exactement ce que nous allons couvrir ensuite.

Note : Pour en savoir plus sur les opérations de base de données dans MongoDB, consultez la documentation mongo Shell Methods .

Construire un contrat intelligent Blockchain simple avec Solidity

Nous allons maintenant écrire un contrat Blockchain dans Solidity (c'est le langage dans lequel les contrats intelligents sont écrits) pour simplement stocker nos données et les récupérer quand nous en avons besoin. Les données que nous voulons stocker sont les données du fichier de musique, ce qui signifie que nous devons télécharger la musique sur IPFS, puis stocker l'adresse du tampon dans une blockchain.

Tout d'abord, nous créons un nouveau fichier dans le dossier et le nom du contrat. it Inbox.sol . Pour rédiger un contrat intelligent, il est utile d'avoir une bonne compréhension de Solidity, mais ce n'est pas difficile car c'est similaire à JavaScript.

Note : Si vous souhaitez en savoir plus sur Solidity , J'ai ajouté quelques ressources au bas de l'article pour vous aider à démarrer.

 pragma solidity ^ 0.5.0;


boîte de réception du contrat {
    //Structure
    mapping (chaîne => chaîne) public ipfsInbox;
    //Événements
    événement ipfsSent (chaîne _ipfsHash, chaîne _address);
    event inboxResponse (réponse sous forme de chaîne);
    // Modificateurs
    modificateur notFull (chaîne mémoire _string) {
    octets mémoire stringTest = bytes (_string);
    require (stringTest.length == 0);
    _;
    }
    // Un constructeur vide qui crée une instance du conteact
    constructeur () public {}
    // prend l'adresse du destinataire et le hachage IPFS. Place l'adresse IPFS dans la boîte de réception du destinataire
    function sendIPFS (string memory _address, string memory _ipfsHash) notFull (ipfsInbox [_address]) public {
        ipfsInbox [_address] = _ipfsHash;
        émettre ipfsSent (_ipfsHash, _address);
    }
    // récupère le hachage
    function getHash (string memory _address) la vue publique renvoie (string memory) {
        chaîne mémoire ipfs_hash = ipfsInbox [_address];
         // émet inboxResponse (ipfs_hash);
        return ipfs_hash;
    }
}

Dans notre contrat, nous avons deux fonctions principales: les fonctions sendIPFS et getHash . Avant de parler des fonctions, nous pouvons voir que nous avons d'abord dû définir un contrat appelé Inbox . À l'intérieur de cette classe, nous avons des structures utilisées dans l'objet ipfsInbox (premiers événements, puis modificateurs).

Après avoir défini les structures et les événements, nous devons initialiser le contrat en appelant le constructeur . Ensuite, nous avons défini trois fonctions. (La fonction checkInbox a été utilisée dans le test pour tester les résultats.)

Le sendIPFS est l'endroit où l'utilisateur entre l'identifiant et l'adresse de hachage après quoi il est stocké sur la blockchain. La fonction getHash récupère l'adresse de hachage lorsqu'elle reçoit l'identifiant. Encore une fois, la logique derrière cela est que nous voulons finalement stocker la musique dans IPFS. Pour tester son fonctionnement, vous pouvez accéder à un Remix IDE copier, coller et tester votre contrat, ainsi que déboguer les erreurs et exécuter à nouveau (espérons que cela ne sera pas nécessaire!).

Après avoir testé que notre code fonctionne correctement dans le remix, passons à le compiler localement avec la suite Truffle. Mais d'abord, nous devons apporter quelques modifications à nos fichiers et configurer notre émulateur en utilisant ganache-cli :

Tout d'abord, installons ganache-cli . Dans le même répertoire, exécutez la commande suivante dans votre terminal:

 $ npm install ganache-cli -g

Ouvrons ensuite un autre terminal et exécutons une autre commande dans le même dossier:

 $ ganache-cli

Cela démarre l'émulateur de notre contrat blockchain pour se connecter et fonctionner. Réduisez le terminal et continuez avec l'autre terminal que vous avez utilisé.

Allez maintenant dans le fichier truffle.js si vous utilisez un Linux / Mac OS ou truffle-config. js dans Windows et modifiez ce fichier pour qu'il ressemble à ceci:

 const path = require ("path");
module.exports = {
  // pour personnaliser votre configuration Truffle!
  Contrats_build_directory: path.join (__ dirname, "/ build"),
  réseaux: {
    développement: {
      hôte: "127.0.0.1",
      port: 8545,
      network_id: "*" // Correspond à n'importe quel identifiant de réseau
    }
  }
};

Fondamentalement, nous avons ajouté le chemin du dossier de construction où le contrat intelligent est converti en fichiers JSON. Ensuite, nous avons également spécifié le réseau que Truffle doit utiliser pour la migration.

Ensuite, également dans le dossier migrations créez un nouveau fichier nommé 2_migrate_inbox.js et ajoutez le code suivant à l'intérieur les fichiers:

 var IPFSInbox = artifacts.require ("./ Inbox.sol");
module.exports = fonction (déployeur) {
    deployer.deploy (IPFSInbox);
};

Nous l'avons fait pour obtenir le fichier de contrat et le déployer automatiquement sur un JSON, en utilisant la fonction deployer pendant la migration de Truffle.

Après les changements ci-dessus, nous exécutons:

 $ truffle compile

Nous devrions voir quelques messages à la fin qui montrent une compilation réussie, tels que:

> Compilé avec succès en utilisant:
    - solc: 0.5.16 + commit.9c3226ce.Emscripten.clang

Ensuite, nous migrons notre contrat en exécutant:

 $ truffle migrate

Une fois que nous avons réussi à migrer nos contrats, nous devrions avoir quelque chose comme ceci à la fin:

 Résumé
=======
> Déploiements totaux: 1
> Coût final: 0,00973432 ETH

Et nous avons presque terminé! Nous avons construit notre API avec Node.js, et également mis en place et construit notre contrat intelligent.

Nous devrions également écrire des tests pour notre contrat afin de tester le comportement de notre contrat et nous assurer qu'il est le comportement souhaité. Les tests sont généralement écrits et placés dans le dossier test . Un exemple de test écrit dans un fichier nommé InboxTest.js créé dans le dossier de test est:

 const IPFSInbox = artifacts.require ("./ Inbox.sol")
contrat ("IPFSInbox", comptes => {
    it ("émettre un événement lorsque vous envoyez une adresse ipfs", async () => {
        // ait pour le contrat
        const ipfsInbox = attendre IPFSInbox.deployed ()

        // définit une variable sur false et récupère l'écouteur d'événements
        eventEmitted = faux
        // var événement = ()
        attendre ipfsInbox.ipfsSent ((err, res) => {
            eventEmitted = vrai
        })
        // appelle la fonction contract qui envoie l'adresse ipfs
        wait ipfsInbox.sendIPFS (accounts [1]"sampleAddress", {from: accounts [0]})
        assert.equal (eventEmitted, true, "l'envoi d'une requête IPFS n'émet pas d'événement")
    })
})

Nous exécutons donc notre test en exécutant ce qui suit:

 $ 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 .contractsInbox.sol
> Artifacts written to C:UsersAdemolaAppDataLocalTemptest--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)
  } else {
    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 idwe 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.

Smashing Editorial" width="35" height="46" loading="lazy" decoding="async(vf, il)




Source link