import { construct, verify_proof } from 'mrklt';
import '../common/abstract-api-provider.js';
import AbstractBaseModule from '../common/abstract-base-module.js';
import '../../../utils/types/array.js';
import 'crypto';
import { withExtendedPrototypeProperties } from '../../../utils/inheritance.js';
import 'bs58';
import 'multiformats/bases/base58';
import 'varint';
import '../../../utils/encoding/ss-58.js';
import { Anchor } from '../../../types/anchor/index.js';
import '../../../utils/types/object.js';
import '../../../utils/types/iterable.js';
import '../../../utils/types/set.js';
import 'blake2b';
import '../../../utils/types/bytes.js';
import '../../../utils/interfaces.js';
import '../../../utils/assert.js';
import '../../../utils/error.js';
import '../../../utils/types/string.js';
import '../../../types/generic/typed-enum.js';
import '../../../types/generic/with-base.js';
import '../../../types/generic/with-catch-null.js';
import '../../../types/generic/with-eq.js';
import '../../../types/generic/any-of.js';
import '../../../types/generic/with-from.js';
import '../../../types/generic/with-from-json-bytes.js';
import '../../../types/generic/typed-null.js';
import '../../../types/generic/create-placeholder.js';
import '../../../types/generic/typed-bytes.js';
import '../../../types/generic/typed-string.js';
import '../../../types/generic/typed-array.js';
import '../../../types/generic/typed-tuple.js';
import '../../../types/generic/sized.js';
import '../../../utils/types/number.js';
import '../../../types/generic/typed-number.js';
import '../../../types/generic/typed-set.js';
import '../../../types/generic/typed-map.js';
import '../../../types/generic/typed-struct.js';
import 'uuid';
import 'js-sha256';

/* eslint-disable camelcase */

/** Class to create and query anchors from chain. */
class AbstractAnchorModule extends AbstractBaseModule {
  /**
   * Write anchor on chain
   * @param anchor
   * @returns {Promise<*>}
   */
  async deploy(anchor, params) {
    return await this.signAndSend(await this.deployTx(anchor), params);
  }

  /**
   * Query anchor from chain
   * @param {AnchorHash} anchor
   * @param {boolean} preHashed - If the anchor has already been hashed.
   * @returns {Promise<Anchor>} - The promise will either successfully resolve to the block number where anchor was created
   * or reject with an error.
   */
  async get(_anchorKey, _preHashed = false) {
    throw new Error('Unimplemented');
  }

  /**
   * Batch multiple documents in binary merkle tree and return the root and proofs for each document
   * @param documents
   * @returns {Array} - An 2 element array where 1st element is root and 2nd is an array with proofs for
   * each document.
   */
  static batchDocumentsInMerkleTree(documents) {
    // Hash all documents
    const leafHashes = documents.map((doc) => Anchor.hash(doc).bytes);

    // If only one document was hashed, just return that as the root with no proofs (single anchor)
    if (leafHashes.length === 1) {
      return [leafHashes[0], []];
    }

    // Concatenate all leaf hashes into one bytearray
    const packed = new Uint8Array(leafHashes.map((a) => [...a]).flat());
    const [root, proofs] = construct(packed);
    return [Uint8Array.from(root), proofs, leafHashes];
  }

  /**
   * Verify inclusion proof of document in a merkle tree with given root. The document is hashed to form a leaf first
   * @param document
   * @param proof
   * @param root
   * @returns {boolean}
   */
  static verifyMerkleProofOfDocument(document, proof, root) {
    const hash = Anchor.hash(document).bytes;
    return this.verifyMerkleProofOfLeaf(hash, proof, root);
  }

  /**
   * Verify inclusion proof of leaf in a merkle tree with given root.
   * @param leaf
   * @param proof
   * @param root
   * @returns {boolean}
   */
  static verifyMerkleProofOfLeaf(leaf, proof, root) {
    /* eslint-disable camelcase */
    const calculatedRoot = verify_proof(leaf, proof);
    return (
      calculatedRoot.length === root.length
      && calculatedRoot.every((v, i) => v === root[i])
    );
  }
}

var AbstractAnchorModule$1 = withExtendedPrototypeProperties(
  ['deployTx', 'get'],
  AbstractAnchorModule,
);

export { AbstractAnchorModule$1 as default };
//# sourceMappingURL=module.js.map
