Skip to content

Instantly share code, notes, and snippets.

@bellbind
Last active August 14, 2024 22:40
Show Gist options
  • Save bellbind/23ad8d6e3a1509335253ff074fcd3cb6 to your computer and use it in GitHub Desktop.
Save bellbind/23ad8d6e3a1509335253ff074fcd3cb6 to your computer and use it in GitHub Desktop.
[helia] serving contents from browser to browser with nodejs helia as a bootstrap target

0. Setup

Clone this repo:

$ git clone https://gist.github.com/23ad8d6e3a1509335253ff074fcd3cb6.git helia-b2b-sharing
$ cd helia-b2b-sharing/

Generate npm-browser.js npm package bundle:

$ npm i
$ npm run build

1. Run code

$ node case-b2b.mjs
...

1.1. Successful case: WebRTCStream

...
{ url: '', lineNumber: 4, columnNumber: 10 } [peerId on browser1] 12D3KooWChrHSYCoL4H8FYYPBPY9setKbK8wk4hAhN6oB2b217uV
[serving cid on browser1] bafkreif5viehisdkgsxmfrmu5crzazgqhtg7xaifnjzyrcypsddkfnecaa
...
{ url: '', lineNumber: 4, columnNumber: 10 } [peerId on browser2] 12D3KooWCmcNxC3JyMEPTtUDob5Y18B7opU3Gcfzaj62J2ei4RuQ
[browser1 multiaddrs] [
  '/ip4/127.0.0.1/tcp/63705/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit/webrtc/p2p/12D3KooWChrHSYCoL4H8FYYPBPY9setKbK8wk4hAhN6oB2b217uV',
  '/ip4/192.168.10.5/tcp/63705/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit/webrtc/p2p/12D3KooWChrHSYCoL4H8FYYPBPY9setKbK8wk4hAhN6oB2b217uV',
  '/ip4/127.0.0.1/tcp/63706/ws/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit/webrtc/p2p/12D3KooWChrHSYCoL4H8FYYPBPY9setKbK8wk4hAhN6oB2b217uV',
  '/ip4/192.168.10.5/tcp/63706/ws/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit/webrtc/p2p/12D3KooWChrHSYCoL4H8FYYPBPY9setKbK8wk4hAhN6oB2b217uV',
  '/ip4/127.0.0.1/tcp/63705/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit/p2p/12D3KooWChrHSYCoL4H8FYYPBPY9setKbK8wk4hAhN6oB2b217uV',
  '/ip4/192.168.10.5/tcp/63705/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit/p2p/12D3KooWChrHSYCoL4H8FYYPBPY9setKbK8wk4hAhN6oB2b217uV',
  '/ip4/127.0.0.1/tcp/63706/ws/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit/p2p/12D3KooWChrHSYCoL4H8FYYPBPY9setKbK8wk4hAhN6oB2b217uV',
  '/ip4/192.168.10.5/tcp/63706/ws/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit/p2p/12D3KooWChrHSYCoL4H8FYYPBPY9setKbK8wk4hAhN6oB2b217uV'
]
...
{ url: '', lineNumber: 5, columnNumber: 14 } [dialProtocol from browser2 to browser1] /ip4/127.0.0.1/tcp/63705/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit/webrtc/p2p/12D3KooWChrHSYCoL4H8FYYPBPY9setKbK8wk4hAhN6oB2b217uV WebRTCStream WebRTCStream
{ url: '', lineNumber: 4, columnNumber: 12 } [findProviders peer.id] 12D3KooWChrHSYCoL4H8FYYPBPY9setKbK8wk4hAhN6oB2b217uV
{ url: '', lineNumber: 5, columnNumber: 12 } [findProviders peer.multiaddrs.length] 8
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/127.0.0.1/tcp/63705/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/127.0.0.1/tcp/63705/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit/webrtc
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/127.0.0.1/tcp/63706/ws/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/127.0.0.1/tcp/63706/ws/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit/webrtc
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/192.168.10.5/tcp/63705/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/192.168.10.5/tcp/63705/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit/webrtc
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/192.168.10.5/tcp/63706/ws/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/192.168.10.5/tcp/63706/ws/p2p/12D3KooWMyU11MoSF8Bov94UZpTeEhyjeJk9YjdZfTPZd6tqwSVb/p2p-circuit/webrtc
{ url: '', lineNumber: 7, columnNumber: 12 } [findProviders peer.protocolss.length] 0
{ url: '', lineNumber: 13, columnNumber: 10 } [stat of cid from other browser] {cid: _CID, mode: undefined, mtime: undefined, fileSize: 18n, dagSize: 18n}
{ url: '', lineNumber: 19, columnNumber: 10 } [text of cid from other browser] Hello from browser
[closing...]
...

1.2.1. Failed case: WebRTCStream Query aborted

...
{ url: '', lineNumber: 5, columnNumber: 14 } [dialProtocol from browser2 to browser1] /ip4/127.0.0.1/tcp/58264/p2p/12D3KooWQ4mcV74JLYwTaCi2wYev7VJSgmumuL5bYe5CE7CfQUWm/p2p-circuit/webrtc/p2p/12D3KooWP83taKU7797FKSu1eHvGH2QF9yaoriz6mHXorWohHJjc WebRTCStream WebRTCStream
node:internal/process/esm_loader:46
      internalBinding('errors').triggerUncaughtException(
                                ^

page.evaluate: CodeError: Query aborted
    at AbortSignal.<anonymous> (http://localhost:58266/npm-browser.js:80209:23)
    at AbortSignal.onAbort (http://localhost:58266/npm-browser.js:29123:16)
    at file:///Users/bellbind/exp/helia/helia-b2l-direct/case-b2b.mjs:78:13

Node.js v20.5.1

1.2.2. Failed case: WebRTCStream Query was aborted before self-query ran

...
{ url: '', lineNumber: 5, columnNumber: 14 } [dialProtocol from browser2 to browser1] /ip4/127.0.0.1/tcp/60864/p2p/12D3KooWLzWHFaYcJqaJRZPA9jnG7U8vzh4DVPoMMhWcwT4EWZ3f/p2p-circuit/webrtc/p2p/12D3KooWJ89ZttD5WsQJBB6Jn2Dq4fhZUnhBqRTWDdiAGjCBPLwz WebRTCStream WebRTCStream
node:internal/process/esm_loader:46
      internalBinding('errors').triggerUncaughtException(
                                ^

page.evaluate: Error: Query was aborted before self-query ran
    at AbortSignal.<anonymous> (http://localhost:60866/npm-browser.js:80311:22)
    at AbortSignal.onAbort (http://localhost:60866/npm-browser.js:29123:16)
    at file:///Users/bellbind/exp/helia/helia-b2l-direct/case-b2b.mjs:78:13

Node.js v20.5.1

1.2.3. Failed case: YamuxStream

...
{ url: '', lineNumber: 5, columnNumber: 14 } [dialProtocol from browser2 to browser1] /ip4/127.0.0.1/tcp/64416/p2p/12D3KooWFfV7F3p2pScoLfqbvnHdEDre6MiYNGsSkBCpJnHyQJ35/p2p-circuit/webrtc/p2p/12D3KooWNgvfGamtMAJb7sbJaPRtcsdgqKRFAtg8FiAKCsLFbBwx YamuxStream YamuxStream
{ url: '', lineNumber: 4, columnNumber: 12 } [findProviders peer.id] 12D3KooWHnN6wa4Dav2k5KEPnZqSvotjvPhYYCZN99YMS8otMoLw
{ url: '', lineNumber: 5, columnNumber: 12 } [findProviders peer.multiaddrs.length] 8
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/192.168.10.5/tcp/57038/ws/p2p/12D3KooWFGWBySRPkvMkZnWiRzymQNzSqgWQfNRVJEyhwwnHG36U/p2p-circuit
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/127.0.0.1/tcp/57037/p2p/12D3KooWFGWBySRPkvMkZnWiRzymQNzSqgWQfNRVJEyhwwnHG36U/p2p-circuit/webrtc
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/192.168.10.5/tcp/57037/p2p/12D3KooWFGWBySRPkvMkZnWiRzymQNzSqgWQfNRVJEyhwwnHG36U/p2p-circuit/webrtc
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/127.0.0.1/tcp/57038/ws/p2p/12D3KooWFGWBySRPkvMkZnWiRzymQNzSqgWQfNRVJEyhwwnHG36U/p2p-circuit/webrtc
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/192.168.10.5/tcp/57038/ws/p2p/12D3KooWFGWBySRPkvMkZnWiRzymQNzSqgWQfNRVJEyhwwnHG36U/p2p-circuit/webrtc
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/127.0.0.1/tcp/57037/p2p/12D3KooWFGWBySRPkvMkZnWiRzymQNzSqgWQfNRVJEyhwwnHG36U/p2p-circuit
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/192.168.10.5/tcp/57037/p2p/12D3KooWFGWBySRPkvMkZnWiRzymQNzSqgWQfNRVJEyhwwnHG36U/p2p-circuit
{ url: '', lineNumber: 6, columnNumber: 46 } [findProviders peer.multiaddrs] /ip4/127.0.0.1/tcp/57038/ws/p2p/12D3KooWFGWBySRPkvMkZnWiRzymQNzSqgWQfNRVJEyhwwnHG36U/p2p-circuit
{ url: '', lineNumber: 7, columnNumber: 12 } [findProviders peer.protocolss.length] 0
{
  url: 'http://localhost:64418/browser.js',
  lineNumber: 66,
  columnNumber: 37
} [/ipfs/bitswap/1.2.0 on 12D3KooWH3FMEApxmAvhfw1pZuQpB3GDggCw8CF2xXjBuony2Xr1] onDisconnect 12D3KooWNgvfGamtMAJb7sbJaPRtcsdgqKRFAtg8FiAKCsLFbBwx
^Cnode:internal/process/esm_loader:46
      internalBinding('errors').triggerUncaughtException(
                                ^

page.evaluate: Target closed
    at file:///Users/bellbind/exp/helia/helia-b2l-direct/case-b2b.mjs:78:13 {
  name: 'Error'
}

Node.js v20.5.1
  • NOTE: Stop with Ctrl+C after onDisconnect printed
import {createHelia} from "helia";
import {unixfs} from "@helia/unixfs";
import {CID} from "multiformats/cid";
import {multiaddr} from "@multiformats/multiaddr";
import {peerIdFromString} from "@libp2p/peer-id";
import {createTopology} from "@libp2p/topology";
import {mplex} from "@libp2p/mplex";
import {yamux} from "@chainsafe/libp2p-yamux";
import {bootstrap} from "@libp2p/bootstrap";
import {pubsubPeerDiscovery} from "@libp2p/pubsub-peer-discovery";
import {circuitRelayTransport, circuitRelayServer} from "libp2p/circuit-relay";
import {webRTC, webRTCDirect} from "@libp2p/webrtc";
import {webTransport} from "@libp2p/webtransport";
import {webSockets} from "@libp2p/websockets";
import {all} from "@libp2p/websockets/filters";
import {identifyService} from "libp2p/identify";
import {autoNATService} from "libp2p/autonat";
import {gossipsub} from "@chainsafe/libp2p-gossipsub";
import {kadDHT} from "@libp2p/kad-dht";
import {ipnsSelector} from "ipns/selector";
import {ipnsValidator} from "ipns/validator";
export const createHeliaFromMultiaddrs = async multiaddrs => {
// browser helia node which bootstrap target is localhost helia node
const bootstrapConfig = {list: multiaddrs};
const node = await createHelia({
libp2p: {
// https://github.com/ipfs/helia/blob/main/packages/helia/src/utils/libp2p-defaults.browser.ts#L27
addresses: {
listen: [
"/webrtc", "/wss", "/ws",
],
},
transports: [
webSockets({filter: all}),
webRTC(), webRTCDirect(),
webTransport(),
// https://github.com/libp2p/js-libp2p-websockets#libp2p-usage-example
circuitRelayTransport({discoverRelays: 3}),
],
//streamMuxers: [mplex()],
streamMuxers: [yamux()],
peerDiscovery: [bootstrap(bootstrapConfig), pubsubPeerDiscovery()],
services: {
identify: identifyService(),
autoNAT: autoNATService(),
//pubsub: gossipsub({allowPublishToZeroPeers: true, emitSelf: false, canRelayMessage: true}),
pubsub: gossipsub({allowPublishToZeroPeers: true, emitSelf: true, canRelayMessage: true}),
dht: kadDHT({
clientMode: true,
validators: {ipns: ipnsValidator},
selectors: {ipns: ipnsSelector},
}),
},
// https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md#configuring-connection-gater
connectionGater: {denyDialMultiaddr: async (...args) => false},
},
});
// print peer connecting info
node.libp2p.addEventListener("peer:connect", ev => {
console.log(`[peer:connect on ${node.libp2p.peerId}]`, ev.detail.toString());
});
// js-ipfs-bitswap/src/network.ts
await node.libp2p.register("/ipfs/bitswap/1.2.0", createTopology({
onConnect: (peerId, conn) => {console.log(`[/ipfs/bitswap/1.2.0 on ${node.libp2p.peerId}] onConnect`, `${peerId}`);},
onDisconnect: peerId => {console.log(`[/ipfs/bitswap/1.2.0 on ${node.libp2p.peerId}] onDisconnect`, `${peerId}`);},
}));
// wait to connect bootstrap
while (node.libp2p.getMultiaddrs().length === 0) await new Promise(f => setTimeout(f, 500));
const nodefs = unixfs(node);
return {node, nodefs, CID, peerIdFromString, multiaddr}; // returns helia node and imported utils
};
// Example of indirect connect of 2 helia noeds between browser and browser connected to same helia on nodejs
// resolve cid from browser to browser
import {CID} from "multiformats/cid";
import {unixfs} from "@helia/unixfs";
import {chromium} from "playwright";
import {createServer} from "http-server";
import {createNode} from "./nodejs.js";
// [1. nodejs helia node]
const node = await createNode();
console.log("[peerId on nodejs]", `${node.libp2p.peerId}`);
// [2. http server for url to playwright]
const httpServer = createServer();
await new Promise(f => httpServer.server.listen(f));
const pageUrl = `http://localhost:${httpServer.server.address().port}/index.html`; // importmap only html
console.log("[page server url]", pageUrl);
// [3. helia node on playwright]
const browser = await chromium.launch();
const page1 = await browser.newPage();
await page1.goto(pageUrl);
page1.on("console", msg => {
if (msg.type() === "log") console.log(msg.location(), msg.text());
//if (msg.type() === "error") console.log(msg.location(), msg.text());
});
const page2 = await browser.newPage();
await page2.goto(pageUrl);
page2.on("console", msg => {
if (msg.type() === "log") console.log(msg.location(), msg.text());
//if (msg.type() === "error") console.log(msg.location(), msg.text());
});
const cidStr = await page1.evaluate(({multiaddrs}) => (async () => {
const {createHeliaFromMultiaddrs} = await import("./browser.js");
globalThis.ctx = await createHeliaFromMultiaddrs(multiaddrs);
console.log("[peerId on browser1]", `${ctx.node.libp2p.peerId}`);
// [4. serve content on browser helia node]
const cid = await ctx.nodefs.addBytes(new TextEncoder().encode("Hello from browser"));
try {ctx.node.pins.add(cid);} catch (error) {}
return `${cid}`;
})(), {multiaddrs: node.libp2p.getMultiaddrs().map(ma => `${ma}`)});
console.log("[serving cid on browser1]", cidStr);
await page2.evaluate(({multiaddrs}) => (async () => {
const {createHeliaFromMultiaddrs} = await import("./browser.js");
globalThis.ctx = await createHeliaFromMultiaddrs(multiaddrs);
console.log("[peerId on browser2]", `${ctx.node.libp2p.peerId}`);
})(), {multiaddrs: node.libp2p.getMultiaddrs().map(ma => `${ma}`)});
// [5. dialProtocol from browser2 to browser1] required before access on helia-2.0.1
const multiaddrs = await await page1.evaluate(() => (async () => {
return ctx.node.libp2p.getMultiaddrs().map(ma => `${ma}`);
})());
console.log("[browser1 multiaddrs]", multiaddrs);
await page2.evaluate(({multiaddrs}) => (async () => {
for (const ma of multiaddrs) {
try {
const stream = await ctx.node.libp2p.dialProtocol(ctx.multiaddr(ma), "/ipfs/bitswap/1.2.0", {runOnTransientConnection: true});
const isWebRTCStream = stream.constructor.name === "WebRTCStream";
console.log("[dialProtocol from browser2 to browser1]", ma, stream, stream.constructor.name);
//await stream.close();
break;
} catch (error) {
console.log("[dialProtocol error]", error);
//TBD: how to set runOnTransientConnection = true?
}
}
})(), {multiaddrs});
// [6. access cid from browser to browser]
await page2.evaluate(({cidStr}) => (async () => {
const cid = ctx.CID.parse(cidStr);
// print result of findProviders(cid)
for await (const peer of ctx.node.libp2p.contentRouting.findProviders(cid)) {
console.log("[findProviders peer.id]", `${peer.id}`);
console.log("[findProviders peer.multiaddrs.length]", peer.multiaddrs.length);
for (const ma of peer.multiaddrs) console.log("[findProviders peer.multiaddrs]", `${ma}`);
console.log("[findProviders peer.protocolss.length]", peer.protocols.length);
for (const proto of peer.protocols) console.log("[findProviders peer.protocols]", `${proto}`);
break;
}
const stat = await ctx.nodefs.stat(cid); // halt
console.log("[stat of cid from other browser]", stat);
const decoder = new TextDecoder();
const texts = [];
for await (const chunk of ctx.nodefs.cat(cid)) {
texts.push(decoder.decode(chunk, {stream: true}));
}
console.log("[text of cid from other browser]", texts.join(""));
})(), {cidStr});
// [7. closing]
console.log("[closing...]");
await page1.evaluate(() => ctx.node.stop());
await page2.evaluate(() => ctx.node.stop());
await browser.close();
await new Promise(f => httpServer.server.close(f));
await node.stop();
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<script type="importmap">
{
"imports": {
"helia": "./npm-browser.js",
"libp2p/circuit-relay": "./npm-browser.js",
"@libp2p/peer-id": "./npm-browser.js",
"@libp2p/topology": "./npm-browser.js",
"@libp2p/mplex": "./npm-browser.js",
"@chainsafe/libp2p-yamux": "./npm-browser.js",
"@libp2p/bootstrap": "./npm-browser.js",
"@libp2p/pubsub-peer-discovery": "./npm-browser.js",
"@libp2p/webtransport": "./npm-browser.js",
"@libp2p/webrtc": "./npm-browser.js",
"@libp2p/websockets": "./npm-browser.js",
"@libp2p/websockets/filters": "./npm-browser.js",
"@libp2p/circuit-relay": "./npm-browser.js",
"libp2p/identify": "./npm-browser.js",
"libp2p/autonat": "./npm-browser.js",
"@chainsafe/libp2p-gossipsub": "./npm-browser.js",
"@libp2p/kad-dht": "./npm-browser.js",
"ipns/selector": "./npm-browser.js",
"ipns/validator": "./npm-browser.js",
"@multiformats/multiaddr": "./npm-browser.js",
"multiformats/cid": "./npm-browser.js",
"@helia/unixfs": "./npm-browser.js"
}
}
</script>
<link rel="icon" href="data:image/x-icon;" />
</head>
<body></body>
</html>
import * as http from "node:http";
import {createHelia} from "helia";
import {createTopology} from "@libp2p/topology";
import {mplex} from "@libp2p/mplex";
import {yamux} from "@chainsafe/libp2p-yamux";
import {tcp} from "@libp2p/tcp";
import {webSockets} from "@libp2p/websockets";
import {webRTC, webRTCDirect} from "@libp2p/webrtc";
import {circuitRelayTransport, circuitRelayServer} from "libp2p/circuit-relay";
import {mdns} from "@libp2p/mdns";
import {bootstrap} from "@libp2p/bootstrap";
import {pubsubPeerDiscovery} from "@libp2p/pubsub-peer-discovery";
import {ipniContentRouting} from "@libp2p/ipni-content-routing";
import {identifyService} from "libp2p/identify";
import {autoNATService} from "libp2p/autonat";
import {uPnPNATService} from "libp2p/upnp-nat";
import {gossipsub} from "@chainsafe/libp2p-gossipsub";
import {kadDHT} from "@libp2p/kad-dht";
import {ipnsSelector} from "ipns/selector";
import {ipnsValidator} from "ipns/validator";
export const createNode = async () => {
// localhost helia node for using bootstrap target from browser helia
const node = await createHelia({
libp2p: {
addresses: {
listen: [
"/ip4/0.0.0.0/tcp/0",
"/ip4/0.0.0.0/tcp/0/ws",
"/webrtc",
]
},
transports: [
tcp(),
webSockets({websocket: {rejectUnauthorized: false}}),
circuitRelayTransport({discoverRelays: 3}),
webRTC(),
webRTCDirect(),
],
//streamMuxers: [mplex()],
//streamMuxers: [yamux()],
services: {
identify: identifyService(),
autoNAT: autoNATService(),
upnp: uPnPNATService(),
pubsub: gossipsub({allowPublishToZeroPeers: true, emitSelf: true, canRelayMessage: true}),
dht: kadDHT({
validators: {ipns: ipnsValidator},
selectors: {ipns: ipnsSelector},
}),
relay: circuitRelayServer({advertise: true}),
},
},
});
// uncomment for print peer connecting info
node.libp2p.addEventListener("peer:connect", ev => {
//console.log("[peer:connect]", ev.detail);
});
node.libp2p.addEventListener("peer:discovery", ev => {
//console.log("[peer:discovery]", ev.detail);
});
await node.libp2p.register("/ipfs/bitswap/1.2.0", createTopology({
onConnect: (peerId, conn) => {
//console.log("[/ipfs/bitswap/1.2.0] onConnect", peerId);
},
onDisonnect: peerId => {
//console.log("[/ipfs/bitswap/1.2.0] onDisonnect", peerId);
},
}));
return node;
};
// esbuild to single js file for mapping each module by importmap in HTML
export {createHelia} from "helia";
export {unixfs} from "@helia/unixfs";
export {CID} from "multiformats/cid";
export {multiaddr} from "@multiformats/multiaddr";
export {peerIdFromString} from "@libp2p/peer-id";
export {createTopology} from "@libp2p/topology";
export {mplex} from "@libp2p/mplex";
export {yamux} from "@chainsafe/libp2p-yamux";
export {bootstrap} from "@libp2p/bootstrap";
export {pubsubPeerDiscovery} from "@libp2p/pubsub-peer-discovery";
export {circuitRelayTransport, circuitRelayServer} from "libp2p/circuit-relay";
export {webRTC, webRTCDirect} from "@libp2p/webrtc";
export {webTransport} from "@libp2p/webtransport";
export {webSockets} from "@libp2p/websockets";
export {all} from "@libp2p/websockets/filters";
// services
export {identifyService} from "libp2p/identify";
export {autoNATService} from "libp2p/autonat";
export {gossipsub} from "@chainsafe/libp2p-gossipsub";
export {kadDHT} from "@libp2p/kad-dht";
export {ipnsSelector} from "ipns/selector";
export {ipnsValidator} from "ipns/validator";
{
"type": "module",
"dependencies": {
"@helia/unixfs": "^1.4.1",
"@libp2p/pubsub-peer-discovery": "^8.0.4",
"esbuild": "^0.19.2",
"helia": "^2.0.1",
"http-server": "^14.1.1",
"playwright": "^1.37.1"
},
"scripts": {
"b2b": "node case-b2b.mjs",
"build": "esbuild npm-libs.js --bundle --sourcemap=inline --format=esm --target=chrome115 --define:global=globalThis --define:process.env.NODE_DEBUG=false --outfile=npm-browser.js"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment