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 { createClient } from "../blockchainClient/blockchainClient";
import { calculateBlockRID, fetchAndVerifyTransaction, getAnchoringTransactionForBlockRid, getClusterInfo, getClusterOfBlockchain, } from "./utils";
import { toString, toBuffer } from "../formatter";
/**
 * Creates an ICCF (Inter-Chain Communication Framework) proof transaction.
 * This function generates a proof that a specific transaction has occurred on the source blockchain
 * and constructs an ICCF proof transaction that can be posted to the target blockchain.
 *
 * @param {IClient} client - The client configured to communicate with the management chain.
 * @param {Buffer} txToProveRID - The RID of the transaction to be proven.
 * @param {Buffer} txToProveHash - The hash of the transaction to be proven.
 * @param {PubKey[]} txToProveSigners - An array of public keys representing signers of the transaction to be proven.
 * @param {string} sourceBlockchainRid - The RID of the source blockchain.
 * @param {string} targetBlockchainRid - The RID of the target blockchain.
 * @param {PubKey[]} iccfTxSigners - An array of public keys representing signers of the ICCF proof transaction (optional, default: []).
 * @param {boolean} forceIntraNetworkIccfOperation - Whether to force the ICCF operation to be performed within the same network (optional, default: false).
 * @returns {Promise<IccfProofObject>} A promise that resolves to an ICCF proof object containing the ICCF proof transaction.
 */
export function createIccfProofTx(client, txToProveRID, txToProveHash, txToProveSigners, sourceBlockchainRid, targetBlockchainRid, iccfTxSigners = [], forceIntraNetworkIccfOperation = false) {
    return __awaiter(this, void 0, void 0, function* () {
        const clientConfiguredToSource = yield createClient({
            directoryNodeURLPool: client.config.endpointPool.slice(),
            blockchainRID: sourceBlockchainRid,
        });
        const txProof = yield clientConfiguredToSource.getConfirmationProof(txToProveRID);
        const proofHash = txProof.hash;
        const { verifiedTx, verifiedTxHash } = !txToProveHash.equals(proofHash)
            ? yield fetchAndVerifyTransaction(clientConfiguredToSource, txToProveRID, proofHash, txToProveSigners)
            : { verifiedTx: null, verifiedTxHash: txToProveHash };
        const sourceCluster = yield getClusterOfBlockchain(client, toBuffer(sourceBlockchainRid));
        const targetCluster = yield getClusterOfBlockchain(client, toBuffer(targetBlockchainRid));
        if (!forceIntraNetworkIccfOperation && sourceCluster === targetCluster) {
            // intra-cluster
            const intraClusterProofTx = {
                operations: [
                    {
                        name: "iccf_proof",
                        args: [toBuffer(sourceBlockchainRid), verifiedTxHash, txProof],
                    },
                ],
                signers: iccfTxSigners,
            };
            return { iccfTx: intraClusterProofTx };
        }
        else {
            // intra-network
            const sourceBlockRid = calculateBlockRID(txProof);
            const sourceClusterInfo = yield getClusterInfo(client, sourceCluster);
            const clientConfiguredToAnchoringchain = yield createClient({
                directoryNodeURLPool: client.config.endpointPool.slice(),
                blockchainRID: toString(sourceClusterInfo.anchoring_chain),
            });
            const anchoringTx = yield getAnchoringTransactionForBlockRid(clientConfiguredToAnchoringchain, toBuffer(sourceBlockchainRid), sourceBlockRid);
            if (!anchoringTx) {
                throw new Error("Block is not present in cluster anchoring chain");
            }
            const anchoringProof = yield clientConfiguredToAnchoringchain.getConfirmationProof(anchoringTx.txRid);
            const intraNetworkProofTx = {
                operations: [
                    {
                        name: "iccf_proof",
                        args: [
                            toBuffer(sourceBlockchainRid),
                            verifiedTxHash,
                            txProof,
                            anchoringTx.txData,
                            anchoringTx.txOpIndex,
                            anchoringProof,
                        ],
                    },
                ],
                signers: iccfTxSigners,
            };
            return { iccfTx: intraNetworkProofTx, verifiedTx };
        }
    });
}
//# sourceMappingURL=IccfProofTxMaterialBuilder.js.map