"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.walletRoute = void 0;
const crypto_wallet_core_1 = require("@bitpay-labs/crypto-wallet-core");
const express_1 = require("express");
const config_1 = __importDefault(require("../../config"));
const logger_1 = __importDefault(require("../../logger"));
const chain_state_1 = require("../../providers/chain-state");
const auth_1 = require("../../utils/auth");
const router = (0, express_1.Router)({ mergeParams: true });
function isTooLong(field, maxLength = 255) {
    return field && field.toString().length >= maxLength;
}
// create wallet
router.post('/', async function (req, res) {
    try {
        const { chain, network } = req.params;
        const { name, pubKey, path, singleAddress } = req.body;
        const existingWallet = await chain_state_1.ChainStateProvider.getWallet({
            chain,
            network,
            pubKey
        });
        if (existingWallet) {
            return res.status(200).send('Wallet already exists');
        }
        if (isTooLong(name) || isTooLong(pubKey) || isTooLong(path) || isTooLong(singleAddress)) {
            return res.status(413).send('String length exceeds limit');
        }
        const result = await chain_state_1.ChainStateProvider.createWallet({
            chain,
            network,
            singleAddress,
            name,
            pubKey,
            path
        });
        return res.send(result);
    }
    catch (err) {
        logger_1.default.error('Error getting wallet: %o', err.stack || err.message || err);
        return res.status(500).send(err.message || err);
    }
});
router.get('/:pubKey/addresses/missing', auth_1.Auth.authenticateMiddleware, async (req, res) => {
    try {
        const { chain, network, pubKey } = req.params;
        const payload = {
            chain,
            network,
            pubKey,
            res
        };
        return await chain_state_1.ChainStateProvider.streamMissingWalletAddresses(payload);
    }
    catch (err) {
        logger_1.default.error('Error streaming missing wallets: %o', err.stack || err.message || err);
        return res.status(500).send(err.message || err);
    }
});
router.get('/:pubKey/addresses', auth_1.Auth.authenticateMiddleware, async (req, res) => {
    try {
        const { wallet } = req;
        const { chain, network } = req.params;
        const { limit } = req.query;
        const payload = {
            chain,
            network,
            walletId: wallet._id,
            limit,
            req,
            res
        };
        return await chain_state_1.ChainStateProvider.streamWalletAddresses(payload);
    }
    catch (err) {
        logger_1.default.error('Error streaming wallet addresses: %o', err.stack || err.message || err);
        return res.status(500).send(err.message || err);
    }
});
router.get('/:pubKey/check', auth_1.Auth.authenticateMiddleware, async (req, res) => {
    try {
        const { chain, network } = req.params;
        const wallet = req.wallet._id;
        const result = await chain_state_1.ChainStateProvider.walletCheck({
            chain,
            network,
            wallet
        });
        return res.send(result);
    }
    catch (err) {
        logger_1.default.error('Error checking wallet: %o', err.stack || err.message || err);
        return res.status(500).json(err);
    }
});
// update wallet
router.post('/:pubKey', auth_1.Auth.authenticateMiddleware, async (req, res) => {
    let keepAlive;
    try {
        const { chain, network, pubKey } = req.params;
        const addressLines = req.body.filter(line => !!line.address);
        const addresses = addressLines.map(({ address }) => address);
        for (const address of addresses) {
            if (isTooLong(address) || !crypto_wallet_core_1.Validation.validateAddress(chain, network, address)) {
                return res.status(413).send('Invalid address');
            }
        }
        let reprocess = false;
        if (req.headers['x-reprocess']) {
            const reprocessOk = auth_1.Auth.verifyRequestSignature({
                message: ['reprocess', '/addAddresses' + pubKey, JSON.stringify(req.body)].join('|'),
                pubKey: config_1.default.services.socket.bwsKeys[0],
                signature: req.headers['x-reprocess']
            });
            if (!reprocessOk) {
                return res.status(401).send('Authentication failed');
            }
            reprocess = true;
        }
        res.status(200);
        keepAlive = setInterval(() => {
            res.write('\n');
        }, 1000);
        await chain_state_1.ChainStateProvider.updateWallet({
            chain,
            network,
            wallet: req.wallet,
            addresses,
            reprocess
        });
        clearInterval(keepAlive);
        return res.end();
    }
    catch (err) {
        clearInterval(keepAlive);
        logger_1.default.error('Error updating wallet: %o', err.stack || err.message || err);
        return res.status(500).send(err.message || err);
    }
});
router.get('/:pubKey/transactions', auth_1.Auth.authenticateMiddleware, async (req, res) => {
    try {
        const { chain, network } = req.params;
        return await chain_state_1.ChainStateProvider.streamWalletTransactions({
            chain,
            network,
            wallet: req.wallet,
            req,
            res,
            args: req.query
        });
    }
    catch (err) {
        logger_1.default.error('Error streaming wallet txs: %o', err.stack || err.message || err);
        return res.status(500).send(err.message || err);
    }
});
router.get('/:pubKey/balance', auth_1.Auth.authenticateMiddleware, async (req, res) => {
    const { chain, network } = req.params;
    try {
        const result = await chain_state_1.ChainStateProvider.getWalletBalance({
            chain,
            network,
            wallet: req.wallet,
            args: req.query
        });
        return res.send(result || { confirmed: 0, unconfirmed: 0, balance: 0 });
    }
    catch (err) {
        logger_1.default.error('Error getting wallet balance: %o', err.stack || err.message || err);
        return res.status(500).json(err);
    }
});
router.get('/:pubKey/balance/:time', auth_1.Auth.authenticateMiddleware, async (req, res) => {
    const { chain, network, time } = req.params;
    try {
        const result = await chain_state_1.ChainStateProvider.getWalletBalanceAtTime({
            chain,
            network,
            wallet: req.wallet,
            time,
            args: req.query
        });
        return res.send(result || { confirmed: 0, unconfirmed: 0, balance: 0 });
    }
    catch (err) {
        logger_1.default.error('Error getting wallet: %o', err.stack || err.message || err);
        return res.status(500).json(err);
    }
});
router.get('/:pubKey/utxos', auth_1.Auth.authenticateMiddleware, async (req, res) => {
    const { chain, network } = req.params;
    const { limit } = req.query;
    try {
        return chain_state_1.ChainStateProvider.streamWalletUtxos({
            chain,
            network,
            wallet: req.wallet,
            limit,
            req,
            res,
            args: req.query
        });
    }
    catch (err) {
        logger_1.default.error('Error streaming wallet utxos: %o', err.stack || err.message || err);
        return res.status(500).send(err.message || err);
    }
});
router.get('/:pubKey', auth_1.Auth.authenticateMiddleware, async function (req, res) {
    try {
        const wallet = req.wallet;
        return res.send(wallet);
    }
    catch (err) {
        logger_1.default.error('Error getting wallet: %o', err.stack || err.message || err);
        return res.status(500).send(err.message || err);
    }
});
exports.walletRoute = {
    router,
    path: '/wallet'
};
//# sourceMappingURL=wallet.js.map