"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Bee = void 0; const bzz = __importStar(require("./modules/bzz")); const stewardship = __importStar(require("./modules/stewardship")); const tag = __importStar(require("./modules/tag")); const pinning = __importStar(require("./modules/pinning")); const bytes = __importStar(require("./modules/bytes")); const chunk = __importStar(require("./modules/chunk")); const pss = __importStar(require("./modules/pss")); const status = __importStar(require("./modules/status")); const error_1 = require("./utils/error"); const data_1 = require("./utils/data"); const file_1 = require("./utils/file"); const feed_1 = require("./feed"); const signer_1 = require("./chunk/signer"); const type_1 = require("./feed/type"); const soc_1 = require("./chunk/soc"); const topic_1 = require("./feed/topic"); const feed_2 = require("./modules/feed"); const url_1 = require("./utils/url"); const eth_1 = require("./utils/eth"); const bytes_1 = require("./utils/bytes"); const type_2 = require("./utils/type"); const json_1 = require("./feed/json"); const collection_1 = require("./utils/collection"); const collection_node_1 = require("./utils/collection.node"); const types_1 = require("./types"); const http_1 = require("./utils/http"); const stream_1 = require("./utils/stream"); const retrievable_1 = require("./feed/retrievable"); const swarm_cid_1 = require("@ethersphere/swarm-cid"); /** * The main component that abstracts operations available on the main Bee API. * * Not all methods are always available as it depends in what mode is Bee node launched in. * For example gateway mode and light node mode has only limited set of endpoints enabled. */ class Bee { /** * @param url URL on which is the main API of Bee node exposed * @param options */ constructor(url, options) { var _a; (0, url_1.assertBeeUrl)(url); // Remove last slash if present, as our endpoint strings starts with `/...` // which could lead to double slash in URL to which Bee responds with // unnecessary redirects. this.url = (0, url_1.stripLastSlash)(url); if (options === null || options === void 0 ? void 0 : options.signer) { this.signer = (0, signer_1.makeSigner)(options.signer); } const kyOptions = { prefixUrl: this.url, timeout: (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : false, retry: options === null || options === void 0 ? void 0 : options.retry, fetch: options === null || options === void 0 ? void 0 : options.fetch, hooks: { beforeRequest: [], afterResponse: [], }, }; if (options === null || options === void 0 ? void 0 : options.defaultHeaders) { kyOptions.headers = options.defaultHeaders; } if (options === null || options === void 0 ? void 0 : options.onRequest) { kyOptions.hooks.beforeRequest.push((0, http_1.wrapRequestClosure)(options.onRequest)); } if (options === null || options === void 0 ? void 0 : options.onResponse) { kyOptions.hooks.afterResponse.push((0, http_1.wrapResponseClosure)(options.onResponse)); } this.ky = (0, http_1.makeDefaultKy)(kyOptions); } /** * Upload data to a Bee node * * @param postageBatchId Postage BatchId to be used to upload the data with * @param data Data to be uploaded * @param options Additional options like tag, encryption, pinning, content-type and request options * * @returns reference is a content hash of the data * @see [Bee docs - Upload and download](https://docs.ethswarm.org/docs/access-the-swarm/upload-and-download) * @see [Bee API reference - `POST /bytes`](https://docs.ethswarm.org/api/#tag/Bytes/paths/~1bytes/post) */ uploadData(postageBatchId, data, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertBatchId)(postageBatchId); (0, type_2.assertData)(data); if (options) (0, type_2.assertUploadOptions)(options); return bytes.upload(this.getKy(options), data, postageBatchId, options); }); } /** * Download data as a byte array * * @param reference Bee data reference in hex string (either 64 or 128 chars long) or ENS domain. * @param options Options that affects the request behavior * @throws TypeError if some of the input parameters is not expected type * @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters * @see [Bee docs - Upload and download](https://docs.ethswarm.org/docs/access-the-swarm/upload-and-download) * @see [Bee API reference - `GET /bytes`](https://docs.ethswarm.org/api/#tag/Bytes/paths/~1bytes~1{reference}/get) */ downloadData(reference, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); (0, type_2.assertReferenceOrEns)(reference); return bytes.download(this.getKy(options), reference); }); } /** * Download data as a Readable stream * * @param reference Bee data reference in hex string (either 64 or 128 chars long) or ENS domain. * @param options Options that affects the request behavior * @throws TypeError if some of the input parameters is not expected type * @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters * @see [Bee docs - Upload and download](https://docs.ethswarm.org/docs/access-the-swarm/upload-and-download) * @see [Bee API reference - `GET /bytes`](https://docs.ethswarm.org/api/#tag/Bytes/paths/~1bytes~1{reference}/get) */ downloadReadableData(reference, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); (0, type_2.assertReferenceOrEns)(reference); return bytes.downloadReadable(this.getKy(options), reference); }); } /** * Upload chunk to a Bee node * * @param postageBatchId Postage BatchId to be used to upload the chunk with * @param data Raw chunk to be uploaded * @param options Additional options like tag, encryption, pinning, content-type and request options * * @returns reference is a content hash of the data * @see [Bee docs - Upload and download](https://docs.ethswarm.org/docs/access-the-swarm/upload-and-download) * @see [Bee API reference - `POST /chunks`](https://docs.ethswarm.org/api/#tag/Chunk/paths/~1chunks/post) */ uploadChunk(postageBatchId, data, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertBatchId)(postageBatchId); if (!(data instanceof Uint8Array)) { throw new TypeError('Data has to be Uint8Array instance!'); } if (data.length < types_1.SPAN_SIZE) { throw new error_1.BeeArgumentError(`Chunk has to have size of at least ${types_1.SPAN_SIZE}.`, data); } if (data.length > types_1.CHUNK_SIZE + types_1.SPAN_SIZE) { throw new error_1.BeeArgumentError(`Chunk has to have size of at most ${types_1.CHUNK_SIZE}.`, data); } if (options) (0, type_2.assertUploadOptions)(options); return chunk.upload(this.getKy(options), data, postageBatchId, options); }); } /** * Download chunk as a byte array * * @param reference Bee chunk reference in hex string (either 64 or 128 chars long) or ENS domain. * @param options Options that affects the request behavior * @throws TypeError if some of the input parameters is not expected type * @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters * @see [Bee docs - Upload and download](https://docs.ethswarm.org/docs/access-the-swarm/upload-and-download) * @see [Bee API reference - `GET /chunks`](https://docs.ethswarm.org/api/#tag/Chunk/paths/~1chunks~1{reference}/get) */ downloadChunk(reference, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); (0, type_2.assertReferenceOrEns)(reference); return chunk.download(this.getKy(options), reference); }); } /** * Upload single file to a Bee node. * * **To make sure that you won't loose critical data it is highly recommended to also * locally pin the data with `options.pin = true`** * * @param postageBatchId Postage BatchId to be used to upload the data with * @param data Data or file to be uploaded * @param name Optional name of the uploaded file * @param options Additional options like tag, encryption, pinning, content-type and request options * * @see [Bee docs - Keep your data alive / Postage stamps](https://docs.ethswarm.org/docs/access-the-swarm/keep-your-data-alive) * @see [Bee docs - Upload and download](https://docs.ethswarm.org/docs/access-the-swarm/upload-and-download) * @see [Bee API reference - `POST /bzz`](https://docs.ethswarm.org/api/#tag/File/paths/~1bzz/post) * @returns reference is a content hash of the file */ uploadFile(postageBatchId, data, name, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertBatchId)(postageBatchId); (0, type_2.assertFileData)(data); if (options) (0, type_2.assertFileUploadOptions)(options); if (name && typeof name !== 'string') { throw new TypeError('name has to be string or undefined!'); } if ((0, file_1.isFile)(data)) { const fileData = yield (0, file_1.fileArrayBuffer)(data); const fileName = name !== null && name !== void 0 ? name : data.name; const contentType = data.type; const fileOptions = Object.assign({ contentType }, options); return (0, type_2.addCidConversionFunction)(yield bzz.uploadFile(this.getKy(options), fileData, postageBatchId, fileName, fileOptions), swarm_cid_1.ReferenceType.MANIFEST); } else if ((0, stream_1.isReadable)(data) && (options === null || options === void 0 ? void 0 : options.tag) && !options.size) { // TODO: Needed until https://github.com/ethersphere/bee/issues/2317 is resolved const result = yield bzz.uploadFile(this.getKy(options), data, postageBatchId, name, options); yield this.updateTag(options.tag, result.reference); return (0, type_2.addCidConversionFunction)(result, swarm_cid_1.ReferenceType.MANIFEST); } else { return (0, type_2.addCidConversionFunction)(yield bzz.uploadFile(this.getKy(options), data, postageBatchId, name, options), swarm_cid_1.ReferenceType.MANIFEST); } }); } /** * Download single file. * * @param reference Bee file reference in hex string (either 64 or 128 chars long), ENS domain or Swarm CID. * @param path If reference points to manifest, then this parameter defines path to the file * @param options Options that affects the request behavior * @throws TypeError if some of the input parameters is not expected type * @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters * @see Data * @see [Bee docs - Upload and download](https://docs.ethswarm.org/docs/access-the-swarm/upload-and-download) * @see [Bee API reference - `GET /bzz`](https://docs.ethswarm.org/api/#tag/Collection/paths/~1bzz~1{reference}~1{path}/get) */ downloadFile(reference, path = '', options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); reference = (0, type_2.makeReferenceOrEns)(reference, swarm_cid_1.ReferenceType.MANIFEST); return bzz.downloadFile(this.getKy(options), reference, path); }); } /** * Download single file as a readable stream * * @param reference Bee file reference in hex string (either 64 or 128 chars long), ENS domain or Swarm CID. * @param path If reference points to manifest / collections, then this parameter defines path to the file * @param options Options that affects the request behavior * @throws TypeError if some of the input parameters is not expected type * @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters * * @see [Bee docs - Upload and download](https://docs.ethswarm.org/docs/access-the-swarm/upload-and-download) * @see [Bee API reference - `GET /bzz`](https://docs.ethswarm.org/api/#tag/Collection/paths/~1bzz~1{reference}~1{path}/get) */ downloadReadableFile(reference, path = '', options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); reference = (0, type_2.makeReferenceOrEns)(reference, swarm_cid_1.ReferenceType.MANIFEST); return bzz.downloadFileReadable(this.getKy(options), reference, path); }); } /** * Upload collection of files to a Bee node * * Uses the FileList API from the browser. * * The returned `UploadResult.tag` might be undefined if called in CORS-enabled environment. * This will be fixed upon next Bee release. https://github.com/ethersphere/bee-js/issues/406 * * @param postageBatchId Postage BatchId to be used to upload the data with * @param fileList list of files to be uploaded * @param options Additional options like tag, encryption, pinning and request options * * @see [Bee docs - Keep your data alive / Postage stamps](https://docs.ethswarm.org/docs/access-the-swarm/keep-your-data-alive) * @see [Bee docs - Upload directory](https://docs.ethswarm.org/docs/access-the-swarm/upload-a-directory/) * @see [Bee API reference - `POST /bzz`](https://docs.ethswarm.org/api/#tag/Collection/paths/~1bzz/post) */ uploadFiles(postageBatchId, fileList, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertBatchId)(postageBatchId); if (options) (0, type_2.assertCollectionUploadOptions)(options); const data = yield (0, collection_1.makeCollectionFromFileList)(fileList); return (0, type_2.addCidConversionFunction)(yield bzz.uploadCollection(this.getKy(options), data, postageBatchId, options), swarm_cid_1.ReferenceType.MANIFEST); }); } /** * Upload Collection that you can assembly yourself. * * The returned `UploadResult.tag` might be undefined if called in CORS-enabled environment. * This will be fixed upon next Bee release. https://github.com/ethersphere/bee-js/issues/406 * * @param postageBatchId * @param collection * @param options Collections and request options */ uploadCollection(postageBatchId, collection, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertBatchId)(postageBatchId); (0, collection_1.assertCollection)(collection); if (options) (0, type_2.assertCollectionUploadOptions)(options); return (0, type_2.addCidConversionFunction)(yield bzz.uploadCollection(this.ky, collection, postageBatchId, options), swarm_cid_1.ReferenceType.MANIFEST); }); } /** * Upload collection of files. * * Available only in Node.js as it uses the `fs` module. * * The returned `UploadResult.tag` might be undefined if called in CORS-enabled environment. * This will be fixed upon next Bee release. https://github.com/ethersphere/bee-js/issues/406 * * @param postageBatchId Postage BatchId to be used to upload the data with * @param dir the path of the files to be uploaded * @param options Additional options like tag, encryption, pinning and request options * * @see [Bee docs - Keep your data alive / Postage stamps](https://docs.ethswarm.org/docs/access-the-swarm/keep-your-data-alive) * @see [Bee docs - Upload directory](https://docs.ethswarm.org/docs/access-the-swarm/upload-a-directory/) * @see [Bee API reference - `POST /bzz`](https://docs.ethswarm.org/api/#tag/Collection/paths/~1bzz/post) */ uploadFilesFromDirectory(postageBatchId, dir, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertBatchId)(postageBatchId); if (options) (0, type_2.assertCollectionUploadOptions)(options); const data = yield (0, collection_node_1.makeCollectionFromFS)(dir); return (0, type_2.addCidConversionFunction)(yield bzz.uploadCollection(this.getKy(options), data, postageBatchId, options), swarm_cid_1.ReferenceType.MANIFEST); }); } /** * Create a new Tag which is meant for tracking progres of syncing data across network. * * **Warning! Not allowed when node is in Gateway mode!** * * @param options Options that affects the request behavior * @see [Bee docs - Syncing / Tags](https://docs.ethswarm.org/docs/access-the-swarm/syncing) * @see [Bee API reference - `POST /tags`](https://docs.ethswarm.org/api/#tag/Tag/paths/~1tags/post) */ createTag(options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); return tag.createTag(this.getKy(options)); }); } /** * Fetches all tags. * * The listing is limited by options.limit. So you have to iterate using options.offset to get all tags. * * **Warning! Not allowed when node is in Gateway mode!** * * @param options Options that affects the request behavior * @throws TypeError if limit or offset are not numbers or undefined * @throws BeeArgumentError if limit or offset have invalid options * * @see [Bee docs - Syncing / Tags](https://docs.ethswarm.org/docs/access-the-swarm/syncing) * @see [Bee API reference - `GET /tags`](https://docs.ethswarm.org/api/#tag/Tag/paths/~1tags/get) */ getAllTags(options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); (0, type_2.assertAllTagsOptions)(options); return tag.getAllTags(this.getKy(options), options === null || options === void 0 ? void 0 : options.offset, options === null || options === void 0 ? void 0 : options.limit); }); } /** * Retrieve tag information from Bee node * * **Warning! Not allowed when node is in Gateway mode!** * * @param tagUid UID or tag object to be retrieved * @param options Options that affects the request behavior * @throws TypeError if tagUid is in not correct format * * @see [Bee docs - Syncing / Tags](https://docs.ethswarm.org/docs/access-the-swarm/syncing) * @see [Bee API reference - `GET /tags/{uid}`](https://docs.ethswarm.org/api/#tag/Tag/paths/~1tags~1{uid}/get) * */ retrieveTag(tagUid, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); tagUid = (0, type_2.makeTagUid)(tagUid); return tag.retrieveTag(this.getKy(options), tagUid); }); } /** * Delete Tag * * **Warning! Not allowed when node is in Gateway mode!** * * @param tagUid UID or tag object to be retrieved * @param options Options that affects the request behavior * @throws TypeError if tagUid is in not correct format * @throws BeeResponse error if something went wrong on the Bee node side while deleting the tag. * * @see [Bee docs - Syncing / Tags](https://docs.ethswarm.org/docs/access-the-swarm/syncing) * @see [Bee API reference - `DELETE /tags/{uid}`](https://docs.ethswarm.org/api/#tag/Tag/paths/~1tags~1{uid}/delete) */ deleteTag(tagUid, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); tagUid = (0, type_2.makeTagUid)(tagUid); return tag.deleteTag(this.getKy(options), tagUid); }); } /** * Update tag's total chunks count. * * This is important if you are uploading individual chunks with a tag. Then upon finishing the final root chunk, * you can use this method to update the total chunks count for the tag. * * **Warning! Not allowed when node is in Gateway mode!** * * @param tagUid UID or tag object to be retrieved * @param reference The root reference that contains all the chunks to be counted * @param options Options that affects the request behavior * @throws TypeError if tagUid is in not correct format * @throws BeeResponse error if something went wrong on the Bee node side while deleting the tag. * * @see [Bee docs - Syncing / Tags](https://docs.ethswarm.org/docs/access-the-swarm/syncing) * @see [Bee API reference - `PATCH /tags/{uid}`](https://docs.ethswarm.org/api/#tag/Tag/paths/~1tags~1{uid}/patch) */ updateTag(tagUid, reference, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertReference)(reference); (0, type_2.assertRequestOptions)(options); tagUid = (0, type_2.makeTagUid)(tagUid); return tag.updateTag(this.getKy(options), tagUid, reference); }); } /** * Pin local data with given reference * * **Warning! Not allowed when node is in Gateway mode!** * * @param reference Data reference * @param options Options that affects the request behavior * @throws TypeError if reference is in not correct format * * @see [Bee docs - Pinning](https://docs.ethswarm.org/docs/access-the-swarm/pinning) */ pin(reference, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); (0, type_2.assertReference)(reference); return pinning.pin(this.getKy(options), reference); }); } /** * Unpin local data with given reference * * **Warning! Not allowed when node is in Gateway mode!** * * @param reference Data reference * @param options Options that affects the request behavior * @throws TypeError if reference is in not correct format * * @see [Bee docs - Pinning](https://docs.ethswarm.org/docs/access-the-swarm/pinning) */ unpin(reference, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); (0, type_2.assertReference)(reference); return pinning.unpin(this.getKy(options), reference); }); } /** * Get list of all locally pinned references * * **Warning! Not allowed when node is in Gateway mode!** * * @param options Options that affects the request behavior * @see [Bee docs - Pinning](https://docs.ethswarm.org/docs/access-the-swarm/pinning) */ getAllPins(options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); return pinning.getAllPins(this.getKy(options)); }); } /** * Get pinning status of chunk with given reference * * **Warning! Not allowed when node is in Gateway mode!** * * @param reference Bee data reference in hex string (either 64 or 128 chars long) or ENS domain. * @param options Options that affects the request behavior * @throws TypeError if some of the input parameters is not expected type * @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters * * @see [Bee docs - Pinning](https://docs.ethswarm.org/docs/access-the-swarm/pinning) */ getPin(reference, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); (0, type_2.assertReference)(reference); return pinning.getPin(this.getKy(options), reference); }); } /** * Instructs the Bee node to reupload a locally pinned data into the network. * * @param reference Bee data reference to be re-uploaded in hex string (either 64 or 128 chars long) or ENS domain. * @param options Options that affects the request behavior * @throws BeeArgumentError if the reference is not locally pinned * @throws TypeError if some of the input parameters is not expected type * @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters * * @see [Bee API reference - `PUT /stewardship`](https://docs.ethswarm.org/api/#tag/Stewardship/paths/~1stewardship~1{reference}/put) */ reuploadPinnedData(reference, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); (0, type_2.assertReferenceOrEns)(reference); yield stewardship.reupload(this.getKy(options), reference); }); } /** * Checks if content specified by reference is retrievable from the network. * * @param reference Bee data reference to be checked in hex string (either 64 or 128 chars long) or ENS domain. * @param options Options that affects the request behavior * @throws TypeError if some of the input parameters is not expected type * @throws BeeArgumentError if there is passed ENS domain with invalid unicode characters * * @see [Bee API reference - `GET /stewardship`](https://docs.ethswarm.org/api/#tag/Stewardship/paths/~1stewardship~1{reference}/get) */ isReferenceRetrievable(reference, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); (0, type_2.assertReferenceOrEns)(reference); return stewardship.isRetrievable(this.getKy(options), reference); }); } /** * Functions that validates if feed is retrievable in the network. * * If no index is passed then it check for "latest" update, which is a weaker guarantee as nobody can be really * sure what is the "latest" update. * * If index is passed then it validates all previous sequence index chunks if they are available as they are required * to correctly resolve the feed upto the given index update. * * @param type * @param owner * @param topic * @param index * @param options */ isFeedRetrievable(type, owner, topic, index, options) { return __awaiter(this, void 0, void 0, function* () { const canonicalOwner = (0, eth_1.makeEthAddress)(owner); const canonicalTopic = (0, topic_1.makeTopic)(topic); if (!index) { try { yield this.makeFeedReader(type, canonicalTopic, canonicalOwner).download(); return true; } catch (e) { const err = e; // Only if the error is "not-found" then we return false otherwise we re-throw the error if ((err === null || err === void 0 ? void 0 : err.status) === 404) { return false; } throw e; } } if (type !== 'sequence') { throw new error_1.BeeError('Only Sequence type of Feeds is supported at the moment'); } return (0, retrievable_1.areAllSequentialFeedsUpdateRetrievable)(this, canonicalOwner, canonicalTopic, index, options); }); } /** * Send data to recipient or target with Postal Service for Swarm. * * Because sending a PSS message is slow and CPU intensive, * it is not supposed to be used for general messaging but * most likely for setting up an encrypted communication * channel by sending an one-off message. * * **Warning! Not allowed when node is in Gateway mode!** * * **Warning! If the recipient Bee node is a light node, then he will never receive the message!** * This is because light nodes does not fully participate in the data exchange in Swarm network and hence the message won't arrive to them. * * @param postageBatchId Postage BatchId that will be assigned to sent message * @param topic Topic name * @param target Target message address prefix. Has a limit on length. Recommend to use `Utils.Pss.makeMaxTarget()` to get the most specific target that Bee node will accept. * @param data Message to be sent * @param recipient Recipient public key * @param options Options that affects the request behavior * @throws TypeError if `data`, `batchId`, `target` or `recipient` are in invalid format * * @see [Bee docs - PSS](https://docs.ethswarm.org/docs/dapps-on-swarm/pss) * @see [Bee API reference - `POST /pss`](https://docs.ethswarm.org/api/#tag/Postal-Service-for-Swarm/paths/~1pss~1send~1{topic}~1{targets}/post) */ pssSend(postageBatchId, topic, target, data, recipient, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); (0, type_2.assertData)(data); (0, type_2.assertBatchId)(postageBatchId); (0, type_2.assertAddressPrefix)(target); if (typeof topic !== 'string') { throw new TypeError('topic has to be an string!'); } if (recipient) { (0, type_2.assertPublicKey)(recipient); return pss.send(this.getKy(options), topic, target, data, postageBatchId, recipient); } else { return pss.send(this.getKy(options), topic, target, data, postageBatchId); } }); } /** * Subscribe to messages for given topic with Postal Service for Swarm * * **Warning! Not allowed when node is in Gateway mode!** * * **Warning! If connected Bee node is a light node, then he will never receive any message!** * This is because light nodes does not fully participate in the data exchange in Swarm network and hence the message won't arrive to them. * * @param topic Topic name * @param handler Message handler interface * * @returns Subscription to a given topic * * @see [Bee docs - PSS](https://docs.ethswarm.org/docs/dapps-on-swarm/pss) * @see [Bee API reference - `GET /pss`](https://docs.ethswarm.org/api/#tag/Postal-Service-for-Swarm/paths/~1pss~1subscribe~1{topic}/get) */ pssSubscribe(topic, handler) { (0, type_2.assertPssMessageHandler)(handler); if (typeof topic !== 'string') { throw new TypeError('topic has to be an string!'); } const ws = pss.subscribe(this.url, topic); let cancelled = false; const cancel = () => { if (cancelled === false) { cancelled = true; // although the WebSocket API offers a `close` function, it seems that // with the library that we are using (isomorphic-ws) it doesn't close // the websocket properly, whereas `terminate` does if (ws.terminate) ws.terminate(); else ws.close(); // standard Websocket in browser does not have terminate function } }; const subscription = { topic, cancel, }; ws.onmessage = (ev) => __awaiter(this, void 0, void 0, function* () { const data = yield (0, data_1.prepareWebsocketData)(ev.data); // ignore empty messages if (data.length > 0) { handler.onMessage((0, bytes_1.wrapBytesWithHelpers)(data), subscription); } }); ws.onerror = ev => { // ignore errors after subscription was cancelled if (!cancelled) { handler.onError(new error_1.BeeError(ev.message), subscription); } }; return subscription; } /** * Receive message with Postal Service for Swarm * * Because sending a PSS message is slow and CPU intensive, * it is not supposed to be used for general messaging but * most likely for setting up an encrypted communication * channel by sending an one-off message. * * This is a helper function to wait for exactly one message to * arrive and then cancel the subscription. Additionally a * timeout can be provided for the message to arrive or else * an error will be thrown. * * **Warning! Not allowed when node is in Gateway mode!** * * **Warning! If connected Bee node is a light node, then he will never receive any message!** * This is because light nodes does not fully participate in the data exchange in Swarm network and hence the message won't arrive to them. * * @param topic Topic name * @param timeoutMsec Timeout in milliseconds * * @returns Message in byte array * * @see [Bee docs - PSS](https://docs.ethswarm.org/docs/dapps-on-swarm/pss) * @see [Bee API reference - `GET /pss`](https://docs.ethswarm.org/api/#tag/Postal-Service-for-Swarm/paths/~1pss~1subscribe~1{topic}/get) */ pssReceive(topic, timeoutMsec = 0) { return __awaiter(this, void 0, void 0, function* () { if (typeof topic !== 'string') { throw new TypeError('topic has to be an string!'); } if (typeof timeoutMsec !== 'number') { throw new TypeError('timeoutMsc parameter has to be a number!'); } return new Promise((resolve, reject) => { let timeout; const subscription = this.pssSubscribe(topic, { onError: error => { clearTimeout(timeout); subscription.cancel(); reject(error.message); }, onMessage: message => { clearTimeout(timeout); subscription.cancel(); resolve(message); }, }); if (timeoutMsec > 0) { // we need to cast the type because Typescript is getting confused with Node.js' // alternative type definitions timeout = setTimeout(() => { subscription.cancel(); reject(new error_1.BeeError('pssReceive timeout')); }, timeoutMsec); } }); }); } /** * Create feed manifest chunk and return the reference to it. * * Feed manifest chunk allows for a feed to be able to be resolved through `/bzz` endpoint. * * @param postageBatchId Postage BatchId to be used to create the Feed Manifest * @param type The type of the feed, can be 'epoch' or 'sequence' * @param topic Topic in hex or bytes * @param owner Owner's ethereum address in hex or bytes * @param options Options that affects the request behavior * * @see [Bee docs - Feeds](https://docs.ethswarm.org/docs/dapps-on-swarm/feeds) * @see [Bee API reference - `POST /feeds`](https://docs.ethswarm.org/api/#tag/Feed/paths/~1feeds~1{owner}~1{topic}/post) * TODO: Once breaking add support for Feed CID */ createFeedManifest(postageBatchId, type, topic, owner, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options); (0, type_1.assertFeedType)(type); (0, type_2.assertBatchId)(postageBatchId); const canonicalTopic = (0, topic_1.makeTopic)(topic); const canonicalOwner = (0, eth_1.makeHexEthAddress)(owner); return (0, feed_2.createFeedManifest)(this.getKy(options), canonicalOwner, canonicalTopic, postageBatchId, { type }); }); } /** * Make a new feed reader for downloading feed updates. * * @param type The type of the feed, can be 'epoch' or 'sequence' * @param topic Topic in hex or bytes * @param owner Owner's ethereum address in hex or bytes * @param options Options that affects the request behavior * * @see [Bee docs - Feeds](https://docs.ethswarm.org/docs/dapps-on-swarm/feeds) */ makeFeedReader(type, topic, owner, options) { (0, type_2.assertRequestOptions)(options); (0, type_1.assertFeedType)(type); const canonicalTopic = (0, topic_1.makeTopic)(topic); const canonicalOwner = (0, eth_1.makeHexEthAddress)(owner); return (0, feed_1.makeFeedReader)(this.getKy(options), type, canonicalTopic, canonicalOwner); } /** * Make a new feed writer for updating feeds * * @param type The type of the feed, can be 'epoch' or 'sequence' * @param topic Topic in hex or bytes * @param signer The signer's private key or a Signer instance that can sign data * @param options Options that affects the request behavior * * @see [Bee docs - Feeds](https://docs.ethswarm.org/docs/dapps-on-swarm/feeds) */ makeFeedWriter(type, topic, signer, options) { (0, type_2.assertRequestOptions)(options); (0, type_1.assertFeedType)(type); const canonicalTopic = (0, topic_1.makeTopic)(topic); const canonicalSigner = this.resolveSigner(signer); return (0, feed_1.makeFeedWriter)(this.getKy(options), type, canonicalTopic, canonicalSigner); } /** * High-level function that allows you to easily set JSON data to feed. * JSON-like data types are supported. * * The default Signer of Bee instance is used if `options.signer` is not specified. * If none of those two is set error is thrown. * * @param postageBatchId Postage BatchId to be used to upload the data with * @param topic Human readable string, that is internally hashed so there are no constrains there. * @param data JSON compatible data * @param options * @param options.signer Custom instance of Signer or string with private key. * @param options.type Type of Feed * * @throws BeeError if `options.signer` is not specified nor the default Signer on Bee's instance is specified. * * @see [Bee docs - Feeds](https://docs.ethswarm.org/docs/dapps-on-swarm/feeds) */ setJsonFeed(postageBatchId, topic, data, options) { var _a; return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options, 'JsonFeedOptions'); (0, type_2.assertBatchId)(postageBatchId); const hashedTopic = this.makeFeedTopic(topic); const feedType = (_a = options === null || options === void 0 ? void 0 : options.type) !== null && _a !== void 0 ? _a : type_1.DEFAULT_FEED_TYPE; const writer = this.makeFeedWriter(feedType, hashedTopic, options === null || options === void 0 ? void 0 : options.signer, options); return (0, json_1.setJsonData)(this, writer, postageBatchId, data, options); }); } /** * High-level function that allows you to easily get data from feed. * Returned data are parsed using JSON.parse(). * * This method also supports specification of `signer` object passed to constructor. The order of evaluation is: * - `options.address` * - `options.signer` * - `this.signer` * * At least one of these has to be specified! * * @param topic Human readable string, that is internally hashed so there are no constrains there. * @param options * @param options.signer Custom instance of Signer or string with private key. This option is exclusive with `address` option. * @param options.address Ethereum address of owner of the feed that signed it. This option is exclusive with `signer` option. * @param options.type Type of Feed * * @see [Bee docs - Feeds](https://docs.ethswarm.org/docs/dapps-on-swarm/feeds) */ getJsonFeed(topic, options) { var _a; return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options, 'JsonFeedOptions'); const hashedTopic = this.makeFeedTopic(topic); const feedType = (_a = options === null || options === void 0 ? void 0 : options.type) !== null && _a !== void 0 ? _a : type_1.DEFAULT_FEED_TYPE; if ((options === null || options === void 0 ? void 0 : options.signer) && (options === null || options === void 0 ? void 0 : options.address)) { throw new error_1.BeeError('Both options "signer" and "address" can not be specified at one time!'); } let address; if (options === null || options === void 0 ? void 0 : options.address) { address = (0, eth_1.makeEthAddress)(options === null || options === void 0 ? void 0 : options.address); } else { try { address = this.resolveSigner(options === null || options === void 0 ? void 0 : options.signer).address; } catch (e) { if (e instanceof error_1.BeeError) { throw new error_1.BeeError('Either address, signer or default signer has to be specified!'); } else { throw e; } } } const reader = this.makeFeedReader(feedType, hashedTopic, address, options); return (0, json_1.getJsonData)(this, reader); }); } /** * Make a new feed topic from a string * * Because the topic has to be 32 bytes long this function * hashes the input string to create a topic string of arbitrary length. * * @param topic The input string */ makeFeedTopic(topic) { return (0, topic_1.makeTopicFromString)(topic); } /** * Returns an object for reading single owner chunks * * @param ownerAddress The ethereum address of the owner * @param options Options that affects the request behavior * @see [Bee docs - Chunk Types](https://docs.ethswarm.org/docs/dapps-on-swarm/chunk-types#single-owner-chunks) */ makeSOCReader(ownerAddress, options) { (0, type_2.assertRequestOptions)(options); const canonicalOwner = (0, eth_1.makeEthAddress)(ownerAddress); return { owner: (0, eth_1.makeHexEthAddress)(canonicalOwner), download: soc_1.downloadSingleOwnerChunk.bind(null, this.getKy(options), canonicalOwner), }; } /** * Returns an object for reading and writing single owner chunks * * @param signer The signer's private key or a Signer instance that can sign data * @param options Options that affects the request behavior * @see [Bee docs - Chunk Types](https://docs.ethswarm.org/docs/dapps-on-swarm/chunk-types#single-owner-chunks) */ makeSOCWriter(signer, options) { (0, type_2.assertRequestOptions)(options); const canonicalSigner = this.resolveSigner(signer); return Object.assign(Object.assign({}, this.makeSOCReader(canonicalSigner.address, options)), { upload: soc_1.uploadSingleOwnerChunkData.bind(null, this.getKy(options), canonicalSigner) }); } /** * Ping the Bee node to see if there is a live Bee node on the given URL. * * @param options Options that affects the request behavior * @throws If connection was not successful throw error */ checkConnection(options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options, 'PostageBatchOptions'); return status.checkConnection(this.getKy(options)); }); } /** * Ping the Bee node to see if there is a live Bee node on the given URL. * * @param options Options that affects the request behavior * @returns true if successful, false on error */ isConnected(options) { return __awaiter(this, void 0, void 0, function* () { (0, type_2.assertRequestOptions)(options, 'PostageBatchOptions'); try { yield status.checkConnection(this.getKy(options)); } catch (e) { return false; } return true; }); } /** * @param signer * @private * @throws BeeError if either no Signer was passed or no default Signer was specified for the instance */ resolveSigner(signer) { if (signer) { return (0, signer_1.makeSigner)(signer); } if (this.signer) { return this.signer; } throw new error_1.BeeError('You have to pass Signer as property to either the method call or constructor! Non found.'); } getKy(options) { if (!options) { return this.ky; } return this.ky.extend(options); } } exports.Bee = Bee;