Created
August 16, 2021 10:53
-
-
Save TheBojda/e201e9f9805edb032a7fdb3006c2ce96 to your computer and use it in GitHub Desktop.
libp2p browser chat example in JavaScript with vue.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div> | |
<p>Your peerId: {{ myPeerId }}</p> | |
<p> | |
Other peerId: | |
<input type="text" style="width: 420px" v-model="otherPeerId" /><button | |
@click="findOtherPeer" | |
> | |
Find | |
</button> | |
</p> | |
<p v-for="(multiaddr, idx) in otherPeerMultiaddrs" :key="'ma_' + idx"> | |
Other peer multiaddr: {{ multiaddr.toString() }} | |
</p> | |
<p v-for="(protocol, idx) in otherPeerProtocols" :key="'p_' + idx"> | |
Other peer protocol: {{ protocol }} | |
</p> | |
<div v-if="otherPeerMultiaddrs.length > 0 && otherPeerProtocols.length > 0"> | |
<p> | |
{{ otherPeerMultiaddr }}{{ otherPeerProtocol }} | |
<button @click="dialProtocol">Dial protocol</button> | |
</p> | |
</div> | |
<p v-if="remotePeerId"> | |
Remote peer connected: {{ remotePeerId.toString() }} | |
</p> | |
<p v-for="(msg, idx) in messages" :key="'msg_' + idx"> | |
{{ msg }} | |
</p> | |
<div v-if="chatQueue"> | |
<input type="text" style="width: 600px" v-model="chatMessage" /><button | |
@click="sendMessage" | |
> | |
Send message | |
</button> | |
</div> | |
</div> | |
</template> | |
<script lang="ts"> | |
import "babel-polyfill"; | |
import Libp2p from "libp2p"; | |
import Websockets from "libp2p-websockets"; | |
import WebRTCStar from "libp2p-webrtc-star"; | |
import { NOISE } from "libp2p-noise"; | |
import Mplex from "libp2p-mplex"; | |
import Bootstrap from "libp2p-bootstrap"; | |
import KadDHT from "libp2p-kad-dht"; | |
import PeerId from "peer-id"; | |
import pushable from "it-pushable"; | |
import pipe from "it-pipe"; | |
import { array2str, str2array } from "./utils"; | |
import { Component, Vue } from "vue-property-decorator"; | |
const chatProtocol = "/chat/1.0.0"; | |
@Component | |
export default class App extends Vue { | |
private libp2p: Libp2p; | |
private myPeerId: string = ""; | |
private otherPeerId: string = ""; | |
private otherPeerMultiaddrs: any[] = []; | |
private otherPeerProtocols: string[] = []; | |
private otherPeerMultiaddr: string = ""; | |
private otherPeerProtocol: string = ""; | |
private remotePeerId: any = ""; | |
private chatMessage: string = ""; | |
private messages: string[] = []; | |
private chatQueue: any = false; | |
async init() { | |
this.libp2p = await Libp2p.create({ | |
addresses: { | |
listen: [ | |
"/dns4/wrtc-star1.par.dwebops.pub/tcp/443/wss/p2p-webrtc-star", | |
"/dns4/wrtc-star2.sjc.dwebops.pub/tcp/443/wss/p2p-webrtc-star", | |
], | |
}, | |
modules: { | |
transport: [Websockets, WebRTCStar], | |
connEncryption: [NOISE], | |
streamMuxer: [Mplex], | |
peerDiscovery: [Bootstrap], | |
dht: KadDHT, | |
}, | |
config: { | |
peerDiscovery: { | |
[Bootstrap.tag]: { | |
enabled: true, | |
list: [ | |
"/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN", | |
"/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb", | |
"/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp", | |
"/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa", | |
"/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt", | |
], | |
}, | |
}, | |
dht: { | |
enabled: true, | |
}, | |
}, | |
}); | |
await this.libp2p.start(); | |
this.myPeerId = this.libp2p.peerId.toB58String(); | |
this.libp2p.handle(chatProtocol, ({ connection, stream, protocol }) => { | |
this.remotePeerId = connection.remoteAddr.getPeerId(); | |
pipe( | |
stream, | |
(source) => { | |
return (async function* () { | |
for await (const buf of source) yield array2str(buf.slice()); | |
})(); | |
}, | |
async (source) => { | |
for await (const msg of source) { | |
this.messages.push("> " + msg); | |
} | |
} | |
); | |
}); | |
} | |
mounted() { | |
this.init(); | |
} | |
async findOtherPeer() { | |
let peerId = PeerId.parse(this.otherPeerId); | |
let result = await this.libp2p.peerRouting.findPeer(peerId); | |
this.otherPeerMultiaddrs = result.multiaddrs; | |
this.otherPeerProtocols = this.libp2p.peerStore.protoBook.get(peerId); | |
this.otherPeerMultiaddr = this.otherPeerMultiaddrs[0]; | |
this.otherPeerProtocol = chatProtocol; | |
} | |
async dialProtocol() { | |
let peerId = PeerId.parse(this.otherPeerId); | |
const { stream, protocol } = await this.libp2p.dialProtocol( | |
peerId, | |
chatProtocol | |
); | |
this.chatQueue = pushable(); | |
pipe( | |
this.chatQueue, | |
(source) => { | |
return (async function* () { | |
for await (const msg of source) yield str2array(msg); | |
})(); | |
}, | |
stream | |
); | |
} | |
sendMessage() { | |
this.chatQueue.push(this.chatMessage); | |
this.messages.push("< " + this.chatMessage); | |
this.chatMessage = ""; | |
} | |
} | |
</script> | |
<style> | |
body { | |
padding: 20px; | |
} | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// based on https://www.dreamincode.net/forums/topic/353343-how-to-convert-uint8array-to-uint16array-or-string/ | |
export function array2str(uint8buf) { | |
let buf = new ArrayBuffer(uint8buf.length); | |
let bufView = new Uint16Array(buf); | |
let count = 0; | |
for (let i = 0; i < bufView.length; i++) { | |
bufView[i] = uint8buf[count++] + (uint8buf[count++] << 8); | |
} | |
return String.fromCharCode.apply(null, bufView); | |
} | |
// based on str2ab from https://gist.github.com/skratchdot/e095036fad80597f1c1a | |
export function str2array(str) { | |
let buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char | |
let bufView = new Uint16Array(buf); | |
for (var i = 0, strLen = str.length; i < strLen; i++) { | |
bufView[i] = str.charCodeAt(i); | |
} | |
return new Uint8Array(bufView.buffer, bufView.byteOffset, bufView.byteLength); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Original repo: https://github.com/TheBojda/js-libp2p-browser-chat
Online demo: https://thebojda.github.io/js-libp2p-browser-chat/index.html