Skip to content

Migrating from js IPFS

Alex Potsides edited this page Sep 8, 2023 · 12 revisions

Getting started

js-IPFS

import { create } from 'ipfs-core'

const ipfs = await create()
// the node is running

await ipfs.stop()
// the node is stopped

Helia

import { createHelia } from 'helia'

const helia = await createHelia()
// the node is running

await helia.stop()
// the node is stopped

Examples

js-IPFS has a comprehensive examples repo that shows how to integrate with common build tools and accomplish common tasks in fork-n-go style repos that make it easy to hit the ground running.

The good news is that most of these have or are in the process of being converted to Helia.

Please see the Helia examples repo for ones that have made the jump and open an issue for any ones that are missing or better yet open a PR!

Core API

How to perform the tasks with Helia that you previously used the js-IPFS API for.

Bitswap

At the time of writing there's no way to interact with Bitswap inside Helia.

This will be enabled in a future release - please check in on #98 for the current status of this effort.

Comprehensive metrics about your running node, including the state of the bitswap wantlist can be collected using implementations of @libp2p/interface-metrics.

For example if you configure @libp2p/prometheus-metrics and collect data using Graphana or Prometheus you will see several metrics prefixed with ipfs_bitswap_, for example the size of the wantlist (ipfs_bitswap_wantlist), peer stats (ipfs_bitswap_stats_peers), etc.

Block

Instead of accessing the block API you can access Helia's blockstore directly:

js-IPFS

await ipfs.block.get(cid)
await ipfs.block.put(buf)
// etc

Helia

await helia.blockstore.get(cid)
await helia.blockstore.put(cid, buf)
// etc

Please see interface-blockstore for full details of all available methods.

Bootstrap

The bootstrap API has been retired. Please configure @libp2p/bootstrap directly.

js-IPFS

await ipfs.bootstrap.add(multiaddr)
await ipfs.bootstrap.rm(multiaddr)
// etc

Helia

const node = await createHelia({
  libp2p: createLibp2p({
    // ..other settings
    peerDiscovery: [
      bootstrap({
        list: [
          '/dnsaddr/bootstrap.io/p2p/QmBootstrap1',
          '/dnsaddr/bootstrap.io/p2p/QmBootstrap2'
          // etc
        ]
      })
    ]
  })
})

Config

The config API has been retired. Please configure Helia directly.

js-IPFS

ipfs.config.get('key')
ipfs.config.set('key', 'value')
// etc

Helia

const node = await createHelia({
  // config here
})

Please see the docs for the HeliaInit type for all config options.

DAG

The DAG API has been retired. To conduct similar operations please use one of the helper modules or write your own!

js-IPFS

const cid = await ipfs.dag.put({
  hello: 'world'
}, {
  storeCodec: 'json'
})

const obj = await ipfs.dag.get(cid)
// etc

Helia

import { json } from '@helia/json'

const j = json(helia)
const cid = await j.add({ hello: 'world' })

const obj = await j.get(cid)
// etc

For more data types, see:

DHT

DHT operations are now available on the .libp2p object.

js-IPFS

await ipfs.dht.findPeer(peerId)
await ipfs.dht.findProvs(cid)
// etc

Helia

import { createHelia } from 'helia'
import { createLibp2p } from 'libp2p'
import { kadDHT } from '@libp2p/kad-dht'

const helia = await createHelia({
  libp2p: createLibp2p({
    //... other libp2p config
    services: {
      dht: kadDHT()
    }
  })
})

for await (const event of helia.libp2p.services.dht.findPeer(peerId)) {
  // etc
}

Please see the docs for the KadDHT type for details of all available operations.

Files

The regular files API is replaced by the @helia/unixfs module.

A Mutable File System implementation is available via @helia/mfs.

Regular Files API

js-IPFS

const { cid } = await ipfs.add(buf)

Helia

import { unixfs } from '@helia/unixfs'

const fs = unixfs(helia)
const cid = await fs.addBytes(buf)

Please see the docs for the UnixFS type for full details of all available operations.

MFS

js-IPFS

const { cid } = await ipfs.add(buf)

await ipfs.files.mkdir('/foo')
await ipfs.files.cp(cid, '/foo/bar.txt')
const { cid: updatedDirCid } = ipfs.files.stat('/foo')

Helia

import { mfs } from '@helia/mfs'

const fs = mfs(helia)
await fs.mkdir('/foo')
await fs.writeBytes(buf, '/foo/bar.txt')

Please see the docs for the MFS type for full details of all available operations.

Key

Key operations are now available on the .libp2p object.

js-IPFS

await ipfs.key.gen('my-key')
await ipfs.key.list()
// etc

Helia

await helia.libp2p.keychain.createKey('my-key')
await helia.libp2p.keychain.listKeys()
// etc

Please see the docs for the KeyChain type for full details of all available operations.

Miscellaneous

id

The id method has been retired. The equivalent information can be accessed from the .libp2p property directly.

js-IPFS

const {
  id,
  multiaddrs
  // etc
} = await ipfs.id()

Helia

const id = helia.libp2p.peerId
const multiaddrs = helia.libp2p.getMultiaddrs()
// etc

version

The version method has been retired. This can be read from the relevant package.json of your project's dependencies.

dns (DNSLink)

DNSLink entries can be resolved using the @helia/ipns module.

js-IPFS

const result = await ipfs.dns('ipfs.io')

Helia

import { ipns } from '@helia/ipns'

const i = ipns(helia)
const result = await i.resolveDns('ipfs.io')

Please see the docs for the resolveDns method for full details of all options.

stop

This API is the same, a .stop method on the root object that returns a promise.

ping

Ping operations are now available on the .libp2p object.

js-IPFS

const result = await ipfs.ping(peerId)
// etc

Helia

import { createHelia } from 'helia'
import { createLibp2p } from 'libp2p'
import { pingService } from 'libp2p/ping'

const helia = await createHelia({
  libp2p: createLibp2p({
    //... other libp2p config
    services: {
      ping: pingService()
    }
  })
})

const result = await libp2p.services.ping.ping(peerId)

Please see the docs for the PingService type for full details of all available operations.

resolve

The resolve method has been retired. Please use the @helia/ipns module to resolve IPNS names and DNSLink entries from domain names.

Name (IPNS)

IPNS operations are carried out using the @helia/ipns module.

js-IPFS

await ipfs.name.publish(cid, {
  key: 'my-key'
})

Helia

import { ipns } from '@helia/ipns'

const name = ipns(helia, [
  // configure routings here
])

// create a public key to publish as an IPNS name
const keyInfo = await helia.libp2p.keychain.createKey('my-key')
const peerId = await helia.libp2p.keychain.exportPeerId(keyInfo.name)

// publish the name
await name.publish(peerId, cid)

// resolve the name
const cid = name.resolve(peerId)

Please see the docs for the IPNS type for all available operations and options.

Namesys PubSub

To perform IPNS over PubSub operations, configure @helia/pubsub with the pubsub routing and perform IPNS operations as normal.

Helia

import { ipns } from '@helia/ipns'
import { pubsub } from '@helia/ipns/routing'

const name = ipns(helia, [
  pubsub(helia)
])

// publish a name
await name.publish(peerId, cid)

Object

The Object API has been retired. Please use the @helia/unixfs module for mutating UnixFS file systems or the @ipld/dag-pb module to manipulate DAGs directly.

js-IPFS

// add a directory to a dag
const block = await ipfs.block.get(dirCid)
const updatedCid = await ipfs.object.patch.addLink(containingCid, {
  Name: 'new-dir',
  Hash: dirCid,
  Size: block.byteLength
})

Helia

// add a directory to a dag
const fs = unixfs(helia)
const updatedCid = await fs.cp(dirCid, containingCid, 'new folder')

Pin

Helia's pinning API is similar to the one from js-IPFS except it's much, much faster.

js-IPFS

await ipfs.pin.add(cid)
await ipfs.pin.ls()
// etc

Helia

await helia.pin.add(cid)
await helia.pin.ls()
// etc

Please see the docs for the Pins type for all available operations and options.

PubSub

PubSub operations are now available on the .libp2p object.

js-IPFS

await ipfs.pubsub.subscribe('topic', (evt) => {
  // handle message
})
// etc

Helia

import { createHelia } from 'helia'
import { createLibp2p } from 'libp2p'
import { gossipsub } from '@chainsafe/libp2p-gossipsub'

const helia = await createHelia({
  libp2p: createLibp2p({
    //... other libp2p config
    services: {
      pubsub: gossipsub()
    }
  })
})

await helia.libp2p.services.pubsub.addEventListener('message', (evt) => {
  if (evt.detail.topic === 'topic') {
    // handle message
  }
})
// etc

Please see the docs for the ChainSafe Gossipsub docs type for full details of all available operations.

Refs

The Refs API has been retired.

If you would like to see similar functionality please publish a module and open a PR here to add it to the docs!

Repo

The Repo API has been retired.

Garbage collection now happens via the .gc method on the root object.

js-IPFS

await ipfs.repo.gc

Helia

await helia.gc()

Stats

The Stats API has been retired.

Comprehensive metrics about your running node can be collected using implementations of @libp2p/interface-metrics.

See:

Swarm

Swarm operations are now carried out be invoking methods on the .libp2p object.

js-IPFS

await ipfs.swarm.addrs()
await ipfs.swarm.connect()
await ipfs.swarm.disconnect()
// etc

Helia

helia.libp2p.getMultiaddrs()
await helia.libp2p.dial(multiaddr)
await helia.libp2p.hangUp(multiaddr)
// etc