PHP WebShell
Текущая директория: /opt/BitGoJS/modules/express/dist
Просмотр файла: clientRoutes.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleV2GenerateShareTSS = handleV2GenerateShareTSS;
exports.handleV2SignTSSWalletTx = handleV2SignTSSWalletTx;
exports.handleV2Sign = handleV2Sign;
exports.handleV2OFCSignPayloadInExtSigningMode = handleV2OFCSignPayloadInExtSigningMode;
exports.handleV2OFCSignPayload = handleV2OFCSignPayload;
exports.handleV2GenerateWallet = handleV2GenerateWallet;
exports.handleV2CreateAddress = handleV2CreateAddress;
exports.handleV2ConsolidateAccount = handleV2ConsolidateAccount;
exports.handleV2PrebuildAndSignTransaction = handleV2PrebuildAndSignTransaction;
exports.handleV2EnableTokens = handleV2EnableTokens;
exports.handleKeychainChangePassword = handleKeychainChangePassword;
exports.redirectRequest = redirectRequest;
exports.promiseWrapper = promiseWrapper;
exports.createCustomSigningFunction = createCustomSigningFunction;
exports.createCustomPaillierModulusGetter = createCustomPaillierModulusGetter;
exports.createCustomKShareGenerator = createCustomKShareGenerator;
exports.createCustomMuDeltaShareGenerator = createCustomMuDeltaShareGenerator;
exports.createCustomSShareGenerator = createCustomSShareGenerator;
exports.createCustomCommitmentGenerator = createCustomCommitmentGenerator;
exports.createCustomRShareGenerator = createCustomRShareGenerator;
exports.createCustomGShareGenerator = createCustomGShareGenerator;
exports.createCustomMPCv2SigningRound1Generator = createCustomMPCv2SigningRound1Generator;
exports.createCustomMPCv2SigningRound2Generator = createCustomMPCv2SigningRound2Generator;
exports.createCustomMPCv2SigningRound3Generator = createCustomMPCv2SigningRound3Generator;
exports.setupAPIRoutes = setupAPIRoutes;
exports.setupSigningRoutes = setupSigningRoutes;
exports.setupLightningSignerNodeRoutes = setupLightningSignerNodeRoutes;
/**
* @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;
}
}
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;
}
}
/**
* 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;
}
}
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;
}
}
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,
};
}
/**
* 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() };
}
/**
* 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);
}
/**
* 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;
}
/**
* 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;
}
/**
* 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;
}
}
/**
* 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,
});
}
/**
* 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();
}
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);
}
};
}
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;
};
}
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;
};
}
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;
};
}
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;
};
}
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;
};
}
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;
};
}
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;
};
}
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;
};
}
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;
};
}
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;
};
}
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;
};
}
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));
}
}
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));
}
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));
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50Um91dGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NsaWVudFJvdXRlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQWdhQSw0REErRUM7QUFFRCwwREFVQztBQUtELG9DQTJCQztBQUVELHdGQWdEQztBQUVELHdEQWtEQztBQU1ELHdEQVFDO0FBTUQsc0RBS0M7QUEyR0QsZ0VBNENDO0FBZ0tELGdGQWNDO0FBTUQsb0RBWUM7QUF1QkQsb0VBK0JDO0FBa0hELDBDQTJDQztBQXlIRCx3Q0FlQztBQUVELGtFQWdCQztBQUNELDhFQWVDO0FBRUQsa0VBVUM7QUFFRCw4RUFhQztBQUVELGtFQVVDO0FBRUQsMEVBaUJDO0FBRUQsa0VBVUM7QUFFRCxrRUFVQztBQUVELDBGQWFDO0FBRUQsMEZBYUM7QUFFRCwwRkFhQztBQUVELHdDQTJPQztBQUVELGdEQWNDO0FBRUQsd0VBb0JDO0FBaHdERDs7R0FFRztBQUNILDhDQTRCeUI7QUFDekIsaUNBQXNIO0FBQ3RILDBDQUEwQztBQUMxQyxrQ0FBa0M7QUFHbEMsNEJBQTRCO0FBQzVCLDJCQUEyQjtBQUMzQix5Q0FBeUM7QUFFekMsNEVBQTRFO0FBQzVFLGtEQUFrRDtBQUNsRCwwREFBZ0U7QUFHaEUscUNBQTRDO0FBQzVDLDJCQUFvQztBQUNwQyxpREFBOEM7QUFDOUMsNkVBSzJDO0FBQzNDLCtFQUErRTtBQUMvRSw2RUFBNEY7QUFDNUYsNkNBQXlDO0FBQ3pDLGtFQUFnRTtBQUNoRSxpRkFBOEU7QUFFOUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0FBQ2xELE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBQ3pDLE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQztBQUV4QyxNQUFNLHVCQUF1QixHQUFHLGdCQUFnQixLQUFLLENBQUMsT0FBTyxZQUFZLE9BQU8sRUFB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bURBQTJCLENBQUMsQ0FDNUMsQ0FBQztJQUNGLEdBQUcsQ0FBQyxHQUFHLENBQUMsZ0NBQWdDLEVBQUUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLGNBQWMsQ0FBQyxxREFBNkIsQ0FBQyxDQUFDLENBQUM7QUFDakgsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQHByZXR0aWVyXG4gKi9cbmltcG9ydCB7XG4gIENvbW1pdG1lbnRTaGFyZVJlY29yZCxcbiAgQ3JlYXRlTmV0d29ya0Nvbm5lY3Rpb25QYXJhbXMsXG4gIEN1c3RvbUNvbW1pdG1lbnRHZW5lcmF0aW5nRnVuY3Rpb24sXG4gIEN1c3RvbUdTaGFyZUdlbmVyYXRpbmdGdW5jdGlvbixcbiAgQ3VzdG9tS1NoYXJlR2VuZXJhdGluZ0Z1bmN0aW9uLFxuICBDdXN0b21NUEN2MlNpZ25pbmdSb3VuZDFHZW5lcmF0aW5nRnVuY3Rpb24sXG4gIEN1c3RvbU1QQ3YyU2lnbmluZ1JvdW5kMkdlbmVyYXRpbmdGdW5jdGlvbixcbiAgQ3VzdG9tTVBDdjJTaWduaW5nUm91bmQzR2VuZXJhdGluZ0Z1bmN0aW9uLFxuICBDdXN0b21NdURlbHRhU2hhcmVHZW5lcmF0aW5nRnVuY3Rpb24sXG4gIEN1c3RvbVBhaWxsaWVyTW9kdWx1c0dldHRlckZ1bmN0aW9uLFxuICBDdXN0b21SU2hhcmVHZW5lcmF0aW5nRnVuY3Rpb24sXG4gIEN1c3RvbVNTaGFyZUdlbmVyYXRpbmdGdW5jdGlvbixcbiAgRWNkc2FNUEN2MlV0aWxzLFxuICBFY2RzYVV0aWxzLFxuICBFZGRzYVV0aWxzLFxuICBFbmNyeXB0ZWRTaWduZXJTaGFyZVJlY29yZCxcbiAgZW5jcnlwdFJzYVdpdGhBZXNHY20sXG4gIEdldE5ldHdvcmtQYXJ0bmVyc1Jlc3BvbnNlLFxuICBHU2hhcmUsXG4gIE1QQ1R5cGUsXG4gIFNoYXJlVHlwZSxcbiAgU2lnblNoYXJlLFxuICBTU2hhcmUsXG4gIFRzc0VjZHNhU3RlcDFSZXR1cm5NZXNzYWdlLFxuICBUc3NFY2RzYVN0ZXAyUmV0dXJuTWVzc2FnZSxcbiAgVW5zdXBwb3J0ZWRDb2luRXJyb3IsXG4gIFdhbGxldCxcbn0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcbmltcG9ydCB7IEJpdEdvLCBCaXRHb09wdGlvbnMsIENvaW4sIEN1c3RvbVNpZ25pbmdGdW5jdGlvbiwgU2lnbmVkVHJhbnNhY3Rpb24sIFNpZ25lZFRyYW5zYWN0aW9uUmVxdWVzdCB9IGZyb20gJ2JpdGdvJztcbmltcG9ydCAqIGFzIGJvZHlQYXJzZXIgZnJvbSAnYm9keS1wYXJzZXInO1xuaW1wb3J0ICogYXMgZGVidWdMaWIgZnJvbSAnZGVidWcnO1xuaW1wb3J0ICogYXMgZXhwcmVzcyBmcm9tICdleHByZXNzJztcbmltcG9ydCB0eXBlIHsgUGFyYW1zRGljdGlvbmFyeSB9IGZyb20gJ2V4cHJlc3Mtc2VydmUtc3RhdGljLWNvcmUnO1xuaW1wb3J0ICogYXMgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0ICogYXMgdXJsIGZyb20gJ3VybCc7XG5pbXBvcnQgKiBhcyBzdXBlcmFnZW50IGZyb20gJ3N1cGVyYWdlbnQnO1xuXG4vLyBSZXF1ZXN0VHJhY2VyIHNob3VsZCBiZSBleHRyYWN0ZWQgaW50byBhIHNlcGFyYXRlIG5wbSBwYWNrYWdlIChhbG9uZyB3aXRoXG4vLyB0aGUgcmVzdCBvZiB0aGUgQml0R29KUyBIVFRQIHJlcXVlc3QgbWFjaGluZXJ5KVxuaW1wb3J0IHsgUmVxdWVzdFRyYWNlciB9IGZyb20gJ2JpdGdvL2Rpc3Qvc3JjL3YyL2ludGVybmFsL3V0aWwnO1xuXG5pbXBvcnQgeyBDb25maWcgfSBmcm9tICcuL2NvbmZpZyc7XG5pbXBvcnQgeyBBcGlSZXNwb25zZUVycm9yIH0gZnJvbSAnLi9lcnJvcnMnO1xuaW1wb3J0IHsgcHJvbWlzZXMgYXMgZnMgfSBmcm9tICdmcyc7XG5pbXBvcnQgeyByZXRyeVByb21pc2UgfSBmcm9tICcuL3JldHJ5UHJvbWlzZSc7XG5pbXBvcnQge1xuICBoYW5kbGVDcmVhdGVTaWduZXJNYWNhcm9vbixcbiAgaGFuZGxlR2V0TGlnaHRuaW5nV2FsbGV0U3RhdGUsXG4gIGhhbmRsZUluaXRMaWdodG5pbmdXYWxsZXQsXG4gIGhhbmRsZVVubG9ja0xpZ2h0bmluZ1dhbGxldCxcbn0gZnJvbSAnLi9saWdodG5pbmcvbGlnaHRuaW5nU2lnbmVyUm91dGVzJztcbmltcG9ydCB7IGhhbmRsZVBheUxpZ2h0bmluZ0ludm9pY2UgfSBmcm9tICcuL2xpZ2h0bmluZy9saWdodG5pbmdJbnZvaWNlUm91dGVzJztcbmltcG9ydCB7IGhhbmRsZVVwZGF0ZUxpZ2h0bmluZ1dhbGxldENvaW5TcGVjaWZpYyB9IGZyb20gJy4vbGlnaHRuaW5nL2xpZ2h0bmluZ1dhbGxldFJvdXRlcyc7XG5pbXBvcnQgeyBQcm94eUFnZW50IH0gZnJvbSAncHJveHktYWdlbnQnO1xuaW1wb3J0IHsgaXNMaWdodG5pbmdDb2luTmFtZSB9IGZyb20gJ0BiaXRnby9hYnN0cmFjdC1saWdodG5pbmcnO1xuaW1wb3J0IHsgaGFuZGxlTGlnaHRuaW5nV2l0aGRyYXcgfSBmcm9tICcuL2xpZ2h0bmluZy9saWdodG5pbmdXaXRoZHJhd1JvdXRlcyc7XG5cbmNvbnN0IHsgdmVyc2lvbiB9ID0gcmVxdWlyZSgnYml0Z28vcGFja2FnZS5qc29uJyk7XG5jb25zdCBwanNvbiA9IHJlcXVpcmUoJy4uL3BhY2thZ2UuanNvbicpO1xuY29uc3QgZGVidWcgPSBkZWJ1Z0xpYignYml0Z286ZXhwcmVzcycpO1xuXG5jb25zdCBCSVRHT0VYUFJFU1NfVVNFUl9BR0VOVCA9IGBCaXRHb0V4cHJlc3MvJHtwanNvbi52ZXJzaW9ufSBCaXRHb0pTLyR7dmVyc2lvbn1gO1xuXG5mdW5jdGlvbiBoYW5kbGVQaW5nKHJlcTogZXhwcmVzcy5SZXF1ZXN0LCByZXM6IGV4cHJlc3MuUmVzcG9uc2UsIG5leHQ6IGV4cHJlc3MuTmV4dEZ1bmN0aW9uKSB7XG4gIHJldHVybiByZXEuYml0Z28ucGluZygpO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVQaW5nRXhwcmVzcyhyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICByZXR1cm4ge1xuICAgIHN0YXR1czogJ2V4cHJlc3Mgc2VydmVyIGlzIG9rIScsXG4gIH07XG59XG5cbmZ1bmN0aW9uIGhhbmRsZUxvZ2luKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IHVzZXJuYW1lID0gcmVxLmJvZHkudXNlcm5hbWUgfHwgcmVxLmJvZHkuZW1haWw7XG4gIGNvbnN0IGJvZHkgPSByZXEuYm9keTtcbiAgYm9keS51c2VybmFtZSA9IHVzZXJuYW1lO1xuICByZXR1cm4gcmVxLmJpdGdvLmF1dGhlbnRpY2F0ZShib2R5KTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlRGVjcnlwdChyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICByZXR1cm4ge1xuICAgIGRlY3J5cHRlZDogcmVxLmJpdGdvLmRlY3J5cHQocmVxLmJvZHkpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBoYW5kbGVFbmNyeXB0KHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIHJldHVybiB7XG4gICAgZW5jcnlwdGVkOiByZXEuYml0Z28uZW5jcnlwdChyZXEuYm9keSksXG4gIH07XG59XG5cbi8qKlxuICogQGRlcHJlY2F0ZWRcbiAqIEBwYXJhbSByZXFcbiAqL1xuZnVuY3Rpb24gaGFuZGxlVmVyaWZ5QWRkcmVzcyhyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICByZXR1cm4ge1xuICAgIHZlcmlmaWVkOiByZXEuYml0Z28udmVyaWZ5QWRkcmVzcyhyZXEuYm9keSksXG4gIH07XG59XG5cbi8qKlxuICogQGRlcHJlY2F0ZWRcbiAqIEBwYXJhbSByZXFcbiAqL1xuZnVuY3Rpb24gaGFuZGxlQ3JlYXRlTG9jYWxLZXlDaGFpbihyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICByZXR1cm4gcmVxLmJpdGdvLmtleWNoYWlucygpLmNyZWF0ZShyZXEuYm9keSk7XG59XG5cbi8qKlxuICogQGRlcHJlY2F0ZWRcbiAqIEBwYXJhbSByZXFcbiAqL1xuZnVuY3Rpb24gaGFuZGxlRGVyaXZlTG9jYWxLZXlDaGFpbihyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICByZXR1cm4gcmVxLmJpdGdvLmtleWNoYWlucygpLmRlcml2ZUxvY2FsKHJlcS5ib2R5KTtcbn1cblxuLyoqXG4gKiBAZGVwcmVjYXRlZFxuICogQHBhcmFtIHJlcVxuICovXG5mdW5jdGlvbiBoYW5kbGVDcmVhdGVXYWxsZXRXaXRoS2V5Y2hhaW5zKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIHJldHVybiByZXEuYml0Z28ud2FsbGV0cygpLmNyZWF0ZVdhbGxldFdpdGhLZXljaGFpbnMocmVxLmJvZHkpO1xufVxuXG4vKipcbiAqIEBkZXByZWNhdGVkXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZVNlbmRDb2lucyhyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICByZXR1cm4gcmVxLmJpdGdvXG4gICAgLndhbGxldHMoKVxuICAgIC5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KVxuICAgIC50aGVuKGZ1bmN0aW9uICh3YWxsZXQpIHtcbiAgICAgIHJldHVybiB3YWxsZXQuc2VuZENvaW5zKHJlcS5ib2R5KTtcbiAgICB9KVxuICAgIC5jYXRjaChmdW5jdGlvbiAoZXJyKSB7XG4gICAgICBlcnIuc3RhdHVzID0gNDAwO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH0pXG4gICAgLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICdwZW5kaW5nQXBwcm92YWwnKSB7XG4gICAgICAgIHRocm93IGFwaVJlc3BvbnNlKDIwMiwgcmVzdWx0KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQGRlcHJlY2F0ZWRcbiAqIEBwYXJhbSByZXFcbiAqL1xuZnVuY3Rpb24gaGFuZGxlU2VuZE1hbnkocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgcmV0dXJuIHJlcS5iaXRnb1xuICAgIC53YWxsZXRzKClcbiAgICAuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQgfSlcbiAgICAudGhlbihmdW5jdGlvbiAod2FsbGV0KSB7XG4gICAgICByZXR1cm4gd2FsbGV0LnNlbmRNYW55KHJlcS5ib2R5KTtcbiAgICB9KVxuICAgIC5jYXRjaChmdW5jdGlvbiAoZXJyKSB7XG4gICAgICBlcnIuc3RhdHVzID0gNDAwO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH0pXG4gICAgLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICdwZW5kaW5nQXBwcm92YWwnKSB7XG4gICAgICAgIHRocm93IGFwaVJlc3BvbnNlKDIwMiwgcmVzdWx0KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQGRlcHJlY2F0ZWRcbiAqIEBwYXJhbSByZXFcbiAqL1xuZnVuY3Rpb24gaGFuZGxlQ3JlYXRlVHJhbnNhY3Rpb24ocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgcmV0dXJuIHJlcS5iaXRnb1xuICAgIC53YWxsZXRzKClcbiAgICAuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQgfSlcbiAgICAudGhlbihmdW5jdGlvbiAod2FsbGV0KSB7XG4gICAgICByZXR1cm4gd2FsbGV0LmNyZWF0ZVRyYW5zYWN0aW9uKHJlcS5ib2R5KTtcbiAgICB9KVxuICAgIC5jYXRjaChmdW5jdGlvbiAoZXJyKSB7XG4gICAgICBlcnIuc3RhdHVzID0gNDAwO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEBkZXByZWNhdGVkXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZVNpZ25UcmFuc2FjdGlvbihyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICByZXR1cm4gcmVxLmJpdGdvXG4gICAgLndhbGxldHMoKVxuICAgIC5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KVxuICAgIC50aGVuKGZ1bmN0aW9uICh3YWxsZXQpIHtcbiAgICAgIHJldHVybiB3YWxsZXQuc2lnblRyYW5zYWN0aW9uKHJlcS5ib2R5KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAZGVwcmVjYXRlZFxuICogQHBhcmFtIHJlcVxuICovXG5mdW5jdGlvbiBoYW5kbGVTaGFyZVdhbGxldChyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICByZXR1cm4gcmVxLmJpdGdvXG4gICAgLndhbGxldHMoKVxuICAgIC5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KVxuICAgIC50aGVuKGZ1bmN0aW9uICh3YWxsZXQpIHtcbiAgICAgIHJldHVybiB3YWxsZXQuc2hhcmVXYWxsZXQocmVxLmJvZHkpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEBkZXByZWNhdGVkXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZUFjY2VwdFNoYXJlKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IHBhcmFtcyA9IHJlcS5ib2R5IHx8IHt9O1xuICBwYXJhbXMud2FsbGV0U2hhcmVJZCA9IHJlcS5wYXJhbXMuc2hhcmVJZDtcbiAgcmV0dXJuIHJlcS5iaXRnby53YWxsZXRzKCkuYWNjZXB0U2hhcmUocGFyYW1zKTtcbn1cblxuLyoqXG4gKiBAZGVwcmVjYXRlZFxuICogQHBhcmFtIHJlcVxuICovXG5mdW5jdGlvbiBoYW5kbGVBcHByb3ZlVHJhbnNhY3Rpb24ocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgcGFyYW1zID0gcmVxLmJvZHkgfHwge307XG4gIHJldHVybiByZXEuYml0Z29cbiAgICAucGVuZGluZ0FwcHJvdmFscygpXG4gICAgLmdldCh7IGlkOiByZXEucGFyYW1zLmlkIH0pXG4gICAgLnRoZW4oZnVuY3Rpb24gKHBlbmRpbmdBcHByb3ZhbCkge1xuICAgICAgaWYgKHBhcmFtcy5zdGF0ZSA9PT0gJ2FwcHJvdmVkJykge1xuICAgICAgICByZXR1cm4gcGVuZGluZ0FwcHJvdmFsLmFwcHJvdmUocGFyYW1zKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBwZW5kaW5nQXBwcm92YWwucmVqZWN0KHBhcmFtcyk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogQGRlcHJlY2F0ZWRcbiAqIEBwYXJhbSByZXFcbiAqL1xuZnVuY3Rpb24gaGFuZGxlQ29uc3RydWN0QXBwcm92YWxUeChyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBjb25zdCBwYXJhbXMgPSByZXEuYm9keSB8fCB7fTtcbiAgcmV0dXJuIHJlcS5iaXRnb1xuICAgIC5wZW5kaW5nQXBwcm92YWxzKClcbiAgICAuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQgfSlcbiAgICAudGhlbihmdW5jdGlvbiAocGVuZGluZ0FwcHJvdmFsKSB7XG4gICAgICByZXR1cm4gcGVuZGluZ0FwcHJvdmFsLmNvbnN0cnVjdEFwcHJvdmFsVHgocGFyYW1zKTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAZGVwcmVjYXRlZFxuICogQHBhcmFtIHJlcVxuICovXG5mdW5jdGlvbiBoYW5kbGVDb25zb2xpZGF0ZVVuc3BlbnRzKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIHJldHVybiByZXEuYml0Z29cbiAgICAud2FsbGV0cygpXG4gICAgLmdldCh7IGlkOiByZXEucGFyYW1zLmlkIH0pXG4gICAgLnRoZW4oZnVuY3Rpb24gKHdhbGxldCkge1xuICAgICAgcmV0dXJuIHdhbGxldC5jb25zb2xpZGF0ZVVuc3BlbnRzKHJlcS5ib2R5KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAZGVwcmVjYXRlZFxuICogQHBhcmFtIHJlcVxuICovXG5mdW5jdGlvbiBoYW5kbGVGYW5PdXRVbnNwZW50cyhyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICByZXR1cm4gcmVxLmJpdGdvXG4gICAgLndhbGxldHMoKVxuICAgIC5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KVxuICAgIC50aGVuKGZ1bmN0aW9uICh3YWxsZXQpIHtcbiAgICAgIHJldHVybiB3YWxsZXQuZmFuT3V0VW5zcGVudHMocmVxLmJvZHkpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEBkZXByZWNhdGVkXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZUNhbGN1bGF0ZU1pbmVyRmVlSW5mbyhyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICByZXR1cm4gcmVxLmJpdGdvLmNhbGN1bGF0ZU1pbmVyRmVlSW5mbyh7XG4gICAgYml0Z286IHJlcS5iaXRnbyxcbiAgICBmZWVSYXRlOiByZXEuYm9keS5mZWVSYXRlLFxuICAgIG5QMnNoSW5wdXRzOiByZXEuYm9keS5uUDJzaElucHV0cyxcbiAgICBuUDJwa2hJbnB1dHM6IHJlcS5ib2R5Lm5QMnBraElucHV0cyxcbiAgICBuUDJzaFAyd3NoSW5wdXRzOiByZXEuYm9keS5uUDJzaFAyd3NoSW5wdXRzLFxuICAgIG5PdXRwdXRzOiByZXEuYm9keS5uT3V0cHV0cyxcbiAgfSk7XG59XG5cbi8qKlxuICogQnVpbGRzIHRoZSBBUEkncyBVUkwgc3RyaW5nLCBvcHRpb25hbGx5IGJ1aWxkaW5nIHRoZSBxdWVyeXN0cmluZyBpZiBwYXJhbWV0ZXJzIGV4aXN0XG4gKiBAcGFyYW0gcmVxXG4gKiBAcmV0dXJuIHtzdHJpbmd9XG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUFQSVBhdGgocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgbGV0IGFwaVBhdGggPSAnLycgKyByZXEucGFyYW1zWzBdO1xuICBpZiAoIV8uaXNFbXB0eShyZXEucXVlcnkpKSB7XG4gICAgLy8gcmVxLnBhcmFtcyBkb2VzIG5vdCBjb250YWluIHRoZSBxdWVyeXN0cmluZywgc28gd2UgbWFudWFsbHkgYWRkIHRoZW0gaGVyZVxuICAgIGNvbnN0IHVybERldGFpbHMgPSB1cmwucGFyc2UocmVxLnVybCk7XG4gICAgaWYgKHVybERldGFpbHMuc2VhcmNoKSB7XG4gICAgICAvLyBcInNlYXJjaFwiIGlzIHRoZSBwcm9wZXJseSBVUkwgZW5jb2RlZCBxdWVyeSBwYXJhbXMsIHByZWZpeGVkIHdpdGggXCI/XCJcbiAgICAgIGFwaVBhdGggKz0gdXJsRGV0YWlscy5zZWFyY2g7XG4gICAgfVxuICB9XG4gIHJldHVybiBhcGlQYXRoO1xufVxuXG4vKipcbiAqIGhhbmRsZSBhbnkgb3RoZXIgVjEgQVBJIGNhbGxcbiAqIEBkZXByZWNhdGVkXG4gKiBAcGFyYW0gcmVxXG4gKiBAcGFyYW0gcmVzXG4gKiBAcGFyYW0gbmV4dFxuICovXG5mdW5jdGlvbiBoYW5kbGVSRVNUKHJlcTogZXhwcmVzcy5SZXF1ZXN0LCByZXM6IGV4cHJlc3MuUmVzcG9uc2UsIG5leHQ6IGV4cHJlc3MuTmV4dEZ1bmN0aW9uKSB7XG4gIGNvbnN0IG1ldGhvZCA9IHJlcS5tZXRob2Q7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBiaXRnb1VSTCA9IGJpdGdvLnVybChjcmVhdGVBUElQYXRoKHJlcSkpO1xuICByZXR1cm4gcmVkaXJlY3RSZXF1ZXN0KGJpdGdvLCBtZXRob2QsIGJpdGdvVVJMLCByZXEsIG5leHQpO1xufVxuXG4vKipcbiAqIGhhbmRsZSBhbnkgb3RoZXIgVjIgQVBJIGNhbGxcbiAqIEBwYXJhbSByZXFcbiAqIEBwYXJhbSByZXNcbiAqIEBwYXJhbSBuZXh0XG4gKi9cbmZ1bmN0aW9uIGhhbmRsZVYyVXNlclJFU1QocmVxOiBleHByZXNzLlJlcXVlc3QsIHJlczogZXhwcmVzcy5SZXNwb25zZSwgbmV4dDogZXhwcmVzcy5OZXh0RnVuY3Rpb24pIHtcbiAgY29uc3QgbWV0aG9kID0gcmVxLm1ldGhvZDtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGJpdGdvVVJMID0gYml0Z28udXJsKCcvdXNlcicgKyBjcmVhdGVBUElQYXRoKHJlcSksIDIpO1xuICByZXR1cm4gcmVkaXJlY3RSZXF1ZXN0KGJpdGdvLCBtZXRob2QsIGJpdGdvVVJMLCByZXEsIG5leHQpO1xufVxuXG4vKipcbiAqIGhhbmRsZSB2MiBhZGRyZXNzIHZhbGlkYXRpb25cbiAqIEBwYXJhbSByZXFcbiAqL1xuZnVuY3Rpb24gaGFuZGxlVjJWZXJpZnlBZGRyZXNzKHJlcTogZXhwcmVzcy5SZXF1ZXN0KTogeyBpc1ZhbGlkOiBib29sZWFuIH0ge1xuICBpZiAoIV8uaXNTdHJpbmcocmVxLmJvZHkuYWRkcmVzcykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdGVkIGFkZHJlc3MgdG8gYmUgYSBzdHJpbmcnKTtcbiAgfVxuXG4gIGlmIChyZXEuYm9keS5zdXBwb3J0T2xkU2NyaXB0SGFzaFZlcnNpb24gIT09IHVuZGVmaW5lZCAmJiAhXy5pc0Jvb2xlYW4ocmVxLmJvZHkuc3VwcG9ydE9sZFNjcmlwdEhhc2hWZXJzaW9uKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0ZWQgc3VwcG9ydE9sZFNjcmlwdEhhc2hWZXJzaW9uIHRvIGJlIGEgYm9vbGVhbi4nKTtcbiAgfVxuXG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuXG4gIGlmIChjb2luIGluc3RhbmNlb2YgQ29pbi5BYnN0cmFjdFV0eG9Db2luKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGlzVmFsaWQ6IGNvaW4uaXNWYWxpZEFkZHJlc3MocmVxLmJvZHkuYWRkcmVzcywgISFyZXEuYm9keS5zdXBwb3J0T2xkU2NyaXB0SGFzaFZlcnNpb24pLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGlzVmFsaWQ6IGNvaW4uaXNWYWxpZEFkZHJlc3MocmVxLmJvZHkuYWRkcmVzcyksXG4gIH07XG59XG5cbi8qKlxuICogaGFuZGxlIGFkZHJlc3MgY2Fub25pY2FsaXphdGlvblxuICogQHBhcmFtIHJlcVxuICovXG5mdW5jdGlvbiBoYW5kbGVDYW5vbmljYWxBZGRyZXNzKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICBpZiAoIVsnbHRjJywgJ2JjaCcsICdic3YnXS5pbmNsdWRlcyhjb2luLmdldEZhbWlseSgpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignb25seSBMaXRlY29pbi9CaXRjb2luIENhc2gvQml0Y29pbiBTViBhZGRyZXNzIGNhbm9uaWNhbGl6YXRpb24gaXMgc3VwcG9ydGVkJyk7XG4gIH1cblxuICBjb25zdCBhZGRyZXNzID0gcmVxLmJvZHkuYWRkcmVzcztcbiAgY29uc3QgZmFsbGJhY2tWZXJzaW9uID0gcmVxLmJvZHkuc2NyaXB0SGFzaFZlcnNpb247IC8vIGRlcHJlY2F0ZVxuICBjb25zdCB2ZXJzaW9uID0gcmVxLmJvZHkudmVyc2lvbjtcbiAgcmV0dXJuIChjb2luIGFzIENvaW4uQmNoIHwgQ29pbi5Cc3YgfCBDb2luLkx0YykuY2Fub25pY2FsQWRkcmVzcyhhZGRyZXNzLCB2ZXJzaW9uIHx8IGZhbGxiYWNrVmVyc2lvbik7XG59XG5cbmZ1bmN0aW9uIGdldFdhbGxldFB3RnJvbUVudih3YWxsZXRJZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgbmFtZSA9IGBXQUxMRVRfJHt3YWxsZXRJZH1fUEFTU1BIUkFTRWA7XG4gIGNvbnN0IHdhbGxldFB3ID0gcHJvY2Vzcy5lbnZbbmFtZV07XG4gIGlmICh3YWxsZXRQdyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgZmluZCB3YWxsZXQgcGFzc3BocmFzZSAke25hbWV9IGluIGVudmlyb25tZW50YCk7XG4gIH1cbiAgcmV0dXJuIHdhbGxldFB3O1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRFbmNyeXB0ZWRQcml2S2V5KHBhdGg6IHN0cmluZywgd2FsbGV0SWQ6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHByaXZLZXlGaWxlID0gYXdhaXQgZnMucmVhZEZpbGUocGF0aCwgeyBlbmNvZGluZzogJ3V0ZjgnIH0pO1xuICBjb25zdCBlbmNyeXB0ZWRQcml2S2V5ID0gSlNPTi5wYXJzZShwcml2S2V5RmlsZSk7XG4gIGlmIChlbmNyeXB0ZWRQcml2S2V5W3dhbGxldElkXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgZmluZCBhIGZpZWxkIGZvciB3YWxsZXRJZDogJHt3YWxsZXRJZH0gaW4gJHtwYXRofWApO1xuICB9XG4gIHJldHVybiBlbmNyeXB0ZWRQcml2S2V5W3dhbGxldElkXTtcbn1cblxuZnVuY3Rpb24gZGVjcnlwdFByaXZLZXkoYmc6IEJpdEdvLCBlbmNyeXB0ZWRQcml2S2V5OiBzdHJpbmcsIHdhbGxldFB3OiBzdHJpbmcpOiBzdHJpbmcge1xuICB0cnkge1xuICAgIHJldHVybiBiZy5kZWNyeXB0KHsgcGFzc3dvcmQ6IHdhbGxldFB3LCBpbnB1dDogZW5jcnlwdGVkUHJpdktleSB9KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hlbiB0cnlpbmcgdG8gZGVjcnlwdCBwcml2YXRlIGtleTogJHtlfWApO1xuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVWMkdlbmVyYXRlU2hhcmVUU1MocmVxOiBleHByZXNzLlJlcXVlc3QpOiBQcm9taXNlPGFueT4ge1xuICBjb25zdCB3YWxsZXRJZCA9IHJlcS5ib2R5LnR4UmVxdWVzdCA/IHJlcS5ib2R5LnR4UmVxdWVzdC53YWxsZXRJZCA6IHJlcS5ib2R5LnRzc1BhcmFtcy50eFJlcXVlc3Qud2FsbGV0SWQ7XG4gIGlmICghd2FsbGV0SWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgcmVxdWlyZWQgZmllbGQ6IHdhbGxldElkJyk7XG4gIH1cblxuICBjb25zdCB3YWxsZXRQdyA9IGdldFdhbGxldFB3RnJvbUVudih3YWxsZXRJZCk7XG4gIGNvbnN0IHsgc2lnbmVyRmlsZVN5c3RlbVBhdGggfSA9IHJlcS5jb25maWc7XG5cbiAgaWYgKCFzaWduZXJGaWxlU3lzdGVtUGF0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyByZXF1aXJlZCBjb25maWd1cmF0aW9uOiBzaWduZXJGaWxlU3lzdGVtUGF0aCcpO1xuICB9XG5cbiAgY29uc3QgZW5jcnlwdGVkUHJpdktleSA9IGF3YWl0IGdldEVuY3J5cHRlZFByaXZLZXkoc2lnbmVyRmlsZVN5c3RlbVBhdGgsIHdhbGxldElkKTtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IHByaXZLZXkgPSBkZWNyeXB0UHJpdktleShiaXRnbywgZW5jcnlwdGVkUHJpdktleSwgd2FsbGV0UHcpO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICByZXEuYm9keS5wcnYgPSBwcml2S2V5O1xuICByZXEuYm9keS53YWxsZXRQYXNzcGhyYXNlID0gd2FsbGV0UHc7XG4gIHRyeSB7XG4gICAgaWYgKGNvaW4uZ2V0TVBDQWxnb3JpdGhtKCkgPT09IE1QQ1R5cGUuRUREU0EpIHtcbiAgICAgIGNvbnN0IGVkZHNhVXRpbHMgPSBuZXcgRWRkc2FVdGlscyhiaXRnbywgY29pbik7XG4gICAgICBzd2l0Y2ggKHJlcS5wYXJhbXMuc2hhcmV0eXBlKSB7XG4gICAgICAgIGNhc2UgU2hhcmVUeXBlLkNvbW1pdG1lbnQ6XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IGVkZHNhVXRpbHMuY3JlYXRlQ29tbWl0bWVudFNoYXJlRnJvbVR4UmVxdWVzdChyZXEuYm9keSk7XG4gICAgICAgIGNhc2UgU2hhcmVUeXBlLlI6XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IGVkZHNhVXRpbHMuY3JlYXRlUlNoYXJlRnJvbVR4UmVxdWVzdChyZXEuYm9keSk7XG4gICAgICAgIGNhc2UgU2hhcmVUeXBlLkc6XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IGVkZHNhVXRpbHMuY3JlYXRlR1NoYXJlRnJvbVR4UmVxdWVzdChyZXEuYm9keSk7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYFNoYXJlIHR5cGUgJHtyZXEucGFyYW1zLnNoYXJldHlwZX0gbm90IHN1cHBvcnRlZCwgb25seSBjb21taXRtZW50LCBHIGFuZCBSIHNoYXJlIGdlbmVyYXRpb24gaXMgc3VwcG9ydGVkLmBcbiAgICAgICAgICApO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoY29pbi5nZXRNUENBbGdvcml0aG0oKSA9PT0gTVBDVHlwZS5FQ0RTQSkge1xuICAgICAgY29uc3QgaXNNUEN2MiA9IFtcbiAgICAgICAgU2hhcmVUeXBlLk1QQ3YyUm91bmQxLnRvU3RyaW5nKCksXG4gICAgICAgIFNoYXJlVHlwZS5NUEN2MlJvdW5kMi50b1N0cmluZygpLFxuICAgICAgICBTaGFyZVR5cGUuTVBDdjJSb3VuZDMudG9TdHJpbmcoKSxcbiAgICAgIF0uaW5jbHVkZXMocmVxLnBhcmFtcy5zaGFyZXR5cGUpO1xuXG4gICAgICBpZiAoaXNNUEN2Mikge1xuICAgICAgICBjb25zdCBlY2RzYU1QQ3YyVXRpbHMgPSBuZXcgRWNkc2FNUEN2MlV0aWxzKGJpdGdvLCBjb2luKTtcbiAgICAgICAgc3dpdGNoIChyZXEucGFyYW1zLnNoYXJldHlwZSkge1xuICAgICAgICAgIGNhc2UgU2hhcmVUeXBlLk1QQ3YyUm91bmQxOlxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGVjZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQxU2hhcmUocmVxLmJvZHkpO1xuICAgICAgICAgIGNhc2UgU2hhcmVUeXBlLk1QQ3YyUm91bmQyOlxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGVjZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQyU2hhcmUocmVxLmJvZHkpO1xuICAgICAgICAgIGNhc2UgU2hhcmVUeXBlLk1QQ3YyUm91bmQzOlxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGVjZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQzU2hhcmUocmVxLmJvZHkpO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgIGBTaGFyZSB0eXBlICR7cmVxLnBhcmFtcy5zaGFyZXR5cGV9IG5vdCBzdXBwb3J0ZWQgZm9yIE1QQ3YyLCBvbmx5IE1QQ3YyUm91bmQxLCBNUEN2MlJvdW5kMiBhbmQgTVBDdjJSb3VuZDMgaXMgc3VwcG9ydGVkLmBcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGVjZHNhVXRpbHMgPSBuZXcgRWNkc2FVdGlscyhiaXRnbywgY29pbik7XG4gICAgICAgIHN3aXRjaCAocmVxLnBhcmFtcy5zaGFyZXR5cGUpIHtcbiAgICAgICAgICBjYXNlIFNoYXJlVHlwZS5QYWlsbGllck1vZHVsdXM6XG4gICAgICAgICAgICByZXR1cm4gZWNkc2FVdGlscy5nZXRPZmZsaW5lU2lnbmVyUGFpbGxpZXJNb2R1bHVzKHJlcS5ib2R5KTtcbiAgICAgICAgICBjYXNlIFNoYXJlVHlwZS5LOlxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGVjZHNhVXRpbHMuY3JlYXRlT2ZmbGluZUtTaGFyZShyZXEuYm9keSk7XG4gICAgICAgICAgY2FzZSBTaGFyZVR5cGUuTXVEZWx0YTpcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCBlY2RzYVV0aWxzLmNyZWF0ZU9mZmxpbmVNdURlbHRhU2hhcmUocmVxLmJvZHkpO1xuICAgICAgICAgIGNhc2UgU2hhcmVUeXBlLlM6XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgZWNkc2FVdGlscy5jcmVhdGVPZmZsaW5lU1NoYXJlKHJlcS5ib2R5KTtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICBgU2hhcmUgdHlwZSAke3JlcS5wYXJhbXMuc2hhcmV0eXBlfSBub3Qgc3VwcG9ydGVkLCBvbmx5IFBhaWxsaWVyTW9kdWx1cywgSywgTVVEZWx0YSwgYW5kIFMgc2hhcmUgZ2VuZXJhdGlvbiBpcyBzdXBwb3J0ZWQuYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE1QQyBBbGdvcml0aG0gJHtjb2luLmdldE1QQ0FsZ29yaXRobSgpfSBpcyBub3Qgc3VwcG9ydGVkLmApO1xuICAgIH1cbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zb2xlLmVycm9yKCdlcnJvciB3aGlsZSBzaWduaW5nIHdhbGxldCB0cmFuc2FjdGlvbiAnLCBlcnJvcik7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZVYyU2lnblRTU1dhbGxldFR4KHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICBjb25zdCB3YWxsZXQgPSBhd2FpdCBjb2luLndhbGxldHMoKS5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KTtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgd2FsbGV0LnNpZ25UcmFuc2FjdGlvbihjcmVhdGVUU1NTZW5kUGFyYW1zKHJlcSwgd2FsbGV0KSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc29sZS5lcnJvcignZXJyb3Igd2hpbGUgc2lnbmluZyB3YWxsZXQgdHJhbnNhY3Rpb24gJywgZXJyb3IpO1xuICAgIHRocm93IGVycm9yO1xuICB9XG59XG5cbi8qKlxuICogVGhpcyByb3V0ZSBpcyB1c2VkIHRvIHNpZ24gd2hpbGUgZXh0ZXJuYWwgZXhwcmVzcyBzaWduZXIgaXMgZW5hYmxlZFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJTaWduKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IHdhbGxldElkID0gcmVxLmJvZHkudHhQcmVidWlsZD8ud2FsbGV0SWQ7XG5cbiAgaWYgKCF3YWxsZXRJZCkge1xuICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyByZXF1aXJlZCBmaWVsZDogd2FsbGV0SWQnKTtcbiAgfVxuXG4gIGNvbnN0IHdhbGxldFB3ID0gZ2V0V2FsbGV0UHdGcm9tRW52KHdhbGxldElkKTtcbiAgY29uc3QgeyBzaWduZXJGaWxlU3lzdGVtUGF0aCB9ID0gcmVxLmNvbmZpZztcblxuICBpZiAoIXNpZ25lckZpbGVTeXN0ZW1QYXRoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHJlcXVpcmVkIGNvbmZpZ3VyYXRpb246IHNpZ25lckZpbGVTeXN0ZW1QYXRoJyk7XG4gIH1cblxuICBjb25zdCBlbmNyeXB0ZWRQcml2S2V5ID0gYXdhaXQgZ2V0RW5jcnlwdGVkUHJpdktleShzaWduZXJGaWxlU3lzdGVtUGF0aCwgd2FsbGV0SWQpO1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgbGV0IHByaXZLZXkgPSBkZWNyeXB0UHJpdktleShiaXRnbywgZW5jcnlwdGVkUHJpdktleSwgd2FsbGV0UHcpO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICBpZiAocmVxLmJvZHkuZGVyaXZhdGlvblNlZWQpIHtcbiAgICBwcml2S2V5ID0gY29pbi5kZXJpdmVLZXlXaXRoU2VlZCh7IGtleTogcHJpdktleSwgc2VlZDogcmVxLmJvZHkuZGVyaXZhdGlvblNlZWQgfSkua2V5O1xuICB9XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IGNvaW4uc2lnblRyYW5zYWN0aW9uKHsgLi4ucmVxLmJvZHksIHBydjogcHJpdktleSB9KTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zb2xlLmxvZygnZXJyb3Igd2hpbGUgc2lnbmluZyB3YWxsZXQgdHJhbnNhY3Rpb24gJywgZXJyb3IpO1xuICAgIHRocm93IGVycm9yO1xuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVWMk9GQ1NpZ25QYXlsb2FkSW5FeHRTaWduaW5nTW9kZShcbiAgcmVxOiBleHByZXNzLlJlcXVlc3Rcbik6IFByb21pc2U8eyBwYXlsb2FkOiBzdHJpbmc7IHNpZ25hdHVyZTogc3RyaW5nIH0+IHtcbiAgY29uc3Qgd2FsbGV0SWQgPSByZXEuYm9keS53YWxsZXRJZDtcbiAgY29uc3QgcGF5bG9hZCA9IHJlcS5ib2R5LnBheWxvYWQ7XG4gIGNvbnN0IGJvZHlXYWxsZXRQYXNzcGhyYXNlID0gcmVxLmJvZHkud2FsbGV0UGFzc3BocmFzZTtcbiAgY29uc3Qgb2ZjQ29pbk5hbWUgPSAnb2ZjJztcblxuICBpZiAoIXBheWxvYWQpIHtcbiAgICB0aHJvdyBuZXcgQXBpUmVzcG9uc2VFcnJvcignTWlzc2luZyByZXF1aXJlZCBmaWVsZDogcGF5bG9hZCcsIDQwMCk7XG4gIH1cblxuICBpZiAoIXdhbGxldElkKSB7XG4gICAgdGhyb3cgbmV3IEFwaVJlc3BvbnNlRXJyb3IoJ01pc3NpbmcgcmVxdWlyZWQgZmllbGQ6IHdhbGxldElkJywgNDAwKTtcbiAgfVxuXG4gIC8vIGZldGNoIHRoZSBwYXNzd29yZCBmb3IgdGhlIGdpdmVuIHdhbGxldElkIGZyb20gdGhlIGJvZHkgb3IgdGhlIGVudi4gVGhpcyBpcyByZXF1aXJlZCBmb3IgZGVjcnlwdGluZyB0aGUgcHJpdmF0ZSBrZXkgdGhhdCBiZWxvbmdzIHRvIHRoYXQgd2FsbGV0LlxuICBjb25zdCB3YWxsZXRQdyA9IGJvZHlXYWxsZXRQYXNzcGhyYXNlIHx8IGdldFdhbGxldFB3RnJvbUVudih3YWxsZXRJZCk7XG5cbiAgY29uc3QgeyBzaWduZXJGaWxlU3lzdGVtUGF0aCB9ID0gcmVxLmNvbmZpZztcbiAgaWYgKCFzaWduZXJGaWxlU3lzdGVtUGF0aCkge1xuICAgIHRocm93IG5ldyBBcGlSZXNwb25zZUVycm9yKCdNaXNzaW5nIHJlcXVpcmVkIGNvbmZpZ3VyYXRpb246IHNpZ25lckZpbGVTeXN0ZW1QYXRoJywgNTAwKTtcbiAgfVxuICAvLyBnZXQgdGhlIGVuY3J5cHRlZCBwcml2YXRlIGtleSBmcm9tIHRoZSBsb2NhbCBKU09OIGZpbGUgKGVuY3J5cHRlZFByaXZLZXlzLmpzb24pIChwb3B1bGF0ZWQgdXNpbmcgZmV0Y2hFbmNyeXB0ZWRQcml2YXRlS2V5cy50cylcbiAgY29uc3QgZW5jcnlwdGVkUHJpdktleSA9IGF3YWl0IGdldEVuY3J5cHRlZFByaXZLZXkoc2lnbmVyRmlsZVN5c3RlbVBhdGgsIHdhbGxldElkKTtcblxuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcblxuICAvLyBkZWNyeXB0IHRoZSBlbmNyeXB0ZWQgcHJpdmF0ZSBrZXkgdXNpbmcgdGhlIHdhbGxldCBwd2RcbiAgY29uc3QgcHJpdktleSA9IGRlY3J5cHRQcml2S2V5KGJpdGdvLCBlbmNyeXB0ZWRQcml2S2V5LCB3YWxsZXRQdyk7XG5cbiAgLy8gY3JlYXRlIGEgQmFzZUNvaW4gaW5zdGFuY2UgZm9yICdvZmMnXG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKG9mY0NvaW5OYW1lKTtcblxuICAvLyBzdHJpbmdpZnkgdGhlIHBheWxvYWQgaWYgbm90IGFscmVhZHkgYSBzdHJpbmdcbiAgY29uc3Qgc3RyaW5naWZpZWRQYXlsb2FkID0gdHlwZW9mIHBheWxvYWQgPT09ICdzdHJpbmcnID8gcGF5bG9hZCA6IEpTT04uc3RyaW5naWZ5KHBheWxvYWQpO1xuXG4gIHRyeSB7XG4gICAgLy8gc2lnbiB0aGUgbWVzc2FnZSB1c2luZyB0aGUgZGVjcnlwdGVkIHByaXZhdGUga2V5XG4gICAgY29uc3Qgc2lnbmF0dXJlID0gKGF3YWl0IGNvaW4uc2lnbk1lc3NhZ2UoeyBwcnY6IHByaXZLZXkgfSwgc3RyaW5naWZpZWRQYXlsb2FkKSkudG9TdHJpbmcoJ2hleCcpO1xuICAgIHJldHVybiB7XG4gICAgICBwYXlsb2FkOiBzdHJpbmdpZmllZFBheWxvYWQsXG4gICAgICBzaWduYXR1cmUsXG4gICAgfTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zb2xlLmxvZygnRXJyb3Igd2hpbGUgc2lnbmluZyBtZXNzYWdlLicsIGVycm9yKTtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJPRkNTaWduUGF5bG9hZChyZXE6IGV4cHJlc3MuUmVxdWVzdCk6IFByb21pc2U8eyBwYXlsb2FkOiBzdHJpbmc7IHNpZ25hdHVyZTogc3RyaW5nIH0+IHtcbiAgY29uc3Qgd2FsbGV0SWQgPSByZXEuYm9keS53YWxsZXRJZDtcbiAgY29uc3QgcGF5bG9hZCA9IHJlcS5ib2R5LnBheWxvYWQ7XG4gIGNvbnN0IGJvZHlXYWxsZXRQYXNzcGhyYXNlID0gcmVxLmJvZHkud2FsbGV0UGFzc3BocmFzZTtcbiAgY29uc3Qgb2ZjQ29pbk5hbWUgPSAnb2ZjJztcblxuICAvLyBJZiB0aGUgZXh0ZXJuYWxTaWduZXJVcmwgaXMgc2V0LCBmb3J3YXJkIHRoZSByZXF1ZXN0IHRvIHRoZSBleHByZXNzIHNlcnZlciBob3N0ZWQgb24gdGhlIGV4dGVybmFsU2lnbmVyVXJsXG4gIGNvbnN0IGV4dGVybmFsU2lnbmVyVXJsID0gcmVxLmNvbmZpZz8uZXh0ZXJuYWxTaWduZXJVcmw7XG4gIGlmIChleHRlcm5hbFNpZ25lclVybCkge1xuICAgIGNvbnN0IHsgYm9keTogcGF5bG9hZFdpdGhTaWduYXR1cmUgfSA9IGF3YWl0IHJldHJ5UHJvbWlzZShcbiAgICAgICgpID0+XG4gICAgICAgIHN1cGVyYWdlbnRcbiAgICAgICAgICAucG9zdChgJHtleHRlcm5hbFNpZ25lclVybH0vYXBpL3YyL29mYy9zaWduUGF5bG9hZGApXG4gICAgICAgICAgLnR5cGUoJ2pzb24nKVxuICAgICAgICAgIC5zZW5kKHsgd2FsbGV0SWQ6IHdhbGxldElkLCBwYXlsb2FkOiBwYXlsb2FkIH0pLFxuICAgICAgKGVyciwgdHJ5Q291bnQpID0+IHtcbiAgICAgICAgZGVidWcoYGZhaWxlZCB0byBjb25uZWN0IHRvIGV4dGVybmFsIHNpZ25lciAoYXR0ZW1wdCAke3RyeUNvdW50fSwgZXJyb3I6ICR7ZXJyLm1lc3NhZ2V9KWApO1xuICAgICAgfVxuICAgICk7XG4gICAgcmV0dXJuIHBheWxvYWRXaXRoU2lnbmF0dXJlO1xuICB9XG5cbiAgaWYgKCFwYXlsb2FkKSB7XG4gICAgdGhyb3cgbmV3IEFwaVJlc3BvbnNlRXJyb3IoJ01pc3NpbmcgcmVxdWlyZWQgZmllbGQ6IHBheWxvYWQnLCA0MDApO1xuICB9XG5cbiAgaWYgKCF3YWxsZXRJZCkge1xuICAgIHRocm93IG5ldyBBcGlSZXNwb25zZUVycm9yKCdNaXNzaW5nIHJlcXVpcmVkIGZpZWxkOiB3YWxsZXRJZCcsIDQwMCk7XG4gIH1cblxuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcblxuICAvLyBUaGlzIGlzIHRvIHNldCB1cyB1cCBmb3IgbXVsdGlwbGUgdHJhZGluZyBhY2NvdW50cyBwZXIgZW50ZXJwcmlzZVxuICBjb25zdCB3YWxsZXQgPSBhd2FpdCBiaXRnby5jb2luKG9mY0NvaW5OYW1lKS53YWxsZXRzKCkuZ2V0KHsgaWQ6IHdhbGxldElkIH0pO1xuXG4gIGlmICh3YWxsZXQgPT09IHVuZGVmaW5lZCkge1xuICAgIHRocm93IG5ldyBBcGlSZXNwb25zZUVycm9yKGBDb3VsZCBub3QgZmluZCBPRkMgd2FsbGV0ICR7d2FsbGV0SWR9YCwgNDA0KTtcbiAgfVxuXG4gIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSBib2R5V2FsbGV0UGFzc3BocmFzZSB8fCBnZXRXYWxsZXRQd0Zyb21FbnYod2FsbGV0LmlkKCkpO1xuICBjb25zdCB0cmFkaW5nQWNjb3VudCA9IHdhbGxldC50b1RyYWRpbmdBY2NvdW50KCk7XG4gIGNvbnN0IHN0cmluZ2lmaWVkUGF5bG9hZCA9IEpTT04uc3RyaW5naWZ5KHJlcS5ib2R5LnBheWxvYWQpO1xuICBjb25zdCBzaWduYXR1cmUgPSBhd2FpdCB0cmFkaW5nQWNjb3VudC5zaWduUGF5bG9hZCh7XG4gICAgcGF5bG9hZDogc3RyaW5naWZpZWRQYXlsb2FkLFxuICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gIH0pO1xuICByZXR1cm4ge1xuICAgIHBheWxvYWQ6IHN0cmluZ2lmaWVkUGF5bG9hZCxcbiAgICBzaWduYXR1cmUsXG4gIH07XG59XG5cbi8qKlxuICogaGFuZGxlIG5ldyB3YWxsZXQgY3JlYXRpb25cbiAqIEBwYXJhbSByZXFcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZVYyR2VuZXJhdGVXYWxsZXQocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4ud2FsbGV0cygpLmdlbmVyYXRlV2FsbGV0KHJlcS5ib2R5KTtcbiAgaWYgKHJlcS5xdWVyeS5pbmNsdWRlS2V5Y2hhaW5zID09PSAnZmFsc2UnKSB7XG4gICAgcmV0dXJuIHJlc3VsdC53YWxsZXQudG9KU09OKCk7XG4gIH1cbiAgcmV0dXJuIHsgLi4ucmVzdWx0LCB3YWxsZXQ6IHJlc3VsdC53YWxsZXQudG9KU09OKCkgfTtcbn1cblxuLyoqXG4gKiBoYW5kbGUgbmV3IGFkZHJlc3MgY3JlYXRpb25cbiAqIEBwYXJhbSByZXFcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZVYyQ3JlYXRlQWRkcmVzcyhyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcbiAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgY29pbi53YWxsZXRzKCkuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQgfSk7XG4gIHJldHVybiB3YWxsZXQuY3JlYXRlQWRkcmVzcyhyZXEuYm9keSk7XG59XG5cbi8qKlxuICogaGFuZGxlIHYyIGFwcHJvdmUgdHJhbnNhY3Rpb25cbiAqIEBwYXJhbSByZXFcbiAqL1xuYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJQZW5kaW5nQXBwcm92YWwocmVxOiBleHByZXNzLlJlcXVlc3QpOiBQcm9taXNlPGFueT4ge1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcbiAgY29uc3QgcGFyYW1zID0gcmVxLmJvZHkgfHwge307XG4gIGNvbnN0IHBlbmRpbmdBcHByb3ZhbCA9IGF3YWl0IGNvaW4ucGVuZGluZ0FwcHJvdmFscygpLmdldCh7IGlkOiByZXEucGFyYW1zLmlkIH0pO1xuICBpZiAocGFyYW1zLnN0YXRlID09PSAnYXBwcm92ZWQnKSB7XG4gICAgcmV0dXJuIHBlbmRpbmdBcHByb3ZhbC5hcHByb3ZlKHBhcmFtcyk7XG4gIH1cbiAgcmV0dXJuIHBlbmRpbmdBcHByb3ZhbC5yZWplY3QocGFyYW1zKTtcbn1cblxuLyoqXG4gKiBjcmVhdGUgYSBrZXljaGFpblxuICogQHBhcmFtIHJlcVxuICovXG5mdW5jdGlvbiBoYW5kbGVWMkNyZWF0ZUxvY2FsS2V5Q2hhaW4ocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gIHJldHVybiBjb2luLmtleWNoYWlucygpLmNyZWF0ZShyZXEuYm9keSk7XG59XG5cbi8qKlxuICogaGFuZGxlIHdhbGxldCBzaGFyZVxuICogQHBhcmFtIHJlcVxuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVWMlNoYXJlV2FsbGV0KHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICBjb25zdCB3YWxsZXQgPSBhd2FpdCBjb2luLndhbGxldHMoKS5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KTtcbiAgcmV0dXJuIHdhbGxldC5zaGFyZVdhbGxldChyZXEuYm9keSk7XG59XG5cbi8qKlxuICogaGFuZGxlIGFjY2VwdCB3YWxsZXQgc2hhcmVcbiAqIEBwYXJhbSByZXFcbiAqL1xuYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJBY2NlcHRXYWxsZXRTaGFyZShyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcbiAgY29uc3QgcGFyYW1zID0gXy5leHRlbmQoe30sIHJlcS5ib2R5LCB7IHdhbGxldFNoYXJlSWQ6IHJlcS5wYXJhbXMuaWQgfSk7XG4gIHJldHVybiBjb2luLndhbGxldHMoKS5hY2NlcHRTaGFyZShwYXJhbXMpO1xufVxuXG4vKipcbiAqIGhhbmRsZSB3YWxsZXQgc2lnbiB0cmFuc2FjdGlvblxuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVWMlNpZ25UeFdhbGxldChyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcbiAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgY29pbi53YWxsZXRzKCkuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQgfSk7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHdhbGxldC5zaWduVHJhbnNhY3Rpb24oY3JlYXRlU2VuZFBhcmFtcyhyZXEpKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zb2xlLmxvZygnZXJyb3Igd2hpbGUgc2lnbmluZyB3YWxsZXQgdHJhbnNhY3Rpb24gJywgZXJyb3IpO1xuICAgIHRocm93IGVycm9yO1xuICB9XG59XG5cbi8qKlxuICogaGFuZGxlIHNpZ24gdHJhbnNhY3Rpb25cbiAqIEBwYXJhbSByZXFcbiAqL1xuYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJTaWduVHgocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IGNvaW4uc2lnblRyYW5zYWN0aW9uKHJlcS5ib2R5KTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zb2xlLmxvZygnZXJyb3Igd2hpbGUgc2lnbmluZyB0aGUgdHJhbnNhY3Rpb24gJywgZXJyb3IpO1xuICAgIHRocm93IGVycm9yO1xuICB9XG59XG5cbi8qKlxuICogaGFuZGxlIHdhbGxldCByZWNvdmVyIHRva2VuXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZVYyUmVjb3ZlclRva2VuKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuXG4gIGNvbnN0IHdhbGxldCA9IGF3YWl0IGNvaW4ud2FsbGV0cygpLmdldCh7IGlkOiByZXEucGFyYW1zLmlkIH0pO1xuICByZXR1cm4gd2FsbGV0LnJlY292ZXJUb2tlbihyZXEuYm9keSk7XG59XG5cbi8qKlxuICogaGFuZGxlIHdhbGxldCBmYW5vdXQgdW5zcGVudHNcbiAqIEBwYXJhbSByZXFcbiAqL1xuYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJDb25zb2xpZGF0ZVVuc3BlbnRzKHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICBjb25zdCB3YWxsZXQgPSBhd2FpdCBjb2luLndhbGxldHMoKS5nZXQoeyBpZDogcmVxLnBhcmFtcy5pZCB9KTtcbiAgcmV0dXJuIHdhbGxldC5jb25zb2xpZGF0ZVVuc3BlbnRzKGNyZWF0ZVNlbmRQYXJhbXMocmVxKSk7XG59XG5cbi8qKlxuICogSGFuZGxlIFdhbGxldCBBY2NvdW50IENvbnNvbGlkYXRpb24uXG4gKlxuICogQHBhcmFtIHJlcVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJDb25zb2xpZGF0ZUFjY291bnQocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG5cbiAgaWYgKHJlcS5ib2R5LmNvbnNvbGlkYXRlQWRkcmVzc2VzICYmICFfLmlzQXJyYXkocmVxLmJvZHkuY29uc29saWRhdGVBZGRyZXNzZXMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjb25zb2xpZGF0ZSBhZGRyZXNzIG11c3QgYmUgYW4gYXJyYXkgb2YgYWRkcmVzc2VzJyk7XG4gIH1cblxuICBpZiAoIWNvaW4uYWxsb3dzQWNjb3VudENvbnNvbGlkYXRpb25zKCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgY29pbiBzZWxlY3RlZCcpO1xuICB9XG5cbiAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgY29pbi53YWxsZXRzKCkuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQgfSk7XG5cbiAgbGV0IHJlc3VsdDogYW55O1xuICB0cnkge1xuICAgIGlmIChjb2luLnN1cHBvcnRzVHNzKCkpIHtcbiAgICAgIHJlc3VsdCA9IGF3YWl0IHdhbGxldC5zZW5kQWNjb3VudENvbnNvbGlkYXRpb25zKGNyZWF0ZVRTU1NlbmRQYXJhbXMocmVxLCB3YWxsZXQpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzdWx0ID0gYXdhaXQgd2FsbGV0LnNlbmRBY2NvdW50Q29uc29saWRhdGlvbnMoY3JlYXRlU2VuZFBhcmFtcyhyZXEpKTtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGVyci5zdGF0dXMgPSA0MDA7XG4gICAgdGhyb3cgZXJyO1xuICB9XG5cbiAgLy8gd2UgaGFkIGZhaWx1cmVzIHRvIGhhbmRsZVxuICBpZiAocmVzdWx0LmZhaWx1cmUubGVuZ3RoICYmIHJlc3VsdC5mYWlsdXJlLmxlbmd0aCA+IDApIHtcbiAgICBsZXQgbXNnID0gJyc7XG4gICAgbGV0IHN0YXR1cyA9IDIwMjtcblxuICAgIGlmIChyZXN1bHQuc3VjY2Vzcy5sZW5ndGggJiYgcmVzdWx0LnN1Y2Nlc3MubGVuZ3RoID4gMCkge1xuICAgICAgLy8gYnV0IHdlIGFsc28gaGFkIHN1Y2Nlc3Nlc1xuICAgICAgbXNnID0gYFRyYW5zYWN0aW9ucyBmYWlsZWQ6ICR7cmVzdWx0LmZhaWx1cmUubGVuZ3RofSBhbmQgc3VjY2VlZGVkOiAke3Jlc3VsdC5zdWNjZXNzLmxlbmd0aH1gO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBvciBpbiB0aGlzIGNhc2Ugb25seSBmYWlsdXJlc1xuICAgICAgc3RhdHVzID0gNDAwO1xuICAgICAgbXNnID0gYEFsbCB0cmFuc2FjdGlvbnMgZmFpbGVkYDtcbiAgICB9XG5cbiAgICB0aHJvdyBhcGlSZXNwb25zZShzdGF0dXMsIHJlc3VsdCwgbXNnKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogaGFuZGxlIHdhbGxldCBmYW5vdXQgdW5zcGVudHNcbiAqIEBwYXJhbSByZXFcbiAqL1xuYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJGYW5PdXRVbnNwZW50cyhyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcbiAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgY29pbi53YWxsZXRzKCkuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQgfSk7XG4gIHJldHVybiB3YWxsZXQuZmFub3V0VW5zcGVudHMoY3JlYXRlU2VuZFBhcmFtcyhyZXEpKTtcbn1cblxuLyoqXG4gKiBoYW5kbGUgd2FsbGV0IHN3ZWVwXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZVYyU3dlZXAocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gIGNvbnN0IHdhbGxldCA9IGF3YWl0IGNvaW4ud2FsbGV0cygpLmdldCh7IGlkOiByZXEucGFyYW1zLmlkIH0pO1xuICByZXR1cm4gd2FsbGV0LnN3ZWVwKGNyZWF0ZVNlbmRQYXJhbXMocmVxKSk7XG59XG5cbi8qKlxuICogaGFuZGxlIENQRlAgYWNjZWxlcmF0ZSB0cmFuc2FjdGlvbiBjcmVhdGlvblxuICogQHBhcmFtIHJlcVxuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVWMkFjY2VsZXJhdGVUcmFuc2FjdGlvbihyZXE6IGV4cHJlc3MuUmVxdWVzdCkge1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcbiAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgY29pbi53YWxsZXRzKCkuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQgfSk7XG4gIHJldHVybiB3YWxsZXQuYWNjZWxlcmF0ZVRyYW5zYWN0aW9uKGNyZWF0ZVNlbmRQYXJhbXMocmVxKSk7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVNlbmRQYXJhbXMocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgaWYgKHJlcS5jb25maWc/LmV4dGVybmFsU2lnbmVyVXJsICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4ucmVxLmJvZHksXG4gICAgICBjdXN0b21TaWduaW5nRnVuY3Rpb246IGNyZWF0ZUN1c3RvbVNpZ25pbmdGdW5jdGlvbihyZXEuY29uZmlnLmV4dGVybmFsU2lnbmVyVXJsKSxcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXEuYm9keTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjcmVhdGVUU1NTZW5kUGFyYW1zKHJlcTogZXhwcmVzcy5SZXF1ZXN0LCB3YWxsZXQ6IFdhbGxldCkge1xuICBpZiAocmVxLmNvbmZpZz8uZXh0ZXJuYWxTaWduZXJVcmwgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbnN0IGNvaW4gPSByZXEuYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICAgIGlmIChjb2luLmdldE1QQ0FsZ29yaXRobSgpID09PSBNUENUeXBlLkVERFNBKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5yZXEuYm9keSxcbiAgICAgICAgY3VzdG9tQ29tbWl0bWVudEdlbmVyYXRpbmdGdW5jdGlvbjogY3JlYXRlQ3VzdG9tQ29tbWl0bWVudEdlbmVyYXRvcihcbiAgICAgICAgICByZXEuY29uZmlnLmV4dGVybmFsU2lnbmVyVXJsLFxuICAgICAgICAgIHJlcS5wYXJhbXMuY29pblxuICAgICAgICApLFxuICAgICAgICBjdXN0b21SU2hhcmVHZW5lcmF0aW5nRnVuY3Rpb246IGNyZWF0ZUN1c3RvbVJTaGFyZUdlbmVyYXRvcihyZXEuY29uZmlnLmV4dGVybmFsU2lnbmVyVXJsLCByZXEucGFyYW1zLmNvaW4pLFxuICAgICAgICBjdXN0b21HU2hhcmVHZW5lcmF0aW5nRnVuY3Rpb246IGNyZWF0ZUN1c3RvbUdTaGFyZUdlbmVyYXRvcihyZXEuY29uZmlnLmV4dGVybmFsU2lnbmVyVXJsLCByZXEucGFyYW1zLmNvaW4pLFxuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKGNvaW4uZ2V0TVBDQWxnb3JpdGhtKCkgPT09IE1QQ1R5cGUuRUNEU0EpIHtcbiAgICAgIGlmICh3YWxsZXQuX3dhbGxldC5tdWx0aXNpZ1R5cGVWZXJzaW9uID09PSAnTVBDdjInKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgLi4ucmVxLmJvZHksXG4gICAgICAgICAgY3VzdG9tTVBDdjJTaWduaW5nUm91bmQxR2VuZXJhdGlvbkZ1bmN0aW9uOiBjcmVhdGVDdXN0b21NUEN2MlNpZ25pbmdSb3VuZDFHZW5lcmF0b3IoXG4gICAgICAgICAgICByZXEuY29uZmlnLmV4dGVybmFsU2lnbmVyVXJsLFxuICAgICAgICAgICAgcmVxLnBhcmFtcy5jb2luXG4gICAgICAgICAgKSxcbiAgICAgICAgICBjdXN0b21NUEN2MlNpZ25pbmdSb3VuZDJHZW5lcmF0aW9uRnVuY3Rpb246IGNyZWF0ZUN1c3RvbU1QQ3YyU2lnbmluZ1JvdW5kMkdlbmVyYXRvcihcbiAgICAgICAgICAgIHJlcS5jb25maWcuZXh0ZXJuYWxTaWduZXJVcmwsXG4gICAgICAgICAgICByZXEucGFyYW1zLmNvaW5cbiAgICAgICAgICApLFxuICAgICAgICAgIGN1c3RvbU1QQ3YyU2lnbmluZ1JvdW5kM0dlbmVyYXRpb25GdW5jdGlvbjogY3JlYXRlQ3VzdG9tTVBDdjJTaWduaW5nUm91bmQzR2VuZXJhdG9yKFxuICAgICAgICAgICAgcmVxLmNvbmZpZy5leHRlcm5hbFNpZ25lclVybCxcbiAgICAgICAgICAgIHJlcS5wYXJhbXMuY29pblxuICAgICAgICAgICksXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIC4uLnJlcS5ib2R5LFxuICAgICAgICAgIGN1c3RvbVBhaWxsaWVyTW9kdWx1c0dlbmVyYXRpbmdGdW5jdGlvbjogY3JlYXRlQ3VzdG9tUGFpbGxpZXJNb2R1bHVzR2V0dGVyKFxuICAgICAgICAgICAgcmVxLmNvbmZpZy5leHRlcm5hbFNpZ25lclVybCxcbiAgICAgICAgICAgIHJlcS5wYXJhbXMuY29pblxuICAgICAgICAgICksXG4gICAgICAgICAgY3VzdG9tS1NoYXJlR2VuZXJhdGluZ0Z1bmN0aW9uOiBjcmVhdGVDdXN0b21LU2hhcmVHZW5lcmF0b3IocmVxLmNvbmZpZy5leHRlcm5hbFNpZ25lclVybCwgcmVxLnBhcmFtcy5jb2luKSxcbiAgICAgICAgICBjdXN0b21NdURlbHRhU2hhcmVHZW5lcmF0aW5nRnVuY3Rpb246IGNyZWF0ZUN1c3RvbU11RGVsdGFTaGFyZUdlbmVyYXRvcihcbiAgICAgICAgICAgIHJlcS5jb25maWcuZXh0ZXJuYWxTaWduZXJVcmwsXG4gICAgICAgICAgICByZXEucGFyYW1zLmNvaW5cbiAgICAgICAgICApLFxuICAgICAgICAgIGN1c3RvbVNTaGFyZUdlbmVyYXRpbmdGdW5jdGlvbjogY3JlYXRlQ3VzdG9tU1NoYXJlR2VuZXJhdG9yKHJlcS5jb25maWcuZXh0ZXJuYWxTaWduZXJVcmwsIHJlcS5wYXJhbXMuY29pbiksXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTVBDIEFsZ29yaXRobSAke2NvaW4uZ2V0TVBDQWxnb3JpdGhtKCl9IGlzIG5vdCBzdXBwb3J0ZWQuYCk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXEuYm9keTtcbiAgfVxufVxuXG4vKipcbiAqIGhhbmRsZSBzZW5kIG9uZVxuICogQHBhcmFtIHJlcVxuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVWMlNlbmRPbmUocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gIGNvbnN0IHJlcUlkID0gbmV3IFJlcXVlc3RUcmFjZXIoKTtcbiAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgY29pbi53YWxsZXRzKCkuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQsIHJlcUlkIH0pO1xuICByZXEuYm9keS5yZXFJZCA9IHJlcUlkO1xuXG4gIGxldCByZXN1bHQ7XG4gIHRyeSB7XG4gICAgcmVzdWx0ID0gYXdhaXQgd2FsbGV0LnNlbmQoY3JlYXRlU2VuZFBhcmFtcyhyZXEpKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgZXJyLnN0YXR1cyA9IDQwMDtcbiAgICB0aHJvdyBlcnI7XG4gIH1cbiAgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICdwZW5kaW5nQXBwcm92YWwnKSB7XG4gICAgdGhyb3cgYXBpUmVzcG9uc2UoMjAyLCByZXN1bHQpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogaGFuZGxlIHNlbmQgbWFueVxuICogQHBhcmFtIHJlcVxuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVWMlNlbmRNYW55KHJlcTogZXhwcmVzcy5SZXF1ZXN0KSB7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICBjb25zdCByZXFJZCA9IG5ldyBSZXF1ZXN0VHJhY2VyKCk7XG4gIGNvbnN0IHdhbGxldCA9IGF3YWl0IGNvaW4ud2FsbGV0cygpLmdldCh7IGlkOiByZXEucGFyYW1zLmlkLCByZXFJZCB9KTtcbiAgcmVxLmJvZHkucmVxSWQgPSByZXFJZDtcbiAgbGV0IHJlc3VsdDtcbiAgdHJ5IHtcbiAgICBpZiAod2FsbGV0Ll93YWxsZXQubXVsdGlzaWdUeXBlID09PSAndHNzJykge1xuICAgICAgcmVzdWx0ID0gYXdhaXQgd2FsbGV0LnNlbmRNYW55KGNyZWF0ZVRTU1NlbmRQYXJhbXMocmVxLCB3YWxsZXQpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzdWx0ID0gYXdhaXQgd2FsbGV0LnNlbmRNYW55KGNyZWF0ZVNlbmRQYXJhbXMocmVxKSk7XG4gICAgfVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBlcnIuc3RhdHVzID0gNDAwO1xuICAgIHRocm93IGVycjtcbiAgfVxuICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gJ3BlbmRpbmdBcHByb3ZhbCcpIHtcbiAgICB0aHJvdyBhcGlSZXNwb25zZSgyMDIsIHJlc3VsdCk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiAgcGF5bG9hZCBtZWFudCBmb3IgcHJlYnVpbGRBbmRTaWduVHJhbnNhY3Rpb24oKSBpbiBzZGstY29yZSB3aGljaFxuICogdmFsaWRhdGVzIHRoZSBwYXlsb2FkIGFuZCBtYWtlcyB0aGUgYXBwcm9wcmlhdGUgcmVxdWVzdCB0byBXUCB0b1xuICogYnVpbGQsIHNpZ24sIGFuZCBzZW5kIGEgdHguXG4gKiAtIHNlbmRzIHJlcXVlc3QgdG8gUGxhdGZvcm0gdG8gYnVpbGQgdGhlIHRyYW5zYWN0aW9uXG4gKiAtIHNpZ25zIHdpdGggdXNlciBrZXlcbiAqIC0gcmVxdWVzdCBzaWduYXR1cmUgZnJvbSB0aGUgc2Vjb25kIGtleSAoQml0R28gSFNNKVxuICogLSBzZW5kL2Jyb2FkY2FzdCB0cmFuc2FjdGlvblxuICogQHBhcmFtIHJlcSB3aGVyZSByZXEuYm9keSBpcyB7QGxpbmsgUHJlYnVpbGRBbmRTaWduVHJhbnNhY3Rpb25PcHRpb25zfVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJQcmVidWlsZEFuZFNpZ25UcmFuc2FjdGlvbihyZXE6IGV4cHJlc3MuUmVxdWVzdCk6IFByb21pc2U8U2lnbmVkVHJhbnNhY3Rpb25SZXF1ZXN0PiB7XG4gIGNvbnN0IGJpdGdvID0gcmVxLmJpdGdvO1xuICBjb25zdCBjb2luID0gYml0Z28uY29pbihyZXEucGFyYW1zLmNvaW4pO1xuICBjb25zdCByZXFJZCA9IG5ldyBSZXF1ZXN0VHJhY2VyKCk7XG4gIGNvbnN0IHdhbGxldCA9IGF3YWl0IGNvaW4ud2FsbGV0cygpLmdldCh7IGlkOiByZXEucGFyYW1zLmlkLCByZXFJZCB9KTtcbiAgcmVxLmJvZHkucmVxSWQgPSByZXFJZDtcbiAgbGV0IHJlc3VsdDtcbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBhd2FpdCB3YWxsZXQucHJlYnVpbGRBbmRTaWduVHJhbnNhY3Rpb24oY3JlYXRlU2VuZFBhcmFtcyhyZXEpKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgZXJyLnN0YXR1cyA9IDQwMDtcbiAgICB0aHJvdyBlcnI7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBFbmFibGVzIHRva2VucyBvbiBhIHdhbGxldFxuICogQHBhcmFtIHJlcVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlVjJFbmFibGVUb2tlbnMocmVxOiBleHByZXNzLlJlcXVlc3QpIHtcbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG4gIGNvbnN0IHJlcUlkID0gbmV3IFJlcXVlc3RUcmFjZXIoKTtcbiAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgY29pbi53YWxsZXRzKCkuZ2V0KHsgaWQ6IHJlcS5wYXJhbXMuaWQsIHJlcUlkIH0pO1xuICByZXEuYm9keS5yZXFJZCA9IHJlcUlkO1xuICB0cnkge1xuICAgIHJldHVybiB3YWxsZXQuc2VuZFRva2VuRW5hYmxlbWVudHMoY3JlYXRlU2VuZFBhcmFtcyhyZXEpKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgZXJyLnN0YXR1cyA9IDQwMDtcbiAgICB0aHJvdyBlcnI7XG4gIH1cbn1cblxuLyoqXG4gKiBIYW5kbGUgVXBkYXRlIFdhbGxldFxuICogQHBhcmFtIHJlcVxuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVXYWxsZXRVcGRhdGUocmVxOiBleHByZXNzLlJlcXVlc3QpOiBQcm9taXNlPHVua25vd24+IHtcbiAgLy8gSWYgaXQncyBhIGxpZ2h0bmluZyBjb2luLCB1c2UgdGhlIGxpZ2h0bmluZy1zcGVjaWZpYyBoYW5kbGVyXG4gIGlmIChpc0xpZ2h0bmluZ0NvaW5OYW1lKHJlcS5wYXJhbXMuY29pbikpIHtcbiAgICByZXR1cm4gaGFuZGxlVXBkYXRlTGlnaHRuaW5nV2FsbGV0Q29pblNwZWNpZmljKHJlcSk7XG4gIH1cblxuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcbiAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcbiAgLy8gRm9yIG5vbi1saWdodG5pbmcgY29pbnMsIGRpcmVjdGx5IHVwZGF0ZSB0aGUgd2FsbGV0XG4gIGNvbnN0IHdhbGxldCA9IGF3YWl0IGNvaW4ud2FsbGV0cygpLmdldCh7IGlkOiByZXEucGFyYW1zLmlkIH0pO1xuICByZXR1cm4gYXdhaXQgYml0Z28ucHV0KHdhbGxldC51cmwoKSkuc2VuZChyZXEuYm9keSkucmVzdWx0KCk7XG59XG5cbi8qKlxuICogQ2hhbmdlcyBhIGtleWNoYWluJ3MgcGFzc3BocmFzZSwgcmUtZW5jcnlwdGluZyB0aGUga2V5IHRvIGEgbmV3IHBhc3N3b3JkXG4gKiBAcGFyYW0gcmVxXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVLZXljaGFpbkNoYW5nZVBhc3N3b3JkKHJlcTogZXhwcmVzcy5SZXF1ZXN0KTogUHJvbWlzZTx1bmtub3duPiB7XG4gIGNvbnN0IHsgb2xkUGFzc3dvcmQsIG5ld1Bhc3N3b3JkLCBvdHAgfSA9IHJlcS5ib2R5O1xuICBpZiAoIW9sZFBhc3N3b3JkIHx8ICFuZXdQYXNzd29yZCkge1xuICAgIHRocm93IG5ldyBBcGlSZXNwb25zZUVycm9yKCdNaXNzaW5nIDEgb3IgbW9yZSByZXF1aXJlZCBmaWVsZHM6IFtvbGRQYXNzd29yZCwgbmV3UGFzc3dvcmRdJywgNDAwKTtcbiAgfVxuICBjb25zdCByZXFJZCA9IG5ldyBSZXF1ZXN0VHJhY2VyKCk7XG5cbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKHJlcS5wYXJhbXMuY29pbik7XG5cbiAgaWYgKG90cCkge1xuICAgIGF3YWl0IGJpdGdvLnVubG9jayh7IG90cCB9KTtcbiAgfVxuXG4gIGNvbnN0IGtleWNoYWluID0gYXdhaXQgY29pbi5rZXljaGFpbnMoKS5nZXQoe1xuICAgIGlkOiByZXEucGFyYW1zLmlkLFxuICAgIHJlcUlkLFxuICB9KTtcbiAgaWYgKCFrZXljaGFpbikge1xuICAgIHRocm93IG5ldyBBcGlSZXNwb25zZUVycm9yKGBLZXljaGFpbiAke3JlcS5wYXJhbXMuaWR9IG5vdCBmb3VuZGAsIDQwNCk7XG4gIH1cblxuICBjb25zdCB1cGRhdGVkS2V5Y2hhaW4gPSBjb2luLmtleWNoYWlucygpLnVwZGF0ZVNpbmdsZUtleWNoYWluUGFzc3dvcmQoe1xuICAgIGtleWNoYWluLFxuICAgIG9sZFBhc3N3b3JkLFxuICAgIG5ld1Bhc3N3b3JkLFxuICB9KTtcblxuICByZXR1cm4gYml0Z28ucHV0KGNvaW4udXJsKGAva2V5LyR7dXBkYXRlZEtleWNoYWluLmlkfWApKS5zZW5kKHtcbiAgICBlbmNyeXB0ZWRQcnY6IHVwZGF0ZWRLZXljaGFpbi5lbmNyeXB0ZWRQcnYsXG4gIH0pO1xufVxuXG4vKipcbiAqIGhhbmRsZSBhbnkgb3RoZXIgQVBJIGNhbGxcbiAqIEBwYXJhbSByZXFcbiAqIEBwYXJhbSByZXNcbiAqIEBwYXJhbSBuZXh0XG4gKi9cbmZ1bmN0aW9uIGhhbmRsZVYyQ29pblNwZWNpZmljUkVTVChyZXE6IGV4cHJlc3MuUmVxdWVzdCwgcmVzOiBleHByZXNzLlJlc3BvbnNlLCBuZXh0OiBleHByZXNzLk5leHRGdW5jdGlvbikge1xuICBjb25zdCBtZXRob2QgPSByZXEubWV0aG9kO1xuICBjb25zdCBiaXRnbyA9IHJlcS5iaXRnbztcblxuICBkZWJ1ZygnaGFuZGxpbmcgdjIgY29pbiBzcGVjaWZpYyByZXN0IHJlcScpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4ocmVxLnBhcmFtcy5jb2luKTtcbiAgICBjb25zdCBjb2luVVJMID0gY29pbi51cmwoY3JlYXRlQVBJUGF0aChyZXEpKTtcbiAgICByZXR1cm4gcmVkaXJlY3RSZXF1ZXN0KGJpdGdvLCBtZXRob2QsIGNvaW5VUkwsIHJlcSwgbmV4dCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIFVuc3VwcG9ydGVkQ29pbkVycm9yKSB7XG4gICAgICBjb25zdCBxdWVyeVBhcmFtcyA9IF8udHJhbnNmb3JtKFxuICAgICAgICByZXEucXVlcnksXG4gICAgICAgIChhY2M6IHN0cmluZ1tdLCB2YWx1ZSwga2V5KSA9PiB7XG4gICAgICAgICAgZm9yIChjb25zdCB2YWwgb2YgXy5jYXN0QXJyYXkodmFsdWUpKSB7XG4gICAgICAgICAgICBhY2MucHVzaChgJHtrZXl9PSR7dmFsfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgW11cbiAgICAgICk7XG4gICAgICBjb25zdCBiYXNlVXJsID0gYml0Z28udXJsKHJlcS5iYXNlVXJsLnJlcGxhY2UoL15cXC9hcGlcXC92Mi8sICcnKSwgMik7XG4gICAgICBjb25zdCB1cmwgPSBfLmlzRW1wdHkocXVlcnlQYXJhbXMpID8gYmFzZVVybCA6IGAke2Jhc2VVcmx9PyR7cXVlcnlQYXJhbXMuam9pbignJicpfWA7XG5cbiAgICAgIGRlYnVnKGBjb2luICR7cmVxLnBhcmFtcy5jb2lufSBub3Qgc3VwcG9ydGVkLCBhdHRlbXB0aW5nIHRvIGhhbmRsZSBhcyBhIGNvaW5sZXNzIHJvdXRlIHdpdGggdXJsICR7dXJsfWApO1xuICAgICAgcmV0dXJuIHJlZGlyZWN0UmVxdWVzdChiaXRnbywgbWV0aG9kLCB1cmwsIHJlcSwgbmV4dCk7XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfVxufVxuXG4vKipcbiAqIEhhbmRsZSBhZGRpdGlvbmFsIG9wdGlvbiB0byBlbmNyeXB0IG9uIHRoZSBleHByZXNzIHJvdXRlIGZvciBwYXJ0bmVycyByZXF1aXJpbmcgdmFsdWUgZW5jcnlwdGlvblxuICogQHBhcmFtIHJlcS5ib2R5LmVuY3J5cHQgLSBib29sZWFuIHRvIGRldGVybWluZSBpZiB0aGUgcmVxdWVzdCBzaG91bGQgaGFuZGxlIGVuY3J5cHRpb24gb24gYmVoYWxmIG9mIHRoZSBzdWJtaXNzaW9uLlxuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVOZXR3b3JrVjFFbnRlcnByaXNlQ2xpZW50Q29ubmVjdGlvbnMoXG4gIHJlcTogZXhwcmVzcy5SZXF1ZXN0LFxuICByZXM6IGV4cHJlc3MuUmVzcG9uc2UsXG4gIG5leHQ6IGV4cHJlc3MuTmV4dEZ1bmN0aW9uXG4pIHtcbiAgZGVidWcoJ2hhbmRsaW5nIG5ldHdvcmsgdjEgcGFydG5lciBjb25uZWN0aW9uIGNyZWF0aW9uJyk7XG5cbiAgY29uc3QgYml0Z28gPSByZXEuYml0Z287XG4gIGNvbnN0IHBhcmFtcyA9IHJlcS5wYXJhbXM7XG4gIGNvbnN0IGJvZHkgPSByZXEuYm9keSBhcyBDcmVhdGVOZXR3b3JrQ29ubmVjdGlvblBhcmFtcyAmIHtcbiAgICBlbmNyeXB0PzogYm9vbGVhbjtcbiAgfTtcblxuICBpZiAoYm9keS5lbmNyeXB0ID09PSB0cnVlKSB7XG4gICAgaWYgKCFib2R5LnBhcnRuZXJJZCkge1xuICAgICAgdGhyb3cgbmV3IEFwaVJlc3BvbnNlRXJyb3IoJ01pc3NpbmcgcmVxdWlyZWQgZmllbGQ6IHBhcnRuZXJJZCcsIDQwMCk7XG4gICAgfVxuXG4gICAgY29uc3QgcGFydG5lcnNVcmwgPSBiaXRnby5taWNyb3NlcnZpY2VzVXJsKGAvYXBpL25ldHdvcmsvdjEvZW50ZXJwcmlzZXMvJHtwYXJhbXMuZW50ZXJwcmlzZUlkfS9wYXJ0bmVyc2ApO1xuXG4gICAgY29uc3QgcmVzcG9uc2U6IEdldE5ldHdvcmtQYXJ0bmVyc1Jlc3BvbnNlID0gYXdhaXQgYml0Z29cbiAgICAgIC5nZXQocGFydG5lcnNVcmwpXG4gICAgICAuc2V0KCdlbnRlcnByaXNlLWlkJywgcGFyYW1zLmVudGVycHJpc2VJZClcbiAgICAgIC5zZW5kKHsgaWRzOiBbcGFyYW1zLnBhcnRuZXJJZF0gfSlcbiAgICAgIC5yZXN1bHQoKTtcblxuICAgIGNvbnN0IHBhcnRuZXJzID0gcmVzcG9uc2UucGFydG5lcnM7XG4gICAgY29uc3QgcGFydG5lciA9IHBhcnRuZXJzLmZpbmQoKHApID0+IHAuaWQgPT09IGJvZHkucGFydG5lcklkKTtcblxuICAgIGlmICghcGFydG5lcikge1xuICAgICAgdGhyb3cgbmV3IEFwaVJlc3BvbnNlRXJyb3IoYFBhcnRuZXIgbm90IGZvdW5kIGZvciBwYXJ0bmVySWQ6ICR7Ym9keS5wYXJ0bmVySWR9YCwgNDAwKTtcbiAgICB9XG5cbiAgICBpZiAoIXBhcnRuZXIucHVibGljS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgQXBpUmVzcG9uc2VFcnJvcignUGFydG5lciBkb2VzIG5vdCByZXF1aXJlIGVuY3J5cHRpb24nLCA0MDApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoYm9keS5jb25uZWN0aW9uS2V5LnNjaGVtYSkge1xuICAgICAgY2FzZSAndG9rZW4nOlxuICAgICAgICByZXEuYm9keS5jb25uZWN0aW9uS2V5LmNvbm5lY3Rpb25Ub2tlbiA9IGF3YWl0IGVuY3J5cHRSc2FXaXRoQWVzR2NtKFxuICAgICAgICAgIHBhcnRuZXIucHVibGljS2V5LFxuICAgICAgICAgIGJvZHkuY29ubmVjdGlvbktleS5jb25uZWN0aW9uVG9rZW5cbiAgICAgICAgKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd0b2tlbkFuZFNpZ25hdHVyZSc6XG4gICAgICAgIHJlcS5ib2R5LmNvbm5lY3Rpb25LZXkuY29ubmVjdGlvblRva2VuID0gYXdhaXQgZW5jcnlwdFJzYVdpdGhBZXNHY20oXG4gICAgICAgICAgcGFydG5lci5wdWJsaWNLZXksXG4gICAgICAgICAgYm9keS5jb25uZWN0aW9uS2V5LmNvbm5lY3Rpb25Ub2tlblxuICAgICAgICApO1xuICAgICAgICByZXEuYm9keS5jb25uZWN0aW9uS2V5LnNpZ25hdHVyZSA9IGF3YWl0IGVuY3J5cHRSc2FXaXRoQWVzR2NtKHBhcnRuZXIucHVibGljS2V5LCBib2R5LmNvbm5lY3Rpb25LZXkuc2lnbmF0dXJlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdhcGlLZXlBbmRTZWNyZXQnOlxuICAgICAgY2FzZSAnY2xlYXJsb29wJzpcbiAgICAgICAgcmVxLmJvZHkuY29ubmVjdGlvbktleS5hcGlLZXkgPSBhd2FpdCBlbmNyeXB0UnNhV2l0aEFlc0djbShwYXJ0bmVyLnB1YmxpY0tleSwgYm9keS5jb25uZWN0aW9uS2V5LmFwaUtleSk7XG4gICAgICAgIHJlcS5ib2R5LmNvbm5lY3Rpb25LZXkuYXBpU2VjcmV0ID0gYXdhaXQgZW5jcnlwdFJzYVdpdGhBZXNHY20ocGFydG5lci5wdWJsaWNLZXksIGJvZHkuY29ubmVjdGlvbktleS5hcGlTZWNyZXQpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICByZXR1cm4gaGFuZGxlUHJveHlSZXEocmVxLCByZXMsIG5leHQpO1xufVxuXG4vKipcbiAqIFJlZGlyZWN0IGEgcmVxdWVzdCB1c2luZyB0aGUgYml0Z28gcmVxdWVzdCBmdW5jdGlvbnMuXG4gKiBAcGFyYW0gYml0Z29cbiAqIEBwYXJhbSBtZXRob2RcbiAqIEBwYXJhbSB1cmxcbiAqIEBwYXJhbSByZXFcbiAqIEBwYXJhbSBuZXh0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWRpcmVjdFJlcXVlc3QoXG4gIGJpdGdvOiBCaXRHbyxcbiAgbWV0aG9kOiBzdHJpbmcsXG4gIHVybDogc3RyaW5nLFxuICByZXE6IGV4cHJlc3MuUmVxdWVzdCxcbiAgbmV4dDogZXhwcmVzcy5OZXh0RnVuY3Rpb25cbikge1xuICBsZXQgcmVxdWVzdDtcblxuICBzd2l0Y2ggKG1ldGhvZCkge1xuICAgIGNhc2UgJ0dFVCc6XG4gICAgICByZXF1ZXN0ID0gYml0Z28uZ2V0KHVybCk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdQT1NUJzpcbiAgICAgIHJlcXVlc3QgPSBiaXRnby5wb3N0KHVybCkuc2VuZChyZXEuYm9keSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdQVVQnOlxuICAgICAgcmVxdWVzdCA9IGJpdGdvLnB1dCh1cmwpLnNlbmQocmVxLmJvZHkpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnUEFUQ0gnOlxuICAgICAgcmVxdWVzdCA9IGJpdGdvLnBhdGNoKHVybCkuc2VuZChyZXEuYm9keSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdPUFRJT05TJzpcbiAgICAgIHJlcXVlc3QgPSBiaXRnby5vcHRpb25zKHVybCkuc2VuZChyZXEuYm9keSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdERUxFVEUnOlxuICAgICAgcmVxdWVzdCA9IGJpdGdvLmRlbCh1cmwpLnNlbmQocmVxLmJvZHkpO1xuICAgICAgYnJlYWs7XG4gIH1cblxuICBpZiAocmVxdWVzdCkge1xuICAgIGlmIChyZXEucGFyYW1zLmVudGVycHJpc2VJZCkge1xuICAgICAgcmVxdWVzdC5zZXQoJ2VudGVycHJpc2UtaWQnLCByZXEucGFyYW1zLmVudGVycHJpc2VJZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcXVlc3QucmVzdWx0KCkudGhlbigocmVzdWx0KSA9PiB7XG4gICAgICBjb25zdCBzdGF0dXMgPSByZXF1ZXN0LnJlcz8uc3RhdHVzQ29kZSB8fCAyMDA7XG4gICAgICByZXR1cm4geyBzdGF0dXMsIGJvZHk6IHJlc3VsdCB9O1xuICAgIH0pO1xuICB9XG5cbiAgLy8gc29tZXRoaW5nIGhhcyBwcmVzdW1hYmx5IGdvbmUgd3JvbmdcbiAgbmV4dCgpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVQcm94eVJlcShyZXE6IGV4cHJlc3MuUmVxdWVzdCwgcmVzOiBleHByZXNzLlJlc3BvbnNlLCBuZXh0OiBleHByZXNzLk5leHRGdW5jdGlvbikge1xuICBjb25zdCBmdWxsVXJsID0gcmVxLmJpdGdvLm1pY3Jvc2VydmljZXNVcmwocmVxLm9yaWdpbmFsVXJsKTtcbiAgaWYgKHJlcS51cmwgJiYgKC9eXFwvYXBpLiokLy50ZXN0KHJlcS5vcmlnaW5hbFVybCkgfHwgL15cXC9vYXV0aFxcL3Rva2VuLiokLy50ZXN0KHJlcS51cmwpKSkge1xuICAgIHJlcS5pc1Byb3h5ID0gdHJ1ZTtcbiAgICBkZWJ1ZygncHJveHlpbmcgJXMgcmVxdWVzdCB0byAlcycsIHJlcS5tZXRob2QsIGZ1bGxVcmwpO1xuICAgIHJldHVybiBhd2FpdCByZWRpcmVjdFJlcXVlc3QocmVxLmJpdGdvLCByZXEubWV0aG9kLCBmdWxsVXJsLCByZXEsIG5leHQpO1xuICB9XG4gIC8vIHVzZXIgdHJpZWQgdG8gYWNjZXNzIGEgdXJsIHdoaWNoIGlzIG5vdCBhbiBhcGkgcm91dGUsIGRvIG5vdCBwcm94eVxuICBkZWJ1ZygndW5hYmxlIHRvIHByb3h5ICVzIHJlcXVlc3QgdG8gJXMnLCByZXEubWV0aG9kLCBmdWxsVXJsKTtcbiAgdGhyb3cgbmV3IEFwaVJlc3BvbnNlRXJyb3IoJ2JpdGdvLWV4cHJlc3MgY2FuIG9ubHkgcHJveHkgQml0R28gQVBJIHJlcXVlc3RzJywgNDA0KTtcbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIHN0YXR1c1xuICogQHBhcmFtIHJlc3VsdFxuICogQHBhcmFtIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gYXBpUmVzcG9uc2Uoc3RhdHVzOiBudW1iZXIsIHJlc3VsdDogYW55LCBtZXNzYWdlPzogc3RyaW5nKTogQXBpUmVzcG9uc2VFcnJvciB7XG4gIHJldHVybiBuZXcgQXBpUmVzcG9uc2VFcnJvcihtZXNzYWdlLCBzdGF0dXMsIHJlc3VsdCk7XG59XG5cbmNvbnN0IGV4cHJlc3NKU09OUGFyc2VyID0gYm9keVBhcnNlci5qc29uKHsgbGltaXQ6ICcyMG1iJyB9KTtcblxuLyoqXG4gKiBQZXJmb3JtIGJvZHkgcGFyc2luZyBoZXJlIG9ubHkgb24gcm91dGVzIHdlIHdhbnRcbiAqL1xuZnVuY3Rpb24gcGFyc2VCb2R5KHJlcTogZXhwcmVzcy5SZXF1ZXN0LCByZXM6IGV4cHJlc3MuUmVzcG9uc2UsIG5leHQ6IGV4cHJlc3MuTmV4dEZ1bmN0aW9uKSB7XG4gIC8vIFNldCB0aGUgZGVmYXVsdCBDb250ZW50LVR5cGUsIGluIGNhc2UgdGhlIGNsaWVudCBkb2Vzbid0IHNldCBpdC4gIElmXG4gIC8vIENvbnRlbnQtVHlwZSBpc24ndCBzcGVjaWZpZWQsIEV4cHJlc3Mgc2lsZW50bHkgcmVmdXNlcyB0byBwYXJzZSB0aGVcbiAgLy8gcmVxdWVzdCBib2R5LlxuICByZXEuaGVhZGVyc1snY29udGVudC10eXBlJ10gPSByZXEuaGVhZGVyc1snY29udGVudC10eXBlJ10gfHwgJ2FwcGxpY2F0aW9uL2pzb24nO1xuICByZXR1cm4gZXhwcmVzc0pTT05QYXJzZXIocmVxLCByZXMsIG5leHQpO1xufVxuXG4vKipcbiAqIENyZWF0ZSB0aGUgYml0Z28gb2JqZWN0IGluIHRoZSByZXF1ZXN0XG4gKiBAcGFyYW0gY29uZmlnXG4gKi9cbmZ1bmN0aW9uIHByZXBhcmVCaXRHbyhjb25maWc6IENvbmZpZykge1xuICBjb25zdCB7IGVudiwgY3VzdG9tUm9vdFVyaSwgY3VzdG9tQml0Y29pbk5ldHdvcmsgfSA9IGNvbmZpZztcblxuICByZXR1cm4gZnVuY3Rpb24gcHJlcEJpdEdvKHJlcTogZXhwcmVzcy5SZXF1ZXN0LCByZXM6IGV4cHJlc3MuUmVzcG9uc2UsIG5leHQ6IGV4cHJlc3MuTmV4dEZ1bmN0aW9uKSB7XG4gICAgLy8gR2V0IGFjY2VzcyB0b2tlblxuICAgIGxldCBhY2Nlc3NUb2tlbjtcbiAgICBpZiAocmVxLmhlYWRlcnMuYXV0aG9yaXphdGlvbikge1xuICAgICAgY29uc3QgYXV0aFNwbGl0ID0gcmVxLmhlYWRlcnMuYXV0aG9yaXphdGlvbi5zcGxpdCgnICcpO1xuICAgICAgaWYgKGF1dGhTcGxpdC5sZW5ndGggPT09IDIgJiYgYXV0aFNwbGl0WzBdLnRvTG93ZXJDYXNlKCkgPT09ICdiZWFyZXInKSB7XG4gICAgICAgIGFjY2Vzc1Rva2VuID0gYXV0aFNwbGl0WzFdO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCB1c2VyQWdlbnQgPSByZXEuaGVhZGVyc1sndXNlci1hZ2VudCddXG4gICAgICA/IEJJVEdPRVhQUkVTU19VU0VSX0FHRU5UICsgJyAnICsgcmVxLmhlYWRlcnNbJ3VzZXItYWdlbnQnXVxuICAgICAgOiBCSVRHT0VYUFJFU1NfVVNFUl9BR0VOVDtcblxuICAgIGNvbnN0IHVzZVByb3h5VXJsID0gcHJvY2Vzcy5lbnYuQklUR09fVVNFX1BST1hZO1xuICAgIGNvbnN0IGJpdGdvQ29uc3RydWN0b3JQYXJhbXM6IEJpdEdvT3B0aW9ucyA9IHtcbiAgICAgIGVudixcbiAgICAgIGN1c3RvbVJvb3RVUkk6IGN1c3RvbVJvb3RVcmksXG4gICAgICBjdXN0b21CaXRjb2luTmV0d29yayxcbiAgICAgIGFjY2Vzc1Rva2VuLFxuICAgICAgdXNlckFnZW50LFxuICAgICAgLi4uKHVzZVByb3h5VXJsXG4gICAgICAgID8ge1xuICAgICAgICAgICAgY3VzdG9tUHJveHlBZ2VudDogbmV3IFByb3h5QWdlbnQoe1xuICAgICAgICAgICAgICBnZXRQcm94eUZvclVybDogKCkgPT4gdXNlUHJveHlVcmwsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICB9XG4gICAgICAgIDoge30pLFxuICAgIH07XG5cbiAgICByZXEuYml0Z28gPSBuZXcgQml0R28oYml0Z29Db25zdHJ1Y3RvclBhcmFtcyk7XG4gICAgcmVxLmNvbmZpZyA9IGNvbmZpZztcblxuICAgIG5leHQoKTtcbiAgfTtcbn1cbnR5cGUgUmVxdWVzdEhhbmRsZXJSZXNwb25zZSA9IHN0cmluZyB8IHVua25vd24gfCB1bmRlZmluZWQgfCB7IHN0YXR1czogbnVtYmVyOyBib2R5OiB1bmtub3duIH07XG5pbnRlcmZhY2UgUmVxdWVzdEhhbmRsZXIgZXh0ZW5kcyBleHByZXNzLlJlcXVlc3RIYW5kbGVyPFBhcmFtc0RpY3Rpb25hcnksIGFueSwgUmVxdWVzdEhhbmRsZXJSZXNwb25zZT4ge1xuICAocmVxOiBleHByZXNzLlJlcXVlc3QsIHJlczogZXhwcmVzcy5SZXNwb25zZSwgbmV4dDogZXhwcmVzcy5OZXh0RnVuY3Rpb24pOlxuICAgIHwgUmVxdWVzdEhhbmRsZXJSZXNwb25zZVxuICAgIHwgUHJvbWlzZTxSZXF1ZXN0SGFuZGxlclJlc3BvbnNlPjtcbn1cblxuZnVuY3Rpb24gaGFuZGxlUmVxdWVzdEhhbmRsZXJFcnJvcihyZXM6IGV4cHJlc3MuUmVzcG9uc2UsIGVycm9yOiB1bmtub3duKSB7XG4gIGxldCBlcnI7XG4gIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgZXJyID0gZXJyb3I7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGVycm9yID09PSAnc3RyaW5nJykge1xuICAgIGVyciA9IG5ldyBFcnJvcignKHN0cmluZ19lcnJvcikgJyArIGVycm9yKTtcbiAgfSBlbHNlIHtcbiAgICBlcnIgPSBuZXcgRXJyb3IoJyhvYmplY3RfZXJyb3IpICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICB9XG5cbiAgY29uc3QgbWVzc2FnZSA9IGVyci5tZXNzYWdlIHx8ICdsb2NhbCBlcnJvcic7XG4gIC8vIHVzZSBhdHRhY2hlZCByZXN1bHQsIG9yIG1ha2Ugb25lXG4gIGxldCByZXN1bHQgPSBlcnIucmVzdWx0IHx8IHsgZXJyb3I6IG1lc3NhZ2UgfTtcbiAgcmVzdWx0ID0gXy5leHRlbmQoe30sIHJlc3VsdCwge1xuICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgIGJpdGdvSnNWZXJzaW9uOiB2ZXJzaW9uLFxuICAgIGJpdGdvRXhwcmVzc1ZlcnNpb246IHBqc29uLnZlcnNpb24sXG4gIH0pO1xuICBjb25zdCBzdGF0dXMgPSBlcnIuc3RhdHVzIHx8IDUwMDtcbiAgaWYgKCEoc3RhdHVzID49IDIwMCAmJiBzdGF0dXMgPCAzMDApKSB7XG4gICAgY29uc29sZS5sb2coJ2Vycm9yICVzOiAlcycsIHN0YXR1cywgZXJyLm1lc3NhZ2UpO1xuICB9XG4gIGlmIChzdGF0dXMgPj0gNTAwICYmIHN0YXR1cyA8PSA1OTkpIHtcbiAgICBpZiAoZXJyLnJlc3BvbnNlICYmIGVyci5yZXNwb25zZS5yZXF1ZXN0KSB7XG4gICAgICBjb25zb2xlLmxvZyhgZmFpbGVkIHRvIG1ha2UgJHtlcnIucmVzcG9uc2UucmVxdWVzdC5tZXRob2R9IHJlcXVlc3QgdG8gJHtlcnIucmVzcG9uc2UucmVxdWVzdC51cmx9YCk7XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKGVyci5zdGFjayk7XG4gIH1cbiAgcmVzLnN0YXR1cyhzdGF0dXMpLnNlbmQocmVzdWx0KTtcbn1cblxuLyoqXG4gKiBQcm9taXNlIGhhbmRsZXIgd3JhcHBlciB0byBoYW5kbGUgc2VuZGluZyByZXNwb25zZXMgYW5kIGVycm9yIGNhc2VzXG4gKiBAcGFyYW0gcHJvbWlzZVJlcXVlc3RIYW5kbGVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm9taXNlV3JhcHBlcihwcm9taXNlUmVxdWVzdEhhbmRsZXI6IFJlcXVlc3RIYW5kbGVyKSB7XG4gIHJldHVybiBhc3luYyBmdW5jdGlvbiBwcm9tV3JhcHBlcihyZXE6IGV4cHJlc3MuUmVxdWVzdCwgcmVzOiBleHByZXNzLlJlc3BvbnNlLCBuZXh0OiBleHByZXNzLk5leHRGdW5jdGlvbikge1xuICAgIGRlYnVnKGBoYW5kbGU6ICR7cmVxLm1ldGhvZH0gJHtyZXEub3JpZ2luYWxVcmx9YCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHByb21pc2VSZXF1ZXN0SGFuZGxlcihyZXEsIHJlcywgbmV4dCk7XG4gICAgICBpZiAodHlwZW9mIHJlc3VsdCA9PT0gJ29iamVjdCcgJiYgcmVzdWx0ICE9PSBudWxsICYmICdib2R5JyBpbiByZXN1bHQgJiYgJ3N0YXR1cycgaW4gcmVzdWx0KSB7XG4gICAgICAgIGNvbnN0IHsgc3RhdHVzLCBib2R5IH0gPSByZXN1bHQgYXMgeyBzdGF0dXM6IG51bWJlcjsgYm9keTogdW5rbm93biB9O1xuICAgICAgICByZXMuc3RhdHVzKHN0YXR1cykuc2VuZChib2R5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlcy5zdGF0dXMoMjAwKS5zZW5kKHJlc3VsdCk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaGFuZGxlUmVxdWVzdEhhbmRsZXJFcnJvcihyZXMsIGUpO1xuICAgIH1cbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUN1c3RvbVNpZ25pbmdGdW5jdGlvbihleHRlcm5hbFNpZ25lclVybDogc3RyaW5nKTogQ3VzdG9tU2lnbmluZ0Z1bmN0aW9uIHtcbiAgcmV0dXJuIGFzeW5jIGZ1bmN0aW9uIChwYXJhbXMpOiBQcm9taXNlPFNpZ25lZFRyYW5zYWN0aW9uPiB7XG4gICAgY29uc3QgeyBib2R5OiBzaWduZWRUeCB9ID0gYXdhaXQgcmV0cnlQcm9taXNlKFxuICAgICAgKCkgPT5cbiAgICAgICAgc3VwZXJhZ2VudC5wb3N0KGAke2V4dGVybmFsU2lnbmVyVXJsfS9hcGkvdjIvJHtwYXJhbXMuY29pbi5nZXRDaGFpbigpfS9zaWduYCkudHlwZSgnanNvbicpLnNlbmQoe1xuICAgICAgICAgIHR4UHJlYnVpbGQ6IHBhcmFtcy50eFByZWJ1aWxkLFxuICAgICAgICAgIHB1YnM6IHBhcmFtcy5wdWJzLFxuICAgICAgICAgIGRlcml2YXRpb25TZWVkOiBwYXJhbXMuZGVyaXZhdGlvblNlZWQsXG4gICAgICAgICAgc2lnbmluZ1N0ZXA6IHBhcmFtcy5zaWduaW5nU3RlcCxcbiAgICAgICAgfSksXG4gICAgICAoZXJyLCB0cnlDb3VudCkgPT4ge1xuICAgICAgICBkZWJ1ZyhgZmFpbGVkIHRvIGNvbm5lY3QgdG8gZXh0ZXJuYWwgc2lnbmVyIChhdHRlbXB0ICR7dHJ5Q291bnR9LCBlcnJvcjogJHtlcnIubWVzc2FnZX0pYCk7XG4gICAgICB9XG4gICAgKTtcbiAgICByZXR1cm4gc2lnbmVkVHg7XG4gIH07XG59XG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ3VzdG9tUGFpbGxpZXJNb2R1bHVzR2V0dGVyKFxuICBleHRlcm5hbFNpZ25lclVybDogc3RyaW5nLFxuICBjb2luOiBzdHJpbmdcbik6IEN1c3RvbVBhaWxsaWVyTW9kdWx1c0dldHRlckZ1bmN0aW9uIHtcbiAgcmV0dXJuIGFzeW5jIGZ1bmN0aW9uIChwYXJhbXMpOiBQcm9taXNlPHtcbiAgICB1c2VyUGFpbGxpZXJNb2R1bHVzOiBzdHJpbmc7XG4gIH0+IHtcbiAgICBjb25zdCB7IGJvZHk6IHJlc3VsdCB9ID0gYXdhaXQgcmV0cnlQcm9taXNlKFxuICAgICAgKCkgPT4gc3VwZXJhZ2VudC5wb3N0KGAke2V4dGVybmFsU2lnbmVyVXJsfS9hcGkvdjIvJHtjb2lufS90c3NzaGFyZS9QYWlsbGllck1vZHVsdXNgKS50eXBlKCdqc29uJykuc2VuZChwYXJhbXMpLFxuICAgICAgKGVyciwgdHJ5Q291bnQpID0+IHtcbiAgICAgICAgZGVidWcoYGZhaWxlZCB0byBjb25uZWN0IHRvIGV4dGVybmFsIHNpZ25lciAoYXR0ZW1wdCAke3RyeUNvdW50fSwgZXJyb3I6ICR7ZXJyLm1lc3NhZ2V9KWApO1xuICAgICAgfVxuICAgICk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUN1c3RvbUtTaGFyZUdlbmVyYXRvcihleHRlcm5hbFNpZ25lclVybDogc3RyaW5nLCBjb2luOiBzdHJpbmcpOiBDdXN0b21LU2hhcmVHZW5lcmF0aW5nRnVuY3Rpb24ge1xuICByZXR1cm4gYXN5bmMgZnVuY3Rpb24gKHBhcmFtcyk6IFByb21pc2U8VHNzRWNkc2FTdGVwMVJldHVybk1lc3NhZ2U+IHtcbiAgICBjb25zdCB7IGJvZHk6IHJlc3VsdCB9ID0gYXdhaXQgcmV0cnlQcm9taXNlKFxuICAgICAgKCkgPT4gc3VwZXJhZ2VudC5wb3N0KGAke2V4dGVybmFsU2lnbmVyVXJsfS9hcGkvdjIvJHtjb2lufS90c3NzaGFyZS9LYCkudHlwZSgnanNvbicpLnNlbmQocGFyYW1zKSxcbiAgICAgIChlcnIsIHRyeUNvdW50KSA9PiB7XG4gICAgICAgIGRlYnVnKGBmYWlsZWQgdG8gY29ubmVjdCB0byBleHRlcm5hbCBzaWduZXIgKGF0dGVtcHQgJHt0cnlDb3VudH0sIGVycm9yOiAke2Vyci5tZXNzYWdlfSlgKTtcbiAgICAgIH1cbiAgICApO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDdXN0b21NdURlbHRhU2hhcmVHZW5lcmF0b3IoXG4gIGV4dGVybmFsU2lnbmVyVXJsOiBzdHJpbmcsXG4gIGNvaW46IHN0cmluZ1xuKTogQ3VzdG9tTXVEZWx0YVNoYXJlR2VuZXJhdGluZ0Z1bmN0aW9uIHtcbiAgcmV0dXJuIGFzeW5jIGZ1bmN0aW9uIChwYXJhbXMpOiBQcm9taXNlPFRzc0VjZHNhU3RlcDJSZXR1cm5NZXNzYWdlPiB7XG4gICAgY29uc3QgeyBib2R5OiByZXN1bHQgfSA9IGF3YWl0IHJldHJ5UHJvbWlzZShcbiAgICAgICgpID0+IHN1cGVyYWdlbnQucG9zdChgJHtleHRlcm5hbFNpZ25lclVybH0vYXBpL3YyLyR7Y29pbn0vdHNzc2hhcmUvTXVEZWx0YWApLnR5cGUoJ2pzb24nKS5zZW5kKHBhcmFtcyksXG4gICAgICAoZXJyLCB0cnlDb3VudCkgPT4ge1xuICAgICAgICBkZWJ1ZyhgZmFpbGVkIHRvIGNvbm5lY3QgdG8gZXh0ZXJuYWwgc2lnbmVyIChhdHRlbXB0ICR7dHJ5Q291bnR9LCBlcnJvcjogJHtlcnIubWVzc2FnZX0pYCk7XG4gICAgICB9XG4gICAgKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ3VzdG9tU1NoYXJlR2VuZXJhdG9yKGV4dGVybmFsU2lnbmVyVXJsOiBzdHJpbmcsIGNvaW46IHN0cmluZyk6IEN1c3RvbVNTaGFyZUdlbmVyYXRpbmdGdW5jdGlvbiB7XG4gIHJldHVybiBhc3luYyBmdW5jdGlvbiAocGFyYW1zKTogUHJvbWlzZTxTU2hhcmU+IHtcbiAgICBjb25zdCB7IGJvZHk6IHJlc3VsdCB9ID0gYXdhaXQgcmV0cnlQcm9taXNlKFxuICAgICAgKCkgPT4gc3VwZXJhZ2VudC5wb3N0KGAke2V4dGVybmFsU2lnbmVyVXJsfS9hcGkvdjIvJHtjb2lufS90c3NzaGFyZS9TYCkudHlwZSgnanNvbicpLnNlbmQocGFyYW1zKSxcbiAgICAgIChlcnIsIHRyeUNvdW50KSA9PiB7XG4gICAgICAgIGRlYnVnKGBmYWlsZWQgdG8gY29ubmVjdCB0byBleHRlcm5hbCBzaWduZXIgKGF0dGVtcHQgJHt0cnlDb3VudH0sIGVycm9yOiAke2Vyci5tZXNzYWdlfSlgKTtcbiAgICAgIH1cbiAgICApO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDdXN0b21Db21taXRtZW50R2VuZXJhdG9yKFxuICBleHRlcm5hbFNpZ25lclVybDogc3RyaW5nLFxuICBjb2luOiBzdHJpbmdcbik6IEN1c3RvbUNvbW1pdG1lbnRHZW5lcmF0aW5nRnVuY3Rpb24ge1xuICByZXR1cm4gYXN5bmMgZnVuY3Rpb24gKHBhcmFtcyk6IFByb21pc2U8e1xuICAgIHVzZXJUb0JpdGdvQ29tbWl0bWVudDogQ29tbWl0bWVudFNoYXJlUmVjb3JkO1xuICAgIGVuY3J5cHRlZFNpZ25lclNoYXJlOiBFbmNyeXB0ZWRTaWduZXJTaGFyZVJlY29yZDtcbiAgICBlbmNyeXB0ZWRVc2VyVG9CaXRnb1JTaGFyZTogRW5jcnlwdGVkU2lnbmVyU2hhcmVSZWNvcmQ7XG4gIH0+IHtcbiAgICBjb25zdCB7IGJvZHk6IHJlc3VsdCB9ID0gYXdhaXQgcmV0cnlQcm9taXNlKFxuICAgICAgKCkgPT4gc3VwZXJhZ2VudC5wb3N0KGAke2V4dGVybmFsU2lnbmVyVXJsfS9hcGkvdjIvJHtjb2lufS90c3NzaGFyZS9jb21taXRtZW50YCkudHlwZSgnanNvbicpLnNlbmQocGFyYW1zKSxcbiAgICAgIChlcnIsIHRyeUNvdW50KSA9PiB7XG4gICAgICAgIGRlYnVnKGBmYWlsZWQgdG8gY29ubmVjdCB0byBleHRlcm5hbCBzaWduZXIgKGF0dGVtcHQgJHt0cnlDb3VudH0sIGVycm9yOiAke2Vyci5tZXNzYWdlfSlgKTtcbiAgICAgIH1cbiAgICApO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDdXN0b21SU2hhcmVHZW5lcmF0b3IoZXh0ZXJuYWxTaWduZXJVcmw6IHN0cmluZywgY29pbjogc3RyaW5nKTogQ3VzdG9tUlNoYXJlR2VuZXJhdGluZ0Z1bmN0aW9uIHtcbiAgcmV0dXJuIGFzeW5jIGZ1bmN0aW9uIChwYXJhbXMpOiBQcm9taXNlPHsgclNoYXJlOiBTaWduU2hhcmUgfT4ge1xuICAgIGNvbnN0IHsgYm9keTogclNoYXJlIH0gPSBhd2FpdCByZXRyeVByb21pc2UoXG4gICAgICAoKSA9PiBzdXBlcmFnZW50LnBvc3QoYCR7ZXh0ZXJuYWxTaWduZXJVcmx9L2FwaS92Mi8ke2NvaW59L3Rzc3NoYXJlL1JgKS50eXBlKCdqc29uJykuc2VuZChwYXJhbXMpLFxuICAgICAgKGVyciwgdHJ5Q291bnQpID0+IHtcbiAgICAgICAgZGVidWcoYGZhaWxlZCB0byBjb25uZWN0IHRvIGV4dGVybmFsIHNpZ25lciAoYXR0ZW1wdCAke3RyeUNvdW50fSwgZXJyb3I6ICR7ZXJyLm1lc3NhZ2V9KWApO1xuICAgICAgfVxuICAgICk7XG4gICAgcmV0dXJuIHJTaGFyZTtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUN1c3RvbUdTaGFyZUdlbmVyYXRvcihleHRlcm5hbFNpZ25lclVybDogc3RyaW5nLCBjb2luOiBzdHJpbmcpOiBDdXN0b21HU2hhcmVHZW5lcmF0aW5nRnVuY3Rpb24ge1xuICByZXR1cm4gYXN5bmMgZnVuY3Rpb24gKHBhcmFtcyk6IFByb21pc2U8R1NoYXJlPiB7XG4gICAgY29uc3QgeyBib2R5OiBzaWduZWRUeCB9ID0gYXdhaXQgcmV0cnlQcm9taXNlKFxuICAgICAgKCkgPT4gc3VwZXJhZ2VudC5wb3N0KGAke2V4dGVybmFsU2lnbmVyVXJsfS9hcGkvdjIvJHtjb2lufS90c3NzaGFyZS9HYCkudHlwZSgnanNvbicpLnNlbmQocGFyYW1zKSxcbiAgICAgIChlcnIsIHRyeUNvdW50KSA9PiB7XG4gICAgICAgIGRlYnVnKGBmYWlsZWQgdG8gY29ubmVjdCB0byBleHRlcm5hbCBzaWduZXIgKGF0dGVtcHQgJHt0cnlDb3VudH0sIGVycm9yOiAke2Vyci5tZXNzYWdlfSlgKTtcbiAgICAgIH1cbiAgICApO1xuICAgIHJldHVybiBzaWduZWRUeDtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUN1c3RvbU1QQ3YyU2lnbmluZ1JvdW5kMUdlbmVyYXRvcihcbiAgZXh0ZXJuYWxTaWduZXJVcmw6IHN0cmluZyxcbiAgY29pbjogc3RyaW5nXG4pOiBDdXN0b21NUEN2MlNpZ25pbmdSb3VuZDFHZW5lcmF0aW5nRnVuY3Rpb24ge1xuICByZXR1cm4gYXN5bmMgZnVuY3Rpb24gKHBhcmFtcykge1xuICAgIGNvbnN0IHsgYm9keTogcmVzdWx0IH0gPSBhd2FpdCByZXRyeVByb21pc2UoXG4gICAgICAoKSA9PiBzdXBlcmFnZW50LnBvc3QoYCR7ZXh0ZXJuYWxTaWduZXJVcmx9L2FwaS92Mi8ke2NvaW59L3Rzc3NoYXJlL01QQ3YyUm91bmQxYCkudHlwZSgnanNvbicpLnNlbmQocGFyYW1zKSxcbiAgICAgIChlcnIsIHRyeUNvdW50KSA9PiB7XG4gICAgICAgIGRlYnVnKGBmYWlsZWQgdG8gY29ubmVjdCB0byBleHRlcm5hbCBzaWduZXIgKGF0dGVtcHQgJHt0cnlDb3VudH0sIGVycm9yOiAke2Vyci5tZXNzYWdlfSlgKTtcbiAgICAgIH1cbiAgICApO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDdXN0b21NUEN2MlNpZ25pbmdSb3VuZDJHZW5lcmF0b3IoXG4gIGV4dGVybmFsU2lnbmVyVXJsOiBzdHJpbmcsXG4gIGNvaW46IHN0cmluZ1xuKTogQ3VzdG9tTVBDdjJTaWduaW5nUm91bmQyR2VuZXJhdGluZ0Z1bmN0aW9uIHtcbiAgcmV0dXJuIGFzeW5jIGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICBjb25zdCB7IGJvZHk6IHJlc3VsdCB9ID0gYXdhaXQgcmV0cnlQcm9taXNlKFxuICAgICAgKCkgPT4gc3VwZXJhZ2VudC5wb3N0KGAke2V4dGVybmFsU2lnbmVyVXJsfS9hcGkvdjIvJHtjb2lufS90c3NzaGFyZS9NUEN2MlJvdW5kMmApLnR5cGUoJ2pzb24nKS5zZW5kKHBhcmFtcyksXG4gICAgICAoZXJyLCB0cnlDb3VudCkgPT4ge1xuICAgICAgICBkZWJ1ZyhgZmFpbGVkIHRvIGNvbm5lY3QgdG8gZXh0ZXJuYWwgc2lnbmVyIChhdHRlbXB0ICR7dHJ5Q291bnR9LCBlcnJvcjogJHtlcnIubWVzc2FnZX0pYCk7XG4gICAgICB9XG4gICAgKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ3VzdG9tTVBDdjJTaWduaW5nUm91bmQzR2VuZXJhdG9yKFxuICBleHRlcm5hbFNpZ25lclVybDogc3RyaW5nLFxuICBjb2luOiBzdHJpbmdcbik6IEN1c3RvbU1QQ3YyU2lnbmluZ1JvdW5kM0dlbmVyYXRpbmdGdW5jdGlvbiB7XG4gIHJldHVybiBhc3luYyBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgY29uc3QgeyBib2R5OiByZXN1bHQgfSA9IGF3YWl0IHJldHJ5UHJvbWlzZShcbiAgICAgICgpID0+IHN1cGVyYWdlbnQucG9zdChgJHtleHRlcm5hbFNpZ25lclVybH0vYXBpL3YyLyR7Y29pbn0vdHNzc2hhcmUvTVBDdjJSb3VuZDNgKS50eXBlKCdqc29uJykuc2VuZChwYXJhbXMpLFxuICAgICAgKGVyciwgdHJ5Q291bnQpID0+IHtcbiAgICAgICAgZGVidWcoYGZhaWxlZCB0byBjb25uZWN0IHRvIGV4dGVybmFsIHNpZ25lciAoYXR0ZW1wdCAke3RyeUNvdW50fSwgZXJyb3I6ICR7ZXJyLm1lc3NhZ2V9KWApO1xuICAgICAgfVxuICAgICk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldHVwQVBJUm91dGVzKGFwcDogZXhwcmVzcy5BcHBsaWNhdGlvbiwgY29uZmlnOiBDb25maWcpOiB2b2lkIHtcbiAgLy8gV2hlbiBhZGRpbmcgbmV3IHJvdXRlcyB0byBCaXRHbyBFeHByZXNzIG1ha2Ugc3VyZSB0aGF0IHlvdSBhbHNvIGFkZCB0aGUgZXhhY3Qgc2FtZSByb3V0ZXMgdG8gdGhlIHNlcnZlci4gU2luY2VcbiAgLy8gc29tZSBjdXN0b21lcnMgd2VyZSBjb25mdXNlZCB3aGVuIGNhbGxpbmcgYSBCaXRHbyBFeHByZXNzIHJvdXRlIG9uIHRoZSBCaXRHbyBzZXJ2ZXIsIHdlIG5vdyBoYW5kbGUgYWxsIEJpdEdvXG4gIC8vIEV4cHJlc3Mgcm91dGVzIG9uIHRoZSBCaXRHbyBzZXJ2ZXIgYW5kIHJldHVybiBhbiBlcnJvciBtZXNzYWdlIHRoYXQgc2F5cyB0aGF0IG9uZSBzaG91bGQgY2FsbCBCaXRHbyBFeHByZXNzXG4gIC8vIGluc3RlYWQuXG4gIC8vIFYxIHJvdXRlcyBzaG91bGQgYmUgYWRkZWQgdG8gd3d3L2NvbmZpZy9yb3V0ZXMuanNcbiAgLy8gVjIgcm91dGVzIHNob3VsZCBiZSBhZGRlZCB0byB3d3cvY29uZmlnL3JvdXRlc1YyLmpzXG5cbiAgLy8gcGluZ1xuICAvLyAvYXBpL3ZbMTJdL3BpbmdleHByZXNzIGlzIHRoZSBvbmx5IGV4Y2VwdGlvbiB0byB0aGUgcnVsZSBhYm92ZSwgYXMgaXQgZXhwbGljaXRseSBjaGVja3MgdGhlIGhlYWx0aCBvZiB0aGVcbiAgLy8gZXhwcmVzcyBzZXJ2ZXIgd2l0aG91dCBydW5uaW5nIGludG8gcmF0ZSBsaW1pdGluZyB3aXRoIHRoZSBCaXRHbyBzZXJ2ZXIuXG4gIGFwcC5nZXQoJy9hcGkvdlsxMl0vcGluZycsIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVQaW5nKSk7XG4gIGFwcC5nZXQoJy9hcGkvdlsxMl0vcGluZ2V4cHJlc3MnLCBwcm9taXNlV3JhcHBlcihoYW5kbGVQaW5nRXhwcmVzcykpO1xuXG4gIC8vIGF1dGhcbiAgYXBwLnBvc3QoJy9hcGkvdlsxMl0vdXNlci9sb2dpbicsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZUxvZ2luKSk7XG5cbiAgYXBwLnBvc3QoJy9hcGkvdlsxMl0vZGVjcnlwdCcsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZURlY3J5cHQpKTtcbiAgYXBwLnBvc3QoJy9hcGkvdlsxMl0vZW5jcnlwdCcsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZUVuY3J5cHQpKTtcbiAgYXBwLnBvc3QoJy9hcGkvdlsxMl0vdmVyaWZ5YWRkcmVzcycsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZVZlcmlmeUFkZHJlc3MpKTtcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdlsxMl0vY2FsY3VsYXRlbWluZXJmZWVpbmZvJyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlQ2FsY3VsYXRlTWluZXJGZWVJbmZvKVxuICApO1xuXG4gIGFwcC5wb3N0KCcvYXBpL3YxL2tleWNoYWluL2xvY2FsJywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlQ3JlYXRlTG9jYWxLZXlDaGFpbikpO1xuICBhcHAucG9zdCgnL2FwaS92MS9rZXljaGFpbi9kZXJpdmUnLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVEZXJpdmVMb2NhbEtleUNoYWluKSk7XG4gIGFwcC5wb3N0KFxuICAgICcvYXBpL3YxL3dhbGxldHMvc2ltcGxlY3JlYXRlJyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlQ3JlYXRlV2FsbGV0V2l0aEtleWNoYWlucylcbiAgKTtcblxuICBhcHAucG9zdCgnL2FwaS92MS93YWxsZXQvOmlkL3NlbmRjb2lucycsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZVNlbmRDb2lucykpO1xuICBhcHAucG9zdCgnL2FwaS92MS93YWxsZXQvOmlkL3NlbmRtYW55JywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlU2VuZE1hbnkpKTtcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjEvd2FsbGV0LzppZC9jcmVhdGV0cmFuc2FjdGlvbicsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZUNyZWF0ZVRyYW5zYWN0aW9uKVxuICApO1xuICBhcHAucG9zdChcbiAgICAnL2FwaS92MS93YWxsZXQvOmlkL3NpZ250cmFuc2FjdGlvbicsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZVNpZ25UcmFuc2FjdGlvbilcbiAgKTtcblxuICBhcHAucG9zdCgnL2FwaS92MS93YWxsZXQvOmlkL3NpbXBsZXNoYXJlJywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlU2hhcmVXYWxsZXQpKTtcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjEvd2FsbGV0c2hhcmUvOnNoYXJlSWQvYWNjZXB0U2hhcmUnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVBY2NlcHRTaGFyZSlcbiAgKTtcblxuICBhcHAucHV0KFxuICAgICcvYXBpL3YxL3BlbmRpbmdhcHByb3ZhbHMvOmlkL2V4cHJlc3MnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVBcHByb3ZlVHJhbnNhY3Rpb24pXG4gICk7XG4gIGFwcC5wdXQoXG4gICAgJy9hcGkvdjEvcGVuZGluZ2FwcHJvdmFscy86aWQvY29uc3RydWN0VHgnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVDb25zdHJ1Y3RBcHByb3ZhbFR4KVxuICApO1xuXG4gIGFwcC5wdXQoXG4gICAgJy9hcGkvdjEvd2FsbGV0LzppZC9jb25zb2xpZGF0ZXVuc3BlbnRzJyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlQ29uc29saWRhdGVVbnNwZW50cylcbiAgKTtcbiAgYXBwLnB1dCgnL2FwaS92MS93YWxsZXQvOmlkL2Zhbm91dHVuc3BlbnRzJywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlRmFuT3V0VW5zcGVudHMpKTtcblxuICAvLyBhbnkgb3RoZXIgQVBJIGNhbGxcbiAgYXBwLnVzZSgnL2FwaS92WzFdLyonLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVSRVNUKSk7XG5cbiAgLy8gQVBJIHYyXG5cbiAgLy8gY3JlYXRlIGtleWNoYWluXG4gIGFwcC5wb3N0KFxuICAgICcvYXBpL3YyLzpjb2luL2tleWNoYWluL2xvY2FsJyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJDcmVhdGVMb2NhbEtleUNoYWluKVxuICApO1xuXG4gIC8vIGdlbmVyYXRlIHdhbGxldFxuICBhcHAucG9zdCgnL2FwaS92Mi86Y29pbi93YWxsZXQvZ2VuZXJhdGUnLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVWMkdlbmVyYXRlV2FsbGV0KSk7XG5cbiAgYXBwLnB1dCgnL2V4cHJlc3MvYXBpL3YyLzpjb2luL3dhbGxldC86aWQnLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVXYWxsZXRVcGRhdGUpKTtcblxuICAvLyBjaGFuZ2Ugd2FsbGV0IHBhc3NwaHJhc2VcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjIvOmNvaW4va2V5Y2hhaW4vOmlkL2NoYW5nZXBhc3N3b3JkJyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlS2V5Y2hhaW5DaGFuZ2VQYXNzd29yZClcbiAgKTtcblxuICAvLyBjcmVhdGUgYWRkcmVzc1xuICBhcHAucG9zdCgnL2FwaS92Mi86Y29pbi93YWxsZXQvOmlkL2FkZHJlc3MnLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVWMkNyZWF0ZUFkZHJlc3MpKTtcblxuICAvLyBzaGFyZSB3YWxsZXRcbiAgYXBwLnBvc3QoJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9zaGFyZScsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyU2hhcmVXYWxsZXQpKTtcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjIvOmNvaW4vd2FsbGV0c2hhcmUvOmlkL2FjY2VwdHNoYXJlJyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJBY2NlcHRXYWxsZXRTaGFyZSlcbiAgKTtcblxuICAvLyBzaWduIGFyYml0cmFyeSBwYXlsb2FkcyB3LyB0cmFkaW5nIGFjY291bnQga2V5XG4gIGFwcC5wb3N0KGAvYXBpL3YyL29mYy9zaWduUGF5bG9hZGAsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyT0ZDU2lnblBheWxvYWQpKTtcblxuICAvLyBzaWduIHRyYW5zYWN0aW9uXG4gIGFwcC5wb3N0KCcvYXBpL3YyLzpjb2luL3NpZ250eCcsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyU2lnblR4KSk7XG4gIGFwcC5wb3N0KCcvYXBpL3YyLzpjb2luL3dhbGxldC86aWQvc2lnbnR4JywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJTaWduVHhXYWxsZXQpKTtcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9zaWdudHh0c3MnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVWMlNpZ25UU1NXYWxsZXRUeClcbiAgKTtcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9yZWNvdmVydG9rZW4nLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVWMlJlY292ZXJUb2tlbilcbiAgKTtcblxuICAvLyBzZW5kIHRyYW5zYWN0aW9uXG4gIGFwcC5wb3N0KCcvYXBpL3YyLzpjb2luL3dhbGxldC86aWQvc2VuZGNvaW5zJywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJTZW5kT25lKSk7XG4gIGFwcC5wb3N0KCcvYXBpL3YyLzpjb2luL3dhbGxldC86aWQvc2VuZG1hbnknLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVWMlNlbmRNYW55KSk7XG4gIGFwcC5wb3N0KFxuICAgICcvYXBpL3YyLzpjb2luL3dhbGxldC86aWQvcHJlYnVpbGRBbmRTaWduVHJhbnNhY3Rpb24nLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVWMlByZWJ1aWxkQW5kU2lnblRyYW5zYWN0aW9uKVxuICApO1xuXG4gIC8vIHRva2VuIGVuYWJsZW1lbnRcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9lbmFibGVUb2tlbnMnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVWMkVuYWJsZVRva2VucylcbiAgKTtcblxuICAvLyB1bnNwZW50IGNoYW5nZXNcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9jb25zb2xpZGF0ZXVuc3BlbnRzJyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJDb25zb2xpZGF0ZVVuc3BlbnRzKVxuICApO1xuICBhcHAucG9zdChcbiAgICAnL2FwaS92Mi86Y29pbi93YWxsZXQvOmlkL2Zhbm91dHVuc3BlbnRzJyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJGYW5PdXRVbnNwZW50cylcbiAgKTtcblxuICBhcHAucG9zdCgnL2FwaS92Mi86Y29pbi93YWxsZXQvOmlkL3N3ZWVwJywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJTd2VlcCkpO1xuXG4gIC8vIENQRlBcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9hY2NlbGVyYXRldHgnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVWMkFjY2VsZXJhdGVUcmFuc2FjdGlvbilcbiAgKTtcblxuICAvLyBhY2NvdW50LWJhc2VkXG4gIGFwcC5wb3N0KFxuICAgICcvYXBpL3YyLzpjb2luL3dhbGxldC86aWQvY29uc29saWRhdGVBY2NvdW50JyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJDb25zb2xpZGF0ZUFjY291bnQpXG4gICk7XG5cbiAgLy8gTWlzY2VsbGFuZW91c1xuICBhcHAucG9zdCgnL2FwaS92Mi86Y29pbi9jYW5vbmljYWxhZGRyZXNzJywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlQ2Fub25pY2FsQWRkcmVzcykpO1xuICBhcHAucG9zdCgnL2FwaS92Mi86Y29pbi92ZXJpZnlhZGRyZXNzJywgcGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJWZXJpZnlBZGRyZXNzKSk7XG4gIGFwcC5wdXQoXG4gICAgJy9hcGkvdjIvOmNvaW4vcGVuZGluZ2FwcHJvdmFscy86aWQnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVWMlBlbmRpbmdBcHByb3ZhbClcbiAgKTtcblxuICAvLyBsaWdodG5pbmcgLSBwYXkgaW52b2ljZVxuICBhcHAucG9zdChcbiAgICAnL2FwaS92Mi86Y29pbi93YWxsZXQvOmlkL2xpZ2h0bmluZy9wYXltZW50JyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlUGF5TGlnaHRuaW5nSW52b2ljZSlcbiAgKTtcblxuICAvLyBsaWdodG5pbmcgLSBvbmNoYWluIHdpdGhkcmF3YWxcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9saWdodG5pbmcvd2l0aGRyYXcnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVMaWdodG5pbmdXaXRoZHJhdylcbiAgKTtcblxuICAvLyBhbnkgb3RoZXIgQVBJIHYyIGNhbGxcbiAgYXBwLnVzZSgnL2FwaS92Mi91c2VyLyonLCBwYXJzZUJvZHksIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVWMlVzZXJSRVNUKSk7XG4gIGFwcC51c2UoJy9hcGkvdjIvOmNvaW4vKicsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyQ29pblNwZWNpZmljUkVTVCkpO1xuXG4gIGFwcC5wb3N0KFxuICAgICcvYXBpL25ldHdvcmsvdjEvZW50ZXJwcmlzZXMvOmVudGVycHJpc2VJZC9jbGllbnRzL2Nvbm5lY3Rpb25zJyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlTmV0d29ya1YxRW50ZXJwcmlzZUNsaWVudENvbm5lY3Rpb25zKVxuICApO1xuXG4gIC8vIGV2ZXJ5dGhpbmcgZWxzZSBzaG91bGQgdXNlIHRoZSBwcm94eSBoYW5kbGVyXG4gIGlmIChjb25maWcuZGlzYWJsZVByb3h5ICE9PSB0cnVlKSB7XG4gICAgYXBwLnVzZShcbiAgICAgICcvYXBpLzpuYW1lc3BhY2UvdlsxMl0vZW50ZXJwcmlzZXMvOmVudGVycHJpc2VJZC8qJyxcbiAgICAgIHBhcnNlQm9keSxcbiAgICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlUHJveHlSZXEpXG4gICAgKTtcblxuICAgIGFwcC51c2UocGFyc2VCb2R5LCBwcmVwYXJlQml0R28oY29uZmlnKSwgcHJvbWlzZVdyYXBwZXIoaGFuZGxlUHJveHlSZXEpKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0dXBTaWduaW5nUm91dGVzKGFwcDogZXhwcmVzcy5BcHBsaWNhdGlvbiwgY29uZmlnOiBDb25maWcpOiB2b2lkIHtcbiAgYXBwLnBvc3QoJy9hcGkvdjIvOmNvaW4vc2lnbicsIHBhcnNlQm9keSwgcHJlcGFyZUJpdEdvKGNvbmZpZyksIHByb21pc2VXcmFwcGVyKGhhbmRsZVYyU2lnbikpO1xuICBhcHAucG9zdChcbiAgICAnL2FwaS92Mi86Y29pbi90c3NzaGFyZS86c2hhcmV0eXBlJyxcbiAgICBwYXJzZUJvZHksXG4gICAgcHJlcGFyZUJpdEdvKGNvbmZpZyksXG4gICAgcHJvbWlzZVdyYXBwZXIoaGFuZGxlVjJHZW5lcmF0ZVNoYXJlVFNTKVxuICApO1xuICBhcHAucG9zdChcbiAgICBgL2FwaS92Mi9vZmMvc2lnblBheWxvYWRgLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVWMk9GQ1NpZ25QYXlsb2FkSW5FeHRTaWduaW5nTW9kZSlcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldHVwTGlnaHRuaW5nU2lnbmVyTm9kZVJvdXRlcyhhcHA6IGV4cHJlc3MuQXBwbGljYXRpb24sIGNvbmZpZzogQ29uZmlnKTogdm9pZCB7XG4gIGFwcC5wb3N0KFxuICAgICcvYXBpL3YyLzpjb2luL3dhbGxldC86aWQvaW5pdHdhbGxldCcsXG4gICAgcGFyc2VCb2R5LFxuICAgIHByZXBhcmVCaXRHbyhjb25maWcpLFxuICAgIHByb21pc2VXcmFwcGVyKGhhbmRsZUluaXRMaWdodG5pbmdXYWxsZXQpXG4gICk7XG4gIGFwcC5wb3N0KFxuICAgICcvYXBpL3YyLzpjb2luL3dhbGxldC86aWQvc2lnbmVybWFjYXJvb24nLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVDcmVhdGVTaWduZXJNYWNhcm9vbilcbiAgKTtcbiAgYXBwLnBvc3QoXG4gICAgJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC91bmxvY2t3YWxsZXQnLFxuICAgIHBhcnNlQm9keSxcbiAgICBwcmVwYXJlQml0R28oY29uZmlnKSxcbiAgICBwcm9taXNlV3JhcHBlcihoYW5kbGVVbmxvY2tMaWdodG5pbmdXYWxsZXQpXG4gICk7XG4gIGFwcC5nZXQoJy9hcGkvdjIvOmNvaW4vd2FsbGV0LzppZC9zdGF0ZScsIHByZXBhcmVCaXRHbyhjb25maWcpLCBwcm9taXNlV3JhcHBlcihoYW5kbGVHZXRMaWdodG5pbmdXYWxsZXRTdGF0ZSkpO1xufVxuIl19Выполнить команду
Для локальной разработки. Не используйте в интернете!