"use strict";
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 { Buffer } from "buffer";
import * as gtxTool from "./gtx";
import * as logger from "../logger";
import { removeDuplicateSigners } from "../formatter";
export function createClient(restApiClient, blockchainRid, functionNames) {
    functionNames.push("message");
    function transaction(gtx) {
        return {
            gtx,
            sign: function (privOrSigProv, pubKey) {
                return __awaiter(this, void 0, void 0, function* () {
                    logger.debug(`signing transaction with ${privOrSigProv instanceof Buffer
                        ? "privkey: " + privOrSigProv.toString("hex")
                        : "signature provider [pubkey: " + privOrSigProv.pubKey + "]"}`);
                    if (privOrSigProv instanceof Buffer) {
                        yield gtxTool.sign(this.gtx, privOrSigProv, pubKey);
                    }
                    else {
                        yield gtxTool.sign(this.gtx, privOrSigProv);
                    }
                });
            },
            getTxRID: function () {
                return this.getDigestToSign();
            },
            getDigestToSign: function () {
                return gtxTool.getDigestToSign(this.gtx);
            },
            addSignature: function (pubKey, signature) {
                gtxTool.addSignature(pubKey, signature, this.gtx);
            },
            // raw call
            addOperation: function (name, ...args) {
                gtxTool.addTransactionToGtx(name, args, this.gtx);
            },
            postAndWaitConfirmation() {
                return restApiClient.postAndWaitConfirmation(gtxTool.serialize(this.gtx), this.getTxRID());
            },
            send: function (callback) {
                const gtxBytes = gtxTool.serialize(this.gtx);
                restApiClient.postTransaction(gtxBytes, callback);
                this.gtx = null;
                this.gtxBytes = gtxBytes;
            },
            encode: function () {
                return gtxTool.serialize(this.gtx);
            },
        };
    }
    function addFunctions(req) {
        functionNames.forEach((functionName) => {
            req[functionName] = function (...args) {
                gtxTool.addTransactionToGtx(functionName, args, this.gtx);
            };
        });
    }
    const client = {
        newTransaction: function (signers) {
            signers = removeDuplicateSigners(signers);
            const newGtx = gtxTool.emptyGtx(Buffer.from(blockchainRid, "hex"));
            signers.forEach((signer) => gtxTool.addSignerToGtx(signer, newGtx));
            const req = transaction(newGtx);
            addFunctions(req);
            return req;
        },
        transactionFromRawTransaction: function (rawTransaction) {
            const gtx = gtxTool.deserialize(rawTransaction);
            logger.debug(`Output from deserializing a raw transaction: ${JSON.stringify(gtx)}`);
            const req = transaction(gtx);
            addFunctions(req);
            return req;
        },
        query: function (nameOrObject, queryArguments) {
            if (typeof nameOrObject === "string") {
                return restApiClient.query(nameOrObject, queryArguments);
            }
            else {
                return restApiClient.query(nameOrObject);
            }
        },
    };
    return client;
}
//# sourceMappingURL=gtxclient.js.map