From 9eac5cd1a75277566b7d48255467afcd0d478f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Uhl=C3=AD=C5=99?= Date: Mon, 20 Sep 2021 16:32:26 +0200 Subject: [PATCH] feat: request options (#411) --- src/bee-debug.ts | 220 ++++++++++++++++++++---------- src/bee.ts | 220 ++++++++++++++++++++---------- src/feed/json.ts | 5 +- src/types/debug.ts | 4 +- src/types/index.ts | 32 ++++- src/utils/type.ts | 94 +++++++++++-- test/unit/assertions.ts | 97 ++++++++++++- test/unit/bee-class.spec.ts | 178 +++++++++++++++++++++++- test/unit/bee-debug-class.spec.ts | 149 ++++++++++++++------ 9 files changed, 789 insertions(+), 210 deletions(-) diff --git a/src/bee-debug.ts b/src/bee-debug.ts index c894ee80..eba04ed7 100644 --- a/src/bee-debug.ts +++ b/src/bee-debug.ts @@ -38,7 +38,9 @@ import { assertAddress, assertBatchId, assertBoolean, + assertCashoutOptions, assertNonNegativeInteger, + assertRequestOptions, assertTransactionHash, isTag, } from './utils/type' @@ -47,6 +49,7 @@ import { BeeOptions, CashoutOptions, PostageBatchOptions, + RequestOptions, STAMPS_DEPTH_MAX, STAMPS_DEPTH_MIN, Tag, @@ -83,7 +86,9 @@ export class BeeDebug { const kyOptions: KyOptions = { prefixUrl: this.url, - timeout: false, + timeout: options?.timeout ?? false, + retry: options?.retry, + fetch: options?.fetch, hooks: { beforeRequest: [], afterResponse: [], @@ -105,12 +110,16 @@ export class BeeDebug { this.ky = makeDefaultKy(kyOptions) } - async getNodeAddresses(): Promise { - return connectivity.getNodeAddresses(this.ky) + async getNodeAddresses(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return connectivity.getNodeAddresses(this.getKy(options)) } - async getBlocklist(): Promise { - return connectivity.getBlocklist(this.ky) + async getBlocklist(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return connectivity.getBlocklist(this.getKy(options)) } /** @@ -123,7 +132,9 @@ export class BeeDebug { * @see [Bee API reference - `GET /tags/{uid}`](https://docs.ethswarm.org/debug-api/#tag/Tag) * */ - async retrieveExtendedTag(tagUid: number | Tag): Promise { + async retrieveExtendedTag(tagUid: number | Tag, options?: RequestOptions): Promise { + assertRequestOptions(options) + if (isTag(tagUid)) { tagUid = tagUid.uid } else if (typeof tagUid === 'number') { @@ -132,30 +143,36 @@ export class BeeDebug { throw new TypeError('tagUid has to be either Tag or a number (UID)!') } - return tag.retrieveExtendedTag(this.ky, tagUid) + return tag.retrieveExtendedTag(this.getKy(options), tagUid) } /** * Get list of peers for this node */ - async getPeers(): Promise { - return connectivity.getPeers(this.ky) + async getPeers(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return connectivity.getPeers(this.getKy(options)) } - async removePeer(peer: string | Address): Promise { + async removePeer(peer: string | Address, options?: RequestOptions): Promise { + assertRequestOptions(options) assertAddress(peer) - return connectivity.removePeer(this.ky, peer) + return connectivity.removePeer(this.getKy(options), peer) } - async getTopology(): Promise { - return connectivity.getTopology(this.ky) + async getTopology(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return connectivity.getTopology(this.getKy(options)) } - async pingPeer(peer: string | Address): Promise { + async pingPeer(peer: string | Address, options?: RequestOptions): Promise { + assertRequestOptions(options) assertAddress(peer) - return connectivity.pingPeer(this.ky, peer) + return connectivity.pingPeer(this.getKy(options), peer) } /* @@ -165,8 +182,10 @@ export class BeeDebug { /** * Get the balances with all known peers including prepaid services */ - async getAllBalances(): Promise { - return balance.getAllBalances(this.ky) + async getAllBalances(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return balance.getAllBalances(this.getKy(options)) } /** @@ -174,17 +193,20 @@ export class BeeDebug { * * @param address Swarm address of peer */ - async getPeerBalance(address: Address | string): Promise { + async getPeerBalance(address: Address | string, options?: RequestOptions): Promise { + assertRequestOptions(options) assertAddress(address) - return balance.getPeerBalance(this.ky, address) + return balance.getPeerBalance(this.getKy(options), address) } /** * Get the past due consumption balances with all known peers */ - async getPastDueConsumptionBalances(): Promise { - return balance.getPastDueConsumptionBalances(this.ky) + async getPastDueConsumptionBalances(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return balance.getPastDueConsumptionBalances(this.getKy(options)) } /** @@ -192,10 +214,11 @@ export class BeeDebug { * * @param address Swarm address of peer */ - async getPastDueConsumptionPeerBalance(address: Address | string): Promise { + async getPastDueConsumptionPeerBalance(address: Address | string, options?: RequestOptions): Promise { + assertRequestOptions(options) assertAddress(address) - return balance.getPastDueConsumptionPeerBalance(this.ky, address) + return balance.getPastDueConsumptionPeerBalance(this.getKy(options), address) } /* @@ -208,22 +231,28 @@ export class BeeDebug { * **Warning:** The address is returned with 0x prefix unlike all other calls. * https://github.com/ethersphere/bee/issues/1443 */ - async getChequebookAddress(): Promise { - return chequebook.getChequebookAddress(this.ky) + async getChequebookAddress(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return chequebook.getChequebookAddress(this.getKy(options)) } /** * Get the balance of the chequebook */ - async getChequebookBalance(): Promise { - return chequebook.getChequebookBalance(this.ky) + async getChequebookBalance(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return chequebook.getChequebookBalance(this.getKy(options)) } /** * Get last cheques for all peers */ - async getLastCheques(): Promise { - return chequebook.getLastCheques(this.ky) + async getLastCheques(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return chequebook.getLastCheques(this.getKy(options)) } /** @@ -231,10 +260,14 @@ export class BeeDebug { * * @param address Swarm address of peer */ - async getLastChequesForPeer(address: Address | string): Promise { + async getLastChequesForPeer( + address: Address | string, + options?: RequestOptions, + ): Promise { + assertRequestOptions(options) assertAddress(address) - return chequebook.getLastChequesForPeer(this.ky, address) + return chequebook.getLastChequesForPeer(this.getKy(options), address) } /** @@ -242,10 +275,11 @@ export class BeeDebug { * * @param address Swarm address of peer */ - async getLastCashoutAction(address: Address | string): Promise { + async getLastCashoutAction(address: Address | string, options?: RequestOptions): Promise { + assertRequestOptions(options) assertAddress(address) - return chequebook.getLastCashoutAction(this.ky, address) + return chequebook.getLastCashoutAction(this.getKy(options), address) } /** @@ -257,17 +291,10 @@ export class BeeDebug { * @param options.gasLimit Gas limit for the cashout transaction in WEI */ async cashoutLastCheque(address: string | Address, options?: CashoutOptions): Promise { + assertCashoutOptions(options) assertAddress(address) - if (options?.gasLimit) { - assertNonNegativeInteger(options.gasLimit) - } - - if (options?.gasPrice) { - assertNonNegativeInteger(options.gasPrice) - } - - return chequebook.cashoutLastCheque(this.ky, address, options) + return chequebook.cashoutLastCheque(this.getKy(options), address, options) } /** @@ -277,14 +304,19 @@ export class BeeDebug { * @param gasPrice Gas Price in WEI for the transaction call * @return string Hash of the transaction */ - async depositTokens(amount: number | NumberString, gasPrice?: NumberString): Promise { + async depositTokens( + amount: number | NumberString, + gasPrice?: NumberString, + options?: RequestOptions, + ): Promise { + assertRequestOptions(options) assertNonNegativeInteger(amount) if (gasPrice) { assertNonNegativeInteger(gasPrice) } - return chequebook.depositTokens(this.ky, amount, gasPrice) + return chequebook.depositTokens(this.getKy(options), amount, gasPrice) } /** @@ -294,14 +326,19 @@ export class BeeDebug { * @param gasPrice Gas Price in WEI for the transaction call * @return string Hash of the transaction */ - async withdrawTokens(amount: number | NumberString, gasPrice?: NumberString): Promise { + async withdrawTokens( + amount: number | NumberString, + gasPrice?: NumberString, + options?: RequestOptions, + ): Promise { + assertRequestOptions(options) assertNonNegativeInteger(amount) if (gasPrice) { assertNonNegativeInteger(gasPrice) } - return chequebook.withdrawTokens(this.ky, amount, gasPrice) + return chequebook.withdrawTokens(this.getKy(options), amount, gasPrice) } /* @@ -313,24 +350,29 @@ export class BeeDebug { * * @param address Swarm address of peer */ - async getSettlements(address: Address | string): Promise { + async getSettlements(address: Address | string, options?: RequestOptions): Promise { + assertRequestOptions(options) assertAddress(address) - return settlements.getSettlements(this.ky, address) + return settlements.getSettlements(this.getKy(options), address) } /** * Get settlements with all known peers and total amount sent or received */ - async getAllSettlements(): Promise { - return settlements.getAllSettlements(this.ky) + async getAllSettlements(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return settlements.getAllSettlements(this.getKy(options)) } /** * Get health of node */ - async getHealth(): Promise { - return status.getHealth(this.ky) + async getHealth(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return status.getHealth(this.getKy(options)) } /** @@ -338,22 +380,28 @@ export class BeeDebug { * * @returns true if the Bee node version is supported */ - async isSupportedVersion(): Promise | never { - return status.isSupportedVersion(this.ky) + async isSupportedVersion(options?: RequestOptions): Promise | never { + assertRequestOptions(options) + + return status.isSupportedVersion(this.getKy(options)) } /** * Get reserve state */ - async getReserveState(): Promise { - return states.getReserveState(this.ky) + async getReserveState(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return states.getReserveState(this.getKy(options)) } /** * Get chain state */ - async getChainState(): Promise { - return states.getChainState(this.ky) + async getChainState(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return states.getChainState(this.getKy(options)) } /** @@ -374,6 +422,7 @@ export class BeeDebug { * @see [Bee Debug API reference - `POST /stamps`](https://docs.ethswarm.org/debug-api/#tag/Postage-Stamps/paths/~1stamps~1{amount}~1{depth}/post) */ async createPostageBatch(amount: NumberString, depth: number, options?: PostageBatchOptions): Promise { + assertRequestOptions(options) assertNonNegativeInteger(amount) assertNonNegativeInteger(depth) @@ -393,7 +442,7 @@ export class BeeDebug { assertBoolean(options.immutableFlag) } - return stamps.createPostageBatch(this.ky, amount, depth, options) + return stamps.createPostageBatch(this.getKy(options), amount, depth, options) } /** @@ -404,10 +453,11 @@ export class BeeDebug { * @see [Bee docs - Keep your data alive / Postage stamps](https://docs.ethswarm.org/docs/access-the-swarm/keep-your-data-alive) * @see [Bee Debug API reference - `GET /stamps/${id}`](https://docs.ethswarm.org/debug-api/#tag/Postage-Stamps/paths/~1stamps~1{id}/get) */ - async getPostageBatch(postageBatchId: BatchId | string): Promise { + async getPostageBatch(postageBatchId: BatchId | string, options?: RequestOptions): Promise { + assertRequestOptions(options) assertBatchId(postageBatchId) - return stamps.getPostageBatch(this.ky, postageBatchId) + return stamps.getPostageBatch(this.getKy(options), postageBatchId) } /** @@ -418,10 +468,14 @@ export class BeeDebug { * @see [Bee docs - Keep your data alive / Postage stamps](https://docs.ethswarm.org/docs/access-the-swarm/keep-your-data-alive) * @see [Bee Debug API reference - `GET /stamps/${id}/buckets`](https://docs.ethswarm.org/debug-api/#tag/Postage-Stamps/paths/~1stamps~1{id}~1buckets/get) */ - async getPostageBatchBuckets(postageBatchId: BatchId | string): Promise { + async getPostageBatchBuckets( + postageBatchId: BatchId | string, + options?: RequestOptions, + ): Promise { + assertRequestOptions(options) assertBatchId(postageBatchId) - return stamps.getPostageBatchBuckets(this.ky, postageBatchId) + return stamps.getPostageBatchBuckets(this.getKy(options), postageBatchId) } /** @@ -430,25 +484,33 @@ export class BeeDebug { * @see [Bee docs - Keep your data alive / Postage stamps](https://docs.ethswarm.org/docs/access-the-swarm/keep-your-data-alive) * @see [Bee Debug API reference - `GET /stamps`](https://docs.ethswarm.org/debug-api/#tag/Postage-Stamps/paths/~1stamps/get) */ - async getAllPostageBatch(): Promise { - return stamps.getAllPostageBatches(this.ky) + async getAllPostageBatch(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return stamps.getAllPostageBatches(this.getKy(options)) } /** * Return lists of all current pending transactions that the Bee made */ - async getAllPendingTransactions(): Promise { - return transactions.getAllTransactions(this.ky) + async getAllPendingTransactions(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return transactions.getAllTransactions(this.getKy(options)) } /** * Return transaction information for specific transaction * @param transactionHash */ - async getPendingTransaction(transactionHash: TransactionHash | string): Promise { + async getPendingTransaction( + transactionHash: TransactionHash | string, + options?: RequestOptions, + ): Promise { + assertRequestOptions(options) assertTransactionHash(transactionHash) - return transactions.getTransaction(this.ky, transactionHash) + return transactions.getTransaction(this.getKy(options), transactionHash) } /** @@ -457,10 +519,14 @@ export class BeeDebug { * * @param transactionHash */ - async rebroadcastPendingTransaction(transactionHash: TransactionHash | string): Promise { + async rebroadcastPendingTransaction( + transactionHash: TransactionHash | string, + options?: RequestOptions, + ): Promise { + assertRequestOptions(options) assertTransactionHash(transactionHash) - return transactions.rebroadcastTransaction(this.ky, transactionHash) + return transactions.rebroadcastTransaction(this.getKy(options), transactionHash) } /** @@ -471,13 +537,23 @@ export class BeeDebug { async cancelPendingTransaction( transactionHash: TransactionHash | string, gasPrice?: NumberString, + options?: RequestOptions, ): Promise { + assertRequestOptions(options) assertTransactionHash(transactionHash) if (gasPrice) { assertNonNegativeInteger(gasPrice) } - return transactions.cancelTransaction(this.ky, transactionHash, gasPrice) + return transactions.cancelTransaction(this.getKy(options), transactionHash, gasPrice) + } + + private getKy(options?: RequestOptions): Ky { + if (!options) { + return this.ky + } + + return this.ky.extend(options) } } diff --git a/src/bee.ts b/src/bee.ts index 9432b438..e9e0e22c 100644 --- a/src/bee.ts +++ b/src/bee.ts @@ -23,15 +23,16 @@ import { assertAddressPrefix, assertAllTagsOptions, assertBatchId, - assertBoolean, assertCollectionUploadOptions, assertData, assertFileData, assertFileUploadOptions, assertNonNegativeInteger, + assertPostageBatchOptions, assertPssMessageHandler, assertPublicKey, assertReference, + assertRequestOptions, assertUploadOptions, makeTagUid, } from './utils/type' @@ -44,6 +45,7 @@ import { NumberString, PostageBatchOptions, Readable, + RequestOptions, STAMPS_DEPTH_MAX, STAMPS_DEPTH_MIN, UploadResult, @@ -120,7 +122,9 @@ export class Bee { const kyOptions: KyOptions = { prefixUrl: this.url, - timeout: false, + timeout: options?.timeout ?? false, + retry: options?.retry, + fetch: options?.fetch, hooks: { beforeRequest: [], afterResponse: [], @@ -147,7 +151,7 @@ export class Bee { * * @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 + * @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) @@ -163,33 +167,40 @@ export class Bee { if (options) assertUploadOptions(options) - return bytes.upload(this.ky, data, postageBatchId, options) + return bytes.upload(this.getKy(options), data, postageBatchId, options) } /** * Download data as a byte array * * @param reference Bee data reference + * @param options Options that affects the request behavior * @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) */ - async downloadData(reference: Reference | string): Promise { + async downloadData(reference: Reference | string, options?: RequestOptions): Promise { + assertRequestOptions(options) assertReference(reference) - return bytes.download(this.ky, reference) + return bytes.download(this.getKy(options), reference) } /** * Download data as a Readable stream * * @param reference Bee data reference + * @param options Options that affects the request behavior * @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) */ - async downloadReadableData(reference: Reference | string): Promise> { + async downloadReadableData( + reference: Reference | string, + options?: RequestOptions, + ): Promise> { + assertRequestOptions(options) assertReference(reference) - return bytes.downloadReadable(this.ky, reference) + return bytes.downloadReadable(this.getKy(options), reference) } /** @@ -201,7 +212,7 @@ export class Bee { * @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 + * @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) @@ -229,15 +240,15 @@ export class Bee { const contentType = data.type const fileOptions = { contentType, ...options } - return bzz.uploadFile(this.ky, fileData, postageBatchId, fileName, fileOptions) + return bzz.uploadFile(this.getKy(options), fileData, postageBatchId, fileName, fileOptions) } else if (isReadable(data) && options?.tag && !options.size) { // TODO: Needed until https://github.com/ethersphere/bee/issues/2317 is resolved - const result = await bzz.uploadFile(this.ky, data, postageBatchId, name, options) + const result = await bzz.uploadFile(this.getKy(options), data, postageBatchId, name, options) await this.updateTag(options.tag, result.reference) return result } else { - return bzz.uploadFile(this.ky, data, postageBatchId, name, options) + return bzz.uploadFile(this.getKy(options), data, postageBatchId, name, options) } } @@ -246,15 +257,17 @@ export class Bee { * * @param reference Bee file reference * @param path If reference points to manifest, then this parameter defines path to the file + * @param options Options that affects the request behavior * * @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) */ - async downloadFile(reference: Reference | string, path = ''): Promise> { + async downloadFile(reference: Reference | string, path = '', options?: RequestOptions): Promise> { + assertRequestOptions(options) assertReference(reference) - return bzz.downloadFile(this.ky, reference, path) + return bzz.downloadFile(this.getKy(options), reference, path) } /** @@ -262,14 +275,20 @@ export class Bee { * * @param reference Hash reference to file * @param path If reference points to manifest / collections, then this parameter defines path to the file + * @param options Options that affects the request behavior * * @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) */ - async downloadReadableFile(reference: Reference | string, path = ''): Promise>> { + async downloadReadableFile( + reference: Reference | string, + path = '', + options?: RequestOptions, + ): Promise>> { + assertRequestOptions(options) assertReference(reference) - return bzz.downloadFileReadable(this.ky, reference, path) + return bzz.downloadFileReadable(this.getKy(options), reference, path) } /** @@ -282,7 +301,7 @@ export class Bee { * * @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 + * @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/) @@ -299,7 +318,7 @@ export class Bee { const data = await makeCollectionFromFileList(fileList) - return bzz.uploadCollection(this.ky, data, postageBatchId, options) + return bzz.uploadCollection(this.getKy(options), data, postageBatchId, options) } /** @@ -310,7 +329,7 @@ export class Bee { * * @param postageBatchId * @param collection - * @param options + * @param options Collections and request options */ async uploadCollection( postageBatchId: string | BatchId, @@ -335,7 +354,7 @@ export class Bee { * * @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 + * @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/) @@ -351,7 +370,7 @@ export class Bee { if (options) assertCollectionUploadOptions(options) const data = await makeCollectionFromFS(dir) - return bzz.uploadCollection(this.ky, data, postageBatchId, options) + return bzz.uploadCollection(this.getKy(options), data, postageBatchId, options) } /** @@ -359,11 +378,14 @@ export class Bee { * * **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) */ - async createTag(): Promise { - return tag.createTag(this.ky) + async createTag(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return tag.createTag(this.getKy(options)) } /** @@ -373,7 +395,7 @@ export class Bee { * * **Warning! Not allowed when node is in Gateway mode!** * - * @param options + * @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 * @@ -381,9 +403,10 @@ export class Bee { * @see [Bee API reference - `GET /tags`](https://docs.ethswarm.org/api/#tag/Tag/paths/~1tags/get) */ async getAllTags(options?: AllTagsOptions): Promise { + assertRequestOptions(options) assertAllTagsOptions(options) - return tag.getAllTags(this.ky, options?.offset, options?.limit) + return tag.getAllTags(this.getKy(options), options?.offset, options?.limit) } /** @@ -392,16 +415,19 @@ export class Bee { * **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) * */ - async retrieveTag(tagUid: number | Tag): Promise { + async retrieveTag(tagUid: number | Tag, options?: RequestOptions): Promise { + assertRequestOptions(options) + tagUid = makeTagUid(tagUid) - return tag.retrieveTag(this.ky, tagUid) + return tag.retrieveTag(this.getKy(options), tagUid) } /** @@ -410,16 +436,19 @@ export class Bee { * **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) */ - async deleteTag(tagUid: number | Tag): Promise { + async deleteTag(tagUid: number | Tag, options?: RequestOptions): Promise { + assertRequestOptions(options) + tagUid = makeTagUid(tagUid) - return tag.deleteTag(this.ky, tagUid) + return tag.deleteTag(this.getKy(options), tagUid) } /** @@ -432,17 +461,20 @@ export class Bee { * * @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) */ - async updateTag(tagUid: number | Tag, reference: Reference | string): Promise { + async updateTag(tagUid: number | Tag, reference: Reference | string, options?: RequestOptions): Promise { assertReference(reference) + assertRequestOptions(options) + tagUid = makeTagUid(tagUid) - return tag.updateTag(this.ky, tagUid, reference) + return tag.updateTag(this.getKy(options), tagUid, reference) } /** @@ -451,14 +483,16 @@ export class Bee { * **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) */ - async pin(reference: Reference | string): Promise { + async pin(reference: Reference | string, options?: RequestOptions): Promise { + assertRequestOptions(options) assertReference(reference) - return pinning.pin(this.ky, reference) + return pinning.pin(this.getKy(options), reference) } /** @@ -467,14 +501,16 @@ export class Bee { * **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) */ - async unpin(reference: Reference | string): Promise { + async unpin(reference: Reference | string, options?: RequestOptions): Promise { + assertRequestOptions(options) assertReference(reference) - return pinning.unpin(this.ky, reference) + return pinning.unpin(this.getKy(options), reference) } /** @@ -482,10 +518,13 @@ export class Bee { * * **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) */ - async getAllPins(): Promise { - return pinning.getAllPins(this.ky) + async getAllPins(options?: RequestOptions): Promise { + assertRequestOptions(options) + + return pinning.getAllPins(this.getKy(options)) } /** @@ -494,27 +533,31 @@ export class Bee { * **Warning! Not allowed when node is in Gateway mode!** * * @param reference Bee 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) */ - async getPin(reference: Reference | string): Promise { + async getPin(reference: Reference | string, options?: RequestOptions): Promise { + assertRequestOptions(options) assertReference(reference) - return pinning.getPin(this.ky, reference) + return pinning.getPin(this.getKy(options), reference) } /** * Instructs the Bee node to reupload a locally pinned data into the network. * * @param reference + * @param options Options that affects the request behavior * @throws BeeArgumentError if the reference is not locally pinned * @throws TypeError if reference is in not correct format */ - async reuploadPinnedData(reference: Reference | string): Promise { + async reuploadPinnedData(reference: Reference | string, options?: RequestOptions): Promise { + assertRequestOptions(options) assertReference(reference) - await stewardship.reupload(this.ky, reference) + await stewardship.reupload(this.getKy(options), reference) } /** @@ -535,6 +578,7 @@ export class Bee { * @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) @@ -546,7 +590,9 @@ export class Bee { target: AddressPrefix, data: string | Uint8Array, recipient?: string | PublicKey, + options?: RequestOptions, ): Promise { + assertRequestOptions(options) assertData(data) assertBatchId(postageBatchId) assertAddressPrefix(target) @@ -558,9 +604,9 @@ export class Bee { if (recipient) { assertPublicKey(recipient) - return pss.send(this.ky, topic, target, data, postageBatchId, recipient) + return pss.send(this.getKy(options), topic, target, data, postageBatchId, recipient) } else { - return pss.send(this.ky, topic, target, data, postageBatchId) + return pss.send(this.getKy(options), topic, target, data, postageBatchId) } } @@ -695,6 +741,7 @@ export class Bee { * @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) @@ -704,14 +751,16 @@ export class Bee { type: FeedType, topic: Topic | Uint8Array | string, owner: EthAddress | Uint8Array | string, + options?: RequestOptions, ): Promise { + assertRequestOptions(options) assertFeedType(type) assertBatchId(postageBatchId) const canonicalTopic = makeTopic(topic) const canonicalOwner = makeHexEthAddress(owner) - return createFeedManifest(this.ky, canonicalOwner, canonicalTopic, postageBatchId, { type }) + return createFeedManifest(this.getKy(options), canonicalOwner, canonicalTopic, postageBatchId, { type }) } /** @@ -720,6 +769,7 @@ export class Bee { * @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) */ @@ -727,13 +777,15 @@ export class Bee { type: FeedType, topic: Topic | Uint8Array | string, owner: EthAddress | Uint8Array | string, + options?: RequestOptions, ): FeedReader { + assertRequestOptions(options) assertFeedType(type) const canonicalTopic = makeTopic(topic) const canonicalOwner = makeHexEthAddress(owner) - return makeFeedReader(this.ky, type, canonicalTopic, canonicalOwner) + return makeFeedReader(this.getKy(options), type, canonicalTopic, canonicalOwner) } /** @@ -742,6 +794,7 @@ export class Bee { * @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) */ @@ -749,13 +802,15 @@ export class Bee { type: FeedType, topic: Topic | Uint8Array | string, signer?: Signer | Uint8Array | string, + options?: RequestOptions, ): FeedWriter { + assertRequestOptions(options) assertFeedType(type) const canonicalTopic = makeTopic(topic) const canonicalSigner = this.resolveSigner(signer) - return makeFeedWriter(this.ky, type, canonicalTopic, canonicalSigner) + return makeFeedWriter(this.getKy(options), type, canonicalTopic, canonicalSigner) } /** @@ -782,13 +837,14 @@ export class Bee { data: T, options?: JsonFeedOptions, ): Promise { + assertRequestOptions(options, 'JsonFeedOptions') assertBatchId(postageBatchId) const hashedTopic = this.makeFeedTopic(topic) const feedType = options?.type ?? DEFAULT_FEED_TYPE - const writer = this.makeFeedWriter(feedType, hashedTopic, options?.signer) + const writer = this.makeFeedWriter(feedType, hashedTopic, options?.signer, options) - return setJsonData(this, writer, postageBatchId, data) + return setJsonData(this, writer, postageBatchId, data, options) } /** @@ -811,6 +867,8 @@ export class Bee { * @see [Bee docs - Feeds](https://docs.ethswarm.org/docs/dapps-on-swarm/feeds) */ async getJsonFeed(topic: string, options?: JsonFeedOptions): Promise { + assertRequestOptions(options, 'JsonFeedOptions') + const hashedTopic = this.makeFeedTopic(topic) const feedType = options?.type ?? DEFAULT_FEED_TYPE @@ -834,7 +892,7 @@ export class Bee { } } - const reader = this.makeFeedReader(feedType, hashedTopic, address) + const reader = this.makeFeedReader(feedType, hashedTopic, address, options) return getJsonData(this, reader) } @@ -855,14 +913,15 @@ export class Bee { * 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: EthAddress | Uint8Array | string): SOCReader { + makeSOCReader(ownerAddress: EthAddress | Uint8Array | string, options?: RequestOptions): SOCReader { + assertRequestOptions(options) const canonicalOwner = makeEthAddress(ownerAddress) return { - download: downloadSingleOwnerChunk.bind(null, this.ky, canonicalOwner), + download: downloadSingleOwnerChunk.bind(null, this.getKy(options), canonicalOwner), } } @@ -870,16 +929,17 @@ export class Bee { * 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?: Signer | Uint8Array | string): SOCWriter { + makeSOCWriter(signer?: Signer | Uint8Array | string, options?: RequestOptions): SOCWriter { + assertRequestOptions(options) const canonicalSigner = this.resolveSigner(signer) return { - ...this.makeSOCReader(canonicalSigner.address), + ...this.makeSOCReader(canonicalSigner.address, options), - upload: uploadSingleOwnerChunkData.bind(null, this.ky, canonicalSigner), + upload: uploadSingleOwnerChunkData.bind(null, this.getKy(options), canonicalSigner), } } @@ -894,7 +954,7 @@ export class Bee { * * @param amount Amount that represents the value per chunk, has to be greater or equal zero. * @param depth Logarithm of the number of chunks that can be stamped with the batch. - * @param options Options for creation of postage batch + * @param options Options for creation of postage batch and request options * @throws BeeArgumentError when negative amount or depth is specified * @throws TypeError if non-integer value is passed to amount or depth * @@ -903,6 +963,7 @@ export class Bee { * @deprecated Use DebugBee for postage batch management */ async createPostageBatch(amount: NumberString, depth: number, options?: PostageBatchOptions): Promise { + assertPostageBatchOptions(options) assertNonNegativeInteger(amount) assertNonNegativeInteger(depth) @@ -914,15 +975,7 @@ export class Bee { throw new BeeArgumentError(`Depth has to be at most ${STAMPS_DEPTH_MAX}`, depth) } - if (options?.gasPrice) { - assertNonNegativeInteger(options.gasPrice) - } - - if (options?.immutableFlag !== undefined) { - assertBoolean(options.immutableFlag) - } - - return stamps.createPostageBatch(this.ky, amount, depth, options) + return stamps.createPostageBatch(this.getKy(options), amount, depth, options) } /** @@ -931,15 +984,17 @@ export class Bee { * **Warning! Not allowed when node is in Gateway mode!** * * @param postageBatchId Batch ID + * @param options Options that affects the request behavior * * @see [Bee docs - Keep your data alive / Postage stamps](https://docs.ethswarm.org/docs/access-the-swarm/keep-your-data-alive) * @see [Bee API reference - `GET /stamps/${id}`](https://docs.ethswarm.org/api/#tag/Postage-Stamps/paths/~1stamps~1{id}/get) * @deprecated Use DebugBee for postage batch management */ - async getPostageBatch(postageBatchId: BatchId | string): Promise { + async getPostageBatch(postageBatchId: BatchId | string, options?: RequestOptions): Promise { + assertRequestOptions(options, 'PostageBatchOptions') assertBatchId(postageBatchId) - return stamps.getPostageBatch(this.ky, postageBatchId) + return stamps.getPostageBatch(this.getKy(options), postageBatchId) } /** @@ -947,31 +1002,40 @@ export class Bee { * * **Warning! Not allowed when node is in Gateway mode!** * + * @param options Options that affects the request behavior * @see [Bee docs - Keep your data alive / Postage stamps](https://docs.ethswarm.org/docs/access-the-swarm/keep-your-data-alive) * @see [Bee API reference - `GET /stamps`](https://docs.ethswarm.org/api/#tag/Postage-Stamps/paths/~1stamps/get) * @deprecated Use DebugBee for postage batch management */ - async getAllPostageBatch(): Promise { - return stamps.getAllPostageBatches(this.ky) + async getAllPostageBatch(options?: RequestOptions): Promise { + assertRequestOptions(options, 'PostageBatchOptions') + + return stamps.getAllPostageBatches(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 * @throws If connection was not successful throw error */ - async checkConnection(): Promise | never { - return status.checkConnection(this.ky) + async checkConnection(options?: RequestOptions): Promise | never { + 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 */ - async isConnected(): Promise { + async isConnected(options?: RequestOptions): Promise { + assertRequestOptions(options, 'PostageBatchOptions') + try { - await status.checkConnection(this.ky) + await status.checkConnection(this.getKy(options)) } catch (e) { return false } @@ -995,4 +1059,12 @@ export class Bee { throw new BeeError('You have to pass Signer as property to either the method call or constructor! Non found.') } + + private getKy(options?: RequestOptions): Ky { + if (!options) { + return this.ky + } + + return this.ky.extend(options) + } } diff --git a/src/feed/json.ts b/src/feed/json.ts index b1e0c2fc..abe810e1 100644 --- a/src/feed/json.ts +++ b/src/feed/json.ts @@ -1,4 +1,4 @@ -import { FeedWriter, FeedReader, AnyJson, BatchId, Reference } from '../types' +import { FeedWriter, FeedReader, AnyJson, BatchId, Reference, RequestOptions } from '../types' import { Bee } from '../bee' function serializeJson(data: AnyJson): Uint8Array { @@ -24,9 +24,10 @@ export async function setJsonData( writer: FeedWriter, postageBatchId: BatchId, data: AnyJson, + options?: RequestOptions, ): Promise { const serializedData = serializeJson(data) - const { reference } = await bee.uploadData(postageBatchId, serializedData) + const { reference } = await bee.uploadData(postageBatchId, serializedData, options) return writer.upload(postageBatchId, reference) } diff --git a/src/types/debug.ts b/src/types/debug.ts index c44e6885..546f4c4c 100644 --- a/src/types/debug.ts +++ b/src/types/debug.ts @@ -1,4 +1,4 @@ -import { PublicKey, NumberString, Reference, TransactionHash } from './index' +import { PublicKey, NumberString, Reference, TransactionHash, RequestOptions } from './index' import { HexEthAddress } from '../utils/eth' /** @@ -86,7 +86,7 @@ export interface ChequebookBalanceResponse { availableBalance: NumberString } -export interface CashoutOptions { +export interface CashoutOptions extends RequestOptions { /** * Gas price for the cashout transaction in WEI */ diff --git a/src/types/index.ts b/src/types/index.ts index dd33f47a..147e066f 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -72,7 +72,27 @@ export type BatchId = HexString */ export type AddressPrefix = HexString -export interface BeeOptions { +export interface RequestOptions { + /** + * Timeout of requests in milliseconds + */ + timeout?: number + + /** + * Configure backoff mechanism for requests retries. + * Specifies how many retries will be performed before failing a request. + * Retries are performed for GET, PUT, HEAD, DELETE, OPTIONS and TRACE requests. + * Default is 2. + */ + retry?: number + + /** + * User defined Fetch compatible function + */ + fetch?: Fetch +} + +export interface BeeOptions extends RequestOptions { /** * Signer object or private key of the Signer in form of either hex string or Uint8Array that will be default signer for the instance. */ @@ -115,7 +135,7 @@ export interface UploadResult { tagUid?: number } -export interface UploadOptions { +export interface UploadOptions extends RequestOptions { /** * Will pin the data locally in the Bee node as well. * @@ -222,7 +242,7 @@ export interface Tag { startedAt: string } -export interface AllTagsOptions { +export interface AllTagsOptions extends RequestOptions { limit?: number offset?: number } @@ -344,7 +364,7 @@ export interface FeedReader { download(options?: FeedUpdateOptions): Promise } -export interface JsonFeedOptions { +export interface JsonFeedOptions extends RequestOptions { /** * Valid only for `get` action, where either this `address` or `signer` has * to be specified. @@ -464,7 +484,7 @@ export interface TransactionInfo { /** * Options for creation of postage batch */ -export interface PostageBatchOptions { +export interface PostageBatchOptions extends RequestOptions { /** * Sets label for the postage batch */ @@ -542,3 +562,5 @@ interface JsonMap { [key: string]: AnyJson } type JsonArray = Array + +type Fetch = (input: RequestInfo, init?: RequestInit) => Promise diff --git a/src/utils/type.ts b/src/utils/type.ts index 8982267d..3aa7cc2f 100644 --- a/src/utils/type.ts +++ b/src/utils/type.ts @@ -21,6 +21,9 @@ import { PSS_TARGET_HEX_LENGTH_MAX, UploadOptions, TransactionHash, + RequestOptions, + PostageBatchOptions, + CashoutOptions, } from '../types' import { BeeArgumentError } from './error' import { isFile } from './file' @@ -59,16 +62,23 @@ export function isStrictlyObject(value: unknown): value is object { return isObject(value) && !Array.isArray(value) } -export function assertBoolean(value: unknown): asserts value is boolean { - if (value !== true && value !== false) throw new TypeError('value is not boolean') +// eslint-disable-next-line @typescript-eslint/ban-types +export function assertStrictlyObject(value: unknown, name = 'value'): asserts value is object { + if (!isStrictlyObject(value)) { + throw new TypeError(`${name} has to be an object that is not null nor array!`) + } +} + +export function assertBoolean(value: unknown, name = 'value'): asserts value is boolean { + if (value !== true && value !== false) throw new TypeError(`${name} is not boolean`) } -export function assertInteger(value: unknown): asserts value is number | NumberString { - if (!isInteger(value)) throw new TypeError('value is not integer') +export function assertInteger(value: unknown, name = 'value'): asserts value is number | NumberString { + if (!isInteger(value)) throw new TypeError(`${name} is not integer`) } export function assertNonNegativeInteger(value: unknown, name = 'Value'): asserts value is number | NumberString { - assertInteger(value) + assertInteger(value, name) if (Number(value) < 0) throw new BeeArgumentError(`${name} has to be bigger or equal to zero`, value) } @@ -89,11 +99,37 @@ export function assertBatchId(value: unknown): asserts value is BatchId { assertHexString(value, BATCH_ID_HEX_LENGTH, 'BatchId') } +export function assertRequestOptions(value: unknown, name = 'RequestOptions'): asserts value is RequestOptions { + if (value === undefined) { + return + } + + if (!isStrictlyObject(value)) { + throw new TypeError(`${name} has to be an object!`) + } + + const options = value as RequestOptions + + if (options.retry) { + assertNonNegativeInteger(options.retry, `${name}.retry`) + } + + if (options.timeout) { + assertNonNegativeInteger(options.timeout, `${name}.timeout`) + } + + if (options.fetch && typeof options.fetch !== 'function') { + throw new TypeError(`${name}.fetch has to be a function or undefined!`) + } +} + export function assertUploadOptions(value: unknown, name = 'UploadOptions'): asserts value is UploadOptions { if (!isStrictlyObject(value)) { throw new TypeError(`${name} has to be an object!`) } + assertRequestOptions(value, name) + const options = value as UploadOptions if (options.pin && typeof options.pin !== 'boolean') { @@ -220,6 +256,44 @@ export function assertPublicKey(value: unknown): asserts value is PublicKey { assertHexString(value, PUBKEY_HEX_LENGTH, 'PublicKey') } +export function assertPostageBatchOptions(value: unknown): asserts value is PostageBatchOptions { + if (value === undefined) { + return + } + + assertStrictlyObject(value) + + const options = value as PostageBatchOptions + assertRequestOptions(options, 'PostageBatchOptions') + + if (options?.gasPrice) { + assertNonNegativeInteger(options.gasPrice) + } + + if (options?.immutableFlag !== undefined) { + assertBoolean(options.immutableFlag) + } +} + +export function assertCashoutOptions(value: unknown): asserts value is CashoutOptions { + if (value === undefined) { + return + } + + assertStrictlyObject(value) + + const options = value as CashoutOptions + assertRequestOptions(options, 'PostageBatchOptions') + + if (options?.gasLimit) { + assertNonNegativeInteger(options.gasLimit) + } + + if (options?.gasPrice) { + assertNonNegativeInteger(options.gasPrice) + } +} + /** * Check whether the given parameter is valid data to upload * @param value @@ -251,24 +325,26 @@ export function assertAllTagsOptions(entry: unknown): asserts entry is AllTagsOp throw new TypeError('options has to be an object or undefined!') } + assertRequestOptions(entry, 'AllTagsOptions') + const options = entry as AllTagsOptions if (options?.limit !== undefined) { if (typeof options.limit !== 'number') { - throw new TypeError('options.limit has to be a number or undefined!') + throw new TypeError('AllTagsOptions.limit has to be a number or undefined!') } if (options.limit < TAGS_LIMIT_MIN) { - throw new BeeArgumentError(`options.limit has to be at least ${TAGS_LIMIT_MIN}`, options.limit) + throw new BeeArgumentError(`AllTagsOptions.limit has to be at least ${TAGS_LIMIT_MIN}`, options.limit) } if (options.limit > TAGS_LIMIT_MAX) { - throw new BeeArgumentError(`options.limit has to be at most ${TAGS_LIMIT_MAX}`, options.limit) + throw new BeeArgumentError(`AllTagsOptions.limit has to be at most ${TAGS_LIMIT_MAX}`, options.limit) } } if (options?.offset !== undefined) { - assertNonNegativeInteger(options.offset, 'options.offset') + assertNonNegativeInteger(options.offset, 'AllTagsOptions.offset') } } diff --git a/test/unit/assertions.ts b/test/unit/assertions.ts index 1bd49186..e5b2eae9 100644 --- a/test/unit/assertions.ts +++ b/test/unit/assertions.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -import { BeeArgumentError } from '../../src' +import { BeeArgumentError, BeeOptions } from '../../src' import { makeBytes } from '../../src/utils/bytes' export function testBatchIdAssertion(executor: (input: unknown) => void): void { @@ -74,6 +74,101 @@ export function testUploadOptionsAssertions(executor: (input: unknown) => void): }) } +export function testRequestOptionsAssertions( + executor: (input: unknown, beeOptions?: BeeOptions) => void, + testFetch = true, +): void { + it('should throw exception for bad RequestOptions', async () => { + await expect(() => executor(1)).rejects.toThrow(TypeError) + await expect(() => executor(true)).rejects.toThrow(TypeError) + await expect(() => executor([])).rejects.toThrow(TypeError) + await expect(() => executor(() => {})).rejects.toThrow(TypeError) + await expect(() => executor('string')).rejects.toThrow(TypeError) + + await expect(() => executor({ timeout: 'plur' })).rejects.toThrow(TypeError) + await expect(() => executor({ timeout: true })).rejects.toThrow(TypeError) + await expect(() => executor({ timeout: {} })).rejects.toThrow(TypeError) + await expect(() => executor({ timeout: [] })).rejects.toThrow(TypeError) + await expect(() => executor({ timeout: -1 })).rejects.toThrow(BeeArgumentError) + + await expect(() => executor({ retry: 'plur' })).rejects.toThrow(TypeError) + await expect(() => executor({ retry: true })).rejects.toThrow(TypeError) + await expect(() => executor({ retry: {} })).rejects.toThrow(TypeError) + await expect(() => executor({ retry: [] })).rejects.toThrow(TypeError) + await expect(() => executor({ retry: -1 })).rejects.toThrow(BeeArgumentError) + + await expect(() => executor({ fetch: 'plur' })).rejects.toThrow(TypeError) + await expect(() => executor({ fetch: true })).rejects.toThrow(TypeError) + await expect(() => executor({ fetch: {} })).rejects.toThrow(TypeError) + await expect(() => executor({ fetch: [] })).rejects.toThrow(TypeError) + await expect(() => executor({ fetch: -1 })).rejects.toThrow(TypeError) + await expect(() => executor({ fetch: 1 })).rejects.toThrow(TypeError) + }) + + if (testFetch) { + it('should use per-call request options instead of instance request options', async () => { + const instanceFetch = jest.fn() + const instanceMessage = 'instance error' + const instanceError = { message: instanceMessage } + instanceFetch.mockRejectedValue(instanceError) + await expect(() => executor({}, { retry: 0, fetch: instanceFetch })).rejects.toThrow(instanceMessage) + expect(instanceFetch.mock.calls.length).toEqual(1) + + const callFetch = jest.fn() + const callMessage = 'call error' + const callError = { message: callMessage } + callFetch.mockRejectedValue(callError) + await expect(() => executor({ fetch: callFetch }, { retry: 0, fetch: instanceFetch })).rejects.toThrow( + callMessage, + ) + expect(instanceFetch.mock.calls.length).toEqual(1) // The count did not change from last call + expect(callFetch.mock.calls.length).toEqual(1) + }) + } +} + +export function testPostageBatchOptionsAssertions(executor: (input: unknown) => void): void { + it('should throw exception for bad PostageBatch', async () => { + await expect(() => executor(1)).rejects.toThrow(TypeError) + await expect(() => executor(true)).rejects.toThrow(TypeError) + await expect(() => executor([])).rejects.toThrow(TypeError) + await expect(() => executor('string')).rejects.toThrow(TypeError) + + await expect(() => executor({ gasPrice: 'plur' })).rejects.toThrow(TypeError) + await expect(() => executor({ gasPrice: true })).rejects.toThrow(TypeError) + await expect(() => executor({ gasPrice: {} })).rejects.toThrow(TypeError) + await expect(() => executor({ gasPrice: [] })).rejects.toThrow(TypeError) + await expect(() => executor({ gasPrice: -1 })).rejects.toThrow(BeeArgumentError) + + await expect(() => executor({ immutableFlag: 'plur' })).rejects.toThrow(TypeError) + await expect(() => executor({ immutableFlag: 1 })).rejects.toThrow(TypeError) + await expect(() => executor({ immutableFlag: null })).rejects.toThrow(TypeError) + await expect(() => executor({ immutableFlag: {} })).rejects.toThrow(TypeError) + await expect(() => executor({ immutableFlag: [] })).rejects.toThrow(TypeError) + }) +} + +export function testCashoutOptionsAssertions(executor: (input: unknown) => void): void { + it('should throw exception for bad CashoutOptions', async () => { + await expect(() => executor(1)).rejects.toThrow(TypeError) + await expect(() => executor(true)).rejects.toThrow(TypeError) + await expect(() => executor([])).rejects.toThrow(TypeError) + await expect(() => executor('string')).rejects.toThrow(TypeError) + + await expect(() => executor({ gasPrice: 'plur' })).rejects.toThrow(TypeError) + await expect(() => executor({ gasPrice: true })).rejects.toThrow(TypeError) + await expect(() => executor({ gasPrice: {} })).rejects.toThrow(TypeError) + await expect(() => executor({ gasPrice: [] })).rejects.toThrow(TypeError) + await expect(() => executor({ gasPrice: -1 })).rejects.toThrow(BeeArgumentError) + + await expect(() => executor({ gasLimit: 'plur' })).rejects.toThrow(TypeError) + await expect(() => executor({ gasLimit: true })).rejects.toThrow(TypeError) + await expect(() => executor({ gasLimit: {} })).rejects.toThrow(TypeError) + await expect(() => executor({ gasLimit: [] })).rejects.toThrow(TypeError) + await expect(() => executor({ gasLimit: -1 })).rejects.toThrow(BeeArgumentError) + }) +} + export function testFileUploadOptionsAssertions(executor: (input: unknown) => void): void { it('should throw exception for bad FileUploadOptions', async () => { await expect(() => executor({ contentType: true })).rejects.toThrow(TypeError) diff --git a/test/unit/bee-class.spec.ts b/test/unit/bee-class.spec.ts index c4325871..22035eea 100644 --- a/test/unit/bee-class.spec.ts +++ b/test/unit/bee-class.spec.ts @@ -14,8 +14,17 @@ import { PssMessageHandler, ReferenceResponse, UploadOptions, + RequestOptions, + PostageBatchOptions, } from '../../src' -import { testBatchId, testIdentity, testJsonHash, testJsonPayload, testJsonStringPayload } from '../utils' +import { + testBatchId, + testChunkHash, + testIdentity, + testJsonHash, + testJsonPayload, + testJsonStringPayload, +} from '../utils' import { makeTopicFromString } from '../../src/feed/topic' import { testAddressPrefixAssertions, @@ -33,8 +42,11 @@ import { testFeedTopicAssertions, testEthAddressAssertions, testMakeSignerAssertions, + testRequestOptionsAssertions, + testPostageBatchOptionsAssertions, } from './assertions' import { FeedType } from '../../src/feed/type' +import { isStrictlyObject } from '../../src/utils/type' const TOPIC = 'some=very%nice#topic' const HASHED_TOPIC = makeTopicFromString(TOPIC) @@ -89,6 +101,12 @@ describe('Bee class', () => { return bee.uploadData(input as BatchId, '') }) + testRequestOptionsAssertions(async (input, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.uploadData(testBatchId, '', input as RequestOptions) + }) + testDataAssertions(async (input: unknown) => { const bee = new Bee(MOCK_SERVER_URL) @@ -108,6 +126,12 @@ describe('Bee class', () => { return bee.downloadData(input as string) }) + + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.downloadData(testChunkHash, input as RequestOptions) + }) }) describe('downloadReadableData', () => { @@ -116,6 +140,12 @@ describe('Bee class', () => { return bee.downloadReadableData(input as string) }) + + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.downloadReadableData(testChunkHash, input as RequestOptions) + }) }) describe('uploadFile', () => { @@ -125,6 +155,12 @@ describe('Bee class', () => { return bee.uploadFile(input as BatchId, '') }) + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.uploadFile(testBatchId, '', undefined, input as RequestOptions) + }) + testFileDataAssertions(async (input: unknown) => { const bee = new Bee(MOCK_SERVER_URL) @@ -150,6 +186,12 @@ describe('Bee class', () => { return bee.downloadFile(input as string) }) + + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.downloadFile(testChunkHash, '', input as RequestOptions) + }) }) describe('downloadReadableFile', () => { @@ -158,6 +200,12 @@ describe('Bee class', () => { return bee.downloadReadableFile(input as string) }) + + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.downloadReadableFile(testChunkHash, '', input as RequestOptions) + }) }) describe('uploadFiles', () => { @@ -181,6 +229,12 @@ describe('Bee class', () => { return bee.uploadFiles(testBatchId, files, input as UploadOptions) }) + + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.uploadFiles(testBatchId, files, input as RequestOptions) + }) }) describe('uploadFilesFromDirectory', () => { @@ -202,6 +256,12 @@ describe('Bee class', () => { return bee.uploadFilesFromDirectory(testBatchId, 'some path', input as CollectionUploadOptions) }) + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.uploadFilesFromDirectory(testBatchId, './test/data', input as RequestOptions) + }) + it('should throw exception for bad Dir', async () => { const bee = new Bee(MOCK_SERVER_URL) @@ -222,6 +282,12 @@ describe('Bee class', () => { }) describe('retrieveTag', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.retrieveTag(0, input as RequestOptions) + }) + it('should throw exception for bad Tag', async () => { const bee = new Bee(MOCK_SERVER_URL) @@ -250,6 +316,12 @@ describe('Bee class', () => { }) describe('deleteTag', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.deleteTag(0, input as RequestOptions) + }) + it('should throw exception for bad Tag', async () => { const bee = new Bee(MOCK_SERVER_URL) @@ -278,6 +350,12 @@ describe('Bee class', () => { }) describe('getAllTags', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.getAllTags(input as RequestOptions) + }) + it('should throw exception for bad options', async () => { const bee = new Bee(MOCK_SERVER_URL) @@ -330,6 +408,12 @@ describe('Bee class', () => { }) describe('pin', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.pin(testChunkHash, input as RequestOptions) + }) + testReferenceAssertions(async (input: unknown) => { const bee = new Bee(MOCK_SERVER_URL) @@ -338,6 +422,11 @@ describe('Bee class', () => { }) describe('unpin', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.unpin(testChunkHash, input as RequestOptions) + }) testReferenceAssertions(async (input: unknown) => { const bee = new Bee(MOCK_SERVER_URL) @@ -346,6 +435,11 @@ describe('Bee class', () => { }) describe('getPin', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.getPin(testChunkHash, input as RequestOptions) + }) testReferenceAssertions(async (input: unknown) => { const bee = new Bee(MOCK_SERVER_URL) @@ -354,6 +448,12 @@ describe('Bee class', () => { }) describe('reuploadPinnedData', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.reuploadPinnedData(testChunkHash, input as RequestOptions) + }) + testReferenceAssertions(async (input: unknown) => { const bee = new Bee(MOCK_SERVER_URL) @@ -362,6 +462,12 @@ describe('Bee class', () => { }) describe('pssSend', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.pssSend(testBatchId, 'topic', '123', 'data', '', input as RequestOptions) + }) + testBatchIdAssertion(async (input: unknown) => { const bee = new Bee(MOCK_SERVER_URL) @@ -435,6 +541,12 @@ describe('Bee class', () => { }) describe('createFeedManifest', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.createFeedManifest(testBatchId, 'epoch', testChunkHash, testIdentity.address, input as RequestOptions) + }) + testBatchIdAssertion(async (input: unknown) => { const bee = new Bee(MOCK_SERVER_URL) @@ -461,6 +573,12 @@ describe('Bee class', () => { }) describe('makeFeedReader', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.makeFeedReader('epoch', testChunkHash, testIdentity.address, input as RequestOptions) + }, false) + testFeedTypeAssertions(async (input: unknown) => { const bee = new Bee(MOCK_SERVER_URL) @@ -481,6 +599,12 @@ describe('Bee class', () => { }) describe('makeFeedWriter', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.makeFeedWriter('epoch', testChunkHash, testIdentity.address, input as RequestOptions) + }, false) + testFeedTypeAssertions(async (input: unknown) => { const bee = new Bee(MOCK_SERVER_URL) @@ -501,6 +625,23 @@ describe('Bee class', () => { }) describe('setJsonFeed', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + let opts + + if (isStrictlyObject(input)) { + opts = { + signer: testIdentity.privateKey, + ...input, + } + } else { + opts = input + } + + return bee.setJsonFeed(testBatchId, 'epoch', '123', opts as RequestOptions) + }) + testBatchIdAssertion(async (input: unknown) => { const bee = new Bee(MOCK_SERVER_URL) @@ -527,6 +668,23 @@ describe('Bee class', () => { }) describe('getJsonFeed', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + let opts + + if (isStrictlyObject(input)) { + opts = { + signer: testIdentity.privateKey, + ...input, + } + } else { + opts = input + } + + return bee.getJsonFeed(TOPIC, opts as RequestOptions) + }) + it('should fetch with specified address', async () => { downloadDataMock(testJsonHash).reply(200, testJsonStringPayload) fetchFeedUpdateMock(testIdentity.address, HASHED_TOPIC).reply(200, { @@ -614,6 +772,12 @@ describe('Bee class', () => { }) describe('makeSOCReader', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.makeSOCReader(testIdentity.privateKey, input as RequestOptions) + }, false) + testEthAddressAssertions(async (input: unknown) => { const bee = new Bee(MOCK_SERVER_URL) @@ -622,6 +786,12 @@ describe('Bee class', () => { }) describe('makeSOCWriter', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new Bee(MOCK_SERVER_URL, beeOptions) + + return bee.makeSOCWriter(testIdentity.privateKey, input as RequestOptions) + }, false) + testMakeSignerAssertions(async (input: unknown) => { const bee = new Bee(MOCK_SERVER_URL) @@ -635,6 +805,12 @@ describe('Bee class', () => { batchID: BATCH_ID, } + testPostageBatchOptionsAssertions(async (input: unknown) => { + const bee = new Bee(MOCK_SERVER_URL) + + return bee.createPostageBatch('10', 17, input as PostageBatchOptions) + }) + it('should not pass headers if no gas price is specified', async () => { createPostageBatchMock('10', '17').reply(201, BATCH_RESPONSE) diff --git a/test/unit/bee-debug-class.spec.ts b/test/unit/bee-debug-class.spec.ts index 5f1e38cb..4545a338 100644 --- a/test/unit/bee-debug-class.spec.ts +++ b/test/unit/bee-debug-class.spec.ts @@ -6,9 +6,15 @@ import { MOCK_SERVER_URL, withdrawTokensMock, } from './nock' -import { BatchId, BeeArgumentError, BeeDebug } from '../../src' -import { testAddress } from '../utils' -import { testAddressAssertions, testBatchIdAssertion } from './assertions' +import { BatchId, BeeArgumentError, BeeDebug, CashoutOptions, PostageBatchOptions, RequestOptions } from '../../src' +import { testAddress, testBatchId } from '../utils' +import { + testAddressAssertions, + testBatchIdAssertion, + testCashoutOptionsAssertions, + testPostageBatchOptionsAssertions, + testRequestOptionsAssertions, +} from './assertions' const TRANSACTION_HASH = '36b7efd913ca4cf880b8eeac5093fa27b0825906c600685b6abdd6566e6cfe8f' const CASHOUT_RESPONSE = { @@ -53,6 +59,12 @@ describe('BeeDebug class', () => { }) describe('removePeer', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new BeeDebug(MOCK_SERVER_URL, beeOptions) + + return bee.removePeer(testAddress, input as RequestOptions) + }) + testAddressAssertions(async (input: unknown) => { const bee = new BeeDebug(MOCK_SERVER_URL) @@ -61,6 +73,12 @@ describe('BeeDebug class', () => { }) describe('pingPeer', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new BeeDebug(MOCK_SERVER_URL, beeOptions) + + return bee.pingPeer(testAddress, input as RequestOptions) + }) + testAddressAssertions(async (input: unknown) => { const bee = new BeeDebug(MOCK_SERVER_URL) @@ -69,6 +87,12 @@ describe('BeeDebug class', () => { }) describe('getPeerBalance', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new BeeDebug(MOCK_SERVER_URL, beeOptions) + + return bee.getPeerBalance(testAddress, input as RequestOptions) + }) + testAddressAssertions(async (input: unknown) => { const bee = new BeeDebug(MOCK_SERVER_URL) @@ -77,6 +101,12 @@ describe('BeeDebug class', () => { }) describe('getPastDueConsumptionPeerBalance', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new BeeDebug(MOCK_SERVER_URL, beeOptions) + + return bee.getPastDueConsumptionPeerBalance(testAddress, input as RequestOptions) + }) + testAddressAssertions(async (input: unknown) => { const bee = new BeeDebug(MOCK_SERVER_URL) @@ -85,6 +115,12 @@ describe('BeeDebug class', () => { }) describe('getLastChequesForPeer', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new BeeDebug(MOCK_SERVER_URL, beeOptions) + + return bee.getLastChequesForPeer(testAddress, input as RequestOptions) + }) + testAddressAssertions(async (input: unknown) => { const bee = new BeeDebug(MOCK_SERVER_URL) @@ -93,6 +129,12 @@ describe('BeeDebug class', () => { }) describe('getLastCashoutAction', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new BeeDebug(MOCK_SERVER_URL, beeOptions) + + return bee.getLastCashoutAction(testAddress, input as RequestOptions) + }) + testAddressAssertions(async (input: unknown) => { const bee = new BeeDebug(MOCK_SERVER_URL) @@ -101,6 +143,12 @@ describe('BeeDebug class', () => { }) describe('getSettlements', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new BeeDebug(MOCK_SERVER_URL, beeOptions) + + return bee.getSettlements(testAddress, input as RequestOptions) + }) + testAddressAssertions(async (input: unknown) => { const bee = new BeeDebug(MOCK_SERVER_URL) @@ -109,6 +157,18 @@ describe('BeeDebug class', () => { }) describe('cashoutLastCheque', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new BeeDebug(MOCK_SERVER_URL, beeOptions) + + return bee.cashoutLastCheque(testAddress, input as RequestOptions) + }) + + testCashoutOptionsAssertions(async (input: unknown) => { + const bee = new BeeDebug(MOCK_SERVER_URL) + + return bee.cashoutLastCheque('', input as CashoutOptions) + }) + it('should not pass headers if no gas price is specified', async () => { cashoutLastChequeMock(testAddress).reply(201, CASHOUT_RESPONSE) @@ -138,28 +198,6 @@ describe('BeeDebug class', () => { return bee.cashoutLastCheque(input as string) }) - - it('should throw error if passed wrong gas price input', async () => { - const bee = new BeeDebug(MOCK_SERVER_URL) - - // @ts-ignore: Input testing - await expect(bee.cashoutLastCheque(testAddress, { gasPrice: 'asd' })).rejects.toThrow(TypeError) - - // @ts-ignore: Input testing - await expect(bee.cashoutLastCheque(testAddress, { gasPrice: true })).rejects.toThrow(TypeError) - await expect(bee.cashoutLastCheque(testAddress, { gasPrice: '-1' })).rejects.toThrow(BeeArgumentError) - }) - - it('should throw error if passed wrong gas limit input', async () => { - const bee = new BeeDebug(MOCK_SERVER_URL) - - // @ts-ignore: Input testing - await expect(bee.cashoutLastCheque(testAddress, { gasLimit: 'asd' })).rejects.toThrow(TypeError) - - // @ts-ignore: Input testing - await expect(bee.cashoutLastCheque(testAddress, { gasLimit: true })).rejects.toThrow(TypeError) - await expect(bee.cashoutLastCheque(testAddress, { gasLimit: '-1' })).rejects.toThrow(BeeArgumentError) - }) }) describe('withdrawTokens', () => { @@ -168,6 +206,12 @@ describe('BeeDebug class', () => { transactionHash: TRANSACTION_HASH, } + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new BeeDebug(MOCK_SERVER_URL, beeOptions) + + return bee.withdrawTokens('1', '0', input as RequestOptions) + }) + it('should not pass headers if no gas price is specified', async () => { withdrawTokensMock('10').reply(201, CASHOUT_RESPONSE) @@ -217,6 +261,12 @@ describe('BeeDebug class', () => { transactionHash: TRANSACTION_HASH, } + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new BeeDebug(MOCK_SERVER_URL, beeOptions) + + return bee.depositTokens('1', '0', input as RequestOptions) + }) + it('should not pass headers if no gas price is specified', async () => { depositTokensMock('10').reply(201, CASHOUT_RESPONSE) @@ -261,6 +311,12 @@ describe('BeeDebug class', () => { }) describe('retrieveExtendedTag', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new BeeDebug(MOCK_SERVER_URL, beeOptions) + + return bee.retrieveExtendedTag(0, input as RequestOptions) + }) + it('should throw exception for bad Tag', async () => { const bee = new BeeDebug(MOCK_SERVER_URL) @@ -294,6 +350,18 @@ describe('BeeDebug class', () => { batchID: BATCH_ID, } + testPostageBatchOptionsAssertions(async (input: unknown) => { + const bee = new BeeDebug(MOCK_SERVER_URL) + + return bee.createPostageBatch('10', 17, input as PostageBatchOptions) + }) + + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new BeeDebug(MOCK_SERVER_URL, beeOptions) + + return bee.createPostageBatch('10', 17, input as RequestOptions) + }) + it('should not pass headers if no gas price is specified', async () => { createPostageBatchMock('10', '17').reply(201, BATCH_RESPONSE) @@ -310,25 +378,6 @@ describe('BeeDebug class', () => { assertAllIsDone() }) - it('should pass headers if immutable flag is specified', async () => { - createPostageBatchMock('10', '17', undefined, undefined, 'true').reply(201, BATCH_RESPONSE) - - const bee = new BeeDebug(MOCK_SERVER_URL) - await expect(bee.createPostageBatch('10', 17, { immutableFlag: true })).resolves.toEqual(BATCH_ID) - assertAllIsDone() - }) - - it('should throw error if passed wrong gas price input', async () => { - const bee = new BeeDebug(MOCK_SERVER_URL) - - // @ts-ignore: Input testing - await expect(bee.createPostageBatch('10', 17, { gasPrice: 'asd' })).rejects.toThrow(TypeError) - - // @ts-ignore: Input testing - await expect(bee.createPostageBatch('10', 17, { gasPrice: true })).rejects.toThrow(TypeError) - await expect(bee.createPostageBatch('10', 17, { gasPrice: '-1' })).rejects.toThrow(BeeArgumentError) - }) - it('should throw error if passed wrong immutable input', async () => { const bee = new BeeDebug(MOCK_SERVER_URL) @@ -357,6 +406,12 @@ describe('BeeDebug class', () => { }) describe('getPostageBatch', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new BeeDebug(MOCK_SERVER_URL, beeOptions) + + return bee.getPostageBatch(testBatchId, input as RequestOptions) + }) + testBatchIdAssertion(async (input: unknown) => { const bee = new BeeDebug(MOCK_SERVER_URL) @@ -365,6 +420,12 @@ describe('BeeDebug class', () => { }) describe('getPostageBatchBuckets', () => { + testRequestOptionsAssertions(async (input: unknown, beeOptions) => { + const bee = new BeeDebug(MOCK_SERVER_URL, beeOptions) + + return bee.getPostageBatchBuckets(testBatchId, input as RequestOptions) + }) + testBatchIdAssertion(async (input: unknown) => { const bee = new BeeDebug(MOCK_SERVER_URL)