// import { unixfs } from "@helia/unixfs"; // import { MemoryBlockstore } from 'blockstore-core' // import { MemoryDatastore } from 'datastore-core' import type { DAGJSON } from '@helia/dag-json' import type { Helia } from 'helia' import type { Libp2p, Libp2pOptions } from 'libp2p' import { noise } from '@chainsafe/libp2p-noise' import { yamux } from '@chainsafe/libp2p-yamux' import { dagJson } from '@helia/dag-json' import { delegatedPeerRouting } from '@libp2p/delegated-peer-routing' import { mplex } from '@libp2p/mplex' // import { tcp } from '@libp2p/tcp' import { webSockets } from '@libp2p/websockets' import { webTransport } from '@libp2p/webtransport' import { Logger } from 'besonders-logger' import { IDBBlockstore } from 'blockstore-idb' import { IDBDatastore } from 'datastore-idb' import debug from 'debug' import { createHelia } from 'helia' import { create as createKuboClient } from 'kubo-rpc-client' import { createLibp2p } from 'libp2p' import { CID } from 'multiformats/cid' const { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO, { prefix: '[helia]' }) // eslint-disable-line unused-imports/no-unused-vars let helia: Helia | null = null let dag: DAGJSON | null = null debug.enable('libp2p:websockets,libp2p:webtransport,libp2p:kad-dht,libp2p:dialer*,libp2p:connection-manager') debug.enable('libp2p:*:error') debug.enable('libp2p:connection-manager:auto-dialler') debug.enable('libp2p:*:error,libp2p:dialer*,libp2p:connection-manager*,libp2p:webtransport,-*:trace') debug.enable('libp2p:connection-manager*,libp2p:dialer*,libp2p:delegated*') debug.enable('libp2p:*,-*:trace') debug.enable('libp2p:webtransport*,libp2p:connection-manager*') export async function startHelia() { try { if (helia) { console.info('helia already started') // @ts-expect-error window.helia } else if (window.helia) { console.info('found a windowed instance of helia, populating ...') // @ts-expect-error window.helia helia = window.helia // setDag(dagJson(helia)); // setStarting(false); } else { const blockstore = new IDBBlockstore('ipfs/blocks') await blockstore.open() const datastore = new IDBDatastore('ipfs/data') await datastore.open() LOG('Starting Helia') helia = await createHelia({ blockstore, libp2p: await getLibp2p({ type: 'ipni', // preset datastore, }), // services: { // identify: identify(), // pubsub: gossipsub(), // }, }) // setHelia(helia); // setFs(unixfs(helia)); // setStarting(false); LOG('Started Helia') } // @ts-expect-error window.helia window.helia = helia dag = dagJson(helia!) // @ts-expect-error window.helia window.dag = dagJson(helia) } catch (e) { ERROR(e) // setError(true); } } /////////////////////////////////////////////////////////////////////////////////////////////////////// // FROM https://github.com/ipfs-shipyard/helia-service-worker-gateway/blob/main/src/getLibp2p.ts#L37 // /////////////////////////////////////////////////////////////////////////////////////////////////////// interface GetLibP2pOptions { datastore: LibP2pComponents['datastore'] type: Libp2pConfigTypes } const typeFnMap: Record Libp2pOptions> = { ipni: getIpniLibp2pConfig, // https://github.com/ipfs-shipyard/helia-service-worker-gateway/blob/main/src/libp2pConfigs/getIpniLibp2pConfig.ts#L6 // dht: getDhtLibp2pConfig, // https://github.com/ipfs-shipyard/helia-service-worker-gateway/blob/main/src/libp2pConfigs/getDhtLibp2pConfig.ts#L7 // bootstrapOnly: getBootstrapOnlyLibp2pConfig, // https://github.com/ipfs-shipyard/helia-service-worker-gateway/blob/main/src/libp2pConfigs/getBootstrapOnly.ts#L4 } export async function getLibp2p({ datastore, type }: GetLibP2pOptions): Promise { return await createLibp2p({ datastore, transports: [ webSockets(), webTransport(), ], connectionEncryption: [ noise(), ], streamMuxers: [ yamux(), /** * required to prevent `libp2p:dialer:error dial to /dns4/elastic.dag.house/tcp/443/wss/p2p/QmQzqxhK82kAmKvARFZSkUVS6fo9sySaiogAnx5EnZ6ZmC failed +0ms Error: protocol selection failed` * @todo remove when https://github.com/elastic-ipfs/elastic-ipfs/issues/25 is resolved */ mplex(), ], ...typeFnMap[type](), }) } export function getIpniLibp2pConfig(): Libp2pOptions { const delegatedClient = createKuboClient({ // use default api settings protocol: 'https', port: 443, host: 'node3.delegate.ipfs.io', }) return { peerRouters: [delegatedPeerRouting(delegatedClient)], // contentRouters: [ipniRouting('https', 'indexstar.prod.cid.contact', '443'), delegatedContentRouting(delegatedClient)], contentRouters: [ipniRouting('https', 'cid.contact', '443')], /** * @see https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md#configuring-connection-manager */ connectionManager: { // Auto connect to discovered peers (limited by ConnectionManager minConnections) maxConnections: Infinity, minConnections: 1, pollInterval: 2000, }, /** * @see https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md#configuring-peerstore */ peerRouting: { // Peer routing configuration refreshManager: { // Refresh known and connected closest peers enabled: false, // Should find the closest peers. interval: 6e5, // Interval for getting the new for closest peers of 10min bootDelay: 10e3, // Delay for the initial query for closest peers }, }, } } export function ipniRouting(protocol: string, host: string, port: string): (components?: LibP2pComponents) => ContentRouting { return () => new IpniRouting(protocol, host, port) } export function getDag() { if (!dag) { throw new Error(`dag not initialized`) } return dag } // @ts-expect-error window.helia if (typeof window != 'undefined') window.CID = CID