This article was first published on our open-source platform, . If you are interested in IPFS, Libp2p, Ethereum, Zero-knowledge Proofs, DeFi, CryptoEconomics, IPLD, Multiformats, and other Web 3.0 projects, concepts and interactive tutorials, then be sure to check out . SimpleAsWater.com SimpleAsWater Around the 1960s, the early research on ARPANET(predecessor of the internet) began around the question that NUCLEAR WAR How do you build a network which is so resilient, so that it could even survive a ? The reason that this topic was of such interest in the 1960s was that most of the communication infrastructure at that time looked like this: These were banks of human operators connecting wires to facilitate country-wide communication. This was a highly centralized system, which could be destroyed easily in a nuclear war. Fast-forward to today’s world, most of the internet companies today have centralized servers, most of which are hosted in the data centers outside the cities. The internet we see today is still somehow full of services similar to the bank of human operators which are highly centralized and fragile(well, we aren’t in a constant threat of a nuclear war today, but any technical or natural disaster can cause great damage). But, Why do we need to rethink about networking in 2019? Today, we are dependent on the internet more than ever. We are dependent on it for life and death situations. But the current internet, as we see it today is quite fragile and has several design problems. Most of these problems stem from the . location-addressing We can go on and on about and . Why do we need Libp2p How it works But, we are here to BUILD STUFF. So, let’s get right into it. In this series, we are going to cover a number of posts, which dives into practical, or even wild applications of peer-to-peer systems using Libp2p. We will build, and also break a lot of stuff. You can related to Blockchains and in general Web 3.0. suggest any topic for future tutorials This is the first in a series of tutorials on working with libp2p’s javascript implementation, . js-libp2p Building Chat Application using Libp2p After going through this tutorial, you will be able to: Install NodeJS Create an empty project Create a libp2p “bundle” from scratch. Adding support for multiplex & encryption. Create & Start a libp2p peer. Send messages back and forth between two peers. Install node.js Working with js-libp2p requires for development. If you haven’t already, install node using whatever package manager you prefer or . node.js using the official installer We recommend using the latest stable version of node, but anything fairly recent should work fine. If you want to see how low you can go, the current version requirements can always be found at the . js-libp2p project page Create an empty project We need a place to put our work, so open a terminal to make a new directory for your project somewhere and set it up as an npm project: $ mkdir -p hello-libp2p/src $ hello-libp2p $ git init . Initialized empty Git repository /home/vasa/Desktop/simpleaswater/libp2p/.git/ $ npm init -y # create a directory for the project and `cd` into it cd # make it a git repository in # make it an npm project Side note: throughout this tutorial, we use the character to indicate your terminal’s shell prompt. When following along, don’t type the character, or you’ll get some weird errors. $ $ Build a libp2p bundle As we learned in post, libp2p is a very modular framework, which allows javascript devs to target different runtime environments and opt-in to various features by including a custom selection of modules. what is Libp2p In easy words, let’s suppose you are at a hardware store and want to buy some tools for your toolbox. Now, you see all the available wrenches in the store. For most of us, we only want a few sizes of wrenches. So, we pick only the ones that we want. Similarly, when we build a networking stack(toolbox) for our application, we only need a few protocols & modules(wrenches). So, we should be able to select what protocols and modules we want to use and use them independently. Libp2p allows you to do the same for networking, as the hardware store does for the hardware tools, i.e. allowing you to select and use only the tools that you want to use. Now, as everyone needs a different set of wrenches, similarily, every application needs a different “bundle” with just the modules the application needs. You can even make more than one bundle if you want to target multiple javascript runtimes with different features. For example, the IPFS project uses two libp2p bundles, and . one for node.js one for the browser Since, we’re here to learn how libp2p works, we’re going to start from scratch and define our own bundle. We’ll start with a very simple bundle and add features as we need them. First, install the libp2p dependency. We’ll also need at least one transport module, so we’ll pull in libp2p-tcp as well, and the @nodeutils/defaults-deep helper which we'll use when building the bundle. $ npm install libp2p@^0.26.2 libp2p-tcp@^0.13.2 @nodeutils/defaults-deep@^1.1.0 --save In a production application, it may make sense to create a separate npm module for your bundle, which will give you one place to manage the dependencies for all your javascript projects. In that case, you should not depend on directly in your application. libp2p libp2p Instead, you’d depend on your bundle, which would, in turn, depend on libp2p and whatever modules (transports, etc) you might need. For this tutorial, our bundle will just be a javascript file in our application source. Make a file called with the following content: src/libp2p_bundle.js Libp2p = ( ) TCP = ( ) defaultsDeep = ( ) DEFAULT_OPTS = { : { : [ TCP ] } } { (opts) { (defaultsDeep(opts, DEFAULT_OPTS)) } } .exports = P2PNode const require 'libp2p' const require 'libp2p-tcp' const require '@nodeutils/defaults-deep' const modules transport class P2PNode extends Libp2p constructor super module The libp2p module exports a class which we extend into our own P2PNode class. libp2p.Node Right now our class just adds the libp2p-tcp transport module to the default constructor options of the base class. As we go, we'll extend our bundle to include more transports and configure other aspects of the libp2p stack. Create an instance of a libp2p node As we know, libp2p was born while working InterPlanetary File System project, it makes sense to make our libp2p nodes InterPlanetary. Let’s make our first node, . moon.js Using the bundle we defined above, we can create a new P2PNode instance. To do so, create a file called and make it look like this: src/moon.js PeerId = ( ) PeerInfo = ( ) Node = ( ) PeerId.createFromJSON( ( ), (err, peerId) => { (err) { err } peerInfo = PeerInfo(peerId) peerInfo.multiaddrs.add( ) nodeListener = Node({ peerInfo }) }) 'use strict' /* eslint-disable no-console */ const require 'peer-id' const require 'peer-info' const require './libp2p_bundle' require './ids/moonId' if throw const new '/ip4/127.0.0.1/tcp/10333' const new We also have to create a file containing the peerId of our moon peer. This will help other peers find our moon peer. JSON Create a file named src/ids/moonId.json $ mkdir ids $ touch moonId.json; touch earthId.json Now, add the peerId in moonId.json { : , : , : } "id" "QmcrQZ6RJdpYuGvZqD5QEHAv6qX4BrQLJLQPQUrTrzdcgm" "privKey" "CAASqAkwggSkAgEAAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAECggEAQj0obPnVyjxLFZFnsFLgMHDCv9Fk5V5bOYtmxfvcm50us6ye+T8HEYWGUa9RrGmYiLweuJD34gLgwyzE1RwptHPj3tdNsr4NubefOtXwixlWqdNIjKSgPlaGULQ8YF2tm/kaC2rnfifwz0w1qVqhPReO5fypL+0ShyANVD3WN0Fo2ugzrniCXHUpR2sHXSg6K+2+qWdveyjNWog34b7CgpV73Ln96BWae6ElU8PR5AWdMnRaA9ucA+/HWWJIWB3Fb4+6uwlxhu2L50Ckq1gwYZCtGw63q5L4CglmXMfIKnQAuEzazq9T4YxEkp+XDnVZAOgnQGUBYpetlgMmkkh9qQKBgQDvsEs0ThzFLgnhtC2Jy//ZOrOvIAKAZZf/mS08AqWH3L0/Rjm8ZYbLsRcoWU78sl8UFFwAQhMRDBP9G+RPojWVahBL/B7emdKKnFR1NfwKjFdDVaoX5uNvZEKSl9UubbC4WZJ65u/cd5jEnj+w3ir9G8n+P1gp/0yBz02nZXFgSwKBgQDZPQr4HBxZL7Kx7D49ormIlB7CCn2i7mT11Cppn5ifUTrp7DbFJ2t9e8UNk6tgvbENgCKXvXWsmflSo9gmMxeEOD40AgAkO8Pn2R4OYhrwd89dECiKM34HrVNBzGoB5+YsAno6zGvOzLKbNwMG++2iuNXqXTk4uV9GcI8OnU5ZPQKBgCZUGrKSiyc85XeiSGXwqUkjifhHNh8yH8xPwlwGUFIZimnD4RevZI7OEtXw8iCWpX2gg9XGuyXOuKORAkF5vvfVriV4e7c9Ad4Igbj8mQFWz92EpV6NHXGCpuKqRPzXrZrNOA9PPqwSs+s9IxI1dMpk1zhBCOguWx2m+NP79NVhAoGBAI6WSoTfrpu7ewbdkVzTWgQTdLzYNe6jmxDf2ZbKclrf7lNr/+cYIK2Ud5qZunsdBwFdgVcnu/02czeS42TvVBgs8mcgiQc/Uy7yi4/VROlhOnJTEMjlU2umkGc3zLzDgYiRd7jwRDLQmMrYKNyEr02HFKFn3w8kXSzW5I8rISnhAoGBANhchHVtJd3VMYvxNcQb909FiwTnT9kl9pkjhwivx+f8/K8pDfYCjYSBYCfPTM5Pskv5dXzOdnNuCj6Y2H/9m2SsObukBwF0z5Qijgu1DsxvADVIKZ4rzrGb4uSEmM6200qjJ/9U98fVM7rvOraakrhcf9gRwuspguJQnSO9cLj6" "pubKey" "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLZZcGcbe4urMBVlcHgN0fpBymY+xcr14ewvamG70QZODJ1h9sljlExZ7byLiqRB3SjGbfpZ1FweznwNxWtWpjHkQjTVXeoM4EEgDSNO/Cg7KNlU0EJvgPJXeEPycAZX9qASbVJ6EECQ40VR/7+SuSqsdL1hrmG1phpIju+D64gLyWpw9WEALfzMpH5I/KvdYDW3N4g6zOD2mZNp5y1gHeXINHWzMF596O72/6cxwyiXV1eJ000k1NVnUyrPjXtqWdVLRk5IU1LFpoQoXZU5X1hKj1a2qt/lZfH5eOrF/ramHcwhrYYw1txf8JHXWO/bbNnyemTHAvutZpTNrsWATfAgMBAAE=" Let’s see what we did above. In we start out by importing a few modules. Apart from the P2PNode bundle we defined earlier, peer-id, which contains a associated with a peer, and peer-info, which provides a libp2p Peer abstraction. moon.js PeerId The constructor for our bundle( ) requires a peerInfo argument. This can either be generated on-the-fly or loaded from a byte buffer or JSON object. libp2p_bundle.js Here, we're generating a new PeerInfo object for our peer using . This will generate a new PeerId containing the cryptographic key pair that we added in . ids/moonId.json moonId.json Once we have our peerId, we next create a for /ip4/127.0.0.1/tcp/10333, which is the on the TCP port 10333. multiaddress localhost IPv4 address Adding the new multiaddr to our peerInfo object will cause our node to try to listen to that address when the node starts. Next, we create our peer, passing in the peerInfo constructor option. That's it for setting up our moon node. Start the node and listen for connections Before starting our nodes, let’s add some colors and emojis to our command line using chalk and node-emoji. $ npm i chalk node-emoji --save-dev Now, let’s start our moon node. To do that, replace with following code: moon.js PeerId = ( ) PeerInfo = ( ) Node = ( ) chalk = ( ); emoji = ( ) PeerId.createFromJSON( ( ), (err, peerId) => { (err) { err } peerInfo = PeerInfo(peerId) peerInfo.multiaddrs.add( ) nodeListener = Node({ peerInfo }) nodeListener.start( { (err) { err } .log(emoji.get( ), chalk.blue( ), emoji.get( ), chalk.blue( )); peerInfo.multiaddrs.forEach( { .log(ma.toString() + + peerId.toB58String()) }) .log( + emoji.get( ), chalk.blue( ), emoji.get( )); }) }) 'use strict' /* eslint-disable no-console */ const require 'peer-id' const require 'peer-info' const require './libp2p_bundle' const require 'chalk' const require 'node-emoji' require './ids/moonId' if throw const new '/ip4/127.0.0.1/tcp/10333' const new ( ) => err if throw console 'moon' ' Moon ready ' 'headphones' ' Listening on: ' ( ) => ma console '/p2p/' console '\n' 'moon' ' Moon trying to connect with Earth ' 'large_blue_circle' Now, try to run the , using . You will see something like below. moon.js node moon.js Now, we have started our moon node and listening for the earth node. So, we need another node, . But before building our earth node, we need to add one final thing to make our moon node work. earth.js In case you are stuck somewhere, let us know . here Add multiplexing and encryption We can now start a node and listen for connections, but we can’t really do anything yet. This is because we’re missing a key libp2p component called a , which lets us interleave multiple independent streams of communication across one network connection. stream multiplexer But, what is multiplexing? To understand multiplexing, let’s take an example of your TV cable or WiFi router. You can see multiple channels, which all comes through a single cable attached from your setup box. Also, multiple people can connect to the same WiFi router and watch videos and read an article all at the same time…Ever wondered how you can do multiple things using a single wire or router? The answer is multiplexing. Multiplexing (or ) is a way of sending multiple signals or streams of information over a communications link at the same time in the form of a single, complex signal; the receiver recovers the separate signals, a process called demultiplexing (or ). muxing demuxing While we’re at it, we’ll also add support for encrypted communication, which will secure our moon-earth communications so that anyone cannot eavesdrop our messages. Let’s add two new dependencies: $ npm install --save libp2p-mplex@^0.8.5 libp2p-secio@^0.11.1 And we'll need to edit our bundle. Open and import the new modules: src/libp2p_bundle.js Multiplex = ( ) SECIO = ( ) const require 'libp2p-mplex' const require 'libp2p-secio' Then change the DEFAULT_OPTS constant to look like this: DEFAULT_OPTS = { : { : [ TCP ], : [ SECIO ], : [ Multiplex ] } } const modules transport connEncryption streamMuxer That’s it! Now we can open multiple independent streams over our single TCP connection, and our connection will be upgraded to a securely encrypted channel using the . secio module Let’s go interplanetary! As we have now added all the necessary components for our communication, let’s build our earth node. Add the following code in src/earth.js PeerId = ( ) PeerInfo = ( ) Node = ( ) = ( ) chalk = ( ); emoji = ( ) moonPeerId .parallel([ { PeerId.createFromJSON( ( ), (err, earthPeerId) => { (err) { err } callback( , earthPeerId) }) }, (callback) => { PeerId.createFromJSON( ( ), (err, moonPeerId) => { (err) { err } callback( , moonPeerId) }) } ], (err, ids) => { (err) err earthPeerInfo = PeerInfo(ids[ ]) earthPeerInfo.multiaddrs.add( ) nodeDialer = Node({ : earthPeerInfo }) moonPeerInfo = PeerInfo(ids[ ]) moonPeerId = ids[ ] moonPeerInfo.multiaddrs.add( ) nodeDialer.start( { (err) { err } .log(emoji.get( ), chalk.blue( ), emoji.get( ), chalk.blue( )); nodeDialer.dialProtocol(moonPeerInfo, , (err, conn) => { (err) { err } .log( + emoji.get( ), chalk.blue( )); .log( ) }) }) }) 'use strict' /* eslint-disable no-console */ const require 'peer-id' const require 'peer-info' const require './libp2p_bundle' const async require 'async' const require 'chalk' const require 'node-emoji' let async ( ) => callback require './ids/earthId' if throw null require './ids/moonId' if throw null if throw const new 0 '/ip4/127.0.0.1/tcp/0' const new peerInfo const new 1 1 '/ip4/127.0.0.1/tcp/10333' ( ) => err if throw console 'large_blue_circle' ' Earth Ready ' 'headphones' ' Listening on: ' '/chat/1.0.0' if throw console '\n' 'large_blue_circle' ' Earth dialed to Moon on protocol: /chat/1.0.0' console ` ` ${emoji.get( )} 'incoming_envelope' ${chalk.bold( )} `Type a message and press enter. See what happens...` And similarly to the moon peer, we also have to create a file containing the peerId of our earth peer. JSON { : , : , : } "id" "Qma3GsJmB47xYuyahPZPSadh1avvxfyYQwk8R3UnFrQ6aP" "privKey" "CAASpwkwggSjAgEAAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAECggEAZnrCJ6IYiLyyRdr9SbKXCNDb4YByGYPEi/HT1aHgIJfFE1PSMjxcdytxfyjP4JJpVtPjiT9JFVU2ddoYu5qJN6tGwjVwgJEWg1UXmPaAw1T/drjS94kVsAs82qICtFmwp52Apg3dBZ0Qwq/8qE1XbG7lLyohIbfCBiL0tiPYMfkcsN9gnFT/kFCX0LVs2pa9fHCRMY9rqCc4/rWJa1w8sMuQ23y4lDaxKF9OZVvOHFQkbBDrkquWHE4r55fchCz/rJklkPJUNENuncBRu0/2X+p4IKFD1DnttXNwb8j4LPiSlLro1T0hiUr5gO2QmdYwXFF63Q3mjQy0+5I4eNbjjQKBgQDZvZy3gUKS/nQNkYfq9za80uLbIj/cWbO+ZZjXCsj0fNIcQFJcKMBoA7DjJvu2S/lf86/41YHkPdmrLAEQAkJ+5BBNOycjYK9minTEjIMMmZDTXXugZ62wnU6F46uLkgEChTqEP57Y6xwwV+JaEDFEsW5N1eE9lEVX9nGIr4phMwKBgQC1TazLuEt1WBx/iUT83ita7obXqoKNzwsS/MWfY2innzYZKDOqeSYZzLtt9uTtp4X4uLyPbYs0qFYhXLsUYMoGHNN8+NdjoyxCjQRJRBkMtaNR0lc5lVDWl3bTuJovjFCgAr9uqJrmI5OHcCIk/cDpdWb3nWaMihVlePmiTcTy9wKBgQCU0u7c1jKkudqks4XM6a+2HAYGdUBk4cLjLhnrUWnNAcuyl5wzdX8dGPi8KZb+IKuQE8WBNJ2VXVj7kBYh1QmSJVunDflQSvNYCOaKuOeRoxzD+y9Wkca74qkbBmPn/6FFEb7PSZTO+tPHjyodGNgz9XpJJRjQuBk1aDJtlF3m1QKBgE5SAr5ym65SZOU3UGUIOKRsfDW4Q/OsqDUImvpywCgBICaX9lHDShFFHwau7FA52ScL7vDquoMB4UtCOtLfyQYA9995w9oYCCurrVlVIJkb8jSLcADBHw3EmqF1kq3NqJqm9TmBfoDCh52vdCCUufxgKh33kfBOSlXuf7B8dgMbAoGAZ3r0/mBQX6S+s5+xCETMTSNv7TQzxgtURIpVs+ZVr2cMhWhiv+n0Omab9X9Z50se8cWl5lkvx8vn3D/XHHIPrMF6qk7RAXtvReb+PeitNvm0odqjFv0J2qki6fDs0HKwq4kojAXI1Md8Th0eobNjsy21fEEJT7uKMJdovI/SErI=" "pubKey" "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaNSDOjPz6T8HZsf7LDpxiQRiN2OjeyIHUS05p8QWOr3EFUCFsC31R4moihE5HN+FxNalUyyFZU//yjf1pdnlMJqrVByJSMa+y2y4x2FucpoCAO97Tx+iWzwlZ2UXEUXM1Y81mhPbeWXy+wP2xElTgIER0Tsn/thoA0SD2u9wJuVvM7dB7cBcHYmqV6JH+KWCedRTum6O1BssqP/4Lbm2+rkrbZ4+oVRoU2DRLoFhKqwqLtylrbuj4XOI3XykMXV5+uQXz1JzubNOB9lsc6K+eRC+w8hhhDuFMgzkZ4qomCnx3uhO67KaICd8yqqBa6PJ/+fBM5Xk4hjyR40bwcf41AgMBAAE=" Here in , we used the same modules as we used in . The only new module we use here is async, which is used to generate peerIds for moon and earth peers, in parallel. earth.js moon.js Then, as we did in we create the earthPeerInfo, add a , /ip4/127.0.0.1/tcp/0 and finally, create our earth node nodeDialer. moon.js multiaddr Notice that we also, create moonPeerInfo and add the same , that we added in . We do this as the earth node needs to know about the moonPeerInfo in order to our moon peer. So, the moonPeerInfo acts like a phone number here. multiaddr moon.js dial And finally, we start our earth peer and dial the moon peer using nodeDialer.dialProtocol. While dialing to our moon peer, we need to specify a protocol (/chat/1.0.0), using which we will talk to our moon peer. It's like deciding a common language before we start talking to each other. Otherwise, it would make no sense. Now, as earth peer hash defined that it will use /chat/1.0.0 protocol to communicate with the moon peer, let's add that to the as well. moon.js To do that, we need to install a few more libs: $ npm i pull-stream@^3.6.9 pull-pushable --save Now, replace the with the following code: moon.js PeerId = ( ) PeerInfo = ( ) Node = ( ) pull = ( ) Pushable = ( ) p = Pushable() chalk = ( ); emoji = ( ) PeerId.createFromJSON( ( ), (err, peerId) => { (err) { err } peerInfo = PeerInfo(peerId) peerInfo.multiaddrs.add( ) nodeListener = Node({ peerInfo }) nodeListener.start( { (err) { err } nodeListener.on( , (peerInfo) => { .log(emoji.get( ), chalk.blue( ), emoji.get( ), chalk.blue( )); .log( + emoji.get( ), chalk.green( ) + emoji.get( )) }) nodeListener.handle( , (protocol, conn) => { pull( p, conn ) pull( conn, pull.map( { data.toString( ).replace( , ) }), pull.drain( .log) ) }) .log(emoji.get( ), chalk.blue( ), emoji.get( ), chalk.blue( )); peerInfo.multiaddrs.forEach( { .log(ma.toString() + + peerId.toB58String()) }) .log( + emoji.get( ), chalk.blue( ), emoji.get( )); }) }) 'use strict' /* eslint-disable no-console */ const require 'peer-id' const require 'peer-info' const require './libp2p_bundle' const require 'pull-stream' const require 'pull-pushable' const const require 'chalk' const require 'node-emoji' require './ids/moonId' if throw const new '/ip4/127.0.0.1/tcp/10333' const new ( ) => err if throw 'peer:connect' console 'moon' ' Moon found Earth ' 'large_blue_circle' ` on: ` ${peerInfo.id.toB58String()} console '\n' 'moon' ' Moon waiting for message from Earth ' 'large_blue_circle' '/chat/1.0.0' ( ) => data return 'utf8' '\n' '' console console 'moon' ' Moon ready ' 'headphones' ' Listening on: ' ( ) => ma console '/p2p/' console '\n' 'moon' ' Moon trying to connect with Earth ' 'large_blue_circle' Now, as have defined /chat/1.0.0 protocol for moon peer too, let's try to connect earth peer to our moon peer. First, run node in one terminal. Then fire up another terminal and run . moon.js node earth.js If everything went right, then you would see something like below: In case you are stuck somewhere, let us know . here Let’s talk to the moon Till now we have managed to connect moon peer and earth peer. Another interesting thing that we can do here to allow these 2 peers to communicate with each other. We will use the command line to write and send our messages. To do that we need to handle and send messages from the command prompt. We can do that using module available in NodeJS. process Replace with the following code: moon.js PeerId = ( ) PeerInfo = ( ) Node = ( ) pull = ( ) Pushable = ( ) p = Pushable() chalk = ( ); emoji = ( ) PeerId.createFromJSON( ( ), (err, peerId) => { (err) { err } peerInfo = PeerInfo(peerId) peerInfo.multiaddrs.add( ) nodeListener = Node({ peerInfo }) nodeListener.start( { (err) { err } nodeListener.on( , (peerInfo) => { .log(emoji.get( ), chalk.blue( ), emoji.get( ), chalk.blue( )); .log( + emoji.get( ), chalk.green( ) + emoji.get( )) }) nodeListener.handle( , (protocol, conn) => { pull( p, conn ) pull( conn, pull.map( { data.toString( ).replace( , ) }), pull.drain( .log) ) process.stdin.setEncoding( ) process.openStdin().on( , (chunk) => { data = + chunk.toString() + p.push(data) }) }) .log(emoji.get( ), chalk.blue( ), emoji.get( ), chalk.blue( )); peerInfo.multiaddrs.forEach( { .log(ma.toString() + + peerId.toB58String()) }) .log( + emoji.get( ), chalk.blue( ), emoji.get( )); }) }) 'use strict' /* eslint-disable no-console */ const require 'peer-id' const require 'peer-info' const require './libp2p_bundle' const require 'pull-stream' const require 'pull-pushable' const const require 'chalk' const require 'node-emoji' require './ids/moonId' if throw const new '/ip4/127.0.0.1/tcp/10333' const new ( ) => err if throw 'peer:connect' console 'moon' ' Moon found Earth ' 'large_blue_circle' ` on: ` ${peerInfo.id.toB58String()} console '\n' 'moon' ' Moon waiting for message from Earth ' 'large_blue_circle' '/chat/1.0.0' ( ) => data return 'utf8' '\n' '' console 'utf8' 'data' var ` \n\n` ${chalk.blue( )} "Message received from Moon: " `\n ` ${emoji.get( )} 'incoming_envelope' ${chalk.blue( )} " Send message from Earth:" console 'moon' ' Moon ready ' 'headphones' ' Listening on: ' ( ) => ma console '/p2p/' console '\n' 'moon' ' Moon trying to connect with Earth ' 'large_blue_circle' Replace with the following code: earth.js PeerId = ( ) PeerInfo = ( ) Node = ( ) pull = ( ) = ( ) chalk = ( ); emoji = ( ) Pushable = ( ) p = Pushable() moonPeerId .parallel([ { PeerId.createFromJSON( ( ), (err, earthPeerId) => { (err) { err } callback( , earthPeerId) }) }, (callback) => { PeerId.createFromJSON( ( ), (err, moonPeerId) => { (err) { err } callback( , moonPeerId) }) } ], (err, ids) => { (err) err earthPeerInfo = PeerInfo(ids[ ]) earthPeerInfo.multiaddrs.add( ) nodeDialer = Node({ : earthPeerInfo }) moonPeerInfo = PeerInfo(ids[ ]) moonPeerId = ids[ ] moonPeerInfo.multiaddrs.add( ) nodeDialer.start( { (err) { err } .log(emoji.get( ), chalk.blue( ), emoji.get( ), chalk.blue( )); nodeDialer.dialProtocol(moonPeerInfo, , (err, conn) => { (err) { err } .log( + emoji.get( ), chalk.blue( )); .log( ) pull( p, conn ) pull( conn, pull.map( { data.toString( ).replace( , ) }), pull.drain( .log) ) process.stdin.setEncoding( ) process.openStdin().on( , (chunk) => { data = chunk.toString() data = + chunk.toString() + p.push(data) }) }) }) }) 'use strict' /* eslint-disable no-console */ const require 'peer-id' const require 'peer-info' const require './libp2p_bundle' const require 'pull-stream' const async require 'async' const require 'chalk' const require 'node-emoji' const require 'pull-pushable' const let async ( ) => callback require './ids/earthId' if throw null require './ids/moonId' if throw null if throw const new 0 '/ip4/127.0.0.1/tcp/0' const new peerInfo const new 1 1 '/ip4/127.0.0.1/tcp/10333' ( ) => err if throw console 'large_blue_circle' ' Earth Ready ' 'headphones' ' Listening on: ' '/chat/1.0.0' if throw console '\n' 'large_blue_circle' ' Earth dialed to Moon on protocol: /chat/1.0.0' console ` ` ${emoji.get( )} 'incoming_envelope' ${chalk.bold( )} `Type a message and press enter. See what happens...` // Write operation. Data sent as a buffer // Sink, data converted from buffer to utf8 string ( ) => data return 'utf8' '\n' '' console 'utf8' 'data' var var ` \n\n` ${chalk.blue( )} "Message received from Earth: " `\n ` ${emoji.get( )} 'incoming_envelope' ${chalk.blue( )} " Send message from Moon:" That’s all. , in one terminal. Then . First run node moon.js fire up another terminal and run node earth.js Now, if everything in fine, then you will see the earth peer asking you to . If you do that, you can see the same message is received on the moon peer. Also, if you type something and press enter from the moon peer, you can see the same message on the earth peer. type something and press enter Congratulations🎉🎉 You are one of the very few people to communicate from earth to moon!! In case you are stuck somewhere, let us know . here This article was first published on SimpleAsWater.com .