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());
  });
};

import * as connectivity from "./modules/debug/connectivity.js";
import * as balance from "./modules/debug/balance.js";
import * as chequebook from "./modules/debug/chequebook.js";
import * as settlements from "./modules/debug/settlements.js";
import * as status from "./modules/debug/status.js";
import * as transactions from "./modules/debug/transactions.js";
import * as states from "./modules/debug/states.js";
import { BeeArgumentError, BeeError } from "./utils/error.js";
import { assertBeeUrl, stripLastSlash } from "./utils/url.js";
import { assertAddress, assertBatchId, assertCashoutOptions, assertNonNegativeInteger, assertPositiveInteger, assertPostageBatchOptions, assertRequestOptions, assertTransactionHash, isTag } from "./utils/type.js";
import { STAMPS_DEPTH_MAX, STAMPS_DEPTH_MIN } from "./types/index.js";
import * as tag from "./modules/debug/tag.js";
import * as stamps from "./modules/debug/stamps.js";
import { makeDefaultKy, wrapRequestClosure, wrapResponseClosure } from "./utils/http.js";
import { sleep } from "./utils/sleep.js";
export class BeeDebug {
  constructor(url, options) {
    var _a;

    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 = stripLastSlash(url);
    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(wrapRequestClosure(options.onRequest));
    }

    if (options === null || options === void 0 ? void 0 : options.onResponse) {
      kyOptions.hooks.afterResponse.push(wrapResponseClosure(options.onResponse));
    }

    this.ky = makeDefaultKy(kyOptions);
  }

  getNodeAddresses(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return connectivity.getNodeAddresses(this.getKy(options));
    });
  }

  getBlocklist(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return connectivity.getBlocklist(this.getKy(options));
    });
  }
  /**
   * Retrieve tag extended information from Bee node
   *
   * @param tagUid UID or tag object to be retrieved
   * @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/debug-api/#tag/Tag)
   *
   */


  retrieveExtendedTag(tagUid, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);

      if (isTag(tagUid)) {
        tagUid = tagUid.uid;
      } else if (typeof tagUid === 'number') {
        assertNonNegativeInteger(tagUid, 'UID');
      } else {
        throw new TypeError('tagUid has to be either Tag or a number (UID)!');
      }

      return tag.retrieveExtendedTag(this.getKy(options), tagUid);
    });
  }
  /**
   * Get list of peers for this node
   */


  getPeers(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return connectivity.getPeers(this.getKy(options));
    });
  }

  removePeer(peer, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertAddress(peer);
      return connectivity.removePeer(this.getKy(options), peer);
    });
  }

  getTopology(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return connectivity.getTopology(this.getKy(options));
    });
  }

  pingPeer(peer, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertAddress(peer);
      return connectivity.pingPeer(this.getKy(options), peer);
    });
  }
  /*
   * Balance endpoints
   */

  /**
   * Get the balances with all known peers including prepaid services
   */


  getAllBalances(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return balance.getAllBalances(this.getKy(options));
    });
  }
  /**
   * Get the balances with a specific peer including prepaid services
   *
   * @param address Swarm address of peer
   */


  getPeerBalance(address, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertAddress(address);
      return balance.getPeerBalance(this.getKy(options), address);
    });
  }
  /**
   * Get the past due consumption balances with all known peers
   */


  getPastDueConsumptionBalances(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return balance.getPastDueConsumptionBalances(this.getKy(options));
    });
  }
  /**
   * Get the past due consumption balance with a specific peer
   *
   * @param address Swarm address of peer
   */


  getPastDueConsumptionPeerBalance(address, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertAddress(address);
      return balance.getPastDueConsumptionPeerBalance(this.getKy(options), address);
    });
  }
  /*
   * Chequebook endpoints
   */

  /**
   * Get the address of the chequebook contract used.
   *
   * **Warning:** The address is returned with 0x prefix unlike all other calls.
   * https://github.com/ethersphere/bee/issues/1443
   */


  getChequebookAddress(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return chequebook.getChequebookAddress(this.getKy(options));
    });
  }
  /**
   * Get the balance of the chequebook
   */


  getChequebookBalance(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return chequebook.getChequebookBalance(this.getKy(options));
    });
  }
  /**
   * Get last cheques for all peers
   */


  getLastCheques(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return chequebook.getLastCheques(this.getKy(options));
    });
  }
  /**
   * Get last cheques for the peer
   *
   * @param address  Swarm address of peer
   */


  getLastChequesForPeer(address, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertAddress(address);
      return chequebook.getLastChequesForPeer(this.getKy(options), address);
    });
  }
  /**
   * Get last cashout action for the peer
   *
   * @param address  Swarm address of peer
   */


  getLastCashoutAction(address, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertAddress(address);
      return chequebook.getLastCashoutAction(this.getKy(options), address);
    });
  }
  /**
   * Cashout the last cheque for the peer
   *
   * @param address  Swarm address of peer
   * @param options
   * @param options.gasPrice Gas price for the cashout transaction in WEI
   * @param options.gasLimit Gas limit for the cashout transaction in WEI
   */


  cashoutLastCheque(address, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertCashoutOptions(options);
      assertAddress(address);
      return chequebook.cashoutLastCheque(this.getKy(options), address, options);
    });
  }
  /**
   * Deposit tokens from overlay address into chequebook
   *
   * @param amount  Amount of tokens to deposit (must be positive integer)
   * @param gasPrice Gas Price in WEI for the transaction call
   * @return string  Hash of the transaction
   */


  depositTokens(amount, gasPrice, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertNonNegativeInteger(amount);

      if (gasPrice) {
        assertNonNegativeInteger(gasPrice);
      }

      return chequebook.depositTokens(this.getKy(options), amount, gasPrice);
    });
  }
  /**
   * Withdraw tokens from the chequebook to the overlay address
   *
   * @param amount  Amount of tokens to withdraw (must be positive integer)
   * @param gasPrice Gas Price in WEI for the transaction call
   * @return string  Hash of the transaction
   */


  withdrawTokens(amount, gasPrice, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertNonNegativeInteger(amount);

      if (gasPrice) {
        assertNonNegativeInteger(gasPrice);
      }

      return chequebook.withdrawTokens(this.getKy(options), amount, gasPrice);
    });
  }
  /*
   * Settlements endpoint
   */

  /**
   * Get amount of sent and received from settlements with a peer
   *
   * @param address  Swarm address of peer
   */


  getSettlements(address, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertAddress(address);
      return settlements.getSettlements(this.getKy(options), address);
    });
  }
  /**
   * Get settlements with all known peers and total amount sent or received
   */


  getAllSettlements(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return settlements.getAllSettlements(this.getKy(options));
    });
  }
  /**
   * Get health of node
   */


  getHealth(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return status.getHealth(this.getKy(options));
    });
  }
  /**
   * Get mode information of node
   */


  getNodeInfo(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return status.getNodeInfo(this.getKy(options));
    });
  }
  /**
   * Connnects to a node and checks if it is a supported Bee version by the bee-js
   *
   * @returns true if the Bee node version is supported
   * @deprecated Use `BeeDebug.isSupportedExactVersion()` instead
   */


  isSupportedVersion(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return status.isSupportedVersion(this.getKy(options));
    });
  }
  /**
   * Connects to a node and checks if its version matches with the one that bee-js supports.
   *
   * Be aware that this is the most strict version check and most probably
   * you will want to use more relaxed API-versions based checks like
   * `BeeDebug.isSupportedApiVersion()`, `BeeDebug.isSupportedMainApiVersion()` or `BeeDebug.isSupportedDebugApiVersion()`
   * based on your use-case.
   *
   * @param options
   */


  isSupportedExactVersion(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return status.isSupportedExactVersion(this.getKy(options));
    });
  }
  /**
   * Connects to a node and checks if its main's API version matches with the one that bee-js supports.
   *
   * This is useful if you are not using `BeeDebug` class (for anything else then this check)
   * and want to make sure about compatibility.
   *
   * @param options
   */


  isSupportedMainApiVersion(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return status.isSupportedMainApiVersion(this.getKy(options));
    });
  }
  /**
   * Connects to a node and checks if its Debug API version matches with the one that bee-js supports.
   *
   * This is useful if you are not using `Bee` class in your application and want to make sure
   * about compatibility.
   *
   * @param options
   */


  isSupportedDebugApiVersion(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return status.isSupportedDebugApiVersion(this.getKy(options));
    });
  }
  /**
   *
   * Connects to a node and checks if its Main and Debug API versions matches with the one that bee-js supports.
   *
   * This should be the main way how to check compatibility for your app and Bee node.
   *
   * @param options
   */


  isSupportedApiVersion(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return status.isSupportedDebugApiVersion(this.getKy(options));
    });
  }
  /**
   * Returns object with all versions specified by the connected Bee node (properties prefixed with `bee*`)
   * and versions that bee-js supports (properties prefixed with `supported*`).
   *
   * @param options
   */


  getVersions(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return status.getVersions(this.getKy(options));
    });
  }
  /**
   * Get reserve state
   */


  getReserveState(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return states.getReserveState(this.getKy(options));
    });
  }
  /**
   * Get chain state
   */


  getChainState(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return states.getChainState(this.getKy(options));
    });
  }
  /**
   * Get wallet balances for xDai and BZZ of the Bee node
   *
   * @param options
   */


  getWalletBalance(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return states.getWalletBalance(this.getKy(options));
    });
  }
  /**
   * Creates new postage batch from the funds that the node has available in its Ethereum account.
   *
   * For better understanding what each parameter means and what are the optimal values please see
   * [Bee docs - Keep your data alive / Postage stamps](https://docs.ethswarm.org/docs/access-the-swarm/keep-your-data-alive).
   *
   * **WARNING: THIS CREATES TRANSACTIONS THAT SPENDS MONEY**
   *
   * @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
   * @throws BeeArgumentError when negative amount or depth is specified
   * @throws TypeError if non-integer value is passed to amount or depth
   *
   * @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 - `POST /stamps`](https://docs.ethswarm.org/debug-api/#tag/Postage-Stamps/paths/~1stamps~1{amount}~1{depth}/post)
   */


  createPostageBatch(amount, depth, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertPostageBatchOptions(options);
      assertPositiveInteger(amount);
      assertNonNegativeInteger(depth);

      if (depth < STAMPS_DEPTH_MIN) {
        throw new BeeArgumentError(`Depth has to be at least ${STAMPS_DEPTH_MIN}`, depth);
      }

      if (depth > STAMPS_DEPTH_MAX) {
        throw new BeeArgumentError(`Depth has to be at most ${STAMPS_DEPTH_MAX}`, depth);
      }

      const stamp = yield stamps.createPostageBatch(this.getKy(options), amount, depth, options);

      if (options === null || options === void 0 ? void 0 : options.waitForUsable) {
        yield this.waitForUsablePostageStamp(stamp, options === null || options === void 0 ? void 0 : options.waitForUsableTimeout);
      }

      return stamp;
    });
  }
  /**
   * Topup a fresh amount of BZZ to given Postage Batch.
   *
   * For better understanding what each parameter means and what are the optimal values please see
   * [Bee docs - Keep your data alive / Postage stamps](https://docs.ethswarm.org/docs/access-the-swarm/keep-your-data-alive).
   *
   * **WARNING: THIS CREATES TRANSACTIONS THAT SPENDS MONEY**
   *
   * @param postageBatchId Batch ID
   * @param amount Amount to be added to the batch
   * @param options 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 Debug API reference - `PATCH /stamps/topup/${id}/${amount}`](https://docs.ethswarm.org/debug-api/#tag/Postage-Stamps/paths/~1stamps~1topup~1{id}~1{amount}/patch)
   */


  topUpBatch(postageBatchId, amount, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertNonNegativeInteger(amount, 'Amount');
      assertBatchId(postageBatchId);
      yield stamps.topUpBatch(this.getKy(options), postageBatchId, amount);
    });
  }
  /**
   * Dilute given Postage Batch with new depth (that has to be bigger then the original depth), which allows
   * the Postage Batch to be used for more chunks.
   *
   * For better understanding what each parameter means and what are the optimal values please see
   * [Bee docs - Keep your data alive / Postage stamps](https://docs.ethswarm.org/docs/access-the-swarm/keep-your-data-alive).
   *
   * **WARNING: THIS CREATES TRANSACTIONS THAT SPENDS MONEY**
   *
   * @param postageBatchId Batch ID
   * @param depth Amount to be added to the batch
   * @param options 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 Debug API reference - `PATCH /stamps/topup/${id}/${amount}`](https://docs.ethswarm.org/debug-api/#tag/Postage-Stamps/paths/~1stamps~1topup~1{id}~1{amount}/patch)
   */


  diluteBatch(postageBatchId, depth, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertNonNegativeInteger(depth, 'Depth');
      assertBatchId(postageBatchId);
      yield stamps.diluteBatch(this.getKy(options), postageBatchId, depth);
    });
  }
  /**
   * Return details for specific postage batch.
   *
   * @param postageBatchId Batch ID
   *
   * @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)
   */


  getPostageBatch(postageBatchId, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertBatchId(postageBatchId);
      return stamps.getPostageBatch(this.getKy(options), postageBatchId);
    });
  }
  /**
   * Return detailed information related to buckets for specific postage batch.
   *
   * @param postageBatchId Batch ID
   *
   * @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)
   */


  getPostageBatchBuckets(postageBatchId, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertBatchId(postageBatchId);
      return stamps.getPostageBatchBuckets(this.getKy(options), postageBatchId);
    });
  }
  /**
   * Return all postage batches that has the node available.
   *
   * @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)
   */


  getAllPostageBatch(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return stamps.getAllPostageBatches(this.getKy(options));
    });
  }
  /**
   * Return lists of all current pending transactions that the Bee made
   */


  getAllPendingTransactions(options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      return transactions.getAllTransactions(this.getKy(options));
    });
  }
  /**
   * Return transaction information for specific transaction
   * @param transactionHash
   */


  getPendingTransaction(transactionHash, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertTransactionHash(transactionHash);
      return transactions.getTransaction(this.getKy(options), transactionHash);
    });
  }
  /**
   * Rebroadcast already created transaction.
   * This is mainly needed when your transaction fall off mempool from other reason is not incorporated into block.
   *
   * @param transactionHash
   */


  rebroadcastPendingTransaction(transactionHash, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertTransactionHash(transactionHash);
      return transactions.rebroadcastTransaction(this.getKy(options), transactionHash);
    });
  }
  /**
   * Cancel currently pending transaction
   * @param transactionHash
   * @param gasPrice
   */


  cancelPendingTransaction(transactionHash, gasPrice, options) {
    return __awaiter(this, void 0, void 0, function* () {
      assertRequestOptions(options);
      assertTransactionHash(transactionHash);

      if (gasPrice) {
        assertNonNegativeInteger(gasPrice);
      }

      return transactions.cancelTransaction(this.getKy(options), transactionHash, gasPrice);
    });
  }

  waitForUsablePostageStamp(id, timeout = 120000) {
    return __awaiter(this, void 0, void 0, function* () {
      const TIME_STEP = 1500;

      for (let time = 0; time < timeout; time += TIME_STEP) {
        const stamp = yield this.getPostageBatch(id);

        if (stamp.usable) {
          return;
        }

        yield sleep(TIME_STEP);
      }

      throw new BeeError('Timeout on waiting for postage stamp to become usable');
    });
  }

  getKy(options) {
    if (!options) {
      return this.ky;
    }

    return this.ky.extend(options);
  }

}