Source

core/peer.ts

import Libp2p from 'libp2p'
import Bitswap from 'ipfs-bitswap'
import CID from 'cids'
import { BlockService } from './blockservice'
import { BlockStore } from './blockstore'
import { DAGService } from './dagservice'

/**
 * PeerOptions wraps configuration options for the IPFS Lite peer.
 */
export interface PeerOptions {
  /**
   * offline controls whether or not the block service will announce or retrieve blocks from the network.
   */
  offline: boolean
}

/**
 * Peer is an IPFS Lite peer. It provides a DAG service that can fetch and put blocks from/to the IPFS network.
 *
 * It casually satisfies the original IPFS Lite interface: https://github.com/hsanjuan/ipfs-lite.
 */
export class Peer extends DAGService {
  /**
   * config is a set of options to configure the IPFS Lite peer.
   */
  public config: PeerOptions
  /**
   * host is the Libp2p host used to interact with the network.
   */
  public host: Libp2p
  /**
   * store is the underlying block store for locally caching immutable blocks of data.
   */
  public store: BlockStore
  /**
   * blockExchange is the "bitswap" instance that communicates with the network to retrieve blocks that are not in
   * the local store.
   */
  public blockExchange: Bitswap
  /**
   * blockService is a content-addressable store for adding, deleting, and retrieving blocks of immutable data.
   */
  public blockService: BlockService

  /**
   * Peer creates a new IPFS Lite peer.
   *
   * @param {BlockStore} store The underlying block store for locally caching immutable blocks of data.
   * @param {Libp2p} host The Libp2p host to use for interacting with the network.
   * @param {PeerOptions} config An optional set of configuration options. Currently only supports whether or not the
   * peer should run in 'offline' mode.
   */
  constructor(store: BlockStore, host: Libp2p, config: PeerOptions = { offline: false }) {
    const blockExchange = new Bitswap(host, store)
    const blockService = new BlockService(store, config.offline ? undefined : blockExchange)
    super({ blockService })
    this.host = host
    this.store = store
    this.config = config
    this.blockExchange = blockExchange
    this.blockService = blockService
  }

  /**
   * start starts the underlying host and block exchange.
   *
   * @example
   * const peer = new Peer(...)
   * await peer.start()
   * // do stuff with it...
   * await peer.stop()
   */
  async start() {
    await this.host.start()
    this.blockExchange.start()
  }

  /**
   * stop stops the underlying block exchange and host.
   *
   * @example
   * const peer = new Peer(...)
   * await peer.start()
   * // do stuff with it...
   * await peer.stop()
   */
  async stop() {
    this.blockExchange.stop()
    await this.host.stop()
  }

  /**
   * hasBlock returns whether a given block is available locally. This method is shorthand for .store.has().
   *
   * @param {CID} cid The target content identifier.
   * @example
   * const peer = new Peer(...)
   * await peer.start()
   * const has = await peer.hasBlock('bafk...uny')
   * console.log(has)
   * await peer.stop()
   */
  async hasBlock(cid: CID) {
    return this.store.has(cid)
  }

  /**
   * isOnline returns whether the peer has a valid block exchange and its p2p host has been started.
   */
  isOnline() {
    return this.blockExchange && this.host && this.host.isStarted()
  }

  /**
   * dag provides access to the underlying DAG service.
   *
   * The dag API supports the creation and manipulation of dag-pb objects, as well as other IPLD formats
   * (i.e dag-cbor, ethereum-block, git, etc). Use it to put, get, and walk IPLD DAG objects.
   */
  get dag() {
    return this
  }
}