All files / src/modules feed.ts

91.66% Statements 22/24
0% Branches 0/2
100% Functions 4/4
91.66% Lines 22/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 14133x   33x 33x 33x 33x 33x   33x                                                                                                 33x             2x             2x   2x       10x 10x   10x       10x       10x                                     33x           17x           9x           33x         1x               1x    
import { Types } from 'cafe-utility'
import { BeeRequestOptions, UploadOptions } from '../types'
import { Bytes } from '../utils/bytes'
import { BeeError } from '../utils/error'
import { prepareRequestHeaders } from '../utils/headers'
import { http } from '../utils/http'
import { BatchId, EthAddress, FeedIndex, Reference, Topic } from '../utils/typed-bytes'
 
const feedEndpoint = 'feeds'
 
export interface FeedUpdateOptions {
  /**
   * Specifies the start date as unix time stamp
   */
  at?: number
 
  /**
   * Fetch specific previous Feed's update (default fetches latest update)
   */
  index?: FeedIndex | number
 
  /**
   * Whether the first 8 bytes of the payload are a timestamp
   */
  hasTimestamp?: boolean
}
 
interface FeedUpdateHeaders {
  /**
   * The current feed's index
   */
  feedIndex: FeedIndex
 
  /**
   * The feed's index for next update.
   * Only set for the latest update. If update is fetched using previous index, then this is an empty string.
   */
  feedIndexNext?: FeedIndex
}
 
export interface FeedPayloadResult extends FeedUpdateHeaders {
  payload: Bytes
}
 
export interface FeedReferenceResult extends FeedUpdateHeaders {
  reference: Reference
}
 
/**
 * Create an initial feed root manifest
 *
 * @param requestOptions  Options for making requests
 * @param owner           Owner's ethereum address in hex
 * @param topic           Topic in hex
 * @param postageBatchId  Postage BatchId to be used to create the Feed Manifest
 * @param options         Additional options, like type (default: 'sequence')
 */
export async function createFeedManifest(
  requestOptions: BeeRequestOptions,
  owner: EthAddress,
  topic: Topic,
  stamp: BatchId | Uint8Array | string,
  options?: UploadOptions,
): Promise<Reference> {
  const response = await http<unknown>(requestOptions, {
    method: 'post',
    responseType: 'json',
    url: `${feedEndpoint}/${owner}/${topic}`,
    headers: prepareRequestHeaders(stamp, options),
  })
 
  const body = Types.asObject(response.data, { name: 'response.data' })
 
  return new Reference(Types.asHexString(body.reference))
}
 
function readFeedUpdateHeaders(headers: Record<string, string>): FeedUpdateHeaders {
  const feedIndex = headers['swarm-feed-index']
  const feedIndexNext = headers['swarm-feed-index-next']
 
  Iif (!feedIndex) {
    throw new BeeError('Response did not contain expected swarm-feed-index!')
  }
 
  Iif (!feedIndexNext) {
    throw new BeeError('Response did not contain expected swarm-feed-index-next!')
  }
 
  return {
    feedIndex: new FeedIndex(feedIndex),
    feedIndexNext: new FeedIndex(feedIndexNext),
  }
}
 
/**
 * Find and retrieve feed update
 *
 * The feed consists of updates. This endpoint looks up an
 * update that matches the provided parameters and returns
 * the reference it contains along with its index and the
 * index of the subsequent update.
 *
 * @param requestOptions Options for making requests
 * @param owner          Owner's ethereum address
 * @param topic          Topic
 * @param options        Additional options, like index, at, type
 */
export async function fetchLatestFeedUpdate(
  requestOptions: BeeRequestOptions,
  owner: EthAddress,
  topic: Topic,
  options?: FeedUpdateOptions,
): Promise<FeedPayloadResult> {
  const response = await http<ArrayBuffer>(requestOptions, {
    responseType: 'arraybuffer',
    url: `${feedEndpoint}/${owner}/${topic}`,
    params: options,
  })
 
  return {
    payload: new Bytes(response.data),
    ...readFeedUpdateHeaders(response.headers as Record<string, string>),
  }
}
 
export async function probeFeed(
  requestOptions: BeeRequestOptions,
  owner: EthAddress,
  topic: Topic,
): Promise<FeedUpdateHeaders> {
  const response = await http<ArrayBuffer>(requestOptions, {
    responseType: 'arraybuffer',
    url: `${feedEndpoint}/${owner}/${topic}`,
    params: {
      'Swarm-Only-Root-Chunk': true,
    },
  })
 
  return readFeedUpdateHeaders(response.headers as Record<string, string>)
}