mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-03-15 15:10:50 +00:00
Converts this module to typescript. - Ecosystem modules renamed from (e.g.) `libp2p-tcp` to `@libp2p/tcp` - Ecosystem module now have named exports - Configuration has been updated, now pass instances of modules instead of classes: - Some configuration keys have been renamed to make them more descriptive. `transport` -> `transports`, `connEncryption` -> `connectionEncryption`. In general where we pass multiple things, the key is now plural, e.g. `streamMuxer` -> `streamMuxers`, `contentRouting` -> `contentRouters`, etc. Where we are configuring a singleton the config key is singular, e.g. `connProtector` -> `connectionProtector` etc. - Properties of the `modules` config key have been moved to the root - Properties of the `config` config key have been moved to the root ```js // before import Libp2p from 'libp2p' import TCP from 'libp2p-tcp' await Libp2p.create({ modules: { transport: [ TCP ], } config: { transport: { [TCP.tag]: { foo: 'bar' } }, relay: { enabled: true, hop: { enabled: true, active: true } } } }) ``` ```js // after import { createLibp2p } from 'libp2p' import { TCP } from '@libp2p/tcp' await createLibp2p({ transports: [ new TCP({ foo: 'bar' }) ], relay: { enabled: true, hop: { enabled: true, active: true } } }) ``` - Use of `enabled` flag has been reduced - previously you could pass a module but disable it with config. Now if you don't want a feature, just don't pass an implementation. Eg: ```js // before await Libp2p.create({ modules: { transport: [ TCP ], pubsub: Gossipsub }, config: { pubsub: { enabled: false } } }) ``` ```js // after await createLibp2p({ transports: [ new TCP() ] }) ``` - `.multiaddrs` renamed to `.getMultiaddrs()` because it's not a property accessor, work is done by that method to calculate announce addresses, observed addresses, etc - `/p2p/${peerId}` is now appended to all addresses returned by `.getMultiaddrs()` so they can be used opaquely (every consumer has to append the peer ID to the address to actually use it otherwise). If you need low-level unadulterated addresses, call methods on the address manager. BREAKING CHANGE: types are no longer hand crafted, this module is now ESM only
160 lines
4.1 KiB
TypeScript
160 lines
4.1 KiB
TypeScript
import { interopTests } from '@libp2p/interop'
|
|
import type { SpawnOptions, Daemon, DaemonFactory } from '@libp2p/interop'
|
|
import { createServer } from '@libp2p/daemon-server'
|
|
import { createClient } from '@libp2p/daemon-client'
|
|
import { createLibp2p, Libp2pOptions } from '../src/index.js'
|
|
import { Noise } from '@chainsafe/libp2p-noise'
|
|
import { TCP } from '@libp2p/tcp'
|
|
import { Multiaddr } from '@multiformats/multiaddr'
|
|
import { KadDHT } from '@libp2p/kad-dht'
|
|
import { path as p2pd } from 'go-libp2p'
|
|
import execa from 'execa'
|
|
import pDefer from 'p-defer'
|
|
import { logger } from '@libp2p/logger'
|
|
import { Mplex } from '@libp2p/mplex'
|
|
import fs from 'fs'
|
|
import { unmarshalPrivateKey } from '@libp2p/crypto/keys'
|
|
import type { PeerId } from '@libp2p/interfaces/peer-id'
|
|
import { peerIdFromKeys } from '@libp2p/peer-id'
|
|
import { FloodSub } from '@libp2p/floodsub'
|
|
import { Gossipsub } from '@achingbrain/libp2p-gossipsub'
|
|
|
|
// IPFS_LOGGING=debug DEBUG=libp2p*,go-libp2p:* npm run test:interop
|
|
|
|
async function createGoPeer (options: SpawnOptions): Promise<Daemon> {
|
|
const controlPort = Math.floor(Math.random() * (50000 - 10000 + 1)) + 10000
|
|
const apiAddr = new Multiaddr(`/ip4/0.0.0.0/tcp/${controlPort}`)
|
|
|
|
const log = logger(`go-libp2p:${controlPort}`)
|
|
|
|
const opts = [
|
|
`-listen=${apiAddr.toString()}`,
|
|
'-hostAddrs=/ip4/0.0.0.0/tcp/0'
|
|
]
|
|
|
|
if (options.noise === true) {
|
|
opts.push('-noise=true')
|
|
}
|
|
|
|
if (options.dht === true) {
|
|
opts.push('-dhtServer')
|
|
}
|
|
|
|
if (options.pubsub === true) {
|
|
opts.push('-pubsub')
|
|
}
|
|
|
|
if (options.pubsubRouter != null) {
|
|
opts.push(`-pubsubRouter=${options.pubsubRouter}`)
|
|
}
|
|
|
|
if (options.key != null) {
|
|
opts.push(`-id=${options.key}`)
|
|
}
|
|
|
|
const deferred = pDefer()
|
|
const proc = execa(p2pd(), opts)
|
|
|
|
proc.stdout?.on('data', (buf: Buffer) => {
|
|
const str = buf.toString()
|
|
log(str)
|
|
|
|
// daemon has started
|
|
if (str.includes('Control socket:')) {
|
|
deferred.resolve()
|
|
}
|
|
})
|
|
|
|
proc.stderr?.on('data', (buf) => {
|
|
log.error(buf.toString())
|
|
})
|
|
|
|
await deferred.promise
|
|
|
|
return {
|
|
client: createClient(apiAddr),
|
|
stop: async () => {
|
|
await proc.kill()
|
|
}
|
|
}
|
|
}
|
|
|
|
async function createJsPeer (options: SpawnOptions): Promise<Daemon> {
|
|
let peerId: PeerId | undefined
|
|
|
|
if (options.key != null) {
|
|
const keyFile = fs.readFileSync(options.key)
|
|
const privateKey = await unmarshalPrivateKey(keyFile)
|
|
peerId = await peerIdFromKeys(privateKey.public.bytes, privateKey.bytes)
|
|
}
|
|
|
|
const opts: Libp2pOptions = {
|
|
peerId,
|
|
addresses: {
|
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
|
},
|
|
transports: [new TCP()],
|
|
streamMuxers: [new Mplex()],
|
|
connectionEncryption: [new Noise()]
|
|
}
|
|
|
|
if (options.dht === true) {
|
|
// go-libp2p-daemon only has the older single-table DHT instead of the dual
|
|
// lan/wan version found in recent go-ipfs versions. unfortunately it's been
|
|
// abandoned so here we simulate the older config with the js implementation
|
|
const dht = new KadDHT({
|
|
clientMode: false
|
|
})
|
|
const lan = dht.lan
|
|
|
|
const protocol = '/ipfs/kad/1.0.0'
|
|
lan.protocol = protocol
|
|
// @ts-expect-error
|
|
lan.network.protocol = protocol
|
|
// @ts-expect-error
|
|
lan.topologyListener.protocol = protocol
|
|
|
|
// @ts-expect-error
|
|
opts.dht = lan
|
|
}
|
|
|
|
if (options.pubsub === true) {
|
|
if (options.pubsubRouter === 'floodsub') {
|
|
opts.pubsub = new FloodSub()
|
|
} else {
|
|
opts.pubsub = new Gossipsub()
|
|
}
|
|
}
|
|
|
|
const node = await createLibp2p(opts)
|
|
const server = await createServer(new Multiaddr('/ip4/0.0.0.0/tcp/0'), node)
|
|
await server.start()
|
|
|
|
return {
|
|
client: createClient(server.getMultiaddr()),
|
|
stop: async () => {
|
|
await server.stop()
|
|
await node.stop()
|
|
}
|
|
}
|
|
}
|
|
|
|
async function main () {
|
|
const factory: DaemonFactory = {
|
|
async spawn (options: SpawnOptions) {
|
|
if (options.type === 'go') {
|
|
return await createGoPeer(options)
|
|
}
|
|
|
|
return await createJsPeer(options)
|
|
}
|
|
}
|
|
|
|
await interopTests(factory)
|
|
}
|
|
|
|
main().catch(err => {
|
|
console.error(err) // eslint-disable-line no-console
|
|
process.exit(1)
|
|
})
|