PHP WebShell

Текущая директория: /opt/BitGoJS/modules/express/dist/src

Просмотр файла: clientRoutes.js

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setupLightningSignerNodeRoutes = exports.setupSigningRoutes = exports.setupAPIRoutes = exports.createCustomMPCv2SigningRound3Generator = exports.createCustomMPCv2SigningRound2Generator = exports.createCustomMPCv2SigningRound1Generator = exports.createCustomGShareGenerator = exports.createCustomRShareGenerator = exports.createCustomCommitmentGenerator = exports.createCustomSShareGenerator = exports.createCustomMuDeltaShareGenerator = exports.createCustomKShareGenerator = exports.createCustomPaillierModulusGetter = exports.createCustomSigningFunction = exports.promiseWrapper = exports.redirectRequest = exports.handleKeychainChangePassword = exports.handleV2EnableTokens = exports.handleV2PrebuildAndSignTransaction = exports.handleV2ConsolidateAccount = exports.handleV2CreateAddress = exports.handleV2GenerateWallet = exports.handleV2OFCSignPayload = exports.handleV2OFCSignPayloadInExtSigningMode = exports.handleV2Sign = exports.handleV2SignTSSWalletTx = exports.handleV2GenerateShareTSS = void 0;
/**
 * @prettier
 */
const sdk_core_1 = require("@bitgo/sdk-core");
const bitgo_1 = require("bitgo");
const bodyParser = require("body-parser");
const debugLib = require("debug");
const _ = require("lodash");
const url = require("url");
const superagent = require("superagent");
// RequestTracer should be extracted into a separate npm package (along with
// the rest of the BitGoJS HTTP request machinery)
const util_1 = require("bitgo/dist/src/v2/internal/util");
const errors_1 = require("./errors");
const fs_1 = require("fs");
const retryPromise_1 = require("./retryPromise");
const lightningSignerRoutes_1 = require("./lightning/lightningSignerRoutes");
const lightningInvoiceRoutes_1 = require("./lightning/lightningInvoiceRoutes");
const lightningWalletRoutes_1 = require("./lightning/lightningWalletRoutes");
const proxy_agent_1 = require("proxy-agent");
const abstract_lightning_1 = require("@bitgo/abstract-lightning");
const lightningWithdrawRoutes_1 = require("./lightning/lightningWithdrawRoutes");
const { version } = require('bitgo/package.json');
const pjson = require('../package.json');
const debug = debugLib('bitgo:express');
const BITGOEXPRESS_USER_AGENT = `BitGoExpress/${pjson.version} BitGoJS/${version}`;
function handlePing(req, res, next) {
    return req.bitgo.ping();
}
function handlePingExpress(req) {
    return {
        status: 'express server is ok!',
    };
}
function handleLogin(req) {
    const username = req.body.username || req.body.email;
    const body = req.body;
    body.username = username;
    return req.bitgo.authenticate(body);
}
function handleDecrypt(req) {
    return {
        decrypted: req.bitgo.decrypt(req.body),
    };
}
function handleEncrypt(req) {
    return {
        encrypted: req.bitgo.encrypt(req.body),
    };
}
/**
 * @deprecated
 * @param req
 */
function handleVerifyAddress(req) {
    return {
        verified: req.bitgo.verifyAddress(req.body),
    };
}
/**
 * @deprecated
 * @param req
 */
function handleCreateLocalKeyChain(req) {
    return req.bitgo.keychains().create(req.body);
}
/**
 * @deprecated
 * @param req
 */
function handleDeriveLocalKeyChain(req) {
    return req.bitgo.keychains().deriveLocal(req.body);
}
/**
 * @deprecated
 * @param req
 */
function handleCreateWalletWithKeychains(req) {
    return req.bitgo.wallets().createWalletWithKeychains(req.body);
}
/**
 * @deprecated
 * @param req
 */
function handleSendCoins(req) {
    return req.bitgo
        .wallets()
        .get({ id: req.params.id })
        .then(function (wallet) {
        return wallet.sendCoins(req.body);
    })
        .catch(function (err) {
        err.status = 400;
        throw err;
    })
        .then(function (result) {
        if (result.status === 'pendingApproval') {
            throw apiResponse(202, result);
        }
        return result;
    });
}
/**
 * @deprecated
 * @param req
 */
function handleSendMany(req) {
    return req.bitgo
        .wallets()
        .get({ id: req.params.id })
        .then(function (wallet) {
        return wallet.sendMany(req.body);
    })
        .catch(function (err) {
        err.status = 400;
        throw err;
    })
        .then(function (result) {
        if (result.status === 'pendingApproval') {
            throw apiResponse(202, result);
        }
        return result;
    });
}
/**
 * @deprecated
 * @param req
 */
function handleCreateTransaction(req) {
    return req.bitgo
        .wallets()
        .get({ id: req.params.id })
        .then(function (wallet) {
        return wallet.createTransaction(req.body);
    })
        .catch(function (err) {
        err.status = 400;
        throw err;
    });
}
/**
 * @deprecated
 * @param req
 */
function handleSignTransaction(req) {
    return req.bitgo
        .wallets()
        .get({ id: req.params.id })
        .then(function (wallet) {
        return wallet.signTransaction(req.body);
    });
}
/**
 * @deprecated
 * @param req
 */
function handleShareWallet(req) {
    return req.bitgo
        .wallets()
        .get({ id: req.params.id })
        .then(function (wallet) {
        return wallet.shareWallet(req.body);
    });
}
/**
 * @deprecated
 * @param req
 */
function handleAcceptShare(req) {
    const params = req.body || {};
    params.walletShareId = req.params.shareId;
    return req.bitgo.wallets().acceptShare(params);
}
/**
 * @deprecated
 * @param req
 */
function handleApproveTransaction(req) {
    const params = req.body || {};
    return req.bitgo
        .pendingApprovals()
        .get({ id: req.params.id })
        .then(function (pendingApproval) {
        if (params.state === 'approved') {
            return pendingApproval.approve(params);
        }
        return pendingApproval.reject(params);
    });
}
/**
 * @deprecated
 * @param req
 */
function handleConstructApprovalTx(req) {
    const params = req.body || {};
    return req.bitgo
        .pendingApprovals()
        .get({ id: req.params.id })
        .then(function (pendingApproval) {
        return pendingApproval.constructApprovalTx(params);
    });
}
/**
 * @deprecated
 * @param req
 */
function handleConsolidateUnspents(req) {
    return req.bitgo
        .wallets()
        .get({ id: req.params.id })
        .then(function (wallet) {
        return wallet.consolidateUnspents(req.body);
    });
}
/**
 * @deprecated
 * @param req
 */
function handleFanOutUnspents(req) {
    return req.bitgo
        .wallets()
        .get({ id: req.params.id })
        .then(function (wallet) {
        return wallet.fanOutUnspents(req.body);
    });
}
/**
 * @deprecated
 * @param req
 */
function handleCalculateMinerFeeInfo(req) {
    return req.bitgo.calculateMinerFeeInfo({
        bitgo: req.bitgo,
        feeRate: req.body.feeRate,
        nP2shInputs: req.body.nP2shInputs,
        nP2pkhInputs: req.body.nP2pkhInputs,
        nP2shP2wshInputs: req.body.nP2shP2wshInputs,
        nOutputs: req.body.nOutputs,
    });
}
/**
 * Builds the API's URL string, optionally building the querystring if parameters exist
 * @param req
 * @return {string}
 */
function createAPIPath(req) {
    let apiPath = '/' + req.params[0];
    if (!_.isEmpty(req.query)) {
        // req.params does not contain the querystring, so we manually add them here
        const urlDetails = url.parse(req.url);
        if (urlDetails.search) {
            // "search" is the properly URL encoded query params, prefixed with "?"
            apiPath += urlDetails.search;
        }
    }
    return apiPath;
}
/**
 * handle any other V1 API call
 * @deprecated
 * @param req
 * @param res
 * @param next
 */
function handleREST(req, res, next) {
    const method = req.method;
    const bitgo = req.bitgo;
    const bitgoURL = bitgo.url(createAPIPath(req));
    return redirectRequest(bitgo, method, bitgoURL, req, next);
}
/**
 * handle any other V2 API call
 * @param req
 * @param res
 * @param next
 */
function handleV2UserREST(req, res, next) {
    const method = req.method;
    const bitgo = req.bitgo;
    const bitgoURL = bitgo.url('/user' + createAPIPath(req), 2);
    return redirectRequest(bitgo, method, bitgoURL, req, next);
}
/**
 * handle v2 address validation
 * @param req
 */
function handleV2VerifyAddress(req) {
    if (!_.isString(req.body.address)) {
        throw new Error('Expected address to be a string');
    }
    if (req.body.supportOldScriptHashVersion !== undefined && !_.isBoolean(req.body.supportOldScriptHashVersion)) {
        throw new Error('Expected supportOldScriptHashVersion to be a boolean.');
    }
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    if (coin instanceof bitgo_1.Coin.AbstractUtxoCoin) {
        return {
            isValid: coin.isValidAddress(req.body.address, !!req.body.supportOldScriptHashVersion),
        };
    }
    return {
        isValid: coin.isValidAddress(req.body.address),
    };
}
/**
 * handle address canonicalization
 * @param req
 */
function handleCanonicalAddress(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    if (!['ltc', 'bch', 'bsv'].includes(coin.getFamily())) {
        throw new Error('only Litecoin/Bitcoin Cash/Bitcoin SV address canonicalization is supported');
    }
    const address = req.body.address;
    const fallbackVersion = req.body.scriptHashVersion; // deprecate
    const version = req.body.version;
    return coin.canonicalAddress(address, version || fallbackVersion);
}
function getWalletPwFromEnv(walletId) {
    const name = `WALLET_${walletId}_PASSPHRASE`;
    const walletPw = process.env[name];
    if (walletPw === undefined) {
        throw new Error(`Could not find wallet passphrase ${name} in environment`);
    }
    return walletPw;
}
async function getEncryptedPrivKey(path, walletId) {
    const privKeyFile = await fs_1.promises.readFile(path, { encoding: 'utf8' });
    const encryptedPrivKey = JSON.parse(privKeyFile);
    if (encryptedPrivKey[walletId] === undefined) {
        throw new Error(`Could not find a field for walletId: ${walletId} in ${path}`);
    }
    return encryptedPrivKey[walletId];
}
function decryptPrivKey(bg, encryptedPrivKey, walletPw) {
    try {
        return bg.decrypt({ password: walletPw, input: encryptedPrivKey });
    }
    catch (e) {
        throw new Error(`Error when trying to decrypt private key: ${e}`);
    }
}
async function handleV2GenerateShareTSS(req) {
    const walletId = req.body.txRequest ? req.body.txRequest.walletId : req.body.tssParams.txRequest.walletId;
    if (!walletId) {
        throw new Error('Missing required field: walletId');
    }
    const walletPw = getWalletPwFromEnv(walletId);
    const { signerFileSystemPath } = req.config;
    if (!signerFileSystemPath) {
        throw new Error('Missing required configuration: signerFileSystemPath');
    }
    const encryptedPrivKey = await getEncryptedPrivKey(signerFileSystemPath, walletId);
    const bitgo = req.bitgo;
    const privKey = decryptPrivKey(bitgo, encryptedPrivKey, walletPw);
    const coin = bitgo.coin(req.params.coin);
    req.body.prv = privKey;
    req.body.walletPassphrase = walletPw;
    try {
        if (coin.getMPCAlgorithm() === sdk_core_1.MPCType.EDDSA) {
            const eddsaUtils = new sdk_core_1.EddsaUtils(bitgo, coin);
            switch (req.params.sharetype) {
                case sdk_core_1.ShareType.Commitment:
                    return await eddsaUtils.createCommitmentShareFromTxRequest(req.body);
                case sdk_core_1.ShareType.R:
                    return await eddsaUtils.createRShareFromTxRequest(req.body);
                case sdk_core_1.ShareType.G:
                    return await eddsaUtils.createGShareFromTxRequest(req.body);
                default:
                    throw new Error(`Share type ${req.params.sharetype} not supported, only commitment, G and R share generation is supported.`);
            }
        }
        else if (coin.getMPCAlgorithm() === sdk_core_1.MPCType.ECDSA) {
            const isMPCv2 = [
                sdk_core_1.ShareType.MPCv2Round1.toString(),
                sdk_core_1.ShareType.MPCv2Round2.toString(),
                sdk_core_1.ShareType.MPCv2Round3.toString(),
            ].includes(req.params.sharetype);
            if (isMPCv2) {
                const ecdsaMPCv2Utils = new sdk_core_1.EcdsaMPCv2Utils(bitgo, coin);
                switch (req.params.sharetype) {
                    case sdk_core_1.ShareType.MPCv2Round1:
                        return await ecdsaMPCv2Utils.createOfflineRound1Share(req.body);
                    case sdk_core_1.ShareType.MPCv2Round2:
                        return await ecdsaMPCv2Utils.createOfflineRound2Share(req.body);
                    case sdk_core_1.ShareType.MPCv2Round3:
                        return await ecdsaMPCv2Utils.createOfflineRound3Share(req.body);
                    default:
                        throw new Error(`Share type ${req.params.sharetype} not supported for MPCv2, only MPCv2Round1, MPCv2Round2 and MPCv2Round3 is supported.`);
                }
            }
            else {
                const ecdsaUtils = new sdk_core_1.EcdsaUtils(bitgo, coin);
                switch (req.params.sharetype) {
                    case sdk_core_1.ShareType.PaillierModulus:
                        return ecdsaUtils.getOfflineSignerPaillierModulus(req.body);
                    case sdk_core_1.ShareType.K:
                        return await ecdsaUtils.createOfflineKShare(req.body);
                    case sdk_core_1.ShareType.MuDelta:
                        return await ecdsaUtils.createOfflineMuDeltaShare(req.body);
                    case sdk_core_1.ShareType.S:
                        return await ecdsaUtils.createOfflineSShare(req.body);
                    default:
                        throw new Error(`Share type ${req.params.sharetype} not supported, only PaillierModulus, K, MUDelta, and S share generation is supported.`);
                }
            }
        }
        else {
            throw new Error(`MPC Algorithm ${coin.getMPCAlgorithm()} is not supported.`);
        }
    }
    catch (error) {
        console.error('error while signing wallet transaction ', error);
        throw error;
    }
}
exports.handleV2GenerateShareTSS = handleV2GenerateShareTSS;
async function handleV2SignTSSWalletTx(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const wallet = await coin.wallets().get({ id: req.params.id });
    try {
        return await wallet.signTransaction(createTSSSendParams(req, wallet));
    }
    catch (error) {
        console.error('error while signing wallet transaction ', error);
        throw error;
    }
}
exports.handleV2SignTSSWalletTx = handleV2SignTSSWalletTx;
/**
 * This route is used to sign while external express signer is enabled
 */
async function handleV2Sign(req) {
    const walletId = req.body.txPrebuild?.walletId;
    if (!walletId) {
        throw new Error('Missing required field: walletId');
    }
    const walletPw = getWalletPwFromEnv(walletId);
    const { signerFileSystemPath } = req.config;
    if (!signerFileSystemPath) {
        throw new Error('Missing required configuration: signerFileSystemPath');
    }
    const encryptedPrivKey = await getEncryptedPrivKey(signerFileSystemPath, walletId);
    const bitgo = req.bitgo;
    let privKey = decryptPrivKey(bitgo, encryptedPrivKey, walletPw);
    const coin = bitgo.coin(req.params.coin);
    if (req.body.derivationSeed) {
        privKey = coin.deriveKeyWithSeed({ key: privKey, seed: req.body.derivationSeed }).key;
    }
    try {
        return await coin.signTransaction({ ...req.body, prv: privKey });
    }
    catch (error) {
        console.log('error while signing wallet transaction ', error);
        throw error;
    }
}
exports.handleV2Sign = handleV2Sign;
async function handleV2OFCSignPayloadInExtSigningMode(req) {
    const walletId = req.body.walletId;
    const payload = req.body.payload;
    const bodyWalletPassphrase = req.body.walletPassphrase;
    const ofcCoinName = 'ofc';
    if (!payload) {
        throw new errors_1.ApiResponseError('Missing required field: payload', 400);
    }
    if (!walletId) {
        throw new errors_1.ApiResponseError('Missing required field: walletId', 400);
    }
    // fetch the password for the given walletId from the body or the env. This is required for decrypting the private key that belongs to that wallet.
    const walletPw = bodyWalletPassphrase || getWalletPwFromEnv(walletId);
    const { signerFileSystemPath } = req.config;
    if (!signerFileSystemPath) {
        throw new errors_1.ApiResponseError('Missing required configuration: signerFileSystemPath', 500);
    }
    // get the encrypted private key from the local JSON file (encryptedPrivKeys.json) (populated using fetchEncryptedPrivateKeys.ts)
    const encryptedPrivKey = await getEncryptedPrivKey(signerFileSystemPath, walletId);
    const bitgo = req.bitgo;
    // decrypt the encrypted private key using the wallet pwd
    const privKey = decryptPrivKey(bitgo, encryptedPrivKey, walletPw);
    // create a BaseCoin instance for 'ofc'
    const coin = bitgo.coin(ofcCoinName);
    // stringify the payload if not already a string
    const stringifiedPayload = typeof payload === 'string' ? payload : JSON.stringify(payload);
    try {
        // sign the message using the decrypted private key
        const signature = (await coin.signMessage({ prv: privKey }, stringifiedPayload)).toString('hex');
        return {
            payload: stringifiedPayload,
            signature,
        };
    }
    catch (error) {
        console.log('Error while signing message.', error);
        throw error;
    }
}
exports.handleV2OFCSignPayloadInExtSigningMode = handleV2OFCSignPayloadInExtSigningMode;
async function handleV2OFCSignPayload(req) {
    const walletId = req.body.walletId;
    const payload = req.body.payload;
    const bodyWalletPassphrase = req.body.walletPassphrase;
    const ofcCoinName = 'ofc';
    // If the externalSignerUrl is set, forward the request to the express server hosted on the externalSignerUrl
    const externalSignerUrl = req.config?.externalSignerUrl;
    if (externalSignerUrl) {
        const { body: payloadWithSignature } = await (0, retryPromise_1.retryPromise)(() => superagent
            .post(`${externalSignerUrl}/api/v2/ofc/signPayload`)
            .type('json')
            .send({ walletId: walletId, payload: payload }), (err, tryCount) => {
            debug(`failed to connect to external signer (attempt ${tryCount}, error: ${err.message})`);
        });
        return payloadWithSignature;
    }
    if (!payload) {
        throw new errors_1.ApiResponseError('Missing required field: payload', 400);
    }
    if (!walletId) {
        throw new errors_1.ApiResponseError('Missing required field: walletId', 400);
    }
    const bitgo = req.bitgo;
    // This is to set us up for multiple trading accounts per enterprise
    const wallet = await bitgo.coin(ofcCoinName).wallets().get({ id: walletId });
    if (wallet === undefined) {
        throw new errors_1.ApiResponseError(`Could not find OFC wallet ${walletId}`, 404);
    }
    const walletPassphrase = bodyWalletPassphrase || getWalletPwFromEnv(wallet.id());
    const tradingAccount = wallet.toTradingAccount();
    const stringifiedPayload = JSON.stringify(req.body.payload);
    const signature = await tradingAccount.signPayload({
        payload: stringifiedPayload,
        walletPassphrase,
    });
    return {
        payload: stringifiedPayload,
        signature,
    };
}
exports.handleV2OFCSignPayload = handleV2OFCSignPayload;
/**
 * handle new wallet creation
 * @param req
 */
async function handleV2GenerateWallet(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const result = await coin.wallets().generateWallet(req.body);
    if (req.query.includeKeychains === 'false') {
        return result.wallet.toJSON();
    }
    return { ...result, wallet: result.wallet.toJSON() };
}
exports.handleV2GenerateWallet = handleV2GenerateWallet;
/**
 * handle new address creation
 * @param req
 */
async function handleV2CreateAddress(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const wallet = await coin.wallets().get({ id: req.params.id });
    return wallet.createAddress(req.body);
}
exports.handleV2CreateAddress = handleV2CreateAddress;
/**
 * handle v2 approve transaction
 * @param req
 */
async function handleV2PendingApproval(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const params = req.body || {};
    const pendingApproval = await coin.pendingApprovals().get({ id: req.params.id });
    if (params.state === 'approved') {
        return pendingApproval.approve(params);
    }
    return pendingApproval.reject(params);
}
/**
 * create a keychain
 * @param req
 */
function handleV2CreateLocalKeyChain(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    return coin.keychains().create(req.body);
}
/**
 * handle wallet share
 * @param req
 */
async function handleV2ShareWallet(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const wallet = await coin.wallets().get({ id: req.params.id });
    return wallet.shareWallet(req.body);
}
/**
 * handle accept wallet share
 * @param req
 */
async function handleV2AcceptWalletShare(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const params = _.extend({}, req.body, { walletShareId: req.params.id });
    return coin.wallets().acceptShare(params);
}
/**
 * handle wallet sign transaction
 */
async function handleV2SignTxWallet(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const wallet = await coin.wallets().get({ id: req.params.id });
    try {
        return await wallet.signTransaction(createSendParams(req));
    }
    catch (error) {
        console.log('error while signing wallet transaction ', error);
        throw error;
    }
}
/**
 * handle sign transaction
 * @param req
 */
async function handleV2SignTx(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    try {
        return await coin.signTransaction(req.body);
    }
    catch (error) {
        console.log('error while signing the transaction ', error);
        throw error;
    }
}
/**
 * handle wallet recover token
 * @param req
 */
async function handleV2RecoverToken(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const wallet = await coin.wallets().get({ id: req.params.id });
    return wallet.recoverToken(req.body);
}
/**
 * handle wallet fanout unspents
 * @param req
 */
async function handleV2ConsolidateUnspents(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const wallet = await coin.wallets().get({ id: req.params.id });
    return wallet.consolidateUnspents(createSendParams(req));
}
/**
 * Handle Wallet Account Consolidation.
 *
 * @param req
 */
async function handleV2ConsolidateAccount(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    if (req.body.consolidateAddresses && !_.isArray(req.body.consolidateAddresses)) {
        throw new Error('consolidate address must be an array of addresses');
    }
    if (!coin.allowsAccountConsolidations()) {
        throw new Error('invalid coin selected');
    }
    const wallet = await coin.wallets().get({ id: req.params.id });
    let result;
    try {
        if (coin.supportsTss()) {
            result = await wallet.sendAccountConsolidations(createTSSSendParams(req, wallet));
        }
        else {
            result = await wallet.sendAccountConsolidations(createSendParams(req));
        }
    }
    catch (err) {
        err.status = 400;
        throw err;
    }
    // we had failures to handle
    if (result.failure.length && result.failure.length > 0) {
        let msg = '';
        let status = 202;
        if (result.success.length && result.success.length > 0) {
            // but we also had successes
            msg = `Transactions failed: ${result.failure.length} and succeeded: ${result.success.length}`;
        }
        else {
            // or in this case only failures
            status = 400;
            msg = `All transactions failed`;
        }
        throw apiResponse(status, result, msg);
    }
    return result;
}
exports.handleV2ConsolidateAccount = handleV2ConsolidateAccount;
/**
 * handle wallet fanout unspents
 * @param req
 */
async function handleV2FanOutUnspents(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const wallet = await coin.wallets().get({ id: req.params.id });
    return wallet.fanoutUnspents(createSendParams(req));
}
/**
 * handle wallet sweep
 * @param req
 */
async function handleV2Sweep(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const wallet = await coin.wallets().get({ id: req.params.id });
    return wallet.sweep(createSendParams(req));
}
/**
 * handle CPFP accelerate transaction creation
 * @param req
 */
async function handleV2AccelerateTransaction(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const wallet = await coin.wallets().get({ id: req.params.id });
    return wallet.accelerateTransaction(createSendParams(req));
}
function createSendParams(req) {
    if (req.config?.externalSignerUrl !== undefined) {
        return {
            ...req.body,
            customSigningFunction: createCustomSigningFunction(req.config.externalSignerUrl),
        };
    }
    else {
        return req.body;
    }
}
function createTSSSendParams(req, wallet) {
    if (req.config?.externalSignerUrl !== undefined) {
        const coin = req.bitgo.coin(req.params.coin);
        if (coin.getMPCAlgorithm() === sdk_core_1.MPCType.EDDSA) {
            return {
                ...req.body,
                customCommitmentGeneratingFunction: createCustomCommitmentGenerator(req.config.externalSignerUrl, req.params.coin),
                customRShareGeneratingFunction: createCustomRShareGenerator(req.config.externalSignerUrl, req.params.coin),
                customGShareGeneratingFunction: createCustomGShareGenerator(req.config.externalSignerUrl, req.params.coin),
            };
        }
        else if (coin.getMPCAlgorithm() === sdk_core_1.MPCType.ECDSA) {
            if (wallet._wallet.multisigTypeVersion === 'MPCv2') {
                return {
                    ...req.body,
                    customMPCv2SigningRound1GenerationFunction: createCustomMPCv2SigningRound1Generator(req.config.externalSignerUrl, req.params.coin),
                    customMPCv2SigningRound2GenerationFunction: createCustomMPCv2SigningRound2Generator(req.config.externalSignerUrl, req.params.coin),
                    customMPCv2SigningRound3GenerationFunction: createCustomMPCv2SigningRound3Generator(req.config.externalSignerUrl, req.params.coin),
                };
            }
            else {
                return {
                    ...req.body,
                    customPaillierModulusGeneratingFunction: createCustomPaillierModulusGetter(req.config.externalSignerUrl, req.params.coin),
                    customKShareGeneratingFunction: createCustomKShareGenerator(req.config.externalSignerUrl, req.params.coin),
                    customMuDeltaShareGeneratingFunction: createCustomMuDeltaShareGenerator(req.config.externalSignerUrl, req.params.coin),
                    customSShareGeneratingFunction: createCustomSShareGenerator(req.config.externalSignerUrl, req.params.coin),
                };
            }
        }
        else {
            throw new Error(`MPC Algorithm ${coin.getMPCAlgorithm()} is not supported.`);
        }
    }
    else {
        return req.body;
    }
}
/**
 * handle send one
 * @param req
 */
async function handleV2SendOne(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const reqId = new util_1.RequestTracer();
    const wallet = await coin.wallets().get({ id: req.params.id, reqId });
    req.body.reqId = reqId;
    let result;
    try {
        result = await wallet.send(createSendParams(req));
    }
    catch (err) {
        err.status = 400;
        throw err;
    }
    if (result.status === 'pendingApproval') {
        throw apiResponse(202, result);
    }
    return result;
}
/**
 * handle send many
 * @param req
 */
async function handleV2SendMany(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const reqId = new util_1.RequestTracer();
    const wallet = await coin.wallets().get({ id: req.params.id, reqId });
    req.body.reqId = reqId;
    let result;
    try {
        if (wallet._wallet.multisigType === 'tss') {
            result = await wallet.sendMany(createTSSSendParams(req, wallet));
        }
        else {
            result = await wallet.sendMany(createSendParams(req));
        }
    }
    catch (err) {
        err.status = 400;
        throw err;
    }
    if (result.status === 'pendingApproval') {
        throw apiResponse(202, result);
    }
    return result;
}
/**
 *  payload meant for prebuildAndSignTransaction() in sdk-core which
 * validates the payload and makes the appropriate request to WP to
 * build, sign, and send a tx.
 * - sends request to Platform to build the transaction
 * - signs with user key
 * - request signature from the second key (BitGo HSM)
 * - send/broadcast transaction
 * @param req where req.body is {@link PrebuildAndSignTransactionOptions}
 */
async function handleV2PrebuildAndSignTransaction(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const reqId = new util_1.RequestTracer();
    const wallet = await coin.wallets().get({ id: req.params.id, reqId });
    req.body.reqId = reqId;
    let result;
    try {
        result = await wallet.prebuildAndSignTransaction(createSendParams(req));
    }
    catch (err) {
        err.status = 400;
        throw err;
    }
    return result;
}
exports.handleV2PrebuildAndSignTransaction = handleV2PrebuildAndSignTransaction;
/**
 * Enables tokens on a wallet
 * @param req
 */
async function handleV2EnableTokens(req) {
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    const reqId = new util_1.RequestTracer();
    const wallet = await coin.wallets().get({ id: req.params.id, reqId });
    req.body.reqId = reqId;
    try {
        return wallet.sendTokenEnablements(createSendParams(req));
    }
    catch (err) {
        err.status = 400;
        throw err;
    }
}
exports.handleV2EnableTokens = handleV2EnableTokens;
/**
 * Handle Update Wallet
 * @param req
 */
async function handleWalletUpdate(req) {
    // If it's a lightning coin, use the lightning-specific handler
    if ((0, abstract_lightning_1.isLightningCoinName)(req.params.coin)) {
        return (0, lightningWalletRoutes_1.handleUpdateLightningWalletCoinSpecific)(req);
    }
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    // For non-lightning coins, directly update the wallet
    const wallet = await coin.wallets().get({ id: req.params.id });
    return await bitgo.put(wallet.url()).send(req.body).result();
}
/**
 * Changes a keychain's passphrase, re-encrypting the key to a new password
 * @param req
 */
async function handleKeychainChangePassword(req) {
    const { oldPassword, newPassword, otp } = req.body;
    if (!oldPassword || !newPassword) {
        throw new errors_1.ApiResponseError('Missing 1 or more required fields: [oldPassword, newPassword]', 400);
    }
    const reqId = new util_1.RequestTracer();
    const bitgo = req.bitgo;
    const coin = bitgo.coin(req.params.coin);
    if (otp) {
        await bitgo.unlock({ otp });
    }
    const keychain = await coin.keychains().get({
        id: req.params.id,
        reqId,
    });
    if (!keychain) {
        throw new errors_1.ApiResponseError(`Keychain ${req.params.id} not found`, 404);
    }
    const updatedKeychain = coin.keychains().updateSingleKeychainPassword({
        keychain,
        oldPassword,
        newPassword,
    });
    return bitgo.put(coin.url(`/key/${updatedKeychain.id}`)).send({
        encryptedPrv: updatedKeychain.encryptedPrv,
    });
}
exports.handleKeychainChangePassword = handleKeychainChangePassword;
/**
 * handle any other API call
 * @param req
 * @param res
 * @param next
 */
function handleV2CoinSpecificREST(req, res, next) {
    const method = req.method;
    const bitgo = req.bitgo;
    debug('handling v2 coin specific rest req');
    try {
        const coin = bitgo.coin(req.params.coin);
        const coinURL = coin.url(createAPIPath(req));
        return redirectRequest(bitgo, method, coinURL, req, next);
    }
    catch (e) {
        if (e instanceof sdk_core_1.UnsupportedCoinError) {
            const queryParams = _.transform(req.query, (acc, value, key) => {
                for (const val of _.castArray(value)) {
                    acc.push(`${key}=${val}`);
                }
            }, []);
            const baseUrl = bitgo.url(req.baseUrl.replace(/^\/api\/v2/, ''), 2);
            const url = _.isEmpty(queryParams) ? baseUrl : `${baseUrl}?${queryParams.join('&')}`;
            debug(`coin ${req.params.coin} not supported, attempting to handle as a coinless route with url ${url}`);
            return redirectRequest(bitgo, method, url, req, next);
        }
        throw e;
    }
}
/**
 * Handle additional option to encrypt on the express route for partners requiring value encryption
 * @param req.body.encrypt - boolean to determine if the request should handle encryption on behalf of the submission.
 */
async function handleNetworkV1EnterpriseClientConnections(req, res, next) {
    debug('handling network v1 partner connection creation');
    const bitgo = req.bitgo;
    const params = req.params;
    const body = req.body;
    if (body.encrypt === true) {
        if (!body.partnerId) {
            throw new errors_1.ApiResponseError('Missing required field: partnerId', 400);
        }
        const partnersUrl = bitgo.microservicesUrl(`/api/network/v1/enterprises/${params.enterpriseId}/partners`);
        const response = await bitgo
            .get(partnersUrl)
            .set('enterprise-id', params.enterpriseId)
            .send({ ids: [params.partnerId] })
            .result();
        const partners = response.partners;
        const partner = partners.find((p) => p.id === body.partnerId);
        if (!partner) {
            throw new errors_1.ApiResponseError(`Partner not found for partnerId: ${body.partnerId}`, 400);
        }
        if (!partner.publicKey) {
            throw new errors_1.ApiResponseError('Partner does not require encryption', 400);
        }
        switch (body.connectionKey.schema) {
            case 'token':
                req.body.connectionKey.connectionToken = await (0, sdk_core_1.encryptRsaWithAesGcm)(partner.publicKey, body.connectionKey.connectionToken);
                break;
            case 'tokenAndSignature':
                req.body.connectionKey.connectionToken = await (0, sdk_core_1.encryptRsaWithAesGcm)(partner.publicKey, body.connectionKey.connectionToken);
                req.body.connectionKey.signature = await (0, sdk_core_1.encryptRsaWithAesGcm)(partner.publicKey, body.connectionKey.signature);
                break;
            case 'apiKeyAndSecret':
            case 'clearloop':
                req.body.connectionKey.apiKey = await (0, sdk_core_1.encryptRsaWithAesGcm)(partner.publicKey, body.connectionKey.apiKey);
                req.body.connectionKey.apiSecret = await (0, sdk_core_1.encryptRsaWithAesGcm)(partner.publicKey, body.connectionKey.apiSecret);
                break;
        }
    }
    return handleProxyReq(req, res, next);
}
/**
 * Redirect a request using the bitgo request functions.
 * @param bitgo
 * @param method
 * @param url
 * @param req
 * @param next
 */
function redirectRequest(bitgo, method, url, req, next) {
    let request;
    switch (method) {
        case 'GET':
            request = bitgo.get(url);
            break;
        case 'POST':
            request = bitgo.post(url).send(req.body);
            break;
        case 'PUT':
            request = bitgo.put(url).send(req.body);
            break;
        case 'PATCH':
            request = bitgo.patch(url).send(req.body);
            break;
        case 'OPTIONS':
            request = bitgo.options(url).send(req.body);
            break;
        case 'DELETE':
            request = bitgo.del(url).send(req.body);
            break;
    }
    if (request) {
        if (req.params.enterpriseId) {
            request.set('enterprise-id', req.params.enterpriseId);
        }
        return request.result().then((result) => {
            const status = request.res?.statusCode || 200;
            return { status, body: result };
        });
    }
    // something has presumably gone wrong
    next();
}
exports.redirectRequest = redirectRequest;
async function handleProxyReq(req, res, next) {
    const fullUrl = req.bitgo.microservicesUrl(req.originalUrl);
    if (req.url && (/^\/api.*$/.test(req.originalUrl) || /^\/oauth\/token.*$/.test(req.url))) {
        req.isProxy = true;
        debug('proxying %s request to %s', req.method, fullUrl);
        return await redirectRequest(req.bitgo, req.method, fullUrl, req, next);
    }
    // user tried to access a url which is not an api route, do not proxy
    debug('unable to proxy %s request to %s', req.method, fullUrl);
    throw new errors_1.ApiResponseError('bitgo-express can only proxy BitGo API requests', 404);
}
/**
 *
 * @param status
 * @param result
 * @param message
 */
function apiResponse(status, result, message) {
    return new errors_1.ApiResponseError(message, status, result);
}
const expressJSONParser = bodyParser.json({ limit: '20mb' });
/**
 * Perform body parsing here only on routes we want
 */
function parseBody(req, res, next) {
    // Set the default Content-Type, in case the client doesn't set it.  If
    // Content-Type isn't specified, Express silently refuses to parse the
    // request body.
    req.headers['content-type'] = req.headers['content-type'] || 'application/json';
    return expressJSONParser(req, res, next);
}
/**
 * Create the bitgo object in the request
 * @param config
 */
function prepareBitGo(config) {
    const { env, customRootUri, customBitcoinNetwork } = config;
    return function prepBitGo(req, res, next) {
        // Get access token
        let accessToken;
        if (req.headers.authorization) {
            const authSplit = req.headers.authorization.split(' ');
            if (authSplit.length === 2 && authSplit[0].toLowerCase() === 'bearer') {
                accessToken = authSplit[1];
            }
        }
        const userAgent = req.headers['user-agent']
            ? BITGOEXPRESS_USER_AGENT + ' ' + req.headers['user-agent']
            : BITGOEXPRESS_USER_AGENT;
        const useProxyUrl = process.env.BITGO_USE_PROXY;
        const bitgoConstructorParams = {
            env,
            customRootURI: customRootUri,
            customBitcoinNetwork,
            accessToken,
            userAgent,
            ...(useProxyUrl
                ? {
                    customProxyAgent: new proxy_agent_1.ProxyAgent({
                        getProxyForUrl: () => useProxyUrl,
                    }),
                }
                : {}),
        };
        req.bitgo = new bitgo_1.BitGo(bitgoConstructorParams);
        req.config = config;
        next();
    };
}
function handleRequestHandlerError(res, error) {
    let err;
    if (error instanceof Error) {
        err = error;
    }
    else if (typeof error === 'string') {
        err = new Error('(string_error) ' + error);
    }
    else {
        err = new Error('(object_error) ' + JSON.stringify(error));
    }
    const message = err.message || 'local error';
    // use attached result, or make one
    let result = err.result || { error: message };
    result = _.extend({}, result, {
        message: err.message,
        bitgoJsVersion: version,
        bitgoExpressVersion: pjson.version,
    });
    const status = err.status || 500;
    if (!(status >= 200 && status < 300)) {
        console.log('error %s: %s', status, err.message);
    }
    if (status >= 500 && status <= 599) {
        if (err.response && err.response.request) {
            console.log(`failed to make ${err.response.request.method} request to ${err.response.request.url}`);
        }
        console.log(err.stack);
    }
    res.status(status).send(result);
}
/**
 * Promise handler wrapper to handle sending responses and error cases
 * @param promiseRequestHandler
 */
function promiseWrapper(promiseRequestHandler) {
    return async function promWrapper(req, res, next) {
        debug(`handle: ${req.method} ${req.originalUrl}`);
        try {
            const result = await promiseRequestHandler(req, res, next);
            if (typeof result === 'object' && result !== null && 'body' in result && 'status' in result) {
                const { status, body } = result;
                res.status(status).send(body);
            }
            else {
                res.status(200).send(result);
            }
        }
        catch (e) {
            handleRequestHandlerError(res, e);
        }
    };
}
exports.promiseWrapper = promiseWrapper;
function createCustomSigningFunction(externalSignerUrl) {
    return async function (params) {
        const { body: signedTx } = await (0, retryPromise_1.retryPromise)(() => superagent.post(`${externalSignerUrl}/api/v2/${params.coin.getChain()}/sign`).type('json').send({
            txPrebuild: params.txPrebuild,
            pubs: params.pubs,
            derivationSeed: params.derivationSeed,
            signingStep: params.signingStep,
        }), (err, tryCount) => {
            debug(`failed to connect to external signer (attempt ${tryCount}, error: ${err.message})`);
        });
        return signedTx;
    };
}
exports.createCustomSigningFunction = createCustomSigningFunction;
function createCustomPaillierModulusGetter(externalSignerUrl, coin) {
    return async function (params) {
        const { body: result } = await (0, retryPromise_1.retryPromise)(() => superagent.post(`${externalSignerUrl}/api/v2/${coin}/tssshare/PaillierModulus`).type('json').send(params), (err, tryCount) => {
            debug(`failed to connect to external signer (attempt ${tryCount}, error: ${err.message})`);
        });
        return result;
    };
}
exports.createCustomPaillierModulusGetter = createCustomPaillierModulusGetter;
function createCustomKShareGenerator(externalSignerUrl, coin) {
    return async function (params) {
        const { body: result } = await (0, retryPromise_1.retryPromise)(() => superagent.post(`${externalSignerUrl}/api/v2/${coin}/tssshare/K`).type('json').send(params), (err, tryCount) => {
            debug(`failed to connect to external signer (attempt ${tryCount}, error: ${err.message})`);
        });
        return result;
    };
}
exports.createCustomKShareGenerator = createCustomKShareGenerator;
function createCustomMuDeltaShareGenerator(externalSignerUrl, coin) {
    return async function (params) {
        const { body: result } = await (0, retryPromise_1.retryPromise)(() => superagent.post(`${externalSignerUrl}/api/v2/${coin}/tssshare/MuDelta`).type('json').send(params), (err, tryCount) => {
            debug(`failed to connect to external signer (attempt ${tryCount}, error: ${err.message})`);
        });
        return result;
    };
}
exports.createCustomMuDeltaShareGenerator = createCustomMuDeltaShareGenerator;
function createCustomSShareGenerator(externalSignerUrl, coin) {
    return async function (params) {
        const { body: result } = await (0, retryPromise_1.retryPromise)(() => superagent.post(`${externalSignerUrl}/api/v2/${coin}/tssshare/S`).type('json').send(params), (err, tryCount) => {
            debug(`failed to connect to external signer (attempt ${tryCount}, error: ${err.message})`);
        });
        return result;
    };
}
exports.createCustomSShareGenerator = createCustomSShareGenerator;
function createCustomCommitmentGenerator(externalSignerUrl, coin) {
    return async function (params) {
        const { body: result } = await (0, retryPromise_1.retryPromise)(() => superagent.post(`${externalSignerUrl}/api/v2/${coin}/tssshare/commitment`).type('json').send(params), (err, tryCount) => {
            debug(`failed to connect to external signer (attempt ${tryCount}, error: ${err.message})`);
        });
        return result;
    };
}
exports.createCustomCommitmentGenerator = createCustomCommitmentGenerator;
function createCustomRShareGenerator(externalSignerUrl, coin) {
    return async function (params) {
        const { body: rShare } = await (0, retryPromise_1.retryPromise)(() => superagent.post(`${externalSignerUrl}/api/v2/${coin}/tssshare/R`).type('json').send(params), (err, tryCount) => {
            debug(`failed to connect to external signer (attempt ${tryCount}, error: ${err.message})`);
        });
        return rShare;
    };
}
exports.createCustomRShareGenerator = createCustomRShareGenerator;
function createCustomGShareGenerator(externalSignerUrl, coin) {
    return async function (params) {
        const { body: signedTx } = await (0, retryPromise_1.retryPromise)(() => superagent.post(`${externalSignerUrl}/api/v2/${coin}/tssshare/G`).type('json').send(params), (err, tryCount) => {
            debug(`failed to connect to external signer (attempt ${tryCount}, error: ${err.message})`);
        });
        return signedTx;
    };
}
exports.createCustomGShareGenerator = createCustomGShareGenerator;
function createCustomMPCv2SigningRound1Generator(externalSignerUrl, coin) {
    return async function (params) {
        const { body: result } = await (0, retryPromise_1.retryPromise)(() => superagent.post(`${externalSignerUrl}/api/v2/${coin}/tssshare/MPCv2Round1`).type('json').send(params), (err, tryCount) => {
            debug(`failed to connect to external signer (attempt ${tryCount}, error: ${err.message})`);
        });
        return result;
    };
}
exports.createCustomMPCv2SigningRound1Generator = createCustomMPCv2SigningRound1Generator;
function createCustomMPCv2SigningRound2Generator(externalSignerUrl, coin) {
    return async function (params) {
        const { body: result } = await (0, retryPromise_1.retryPromise)(() => superagent.post(`${externalSignerUrl}/api/v2/${coin}/tssshare/MPCv2Round2`).type('json').send(params), (err, tryCount) => {
            debug(`failed to connect to external signer (attempt ${tryCount}, error: ${err.message})`);
        });
        return result;
    };
}
exports.createCustomMPCv2SigningRound2Generator = createCustomMPCv2SigningRound2Generator;
function createCustomMPCv2SigningRound3Generator(externalSignerUrl, coin) {
    return async function (params) {
        const { body: result } = await (0, retryPromise_1.retryPromise)(() => superagent.post(`${externalSignerUrl}/api/v2/${coin}/tssshare/MPCv2Round3`).type('json').send(params), (err, tryCount) => {
            debug(`failed to connect to external signer (attempt ${tryCount}, error: ${err.message})`);
        });
        return result;
    };
}
exports.createCustomMPCv2SigningRound3Generator = createCustomMPCv2SigningRound3Generator;
function setupAPIRoutes(app, config) {
    // When adding new routes to BitGo Express make sure that you also add the exact same routes to the server. Since
    // some customers were confused when calling a BitGo Express route on the BitGo server, we now handle all BitGo
    // Express routes on the BitGo server and return an error message that says that one should call BitGo Express
    // instead.
    // V1 routes should be added to www/config/routes.js
    // V2 routes should be added to www/config/routesV2.js
    // ping
    // /api/v[12]/pingexpress is the only exception to the rule above, as it explicitly checks the health of the
    // express server without running into rate limiting with the BitGo server.
    app.get('/api/v[12]/ping', prepareBitGo(config), promiseWrapper(handlePing));
    app.get('/api/v[12]/pingexpress', promiseWrapper(handlePingExpress));
    // auth
    app.post('/api/v[12]/user/login', parseBody, prepareBitGo(config), promiseWrapper(handleLogin));
    app.post('/api/v[12]/decrypt', parseBody, prepareBitGo(config), promiseWrapper(handleDecrypt));
    app.post('/api/v[12]/encrypt', parseBody, prepareBitGo(config), promiseWrapper(handleEncrypt));
    app.post('/api/v[12]/verifyaddress', parseBody, prepareBitGo(config), promiseWrapper(handleVerifyAddress));
    app.post('/api/v[12]/calculateminerfeeinfo', parseBody, prepareBitGo(config), promiseWrapper(handleCalculateMinerFeeInfo));
    app.post('/api/v1/keychain/local', parseBody, prepareBitGo(config), promiseWrapper(handleCreateLocalKeyChain));
    app.post('/api/v1/keychain/derive', parseBody, prepareBitGo(config), promiseWrapper(handleDeriveLocalKeyChain));
    app.post('/api/v1/wallets/simplecreate', parseBody, prepareBitGo(config), promiseWrapper(handleCreateWalletWithKeychains));
    app.post('/api/v1/wallet/:id/sendcoins', parseBody, prepareBitGo(config), promiseWrapper(handleSendCoins));
    app.post('/api/v1/wallet/:id/sendmany', parseBody, prepareBitGo(config), promiseWrapper(handleSendMany));
    app.post('/api/v1/wallet/:id/createtransaction', parseBody, prepareBitGo(config), promiseWrapper(handleCreateTransaction));
    app.post('/api/v1/wallet/:id/signtransaction', parseBody, prepareBitGo(config), promiseWrapper(handleSignTransaction));
    app.post('/api/v1/wallet/:id/simpleshare', parseBody, prepareBitGo(config), promiseWrapper(handleShareWallet));
    app.post('/api/v1/walletshare/:shareId/acceptShare', parseBody, prepareBitGo(config), promiseWrapper(handleAcceptShare));
    app.put('/api/v1/pendingapprovals/:id/express', parseBody, prepareBitGo(config), promiseWrapper(handleApproveTransaction));
    app.put('/api/v1/pendingapprovals/:id/constructTx', parseBody, prepareBitGo(config), promiseWrapper(handleConstructApprovalTx));
    app.put('/api/v1/wallet/:id/consolidateunspents', parseBody, prepareBitGo(config), promiseWrapper(handleConsolidateUnspents));
    app.put('/api/v1/wallet/:id/fanoutunspents', parseBody, prepareBitGo(config), promiseWrapper(handleFanOutUnspents));
    // any other API call
    app.use('/api/v[1]/*', parseBody, prepareBitGo(config), promiseWrapper(handleREST));
    // API v2
    // create keychain
    app.post('/api/v2/:coin/keychain/local', parseBody, prepareBitGo(config), promiseWrapper(handleV2CreateLocalKeyChain));
    // generate wallet
    app.post('/api/v2/:coin/wallet/generate', parseBody, prepareBitGo(config), promiseWrapper(handleV2GenerateWallet));
    app.put('/express/api/v2/:coin/wallet/:id', parseBody, prepareBitGo(config), promiseWrapper(handleWalletUpdate));
    // change wallet passphrase
    app.post('/api/v2/:coin/keychain/:id/changepassword', parseBody, prepareBitGo(config), promiseWrapper(handleKeychainChangePassword));
    // create address
    app.post('/api/v2/:coin/wallet/:id/address', parseBody, prepareBitGo(config), promiseWrapper(handleV2CreateAddress));
    // share wallet
    app.post('/api/v2/:coin/wallet/:id/share', parseBody, prepareBitGo(config), promiseWrapper(handleV2ShareWallet));
    app.post('/api/v2/:coin/walletshare/:id/acceptshare', parseBody, prepareBitGo(config), promiseWrapper(handleV2AcceptWalletShare));
    // sign arbitrary payloads w/ trading account key
    app.post(`/api/v2/ofc/signPayload`, parseBody, prepareBitGo(config), promiseWrapper(handleV2OFCSignPayload));
    // sign transaction
    app.post('/api/v2/:coin/signtx', parseBody, prepareBitGo(config), promiseWrapper(handleV2SignTx));
    app.post('/api/v2/:coin/wallet/:id/signtx', parseBody, prepareBitGo(config), promiseWrapper(handleV2SignTxWallet));
    app.post('/api/v2/:coin/wallet/:id/signtxtss', parseBody, prepareBitGo(config), promiseWrapper(handleV2SignTSSWalletTx));
    app.post('/api/v2/:coin/wallet/:id/recovertoken', parseBody, prepareBitGo(config), promiseWrapper(handleV2RecoverToken));
    // send transaction
    app.post('/api/v2/:coin/wallet/:id/sendcoins', parseBody, prepareBitGo(config), promiseWrapper(handleV2SendOne));
    app.post('/api/v2/:coin/wallet/:id/sendmany', parseBody, prepareBitGo(config), promiseWrapper(handleV2SendMany));
    app.post('/api/v2/:coin/wallet/:id/prebuildAndSignTransaction', parseBody, prepareBitGo(config), promiseWrapper(handleV2PrebuildAndSignTransaction));
    // token enablement
    app.post('/api/v2/:coin/wallet/:id/enableTokens', parseBody, prepareBitGo(config), promiseWrapper(handleV2EnableTokens));
    // unspent changes
    app.post('/api/v2/:coin/wallet/:id/consolidateunspents', parseBody, prepareBitGo(config), promiseWrapper(handleV2ConsolidateUnspents));
    app.post('/api/v2/:coin/wallet/:id/fanoutunspents', parseBody, prepareBitGo(config), promiseWrapper(handleV2FanOutUnspents));
    app.post('/api/v2/:coin/wallet/:id/sweep', parseBody, prepareBitGo(config), promiseWrapper(handleV2Sweep));
    // CPFP
    app.post('/api/v2/:coin/wallet/:id/acceleratetx', parseBody, prepareBitGo(config), promiseWrapper(handleV2AccelerateTransaction));
    // account-based
    app.post('/api/v2/:coin/wallet/:id/consolidateAccount', parseBody, prepareBitGo(config), promiseWrapper(handleV2ConsolidateAccount));
    // Miscellaneous
    app.post('/api/v2/:coin/canonicaladdress', parseBody, prepareBitGo(config), promiseWrapper(handleCanonicalAddress));
    app.post('/api/v2/:coin/verifyaddress', parseBody, prepareBitGo(config), promiseWrapper(handleV2VerifyAddress));
    app.put('/api/v2/:coin/pendingapprovals/:id', parseBody, prepareBitGo(config), promiseWrapper(handleV2PendingApproval));
    // lightning - pay invoice
    app.post('/api/v2/:coin/wallet/:id/lightning/payment', parseBody, prepareBitGo(config), promiseWrapper(lightningInvoiceRoutes_1.handlePayLightningInvoice));
    // lightning - onchain withdrawal
    app.post('/api/v2/:coin/wallet/:id/lightning/withdraw', parseBody, prepareBitGo(config), promiseWrapper(lightningWithdrawRoutes_1.handleLightningWithdraw));
    // any other API v2 call
    app.use('/api/v2/user/*', parseBody, prepareBitGo(config), promiseWrapper(handleV2UserREST));
    app.use('/api/v2/:coin/*', parseBody, prepareBitGo(config), promiseWrapper(handleV2CoinSpecificREST));
    app.post('/api/network/v1/enterprises/:enterpriseId/clients/connections', parseBody, prepareBitGo(config), promiseWrapper(handleNetworkV1EnterpriseClientConnections));
    // everything else should use the proxy handler
    if (config.disableProxy !== true) {
        app.use('/api/:namespace/v[12]/enterprises/:enterpriseId/*', parseBody, prepareBitGo(config), promiseWrapper(handleProxyReq));
        app.use(parseBody, prepareBitGo(config), promiseWrapper(handleProxyReq));
    }
}
exports.setupAPIRoutes = setupAPIRoutes;
function setupSigningRoutes(app, config) {
    app.post('/api/v2/:coin/sign', parseBody, prepareBitGo(config), promiseWrapper(handleV2Sign));
    app.post('/api/v2/:coin/tssshare/:sharetype', parseBody, prepareBitGo(config), promiseWrapper(handleV2GenerateShareTSS));
    app.post(`/api/v2/ofc/signPayload`, parseBody, prepareBitGo(config), promiseWrapper(handleV2OFCSignPayloadInExtSigningMode));
}
exports.setupSigningRoutes = setupSigningRoutes;
function setupLightningSignerNodeRoutes(app, config) {
    app.post('/api/v2/:coin/wallet/:id/initwallet', parseBody, prepareBitGo(config), promiseWrapper(lightningSignerRoutes_1.handleInitLightningWallet));
    app.post('/api/v2/:coin/wallet/:id/signermacaroon', parseBody, prepareBitGo(config), promiseWrapper(lightningSignerRoutes_1.handleCreateSignerMacaroon));
    app.post('/api/v2/:coin/wallet/:id/unlockwallet', parseBody, prepareBitGo(config), promiseWrapper(lightningSignerRoutes_1.handleUnlockLightningWallet));
    app.get('/api/v2/:coin/wallet/:id/state', prepareBitGo(config), promiseWrapper(lightningSignerRoutes_1.handleGetLightningWalletState));
}
exports.setupLightningSignerNodeRoutes = setupLightningSignerNodeRoutes;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50Um91dGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaWVudFJvdXRlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQTs7R0FFRztBQUNILDhDQTRCeUI7QUFDekIsaUNBQXNIO0FBQ3RILDBDQUEwQztBQUMxQyxrQ0FBa0M7QUFHbEMsNEJBQTRCO0FBQzVCLDJCQUEyQjtBQUMzQix5Q0FBeUM7QUFFekMsNEVBQTRFO0FBQzVFLGtEQUFrRDtBQUNsRCwwREFBZ0U7QUFHaEUscUNBQTRDO0FBQzVDLDJCQUFvQztBQUNwQyxpREFBOEM7QUFDOUMsNkVBSzJDO0FBQzNDLCtFQUErRTtBQUMvRSw2RUFBNEY7QUFDNUYsNkNBQXlDO0FBQ3pDLGtFQUFnRTtBQUNoRSxpRkFBOEU7QUFFOUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0FBQ2xELE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBQ3pDLE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQztBQUV4QyxNQUFNLHVCQUF1QixHQUFHLGdCQUFnQixLQUFLLENBQUMsT0FBTyxZQUFZLE9BQU8sRUFBRSxDQUFDO0FBRW5GLFNBQVMsVUFBVSxDQUFDLEdBQW9CLEVBQUUsR0FBcUIsRUFBRSxJQUEwQjtJQUN6RixPQUFPLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDMUIsQ0FBQztBQUVELFNBQVMsaUJBQWlCLENBQUMsR0FBb0I7SUFDN0MsT0FBTztRQUNMLE1BQU0sRUFBRSx1QkFBdUI7S0FDaEMsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFTLFdBQVcsQ0FBQyxHQUFvQjtJQUN2QyxNQUFNLFFBQVEsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLFFBQVEsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztJQUNyRCxNQUFN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ZXJcbiAqL1xuaW1wb3J0IHtcbiAgQ29tbWl0bWVudFNoYXJlUmVjb3JkLFxuICBDcmVhdGVOZXR3b3JrQ29ubmVjdGlvblBhcmFtcyxcbiAgQ3VzdG9tQ29tbWl0bWVudEdlbmVyYXRpbmdGdW5jdGlvbixcbiAgQ3VzdG9tR1NoYXJlR2VuZXJhdGluZ0Z1bmN0aW9uLFxuICBDdXN0b21LU2hhcmVHZW5lcmF0aW5nRnVuY3Rpb24sXG4gIEN1c3RvbU1QQ3YyU2lnbmluZ1JvdW5kMUdlbmVyYXRpbmdGdW5jdGlvbixcbiAgQ3VzdG9tTVBDdjJTaWduaW5nUm91bmQyR2VuZXJhdGluZ0Z1bmN0aW9uLFxuICBDdXN0b21NUEN2MlNpZ25pbmdSb3VuZDNHZW5lcmF0aW5nRnVuY3Rpb24sXG4gIEN1c3RvbU11RGVsdGFTaGFyZUdlbmVyYXRpbmdGdW5jdGlvbixcbiAgQ3VzdG9tUGFpbGxpZXJNb2R1bHVzR2V0dGVyRnVuY3Rpb24sXG4gIEN1c3RvbVJTaGFyZUdlbmVyYXRpbmdGdW5jdGlvbixcbiAgQ3VzdG9tU1NoYXJlR2VuZXJhdGluZ0Z1bmN0aW9uLFxuICBFY2RzYU1QQ3YyVXRpbHMsXG4gIEVjZHNhVXRpbHMsXG4gIEVkZHNhVXRpbHMsXG4gIEVuY3J5cHRlZFNpZ25lclNoYXJlUmVjb3JkLFxuICBlbmNyeXB0UnNhV2l0aEFlc0djbSxcbiAgR2V0TmV0d29ya1BhcnRuZXJzUmVzcG9uc2UsXG4gIEdTaGFyZSxcbiAgTVBDVHlwZSxcbiAgU2hhcmVUeXBlLFxuICBTaWduU2hhcmUsXG4gIFNTaGFyZSxcbiAgVHNzRWNkc2FTdGVwMVJldHVybk1lc3NhZ2UsXG4gIFRzc0VjZHNhU3RlcDJSZXR1cm5NZXNzYWdlLFxuICBVbnN1cHBvcnRlZENvaW5FcnJvcixcbiAgV2FsbGV0LFxufSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuaW1wb3J0IHsgQml0R28sIEJpdEdvT3B0aW9ucywgQ29pbiwgQ3VzdG9tU2lnbmluZ0Z1bmN0aW9uLCBTaWduZWRUcmFuc2FjdGlvbiwgU2lnbmVkVHJhbnNhY3Rpb25SZXF1ZXN0IH0gZnJvbSAnYml0Z28nO1xuaW1wb3J0ICogYXMgYm9keVBhcnNlciBmcm9tICdib2R5LXBhcnNlcic7XG5pbXBvcnQgKiBhcyBkZWJ1Z0xpYiBmcm9tICdkZWJ1Zyc7XG5pbXBvcnQgKiBhcyBleHByZXNzIGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHR5cGUgeyBQYXJhbXNEaWN0aW9uYXJ5IH0gZnJvbSAnZXhwcmVzcy1zZXJ2ZS1zdGF0aWMtY29yZSc7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgKiBhcyB1cmwgZnJvbSAndXJsJztcbmltcG9ydCAqIGFzIHN1cGVyYWdlbnQgZnJvbSAnc3VwZXJhZ2VudCc7XG5cbi8vIFJlcXVlc3RUcmFjZXIgc2hvdWxkIGJlIGV4dHJhY3RlZCBpbnRvIGEgc2VwYXJhdGUgbnBtIHBhY2thZ2UgKGFsb25nIHdpdGhcbi8vIHRoZSByZXN0IG9mIHRoZSBCaXRHb0pTIEhUVFAgcmVxdWVzdCBtYWNoaW5lcnkpXG5pbXBvcnQgeyBSZXF1ZXN0VHJhY2VyIH0gZnJvbSAnYml0Z28vZGlzdC9zcmMvdjIvaW50ZXJuYWwvdXRpbCc7XG5cbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJy4vY29uZmlnJztcbmltcG9ydCB7IEFwaVJlc3BvbnNlRXJyb3IgfSBmcm9tICcuL2Vycm9ycyc7XG5pbXBvcnQgeyBwcm9taXNlcyBhcyBmcyB9IGZyb20gJ2ZzJztcbmltcG9ydCB7IHJldHJ5UHJvbWlzZSB9IGZyb20gJy4vcmV0cnlQcm9taXNlJztcbmltcG9ydCB7XG4gIGhhbmRsZUNyZWF0ZVNpZ25lck1hY2Fyb29uLFxuICBoYW5kbGVHZXRMaWdodG5pbmdXYWxsZXRTdGF0ZSxcbiAgaGFuZGxlSW5pdExpZ2h0bmluZ1dhbGxldCxcbiAgaGFuZGxlVW5sb2NrTGlnaHRuaW5nV2FsbGV0LFxufSBmcm9tICcuL2xpZ2h0bmluZy9saWdodG5pbmdTaWduZXJSb3V0ZXMnO1xuaW1wb3J0IHsgaGFuZGxlUGF5TGlnaHRuaW5nSW52b2ljZSB9IGZyb20gJy4vbGlnaHRuaW5nL2xpZ2h0bmluZ0ludm9pY2VSb3V0ZXMnO1xuaW1wb3J0IHsgaGFuZGxlVXBkYXRlTGlnaHRuaW5nV2FsbGV0Q29pblNwZWNpZmljIH0gZnJvbSAnLi9saWdodG5pbmcvbGlnaHRuaW5nV2FsbGV0Um91dGVzJztcbmltcG9ydCB7IFByb3h5QWdlbnQgfSBmcm9tICdwcm94eS1hZ2VudCc7XG5pbXBvcnQgeyBpc0xpZ2h0bmluZ0NvaW5OYW1lIH0gZnJvbSAnQGJpdGdvL2Fic3RyYWN0LWxpZ2h0bmluZyc7XG5pbXBvcnQgeyBoYW5kbGVMaWdodG5pbmdXaXRoZHJhdyB9IGZyb20gJy4vbGlnaHRuaW5nL2xpZ2h0bmluZ1dpdGhkcmF3Um91dGVzJztcblxuY29uc3QgeyB2ZXJzaW9uIH0gPSByZXF1aXJlKCdiaXRnby9wYWNrYWdlLmpzb24nKTtcbmNvbnN0IHBqc29uID0gcmVxdWlyZSgnLi4vcGFja2FnZS5qc29uJyk7XG5jb25zdCBkZWJ1ZyA9IGRlYnVnTGliKCdiaXRnbzpleHByZXNzJyk7XG5cbmNvbnN0IEJJVEdPRVhQUkVTU19VU0VSX0FHRU5UID0gYEJpdEdvRXhwcmVzcy8ke3Bqc29uLnZlcnNpb259IEJpdEdvSlMvJHt2ZXJzaW9ufWA7XG5cbmZ1bmN0aW9uIGhhbmRsZVBpbmcocmVxOiBleHByZXNzLlJlcXVlc3QsIHJlczogZXhwcmVzcy5SZXNwb25zZSwgbmV4dDogZXhwcmVzcy5OZXh0RnVuY3Rpb24pIHtcbiAgcmV0dXJuIHJlcS5iaXRnby5waW5nKCk7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZVBpbmdFeHByZXNzKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIHJldHVybiB7XG4gICAgc3RhdHVzOiAnZXhwcmVzcyBzZXJ2ZXIgaXMgb2shJyxcbiAgfTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlTG9naW4ocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgdXNlcm5hbWUgPSByZXEuYm9keS51c2VybmFtZSB8fCByZXEuYm9keS5lbWFpbDtcbiAgY29uc3QgYm9keSA9IHJlcS5ib2R5O1xuICBib2R5LnVzZXJuYW1lID0gdXNlcm5hbWU7XG4gIHJldHVybiByZXEuYml0Z28uYXV0aGVudGljYXRlKGJvZHkpO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVEZWNyeXB0KHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIHJldHVybiB7XG4gICAgZGVjcnlwdGVkOiByZXEuYml0Z28uZGVjcnlwdChyZXEuYm9keSksXG4gIH07XG59XG5cbmZ1bmN0aW9uIGhhbmRsZUVuY3J5cHQocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgcmV0dXJuIHtcbiAgICBlbmNyeXB0ZWQ6IHJlcS5iaXRnby5lbmNyeXB0KHJlcS5ib2R5KSxcbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVwcmVjYXRlZFxuICogQHBhcmFtIHJlcVxuICovXG5mdW5jdGlvbiBoYW5kbGVWZXJpZnlBZGRyZXNzKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIHJldHVybiB7XG4gICAgdmVyaWZpZWQ6IHJlcS5iaXRnby52ZXJpZnlBZGRyZXNzKHJlcS5ib2R5KSxcbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVwcmVjYXRlZFxuICogQHBhcmFtIHJlcVxuICovXG5mdW5jdGlvbiBoYW5kbGVDcmVhdGVMb2NhbEtleUNoYWluKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIHJldHVybiByZXEuYml0Z28ua2V5Y2hhaW5zKCkuY3JlYXRlKHJlcS5ib2R5KTtcbn1cblxuLyoqXG4gKiBAZGVwcmVjYXRlZFxuICogQHBhcmFtIHJlcVxuICovXG5mdW5jdGlvbiBoYW5kbGVEZXJpdmVMb2NhbEtleUNoYWluKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIHJldHVybiByZXEuYml0Z28ua2V5Y2hhaW5zKCkuZGVyaXZlTG9jYWwocmVxLmJvZHkpO1xufVxuXG4vKipcbiAqIEBkZXByZWNhdGVkXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZUNyZWF0ZVdhbGxldFdpdGhLZXljaGFpbnMocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgcmV0dXJuIHJlcS5iaXRnby53YWxsZXRzKCkuY3JlYXRlV2FsbGV0V2l0aEtleWNoYWlucyhyZXEuYm9keSk7XG59XG5cbi8qKlxuICogQGRlcHJlY2F0ZWRcbiAqIEBwYXJhbSByZXFcbiAqL1xuZnVuY3Rpb24gaGFuZGxlU2VuZENvaW5zKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIHJldHVybiByZXEuYml0Z29cbiAgICAud2FsbGV0cygpXG4gICAgLmdldCh7IGlkOiByZXEucGFyYW1zLmlkIH0pXG4gICAgLnRoZW4oZnVuY3Rpb24gKHdhbGxldCkge1xuICAgICAgcmV0dXJuIHdhbGxldC5zZW5kQ29pbnMocmVxLmJvZHkpO1xuICAgIH0pXG4gICAgLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgIGVyci5zdGF0dXMgPSA0MDA7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfSlcbiAgICAudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gJ3BlbmRpbmdBcHByb3ZhbCcpIHtcbiAgICAgICAgdGhyb3cgYXBpUmVzcG9uc2UoMjAyLCByZXN1bHQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAZGVwcmVjYXRlZFxuICogQHBhcmFtIHJlcVxuICovXG5mdW5jdGlvbiBoYW5kbGVTZW5kTWFueShyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICByZXR1cm4gcmVxLmJpdGdvXG4gICAgLndhbGxldHMoKVxuICAgIC5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KVxuICAgIC50aGVuKGZ1bmN0aW9uICh3YWxsZXQpIHtcbiAgICAgIHJldHVybiB3YWxsZXQuc2VuZE1hbnkocmVxLmJvZHkpO1xuICAgIH0pXG4gICAgLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgIGVyci5zdGF0dXMgPSA0MDA7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfSlcbiAgICAudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gJ3BlbmRpbmdBcHByb3ZhbCcpIHtcbiAgICAgICAgdGhyb3cgYXBpUmVzcG9uc2UoMjAyLCByZXN1bHQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAZGVwcmVjYXRlZFxuICogQHBhcmFtIHJlcVxuICovXG5mdW5jdGlvbiBoYW5kbGVDcmVhdGVUcmFuc2FjdGlvbihyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICByZXR1cm4gcmVxLmJpdGdvXG4gICAgLndhbGxldHMoKVxuICAgIC5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KVxuICAgIC50aGVuKGZ1bmN0aW9uICh3YWxsZXQpIHtcbiAgICAgIHJldHVybiB3YWxsZXQuY3JlYXRlVHJhbnNhY3Rpb24ocmVxLmJvZHkpO1xuICAgIH0pXG4gICAgLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgIGVyci5zdGF0dXMgPSA0MDA7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQGRlcHJlY2F0ZWRcbiAqIEBwYXJhbSByZXFcbiAqL1xuZnVuY3Rpb24gaGFuZGxlU2lnblRyYW5zYWN0aW9uKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIHJldHVybiByZXEuYml0Z29cbiAgICAud2FsbGV0cygpXG4gICAgLmdldCh7IGlkOiByZXEucGFyYW1zLmlkIH0pXG4gICAgLnRoZW4oZnVuY3Rpb24gKHdhbGxldCkge1xuICAgICAgcmV0dXJuIHdhbGxldC5zaWduVHJhbnNhY3Rpb24ocmVxLmJvZHkpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEBkZXByZWNhdGVkXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZVNoYXJlV2FsbGV0KHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIHJldHVybiByZXEuYml0Z29cbiAgICAud2FsbGV0cygpXG4gICAgLmdldCh7IGlkOiByZXEucGFyYW1zLmlkIH0pXG4gICAgLnRoZW4oZnVuY3Rpb24gKHdhbGxldCkge1xuICAgICAgcmV0dXJuIHdhbGxldC5zaGFyZVdhbGxldChyZXEuYm9keSk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQGRlcHJlY2F0ZWRcbiAqIEBwYXJhbSByZXFcbiAqL1xuZnVuY3Rpb24gaGFuZGxlQWNjZXB0U2hhcmUocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgcGFyYW1zID0gcmVxLmJvZHkgfHwge307XG4gIHBhcmFtcy53YWxsZXRTaGFyZUlkID0gcmVxLnBhcmFtcy5zaGFyZUlkO1xuICByZXR1cm4gcmVxLmJpdGdvLndhbGxldHMoKS5hY2NlcHRTaGFyZShwYXJhbXMpO1xufVxuXG4vKipcbiAqIEBkZXByZWNhdGVkXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZUFwcHJvdmVUcmFuc2FjdGlvbihyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBjb25zdCBwYXJhbXMgPSByZXEuYm9keSB8fCB7fTtcbiAgcmV0dXJuIHJlcS5iaXRnb1xuICAgIC5wZW5kaW5nQXBwcm92YWxzKClcbiAgICAuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQgfSlcbiAgICAudGhlbihmdW5jdGlvbiAocGVuZGluZ0FwcHJvdmFsKSB7XG4gICAgICBpZiAocGFyYW1zLnN0YXRlID09PSAnYXBwcm92ZWQnKSB7XG4gICAgICAgIHJldHVybiBwZW5kaW5nQXBwcm92YWwuYXBwcm92ZShwYXJhbXMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHBlbmRpbmdBcHByb3ZhbC5yZWplY3QocGFyYW1zKTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAZGVwcmVjYXRlZFxuICogQHBhcmFtIHJlcVxuICovXG5mdW5jdGlvbiBoYW5kbGVDb25zdHJ1Y3RBcHByb3ZhbFR4KHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IHBhcmFtcyA9IHJlcS5ib2R5IHx8IHt9O1xuICByZXR1cm4gcmVxLmJpdGdvXG4gICAgLnBlbmRpbmdBcHByb3ZhbHMoKVxuICAgIC5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KVxuICAgIC50aGVuKGZ1bmN0aW9uIChwZW5kaW5nQXBwcm92YWwpIHtcbiAgICAgIHJldHVybiBwZW5kaW5nQXBwcm92YWwuY29uc3RydWN0QXBwcm92YWxUeChwYXJhbXMpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEBkZXByZWNhdGVkXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZUNvbnNvbGlkYXRlVW5zcGVudHMocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgcmV0dXJuIHJlcS5iaXRnb1xuICAgIC53YWxsZXRzKClcbiAgICAuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQgfSlcbiAgICAudGhlbihmdW5jdGlvbiAod2FsbGV0KSB7XG4gICAgICByZXR1cm4gd2FsbGV0LmNvbnNvbGlkYXRlVW5zcGVudHMocmVxLmJvZHkpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEBkZXByZWNhdGVkXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZUZhbk91dFVuc3BlbnRzKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIHJldHVybiByZXEuYml0Z29cbiAgICAud2FsbGV0cygpXG4gICAgLmdldCh7IGlkOiByZXEucGFyYW1zLmlkIH0pXG4gICAgLnRoZW4oZnVuY3Rpb24gKHdhbGxldCkge1xuICAgICAgcmV0dXJuIHdhbGxldC5mYW5PdXRVbnNwZW50cyhyZXEuYm9keSk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQGRlcHJlY2F0ZWRcbiAqIEBwYXJhbSByZXFcbiAqL1xuZnVuY3Rpb24gaGFuZGxlQ2FsY3VsYXRlTWluZXJGZWVJbmZvKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIHJldHVybiByZXEuYml0Z28uY2FsY3VsYXRlTWluZXJGZWVJbmZvKHtcbiAgICBiaXRnbzogcmVxLmJpdGdvLFxuICAgIGZlZVJhdGU6IHJlcS5ib2R5LmZlZVJhdGUsXG4gICAgblAyc2hJbnB1dHM6IHJlcS5ib2R5Lm5QMnNoSW5wdXRzLFxuICAgIG5QMnBraElucHV0czogcmVxLmJvZHkublAycGtoSW5wdXRzLFxuICAgIG5QMnNoUDJ3c2hJbnB1dHM6IHJlcS5ib2R5Lm5QMnNoUDJ3c2hJbnB1dHMsXG4gICAgbk91dHB1dHM6IHJlcS5ib2R5Lm5PdXRwdXRzLFxuICB9KTtcbn1cblxuLyoqXG4gKiBCdWlsZHMgdGhlIEFQSSdzIFVSTCBzdHJpbmcsIG9wdGlvbmFsbHkgYnVpbGRpbmcgdGhlIHF1ZXJ5c3RyaW5nIGlmIHBhcmFtZXRlcnMgZXhpc3RcbiAqIEBwYXJhbSByZXFcbiAqIEByZXR1cm4ge3N0cmluZ31cbiAqL1xuZnVuY3Rpb24gY3JlYXRlQVBJUGF0aChyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBsZXQgYXBpUGF0aCA9ICcvJyArIHJlcS5wYXJhbXNbMF07XG4gIGlmICghXy5pc0VtcHR5KHJlcS5xdWVyeSkpIHtcbiAgICAvLyByZXEucGFyYW1zIGRvZXMgbm90IGNvbnRhaW4gdGhlIHF1ZXJ5c3RyaW5nLCBzbyB3ZSBtYW51YWxseSBhZGQgdGhlbSBoZXJlXG4gICAgY29uc3QgdXJsRGV0YWlscyA9IHVybC5wYXJzZShyZXEudXJsKTtcbiAgICBpZiAodXJsRGV0YWlscy5zZWFyY2gpIHtcbiAgICAgIC8vIFwic2VhcmNoXCIgaXMgdGhlIHByb3Blcmx5IFVSTCBlbmNvZGVkIHF1ZXJ5IHBhcmFtcywgcHJlZml4ZWQgd2l0aCBcIj9cIlxuICAgICAgYXBpUGF0aCArPSB1cmxEZXRhaWxzLnNlYXJjaDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGFwaVBhdGg7XG59XG5cbi8qKlxuICogaGFuZGxlIGFueSBvdGhlciBWMSBBUEkgY2FsbFxuICogQGRlcHJlY2F0ZWRcbiAqIEBwYXJhbSByZXFcbiAqIEBwYXJhbSByZXNcbiAqIEBwYXJhbSBuZXh0XG4gKi9cbmZ1bmN0aW9uIGhhbmRsZVJFU1QocmVxOiBleHByZXNzLlJlcXVlc3QsIHJlczogZXhwcmVzcy5SZXNwb25zZSwgbmV4dDogZXhwcmVzcy5OZXh0RnVuY3Rpb24pIHtcbiAgY29uc3QgbWV0aG9kID0gcmVxLm1ldGhvZDtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGJpdGdvVVJMID0gYml0Z28udXJsKGNyZWF0ZUFQSVBhdGgocmVxKSk7XG4gIHJldHVybiByZWRpcmVjdFJlcXVlc3QoYml0Z28sIG1ldGhvZCwgYml0Z29VUkwsIHJlcSwgbmV4dCk7XG59XG5cbi8qKlxuICogaGFuZGxlIGFueSBvdGhlciBWMiBBUEkgY2FsbFxuICogQHBhcmFtIHJlcVxuICogQHBhcmFtIHJlc1xuICogQHBhcmFtIG5leHRcbiAqL1xuZnVuY3Rpb24gaGFuZGxlVjJVc2VyUkVTVChyZXE6IGV4cHJlc3MuUmVxdWVzdCwgcmVzOiBleHByZXNzLlJlc3BvbnNlLCBuZXh0OiBleHByZXNzLk5leHRGdW5jdGlvbikge1xuICBjb25zdCBtZXRob2QgPSByZXEubWV0aG9kO1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgYml0Z29VUkwgPSBiaXRnby51cmwoJy91c2VyJyArIGNyZWF0ZUFQSVBhdGgocmVxKSwgMik7XG4gIHJldHVybiByZWRpcmVjdFJlcXVlc3QoYml0Z28sIG1ldGhvZCwgYml0Z29VUkwsIHJlcSwgbmV4dCk7XG59XG5cbi8qKlxuICogaGFuZGxlIHYyIGFkZHJlc3MgdmFsaWRhdGlvblxuICogQHBhcmFtIHJlcVxuICovXG5mdW5jdGlvbiBoYW5kbGVWMlZlcmlmeUFkZHJlc3MocmVxOiBleHByZXNzLlJlcXVlc3QpOiB7IGlzVmFsaWQ6IGJvb2xlYW4gfSB7XG4gIGlmICghXy5pc1N0cmluZyhyZXEuYm9keS5hZGRyZXNzKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0ZWQgYWRkcmVzcyB0byBiZSBhIHN0cmluZycpO1xuICB9XG5cbiAgaWYgKHJlcS5ib2R5LnN1cHBvcnRPbGRTY3JpcHRIYXNoVmVyc2lvbiAhPT0gdW5kZWZpbmVkICYmICFfLmlzQm9vbGVhbihyZXEuYm9keS5zdXBwb3J0T2xkU2NyaXB0SGFzaFZlcnNpb24pKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3RlZCBzdXBwb3J0T2xkU2NyaXB0SGFzaFZlcnNpb24gdG8gYmUgYSBib29sZWFuLicpO1xuICB9XG5cbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG5cbiAgaWYgKGNvaW4gaW5zdGFuY2VvZiBDb2luLkFic3RyYWN0VXR4b0NvaW4pIHtcbiAgICByZXR1cm4ge1xuICAgICAgaXNWYWxpZDogY29pbi5pc1ZhbGlkQWRkcmVzcyhyZXEuYm9keS5hZGRyZXNzLCAhIXJlcS5ib2R5LnN1cHBvcnRPbGRTY3JpcHRIYXNoVmVyc2lvbiksXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgaXNWYWxpZDogY29pbi5pc1ZhbGlkQWRkcmVzcyhyZXEuYm9keS5hZGRyZXNzKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBoYW5kbGUgYWRkcmVzcyBjYW5vbmljYWxpemF0aW9uXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZUNhbm9uaWNhbEFkZHJlc3MocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gIGlmICghWydsdGMnLCAnYmNoJywgJ2JzdiddLmluY2x1ZGVzKGNvaW4uZ2V0RmFtaWx5KCkpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdvbmx5IExpdGVjb2luL0JpdGNvaW4gQ2FzaC9CaXRjb2luIFNWIGFkZHJlc3MgY2Fub25pY2FsaXphdGlvbiBpcyBzdXBwb3J0ZWQnKTtcbiAgfVxuXG4gIGNvbnN0IGFkZHJlc3MgPSByZXEuYm9keS5hZGRyZXNzO1xuICBjb25zdCBmYWxsYmFja1ZlcnNpb24gPSByZXEuYm9keS5zY3JpcHRIYXNoVmVyc2lvbjsgLy8gZGVwcmVjYXRlXG4gIGNvbnN0IHZlcnNpb24gPSByZXEuYm9keS52ZXJzaW9uO1xuICByZXR1cm4gKGNvaW4gYXMgQ29pbi5CY2ggfCBDb2luLkJzdiB8IENvaW4uTHRjKS5jYW5vbmljYWxBZGRyZXNzKGFkZHJlc3MsIHZlcnNpb24gfHwgZmFsbGJhY2tWZXJzaW9uKTtcbn1cblxuZnVuY3Rpb24gZ2V0V2FsbGV0UHdGcm9tRW52KHdhbGxldElkOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBuYW1lID0gYFdBTExFVF8ke3dhbGxldElkfV9QQVNTUEhSQVNFYDtcbiAgY29uc3Qgd2FsbGV0UHcgPSBwcm9jZXNzLmVudltuYW1lXTtcbiAgaWYgKHdhbGxldFB3ID09PSB1bmRlZmluZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBmaW5kIHdhbGxldCBwYXNzcGhyYXNlICR7bmFtZX0gaW4gZW52aXJvbm1lbnRgKTtcbiAgfVxuICByZXR1cm4gd2FsbGV0UHc7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldEVuY3J5cHRlZFByaXZLZXkocGF0aDogc3RyaW5nLCB3YWxsZXRJZDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgcHJpdktleUZpbGUgPSBhd2FpdCBmcy5yZWFkRmlsZShwYXRoLCB7IGVuY29kaW5nOiAndXRmOCcgfSk7XG4gIGNvbnN0IGVuY3J5cHRlZFByaXZLZXkgPSBKU09OLnBhcnNlKHByaXZLZXlGaWxlKTtcbiAgaWYgKGVuY3J5cHRlZFByaXZLZXlbd2FsbGV0SWRdID09PSB1bmRlZmluZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBmaW5kIGEgZmllbGQgZm9yIHdhbGxldElkOiAke3dhbGxldElkfSBpbiAke3BhdGh9YCk7XG4gIH1cbiAgcmV0dXJuIGVuY3J5cHRlZFByaXZLZXlbd2FsbGV0SWRdO1xufVxuXG5mdW5jdGlvbiBkZWNyeXB0UHJpdktleShiZzogQml0R28sIGVuY3J5cHRlZFByaXZLZXk6IHN0cmluZywgd2FsbGV0UHc6IHN0cmluZyk6IHN0cmluZyB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGJnLmRlY3J5cHQoeyBwYXNzd29yZDogd2FsbGV0UHcsIGlucHV0OiBlbmNyeXB0ZWRQcml2S2V5IH0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciB3aGVuIHRyeWluZyB0byBkZWNyeXB0IHByaXZhdGUga2V5OiAke2V9YCk7XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZVYyR2VuZXJhdGVTaGFyZVRTUyhyZXE6IGV4cHJlc3MuUmVxdWVzdCk6IFByb21pc2U8YW55PiB7XG4gIGNvbnN0IHdhbGxldElkID0gcmVxLmJvZHkudHhSZXF1ZXN0ID8gcmVxLmJvZHkudHhSZXF1ZXN0LndhbGxldElkIDogcmVxLmJvZHkudHNzUGFyYW1zLnR4UmVxdWVzdC53YWxsZXRJZDtcbiAgaWYgKCF3YWxsZXRJZCkge1xuICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyByZXF1aXJlZCBmaWVsZDogd2FsbGV0SWQnKTtcbiAgfVxuXG4gIGNvbnN0IHdhbGxldFB3ID0gZ2V0V2FsbGV0UHdGcm9tRW52KHdhbGxldElkKTtcbiAgY29uc3QgeyBzaWduZXJGaWxlU3lzdGVtUGF0aCB9ID0gcmVxLmNvbmZpZztcblxuICBpZiAoIXNpZ25lckZpbGVTeXN0ZW1QYXRoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHJlcXVpcmVkIGNvbmZpZ3VyYXRpb246IHNpZ25lckZpbGVTeXN0ZW1QYXRoJyk7XG4gIH1cblxuICBjb25zdCBlbmNyeXB0ZWRQcml2S2V5ID0gYXdhaXQgZ2V0RW5jcnlwdGVkUHJpdktleShzaWduZXJGaWxlU3lzdGVtUGF0aCwgd2FsbGV0SWQpO1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgcHJpdktleSA9IGRlY3J5cHRQcml2S2V5KGJpdGdvLCBlbmNyeXB0ZWRQcml2S2V5LCB3YWxsZXRQdyk7XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gIHJlcS5ib2R5LnBydiA9IHByaXZLZXk7XG4gIHJlcS5ib2R5LndhbGxldFBhc3NwaHJhc2UgPSB3YWxsZXRQdztcbiAgdHJ5IHtcbiAgICBpZiAoY29pbi5nZXRNUENBbGdvcml0aG0oKSA9PT0gTVBDVHlwZS5FRERTQSkge1xuICAgICAgY29uc3QgZWRkc2FVdGlscyA9IG5ldyBFZGRzYVV0aWxzKGJpdGdvLCBjb2luKTtcbiAgICAgIHN3aXRjaCAocmVxLnBhcmFtcy5zaGFyZXR5cGUpIHtcbiAgICAgICAgY2FzZSBTaGFyZVR5cGUuQ29tbWl0bWVudDpcbiAgICAgICAgICByZXR1cm4gYXdhaXQgZWRkc2FVdGlscy5jcmVhdGVDb21taXRtZW50U2hhcmVGcm9tVHhSZXF1ZXN0KHJlcS5ib2R5KTtcbiAgICAgICAgY2FzZSBTaGFyZVR5cGUuUjpcbiAgICAgICAgICByZXR1cm4gYXdhaXQgZWRkc2FVdGlscy5jcmVhdGVSU2hhcmVGcm9tVHhSZXF1ZXN0KHJlcS5ib2R5KTtcbiAgICAgICAgY2FzZSBTaGFyZVR5cGUuRzpcbiAgICAgICAgICByZXR1cm4gYXdhaXQgZWRkc2FVdGlscy5jcmVhdGVHU2hhcmVGcm9tVHhSZXF1ZXN0KHJlcS5ib2R5KTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgU2hhcmUgdHlwZSAke3JlcS5wYXJhbXMuc2hhcmV0eXBlfSBub3Qgc3VwcG9ydGVkLCBvbmx5IGNvbW1pdG1lbnQsIEcgYW5kIFIgc2hhcmUgZ2VuZXJhdGlvbiBpcyBzdXBwb3J0ZWQuYFxuICAgICAgICAgICk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChjb2luLmdldE1QQ0FsZ29yaXRobSgpID09PSBNUENUeXBlLkVDRFNBKSB7XG4gICAgICBjb25zdCBpc01QQ3YyID0gW1xuICAgICAgICBTaGFyZVR5cGUuTVBDdjJSb3VuZDEudG9TdHJpbmcoKSxcbiAgICAgICAgU2hhcmVUeXBlLk1QQ3YyUm91bmQyLnRvU3RyaW5nKCksXG4gICAgICAgIFNoYXJlVHlwZS5NUEN2MlJvdW5kMy50b1N0cmluZygpLFxuICAgICAgXS5pbmNsdWRlcyhyZXEucGFyYW1zLnNoYXJldHlwZSk7XG5cbiAgICAgIGlmIChpc01QQ3YyKSB7XG4gICAgICAgIGNvbnN0IGVjZHNhTVBDdjJVdGlscyA9IG5ldyBFY2RzYU1QQ3YyVXRpbHMoYml0Z28sIGNvaW4pO1xuICAgICAgICBzd2l0Y2ggKHJlcS5wYXJhbXMuc2hhcmV0eXBlKSB7XG4gICAgICAgICAgY2FzZSBTaGFyZVR5cGUuTVBDdjJSb3VuZDE6XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgZWNkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDFTaGFyZShyZXEuYm9keSk7XG4gICAgICAgICAgY2FzZSBTaGFyZVR5cGUuTVBDdjJSb3VuZDI6XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgZWNkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDJTaGFyZShyZXEuYm9keSk7XG4gICAgICAgICAgY2FzZSBTaGFyZVR5cGUuTVBDdjJSb3VuZDM6XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgZWNkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDNTaGFyZShyZXEuYm9keSk7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgYFNoYXJlIHR5cGUgJHtyZXEucGFyYW1zLnNoYXJldHlwZX0gbm90IHN1cHBvcnRlZCBmb3IgTVBDdjIsIG9ubHkgTVBDdjJSb3VuZDEsIE1QQ3YyUm91bmQyIGFuZCBNUEN2MlJvdW5kMyBpcyBzdXBwb3J0ZWQuYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgZWNkc2FVdGlscyA9IG5ldyBFY2RzYVV0aWxzKGJpdGdvLCBjb2luKTtcbiAgICAgICAgc3dpdGNoIChyZXEucGFyYW1zLnNoYXJldHlwZSkge1xuICAgICAgICAgIGNhc2UgU2hhcmVUeXBlLlBhaWxsaWVyTW9kdWx1czpcbiAgICAgICAgICAgIHJldHVybiBlY2RzYVV0aWxzLmdldE9mZmxpbmVTaWduZXJQYWlsbGllck1vZHVsdXMocmVxLmJvZHkpO1xuICAgICAgICAgIGNhc2UgU2hhcmVUeXBlLks6XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgZWNkc2FVdGlscy5jcmVhdGVPZmZsaW5lS1NoYXJlKHJlcS5ib2R5KTtcbiAgICAgICAgICBjYXNlIFNoYXJlVHlwZS5NdURlbHRhOlxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGVjZHNhVXRpbHMuY3JlYXRlT2ZmbGluZU11RGVsdGFTaGFyZShyZXEuYm9keSk7XG4gICAgICAgICAgY2FzZSBTaGFyZVR5cGUuUzpcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCBlY2RzYVV0aWxzLmNyZWF0ZU9mZmxpbmVTU2hhcmUocmVxLmJvZHkpO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgIGBTaGFyZSB0eXBlICR7cmVxLnBhcmFtcy5zaGFyZXR5cGV9IG5vdCBzdXBwb3J0ZWQsIG9ubHkgUGFpbGxpZXJNb2R1bHVzLCBLLCBNVURlbHRhLCBhbmQgUyBzaGFyZSBnZW5lcmF0aW9uIGlzIHN1cHBvcnRlZC5gXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTVBDIEFsZ29yaXRobSAke2NvaW4uZ2V0TVBDQWxnb3JpdGhtKCl9IGlzIG5vdCBzdXBwb3J0ZWQuYCk7XG4gICAgfVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnNvbGUuZXJyb3IoJ2Vycm9yIHdoaWxlIHNpZ25pbmcgd2FsbGV0IHRyYW5zYWN0aW9uICcsIGVycm9yKTtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJTaWduVFNTV2FsbGV0VHgocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gIGNvbnN0IHdhbGxldCA9IGF3YWl0IGNvaW4ud2FsbGV0cygpLmdldCh7IGlkOiByZXEucGFyYW1zLmlkIH0pO1xuICB0cnkge1xuICAgIHJldHVybiBhd2FpdCB3YWxsZXQuc2lnblRyYW5zYWN0aW9uKGNyZWF0ZVRTU1NlbmRQYXJhbXMocmVxLCB3YWxsZXQpKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zb2xlLmVycm9yKCdlcnJvciB3aGlsZSBzaWduaW5nIHdhbGxldCB0cmFuc2FjdGlvbiAnLCBlcnJvcik7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuLyoqXG4gKiBUaGlzIHJvdXRlIGlzIHVzZWQgdG8gc2lnbiB3aGlsZSBleHRlcm5hbCBleHByZXNzIHNpZ25lciBpcyBlbmFibGVkXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVWMlNpZ24ocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3Qgd2FsbGV0SWQgPSByZXEuYm9keS50eFByZWJ1aWxkPy53YWxsZXRJZDtcblxuICBpZiAoIXdhbGxldElkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHJlcXVpcmVkIGZpZWxkOiB3YWxsZXRJZCcpO1xuICB9XG5cbiAgY29uc3Qgd2FsbGV0UHcgPSBnZXRXYWxsZXRQd0Zyb21FbnYod2FsbGV0SWQpO1xuICBjb25zdCB7IHNpZ25lckZpbGVTeXN0ZW1QYXRoIH0gPSByZXEuY29uZmlnO1xuXG4gIGlmICghc2lnbmVyRmlsZVN5c3RlbVBhdGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgcmVxdWlyZWQgY29uZmlndXJhdGlvbjogc2lnbmVyRmlsZVN5c3RlbVBhdGgnKTtcbiAgfVxuXG4gIGNvbnN0IGVuY3J5cHRlZFByaXZLZXkgPSBhd2FpdCBnZXRFbmNyeXB0ZWRQcml2S2V5KHNpZ25lckZpbGVTeXN0ZW1QYXRoLCB3YWxsZXRJZCk7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBsZXQgcHJpdktleSA9IGRlY3J5cHRQcml2S2V5KGJpdGdvLCBlbmNyeXB0ZWRQcml2S2V5LCB3YWxsZXRQdyk7XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gIGlmIChyZXEuYm9keS5kZXJpdmF0aW9uU2VlZCkge1xuICAgIHByaXZLZXkgPSBjb2luLmRlcml2ZUtleVdpdGhTZWVkKHsga2V5OiBwcml2S2V5LCBzZWVkOiByZXEuYm9keS5kZXJpdmF0aW9uU2VlZCB9KS5rZXk7XG4gIH1cbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgY29pbi5zaWduVHJhbnNhY3Rpb24oeyAuLi5yZXEuYm9keSwgcHJ2OiBwcml2S2V5IH0pO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnNvbGUubG9nKCdlcnJvciB3aGlsZSBzaWduaW5nIHdhbGxldCB0cmFuc2FjdGlvbiAnLCBlcnJvcik7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZVYyT0ZDU2lnblBheWxvYWRJbkV4dFNpZ25pbmdNb2RlKFxuICByZXE6IGV4cHJlc3MuUmVxdWVzdFxuKTogUHJvbWlzZTx7IHBheWxvYWQ6IHN0cmluZzsgc2lnbmF0dXJlOiBzdHJpbmcgfT4ge1xuICBjb25zdCB3YWxsZXRJZCA9IHJlcS5ib2R5LndhbGxldElkO1xuICBjb25zdCBwYXlsb2FkID0gcmVxLmJvZHkucGF5bG9hZDtcbiAgY29uc3QgYm9keVdhbGxldFBhc3NwaHJhc2UgPSByZXEuYm9keS53YWxsZXRQYXNzcGhyYXNlO1xuICBjb25zdCBvZmNDb2luTmFtZSA9ICdvZmMnO1xuXG4gIGlmICghcGF5bG9hZCkge1xuICAgIHRocm93IG5ldyBBcGlSZXNwb25zZUVycm9yKCdNaXNzaW5nIHJlcXVpcmVkIGZpZWxkOiBwYXlsb2FkJywgNDAwKTtcbiAgfVxuXG4gIGlmICghd2FsbGV0SWQpIHtcbiAgICB0aHJvdyBuZXcgQXBpUmVzcG9uc2VFcnJvcignTWlzc2luZyByZXF1aXJlZCBmaWVsZDogd2FsbGV0SWQnLCA0MDApO1xuICB9XG5cbiAgLy8gZmV0Y2ggdGhlIHBhc3N3b3JkIGZvciB0aGUgZ2l2ZW4gd2FsbGV0SWQgZnJvbSB0aGUgYm9keSBvciB0aGUgZW52LiBUaGlzIGlzIHJlcXVpcmVkIGZvciBkZWNyeXB0aW5nIHRoZSBwcml2YXRlIGtleSB0aGF0IGJlbG9uZ3MgdG8gdGhhdCB3YWxsZXQuXG4gIGNvbnN0IHdhbGxldFB3ID0gYm9keVdhbGxldFBhc3NwaHJhc2UgfHwgZ2V0V2FsbGV0UHdGcm9tRW52KHdhbGxldElkKTtcblxuICBjb25zdCB7IHNpZ25lckZpbGVTeXN0ZW1QYXRoIH0gPSByZXEuY29uZmlnO1xuICBpZiAoIXNpZ25lckZpbGVTeXN0ZW1QYXRoKSB7XG4gICAgdGhyb3cgbmV3IEFwaVJlc3BvbnNlRXJyb3IoJ01pc3NpbmcgcmVxdWlyZWQgY29uZmlndXJhdGlvbjogc2lnbmVyRmlsZVN5c3RlbVBhdGgnLCA1MDApO1xuICB9XG4gIC8vIGdldCB0aGUgZW5jcnlwdGVkIHByaXZhdGUga2V5IGZyb20gdGhlIGxvY2FsIEpTT04gZmlsZSAoZW5jcnlwdGVkUHJpdktleXMuanNvbikgKHBvcHVsYXRlZCB1c2luZyBmZXRjaEVuY3J5cHRlZFByaXZhdGVLZXlzLnRzKVxuICBjb25zdCBlbmNyeXB0ZWRQcml2S2V5ID0gYXdhaXQgZ2V0RW5jcnlwdGVkUHJpdktleShzaWduZXJGaWxlU3lzdGVtUGF0aCwgd2FsbGV0SWQpO1xuXG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuXG4gIC8vIGRlY3J5cHQgdGhlIGVuY3J5cHRlZCBwcml2YXRlIGtleSB1c2luZyB0aGUgd2FsbGV0IHB3ZFxuICBjb25zdCBwcml2S2V5ID0gZGVjcnlwdFByaXZLZXkoYml0Z28sIGVuY3J5cHRlZFByaXZLZXksIHdhbGxldFB3KTtcblxuICAvLyBjcmVhdGUgYSBCYXNlQ29pbiBpbnN0YW5jZSBmb3IgJ29mYydcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ob2ZjQ29pbk5hbWUpO1xuXG4gIC8vIHN0cmluZ2lmeSB0aGUgcGF5bG9hZCBpZiBub3QgYWxyZWFkeSBhIHN0cmluZ1xuICBjb25zdCBzdHJpbmdpZmllZFBheWxvYWQgPSB0eXBlb2YgcGF5bG9hZCA9PT0gJ3N0cmluZycgPyBwYXlsb2FkIDogSlNPTi5zdHJpbmdpZnkocGF5bG9hZCk7XG5cbiAgdHJ5IHtcbiAgICAvLyBzaWduIHRoZSBtZXNzYWdlIHVzaW5nIHRoZSBkZWNyeXB0ZWQgcHJpdmF0ZSBrZXlcbiAgICBjb25zdCBzaWduYXR1cmUgPSAoYXdhaXQgY29pbi5zaWduTWVzc2FnZSh7IHBydjogcHJpdktleSB9LCBzdHJpbmdpZmllZFBheWxvYWQpKS50b1N0cmluZygnaGV4Jyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHBheWxvYWQ6IHN0cmluZ2lmaWVkUGF5bG9hZCxcbiAgICAgIHNpZ25hdHVyZSxcbiAgICB9O1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnNvbGUubG9nKCdFcnJvciB3aGlsZSBzaWduaW5nIG1lc3NhZ2UuJywgZXJyb3IpO1xuICAgIHRocm93IGVycm9yO1xuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVWMk9GQ1NpZ25QYXlsb2FkKHJlcTogZXhwcmVzcy5SZXF1ZXN0KTogUHJvbWlzZTx7IHBheWxvYWQ6IHN0cmluZzsgc2lnbmF0dXJlOiBzdHJpbmcgfT4ge1xuICBjb25zdCB3YWxsZXRJZCA9IHJlcS5ib2R5LndhbGxldElkO1xuICBjb25zdCBwYXlsb2FkID0gcmVxLmJvZHkucGF5bG9hZDtcbiAgY29uc3QgYm9keVdhbGxldFBhc3NwaHJhc2UgPSByZXEuYm9keS53YWxsZXRQYXNzcGhyYXNlO1xuICBjb25zdCBvZmNDb2luTmFtZSA9ICdvZmMnO1xuXG4gIC8vIElmIHRoZSBleHRlcm5hbFNpZ25lclVybCBpcyBzZXQsIGZvcndhcmQgdGhlIHJlcXVlc3QgdG8gdGhlIGV4cHJlc3Mgc2VydmVyIGhvc3RlZCBvbiB0aGUgZXh0ZXJuYWxTaWduZXJVcmxcbiAgY29uc3QgZXh0ZXJuYWxTaWduZXJVcmwgPSByZXEuY29uZmlnPy5leHRlcm5hbFNpZ25lclVybDtcbiAgaWYgKGV4dGVybmFsU2lnbmVyVXJsKSB7XG4gICAgY29uc3QgeyBib2R5OiBwYXlsb2FkV2l0aFNpZ25hdHVyZSB9ID0gYXdhaXQgcmV0cnlQcm9taXNlKFxuICAgICAgKCkgPT5cbiAgICAgICAgc3VwZXJhZ2VudFxuICAgICAgICAgIC5wb3N0KGAke2V4dGVybmFsU2lnbmVyVXJsfS9hcGkvdjIvb2ZjL3NpZ25QYXlsb2FkYClcbiAgICAgICAgICAudHlwZSgnanNvbicpXG4gICAgICAgICAgLnNlbmQoeyB3YWxsZXRJZDogd2FsbGV0SWQsIHBheWxvYWQ6IHBheWxvYWQgfSksXG4gICAgICAoZXJyLCB0cnlDb3VudCkgPT4ge1xuICAgICAgICBkZWJ1ZyhgZmFpbGVkIHRvIGNvbm5lY3QgdG8gZXh0ZXJuYWwgc2lnbmVyIChhdHRlbXB0ICR7dHJ5Q291bnR9LCBlcnJvcjogJHtlcnIubWVzc2FnZX0pYCk7XG4gICAgICB9XG4gICAgKTtcbiAgICByZXR1cm4gcGF5bG9hZFdpdGhTaWduYXR1cmU7XG4gIH1cblxuICBpZiAoIXBheWxvYWQpIHtcbiAgICB0aHJvdyBuZXcgQXBpUmVzcG9uc2VFcnJvcignTWlzc2luZyByZXF1aXJlZCBmaWVsZDogcGF5bG9hZCcsIDQwMCk7XG4gIH1cblxuICBpZiAoIXdhbGxldElkKSB7XG4gICAgdGhyb3cgbmV3IEFwaVJlc3BvbnNlRXJyb3IoJ01pc3NpbmcgcmVxdWlyZWQgZmllbGQ6IHdhbGxldElkJywgNDAwKTtcbiAgfVxuXG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuXG4gIC8vIFRoaXMgaXMgdG8gc2V0IHVzIHVwIGZvciBtdWx0aXBsZSB0cmFkaW5nIGFjY291bnRzIHBlciBlbnRlcnByaXNlXG4gIGNvbnN0IHdhbGxldCA9IGF3YWl0IGJpdGdvLmNvaW4ob2ZjQ29pbk5hbWUpLndhbGxldHMoKS5nZXQoeyBpZDogd2FsbGV0SWQgfSk7XG5cbiAgaWYgKHdhbGxldCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IEFwaVJlc3BvbnNlRXJyb3IoYENvdWxkIG5vdCBmaW5kIE9GQyB3YWxsZXQgJHt3YWxsZXRJZH1gLCA0MDQpO1xuICB9XG5cbiAgY29uc3Qgd2FsbGV0UGFzc3BocmFzZSA9IGJvZHlXYWxsZXRQYXNzcGhyYXNlIHx8IGdldFdhbGxldFB3RnJvbUVudih3YWxsZXQuaWQoKSk7XG4gIGNvbnN0IHRyYWRpbmdBY2NvdW50ID0gd2FsbGV0LnRvVHJhZGluZ0FjY291bnQoKTtcbiAgY29uc3Qgc3RyaW5naWZpZWRQYXlsb2FkID0gSlNPTi5zdHJpbmdpZnkocmVxLmJvZHkucGF5bG9hZCk7XG4gIGNvbnN0IHNpZ25hdHVyZSA9IGF3YWl0IHRyYWRpbmdBY2NvdW50LnNpZ25QYXlsb2FkKHtcbiAgICBwYXlsb2FkOiBzdHJpbmdpZmllZFBheWxvYWQsXG4gICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgfSk7XG4gIHJldHVybiB7XG4gICAgcGF5bG9hZDogc3RyaW5naWZpZWRQYXlsb2FkLFxuICAgIHNpZ25hdHVyZSxcbiAgfTtcbn1cblxuLyoqXG4gKiBoYW5kbGUgbmV3IHdhbGxldCBjcmVhdGlvblxuICogQHBhcmFtIHJlcVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJHZW5lcmF0ZVdhbGxldChyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29pbi53YWxsZXRzKCkuZ2VuZXJhdGVXYWxsZXQocmVxLmJvZHkpO1xuICBpZiAocmVxLnF1ZXJ5LmluY2x1ZGVLZXljaGFpbnMgPT09ICdmYWxzZScpIHtcbiAgICByZXR1cm4gcmVzdWx0LndhbGxldC50b0pTT04oKTtcbiAgfVxuICByZXR1cm4geyAuLi5yZXN1bHQsIHdhbGxldDogcmVzdWx0LndhbGxldC50b0pTT04oKSB9O1xufVxuXG4vKipcbiAqIGhhbmRsZSBuZXcgYWRkcmVzcyBjcmVhdGlvblxuICogQHBhcmFtIHJlcVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJDcmVhdGVBZGRyZXNzKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICBjb25zdCB3YWxsZXQgPSBhd2FpdCBjb2luLndhbGxldHMoKS5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KTtcbiAgcmV0dXJuIHdhbGxldC5jcmVhdGVBZGRyZXNzKHJlcS5ib2R5KTtcbn1cblxuLyoqXG4gKiBoYW5kbGUgdjIgYXBwcm92ZSB0cmFuc2FjdGlvblxuICogQHBhcmFtIHJlcVxuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVWMlBlbmRpbmdBcHByb3ZhbChyZXE6IGV4cHJlc3MuUmVxdWVzdCk6IFByb21pc2U8YW55PiB7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICBjb25zdCBwYXJhbXMgPSByZXEuYm9keSB8fCB7fTtcbiAgY29uc3QgcGVuZGluZ0FwcHJvdmFsID0gYXdhaXQgY29pbi5wZW5kaW5nQXBwcm92YWxzKCkuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQgfSk7XG4gIGlmIChwYXJhbXMuc3RhdGUgPT09ICdhcHByb3ZlZCcpIHtcbiAgICByZXR1cm4gcGVuZGluZ0FwcHJvdmFsLmFwcHJvdmUocGFyYW1zKTtcbiAgfVxuICByZXR1cm4gcGVuZGluZ0FwcHJvdmFsLnJlamVjdChwYXJhbXMpO1xufVxuXG4vKipcbiAqIGNyZWF0ZSBhIGtleWNoYWluXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZVYyQ3JlYXRlTG9jYWxLZXlDaGFpbihyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcbiAgcmV0dXJuIGNvaW4ua2V5Y2hhaW5zKCkuY3JlYXRlKHJlcS5ib2R5KTtcbn1cblxuLyoqXG4gKiBoYW5kbGUgd2FsbGV0IHNoYXJlXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZVYyU2hhcmVXYWxsZXQocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gIGNvbnN0IHdhbGxldCA9IGF3YWl0IGNvaW4ud2FsbGV0cygpLmdldCh7IGlkOiByZXEucGFyYW1zLmlkIH0pO1xuICByZXR1cm4gd2FsbGV0LnNoYXJlV2FsbGV0KHJlcS5ib2R5KTtcbn1cblxuLyoqXG4gKiBoYW5kbGUgYWNjZXB0IHdhbGxldCBzaGFyZVxuICogQHBhcmFtIHJlcVxuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVWMkFjY2VwdFdhbGxldFNoYXJlKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICBjb25zdCBwYXJhbXMgPSBfLmV4dGVuZCh7fSwgcmVxLmJvZHksIHsgd2FsbGV0U2hhcmVJZDogcmVxLnBhcmFtcy5pZCB9KTtcbiAgcmV0dXJuIGNvaW4ud2FsbGV0cygpLmFjY2VwdFNoYXJlKHBhcmFtcyk7XG59XG5cbi8qKlxuICogaGFuZGxlIHdhbGxldCBzaWduIHRyYW5zYWN0aW9uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZVYyU2lnblR4V2FsbGV0KHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICBjb25zdCB3YWxsZXQgPSBhd2FpdCBjb2luLndhbGxldHMoKS5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KTtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgd2FsbGV0LnNpZ25UcmFuc2FjdGlvbihjcmVhdGVTZW5kUGFyYW1zKHJlcSkpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnNvbGUubG9nKCdlcnJvciB3aGlsZSBzaWduaW5nIHdhbGxldCB0cmFuc2FjdGlvbiAnLCBlcnJvcik7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuLyoqXG4gKiBoYW5kbGUgc2lnbiB0cmFuc2FjdGlvblxuICogQHBhcmFtIHJlcVxuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVWMlNpZ25UeChyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgY29pbi5zaWduVHJhbnNhY3Rpb24ocmVxLmJvZHkpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnNvbGUubG9nKCdlcnJvciB3aGlsZSBzaWduaW5nIHRoZSB0cmFuc2FjdGlvbiAnLCBlcnJvcik7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuLyoqXG4gKiBoYW5kbGUgd2FsbGV0IHJlY292ZXIgdG9rZW5cbiAqIEBwYXJhbSByZXFcbiAqL1xuYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJSZWNvdmVyVG9rZW4ocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG5cbiAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgY29pbi53YWxsZXRzKCkuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQgfSk7XG4gIHJldHVybiB3YWxsZXQucmVjb3ZlclRva2VuKHJlcS5ib2R5KTtcbn1cblxuLyoqXG4gKiBoYW5kbGUgd2FsbGV0IGZhbm91dCB1bnNwZW50c1xuICogQHBhcmFtIHJlcVxuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVWMkNvbnNvbGlkYXRlVW5zcGVudHMocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gIGNvbnN0IHdhbGxldCA9IGF3YWl0IGNvaW4ud2FsbGV0cygpLmdldCh7IGlkOiByZXEucGFyYW1zLmlkIH0pO1xuICByZXR1cm4gd2FsbGV0LmNvbnNvbGlkYXRlVW5zcGVudHMoY3JlYXRlU2VuZFBhcmFtcyhyZXEpKTtcbn1cblxuLyoqXG4gKiBIYW5kbGUgV2FsbGV0IEFjY291bnQgQ29uc29saWRhdGlvbi5cbiAqXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVWMkNvbnNvbGlkYXRlQWNjb3VudChyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcblxuICBpZiAocmVxLmJvZHkuY29uc29saWRhdGVBZGRyZXNzZXMgJiYgIV8uaXNBcnJheShyZXEuYm9keS5jb25zb2xpZGF0ZUFkZHJlc3NlcykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvbnNvbGlkYXRlIGFkZHJlc3MgbXVzdCBiZSBhbiBhcnJheSBvZiBhZGRyZXNzZXMnKTtcbiAgfVxuXG4gIGlmICghY29pbi5hbGxvd3NBY2NvdW50Q29uc29saWRhdGlvbnMoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBjb2luIHNlbGVjdGVkJyk7XG4gIH1cblxuICBjb25zdCB3YWxsZXQgPSBhd2FpdCBjb2luLndhbGxldHMoKS5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KTtcblxuICBsZXQgcmVzdWx0OiBhbnk7XG4gIHRyeSB7XG4gICAgaWYgKGNvaW4uc3VwcG9ydHNUc3MoKSkge1xuICAgICAgcmVzdWx0ID0gYXdhaXQgd2FsbGV0LnNlbmRBY2NvdW50Q29uc29saWRhdGlvbnMoY3JlYXRlVFNTU2VuZFBhcmFtcyhyZXEsIHdhbGxldCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCB3YWxsZXQuc2VuZEFjY291bnRDb25zb2xpZGF0aW9ucyhjcmVhdGVTZW5kUGFyYW1zKHJlcSkpO1xuICAgIH1cbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgZXJyLnN0YXR1cyA9IDQwMDtcbiAgICB0aHJvdyBlcnI7XG4gIH1cblxuICAvLyB3ZSBoYWQgZmFpbHVyZXMgdG8gaGFuZGxlXG4gIGlmIChyZXN1bHQuZmFpbHVyZS5sZW5ndGggJiYgcmVzdWx0LmZhaWx1cmUubGVuZ3RoID4gMCkge1xuICAgIGxldCBtc2cgPSAnJztcbiAgICBsZXQgc3RhdHVzID0gMjAyO1xuXG4gICAgaWYgKHJlc3VsdC5zdWNjZXNzLmxlbmd0aCAmJiByZXN1bHQuc3VjY2Vzcy5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBidXQgd2UgYWxzbyBoYWQgc3VjY2Vzc2VzXG4gICAgICBtc2cgPSBgVHJhbnNhY3Rpb25zIGZhaWxlZDogJHtyZXN1bHQuZmFpbHVyZS5sZW5ndGh9IGFuZCBzdWNjZWVkZWQ6ICR7cmVzdWx0LnN1Y2Nlc3MubGVuZ3RofWA7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIG9yIGluIHRoaXMgY2FzZSBvbmx5IGZhaWx1cmVzXG4gICAgICBzdGF0dXMgPSA0MDA7XG4gICAgICBtc2cgPSBgQWxsIHRyYW5zYWN0aW9ucyBmYWlsZWRgO1xuICAgIH1cblxuICAgIHRocm93IGFwaVJlc3BvbnNlKHN0YXR1cywgcmVzdWx0LCBtc2cpO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBoYW5kbGUgd2FsbGV0IGZhbm91dCB1bnNwZW50c1xuICogQHBhcmFtIHJlcVxuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVWMkZhbk91dFVuc3BlbnRzKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICBjb25zdCB3YWxsZXQgPSBhd2FpdCBjb2luLndhbGxldHMoKS5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KTtcbiAgcmV0dXJuIHdhbGxldC5mYW5vdXRVbnNwZW50cyhjcmVhdGVTZW5kUGFyYW1zKHJlcSkpO1xufVxuXG4vKipcbiAqIGhhbmRsZSB3YWxsZXQgc3dlZXBcbiAqIEBwYXJhbSByZXFcbiAqL1xuYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJTd2VlcChyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcbiAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgY29pbi53YWxsZXRzKCkuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQgfSk7XG4gIHJldHVybiB3YWxsZXQuc3dlZXAoY3JlYXRlU2VuZFBhcmFtcyhyZXEpKTtcbn1cblxuLyoqXG4gKiBoYW5kbGUgQ1BGUCBhY2NlbGVyYXRlIHRyYW5zYWN0aW9uIGNyZWF0aW9uXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZVYyQWNjZWxlcmF0ZVRyYW5zYWN0aW9uKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICBjb25zdCB3YWxsZXQgPSBhd2FpdCBjb2luLndhbGxldHMoKS5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KTtcbiAgcmV0dXJuIHdhbGxldC5hY2NlbGVyYXRlVHJhbnNhY3Rpb24oY3JlYXRlU2VuZFBhcmFtcyhyZXEpKTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlU2VuZFBhcmFtcyhyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBpZiAocmVxLmNvbmZpZz8uZXh0ZXJuYWxTaWduZXJVcmwgIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5yZXEuYm9keSxcbiAgICAgIGN1c3RvbVNpZ25pbmdGdW5jdGlvbjogY3JlYXRlQ3VzdG9tU2lnbmluZ0Z1bmN0aW9uKHJlcS5jb25maWcuZXh0ZXJuYWxTaWduZXJVcmwpLFxuICAgIH07XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlcS5ib2R5O1xuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVRTU1NlbmRQYXJhbXMocmVxOiBleHByZXNzLlJlcXVlc3QsIHdhbGxldDogV2FsbGV0KSB7XG4gIGlmIChyZXEuY29uZmlnPy5leHRlcm5hbFNpZ25lclVybCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uc3QgY29pbiA9IHJlcS5iaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gICAgaWYgKGNvaW4uZ2V0TVBDQWxnb3JpdGhtKCkgPT09IE1QQ1R5cGUuRUREU0EpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnJlcS5ib2R5LFxuICAgICAgICBjdXN0b21Db21taXRtZW50R2VuZXJhdGluZ0Z1bmN0aW9uOiBjcmVhdGVDdXN0b21Db21taXRtZW50R2VuZXJhdG9yKFxuICAgICAgICAgIHJlcS5jb25maWcuZXh0ZXJuYWxTaWduZXJVcmwsXG4gICAgICAgICAgcmVxLnBhcmFtcy5jb2luXG4gICAgICAgICksXG4gICAgICAgIGN1c3RvbVJTaGFyZUdlbmVyYXRpbmdGdW5jdGlvbjogY3JlYXRlQ3VzdG9tUlNoYXJlR2VuZXJhdG9yKHJlcS5jb25maWcuZXh0ZXJuYWxTaWduZXJVcmwsIHJlcS5wYXJhbXMuY29pbiksXG4gICAgICAgIGN1c3RvbUdTaGFyZUdlbmVyYXRpbmdGdW5jdGlvbjogY3JlYXRlQ3VzdG9tR1NoYXJlR2VuZXJhdG9yKHJlcS5jb25maWcuZXh0ZXJuYWxTaWduZXJVcmwsIHJlcS5wYXJhbXMuY29pbiksXG4gICAgICB9O1xuICAgIH0gZWxzZSBpZiAoY29pbi5nZXRNUENBbGdvcml0aG0oKSA9PT0gTVBDVHlwZS5FQ0RTQSkge1xuICAgICAgaWYgKHdhbGxldC5fd2FsbGV0Lm11bHRpc2lnVHlwZVZlcnNpb24gPT09ICdNUEN2MicpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5yZXEuYm9keSxcbiAgICAgICAgICBjdXN0b21NUEN2MlNpZ25pbmdSb3VuZDFHZW5lcmF0aW9uRnVuY3Rpb246IGNyZWF0ZUN1c3RvbU1QQ3YyU2lnbmluZ1JvdW5kMUdlbmVyYXRvcihcbiAgICAgICAgICAgIHJlcS5jb25maWcuZXh0ZXJuYWxTaWduZXJVcmwsXG4gICAgICAgICAgICByZXEucGFyYW1zLmNvaW5cbiAgICAgICAgICApLFxuICAgICAgICAgIGN1c3RvbU1QQ3YyU2lnbmluZ1JvdW5kMkdlbmVyYXRpb25GdW5jdGlvbjogY3JlYXRlQ3VzdG9tTVBDdjJTaWduaW5nUm91bmQyR2VuZXJhdG9yKFxuICAgICAgICAgICAgcmVxLmNvbmZpZy5leHRlcm5hbFNpZ25lclVybCxcbiAgICAgICAgICAgIHJlcS5wYXJhbXMuY29pblxuICAgICAgICAgICksXG4gICAgICAgICAgY3VzdG9tTVBDdjJTaWduaW5nUm91bmQzR2VuZXJhdGlvbkZ1bmN0aW9uOiBjcmVhdGVDdXN0b21NUEN2MlNpZ25pbmdSb3VuZDNHZW5lcmF0b3IoXG4gICAgICAgICAgICByZXEuY29uZmlnLmV4dGVybmFsU2lnbmVyVXJsLFxuICAgICAgICAgICAgcmVxLnBhcmFtcy5jb2luXG4gICAgICAgICAgKSxcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgLi4ucmVxLmJvZHksXG4gICAgICAgICAgY3VzdG9tUGFpbGxpZXJNb2R1bHVzR2VuZXJhdGluZ0Z1bmN0aW9uOiBjcmVhdGVDdXN0b21QYWlsbGllck1vZHVsdXNHZXR0ZXIoXG4gICAgICAgICAgICByZXEuY29uZmlnLmV4dGVybmFsU2lnbmVyVXJsLFxuICAgICAgICAgICAgcmVxLnBhcmFtcy5jb2luXG4gICAgICAgICAgKSxcbiAgICAgICAgICBjdXN0b21LU2hhcmVHZW5lcmF0aW5nRnVuY3Rpb246IGNyZWF0ZUN1c3RvbUtTaGFyZUdlbmVyYXRvcihyZXEuY29uZmlnLmV4dGVybmFsU2lnbmVyVXJsLCByZXEucGFyYW1zLmNvaW4pLFxuICAgICAgICAgIGN1c3RvbU11RGVsdGFTaGFyZUdlbmVyYXRpbmdGdW5jdGlvbjogY3JlYXRlQ3VzdG9tTXVEZWx0YVNoYXJlR2VuZXJhdG9yKFxuICAgICAgICAgICAgcmVxLmNvbmZpZy5leHRlcm5hbFNpZ25lclVybCxcbiAgICAgICAgICAgIHJlcS5wYXJhbXMuY29pblxuICAgICAgICAgICksXG4gICAgICAgICAgY3VzdG9tU1NoYXJlR2VuZXJhdGluZ0Z1bmN0aW9uOiBjcmVhdGVDdXN0b21TU2hhcmVHZW5lcmF0b3IocmVxLmNvbmZpZy5leHRlcm5hbFNpZ25lclVybCwgcmVxLnBhcmFtcy5jb2luKSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBNUEMgQWxnb3JpdGhtICR7Y29pbi5nZXRNUENBbGdvcml0aG0oKX0gaXMgbm90IHN1cHBvcnRlZC5gKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlcS5ib2R5O1xuICB9XG59XG5cbi8qKlxuICogaGFuZGxlIHNlbmQgb25lXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZVYyU2VuZE9uZShyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcbiAgY29uc3QgcmVxSWQgPSBuZXcgUmVxdWVzdFRyYWNlcigpO1xuICBjb25zdCB3YWxsZXQgPSBhd2FpdCBjb2luLndhbGxldHMoKS5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCwgcmVxSWQgfSk7XG4gIHJlcS5ib2R5LnJlcUlkID0gcmVxSWQ7XG5cbiAgbGV0IHJlc3VsdDtcbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBhd2FpdCB3YWxsZXQuc2VuZChjcmVhdGVTZW5kUGFyYW1zKHJlcSkpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBlcnIuc3RhdHVzID0gNDAwO1xuICAgIHRocm93IGVycjtcbiAgfVxuICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gJ3BlbmRpbmdBcHByb3ZhbCcpIHtcbiAgICB0aHJvdyBhcGlSZXNwb25zZSgyMDIsIHJlc3VsdCk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBoYW5kbGUgc2VuZCBtYW55XG4gKiBAcGFyYW0gcmVxXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZVYyU2VuZE1hbnkocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gIGNvbnN0IHJlcUlkID0gbmV3IFJlcXVlc3RUcmFjZXIoKTtcbiAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgY29pbi53YWxsZXRzKCkuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQsIHJlcUlkIH0pO1xuICByZXEuYm9keS5yZXFJZCA9IHJlcUlkO1xuICBsZXQgcmVzdWx0O1xuICB0cnkge1xuICAgIGlmICh3YWxsZXQuX3dhbGxldC5tdWx0aXNpZ1R5cGUgPT09ICd0c3MnKSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCB3YWxsZXQuc2VuZE1hbnkoY3JlYXRlVFNTU2VuZFBhcmFtcyhyZXEsIHdhbGxldCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCB3YWxsZXQuc2VuZE1hbnkoY3JlYXRlU2VuZFBhcmFtcyhyZXEpKTtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGVyci5zdGF0dXMgPSA0MDA7XG4gICAgdGhyb3cgZXJyO1xuICB9XG4gIGlmIChyZXN1bHQuc3RhdHVzID09PSAncGVuZGluZ0FwcHJvdmFsJykge1xuICAgIHRocm93IGFwaVJlc3BvbnNlKDIwMiwgcmVzdWx0KTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqICBwYXlsb2FkIG1lYW50IGZvciBwcmVidWlsZEFuZFNpZ25UcmFuc2FjdGlvbigpIGluIHNkay1jb3JlIHdoaWNoXG4gKiB2YWxpZGF0ZXMgdGhlIHBheWxvYWQgYW5kIG1ha2VzIHRoZSBhcHByb3ByaWF0ZSByZXF1ZXN0IHRvIFdQIHRvXG4gKiBidWlsZCwgc2lnbiwgYW5kIHNlbmQgYSB0eC5cbiAqIC0gc2VuZHMgcmVxdWVzdCB0byBQbGF0Zm9ybSB0byBidWlsZCB0aGUgdHJhbnNhY3Rpb25cbiAqIC0gc2lnbnMgd2l0aCB1c2VyIGtleVxuICogLSByZXF1ZXN0IHNpZ25hdHVyZSBmcm9tIHRoZSBzZWNvbmQga2V5IChCaXRHbyBIU00pXG4gKiAtIHNlbmQvYnJvYWRjYXN0IHRyYW5zYWN0aW9uXG4gKiBAcGFyYW0gcmVxIHdoZXJlIHJlcS5ib2R5IGlzIHtAbGluayBQcmVidWlsZEFuZFNpZ25UcmFuc2FjdGlvbk9wdGlvbnN9XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVWMlByZWJ1aWxkQW5kU2lnblRyYW5zYWN0aW9uKHJlcTogZXhwcmVzcy5SZXF1ZXN0KTogUHJvbWlzZTxTaWduZWRUcmFuc2FjdGlvblJlcXVlc3Q+IHtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gIGNvbnN0IHJlcUlkID0gbmV3IFJlcXVlc3RUcmFjZXIoKTtcbiAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgY29pbi53YWxsZXRzKCkuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQsIHJlcUlkIH0pO1xuICByZXEuYm9keS5yZXFJZCA9IHJlcUlkO1xuICBsZXQgcmVzdWx0O1xuICB0cnkge1xuICAgIHJlc3VsdCA9IGF3YWl0IHdhbGxldC5wcmVidWlsZEFuZFNpZ25UcmFuc2FjdGlvbihjcmVhdGVTZW5kUGFyYW1zKHJlcSkpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBlcnIuc3RhdHVzID0gNDAwO1xuICAgIHRocm93IGVycjtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIEVuYWJsZXMgdG9rZW5zIG9uIGEgd2FsbGV0XG4gKiBAcGFyYW0gcmVxXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVWMkVuYWJsZVRva2VucyhyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcbiAgY29uc3QgcmVxSWQgPSBuZXcgUmVxdWVzdFRyYWNlcigpO1xuICBjb25zdCB3YWxsZXQgPSBhd2FpdCBjb2luLndhbGxldHMoKS5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCwgcmVxSWQgfSk7XG4gIHJlcS5ib2R5LnJlcUlkID0gcmVxSWQ7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHdhbGxldC5zZW5kVG9rZW5FbmFibGVtZW50cyhjcmVhdGVTZW5kUGFyYW1zKHJlcSkpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBlcnIuc3RhdHVzID0gNDAwO1xuICAgIHRocm93IGVycjtcbiAgfVxufVxuXG4vKipcbiAqIEhhbmRsZSBVcGRhdGUgV2FsbGV0XG4gKiBAcGFyYW0gcmVxXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZVdhbGxldFVwZGF0ZShyZXE6IGV4cHJlc3MuUmVxdWVzdCk6IFByb21pc2U8dW5rbm93bj4ge1xuICAvLyBJZiBpdCdzIGEgbGlnaHRuaW5nIGNvaW4sIHVzZSB0aGUgbGlnaHRuaW5nLXNwZWNpZmljIGhhbmRsZXJcbiAgaWYgKGlzTGlnaHRuaW5nQ29pbk5hbWUocmVxLnBhcmFtcy5jb2luKSkge1xuICAgIHJldHVybiBoYW5kbGVVcGRhdGVMaWdodG5pbmdXYWxsZXRDb2luU3BlY2lmaWMocmVxKTtcbiAgfVxuXG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICAvLyBGb3Igbm9uLWxpZ2h0bmluZyBjb2lucywgZGlyZWN0bHkgdXBkYXRlIHRoZSB3YWxsZXRcbiAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgY29pbi53YWxsZXRzKCkuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQgfSk7XG4gIHJldHVybiBhd2FpdCBiaXRnby5wdXQod2FsbGV0LnVybCgpKS5zZW5kKHJlcS5ib2R5KS5yZXN1bHQoKTtcbn1cblxuLyoqXG4gKiBDaGFuZ2VzIGEga2V5Y2hhaW4ncyBwYXNzcGhyYXNlLCByZS1lbmNyeXB0aW5nIHRoZSBrZXkgdG8gYSBuZXcgcGFzc3dvcmRcbiAqIEBwYXJhbSByZXFcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZUtleWNoYWluQ2hhbmdlUGFzc3dvcmQocmVxOiBleHByZXNzLlJlcXVlc3QpOiBQcm9taXNlPHVua25vd24+IHtcbiAgY29uc3QgeyBvbGRQYXNzd29yZCwgbmV3UGFzc3dvcmQsIG90cCB9ID0gcmVxLmJvZHk7XG4gIGlmICghb2xkUGFzc3dvcmQgfHwgIW5ld1Bhc3N3b3JkKSB7XG4gICAgdGhyb3cgbmV3IEFwaVJlc3BvbnNlRXJyb3IoJ01pc3NpbmcgMSBvciBtb3JlIHJlcXVpcmVkIGZpZWxkczogW29sZFBhc3N3b3JkLCBuZXdQYXNzd29yZF0nLCA0MDApO1xuICB9XG4gIGNvbnN0IHJlcUlkID0gbmV3IFJlcXVlc3RUcmFjZXIoKTtcblxuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcblxuICBpZiAob3RwKSB7XG4gICAgYXdhaXQgYml0Z28udW5sb2NrKHsgb3RwIH0pO1xuICB9XG5cbiAgY29uc3Qga2V5Y2hhaW4gPSBhd2FpdCBjb2luLmtleWNoYWlucygpLmdldCh7XG4gICAgaWQ6IHJlcS5wYXJhbXMuaWQsXG4gICAgcmVxSWQsXG4gIH0pO1xuICBpZiAoIWtleWNoYWluKSB7XG4gICAgdGhyb3cgbmV3IEFwaVJlc3BvbnNlRXJyb3IoYEtleWNoYWluICR7cmVxLnBhcmFtcy5pZH0gbm90IGZvdW5kYCwgNDA0KTtcbiAgfVxuXG4gIGNvbnN0IHVwZGF0ZWRLZXljaGFpbiA9IGNvaW4ua2V5Y2hhaW5zKCkudXBkYXRlU2luZ2xlS2V5Y2hhaW5QYXNzd29yZCh7XG4gICAga2V5Y2hhaW4sXG4gICAgb2xkUGFzc3dvcmQsXG4gICAgbmV3UGFzc3dvcmQsXG4gIH0pO1xuXG4gIHJldHVybiBiaXRnby5wdXQoY29pbi51cmwoYC9rZXkvJHt1cGRhdGVkS2V5Y2hhaW4uaWR9YCkpLnNlbmQoe1xuICAgIGVuY3J5cHRlZFBydjogdXBkYXRlZEtleWNoYWluLmVuY3J5cHRlZFBydixcbiAgfSk7XG59XG5cbi8qKlxuICogaGFuZGxlIGFueSBvdGhlciBBUEkgY2FsbFxuICogQHBhcmFtIHJlcVxuICogQHBhcmFtIHJlc1xuICogQHBhcmFtIG5leHRcbiAqL1xuZnVuY3Rpb24gaGFuZGxlVjJDb2luU3BlY2lmaWNSRVNUKHJlcTogZXhwcmVzcy5SZXF1ZXN0LCByZXM6IGV4cHJlc3MuUmVzcG9uc2UsIG5leHQ6IGV4cHJlc3MuTmV4dEZ1bmN0aW9uKSB7XG4gIGNvbnN0IG1ldGhvZCA9IHJlcS5tZXRob2Q7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuXG4gIGRlYnVnKCdoYW5kbGluZyB2MiBjb2luIHNwZWNpZmljIHJlc3QgcmVxJyk7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICAgIGNvbnN0IGNvaW5VUkwgPSBjb2luLnVybChjcmVhdGVBUElQYXRoKHJlcSkpO1xuICAgIHJldHVybiByZWRpcmVjdFJlcXVlc3QoYml0Z28sIG1ldGhvZCwgY29pblVSTCwgcmVxLCBuZXh0KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChlIGluc3RhbmNlb2YgVW5zdXBwb3J0ZWRDb2luRXJyb3IpIHtcbiAgICAgIGNvbnN0IHF1ZXJ5UGFyYW1zID0gXy50cmFuc2Zvcm0oXG4gICAgICAgIHJlcS5xdWVyeSxcbiAgICAgICAgKGFjYzogc3RyaW5nW10sIHZhbHVlLCBrZXkpID0+IHtcbiAgICAgICAgICBmb3IgKGNvbnN0IHZhbCBvZiBfLmNhc3RBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIGFjYy5wdXNoKGAke2tleX09JHt2YWx9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBbXVxuICAgICAgKTtcbiAgICAgIGNvbnN0IGJhc2VVcmwgPSBiaXRnby51cmwocmVxLmJhc2VVcmwucmVwbGFjZSgvXlxcL2FwaVxcL3YyLywgJycpLCAyKTtcbiAgICAgIGNvbnN0IHVybCA9IF8uaXNFbXB0eShxdWVyeVBhcmFtcykgPyBiYXNlVXJsIDogYCR7YmFzZVVybH0/JHtxdWVyeVBhcmFtcy5qb2luKCcmJyl9YDtcblxuICAgICAgZGVidWcoYGNvaW4gJHtyZXEucGFyYW1zLmNvaW59IG5vdCBzdXBwb3J0ZWQsIGF0dGVtcHRpbmcgdG8gaGFuZGxlIGFzIGEgY29pbmxlc3Mgcm91dGUgd2l0aCB1cmwgJHt1cmx9YCk7XG4gICAgICByZXR1cm4gcmVkaXJlY3RSZXF1ZXN0KGJpdGdvLCBtZXRob2QsIHVybCwgcmVxLCBuZXh0KTtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbi8qKlxuICogSGFuZGxlIGFkZGl0aW9uYWwgb3B0aW9uIHRvIGVuY3J5cHQgb24gdGhlIGV4cHJlc3Mgcm91dGUgZm9yIHBhcnRuZXJzIHJlcXVpcmluZyB2YWx1ZSBlbmNyeXB0aW9uXG4gKiBAcGFyYW0gcmVxLmJvZHkuZW5jcnlwdCAtIGJvb2xlYW4gdG8gZGV0ZXJtaW5lIGlmIHRoZSByZXF1ZXN0IHNob3VsZCBoYW5kbGUgZW5jcnlwdGlvbiBvbiBiZWhhbGYgb2YgdGhlIHN1Ym1pc3Npb24uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZU5ldHdvcmtWMUVudGVycHJpc2VDbGllbnRDb25uZWN0aW9ucyhcbiAgcmVxOiBleHByZXNzLlJlcXVlc3QsXG4gIHJlczogZXhwcmVzcy5SZXNwb25zZSxcbiAgbmV4dDogZXhwcmVzcy5OZXh0RnVuY3Rpb25cbikge1xuICBkZWJ1ZygnaGFuZGxpbmcgbmV0d29yayB2MSBwYXJ0bmVyIGNvbm5lY3Rpb24gY3JlYXRpb24nKTtcblxuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgcGFyYW1zID0gcmVxLnBhcmFtcztcbiAgY29uc3QgYm9keSA9IHJlcS5ib2R5IGFzIENyZWF0ZU5ldHdvcmtDb25uZWN0aW9uUGFyYW1zICYge1xuICAgIGVuY3J5cHQ/OiBib29sZWFuO1xuICB9O1xuXG4gIGlmIChib2R5LmVuY3J5cHQgPT09IHRydWUpIHtcbiAgICBpZiAoIWJvZHkucGFydG5lcklkKSB7XG4gICAgICB0aHJvdyBuZXcgQXBpUmVzcG9uc2VFcnJvcignTWlzc2luZyByZXF1aXJlZCBmaWVsZDogcGFydG5lcklkJywgNDAwKTtcbiAgICB9XG5cbiAgICBjb25zdCBwYXJ0bmVyc1VybCA9IGJpdGdvLm1pY3Jvc2VydmljZXNVcmwoYC9hcGkvbmV0d29yay92MS9lbnRlcnByaXNlcy8ke3BhcmFtcy5lbnRlcnByaXNlSWR9L3BhcnRuZXJzYCk7XG5cbiAgICBjb25zdCByZXNwb25zZTogR2V0TmV0d29ya1BhcnRuZXJzUmVzcG9uc2UgPSBhd2FpdCBiaXRnb1xuICAgICAgLmdldChwYXJ0bmVyc1VybClcbiAgICAgIC5zZXQoJ2VudGVycHJpc2UtaWQnLCBwYXJhbXMuZW50ZXJwcmlzZUlkKVxuICAgICAgLnNlbmQoeyBpZHM6IFtwYXJhbXMucGFydG5lcklkXSB9KVxuICAgICAgLnJlc3VsdCgpO1xuXG4gICAgY29uc3QgcGFydG5lcnMgPSByZXNwb25zZS5wYXJ0bmVycztcbiAgICBjb25zdCBwYXJ0bmVyID0gcGFydG5lcnMuZmluZCgocCkgPT4gcC5pZCA9PT0gYm9keS5wYXJ0bmVySWQpO1xuXG4gICAgaWYgKCFwYXJ0bmVyKSB7XG4gICAgICB0aHJvdyBuZXcgQXBpUmVzcG9uc2VFcnJvcihgUGFydG5lciBub3QgZm91bmQgZm9yIHBhcnRuZXJJZDogJHtib2R5LnBhcnRuZXJJZH1gLCA0MDApO1xuICAgIH1cblxuICAgIGlmICghcGFydG5lci5wdWJsaWNLZXkpIHtcbiAgICAgIHRocm93IG5ldyBBcGlSZXNwb25zZUVycm9yKCdQYXJ0bmVyIGRvZXMgbm90IHJlcXVpcmUgZW5jcnlwdGlvbicsIDQwMCk7XG4gICAgfVxuXG4gICAgc3dpdGNoIChib2R5LmNvbm5lY3Rpb25LZXkuc2NoZW1hKSB7XG4gICAgICBjYXNlICd0b2tlbic6XG4gICAgICAgIHJlcS5ib2R5LmNvbm5lY3Rpb25LZXkuY29ubmVjdGlvblRva2VuID0gYXdhaXQgZW5jcnlwdFJzYVdpdGhBZXNHY20oXG4gICAgICAgICAgcGFydG5lci5wdWJsaWNLZXksXG4gICAgICAgICAgYm9keS5jb25uZWN0aW9uS2V5LmNvbm5lY3Rpb25Ub2tlblxuICAgICAgICApO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3Rva2VuQW5kU2lnbmF0dXJlJzpcbiAgICAgICAgcmVxLmJvZHkuY29ubmVjdGlvbktleS5jb25uZWN0aW9uVG9rZW4gPSBhd2FpdCBlbmNyeXB0UnNhV2l0aEFlc0djbShcbiAgICAgICAgICBwYXJ0bmVyLnB1YmxpY0tleSxcbiAgICAgICAgICBib2R5LmNvbm5lY3Rpb25LZXkuY29ubmVjdGlvblRva2VuXG4gICAgICAgICk7XG4gICAgICAgIHJlcS5ib2R5LmNvbm5lY3Rpb25LZXkuc2lnbmF0dXJlID0gYXdhaXQgZW5jcnlwdFJzYVdpdGhBZXNHY20ocGFydG5lci5wdWJsaWNLZXksIGJvZHkuY29ubmVjdGlvbktleS5zaWduYXR1cmUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2FwaUtleUFuZFNlY3JldCc6XG4gICAgICBjYXNlICdjbGVhcmxvb3AnOlxuICAgICAgICByZXEuYm9keS5jb25uZWN0aW9uS2V5LmFwaUtleSA9IGF3YWl0IGVuY3J5cHRSc2FXaXRoQWVzR2NtKHBhcnRuZXIucHVibGljS2V5LCBib2R5LmNvbm5lY3Rpb25LZXkuYXBpS2V5KTtcbiAgICAgICAgcmVxLmJvZHkuY29ubmVjdGlvbktleS5hcGlTZWNyZXQgPSBhd2FpdCBlbmNyeXB0UnNhV2l0aEFlc0djbShwYXJ0bmVyLnB1YmxpY0tleSwgYm9keS5jb25uZWN0aW9uS2V5LmFwaVNlY3JldCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBoYW5kbGVQcm94eVJlcShyZXEsIHJlcywgbmV4dCk7XG59XG5cbi8qKlxuICogUmVkaXJlY3QgYSByZXF1ZXN0IHVzaW5nIHRoZSBiaXRnbyByZXF1ZXN0IGZ1bmN0aW9ucy5cbiAqIEBwYXJhbSBiaXRnb1xuICogQHBhcmFtIG1ldGhvZFxuICogQHBhcmFtIHVybFxuICogQHBhcmFtIHJlcVxuICogQHBhcmFtIG5leHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZGlyZWN0UmVxdWVzdChcbiAgYml0Z286IEJpdEdvLFxuICBtZXRob2Q6IHN0cmluZyxcbiAgdXJsOiBzdHJpbmcsXG4gIHJlcTogZXhwcmVzcy5SZXF1ZXN0LFxuICBuZXh0OiBleHByZXNzLk5leHRGdW5jdGlvblxuKSB7XG4gIGxldCByZXF1ZXN0O1xuXG4gIHN3aXRjaCAobWV0aG9kKSB7XG4gICAgY2FzZSAnR0VUJzpcbiAgICAgIHJlcXVlc3QgPSBiaXRnby5nZXQodXJsKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ1BPU1QnOlxuICAgICAgcmVxdWVzdCA9IGJpdGdvLnBvc3QodXJsKS5zZW5kKHJlcS5ib2R5KTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ1BVVCc6XG4gICAgICByZXF1ZXN0ID0gYml0Z28ucHV0KHVybCkuc2VuZChyZXEuYm9keSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdQQVRDSCc6XG4gICAgICByZXF1ZXN0ID0gYml0Z28ucGF0Y2godXJsKS5zZW5kKHJlcS5ib2R5KTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ09QVElPTlMnOlxuICAgICAgcmVxdWVzdCA9IGJpdGdvLm9wdGlvbnModXJsKS5zZW5kKHJlcS5ib2R5KTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ0RFTEVURSc6XG4gICAgICByZXF1ZXN0ID0gYml0Z28uZGVsKHVybCkuc2VuZChyZXEuYm9keSk7XG4gICAgICBicmVhaztcbiAgfVxuXG4gIGlmIChyZXF1ZXN0KSB7XG4gICAgaWYgKHJlcS5wYXJhbXMuZW50ZXJwcmlzZUlkKSB7XG4gICAgICByZXF1ZXN0LnNldCgnZW50ZXJwcmlzZS1pZCcsIHJlcS5wYXJhbXMuZW50ZXJwcmlzZUlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVxdWVzdC5yZXN1bHQoKS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgIGNvbnN0IHN0YXR1cyA9IHJlcXVlc3QucmVzPy5zdGF0dXNDb2RlIHx8IDIwMDtcbiAgICAgIHJldHVybiB7IHN0YXR1cywgYm9keTogcmVzdWx0IH07XG4gICAgfSk7XG4gIH1cblxuICAvLyBzb21ldGhpbmcgaGFzIHByZXN1bWFibHkgZ29uZSB3cm9uZ1xuICBuZXh0KCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZVByb3h5UmVxKHJlcTogZXhwcmVzcy5SZXF1ZXN0LCByZXM6IGV4cHJlc3MuUmVzcG9uc2UsIG5leHQ6IGV4cHJlc3MuTmV4dEZ1bmN0aW9uKSB7XG4gIGNvbnN0IGZ1bGxVcmwgPSByZXEuYml0Z28ubWljcm9zZXJ2aWNlc1VybChyZXEub3JpZ2luYWxVcmwpO1xuICBpZiAocmVxLnVybCAmJiAoL15cXC9hcGkuKiQvLnRlc3QocmVxLm9yaWdpbmFsVXJsKSB8fCAvXlxcL29hdXRoXFwvdG9rZW4uKiQvLnRlc3QocmVxLnVybCkpKSB7XG4gICAgcmVxLmlzUHJveHkgPSB0cnVlO1xuICAgIGRlYnVnKCdwcm94eWluZyAlcyByZXF1ZXN0IHRvICVzJywgcmVxLm1ldGhvZCwgZnVsbFVybCk7XG4gICAgcmV0dXJuIGF3YWl0IHJlZGlyZWN0UmVxdWVzdChyZXEuYml0Z28sIHJlcS5tZXRob2QsIGZ1bGxVcmwsIHJlcSwgbmV4dCk7XG4gIH1cbiAgLy8gdXNlciB0cmllZCB0byBhY2Nlc3MgYSB1cmwgd2hpY2ggaXMgbm90IGFuIGFwaSByb3V0ZSwgZG8gbm90IHByb3h5XG4gIGRlYnVnKCd1bmFibGUgdG8gcHJveHkgJXMgcmVxdWVzdCB0byAlcycsIHJlcS5tZXRob2QsIGZ1bGxVcmwpO1xuICB0aHJvdyBuZXcgQXBpUmVzcG9uc2VFcnJvcignYml0Z28tZXhwcmVzcyBjYW4gb25seSBwcm94eSBCaXRHbyBBUEkgcmVxdWVzdHMnLCA0MDQpO1xufVxuXG4vKipcbiAqXG4gKiBAcGFyYW0gc3RhdHVzXG4gKiBAcGFyYW0gcmVzdWx0XG4gKiBAcGFyYW0gbWVzc2FnZVxuICovXG5mdW5jdGlvbiBhcGlSZXNwb25zZShzdGF0dXM6IG51bWJlciwgcmVzdWx0OiBhbnksIG1lc3NhZ2U/OiBzdHJpbmcpOiBBcGlSZXNwb25zZUVycm9yIHtcbiAgcmV0dXJuIG5ldyBBcGlSZXNwb25zZUVycm9yKG1lc3NhZ2UsIHN0YXR1cywgcmVzdWx0KTtcbn1cblxuY29uc3QgZXhwcmVzc0pTT05QYXJzZXIgPSBib2R5UGFyc2VyLmpzb24oeyBsaW1pdDogJzIwbWInIH0pO1xuXG4vKipcbiAqIFBlcmZvcm0gYm9keSBwYXJzaW5nIGhlcmUgb25seSBvbiByb3V0ZXMgd2Ugd2FudFxuICovXG5mdW5jdGlvbiBwYXJzZUJvZHkocmVxOiBleHByZXNzLlJlcXVlc3QsIHJlczogZXhwcmVzcy5SZXNwb25zZSwgbmV4dDogZXhwcmVzcy5OZXh0RnVuY3Rpb24pIHtcbiAgLy8gU2V0IHRoZSBkZWZhdWx0IENvbnRlbnQtVHlwZSwgaW4gY2FzZSB0aGUgY2xpZW50IGRvZXNuJ3Qgc2V0IGl0LiAgSWZcbiAgLy8gQ29udGVudC1UeXBlIGlzbid0IHNwZWNpZmllZCwgRXhwcmVzcyBzaWxlbnRseSByZWZ1c2VzIHRvIHBhcnNlIHRoZVxuICAvLyByZXF1ZXN0IGJvZHkuXG4gIHJlcS5oZWFkZXJzWydjb250ZW50LXR5cGUnXSA9IHJlcS5oZWFkZXJzWydjb250ZW50LXR5cGUnXSB8fCAnYXBwbGljYXRpb24vanNvbic7XG4gIHJldHVybiBleHByZXNzSlNPTlBhcnNlcihyZXEsIHJlcywgbmV4dCk7XG59XG5cbi8qKlxuICogQ3JlYXRlIHRoZSBiaXRnbyBvYmplY3QgaW4gdGhlIHJlcXVlc3RcbiAqIEBwYXJhbSBjb25maWdcbiAqL1xuZnVuY3Rpb24gcHJlcGFyZUJpdEdvKGNvbmZpZzogQ29uZmlnKSB7XG4gIGNvbnN0IHsgZW52LCBjdXN0b21Sb290VXJpLCBjdXN0b21CaXRjb2luTmV0d29yayB9ID0gY29uZmlnO1xuXG4gIHJldHVybiBmdW5jdGlvbiBwcmVwQml0R28ocmVxOiBleHByZXNzLlJlcXVlc3QsIHJlczogZXhwcmVzcy5SZXNwb25zZSwgbmV4dDogZXhwcmVzcy5OZXh0RnVuY3Rpb24pIHtcbiAgICAvLyBHZXQgYWNjZXNzIHRva2VuXG4gICAgbGV0IGFjY2Vzc1Rva2VuO1xuICAgIGlmIChyZXEuaGVhZGVycy5hdXRob3JpemF0aW9uKSB7XG4gICAgICBjb25zdCBhdXRoU3BsaXQgPSByZXEuaGVhZGVycy5hdXRob3JpemF0aW9uLnNwbGl0KCcgJyk7XG4gICAgICBpZiAoYXV0aFNwbGl0Lmxlbmd0aCA9PT0gMiAmJiBhdXRoU3BsaXRbMF0udG9Mb3dlckNhc2UoKSA9PT0gJ2JlYXJlcicpIHtcbiAgICAgICAgYWNjZXNzVG9rZW4gPSBhdXRoU3BsaXRbMV07XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IHVzZXJBZ2VudCA9IHJlcS5oZWFkZXJzWyd1c2VyLWFnZW50J11cbiAgICAgID8gQklUR09FWFBSRVNTX1VTRVJfQUdFTlQgKyAnICcgKyByZXEuaGVhZGVyc1sndXNlci1hZ2VudCddXG4gICAgICA6IEJJVEdPRVhQUkVTU19VU0VSX0FHRU5UO1xuXG4gICAgY29uc3QgdXNlUHJveHlVcmwgPSBwcm9jZXNzLmVudi5CSVRHT19VU0VfUFJPWFk7XG4gICAgY29uc3QgYml0Z29Db25zdHJ1Y3RvclBhcmFtczogQml0R29PcHRpb25zID0ge1xuICAgICAgZW52LFxuICAgICAgY3VzdG9tUm9vdFVSSTogY3VzdG9tUm9vdFVyaSxcbiAgICAgIGN1c3RvbUJpdGNvaW5OZXR3b3JrLFxuICAgICAgYWNjZXNzVG9rZW4sXG4gICAgICB1c2VyQWdlbnQsXG4gICAgICAuLi4odXNlUHJveHlVcmxcbiAgICAgICAgPyB7XG4gICAgICAgICAgICBjdXN0b21Qcm94eUFnZW50OiBuZXcgUHJveHlBZ2VudCh7XG4gICAgICAgICAgICAgIGdldFByb3h5Rm9yVXJsOiAoKSA9PiB1c2VQcm94eVVybCxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIH1cbiAgICAgICAgOiB7fSksXG4gICAgfTtcblxuICAgIHJlcS5iaXRnbyA9IG5ldyBCaXRHbyhiaXRnb0NvbnN0cnVjdG9yUGFyYW1zKTtcbiAgICByZXEuY29uZmlnID0gY29uZmlnO1xuXG4gICAgbmV4dCgpO1xuICB9O1xufVxudHlwZSBSZXF1ZXN0SGFuZGxlclJlc3BvbnNlID0gc3RyaW5nIHwgdW5rbm93biB8IHVuZGVmaW5lZCB8IHsgc3RhdHVzOiBudW1iZXI7IGJvZHk6IHVua25vd24gfTtcbmludGVyZmFjZSBSZXF1ZXN0SGFuZGxlciBleHRlbmRzIGV4cHJlc3MuUmVxdWVzdEhhbmRsZXI8UGFyYW1zRGljdGlvbmFyeSwgYW55LCBSZXF1ZXN0SGFuZGxlclJlc3BvbnNlPiB7XG4gIChyZXE6IGV4cHJlc3MuUmVxdWVzdCwgcmVzOiBleHByZXNzLlJlc3BvbnNlLCBuZXh0OiBleHByZXNzLk5leHRGdW5jdGlvbik6XG4gICAgfCBSZXF1ZXN0SGFuZGxlclJlc3BvbnNlXG4gICAgfCBQcm9taXNlPFJlcXVlc3RIYW5kbGVyUmVzcG9uc2U+O1xufVxuXG5mdW5jdGlvbiBoYW5kbGVSZXF1ZXN0SGFuZGxlckVycm9yKHJlczogZXhwcmVzcy5SZXNwb25zZSwgZXJyb3I6IHVua25vd24pIHtcbiAgbGV0IGVycjtcbiAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICBlcnIgPSBlcnJvcjtcbiAgfSBlbHNlIGlmICh0eXBlb2YgZXJyb3IgPT09ICdzdHJpbmcnKSB7XG4gICAgZXJyID0gbmV3IEVycm9yKCcoc3RyaW5nX2Vycm9yKSAnICsgZXJyb3IpO1xuICB9IGVsc2Uge1xuICAgIGVyciA9IG5ldyBFcnJvcignKG9iamVjdF9lcnJvcikgJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gIH1cblxuICBjb25zdCBtZXNzYWdlID0gZXJyLm1lc3NhZ2UgfHwgJ2xvY2FsIGVycm9yJztcbiAgLy8gdXNlIGF0dGFjaGVkIHJlc3VsdCwgb3IgbWFrZSBvbmVcbiAgbGV0IHJlc3VsdCA9IGVyci5yZXN1bHQgfHwgeyBlcnJvcjogbWVzc2FnZSB9O1xuICByZXN1bHQgPSBfLmV4dGVuZCh7fSwgcmVzdWx0LCB7XG4gICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgYml0Z29Kc1ZlcnNpb246IHZlcnNpb24sXG4gICAgYml0Z29FeHByZXNzVmVyc2lvbjogcGpzb24udmVyc2lvbixcbiAgfSk7XG4gIGNvbnN0IHN0YXR1cyA9IGVyci5zdGF0dXMgfHwgNTAwO1xuICBpZiAoIShzdGF0dXMgPj0gMjAwICYmIHN0YXR1cyA8IDMwMCkpIHtcbiAgICBjb25zb2xlLmxvZygnZXJyb3IgJXM6ICVzJywgc3RhdHVzLCBlcnIubWVzc2FnZSk7XG4gIH1cbiAgaWYgKHN0YXR1cyA+PSA1MDAgJiYgc3RhdHVzIDw9IDU5OSkge1xuICAgIGlmIChlcnIucmVzcG9uc2UgJiYgZXJyLnJlc3BvbnNlLnJlcXVlc3QpIHtcbiAgICAgIGNvbnNvbGUubG9nKGBmYWlsZWQgdG8gbWFrZSAke2Vyci5yZXNwb25zZS5yZXF1ZXN0Lm1ldGhvZH0gcmVxdWVzdCB0byAke2Vyci5yZXNwb25zZS5yZXF1ZXN0LnVybH1gKTtcbiAgICB9XG4gICAgY29uc29sZS5sb2coZXJyLnN0YWNrKTtcbiAgfVxuICByZXMuc3RhdHVzKHN0YXR1cykuc2VuZChyZXN1bHQpO1xufVxuXG4vKipcbiAqIFByb21pc2UgaGFuZGxlciB3cmFwcGVyIHRvIGhhbmRsZSBzZW5kaW5nIHJlc3BvbnNlcyBhbmQgZXJyb3IgY2FzZXNcbiAqIEBwYXJhbSBwcm9taXNlUmVxdWVzdEhhbmRsZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb21pc2VXcmFwcGVyKHByb21pc2VSZXF1ZXN0SGFuZGxlcjogUmVxdWVzdEhhbmRsZXIpIHtcbiAgcmV0dXJuIGFzeW5jIGZ1bmN0aW9uIHByb21XcmFwcGVyKHJlcTogZXhwcmVzcy5SZXF1ZXN0LCByZXM6IGV4cHJlc3MuUmVzcG9uc2UsIG5leHQ6IGV4cHJlc3MuTmV4dEZ1bmN0aW9uKSB7XG4gICAgZGVidWcoYGhhbmRsZTogJHtyZXEubWV0aG9kfSAke3JlcS5vcmlnaW5hbFVybH1gKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcHJvbWlzZVJlcXVlc3RIYW5kbGVyKHJlcSwgcmVzLCBuZXh0KTtcbiAgICAgIGlmICh0eXBlb2YgcmVzdWx0ID09PSAnb2JqZWN0JyAmJiByZXN1bHQgIT09IG51bGwgJiYgJ2JvZHknIGluIHJlc3VsdCAmJiAnc3RhdHVzJyBpbiByZXN1bHQpIHtcbiAgICAgICAgY29uc3QgeyBzdGF0dXMsIGJvZHkgfSA9IHJlc3VsdCBhcyB7IHN0YXR1czogbnVtYmVyOyBib2R5OiB1bmtub3duIH07XG4gICAgICAgIHJlcy5zdGF0dXMoc3RhdHVzKS5zZW5kKGJvZHkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzLnN0YXR1cygyMDApLnNlbmQocmVzdWx0KTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBoYW5kbGVSZXF1ZXN0SGFuZGxlckVycm9yKHJlcywgZSk7XG4gICAgfVxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ3VzdG9tU2lnbmluZ0Z1bmN0aW9uKGV4dGVybmFsU2lnbmVyVXJsOiBzdHJpbmcpOiBDdXN0b21TaWduaW5nRnVuY3Rpb24ge1xuICByZXR1cm4gYXN5bmMgZnVuY3Rpb24gKHBhcmFtcyk6IFByb21pc2U8U2lnbmVkVHJhbnNhY3Rpb24+IHtcbiAgICBjb25zdCB7IGJvZHk6IHNpZ25lZFR4IH0gPSBhd2FpdCByZXRyeVByb21pc2UoXG4gICAgICAoKSA9PlxuICAgICAgICBzdXBlcmFnZW50LnBvc3QoYCR7ZXh0ZXJuYWxTaWduZXJVcmx9L2FwaS92Mi8ke3BhcmFtcy5jb2luLmdldENoYWluKCl9L3NpZ25gKS50eXBlKCdqc29uJykuc2VuZCh7XG4gICAgICAgICAgdHhQcmVidWlsZDogcGFyYW1zLnR4UHJlYnVpbGQsXG4gICAgICAgICAgcHViczogcGFyYW1zLnB1YnMsXG4gICAgICAgICAgZGVyaXZhdGlvblNlZWQ6IHBhcmFtcy5kZXJpdmF0aW9uU2VlZCxcbiAgICAgICAgICBzaWduaW5nU3RlcDogcGFyYW1zLnNpZ25pbmdTdGVwLFxuICAgICAgICB9KSxcbiAgICAgIChlcnIsIHRyeUNvdW50KSA9PiB7XG4gICAgICAgIGRlYnVnKGBmYWlsZWQgdG8gY29ubmVjdCB0byBleHRlcm5hbCBzaWduZXIgKGF0dGVtcHQgJHt0cnlDb3VudH0sIGVycm9yOiAke2Vyci5tZXNzYWdlfSlgKTtcbiAgICAgIH1cbiAgICApO1xuICAgIHJldHVybiBzaWduZWRUeDtcbiAgfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDdXN0b21QYWlsbGllck1vZHVsdXNHZXR0ZXIoXG4gIGV4dGVybmFsU2lnbmVyVXJsOiBzdHJpbmcsXG4gIGNvaW46IHN0cmluZ1xuKTogQ3VzdG9tUGFpbGxpZXJNb2R1bHVzR2V0dGVyRnVuY3Rpb24ge1xuICByZXR1cm4gYXN5bmMgZnVuY3Rpb24gKHBhcmFtcyk6IFByb21pc2U8e1xuICAgIHVzZXJQYWlsbGllck1vZHVsdXM6IHN0cmluZztcbiAgfT4ge1xuICAgIGNvbnN0IHsgYm9keTogcmVzdWx0IH0gPSBhd2FpdCByZXRyeVByb21pc2UoXG4gICAgICAoKSA9PiBzdXBlcmFnZW50LnBvc3QoYCR7ZXh0ZXJuYWxTaWduZXJVcmx9L2FwaS92Mi8ke2NvaW59L3Rzc3NoYXJlL1BhaWxsaWVyTW9kdWx1c2ApLnR5cGUoJ2pzb24nKS5zZW5kKHBhcmFtcyksXG4gICAgICAoZXJyLCB0cnlDb3VudCkgPT4ge1xuICAgICAgICBkZWJ1ZyhgZmFpbGVkIHRvIGNvbm5lY3QgdG8gZXh0ZXJuYWwgc2lnbmVyIChhdHRlbXB0ICR7dHJ5Q291bnR9LCBlcnJvcjogJHtlcnIubWVzc2FnZX0pYCk7XG4gICAgICB9XG4gICAgKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ3VzdG9tS1NoYXJlR2VuZXJhdG9yKGV4dGVybmFsU2lnbmVyVXJsOiBzdHJpbmcsIGNvaW46IHN0cmluZyk6IEN1c3RvbUtTaGFyZUdlbmVyYXRpbmdGdW5jdGlvbiB7XG4gIHJldHVybiBhc3luYyBmdW5jdGlvbiAocGFyYW1zKTogUHJvbWlzZTxUc3NFY2RzYVN0ZXAxUmV0dXJuTWVzc2FnZT4ge1xuICAgIGNvbnN0IHsgYm9keTogcmVzdWx0IH0gPSBhd2FpdCByZXRyeVByb21pc2UoXG4gICAgICAoKSA9PiBzdXBlcmFnZW50LnBvc3QoYCR7ZXh0ZXJuYWxTaWduZXJVcmx9L2FwaS92Mi8ke2NvaW59L3Rzc3NoYXJlL0tgKS50eXBlKCdqc29uJykuc2VuZChwYXJhbXMpLFxuICAgICAgKGVyciwgdHJ5Q291bnQpID0+IHtcbiAgICAgICAgZGVidWcoYGZhaWxlZCB0byBjb25uZWN0IHRvIGV4dGVybmFsIHNpZ25lciAoYXR0ZW1wdCAke3RyeUNvdW50fSwgZXJyb3I6ICR7ZXJyLm1lc3NhZ2V9KWApO1xuICAgICAgfVxuICAgICk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUN1c3RvbU11RGVsdGFTaGFyZUdlbmVyYXRvcihcbiAgZXh0ZXJuYWxTaWduZXJVcmw6IHN0cmluZyxcbiAgY29pbjogc3RyaW5nXG4pOiBDdXN0b21NdURlbHRhU2hhcmVHZW5lcmF0aW5nRnVuY3Rpb24ge1xuICByZXR1cm4gYXN5bmMgZnVuY3Rpb24gKHBhcmFtcyk6IFByb21pc2U8VHNzRWNkc2FTdGVwMlJldHVybk1lc3NhZ2U+IHtcbiAgICBjb25zdCB7IGJvZHk6IHJlc3VsdCB9ID0gYXdhaXQgcmV0cnlQcm9taXNlKFxuICAgICAgKCkgPT4gc3VwZXJhZ2VudC5wb3N0KGAke2V4dGVybmFsU2lnbmVyVXJsfS9hcGkvdjIvJHtjb2lufS90c3NzaGFyZS9NdURlbHRhYCkudHlwZSgnanNvbicpLnNlbmQocGFyYW1zKSxcbiAgICAgIChlcnIsIHRyeUNvdW50KSA9PiB7XG4gICAgICAgIGRlYnVnKGBmYWlsZWQgdG8gY29ubmVjdCB0byBleHRlcm5hbCBzaWduZXIgKGF0dGVtcHQgJHt0cnlDb3VudH0sIGVycm9yOiAke2Vyci5tZXNzYWdlfSlgKTtcbiAgICAgIH1cbiAgICApO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDdXN0b21TU2hhcmVHZW5lcmF0b3IoZXh0ZXJuYWxTaWduZXJVcmw6IHN0cmluZywgY29pbjogc3RyaW5nKTogQ3VzdG9tU1NoYXJlR2VuZXJhdGluZ0Z1bmN0aW9uIHtcbiAgcmV0dXJuIGFzeW5jIGZ1bmN0aW9uIChwYXJhbXMpOiBQcm9taXNlPFNTaGFyZT4ge1xuICAgIGNvbnN0IHsgYm9keTogcmVzdWx0IH0gPSBhd2FpdCByZXRyeVByb21pc2UoXG4gICAgICAoKSA9PiBzdXBlcmFnZW50LnBvc3QoYCR7ZXh0ZXJuYWxTaWduZXJVcmx9L2FwaS92Mi8ke2NvaW59L3Rzc3NoYXJlL1NgKS50eXBlKCdqc29uJykuc2VuZChwYXJhbXMpLFxuICAgICAgKGVyciwgdHJ5Q291bnQpID0+IHtcbiAgICAgICAgZGVidWcoYGZhaWxlZCB0byBjb25uZWN0IHRvIGV4dGVybmFsIHNpZ25lciAoYXR0ZW1wdCAke3RyeUNvdW50fSwgZXJyb3I6ICR7ZXJyLm1lc3NhZ2V9KWApO1xuICAgICAgfVxuICAgICk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUN1c3RvbUNvbW1pdG1lbnRHZW5lcmF0b3IoXG4gIGV4dGVybmFsU2lnbmVyVXJsOiBzdHJpbmcsXG4gIGNvaW46IHN0cmluZ1xuKTogQ3VzdG9tQ29tbWl0bWVudEdlbmVyYXRpbmdGdW5jdGlvbiB7XG4gIHJldHVybiBhc3luYyBmdW5jdGlvbiAocGFyYW1zKTogUHJvbWlzZTx7XG4gICAgdXNlclRvQml0Z29Db21taXRtZW50OiBDb21taXRtZW50U2hhcmVSZWNvcmQ7XG4gICAgZW5jcnlwdGVkU2lnbmVyU2hhcmU6IEVuY3J5cHRlZFNpZ25lclNoYXJlUmVjb3JkO1xuICAgIGVuY3J5cHRlZFVzZXJUb0JpdGdvUlNoYXJlOiBFbmNyeXB0ZWRTaWduZXJTaGFyZVJlY29yZDtcbiAgfT4ge1xuICAgIGNvbnN0IHsgYm9keTogcmVzdWx0IH0gPSBhd2FpdCByZXRyeVByb21pc2UoXG4gICAgICAoKSA9PiBzdXBlcmFnZW50LnBvc3QoYCR7ZXh0ZXJuYWxTaWduZXJVcmx9L2FwaS92Mi8ke2NvaW59L3Rzc3NoYXJlL2NvbW1pdG1lbnRgKS50eXBlKCdqc29uJykuc2VuZChwYXJhbXMpLFxuICAgICAgKGVyciwgdHJ5Q291bnQpID0+IHtcbiAgICAgICAgZGVidWcoYGZhaWxlZCB0byBjb25uZWN0IHRvIGV4dGVybmFsIHNpZ25lciAoYXR0ZW1wdCAke3RyeUNvdW50fSwgZXJyb3I6ICR7ZXJyLm1lc3NhZ2V9KWApO1xuICAgICAgfVxuICAgICk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUN1c3RvbVJTaGFyZUdlbmVyYXRvcihleHRlcm5hbFNpZ25lclVybDogc3RyaW5nLCBjb2luOiBzdHJpbmcpOiBDdXN0b21SU2hhcmVHZW5lcmF0aW5nRnVuY3Rpb24ge1xuICByZXR1cm4gYXN5bmMgZnVuY3Rpb24gKHBhcmFtcyk6IFByb21pc2U8eyByU2hhcmU6IFNpZ25TaGFyZSB9PiB7XG4gICAgY29uc3QgeyBib2R5OiByU2hhcmUgfSA9IGF3YWl0IHJldHJ5UHJvbWlzZShcbiAgICAgICgpID0+IHN1cGVyYWdlbnQucG9zdChgJHtleHRlcm5hbFNpZ25lclVybH0vYXBpL3YyLyR7Y29pbn0vdHNzc2hhcmUvUmApLnR5cGUoJ2pzb24nKS5zZW5kKHBhcmFtcyksXG4gICAgICAoZXJyLCB0cnlDb3VudCkgPT4ge1xuICAgICAgICBkZWJ1ZyhgZmFpbGVkIHRvIGNvbm5lY3QgdG8gZXh0ZXJuYWwgc2lnbmVyIChhdHRlbXB0ICR7dHJ5Q291bnR9LCBlcnJvcjogJHtlcnIubWVzc2FnZX0pYCk7XG4gICAgICB9XG4gICAgKTtcbiAgICByZXR1cm4gclNoYXJlO1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ3VzdG9tR1NoYXJlR2VuZXJhdG9yKGV4dGVybmFsU2lnbmVyVXJsOiBzdHJpbmcsIGNvaW46IHN0cmluZyk6IEN1c3RvbUdTaGFyZUdlbmVyYXRpbmdGdW5jdGlvbiB7XG4gIHJldHVybiBhc3luYyBmdW5jdGlvbiAocGFyYW1zKTogUHJvbWlzZTxHU2hhcmU+IHtcbiAgICBjb25zdCB7IGJvZHk6IHNpZ25lZFR4IH0gPSBhd2FpdCByZXRyeVByb21pc2UoXG4gICAgICAoKSA9PiBzdXBlcmFnZW50LnBvc3QoYCR7ZXh0ZXJuYWxTaWduZXJVcmx9L2FwaS92Mi8ke2NvaW59L3Rzc3NoYXJlL0dgKS50eXBlKCdqc29uJykuc2VuZChwYXJhbXMpLFxuICAgICAgKGVyciwgdHJ5Q291bnQpID0+IHtcbiAgICAgICAgZGVidWcoYGZhaWxlZCB0byBjb25uZWN0IHRvIGV4dGVybmFsIHNpZ25lciAoYXR0ZW1wdCAke3RyeUNvdW50fSwgZXJyb3I6ICR7ZXJyLm1lc3NhZ2V9KWApO1xuICAgICAgfVxuICAgICk7XG4gICAgcmV0dXJuIHNpZ25lZFR4O1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ3VzdG9tTVBDdjJTaWduaW5nUm91bmQxR2VuZXJhdG9yKFxuICBleHRlcm5hbFNpZ25lclVybDogc3RyaW5nLFxuICBjb2luOiBzdHJpbmdcbik6IEN1c3RvbU1QQ3YyU2lnbmluZ1JvdW5kMUdlbmVyYXRpbmdGdW5jdGlvbiB7XG4gIHJldHVybiBhc3luYyBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgY29uc3QgeyBib2R5OiByZXN1bHQgfSA9IGF3YWl0IHJldHJ5UHJvbWlzZShcbiAgICAgICgpID0+IHN1cGVyYWdlbnQucG9zdChgJHtleHRlcm5hbFNpZ25lclVybH0vYXBpL3YyLyR7Y29pbn0vdHNzc2hhcmUvTVBDdjJSb3VuZDFgKS50eXBlKCdqc29uJykuc2VuZChwYXJhbXMpLFxuICAgICAgKGVyciwgdHJ5Q291bnQpID0+IHtcbiAgICAgICAgZGVidWcoYGZhaWxlZCB0byBjb25uZWN0IHRvIGV4dGVybmFsIHNpZ25lciAoYXR0ZW1wdCAke3RyeUNvdW50fSwgZXJyb3I6ICR7ZXJyLm1lc3NhZ2V9KWApO1xuICAgICAgfVxuICAgICk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUN1c3RvbU1QQ3YyU2lnbmluZ1JvdW5kMkdlbmVyYXRvcihcbiAgZXh0ZXJuYWxTaWduZXJVcmw6IHN0cmluZyxcbiAgY29pbjogc3RyaW5nXG4pOiBDdXN0b21NUEN2MlNpZ25pbmdSb3VuZDJHZW5lcmF0aW5nRnVuY3Rpb24ge1xuICByZXR1cm4gYXN5bmMgZnVuY3Rpb24gKHBhcmFtcykge1xuICAgIGNvbnN0IHsgYm9keTogcmVzdWx0IH0gPSBhd2FpdCByZXRyeVByb21pc2UoXG4gICAgICAoKSA9PiBzdXBlcmFnZW50LnBvc3QoYCR7ZXh0ZXJuYWxTaWduZXJVcmx9L2FwaS92Mi8ke2NvaW59L3Rzc3NoYXJlL01QQ3YyUm91bmQyYCkudHlwZSgnanNvbicpLnNlbmQocGFyYW1zKSxcbiAgICAgIChlcnIsIHRyeUNvdW50KSA9PiB7XG4gICAgICAgIGRlYnVnKGBmYWlsZWQgdG8gY29ubmVjdCB0byBleHRlcm5hbCBzaWduZXIgKGF0dGVtcHQgJHt0cnlDb3VudH0sIGVycm9yOiAke2Vyci5tZXNzYWdlfSlgKTtcbiAgICAgIH1cbiAgICApO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDdXN0b21NUEN2MlNpZ25pbmdSb3VuZDNHZW5lcmF0b3IoXG4gIGV4dGVybmFsU2lnbmVyVXJsOiBzdHJpbmcsXG4gIGNvaW46IHN0cmluZ1xuKTogQ3VzdG9tTVBDdjJTaWduaW5nUm91bmQzR2VuZXJhdGluZ0Z1bmN0aW9uIHtcbiAgcmV0dXJuIGFzeW5jIGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICBjb25zdCB7IGJvZHk6IHJlc3VsdCB9ID0gYXdhaXQgcmV0cnlQcm9taXNlKFxuICAgICAgKCkgPT4gc3VwZXJhZ2VudC5wb3N0KGAke2V4dGVybmFsU2lnbmVyVXJsfS9hcGkvdjIvJHtjb2lufS90c3NzaGFyZS9NUEN2MlJvdW5kM2ApLnR5cGUoJ2pzb24nKS5zZW5kKHBhcmFtcyksXG4gICAgICAoZXJyLCB0cnlDb3VudCkgPT4ge1xuICAgICAgICBkZWJ1ZyhgZmFpbGVkIHRvIGNvbm5lY3QgdG8gZXh0ZXJuYWwgc2lnbmVyIChhdHRlbXB0ICR7dHJ5Q291bnR9LCBlcnJvcjogJHtlcnIubWVzc2FnZX0pYCk7XG4gICAgICB9XG4gICAgKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0dXBBUElSb3V0ZXMoYXBwOiBleHByZXNzLkFwcGxpY2F0aW9uLCBjb25maWc6IENvbmZpZyk6IHZvaWQge1xuICAvLyBXaGVuIGFkZGluZyBuZXcgcm91dGVzIHRvIEJpdEdvIEV4cHJlc3MgbWFrZSBzdXJlIHRoYXQgeW91IGFsc28gYWRkIHRoZSBleGFjdCBzYW1lIHJvdXRlcyB0byB0aGUgc2VydmVyLiBTaW5jZVxuICAvLyBzb21lIGN1c3RvbWVycyB3ZXJlIGNvbmZ1c2VkIHdoZW4gY2FsbGluZyBhIEJpdEdvIEV4cHJlc3Mgcm91dGUgb24gdGhlIEJpdEdvIHNlcnZlciwgd2Ugbm93IGhhbmRsZSBhbGwgQml0R29cbiAgLy8gRXhwcmVzcyByb3V0ZXMgb24gdGhlIEJpdEdvIHNlcnZlciBhbmQgcmV0dXJuIGFuIGVycm9yIG1lc3NhZ2UgdGhhdCBzYXlzIHRoYXQgb25lIHNob3VsZCBjYWxsIEJpdEdvIEV4cHJlc3NcbiAgLy8gaW5zdGVhZC5cbiAgLy8gVjEgcm91dGVzIHNob3VsZCBiZSBhZGRlZCB0byB3d3cvY29uZmlnL3JvdXRlcy5qc1xuICAvLyBWMiByb3V0ZXMgc2hvdWxkIGJlIGFkZGVkIHRvIHd3dy9jb25maWcvcm91dGVzVjIuanNcblxuICAvLyBwaW5nXG4gIC8vIC9hcGkvdlsxMl0vcGluZ2V4cHJlc3MgaXMgdGhlIG9ubHkgZXhjZXB0aW9uIHRvIHRoZSBydWxlIGFib3ZlLCBhcyBpdCBleHBsaWNpdGx5IGNoZWNrcyB0aGUgaGVhbHRoIG9mIHRoZVxuICAvLyBleHByZXNzIHNlcnZlciB3aXRob3V0IHJ1bm5pbmcgaW50byByYXRlIGxpbWl0aW5nIHdpdGggdGhlIEJpdEdvIHNlcnZlci5cbiAgYXBwLmdldCgnL2FwaS92WzEyXS9waW5nJywgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZVBpbmcpKTtcbiAgYXBwLmdldCgnL2FwaS92WzEyXS9waW5nZXhwcmVzcycsIHByb21pc2VXcmFwcGVyKGhhbmRsZVBpbmdFeHByZXNzKSk7XG5cbiAgLy8gYXV0aFxuICBhcHAucG9zdCgnL2FwaS92WzEyXS91c2VyL2xvZ2luJywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlTG9naW4pKTtcblxuICBhcHAucG9zdCgnL2FwaS92WzEyXS9kZWNyeXB0JywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlRGVjcnlwdCkpO1xuICBhcHAucG9zdCgnL2FwaS92WzEyXS9lbmNyeXB0JywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlRW5jcnlwdCkpO1xuICBhcHAucG9zdCgnL2FwaS92WzEyXS92ZXJpZnlhZGRyZXNzJywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVmVyaWZ5QWRkcmVzcykpO1xuICBhcHAucG9zdChcbiAgICAnL2FwaS92WzEyXS9jYWxjdWxhdGVtaW5lcmZlZWluZm8nLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVDYWxjdWxhdGVNaW5lckZlZUluZm8pXG4gICk7XG5cbiAgYXBwLnBvc3QoJy9hcGkvdjEva2V5Y2hhaW4vbG9jYWwnLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVDcmVhdGVMb2NhbEtleUNoYWluKSk7XG4gIGFwcC5wb3N0KCcvYXBpL3YxL2tleWNoYWluL2Rlcml2ZScsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZURlcml2ZUxvY2FsS2V5Q2hhaW4pKTtcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjEvd2FsbGV0cy9zaW1wbGVjcmVhdGUnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVDcmVhdGVXYWxsZXRXaXRoS2V5Y2hhaW5zKVxuICApO1xuXG4gIGFwcC5wb3N0KCcvYXBpL3YxL3dhbGxldC86aWQvc2VuZGNvaW5zJywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlU2VuZENvaW5zKSk7XG4gIGFwcC5wb3N0KCcvYXBpL3YxL3dhbGxldC86aWQvc2VuZG1hbnknLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVTZW5kTWFueSkpO1xuICBhcHAucG9zdChcbiAgICAnL2FwaS92MS93YWxsZXQvOmlkL2NyZWF0ZXRyYW5zYWN0aW9uJyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlQ3JlYXRlVHJhbnNhY3Rpb24pXG4gICk7XG4gIGFwcC5wb3N0KFxuICAgICcvYXBpL3YxL3dhbGxldC86aWQvc2lnbnRyYW5zYWN0aW9uJyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlU2lnblRyYW5zYWN0aW9uKVxuICApO1xuXG4gIGFwcC5wb3N0KCcvYXBpL3YxL3dhbGxldC86aWQvc2ltcGxlc2hhcmUnLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVTaGFyZVdhbGxldCkpO1xuICBhcHAucG9zdChcbiAgICAnL2FwaS92MS93YWxsZXRzaGFyZS86c2hhcmVJZC9hY2NlcHRTaGFyZScsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZUFjY2VwdFNoYXJlKVxuICApO1xuXG4gIGFwcC5wdXQoXG4gICAgJy9hcGkvdjEvcGVuZGluZ2FwcHJvdmFscy86aWQvZXhwcmVzcycsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZUFwcHJvdmVUcmFuc2FjdGlvbilcbiAgKTtcbiAgYXBwLnB1dChcbiAgICAnL2FwaS92MS9wZW5kaW5nYXBwcm92YWxzLzppZC9jb25zdHJ1Y3RUeCcsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZUNvbnN0cnVjdEFwcHJvdmFsVHgpXG4gICk7XG5cbiAgYXBwLnB1dChcbiAgICAnL2FwaS92MS93YWxsZXQvOmlkL2NvbnNvbGlkYXRldW5zcGVudHMnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVDb25zb2xpZGF0ZVVuc3BlbnRzKVxuICApO1xuICBhcHAucHV0KCcvYXBpL3YxL3dhbGxldC86aWQvZmFub3V0dW5zcGVudHMnLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVGYW5PdXRVbnNwZW50cykpO1xuXG4gIC8vIGFueSBvdGhlciBBUEkgY2FsbFxuICBhcHAudXNlKCcvYXBpL3ZbMV0vKicsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZVJFU1QpKTtcblxuICAvLyBBUEkgdjJcblxuICAvLyBjcmVhdGUga2V5Y2hhaW5cbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjIvOmNvaW4va2V5Y2hhaW4vbG9jYWwnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVWMkNyZWF0ZUxvY2FsS2V5Q2hhaW4pXG4gICk7XG5cbiAgLy8gZ2VuZXJhdGUgd2FsbGV0XG4gIGFwcC5wb3N0KCcvYXBpL3YyLzpjb2luL3dhbGxldC9nZW5lcmF0ZScsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyR2VuZXJhdGVXYWxsZXQpKTtcblxuICBhcHAucHV0KCcvZXhwcmVzcy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZCcsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZVdhbGxldFVwZGF0ZSkpO1xuXG4gIC8vIGNoYW5nZSB3YWxsZXQgcGFzc3BocmFzZVxuICBhcHAucG9zdChcbiAgICAnL2FwaS92Mi86Y29pbi9rZXljaGFpbi86aWQvY2hhbmdlcGFzc3dvcmQnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVLZXljaGFpbkNoYW5nZVBhc3N3b3JkKVxuICApO1xuXG4gIC8vIGNyZWF0ZSBhZGRyZXNzXG4gIGFwcC5wb3N0KCcvYXBpL3YyLzpjb2luL3dhbGxldC86aWQvYWRkcmVzcycsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyQ3JlYXRlQWRkcmVzcykpO1xuXG4gIC8vIHNoYXJlIHdhbGxldFxuICBhcHAucG9zdCgnL2FwaS92Mi86Y29pbi93YWxsZXQvOmlkL3NoYXJlJywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJTaGFyZVdhbGxldCkpO1xuICBhcHAucG9zdChcbiAgICAnL2FwaS92Mi86Y29pbi93YWxsZXRzaGFyZS86aWQvYWNjZXB0c2hhcmUnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVWMkFjY2VwdFdhbGxldFNoYXJlKVxuICApO1xuXG4gIC8vIHNpZ24gYXJiaXRyYXJ5IHBheWxvYWRzIHcvIHRyYWRpbmcgYWNjb3VudCBrZXlcbiAgYXBwLnBvc3QoYC9hcGkvdjIvb2ZjL3NpZ25QYXlsb2FkYCwgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJPRkNTaWduUGF5bG9hZCkpO1xuXG4gIC8vIHNpZ24gdHJhbnNhY3Rpb25cbiAgYXBwLnBvc3QoJy9hcGkvdjIvOmNvaW4vc2lnbnR4JywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJTaWduVHgpKTtcbiAgYXBwLnBvc3QoJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9zaWdudHgnLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVWMlNpZ25UeFdhbGxldCkpO1xuICBhcHAucG9zdChcbiAgICAnL2FwaS92Mi86Y29pbi93YWxsZXQvOmlkL3NpZ250eHRzcycsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyU2lnblRTU1dhbGxldFR4KVxuICApO1xuICBhcHAucG9zdChcbiAgICAnL2FwaS92Mi86Y29pbi93YWxsZXQvOmlkL3JlY292ZXJ0b2tlbicsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyUmVjb3ZlclRva2VuKVxuICApO1xuXG4gIC8vIHNlbmQgdHJhbnNhY3Rpb25cbiAgYXBwLnBvc3QoJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9zZW5kY29pbnMnLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVWMlNlbmRPbmUpKTtcbiAgYXBwLnBvc3QoJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9zZW5kbWFueScsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyU2VuZE1hbnkpKTtcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9wcmVidWlsZEFuZFNpZ25UcmFuc2FjdGlvbicsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyUHJlYnVpbGRBbmRTaWduVHJhbnNhY3Rpb24pXG4gICk7XG5cbiAgLy8gdG9rZW4gZW5hYmxlbWVudFxuICBhcHAucG9zdChcbiAgICAnL2FwaS92Mi86Y29pbi93YWxsZXQvOmlkL2VuYWJsZVRva2VucycsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyRW5hYmxlVG9rZW5zKVxuICApO1xuXG4gIC8vIHVuc3BlbnQgY2hhbmdlc1xuICBhcHAucG9zdChcbiAgICAnL2FwaS92Mi86Y29pbi93YWxsZXQvOmlkL2NvbnNvbGlkYXRldW5zcGVudHMnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVWMkNvbnNvbGlkYXRlVW5zcGVudHMpXG4gICk7XG4gIGFwcC5wb3N0KFxuICAgICcvYXBpL3YyLzpjb2luL3dhbGxldC86aWQvZmFub3V0dW5zcGVudHMnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVWMkZhbk91dFVuc3BlbnRzKVxuICApO1xuXG4gIGFwcC5wb3N0KCcvYXBpL3YyLzpjb2luL3dhbGxldC86aWQvc3dlZXAnLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVWMlN3ZWVwKSk7XG5cbiAgLy8gQ1BGUFxuICBhcHAucG9zdChcbiAgICAnL2FwaS92Mi86Y29pbi93YWxsZXQvOmlkL2FjY2VsZXJhdGV0eCcsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyQWNjZWxlcmF0ZVRyYW5zYWN0aW9uKVxuICApO1xuXG4gIC8vIGFjY291bnQtYmFzZWRcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9jb25zb2xpZGF0ZUFjY291bnQnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVWMkNvbnNvbGlkYXRlQWNjb3VudClcbiAgKTtcblxuICAvLyBNaXNjZWxsYW5lb3VzXG4gIGFwcC5wb3N0KCcvYXBpL3YyLzpjb2luL2Nhbm9uaWNhbGFkZHJlc3MnLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVDYW5vbmljYWxBZGRyZXNzKSk7XG4gIGFwcC5wb3N0KCcvYXBpL3YyLzpjb2luL3ZlcmlmeWFkZHJlc3MnLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVWMlZlcmlmeUFkZHJlc3MpKTtcbiAgYXBwLnB1dChcbiAgICAnL2FwaS92Mi86Y29pbi9wZW5kaW5nYXBwcm92YWxzLzppZCcsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyUGVuZGluZ0FwcHJvdmFsKVxuICApO1xuXG4gIC8vIGxpZ2h0bmluZyAtIHBheSBpbnZvaWNlXG4gIGFwcC5wb3N0KFxuICAgICcvYXBpL3YyLzpjb2luL3dhbGxldC86aWQvbGlnaHRuaW5nL3BheW1lbnQnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVQYXlMaWdodG5pbmdJbnZvaWNlKVxuICApO1xuXG4gIC8vIGxpZ2h0bmluZyAtIG9uY2hhaW4gd2l0aGRyYXdhbFxuICBhcHAucG9zdChcbiAgICAnL2FwaS92Mi86Y29pbi93YWxsZXQvOmlkL2xpZ2h0bmluZy93aXRoZHJhdycsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZUxpZ2h0bmluZ1dpdGhkcmF3KVxuICApO1xuXG4gIC8vIGFueSBvdGhlciBBUEkgdjIgY2FsbFxuICBhcHAudXNlKCcvYXBpL3YyL3VzZXIvKicsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyVXNlclJFU1QpKTtcbiAgYXBwLnVzZSgnL2FwaS92Mi86Y29pbi8qJywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJDb2luU3BlY2lmaWNSRVNUKSk7XG5cbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvbmV0d29yay92MS9lbnRlcnByaXNlcy86ZW50ZXJwcmlzZUlkL2NsaWVudHMvY29ubmVjdGlvbnMnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVOZXR3b3JrVjFFbnRlcnByaXNlQ2xpZW50Q29ubmVjdGlvbnMpXG4gICk7XG5cbiAgLy8gZXZlcnl0aGluZyBlbHNlIHNob3VsZCB1c2UgdGhlIHByb3h5IGhhbmRsZXJcbiAgaWYgKGNvbmZpZy5kaXNhYmxlUHJveHkgIT09IHRydWUpIHtcbiAgICBhcHAudXNlKFxuICAgICAgJy9hcGkvOm5hbWVzcGFjZS92WzEyXS9lbnRlcnByaXNlcy86ZW50ZXJwcmlzZUlkLyonLFxuICAgICAgcGFyc2VCb2R5LFxuICAgICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVQcm94eVJlcSlcbiAgICApO1xuXG4gICAgYXBwLnVzZShwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVQcm94eVJlcSkpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXR1cFNpZ25pbmdSb3V0ZXMoYXBwOiBleHByZXNzLkFwcGxpY2F0aW9uLCBjb25maWc6IENvbmZpZyk6IHZvaWQge1xuICBhcHAucG9zdCgnL2FwaS92Mi86Y29pbi9zaWduJywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJTaWduKSk7XG4gIGFwcC5wb3N0KFxuICAgICcvYXBpL3YyLzpjb2luL3Rzc3NoYXJlLzpzaGFyZXR5cGUnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVWMkdlbmVyYXRlU2hhcmVUU1MpXG4gICk7XG4gIGFwcC5wb3N0KFxuICAgIGAvYXBpL3YyL29mYy9zaWduUGF5bG9hZGAsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyT0ZDU2lnblBheWxvYWRJbkV4dFNpZ25pbmdNb2RlKVxuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0dXBMaWdodG5pbmdTaWduZXJOb2RlUm91dGVzKGFwcDogZXhwcmVzcy5BcHBsaWNhdGlvbiwgY29uZmlnOiBDb25maWcpOiB2b2lkIHtcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9pbml0d2FsbGV0JyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlSW5pdExpZ2h0bmluZ1dhbGxldClcbiAgKTtcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9zaWduZXJtYWNhcm9vbicsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZUNyZWF0ZVNpZ25lck1hY2Fyb29uKVxuICApO1xuICBhcHAucG9zdChcbiAgICAnL2FwaS92Mi86Y29pbi93YWxsZXQvOmlkL3VubG9ja3dhbGxldCcsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZVVubG9ja0xpZ2h0bmluZ1dhbGxldClcbiAgKTtcbiAgYXBwLmdldCgnL2FwaS92Mi86Y29pbi93YWxsZXQvOmlkL3N0YXRlJywgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZUdldExpZ2h0bmluZ1dhbGxldFN0YXRlKSk7XG59XG4iXX0=

Выполнить команду


Для локальной разработки. Не используйте в интернете!