PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@bitgo/sdk-api/dist/src/v1
Просмотр файла: pendingapproval.js
"use strict";
/**
* @hidden
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
/**
*/
// Pending Approval Object
// Handles approving, rejecting and getting information on pending approvals
//
// Copyright 2015, BitGo, Inc. All Rights Reserved.
//
const sdk_core_1 = require("@bitgo/sdk-core");
const utxolib = __importStar(require("@bitgo/utxo-lib"));
const lodash_1 = __importDefault(require("lodash"));
const util_1 = require("../util");
//
// Constructor
//
const PendingApproval = function (bitgo, pendingApproval, wallet) {
// @ts-expect-error - no implicit this
this.bitgo = bitgo;
// @ts-expect-error - no implicit this
this.pendingApproval = pendingApproval;
// @ts-expect-error - no implicit this
this.wallet = wallet;
};
//
// id
// Get the id of this pending approval.
//
PendingApproval.prototype.id = function () {
return this.pendingApproval.id;
};
//
// ownerType
// Get the owner type (wallet or enterprise)
// Pending approvals can be approved or modified by different scopes (depending on how they were created)
// If a pending approval is owned by a wallet, then it can be approved by administrators of the wallet
// If a pending approval is owned by an enterprise, then it can be approved by administrators of the enterprise
//
PendingApproval.prototype.ownerType = function (params, callback) {
params = params || {};
sdk_core_1.common.validateParams(params, [], [], callback);
if (this.pendingApproval.walletId) {
return 'wallet';
}
else if (this.pendingApproval.enterprise) {
return 'enterprise';
}
else {
throw new Error('unexpected pending approval owner: neither walletId nor enterprise was present');
}
};
//
// walletId
// Get the wallet ID that owns / is associated with the pending approval
//
PendingApproval.prototype.walletId = function () {
return this.pendingApproval.walletId;
};
//
// enterpriseId
// Get the enterprise ID that owns / is associated with the pending approval
//
PendingApproval.prototype.enterpriseId = function () {
return this.pendingApproval.enterprise;
};
//
// state
// Get the state of the pending approval
//
PendingApproval.prototype.state = function () {
return this.pendingApproval.state;
};
//
// creator
// Get the id of the user that performed the action resulting in this pending approval
//
PendingApproval.prototype.creator = function () {
return this.pendingApproval.creator;
};
//
// type
// Get the type of the pending approval (what it approves)
// Example: transactionRequest, tagUpdateRequest, policyRuleRequest
//
PendingApproval.prototype.type = function () {
if (!this.pendingApproval.info) {
throw new Error('pending approval info is not available');
}
return this.pendingApproval.info.type;
};
//
// type
// Get information about the pending approval
//
PendingApproval.prototype.info = function () {
return this.pendingApproval.info;
};
//
// approvalsRequired
// get the number of approvals that are required for this pending approval to be approved.
// Defaults to 1 if approvalsRequired doesn't exist on the object
//
PendingApproval.prototype.approvalsRequired = function () {
return this.pendingApproval.approvalsRequired || 1;
};
//
// url
// Gets the url for this pending approval
//
PendingApproval.prototype.url = function (extra) {
extra = extra || '';
return this.bitgo.url('/pendingapprovals/' + this.id() + extra);
};
//
// get
// Refetches this pending approval and returns it
//
PendingApproval.prototype.get = function (params, callback) {
params = params || {};
sdk_core_1.common.validateParams(params, [], [], callback);
const self = this;
return Promise.resolve(this.bitgo.get(this.url()).result())
.then(function (res) {
self.pendingApproval = res;
return self;
})
.then(callback)
.catch(callback);
};
//
// Helper function to ensure that self.wallet is set
//
PendingApproval.prototype.populateWallet = function () {
const self = this;
if (!self.wallet) {
return self.bitgo
.wallets()
.get({ id: self.info().transactionRequest.sourceWallet })
.then(function (wallet) {
if (!wallet) {
throw new Error('unexpected - unable to get wallet using sourcewallet');
}
self.wallet = wallet;
});
}
if (self.wallet.id() !== self.info().transactionRequest.sourceWallet) {
throw new Error('unexpected source wallet for pending approval');
}
return Promise.resolve(); // otherwise returns undefined
};
//
// helper function to recreate and sign a transaction on a wallet
// we should hopefully be able to move this logic server side soon
//
PendingApproval.prototype.recreateAndSignTransaction = function (params, callback) {
params = lodash_1.default.extend({}, params);
sdk_core_1.common.validateParams(params, ['txHex'], [], callback);
const transaction = utxolib.bitgo.createTransactionFromHex(params.txHex, utxolib.networks.bitcoin);
if (!transaction.outs) {
throw new Error('transaction had no outputs or failed to parse successfully');
}
const network = utxolib.networks[sdk_core_1.common.Environments[this.bitgo.getEnv()].network];
params.recipients = {};
const self = this;
return (0, util_1.tryPromise)(function () {
if (self.info().transactionRequest.recipients) {
// recipients object found on the pending approvals - use it
params.recipients = self.info().transactionRequest.recipients;
return;
}
if (transaction.outs.length <= 2) {
transaction.outs.forEach(function (out) {
const outAddress = utxolib.address.fromOutputScript(out.script, network);
if (self.info().transactionRequest.destinationAddress === outAddress) {
// If this is the destination, then spend to it
params.recipients[outAddress] = out.value;
}
});
return;
}
// This looks like a sendmany
// Attempt to figure out the outputs by choosing all outputs that were not going back to the wallet as change addresses
return self.wallet.addresses({ chain: 1, sort: -1, limit: 500 }).then(function (result) {
const changeAddresses = lodash_1.default.keyBy(result.addresses, 'address');
transaction.outs.forEach(function (out) {
const outAddress = utxolib.address.fromOutputScript(out.script, network);
if (!changeAddresses[outAddress]) {
// If this is not a change address, then spend to it
params.recipients[outAddress] = out.value;
}
});
});
}).then(function () {
return self.wallet.createAndSignTransaction(params);
});
};
//
// constructApprovalTx
// constructs/signs a transaction for this pending approval, returning the txHex (but not sending it)
//
PendingApproval.prototype.constructApprovalTx = function (params, callback) {
params = params || {};
sdk_core_1.common.validateParams(params, [], ['walletPassphrase'], callback);
if (this.type() === 'transactionRequest' && !(params.walletPassphrase || params.xprv)) {
throw new Error('wallet passphrase or xprv required to approve a transactionRequest');
}
if (params.useOriginalFee) {
if (!lodash_1.default.isBoolean(params.useOriginalFee)) {
throw new Error('invalid type for useOriginalFeeRate');
}
if (params.fee || params.feeRate || params.feeTxConfirmTarget) {
throw new Error('cannot specify a fee/feerate/feeTxConfirmTarget as well as useOriginalFee');
}
}
const self = this;
return (0, util_1.tryPromise)(function () {
if (self.type() === 'transactionRequest') {
const extendParams = { txHex: self.info().transactionRequest.transaction };
if (params.useOriginalFee) {
extendParams.fee = self.info().transactionRequest.fee;
}
return self.populateWallet().then(function () {
return self.recreateAndSignTransaction(lodash_1.default.extend(params, extendParams));
});
}
});
};
//
// approve
// sets the pending approval to an approved state
//
PendingApproval.prototype.approve = function (params, callback) {
params = params || {};
sdk_core_1.common.validateParams(params, [], ['walletPassphrase', 'otp'], callback);
let canRecreateTransaction = true;
if (this.type() === 'transactionRequest') {
if (!params.walletPassphrase && !params.xprv) {
canRecreateTransaction = false;
}
// check the wallet balance and compare it with the transaction amount and fee
if (lodash_1.default.isUndefined(params.forceRecreate) && lodash_1.default.isObject(lodash_1.default.get(this, 'wallet.wallet'))) {
const requestedAmount = this.pendingApproval.info.transactionRequest.requestedAmount || 0;
const walletBalance = this.wallet.wallet.spendableBalance;
const delta = Math.abs(requestedAmount - walletBalance);
if (delta <= 10000) {
// it's a sweep because we're within 10k satoshis of the wallet balance
canRecreateTransaction = false;
}
}
}
const self = this;
return (0, util_1.tryPromise)(function () {
if (self.type() === 'transactionRequest') {
if (params.tx) {
// the approval tx was reconstructed and explicitly specified - pass it through
return {
tx: params.tx,
};
}
// this user may not have spending privileges or a passphrase may not have been passed in
if (!canRecreateTransaction) {
return {
tx: self.info().transactionRequest.transaction,
};
}
return self.populateWallet().then(function () {
const recreationParams = lodash_1.default.extend({}, params, { txHex: self.info().transactionRequest.transaction }, self.info().transactionRequest.buildParams);
// delete the old build params because we want 'recreateAndSign' to recreate the transaction
delete recreationParams.fee;
delete recreationParams.unspents;
delete recreationParams.txInfo;
delete recreationParams.estimatedSize;
delete recreationParams.changeAddresses;
return self.recreateAndSignTransaction(recreationParams);
});
}
})
.then(function (transaction) {
const approvalParams = { state: 'approved', otp: params.otp };
if (transaction) {
approvalParams.tx = transaction.tx;
}
return Promise.resolve(self.bitgo.put(self.url()).send(approvalParams).result()).then(callback).catch(callback);
})
.catch(function (error) {
if (!canRecreateTransaction &&
(error.message.indexOf('could not find unspent output for input') !== -1 ||
error.message.indexOf('transaction conflicts with an existing transaction in the send queue') !== -1)) {
throw new Error('unspents expired, wallet passphrase or xprv required to recreate transaction');
}
if (lodash_1.default.isUndefined(params.forceRecreate) &&
error.message.indexOf('could not find unspent output for input') !== -1) {
// if the unspents can't be found, we must retry with a newly constructed transaction, so we delete the tx and try again
// deleting params.tx will force the code to reach the 'recreateAndSignTransaction' function
delete params.tx;
params.forceRecreate = true;
self.approve(params, callback);
}
else {
throw error;
}
});
};
//
// rejected
// sets the pending approval to a rejected state
//
PendingApproval.prototype.reject = function (params, callback) {
params = params || {};
sdk_core_1.common.validateParams(params, [], [], callback);
return Promise.resolve(this.bitgo.put(this.url()).send({ state: 'rejected' }).result())
.then(callback)
.catch(callback);
};
//
// cancel
// rejects the pending approval
//
PendingApproval.prototype.cancel = function (params, callback) {
return this.reject(params, callback);
};
module.exports = PendingApproval;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVuZGluZ2FwcHJvdmFsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3YxL3BlbmRpbmdhcHByb3ZhbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7O0dBRUc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFSDtHQUNHO0FBQ0gsMEJBQTBCO0FBQzFCLDRFQUE0RTtBQUM1RSxFQUFFO0FBQ0Ysb0RBQW9EO0FBQ3BELEVBQUU7QUFDRiw4Q0FBeUM7QUFDekMseURBQTJDO0FBRTNDLG9EQUF1QjtBQUN2QixrQ0FBcUM7QUFFckMsRUFBRTtBQUNGLGNBQWM7QUFDZCxFQUFFO0FBQ0YsTUFBTSxlQUFlLEdBQUcsVUFBVSxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU07SUFDOUQsc0NBQXNDO0lBQ3RDLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO0lBQ25CLHNDQUFzQztJQUN0QyxJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsQ0FBQztJQUN2QyxzQ0FBc0M7SUFDdEMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7QUFDdkIsQ0FBQyxDQUFDO0FBRUYsRUFBRTtBQUNGLEtBQUs7QUFDTCx1Q0FBdUM7QUFDdkMsRUFBRTtBQUNGLGVBQWUsQ0FBQyxTQUFTLENBQUMsRUFBRSxHQUFHO0lBQzdCLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7QUFDakMsQ0FBQyxDQUFDO0FBRUYsRUFBRTtBQUNGLFlBQVk7QUFDWiw0Q0FBNEM7QUFDNUMseUdBQXlHO0FBQ3pHLHNHQUFzRztBQUN0RywrR0FBK0c7QUFDL0csRUFBRTtBQUNGLGVBQWUsQ0FBQyxTQUFTLENBQUMsU0FBUyxHQUFHLFVBQVUsTUFBTSxFQUFFLFFBQVE7SUFDOUQsTUFBTSxHQUFHLE1BQU0sSUFBSSxFQUFFLENBQUM7SUFDdEIsaUJBQU0sQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFF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LENBQUMsUUFBUSxDQUFDLENBQUM7QUFDckIsQ0FBQyxDQUFDO0FBRUYsRUFBRTtBQUNGLFNBQVM7QUFDVCwrQkFBK0I7QUFDL0IsRUFBRTtBQUNGLGVBQWUsQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLFVBQVUsTUFBTSxFQUFFLFFBQVE7SUFDM0QsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQztBQUN2QyxDQUFDLENBQUM7QUFFRixpQkFBUyxlQUFlLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBoaWRkZW5cbiAqL1xuXG4vKipcbiAqL1xuLy8gUGVuZGluZyBBcHByb3ZhbCBPYmplY3Rcbi8vIEhhbmRsZXMgYXBwcm92aW5nLCByZWplY3RpbmcgYW5kIGdldHRpbmcgaW5mb3JtYXRpb24gb24gcGVuZGluZyBhcHByb3ZhbHNcbi8vXG4vLyBDb3B5cmlnaHQgMjAxNSwgQml0R28sIEluYy4gIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4vL1xuaW1wb3J0IHsgY29tbW9uIH0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcbmltcG9ydCAqIGFzIHV0eG9saWIgZnJvbSAnQGJpdGdvL3V0eG8tbGliJztcblxuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IHRyeVByb21pc2UgfSBmcm9tICcuLi91dGlsJztcblxuLy9cbi8vIENvbnN0cnVjdG9yXG4vL1xuY29uc3QgUGVuZGluZ0FwcHJvdmFsID0gZnVuY3Rpb24gKGJpdGdvLCBwZW5kaW5nQXBwcm92YWwsIHdhbGxldCkge1xuICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gbm8gaW1wbGljaXQgdGhpc1xuICB0aGlzLmJpdGdvID0gYml0Z287XG4gIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBubyBpbXBsaWNpdCB0aGlzXG4gIHRoaXMucGVuZGluZ0FwcHJvdmFsID0gcGVuZGluZ0FwcHJvdmFsO1xuICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gbm8gaW1wbGljaXQgdGhpc1xuICB0aGlzLndhbGxldCA9IHdhbGxldDtcbn07XG5cbi8vXG4vLyBpZFxuLy8gR2V0IHRoZSBpZCBvZiB0aGlzIHBlbmRpbmcgYXBwcm92YWwuXG4vL1xuUGVuZGluZ0FwcHJvdmFsLnByb3RvdHlwZS5pZCA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMucGVuZGluZ0FwcHJvdmFsLmlkO1xufTtcblxuLy9cbi8vIG93bmVyVHlwZVxuLy8gR2V0IHRoZSBvd25lciB0eXBlICh3YWxsZXQgb3IgZW50ZXJwcmlzZSlcbi8vIFBlbmRpbmcgYXBwcm92YWxzIGNhbiBiZSBhcHByb3ZlZCBvciBtb2RpZmllZCBieSBkaWZmZXJlbnQgc2NvcGVzIChkZXBlbmRpbmcgb24gaG93IHRoZXkgd2VyZSBjcmVhdGVkKVxuLy8gSWYgYSBwZW5kaW5nIGFwcHJvdmFsIGlzIG93bmVkIGJ5IGEgd2FsbGV0LCB0aGVuIGl0IGNhbiBiZSBhcHByb3ZlZCBieSBhZG1pbmlzdHJhdG9ycyBvZiB0aGUgd2FsbGV0XG4vLyBJZiBhIHBlbmRpbmcgYXBwcm92YWwgaXMgb3duZWQgYnkgYW4gZW50ZXJwcmlzZSwgdGhlbiBpdCBjYW4gYmUgYXBwcm92ZWQgYnkgYWRtaW5pc3RyYXRvcnMgb2YgdGhlIGVudGVycHJpc2Vcbi8vXG5QZW5kaW5nQXBwcm92YWwucHJvdG90eXBlLm93bmVyVHlwZSA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgW10sIFtdLCBjYWxsYmFjayk7XG5cbiAgaWYgKHRoaXMucGVuZGluZ0FwcHJvdmFsLndhbGxldElkKSB7XG4gICAgcmV0dXJuICd3YWxsZXQnO1xuICB9IGVsc2UgaWYgKHRoaXMucGVuZGluZ0FwcHJvdmFsLmVudGVycHJpc2UpIHtcbiAgICByZXR1cm4gJ2VudGVycHJpc2UnO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcigndW5leHBlY3RlZCBwZW5kaW5nIGFwcHJvdmFsIG93bmVyOiBuZWl0aGVyIHdhbGxldElkIG5vciBlbnRlcnByaXNlIHdhcyBwcmVzZW50Jyk7XG4gIH1cbn07XG5cbi8vXG4vLyB3YWxsZXRJZFxuLy8gR2V0IHRoZSB3YWxsZXQgSUQgdGhhdCBvd25zIC8gaXMgYXNzb2NpYXRlZCB3aXRoIHRoZSBwZW5kaW5nIGFwcHJvdmFsXG4vL1xuUGVuZGluZ0FwcHJvdmFsLnByb3RvdHlwZS53YWxsZXRJZCA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMucGVuZGluZ0FwcHJvdmFsLndhbGxldElkO1xufTtcblxuLy9cbi8vIGVudGVycHJpc2VJZFxuLy8gR2V0IHRoZSBlbnRlcnByaXNlIElEIHRoYXQgb3ducyAvIGlzIGFzc29jaWF0ZWQgd2l0aCB0aGUgcGVuZGluZyBhcHByb3ZhbFxuLy9cblBlbmRpbmdBcHByb3ZhbC5wcm90b3R5cGUuZW50ZXJwcmlzZUlkID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy5wZW5kaW5nQXBwcm92YWwuZW50ZXJwcmlzZTtcbn07XG5cbi8vXG4vLyBzdGF0ZVxuLy8gR2V0IHRoZSBzdGF0ZSBvZiB0aGUgcGVuZGluZyBhcHByb3ZhbFxuLy9cblBlbmRpbmdBcHByb3ZhbC5wcm90b3R5cGUuc3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLnBlbmRpbmdBcHByb3ZhbC5zdGF0ZTtcbn07XG5cbi8vXG4vLyBjcmVhdG9yXG4vLyBHZXQgdGhlIGlkIG9mIHRoZSB1c2VyIHRoYXQgcGVyZm9ybWVkIHRoZSBhY3Rpb24gcmVzdWx0aW5nIGluIHRoaXMgcGVuZGluZyBhcHByb3ZhbFxuLy9cblBlbmRpbmdBcHByb3ZhbC5wcm90b3R5cGUuY3JlYXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMucGVuZGluZ0FwcHJvdmFsLmNyZWF0b3I7XG59O1xuXG4vL1xuLy8gdHlwZVxuLy8gR2V0IHRoZSB0eXBlIG9mIHRoZSBwZW5kaW5nIGFwcHJvdmFsICh3aGF0IGl0IGFwcHJvdmVzKVxuLy8gRXhhbXBsZTogdHJhbnNhY3Rpb25SZXF1ZXN0LCB0YWdVcGRhdGVSZXF1ZXN0LCBwb2xpY3lSdWxlUmVxdWVzdFxuLy9cblBlbmRpbmdBcHByb3ZhbC5wcm90b3R5cGUudHlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgaWYgKCF0aGlzLnBlbmRpbmdBcHByb3ZhbC5pbmZvKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwZW5kaW5nIGFwcHJvdmFsIGluZm8gaXMgbm90IGF2YWlsYWJsZScpO1xuICB9XG4gIHJldHVybiB0aGlzLnBlbmRpbmdBcHByb3ZhbC5pbmZvLnR5cGU7XG59O1xuXG4vL1xuLy8gdHlwZVxuLy8gR2V0IGluZm9ybWF0aW9uIGFib3V0IHRoZSBwZW5kaW5nIGFwcHJvdmFsXG4vL1xuUGVuZGluZ0FwcHJvdmFsLnByb3RvdHlwZS5pbmZvID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy5wZW5kaW5nQXBwcm92YWwuaW5mbztcbn07XG5cbi8vXG4vLyBhcHByb3ZhbHNSZXF1aXJlZFxuLy8gZ2V0IHRoZSBudW1iZXIgb2YgYXBwcm92YWxzIHRoYXQgYXJlIHJlcXVpcmVkIGZvciB0aGlzIHBlbmRpbmcgYXBwcm92YWwgdG8gYmUgYXBwcm92ZWQuXG4vLyBEZWZhdWx0cyB0byAxIGlmIGFwcHJvdmFsc1JlcXVpcmVkIGRvZXNuJ3QgZXhpc3Qgb24gdGhlIG9iamVjdFxuLy9cblBlbmRpbmdBcHByb3ZhbC5wcm90b3R5cGUuYXBwcm92YWxzUmVxdWlyZWQgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLnBlbmRpbmdBcHByb3ZhbC5hcHByb3ZhbHNSZXF1aXJlZCB8fCAxO1xufTtcblxuLy9cbi8vIHVybFxuLy8gR2V0cyB0aGUgdXJsIGZvciB0aGlzIHBlbmRpbmcgYXBwcm92YWxcbi8vXG5QZW5kaW5nQXBwcm92YWwucHJvdG90eXBlLnVybCA9IGZ1bmN0aW9uIChleHRyYSkge1xuICBleHRyYSA9IGV4dHJhIHx8ICcnO1xuICByZXR1cm4gdGhpcy5iaXRnby51cmwoJy9wZW5kaW5nYXBwcm92YWxzLycgKyB0aGlzLmlkKCkgKyBleHRyYSk7XG59O1xuXG4vL1xuLy8gZ2V0XG4vLyBSZWZldGNoZXMgdGhpcyBwZW5kaW5nIGFwcHJvdmFsIGFuZCByZXR1cm5zIGl0XG4vL1xuUGVuZGluZ0FwcHJvdmFsLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFtdLCBbXSwgY2FsbGJhY2spO1xuXG4gIGNvbnN0IHNlbGYgPSB0aGlzO1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuYml0Z28uZ2V0KHRoaXMudXJsKCkpLnJlc3VsdCgpKVxuICAgIC50aGVuKGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgIHNlbGYucGVuZGluZ0FwcHJvdmFsID0gcmVzO1xuICAgICAgcmV0dXJuIHNlbGY7XG4gICAgfSlcbiAgICAudGhlbihjYWxsYmFjaylcbiAgICAuY2F0Y2goY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIEhlbHBlciBmdW5jdGlvbiB0byBlbnN1cmUgdGhhdCBzZWxmLndhbGxldCBpcyBzZXRcbi8vXG5QZW5kaW5nQXBwcm92YWwucHJvdG90eXBlLnBvcHVsYXRlV2FsbGV0ID0gZnVuY3Rpb24gKCkge1xuICBjb25zdCBzZWxmID0gdGhpcztcbiAgaWYgKCFzZWxmLndhbGxldCkge1xuICAgIHJldHVybiBzZWxmLmJpdGdvXG4gICAgICAud2FsbGV0cygpXG4gICAgICAuZ2V0KHsgaWQ6IHNlbGYuaW5mbygpLnRyYW5zYWN0aW9uUmVxdWVzdC5zb3VyY2VXYWxsZXQgfSlcbiAgICAgIC50aGVuKGZ1bmN0aW9uICh3YWxsZXQpIHtcbiAgICAgICAgaWYgKCF3YWxsZXQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3VuZXhwZWN0ZWQgLSB1bmFibGUgdG8gZ2V0IHdhbGxldCB1c2luZyBzb3VyY2V3YWxsZXQnKTtcbiAgICAgICAgfVxuICAgICAgICBzZWxmLndhbGxldCA9IHdhbGxldDtcbiAgICAgIH0pO1xuICB9XG5cbiAgaWYgKHNlbGYud2FsbGV0LmlkKCkgIT09IHNlbGYuaW5mbygpLnRyYW5zYWN0aW9uUmVxdWVzdC5zb3VyY2VXYWxsZXQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3VuZXhwZWN0ZWQgc291cmNlIHdhbGxldCBmb3IgcGVuZGluZyBhcHByb3ZhbCcpO1xuICB9XG5cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpOyAvLyBvdGhlcndpc2UgcmV0dXJucyB1bmRlZmluZWRcbn07XG5cbi8vXG4vLyBoZWxwZXIgZnVuY3Rpb24gdG8gcmVjcmVhdGUgYW5kIHNpZ24gYSB0cmFuc2FjdGlvbiBvbiBhIHdhbGxldFxuLy8gd2Ugc2hvdWxkIGhvcGVmdWxseSBiZSBhYmxlIHRvIG1vdmUgdGhpcyBsb2dpYyBzZXJ2ZXIgc2lkZSBzb29uXG4vL1xuUGVuZGluZ0FwcHJvdmFsLnByb3RvdHlwZS5yZWNyZWF0ZUFuZFNpZ25UcmFuc2FjdGlvbiA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IF8uZXh0ZW5kKHt9LCBwYXJhbXMpO1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbJ3R4SGV4J10sIFtdLCBjYWxsYmFjayk7XG5cbiAgY29uc3QgdHJhbnNhY3Rpb24gPSB1dHhvbGliLmJpdGdvLmNyZWF0ZVRyYW5zYWN0aW9uRnJvbUhleChwYXJhbXMudHhIZXgsIHV0eG9saWIubmV0d29ya3MuYml0Y29pbik7XG4gIGlmICghdHJhbnNhY3Rpb24ub3V0cykge1xuICAgIHRocm93IG5ldyBFcnJvcigndHJhbnNhY3Rpb24gaGFkIG5vIG91dHB1dHMgb3IgZmFpbGVkIHRvIHBhcnNlIHN1Y2Nlc3NmdWxseScpO1xuICB9XG5cbiAgY29uc3QgbmV0d29yayA9IHV0eG9saWIubmV0d29ya3NbY29tbW9uLkVudmlyb25tZW50c1t0aGlzLmJpdGdvLmdldEVudigpXS5uZXR3b3JrXTtcbiAgcGFyYW1zLnJlY2lwaWVudHMgPSB7fTtcblxuICBjb25zdCBzZWxmID0gdGhpcztcblxuICByZXR1cm4gdHJ5UHJvbWlzZShmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHNlbGYuaW5mbygpLnRyYW5zYWN0aW9uUmVxdWVzdC5yZWNpcGllbnRzKSB7XG4gICAgICAvLyByZWNpcGllbnRzIG9iamVjdCBmb3VuZCBvbiB0aGUgcGVuZGluZyBhcHByb3ZhbHMgLSB1c2UgaXRcbiAgICAgIHBhcmFtcy5yZWNpcGllbnRzID0gc2VsZi5pbmZvKCkudHJhbnNhY3Rpb25SZXF1ZXN0LnJlY2lwaWVudHM7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh0cmFuc2FjdGlvbi5vdXRzLmxlbmd0aCA8PSAyKSB7XG4gICAgICB0cmFuc2FjdGlvbi5vdXRzLmZvckVhY2goZnVuY3Rpb24gKG91dCkge1xuICAgICAgICBjb25zdCBvdXRBZGRyZXNzID0gdXR4b2xpYi5hZGRyZXNzLmZyb21PdXRwdXRTY3JpcHQob3V0LnNjcmlwdCwgbmV0d29yayk7XG4gICAgICAgIGlmIChzZWxmLmluZm8oKS50cmFuc2FjdGlvblJlcXVlc3QuZGVzdGluYXRpb25BZGRyZXNzID09PSBvdXRBZGRyZXNzKSB7XG4gICAgICAgICAgLy8gSWYgdGhpcyBpcyB0aGUgZGVzdGluYXRpb24sIHRoZW4gc3BlbmQgdG8gaXRcbiAgICAgICAgICBwYXJhbXMucmVjaXBpZW50c1tvdXRBZGRyZXNzXSA9IG91dC52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVGhpcyBsb29rcyBsaWtlIGEgc2VuZG1hbnlcbiAgICAvLyBBdHRlbXB0IHRvIGZpZ3VyZSBvdXQgdGhlIG91dHB1dHMgYnkgY2hvb3NpbmcgYWxsIG91dHB1dHMgdGhhdCB3ZXJlIG5vdCBnb2luZyBiYWNrIHRvIHRoZSB3YWxsZXQgYXMgY2hhbmdlIGFkZHJlc3Nlc1xuICAgIHJldHVybiBzZWxmLndhbGxldC5hZGRyZXNzZXMoeyBjaGFpbjogMSwgc29ydDogLTEsIGxpbWl0OiA1MDAgfSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICBjb25zdCBjaGFuZ2VBZGRyZXNzZXMgPSBfLmtleUJ5KHJlc3VsdC5hZGRyZXNzZXMsICdhZGRyZXNzJyk7XG4gICAgICB0cmFuc2FjdGlvbi5vdXRzLmZvckVhY2goZnVuY3Rpb24gKG91dCkge1xuICAgICAgICBjb25zdCBvdXRBZGRyZXNzID0gdXR4b2xpYi5hZGRyZXNzLmZyb21PdXRwdXRTY3JpcHQob3V0LnNjcmlwdCwgbmV0d29yayk7XG4gICAgICAgIGlmICghY2hhbmdlQWRkcmVzc2VzW291dEFkZHJlc3NdKSB7XG4gICAgICAgICAgLy8gSWYgdGhpcyBpcyBub3QgYSBjaGFuZ2UgYWRkcmVzcywgdGhlbiBzcGVuZCB0byBpdFxuICAgICAgICAgIHBhcmFtcy5yZWNpcGllbnRzW291dEFkZHJlc3NdID0gb3V0LnZhbHVlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHNlbGYud2FsbGV0LmNyZWF0ZUFuZFNpZ25UcmFuc2FjdGlvbihwYXJhbXMpO1xuICB9KTtcbn07XG5cbi8vXG4vLyBjb25zdHJ1Y3RBcHByb3ZhbFR4XG4vLyBjb25zdHJ1Y3RzL3NpZ25zIGEgdHJhbnNhY3Rpb24gZm9yIHRoaXMgcGVuZGluZyBhcHByb3ZhbCwgcmV0dXJuaW5nIHRoZSB0eEhleCAoYnV0IG5vdCBzZW5kaW5nIGl0KVxuLy9cblBlbmRpbmdBcHByb3ZhbC5wcm90b3R5cGUuY29uc3RydWN0QXBwcm92YWxUeCA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgW10sIFsnd2FsbGV0UGFzc3BocmFzZSddLCBjYWxsYmFjayk7XG5cbiAgaWYgKHRoaXMudHlwZSgpID09PSAndHJhbnNhY3Rpb25SZXF1ZXN0JyAmJiAhKHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlIHx8IHBhcmFtcy54cHJ2KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignd2FsbGV0IHBhc3NwaHJhc2Ugb3IgeHBydiByZXF1aXJlZCB0byBhcHByb3ZlIGEgdHJhbnNhY3Rpb25SZXF1ZXN0Jyk7XG4gIH1cblxuICBpZiAocGFyYW1zLnVzZU9yaWdpbmFsRmVlKSB7XG4gICAgaWYgKCFfLmlzQm9vbGVhbihwYXJhbXMudXNlT3JpZ2luYWxGZWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgdHlwZSBmb3IgdXNlT3JpZ2luYWxGZWVSYXRlJyk7XG4gICAgfVxuICAgIGlmIChwYXJhbXMuZmVlIHx8IHBhcmFtcy5mZWVSYXRlIHx8IHBhcmFtcy5mZWVUeENvbmZpcm1UYXJnZXQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY2Fubm90IHNwZWNpZnkgYSBmZWUvZmVlcmF0ZS9mZWVUeENvbmZpcm1UYXJnZXQgYXMgd2VsbCBhcyB1c2VPcmlnaW5hbEZlZScpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHNlbGYgPSB0aGlzO1xuICByZXR1cm4gdHJ5UHJvbWlzZShmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHNlbGYudHlwZSgpID09PSAndHJhbnNhY3Rpb25SZXF1ZXN0Jykge1xuICAgICAgY29uc3QgZXh0ZW5kUGFyYW1zOiBhbnkgPSB7IHR4SGV4OiBzZWxmLmluZm8oKS50cmFuc2FjdGlvblJlcXVlc3QudHJhbnNhY3Rpb24gfTtcbiAgICAgIGlmIChwYXJhbXMudXNlT3JpZ2luYWxGZWUpIHtcbiAgICAgICAgZXh0ZW5kUGFyYW1zLmZlZSA9IHNlbGYuaW5mbygpLnRyYW5zYWN0aW9uUmVxdWVzdC5mZWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2VsZi5wb3B1bGF0ZVdhbGxldCgpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gc2VsZi5yZWNyZWF0ZUFuZFNpZ25UcmFuc2FjdGlvbihfLmV4dGVuZChwYXJhbXMsIGV4dGVuZFBhcmFtcykpO1xuICAgICAgfSk7XG4gICAgfVxuICB9KTtcbn07XG5cbi8vXG4vLyBhcHByb3ZlXG4vLyBzZXRzIHRoZSBwZW5kaW5nIGFwcHJvdmFsIHRvIGFuIGFwcHJvdmVkIHN0YXRlXG4vL1xuUGVuZGluZ0FwcHJvdmFsLnByb3RvdHlwZS5hcHByb3ZlID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbXSwgWyd3YWxsZXRQYXNzcGhyYXNlJywgJ290cCddLCBjYWxsYmFjayk7XG5cbiAgbGV0IGNhblJlY3JlYXRlVHJhbnNhY3Rpb24gPSB0cnVlO1xuICBpZiAodGhpcy50eXBlKCkgPT09ICd0cmFuc2FjdGlvblJlcXVlc3QnKSB7XG4gICAgaWYgKCFwYXJhbXMud2FsbGV0UGFzc3BocmFzZSAmJiAhcGFyYW1zLnhwcnYpIHtcbiAgICAgIGNhblJlY3JlYXRlVHJhbnNhY3Rpb24gPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBjaGVjayB0aGUgd2FsbGV0IGJhbGFuY2UgYW5kIGNvbXBhcmUgaXQgd2l0aCB0aGUgdHJhbnNhY3Rpb24gYW1vdW50IGFuZCBmZWVcbiAgICBpZiAoXy5pc1VuZGVmaW5lZChwYXJhbXMuZm9yY2VSZWNyZWF0ZSkgJiYgXy5pc09iamVjdChfLmdldCh0aGlzLCAnd2FsbGV0LndhbGxldCcpKSkge1xuICAgICAgY29uc3QgcmVxdWVzdGVkQW1vdW50ID0gdGhpcy5wZW5kaW5nQXBwcm92YWwuaW5mby50cmFuc2FjdGlvblJlcXVlc3QucmVxdWVzdGVkQW1vdW50IHx8IDA7XG4gICAgICBjb25zdCB3YWxsZXRCYWxhbmNlID0gdGhpcy53YWxsZXQud2FsbGV0LnNwZW5kYWJsZUJhbGFuY2U7XG4gICAgICBjb25zdCBkZWx0YSA9IE1hdGguYWJzKHJlcXVlc3RlZEFtb3VudCAtIHdhbGxldEJhbGFuY2UpO1xuICAgICAgaWYgKGRlbHRhIDw9IDEwMDAwKSB7XG4gICAgICAgIC8vIGl0J3MgYSBzd2VlcCBiZWNhdXNlIHdlJ3JlIHdpdGhpbiAxMGsgc2F0b3NoaXMgb2YgdGhlIHdhbGxldCBiYWxhbmNlXG4gICAgICAgIGNhblJlY3JlYXRlVHJhbnNhY3Rpb24gPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb25zdCBzZWxmID0gdGhpcztcbiAgcmV0dXJuIHRyeVByb21pc2UoZnVuY3Rpb24gKCkge1xuICAgIGlmIChzZWxmLnR5cGUoKSA9PT0gJ3RyYW5zYWN0aW9uUmVxdWVzdCcpIHtcbiAgICAgIGlmIChwYXJhbXMudHgpIHtcbiAgICAgICAgLy8gdGhlIGFwcHJvdmFsIHR4IHdhcyByZWNvbnN0cnVjdGVkIGFuZCBleHBsaWNpdGx5IHNwZWNpZmllZCAtIHBhc3MgaXQgdGhyb3VnaFxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR4OiBwYXJhbXMudHgsXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIHRoaXMgdXNlciBtYXkgbm90IGhhdmUgc3BlbmRpbmcgcHJpdmlsZWdlcyBvciBhIHBhc3NwaHJhc2UgbWF5IG5vdCBoYXZlIGJlZW4gcGFzc2VkIGluXG4gICAgICBpZiAoIWNhblJlY3JlYXRlVHJhbnNhY3Rpb24pIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eDogc2VsZi5pbmZvKCkudHJhbnNhY3Rpb25SZXF1ZXN0LnRyYW5zYWN0aW9uLFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc2VsZi5wb3B1bGF0ZVdhbGxldCgpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCByZWNyZWF0aW9uUGFyYW1zID0gXy5leHRlbmQoXG4gICAgICAgICAge30sXG4gICAgICAgICAgcGFyYW1zLFxuICAgICAgICAgIHsgdHhIZXg6IHNlbGYuaW5mbygpLnRyYW5zYWN0aW9uUmVxdWVzdC50cmFuc2FjdGlvbiB9LFxuICAgICAgICAgIHNlbGYuaW5mbygpLnRyYW5zYWN0aW9uUmVxdWVzdC5idWlsZFBhcmFtc1xuICAgICAgICApO1xuICAgICAgICAvLyBkZWxldGUgdGhlIG9sZCBidWlsZCBwYXJhbXMgYmVjYXVzZSB3ZSB3YW50ICdyZWNyZWF0ZUFuZFNpZ24nIHRvIHJlY3JlYXRlIHRoZSB0cmFuc2FjdGlvblxuICAgICAgICBkZWxldGUgcmVjcmVhdGlvblBhcmFtcy5mZWU7XG4gICAgICAgIGRlbGV0ZSByZWNyZWF0aW9uUGFyYW1zLnVuc3BlbnRzO1xuICAgICAgICBkZWxldGUgcmVjcmVhdGlvblBhcmFtcy50eEluZm87XG4gICAgICAgIGRlbGV0ZSByZWNyZWF0aW9uUGFyYW1zLmVzdGltYXRlZFNpemU7XG4gICAgICAgIGRlbGV0ZSByZWNyZWF0aW9uUGFyYW1zLmNoYW5nZUFkZHJlc3NlcztcbiAgICAgICAgcmV0dXJuIHNlbGYucmVjcmVhdGVBbmRTaWduVHJhbnNhY3Rpb24ocmVjcmVhdGlvblBhcmFtcyk7XG4gICAgICB9KTtcbiAgICB9XG4gIH0pXG4gICAgLnRoZW4oZnVuY3Rpb24gKHRyYW5zYWN0aW9uKSB7XG4gICAgICBjb25zdCBhcHByb3ZhbFBhcmFtczogYW55ID0geyBzdGF0ZTogJ2FwcHJvdmVkJywgb3RwOiBwYXJhbXMub3RwIH07XG4gICAgICBpZiAodHJhbnNhY3Rpb24pIHtcbiAgICAgICAgYXBwcm92YWxQYXJhbXMudHggPSB0cmFuc2FjdGlvbi50eDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoc2VsZi5iaXRnby5wdXQoc2VsZi51cmwoKSkuc2VuZChhcHByb3ZhbFBhcmFtcykucmVzdWx0KCkpLnRoZW4oY2FsbGJhY2spLmNhdGNoKGNhbGxiYWNrKTtcbiAgICB9KVxuICAgIC5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIGlmIChcbiAgICAgICAgIWNhblJlY3JlYXRlVHJhbnNhY3Rpb24gJiZcbiAgICAgICAgKGVycm9yLm1lc3NhZ2UuaW5kZXhPZignY291bGQgbm90IGZpbmQgdW5zcGVudCBvdXRwdXQgZm9yIGlucHV0JykgIT09IC0xIHx8XG4gICAgICAgICAgZXJyb3IubWVzc2FnZS5pbmRleE9mKCd0cmFuc2FjdGlvbiBjb25mbGljdHMgd2l0aCBhbiBleGlzdGluZyB0cmFuc2FjdGlvbiBpbiB0aGUgc2VuZCBxdWV1ZScpICE9PSAtMSlcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Vuc3BlbnRzIGV4cGlyZWQsIHdhbGxldCBwYXNzcGhyYXNlIG9yIHhwcnYgcmVxdWlyZWQgdG8gcmVjcmVhdGUgdHJhbnNhY3Rpb24nKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgXy5pc1VuZGVmaW5lZChwYXJhbXMuZm9yY2VSZWNyZWF0ZSkgJiZcbiAgICAgICAgZXJyb3IubWVzc2FnZS5pbmRleE9mKCdjb3VsZCBub3QgZmluZCB1bnNwZW50IG91dHB1dCBmb3IgaW5wdXQnKSAhPT0gLTFcbiAgICAgICkge1xuICAgICAgICAvLyBpZiB0aGUgdW5zcGVudHMgY2FuJ3QgYmUgZm91bmQsIHdlIG11c3QgcmV0cnkgd2l0aCBhIG5ld2x5IGNvbnN0cnVjdGVkIHRyYW5zYWN0aW9uLCBzbyB3ZSBkZWxldGUgdGhlIHR4IGFuZCB0cnkgYWdhaW5cbiAgICAgICAgLy8gZGVsZXRpbmcgcGFyYW1zLnR4IHdpbGwgZm9yY2UgdGhlIGNvZGUgdG8gcmVhY2ggdGhlICdyZWNyZWF0ZUFuZFNpZ25UcmFuc2FjdGlvbicgZnVuY3Rpb25cbiAgICAgICAgZGVsZXRlIHBhcmFtcy50eDtcbiAgICAgICAgcGFyYW1zLmZvcmNlUmVjcmVhdGUgPSB0cnVlO1xuICAgICAgICBzZWxmLmFwcHJvdmUocGFyYW1zLCBjYWxsYmFjayk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICB9KTtcbn07XG5cbi8vXG4vLyByZWplY3RlZFxuLy8gc2V0cyB0aGUgcGVuZGluZyBhcHByb3ZhbCB0byBhIHJlamVjdGVkIHN0YXRlXG4vL1xuUGVuZGluZ0FwcHJvdmFsLnByb3RvdHlwZS5yZWplY3QgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFtdLCBbXSwgY2FsbGJhY2spO1xuXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5iaXRnby5wdXQodGhpcy51cmwoKSkuc2VuZCh7IHN0YXRlOiAncmVqZWN0ZWQnIH0pLnJlc3VsdCgpKVxuICAgIC50aGVuKGNhbGxiYWNrKVxuICAgIC5jYXRjaChjYWxsYmFjayk7XG59O1xuXG4vL1xuLy8gY2FuY2VsXG4vLyByZWplY3RzIHRoZSBwZW5kaW5nIGFwcHJvdmFsXG4vL1xuUGVuZGluZ0FwcHJvdmFsLnByb3RvdHlwZS5jYW5jZWwgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICByZXR1cm4gdGhpcy5yZWplY3QocGFyYW1zLCBjYWxsYmFjayk7XG59O1xuXG5leHBvcnQgPSBQZW5kaW5nQXBwcm92YWw7XG4iXX0=Выполнить команду
Для локальной разработки. Не используйте в интернете!