"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.txRoute = void 0;
const express_1 = require("express");
const logger_1 = __importDefault(require("../../logger"));
const chain_state_1 = require("../../providers/chain-state");
const apiUtils_1 = require("../apiUtils");
const middleware_1 = require("../middleware");
const router = (0, express_1.Router)({ mergeParams: true });
router.get('/', async function (req, res) {
    try {
        let { chain, network } = req.params;
        const { blockHeight, blockHash, limit, since, direction, paging } = req.query;
        if (!chain || !network) {
            return res.status(400).send('Missing required param');
        }
        if (!blockHash && !blockHeight) {
            return res.status(400).send('Must provide blockHash or blockHeight');
        }
        chain = chain.toUpperCase();
        network = network.toLowerCase();
        const payload = {
            chain,
            network,
            req,
            res,
            args: { limit, since, direction, paging }
        };
        if (blockHeight !== undefined) {
            payload.args.blockHeight = parseInt(blockHeight);
        }
        if (blockHash !== undefined) {
            payload.args.blockHash = blockHash;
        }
        return await chain_state_1.ChainStateProvider.streamTransactions(payload);
    }
    catch (err) {
        logger_1.default.error('Error streaming transactions: %o', err.stack || err.message || err);
        return (0, apiUtils_1.respondWithError)(res, err);
    }
});
router.get('/:txId', async (req, res) => {
    let { chain, network, txId } = req.params;
    if (typeof txId !== 'string' || !chain || !network) {
        return res.status(400).send('Missing required param');
    }
    txId = txId
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;');
    chain = chain.toUpperCase();
    network = network.toLowerCase();
    try {
        const tx = await chain_state_1.ChainStateProvider.getTransaction({ chain, network, txId });
        if (!tx) {
            return res.status(404).send(`The requested txid ${txId} could not be found.`);
        }
        else {
            const tip = await chain_state_1.ChainStateProvider.getLocalTip({ chain, network });
            if (tx && tip && tx.blockHeight > -1 && tip.height - tx.blockHeight > 100) {
                (0, middleware_1.SetCache)(res, middleware_1.CacheTimes.Month);
            }
            return res.send(tx);
        }
    }
    catch (err) {
        logger_1.default.error('Error getting transaction: %o', err.stack || err.message || err);
        return (0, apiUtils_1.respondWithError)(res, err);
    }
});
// Get transaction with input and outputs, assigned to key coins
router.get('/:txId/populated', async (req, res) => {
    const { chain, network, txId } = req.params;
    const txid = txId;
    if (typeof txid !== 'string' || !chain || !network) {
        return res.status(400).send('Missing required param');
    }
    try {
        const [tx, coins, tip] = await Promise.all([
            chain_state_1.ChainStateProvider.getTransaction({ chain, network, txId }),
            chain_state_1.ChainStateProvider.getCoinsForTx({ chain, network, txid }), // must cast as any so tx.coins can be set to coins
            chain_state_1.ChainStateProvider.getLocalTip({ chain, network })
        ]);
        if (!tx) {
            return res.status(404).send(`The requested txid ${txid} could not be found.`);
        }
        else {
            if (tx && tip && tx.blockHeight > 0 && tip.height - tx.blockHeight > 100) {
                (0, middleware_1.SetCache)(res, middleware_1.CacheTimes.Month);
            }
            if (!coins) {
                res.status(404).send(`The requested coins for txid ${txid} could not be found.`);
            }
            tx.coins = coins;
            return res.send(tx);
        }
    }
    catch (err) {
        logger_1.default.error('Error getting populated transaction: %o', err.stack || err.message || err);
        return (0, apiUtils_1.respondWithError)(res, err);
    }
});
router.get('/:txId/authhead', async (req, res) => {
    let { chain, network } = req.params;
    const { txId } = req.params;
    if (typeof txId !== 'string' || !chain || !network) {
        return res.status(400).send('Missing required param');
    }
    chain = chain.toUpperCase();
    network = network.toLowerCase();
    try {
        const authhead = await chain_state_1.ChainStateProvider.getAuthhead({ chain, network, txId });
        if (!authhead) {
            return res.status(404).send(`Authhead for txid ${txId} could not be found.`);
        }
        else {
            return res.send(authhead);
        }
    }
    catch (err) {
        logger_1.default.error('Error getting transaction authhead: %o', err.stack || err.message || err);
        return (0, apiUtils_1.respondWithError)(res, err);
    }
});
router.get('/:txid/coins', (req, res, next) => {
    let { chain, network } = req.params;
    const { txid } = req.params;
    if (typeof txid !== 'string' || typeof chain !== 'string' || typeof network !== 'string') {
        res.status(400).send('Missing required param');
    }
    else {
        chain = chain.toUpperCase();
        network = network.toLowerCase();
        chain_state_1.ChainStateProvider.getCoinsForTx({ chain, network, txid })
            .then(coins => {
            res.setHeader('Content-Type', 'application/json');
            return res.status(200).send(JSON.stringify(coins));
        })
            .catch(next);
    }
});
router.post('/send', async function (req, res) {
    let { chain, network } = req.params;
    const { rawTx } = req.body;
    try {
        if (typeof rawTx !== 'string' && !Array.isArray(rawTx)) {
            return res.status(400).send('Invalid rawTx');
        }
        if (Array.isArray(rawTx) && !rawTx.every(tx => typeof tx === 'string')) {
            return res.status(400).send('Invalid array of rawTx');
        }
        chain = chain.toUpperCase();
        network = network.toLowerCase();
        const txid = await chain_state_1.ChainStateProvider.broadcastTransaction({
            chain,
            network,
            rawTx
        });
        return res.send({ txid });
    }
    catch (err) {
        logger_1.default.error('Broadcast error: %o %o %o %o', chain, network, rawTx, err.stack || err.message || err);
        return (0, apiUtils_1.respondWithError)(res, err);
    }
});
exports.txRoute = {
    router,
    path: '/tx'
};
//# sourceMappingURL=tx.js.map