PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@bitgo/sdk-coin-hbar/dist/src
Просмотр файла: hbar.js
"use strict";
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;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Hbar = void 0;
/**
* @prettier
*/
const statics_1 = require("@bitgo/statics");
const sdk_core_1 = require("@bitgo/sdk-core");
const bignumber_js_1 = require("bignumber.js");
const stellar = __importStar(require("stellar-sdk"));
const seedValidator_1 = require("./seedValidator");
const lib_1 = require("./lib");
const Utils = __importStar(require("./lib/utils"));
const _ = __importStar(require("lodash"));
const sdk_1 = require("@hashgraph/sdk");
const keyPair_1 = require("./lib/keyPair");
class Hbar extends sdk_core_1.BaseCoin {
constructor(bitgo, staticsCoin) {
super(bitgo);
if (!staticsCoin) {
throw new Error('missing required constructor parameter staticsCoin');
}
this._staticsCoin = staticsCoin;
}
getChain() {
return this._staticsCoin.name;
}
getFamily() {
return this._staticsCoin.family;
}
getFullName() {
return this._staticsCoin.fullName;
}
getBaseFactor() {
return Math.pow(10, this._staticsCoin.decimalPlaces);
}
static createInstance(bitgo, staticsCoin) {
return new Hbar(bitgo, staticsCoin);
}
/**
* Flag for sending value of 0
* @returns {boolean} True if okay to send 0 value, false otherwise
*/
valuelessTransferAllowed() {
return false;
}
/**
* Checks if this is a valid base58 or hex address
* @param address
*/
isValidAddress(address) {
try {
return Utils.isValidAddressWithPaymentId(address);
}
catch (e) {
return false;
}
}
/** inheritdoc */
deriveKeyWithSeed() {
throw new sdk_core_1.NotSupported('method deriveKeyWithSeed not supported for eddsa curve');
}
/** inheritdoc */
generateKeyPair(seed) {
const keyPair = seed ? new lib_1.KeyPair({ seed }) : new lib_1.KeyPair();
const keys = keyPair.getKeys();
if (!keys.prv) {
throw new Error('Keypair generation failed to generate a prv');
}
return {
pub: keys.pub,
prv: keys.prv,
};
}
/** inheritdoc */
generateRootKeyPair(seed) {
const keyPair = seed ? new lib_1.KeyPair({ seed }) : new lib_1.KeyPair();
const keys = keyPair.getKeys(true);
if (!keys.prv) {
throw new Error('Missing prv in key generation.');
}
return { prv: keys.prv + keys.pub, pub: keys.pub };
}
async parseTransaction(params) {
return {};
}
/**
* Check if address is valid, then make sure it matches the base address.
*
* @param {VerifyAddressOptions} params
* @param {String} params.address - the address to verify
* @param {String} params.baseAddress - the base address from the wallet
*/
async isWalletAddress(params) {
const { address, baseAddress } = params;
return Utils.isSameBaseAddress(address, baseAddress);
}
async verifyTransaction(params) {
// asset name to transfer amount map
const coinConfig = statics_1.coins.get(this.getChain());
const { txParams: txParams, txPrebuild: txPrebuild, memo: memo } = params;
const transaction = new lib_1.Transaction(coinConfig);
if (!txPrebuild.txHex) {
throw new Error('missing required tx prebuild property txHex');
}
transaction.fromRawTransaction(txPrebuild.txHex);
const explainTxParams = {
txHex: txPrebuild.txHex,
feeInfo: txPrebuild.feeInfo,
memo: memo,
};
const explainedTx = await this.explainTransaction(explainTxParams);
if (!txParams.recipients) {
throw new Error('missing required tx params property recipients');
}
// for enabletoken, recipient output amount is 0
const recipients = txParams.recipients.map((recipient) => ({
...recipient,
amount: txParams.type === 'enabletoken' ? '0' : recipient.amount,
address: Utils.getAddressDetails(recipient.address).address,
}));
if (coinConfig.isToken) {
recipients.forEach((recipient) => {
if (recipient.tokenName !== undefined && recipient.tokenName !== coinConfig.name) {
throw new Error('Incorrect token name specified in recipients');
}
recipient.tokenName = coinConfig.name;
});
}
// verify recipients from params and explainedTx
const filteredRecipients = recipients?.map((recipient) => _.pick(recipient, ['address', 'amount', 'tokenName']));
const filteredOutputs = explainedTx.outputs.map((output) => _.pick(output, ['address', 'amount', 'tokenName']));
if (!_.isEqual(filteredOutputs, filteredRecipients)) {
throw new Error('Tx outputs does not match with expected txParams recipients');
}
return true;
}
/**
* Assemble keychain and half-sign prebuilt transaction
*
* @param params
* @param params.txPrebuild {Object} prebuild object returned by platform
* @param params.prv {String} user prv
* @returns Promise<SignedTransaction>
*/
async signTransaction(params) {
const factory = this.getBuilderFactory();
const txBuilder = factory.from(params.txPrebuild.txHex);
txBuilder.sign({ key: params.prv });
const transaction = await txBuilder.build();
if (!transaction) {
throw new Error('Invalid messaged passed to signMessage');
}
const response = {
txHex: transaction.toBroadcastFormat(),
};
return transaction.signature.length >= 2 ? response : { halfSigned: response };
}
/**
* Sign message with private key
*
* @param key
* @param message
* @return {Buffer} A signature over the given message using the given key
*/
async signMessage(key, message) {
const msg = Buffer.isBuffer(message) ? message.toString('utf8') : message;
// reconstitute keys and sign
return Buffer.from(new lib_1.KeyPair({ prv: key.prv }).signMessage(msg));
}
/**
* Builds a funds recovery transaction without BitGo.
* We need to do three queries during this:
* 1) Node query - how much money is in the account
* 2) Build transaction - build our transaction for the amount
* 3) Send signed build - send our signed build to a public node
* @param params
*/
async recover(params) {
const isUnsignedSweep = (params.backupKey.startsWith(keyPair_1.PUBLIC_KEY_PREFIX) && params.userKey.startsWith(keyPair_1.PUBLIC_KEY_PREFIX)) ||
(Utils.isValidPublicKey(params.userKey) && Utils.isValidPublicKey(params.backupKey));
// Validate the root address
if (!this.isValidAddress(params.rootAddress)) {
throw new Error('invalid rootAddress, got: ' + params.rootAddress);
}
// Validate the destination address
if (!this.isValidAddress(params.recoveryDestination)) {
throw new Error('invalid recoveryDestination, got: ' + params.recoveryDestination);
}
// Validate nodeId
if (params.nodeId && !Utils.isValidAddress(params.nodeId)) {
throw new Error('invalid nodeId, got: ' + params.nodeId);
}
// validate fee
if (params.maxFee && !Utils.isValidAmount(params.maxFee)) {
throw new Error('invalid maxFee, got: ' + params.maxFee);
}
// validate startTime
if (params.startTime) {
Utils.validateStartTime(params.startTime);
}
if (isUnsignedSweep && !params.startTime) {
throw new Error('start time is required for unsigned sweep');
}
if (!isUnsignedSweep && !params.walletPassphrase) {
throw new Error('walletPassphrase is required for non-bitgo recovery');
}
let userPrv;
let backUp;
if (!isUnsignedSweep) {
try {
userPrv = this.bitgo.decrypt({ input: params.userKey, password: params.walletPassphrase });
backUp = this.bitgo.decrypt({ input: params.backupKey, password: params.walletPassphrase });
}
catch (e) {
throw new Error('unable to decrypt userKey or backupKey with the walletPassphrase provided, got error: ' + e.message);
}
}
// validate userKey for unsigned sweep
if (isUnsignedSweep && !Utils.isValidPublicKey(params.userKey)) {
throw new Error('invalid userKey, got: ' + params.userKey);
}
// validate backupKey for unsigned sweep
if (isUnsignedSweep && !Utils.isValidPublicKey(params.backupKey)) {
throw new Error('invalid backupKey, got: ' + params.backupKey);
}
const { address: destinationAddress, memoId } = Utils.getAddressDetails(params.recoveryDestination);
const nodeId = params.nodeId ? params.nodeId : '0.0.3';
const client = this.getHbarClient();
const balance = await this.getAccountBalance(params.rootAddress, client);
const fee = params.maxFee ? params.maxFee : '10000000'; // default fee to 1 hbar
const nativeBalance = sdk_1.Hbar.fromString(balance.hbars).toTinybars().toString();
const spendableAmount = new bignumber_js_1.BigNumber(nativeBalance).minus(fee);
let txBuilder;
if (!params.tokenId) {
if (spendableAmount.isZero() || spendableAmount.isNegative()) {
throw new Error(`Insufficient balance to recover, got balance: ${nativeBalance} fee: ${fee}`);
}
txBuilder = this.getBuilderFactory().getTransferBuilder();
txBuilder.send({ address: destinationAddress, amount: spendableAmount.toString() });
}
else {
if (spendableAmount.isNegative()) {
throw new Error(`Insufficient native balance to recover tokens, got native balance: ${nativeBalance} fee: ${fee}`);
}
const tokenBalance = balance.tokens.find((token) => token.tokenId === params.tokenId);
const token = Utils.getHederaTokenNameFromId(params.tokenId);
if (!token) {
throw new Error(`Unsupported token: ${params.tokenId}`);
}
if (!tokenBalance || new bignumber_js_1.BigNumber(tokenBalance.balance).isZero()) {
throw new Error(`Insufficient balance to recover token: ${params.tokenId} for account: ${params.rootAddress}`);
}
txBuilder = this.getBuilderFactory().getTokenTransferBuilder();
txBuilder.send({ address: destinationAddress, amount: tokenBalance.balance, tokenName: token.name });
}
txBuilder.node({ nodeId });
txBuilder.fee({ fee });
txBuilder.source({ address: params.rootAddress });
txBuilder.validDuration(180);
if (memoId) {
txBuilder.memo(memoId);
}
if (params.startTime) {
txBuilder.startTime(Utils.normalizeStarttime(params.startTime));
}
if (isUnsignedSweep) {
const tx = await txBuilder.build();
const txJson = tx.toJson();
return {
txHex: tx.toBroadcastFormat(),
coin: this.getChain(),
id: txJson.id,
startTime: txJson.startTime,
validDuration: txJson.validDuration,
nodeId: txJson.node,
memo: txJson.memo,
userKey: params.userKey,
backupKey: params.backupKey,
bitgoKey: params.bitgoKey,
maxFee: fee,
address: params.rootAddress,
recipients: txJson.instructionsData.params.recipients,
amount: txJson.amount,
json: txJson,
};
}
txBuilder.sign({ key: userPrv });
txBuilder.sign({ key: backUp });
const tx = await txBuilder.build();
return {
tx: tx.toBroadcastFormat(),
id: tx.toJson().id,
coin: this.getChain(),
startTime: tx.toJson().startTime,
nodeId: tx.toJson().node,
};
}
/**
* Explain a Hedera transaction from txHex
* @param params
*/
async explainTransaction(params) {
const txHex = params.txHex || (params.halfSigned && params.halfSigned.txHex);
if (!txHex) {
throw new Error('missing explain tx parameters');
}
const factory = this.getBuilderFactory();
const txBuilder = factory.from(txHex);
const tx = await txBuilder.build();
const txJson = tx.toJson();
let outputAmount = new bignumber_js_1.BigNumber(0);
const outputs = [];
// TODO(BG-24809): get the memo from the toJson
let memo = '';
if (params.memo) {
memo = params.memo.value;
}
switch (txJson.instructionsData.type) {
case 'cryptoTransfer':
const recipients = txJson.instructionsData.params.recipients || [];
recipients.forEach((recipient) => {
if (!recipient.tokenName) {
// token transfer doesn't change outputAmount
outputAmount = outputAmount.plus(recipient.amount);
}
outputs.push({
address: recipient.address,
amount: recipient.amount.toString(),
memo,
...(recipient.tokenName && {
tokenName: recipient.tokenName,
}),
});
});
break;
case 'tokenAssociate':
const tokens = txJson.instructionsData.params.tokenNames || [];
const accountId = txJson.instructionsData.params.accountId;
tokens.forEach((token) => {
outputs.push({
address: accountId,
amount: '0',
memo,
tokenName: token,
});
});
break;
default:
throw new Error('Transaction format outside of cryptoTransfer not supported for explanation.');
}
const displayOrder = [
'id',
'outputAmount',
'changeAmount',
'outputs',
'changeOutputs',
'fee',
'timestamp',
'expiration',
'memo',
];
return {
displayOrder,
id: txJson.id,
outputs,
outputAmount: outputAmount.toString(),
changeOutputs: [], // account based does not use change outputs
changeAmount: '0', // account base does not make change
fee: params.feeInfo?.fee || txJson.fee, // in the instance no feeInfo is passed in as a param, show the fee given by the txJSON
timestamp: txJson.startTime,
expiration: txJson.validDuration,
};
}
isStellarSeed(seed) {
return seedValidator_1.SeedValidator.isValidEd25519SeedForCoin(seed, statics_1.CoinFamily.XLM);
}
convertFromStellarSeed(seed) {
// assume this is a trust custodial seed if its a valid ed25519 prv
if (!this.isStellarSeed(seed) || seedValidator_1.SeedValidator.hasCompetingSeedFormats(seed)) {
return null;
}
if (seedValidator_1.SeedValidator.isValidEd25519SeedForCoin(seed, statics_1.CoinFamily.XLM)) {
const keyFromSeed = new lib_1.KeyPair({ seed: stellar.StrKey.decodeEd25519SecretSeed(seed) });
const keys = keyFromSeed.getKeys();
if (keys !== undefined && keys.prv) {
return keys.prv;
}
}
return null;
}
isValidPub(pub) {
return Utils.isValidPublicKey(pub);
}
supportsDeriveKeyWithSeed() {
return false;
}
/** inherited doc */
getDefaultMultisigType() {
return sdk_core_1.multisigTypes.onchain;
}
getTokenEnablementConfig() {
return {
requiresTokenEnablement: true,
supportsMultipleTokenEnablements: true,
};
}
getBuilderFactory() {
return new lib_1.TransactionBuilderFactory(statics_1.coins.get(this.getChain()));
}
getHbarClient() {
const client = this.bitgo.getEnv() === 'prod' ? sdk_1.Client.forMainnet() : sdk_1.Client.forTestnet();
return client;
}
async getAccountBalance(accountId, client) {
try {
const balance = await new sdk_1.AccountBalanceQuery().setAccountId(accountId).execute(client);
return balance.toJSON();
}
catch (e) {
throw new Error('Failed to get account balance, error: ' + e.message);
}
}
async broadcastTransaction({ serializedSignedTransaction, startTime, }) {
try {
const hbarTx = sdk_1.Transaction.fromBytes(Utils.toUint8Array(serializedSignedTransaction));
if (startTime) {
Utils.isValidTimeString(startTime);
while (!Utils.shouldBroadcastNow(startTime)) {
await Utils.sleep(1000);
}
}
return this.clientBroadcastTransaction(hbarTx);
}
catch (e) {
throw new Error('Failed to broadcast transaction, error: ' + e.message);
}
}
async clientBroadcastTransaction(hbarTx) {
const client = this.getHbarClient();
const transactionResponse = await hbarTx.execute(client);
const transactionReceipt = await transactionResponse.getReceipt(client);
return { txId: transactionResponse.transactionId.toString(), status: transactionReceipt.status.toString() };
}
/** @inheritDoc */
auditDecryptedKey({ prv, publicKey, multiSigType }) {
if (multiSigType === 'tss') {
throw new Error('Unsupported multiSigType');
}
let hbarKeyPair;
try {
hbarKeyPair = new lib_1.KeyPair({ prv });
}
catch (e) {
throw new Error(`Invalid private key: ${e.message}`);
}
const genPubKey = hbarKeyPair.getKeys().pub;
if (publicKey && publicKey !== genPubKey) {
throw new Error('Invalid public key');
}
}
}
exports.Hbar = Hbar;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGJhci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9oYmFyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBOztHQUVHO0FBQ0gsNENBQWdGO0FBQ2hGLDhDQXNCeUI7QUFDekIsK0NBQXlDO0FBQ3pDLHFEQUF1QztBQUN2QyxtREFBZ0Q7QUFDaEQsK0JBQXVGO0FBQ3ZGLG1EQUFxQztBQUNyQywwQ0FBNEI7QUFDNUIsd0NBTXdCO0FBQ3hCLDJDQUFrRDtBQXVGbEQsTUFBYSxJQUFLLFNBQVEsbUJBQVE7SUFHaEMsWUFBWSxLQUFnQixFQUFFLFdBQXVDO1FBQ25FLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUViLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLG9EQUFvRCxDQUFDLENBQUM7UUFDeEUsQ0FBQztRQUVELElBQUksQ0FBQyxZQUFZLEdBQUcsV0FBVyxDQUFDO0lBQ2xDLENBQUM7SUFFRCxRQUFRO1FBQ04sT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQztJQUNoQyxDQUFDO0lBRUQsU0FBUztRQUNQLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUM7SUFDbEMsQ0FBQztJQUVELFdBQVc7UUFDVCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDO0lBQ3BDLENBQUM7SUFFRCxhQUFhO1FBQ1gsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFFRCxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQWdCLEVBQUUsV0FBdUM7UUFDN0UsT0FBTyxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVEOzs7T0FHRztJQUNILHdCQUF3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SSxFQUFFLG1CQUFtQixDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUUsRUFBRSxNQUFNLEVBQUUsa0JBQWtCLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUM7SUFDOUcsQ0FBQztJQUVELGtCQUFrQjtJQUNsQixpQkFBaUIsQ0FBQyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUEyQjtRQUN6RSxJQUFJLFlBQVksS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLDBCQUEwQixDQUFDLENBQUM7UUFDOUMsQ0FBQztRQUVELElBQUksV0FBVyxDQUFDO1FBRWhCLElBQUksQ0FBQztZQUNILFdBQVcsR0FBRyxJQUFJLGFBQVcsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDekMsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDWCxNQUFNLElBQUksS0FBSyxDQUFDLHdCQUF3QixDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUN2RCxDQUFDO1FBQ0QsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsQ0FBQztRQUM1QyxJQUFJLFNBQVMsSUFBSSxTQUFTLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDekMsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQ3hDLENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUE1Z0JELG9CQTRnQkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBwcmV0dGllclxuICovXG5pbXBvcnQgeyBDb2luRmFtaWx5LCBCYXNlQ29pbiBhcyBTdGF0aWNzQmFzZUNvaW4sIGNvaW5zIH0gZnJvbSAnQGJpdGdvL3N0YXRpY3MnO1xuaW1wb3J0IHtcbiAgQmFzZUNvaW4sXG4gIEJpdEdvQmFzZSxcbiAgS2V5UGFpcixcbiAgUGFyc2VkVHJhbnNhY3Rpb24sXG4gIFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zLFxuICBTaWduZWRUcmFuc2FjdGlvbixcbiAgU2lnblRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgVmVyaWZ5QWRkcmVzc09wdGlvbnMgYXMgQmFzZVZlcmlmeUFkZHJlc3NPcHRpb25zLFxuICBWZXJpZnlUcmFuc2FjdGlvbk9wdGlvbnMsXG4gIFRyYW5zYWN0aW9uRmVlLFxuICBUcmFuc2FjdGlvblJlY2lwaWVudCBhcyBSZWNpcGllbnQsXG4gIFRyYW5zYWN0aW9uUHJlYnVpbGQgYXMgQmFzZVRyYW5zYWN0aW9uUHJlYnVpbGQsXG4gIFRyYW5zYWN0aW9uRXhwbGFuYXRpb24sXG4gIE1lbW8sXG4gIFRva2VuRW5hYmxlbWVudENvbmZpZyxcbiAgQmFzZUJyb2FkY2FzdFRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgQmFzZUJyb2FkY2FzdFRyYW5zYWN0aW9uUmVzdWx0LFxuICBOb3RTdXBwb3J0ZWQsXG4gIE11bHRpc2lnVHlwZSxcbiAgbXVsdGlzaWdUeXBlcyxcbiAgQXVkaXREZWNyeXB0ZWRLZXlQYXJhbXMsXG59IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBCaWdOdW1iZXIgfSBmcm9tICdiaWdudW1iZXIuanMnO1xuaW1wb3J0ICogYXMgc3RlbGxhciBmcm9tICdzdGVsbGFyLXNkayc7XG5pbXBvcnQgeyBTZWVkVmFsaWRhdG9yIH0gZnJvbSAnLi9zZWVkVmFsaWRhdG9yJztcbmltcG9ydCB7IEtleVBhaXIgYXMgSGJhcktleVBhaXIsIFRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnksIFRyYW5zYWN0aW9uIH0gZnJvbSAnLi9saWInO1xuaW1wb3J0ICogYXMgVXRpbHMgZnJvbSAnLi9saWIvdXRpbHMnO1xuaW1wb3J0ICogYXMgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHtcbiAgQ2xpZW50LFxuICBUcmFuc2FjdGlvbiBhcyBIYmFyVHJhbnNhY3Rpb24sXG4gIEFjY291bnRCYWxhbmNlUXVlcnksXG4gIEFjY291bnRCYWxhbmNlSnNvbixcbiAgSGJhciBhcyBIYmFyVW5pdCxcbn0gZnJvbSAnQGhhc2hncmFwaC9zZGsnO1xuaW1wb3J0IHsgUFVCTElDX0tFWV9QUkVGSVggfSBmcm9tICcuL2xpYi9rZXlQYWlyJztcbmV4cG9ydCBpbnRlcmZhY2UgSGJhclNpZ25UcmFuc2FjdGlvbk9wdGlvbnMgZXh0ZW5kcyBTaWduVHJhbnNhY3Rpb25PcHRpb25zIHtcbiAgdHhQcmVidWlsZDogVHJhbnNhY3Rpb25QcmVidWlsZDtcbiAgcHJ2OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHhJbmZvIHtcbiAgcmVjaXBpZW50czogUmVjaXBpZW50W107XG4gIGZyb206IHN0cmluZztcbiAgdHhpZDogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRyYW5zYWN0aW9uUHJlYnVpbGQgZXh0ZW5kcyBCYXNlVHJhbnNhY3Rpb25QcmVidWlsZCB7XG4gIHR4SGV4OiBzdHJpbmc7XG4gIHR4SW5mbzogVHhJbmZvO1xuICBmZWVJbmZvOiBUcmFuc2FjdGlvbkZlZTtcbiAgc291cmNlOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9ucyB7XG4gIHR4SGV4Pzogc3RyaW5nO1xuICBoYWxmU2lnbmVkPzoge1xuICAgIHR4SGV4OiBzdHJpbmc7XG4gIH07XG4gIGZlZUluZm8/OiBUcmFuc2FjdGlvbkZlZTtcbiAgLy8gVE9ETyhCRy0yNDgwOSk6IGdldCB0aGUgbWVtbyBmcm9tIHRoZSB0b0pzb25cbiAgbWVtbz86IHtcbiAgICB0eXBlOiBzdHJpbmc7XG4gICAgdmFsdWU6IHN0cmluZztcbiAgfTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBIYmFyVmVyaWZ5VHJhbnNhY3Rpb25PcHRpb25zIGV4dGVuZHMgVmVyaWZ5VHJhbnNhY3Rpb25PcHRpb25zIHtcbiAgdHhQcmVidWlsZDogVHJhbnNhY3Rpb25QcmVidWlsZDtcbiAgbWVtbz86IE1lbW87XG59XG5cbmludGVyZmFjZSBWZXJpZnlBZGRyZXNzT3B0aW9ucyBleHRlbmRzIEJhc2VWZXJpZnlBZGRyZXNzT3B0aW9ucyB7XG4gIGJhc2VBZGRyZXNzOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVjb3ZlcnlPcHRpb25zIHtcbiAgYmFja3VwS2V5OiBzdHJpbmc7XG4gIHVzZXJLZXk6IHN0cmluZztcbiAgcm9vdEFkZHJlc3M6IHN0cmluZztcbiAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogc3RyaW5nO1xuICBiaXRnb0tleT86IHN0cmluZztcbiAgd2FsbGV0UGFzc3BocmFzZT86IHN0cmluZztcbiAgbWF4RmVlPzogc3RyaW5nO1xuICBub2RlSWQ/OiBzdHJpbmc7XG4gIHN0YXJ0VGltZT86IHN0cmluZztcbiAgdG9rZW5JZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZWNvdmVyeUluZm8ge1xuICBpZDogc3RyaW5nO1xuICB0eDogc3RyaW5nO1xuICBjb2luOiBzdHJpbmc7XG4gIHN0YXJ0VGltZTogc3RyaW5nO1xuICBub2RlSWQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPZmZsaW5lVmF1bHRUeEluZm8ge1xuICB0eEhleDogc3RyaW5nO1xuICB1c2VyS2V5OiBzdHJpbmc7XG4gIGJhY2t1cEtleTogc3RyaW5nO1xuICBiaXRnb0tleT86IHN0cmluZztcbiAgYWRkcmVzczogc3RyaW5nO1xuICBjb2luOiBzdHJpbmc7XG4gIG1heEZlZTogc3RyaW5nO1xuICByZWNpcGllbnRzOiBSZWNpcGllbnRbXTtcbiAgYW1vdW50OiBzdHJpbmc7XG4gIHN0YXJ0VGltZTogc3RyaW5nO1xuICB2YWxpZER1cmF0aW9uOiBzdHJpbmc7XG4gIG5vZGVJZDogc3RyaW5nO1xuICBtZW1vOiBzdHJpbmc7XG4gIGpzb24/OiBhbnk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQnJvYWRjYXN0VHJhbnNhY3Rpb25PcHRpb25zIGV4dGVuZHMgQmFzZUJyb2FkY2FzdFRyYW5zYWN0aW9uT3B0aW9ucyB7XG4gIHN0YXJ0VGltZT86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCcm9hZGNhc3RUcmFuc2FjdGlvblJlc3VsdCBleHRlbmRzIEJhc2VCcm9hZGNhc3RUcmFuc2FjdGlvblJlc3VsdCB7XG4gIHN0YXR1cz86IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIEhiYXIgZXh0ZW5kcyBCYXNlQ29pbiB7XG4gIHByb3RlY3RlZCByZWFkb25seSBfc3RhdGljc0NvaW46IFJlYWRvbmx5PFN0YXRpY3NCYXNlQ29pbj47XG5cbiAgY29uc3RydWN0b3IoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KSB7XG4gICAgc3VwZXIoYml0Z28pO1xuXG4gICAgaWYgKCFzdGF0aWNzQ29pbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHJlcXVpcmVkIGNvbnN0cnVjdG9yIHBhcmFtZXRlciBzdGF0aWNzQ29pbicpO1xuICAgIH1cblxuICAgIHRoaXMuX3N0YXRpY3NDb2luID0gc3RhdGljc0NvaW47XG4gIH1cblxuICBnZXRDaGFpbigpIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4ubmFtZTtcbiAgfVxuXG4gIGdldEZhbWlseSgpOiBDb2luRmFtaWx5IHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4uZmFtaWx5O1xuICB9XG5cbiAgZ2V0RnVsbE5hbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3N0YXRpY3NDb2luLmZ1bGxOYW1lO1xuICB9XG5cbiAgZ2V0QmFzZUZhY3RvcigpIHtcbiAgICByZXR1cm4gTWF0aC5wb3coMTAsIHRoaXMuX3N0YXRpY3NDb2luLmRlY2ltYWxQbGFjZXMpO1xuICB9XG5cbiAgc3RhdGljIGNyZWF0ZUluc3RhbmNlKGJpdGdvOiBCaXRHb0Jhc2UsIHN0YXRpY3NDb2luPzogUmVhZG9ubHk8U3RhdGljc0Jhc2VDb2luPik6IEJhc2VDb2luIHtcbiAgICByZXR1cm4gbmV3IEhiYXIoYml0Z28sIHN0YXRpY3NDb2luKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGbGFnIGZvciBzZW5kaW5nIHZhbHVlIG9mIDBcbiAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgb2theSB0byBzZW5kIDAgdmFsdWUsIGZhbHNlIG90aGVyd2lzZVxuICAgKi9cbiAgdmFsdWVsZXNzVHJhbnNmZXJBbGxvd2VkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgdGhpcyBpcyBhIHZhbGlkIGJhc2U1OCBvciBoZXggYWRkcmVzc1xuICAgKiBAcGFyYW0gYWRkcmVzc1xuICAgKi9cbiAgaXNWYWxpZEFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBVdGlscy5pc1ZhbGlkQWRkcmVzc1dpdGhQYXltZW50SWQoYWRkcmVzcyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBpbmhlcml0ZG9jICovXG4gIGRlcml2ZUtleVdpdGhTZWVkKCk6IHsgZGVyaXZhdGlvblBhdGg6IHN0cmluZzsga2V5OiBzdHJpbmcgfSB7XG4gICAgdGhyb3cgbmV3IE5vdFN1cHBvcnRlZCgnbWV0aG9kIGRlcml2ZUtleVdpdGhTZWVkIG5vdCBzdXBwb3J0ZWQgZm9yIGVkZHNhIGN1cnZlJyk7XG4gIH1cblxuICAvKiogaW5oZXJpdGRvYyAqL1xuICBnZW5lcmF0ZUtleVBhaXIoc2VlZD86IEJ1ZmZlcik6IEtleVBhaXIge1xuICAgIGNvbnN0IGtleVBhaXIgPSBzZWVkID8gbmV3IEhiYXJLZXlQYWlyKHsgc2VlZCB9KSA6IG5ldyBIYmFyS2V5UGFpcigpO1xuICAgIGNvbnN0IGtleXMgPSBrZXlQYWlyLmdldEtleXMoKTtcblxuICAgIGlmICgha2V5cy5wcnYpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignS2V5cGFpciBnZW5lcmF0aW9uIGZhaWxlZCB0byBnZW5lcmF0ZSBhIHBydicpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBwdWI6IGtleXMucHViLFxuICAgICAgcHJ2OiBrZXlzLnBydixcbiAgICB9O1xuICB9XG5cbiAgLyoqIGluaGVyaXRkb2MgKi9cbiAgZ2VuZXJhdGVSb290S2V5UGFpcihzZWVkPzogQnVmZmVyKTogS2V5UGFpciB7XG4gICAgY29uc3Qga2V5UGFpciA9IHNlZWQgPyBuZXcgSGJhcktleVBhaXIoeyBzZWVkIH0pIDogbmV3IEhiYXJLZXlQYWlyKCk7XG4gICAgY29uc3Qga2V5cyA9IGtleVBhaXIuZ2V0S2V5cyh0cnVlKTtcbiAgICBpZiAoIWtleXMucHJ2KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgcHJ2IGluIGtleSBnZW5lcmF0aW9uLicpO1xuICAgIH1cbiAgICByZXR1cm4geyBwcnY6IGtleXMucHJ2ICsga2V5cy5wdWIsIHB1Yjoga2V5cy5wdWIgfTtcbiAgfVxuXG4gIGFzeW5jIHBhcnNlVHJhbnNhY3Rpb24ocGFyYW1zOiBQYXJzZVRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8UGFyc2VkVHJhbnNhY3Rpb24+IHtcbiAgICByZXR1cm4ge307XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgYWRkcmVzcyBpcyB2YWxpZCwgdGhlbiBtYWtlIHN1cmUgaXQgbWF0Y2hlcyB0aGUgYmFzZSBhZGRyZXNzLlxuICAgKlxuICAgKiBAcGFyYW0ge1ZlcmlmeUFkZHJlc3NPcHRpb25zfSBwYXJhbXNcbiAgICogQHBhcmFtIHtTdHJpbmd9IHBhcmFtcy5hZGRyZXNzIC0gdGhlIGFkZHJlc3MgdG8gdmVyaWZ5XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwYXJhbXMuYmFzZUFkZHJlc3MgLSB0aGUgYmFzZSBhZGRyZXNzIGZyb20gdGhlIHdhbGxldFxuICAgKi9cbiAgYXN5bmMgaXNXYWxsZXRBZGRyZXNzKHBhcmFtczogVmVyaWZ5QWRkcmVzc09wdGlvbnMpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCB7IGFkZHJlc3MsIGJhc2VBZGRyZXNzIH0gPSBwYXJhbXM7XG4gICAgcmV0dXJuIFV0aWxzLmlzU2FtZUJhc2VBZGRyZXNzKGFkZHJlc3MsIGJhc2VBZGRyZXNzKTtcbiAgfVxuXG4gIGFzeW5jIHZlcmlmeVRyYW5zYWN0aW9uKHBhcmFtczogSGJhclZlcmlmeVRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIGFzc2V0IG5hbWUgdG8gdHJhbnNmZXIgYW1vdW50IG1hcFxuICAgIGNvbnN0IGNvaW5Db25maWcgPSBjb2lucy5nZXQodGhpcy5nZXRDaGFpbigpKTtcbiAgICBjb25zdCB7IHR4UGFyYW1zOiB0eFBhcmFtcywgdHhQcmVidWlsZDogdHhQcmVidWlsZCwgbWVtbzogbWVtbyB9ID0gcGFyYW1zO1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gbmV3IFRyYW5zYWN0aW9uKGNvaW5Db25maWcpO1xuICAgIGlmICghdHhQcmVidWlsZC50eEhleCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHJlcXVpcmVkIHR4IHByZWJ1aWxkIHByb3BlcnR5IHR4SGV4Jyk7XG4gICAgfVxuXG4gICAgdHJhbnNhY3Rpb24uZnJvbVJhd1RyYW5zYWN0aW9uKHR4UHJlYnVpbGQudHhIZXgpO1xuICAgIGNvbnN0IGV4cGxhaW5UeFBhcmFtczogRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9ucyA9IHtcbiAgICAgIHR4SGV4OiB0eFByZWJ1aWxkLnR4SGV4LFxuICAgICAgZmVlSW5mbzogdHhQcmVidWlsZC5mZWVJbmZvLFxuICAgICAgbWVtbzogbWVtbyxcbiAgICB9O1xuICAgIGNvbnN0IGV4cGxhaW5lZFR4ID0gYXdhaXQgdGhpcy5leHBsYWluVHJhbnNhY3Rpb24oZXhwbGFpblR4UGFyYW1zKTtcblxuICAgIGlmICghdHhQYXJhbXMucmVjaXBpZW50cykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHJlcXVpcmVkIHR4IHBhcmFtcyBwcm9wZXJ0eSByZWNpcGllbnRzJyk7XG4gICAgfVxuXG4gICAgLy8gZm9yIGVuYWJsZXRva2VuLCByZWNpcGllbnQgb3V0cHV0IGFtb3VudCBpcyAwXG4gICAgY29uc3QgcmVjaXBpZW50cyA9IHR4UGFyYW1zLnJlY2lwaWVudHMubWFwKChyZWNpcGllbnQpID0+ICh7XG4gICAgICAuLi5yZWNpcGllbnQsXG4gICAgICBhbW91bnQ6IHR4UGFyYW1zLnR5cGUgPT09ICdlbmFibGV0b2tlbicgPyAnMCcgOiByZWNpcGllbnQuYW1vdW50LFxuICAgICAgYWRkcmVzczogVXRpbHMuZ2V0QWRkcmVzc0RldGFpbHMocmVjaXBpZW50LmFkZHJlc3MpLmFkZHJlc3MsXG4gICAgfSkpO1xuICAgIGlmIChjb2luQ29uZmlnLmlzVG9rZW4pIHtcbiAgICAgIHJlY2lwaWVudHMuZm9yRWFjaCgocmVjaXBpZW50KSA9PiB7XG4gICAgICAgIGlmIChyZWNpcGllbnQudG9rZW5OYW1lICE9PSB1bmRlZmluZWQgJiYgcmVjaXBpZW50LnRva2VuTmFtZSAhPT0gY29pbkNvbmZpZy5uYW1lKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbmNvcnJlY3QgdG9rZW4gbmFtZSBzcGVjaWZpZWQgaW4gcmVjaXBpZW50cycpO1xuICAgICAgICB9XG4gICAgICAgIHJlY2lwaWVudC50b2tlbk5hbWUgPSBjb2luQ29uZmlnLm5hbWU7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyB2ZXJpZnkgcmVjaXBpZW50cyBmcm9tIHBhcmFtcyBhbmQgZXhwbGFpbmVkVHhcbiAgICBjb25zdCBmaWx0ZXJlZFJlY2lwaWVudHMgPSByZWNpcGllbnRzPy5tYXAoKHJlY2lwaWVudCkgPT4gXy5waWNrKHJlY2lwaWVudCwgWydhZGRyZXNzJywgJ2Ftb3VudCcsICd0b2tlbk5hbWUnXSkpO1xuICAgIGNvbnN0IGZpbHRlcmVkT3V0cHV0cyA9IGV4cGxhaW5lZFR4Lm91dHB1dHMubWFwKChvdXRwdXQpID0+IF8ucGljayhvdXRwdXQsIFsnYWRkcmVzcycsICdhbW91bnQnLCAndG9rZW5OYW1lJ10pKTtcblxuICAgIGlmICghXy5pc0VxdWFsKGZpbHRlcmVkT3V0cHV0cywgZmlsdGVyZWRSZWNpcGllbnRzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUeCBvdXRwdXRzIGRvZXMgbm90IG1hdGNoIHdpdGggZXhwZWN0ZWQgdHhQYXJhbXMgcmVjaXBpZW50cycpO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEFzc2VtYmxlIGtleWNoYWluIGFuZCBoYWxmLXNpZ24gcHJlYnVpbHQgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKiBAcGFyYW0gcGFyYW1zLnR4UHJlYnVpbGQge09iamVjdH0gcHJlYnVpbGQgb2JqZWN0IHJldHVybmVkIGJ5IHBsYXRmb3JtXG4gICAqIEBwYXJhbSBwYXJhbXMucHJ2IHtTdHJpbmd9IHVzZXIgcHJ2XG4gICAqIEByZXR1cm5zIFByb21pc2U8U2lnbmVkVHJhbnNhY3Rpb24+XG4gICAqL1xuICBhc3luYyBzaWduVHJhbnNhY3Rpb24ocGFyYW1zOiBIYmFyU2lnblRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8U2lnbmVkVHJhbnNhY3Rpb24+IHtcbiAgICBjb25zdCBmYWN0b3J5ID0gdGhpcy5nZXRCdWlsZGVyRmFjdG9yeSgpO1xuICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZnJvbShwYXJhbXMudHhQcmVidWlsZC50eEhleCk7XG4gICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IHBhcmFtcy5wcnYgfSk7XG5cbiAgICBjb25zdCB0cmFuc2FjdGlvbiA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuXG4gICAgaWYgKCF0cmFuc2FjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG1lc3NhZ2VkIHBhc3NlZCB0byBzaWduTWVzc2FnZScpO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc3BvbnNlID0ge1xuICAgICAgdHhIZXg6IHRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCksXG4gICAgfTtcbiAgICByZXR1cm4gdHJhbnNhY3Rpb24uc2lnbmF0dXJlLmxlbmd0aCA+PSAyID8gcmVzcG9uc2UgOiB7IGhhbGZTaWduZWQ6IHJlc3BvbnNlIH07XG4gIH1cblxuICAvKipcbiAgICogU2lnbiBtZXNzYWdlIHdpdGggcHJpdmF0ZSBrZXlcbiAgICpcbiAgICogQHBhcmFtIGtleVxuICAgKiBAcGFyYW0gbWVzc2FnZVxuICAgKiBAcmV0dXJuIHtCdWZmZXJ9IEEgc2lnbmF0dXJlIG92ZXIgdGhlIGdpdmVuIG1lc3NhZ2UgdXNpbmcgdGhlIGdpdmVuIGtleVxuICAgKi9cbiAgYXN5bmMgc2lnbk1lc3NhZ2Uoa2V5OiBLZXlQYWlyLCBtZXNzYWdlOiBzdHJpbmcgfCBCdWZmZXIpOiBQcm9taXNlPEJ1ZmZlcj4ge1xuICAgIGNvbnN0IG1zZyA9IEJ1ZmZlci5pc0J1ZmZlcihtZXNzYWdlKSA/IG1lc3NhZ2UudG9TdHJpbmcoJ3V0ZjgnKSA6IG1lc3NhZ2U7XG4gICAgLy8gcmVjb25zdGl0dXRlIGtleXMgYW5kIHNpZ25cbiAgICByZXR1cm4gQnVmZmVyLmZyb20obmV3IEhiYXJLZXlQYWlyKHsgcHJ2OiBrZXkucHJ2IH0pLnNpZ25NZXNzYWdlKG1zZykpO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyBhIGZ1bmRzIHJlY292ZXJ5IHRyYW5zYWN0aW9uIHdpdGhvdXQgQml0R28uXG4gICAqIFdlIG5lZWQgdG8gZG8gdGhyZWUgcXVlcmllcyBkdXJpbmcgdGhpczpcbiAgICogMSkgTm9kZSBxdWVyeSAtIGhvdyBtdWNoIG1vbmV5IGlzIGluIHRoZSBhY2NvdW50XG4gICAqIDIpIEJ1aWxkIHRyYW5zYWN0aW9uIC0gYnVpbGQgb3VyIHRyYW5zYWN0aW9uIGZvciB0aGUgYW1vdW50XG4gICAqIDMpIFNlbmQgc2lnbmVkIGJ1aWxkIC0gc2VuZCBvdXIgc2lnbmVkIGJ1aWxkIHRvIGEgcHVibGljIG5vZGVcbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKi9cbiAgcHVibGljIGFzeW5jIHJlY292ZXIocGFyYW1zOiBSZWNvdmVyeU9wdGlvbnMpOiBQcm9taXNlPFJlY292ZXJ5SW5mbyB8IE9mZmxpbmVWYXVsdFR4SW5mbz4ge1xuICAgIGNvbnN0IGlzVW5zaWduZWRTd2VlcCA9XG4gICAgICAocGFyYW1zLmJhY2t1cEtleS5zdGFydHNXaXRoKFBVQkxJQ19LRVlfUFJFRklYKSAmJiBwYXJhbXMudXNlcktleS5zdGFydHNXaXRoKFBVQkxJQ19LRVlfUFJFRklYKSkgfHxcbiAgICAgIChVdGlscy5pc1ZhbGlkUHVibGljS2V5KHBhcmFtcy51c2VyS2V5KSAmJiBVdGlscy5pc1ZhbGlkUHVibGljS2V5KHBhcmFtcy5iYWNrdXBLZXkpKTtcblxuICAgIC8vIFZhbGlkYXRlIHRoZSByb290IGFkZHJlc3NcbiAgICBpZiAoIXRoaXMuaXNWYWxpZEFkZHJlc3MocGFyYW1zLnJvb3RBZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHJvb3RBZGRyZXNzLCBnb3Q6ICcgKyBwYXJhbXMucm9vdEFkZHJlc3MpO1xuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIHRoZSBkZXN0aW5hdGlvbiBhZGRyZXNzXG4gICAgaWYgKCF0aGlzLmlzVmFsaWRBZGRyZXNzKHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHJlY292ZXJ5RGVzdGluYXRpb24sIGdvdDogJyArIHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uKTtcbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBub2RlSWRcbiAgICBpZiAocGFyYW1zLm5vZGVJZCAmJiAhVXRpbHMuaXNWYWxpZEFkZHJlc3MocGFyYW1zLm5vZGVJZCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBub2RlSWQsIGdvdDogJyArIHBhcmFtcy5ub2RlSWQpO1xuICAgIH1cblxuICAgIC8vIHZhbGlkYXRlIGZlZVxuICAgIGlmIChwYXJhbXMubWF4RmVlICYmICFVdGlscy5pc1ZhbGlkQW1vdW50KHBhcmFtcy5tYXhGZWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgbWF4RmVlLCBnb3Q6ICcgKyBwYXJhbXMubWF4RmVlKTtcbiAgICB9XG5cbiAgICAvLyB2YWxpZGF0ZSBzdGFydFRpbWVcblxuICAgIGlmIChwYXJhbXMuc3RhcnRUaW1lKSB7XG4gICAgICBVdGlscy52YWxpZGF0ZVN0YXJ0VGltZShwYXJhbXMuc3RhcnRUaW1lKTtcbiAgICB9XG5cbiAgICBpZiAoaXNVbnNpZ25lZFN3ZWVwICYmICFwYXJhbXMuc3RhcnRUaW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3N0YXJ0IHRpbWUgaXMgcmVxdWlyZWQgZm9yIHVuc2lnbmVkIHN3ZWVwJyk7XG4gICAgfVxuXG4gICAgaWYgKCFpc1Vuc2lnbmVkU3dlZXAgJiYgIXBhcmFtcy53YWxsZXRQYXNzcGhyYXNlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3dhbGxldFBhc3NwaHJhc2UgaXMgcmVxdWlyZWQgZm9yIG5vbi1iaXRnbyByZWNvdmVyeScpO1xuICAgIH1cblxuICAgIGxldCB1c2VyUHJ2OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgbGV0IGJhY2tVcDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgIGlmICghaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICB0cnkge1xuICAgICAgICB1c2VyUHJ2ID0gdGhpcy5iaXRnby5kZWNyeXB0KHsgaW5wdXQ6IHBhcmFtcy51c2VyS2V5LCBwYXNzd29yZDogcGFyYW1zLndhbGxldFBhc3NwaHJhc2UgfSk7XG4gICAgICAgIGJhY2tVcCA9IHRoaXMuYml0Z28uZGVjcnlwdCh7IGlucHV0OiBwYXJhbXMuYmFja3VwS2V5LCBwYXNzd29yZDogcGFyYW1zLndhbGxldFBhc3NwaHJhc2UgfSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAndW5hYmxlIHRvIGRlY3J5cHQgdXNlcktleSBvciBiYWNrdXBLZXkgd2l0aCB0aGUgd2FsbGV0UGFzc3BocmFzZSBwcm92aWRlZCwgZ290IGVycm9yOiAnICsgZS5tZXNzYWdlXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gdmFsaWRhdGUgdXNlcktleSBmb3IgdW5zaWduZWQgc3dlZXBcbiAgICBpZiAoaXNVbnNpZ25lZFN3ZWVwICYmICFVdGlscy5pc1ZhbGlkUHVibGljS2V5KHBhcmFtcy51c2VyS2V5KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHVzZXJLZXksIGdvdDogJyArIHBhcmFtcy51c2VyS2V5KTtcbiAgICB9XG5cbiAgICAvLyB2YWxpZGF0ZSBiYWNrdXBLZXkgZm9yIHVuc2lnbmVkIHN3ZWVwXG4gICAgaWYgKGlzVW5zaWduZWRTd2VlcCAmJiAhVXRpbHMuaXNWYWxpZFB1YmxpY0tleShwYXJhbXMuYmFja3VwS2V5KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGJhY2t1cEtleSwgZ290OiAnICsgcGFyYW1zLmJhY2t1cEtleSk7XG4gICAgfVxuXG4gICAgY29uc3QgeyBhZGRyZXNzOiBkZXN0aW5hdGlvbkFkZHJlc3MsIG1lbW9JZCB9ID0gVXRpbHMuZ2V0QWRkcmVzc0RldGFpbHMocGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24pO1xuICAgIGNvbnN0IG5vZGVJZCA9IHBhcmFtcy5ub2RlSWQgPyBwYXJhbXMubm9kZUlkIDogJzAuMC4zJztcbiAgICBjb25zdCBjbGllbnQgPSB0aGlzLmdldEhiYXJDbGllbnQoKTtcbiAgICBjb25zdCBiYWxhbmNlID0gYXdhaXQgdGhpcy5nZXRBY2NvdW50QmFsYW5jZShwYXJhbXMucm9vdEFkZHJlc3MsIGNsaWVudCk7XG4gICAgY29uc3QgZmVlID0gcGFyYW1zLm1heEZlZSA/IHBhcmFtcy5tYXhGZWUgOiAnMTAwMDAwMDAnOyAvLyBkZWZhdWx0IGZlZSB0byAxIGhiYXJcbiAgICBjb25zdCBuYXRpdmVCYWxhbmNlID0gSGJhclVuaXQuZnJvbVN0cmluZyhiYWxhbmNlLmhiYXJzKS50b1RpbnliYXJzKCkudG9TdHJpbmcoKTtcbiAgICBjb25zdCBzcGVuZGFibGVBbW91bnQgPSBuZXcgQmlnTnVtYmVyKG5hdGl2ZUJhbGFuY2UpLm1pbnVzKGZlZSk7XG5cbiAgICBsZXQgdHhCdWlsZGVyO1xuICAgIGlmICghcGFyYW1zLnRva2VuSWQpIHtcbiAgICAgIGlmIChzcGVuZGFibGVBbW91bnQuaXNaZXJvKCkgfHwgc3BlbmRhYmxlQW1vdW50LmlzTmVnYXRpdmUoKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEluc3VmZmljaWVudCBiYWxhbmNlIHRvIHJlY292ZXIsIGdvdCBiYWxhbmNlOiAke25hdGl2ZUJhbGFuY2V9IGZlZTogJHtmZWV9YCk7XG4gICAgICB9XG4gICAgICB0eEJ1aWxkZXIgPSB0aGlzLmdldEJ1aWxkZXJGYWN0b3J5KCkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZCh7IGFkZHJlc3M6IGRlc3RpbmF0aW9uQWRkcmVzcywgYW1vdW50OiBzcGVuZGFibGVBbW91bnQudG9TdHJpbmcoKSB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHNwZW5kYWJsZUFtb3VudC5pc05lZ2F0aXZlKCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBJbnN1ZmZpY2llbnQgbmF0aXZlIGJhbGFuY2UgdG8gcmVjb3ZlciB0b2tlbnMsIGdvdCBuYXRpdmUgYmFsYW5jZTogJHtuYXRpdmVCYWxhbmNlfSBmZWU6ICR7ZmVlfWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHRva2VuQmFsYW5jZSA9IGJhbGFuY2UudG9rZW5zLmZpbmQoKHRva2VuKSA9PiB0b2tlbi50b2tlbklkID09PSBwYXJhbXMudG9rZW5JZCk7XG4gICAgICBjb25zdCB0b2tlbiA9IFV0aWxzLmdldEhlZGVyYVRva2VuTmFtZUZyb21JZChwYXJhbXMudG9rZW5JZCk7XG4gICAgICBpZiAoIXRva2VuKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgdG9rZW46ICR7cGFyYW1zLnRva2VuSWR9YCk7XG4gICAgICB9XG4gICAgICBpZiAoIXRva2VuQmFsYW5jZSB8fCBuZXcgQmlnTnVtYmVyKHRva2VuQmFsYW5jZS5iYWxhbmNlKS5pc1plcm8oKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEluc3VmZmljaWVudCBiYWxhbmNlIHRvIHJlY292ZXIgdG9rZW46ICR7cGFyYW1zLnRva2VuSWR9IGZvciBhY2NvdW50OiAke3BhcmFtcy5yb290QWRkcmVzc31gKTtcbiAgICAgIH1cbiAgICAgIHR4QnVpbGRlciA9IHRoaXMuZ2V0QnVpbGRlckZhY3RvcnkoKS5nZXRUb2tlblRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQoeyBhZGRyZXNzOiBkZXN0aW5hdGlvbkFkZHJlc3MsIGFtb3VudDogdG9rZW5CYWxhbmNlLmJhbGFuY2UsIHRva2VuTmFtZTogdG9rZW4ubmFtZSB9KTtcbiAgICB9XG5cbiAgICB0eEJ1aWxkZXIubm9kZSh7IG5vZGVJZCB9KTtcbiAgICB0eEJ1aWxkZXIuZmVlKHsgZmVlIH0pO1xuICAgIHR4QnVpbGRlci5zb3VyY2UoeyBhZGRyZXNzOiBwYXJhbXMucm9vdEFkZHJlc3MgfSk7XG4gICAgdHhCdWlsZGVyLnZhbGlkRHVyYXRpb24oMTgwKTtcbiAgICBpZiAobWVtb0lkKSB7XG4gICAgICB0eEJ1aWxkZXIubWVtbyhtZW1vSWQpO1xuICAgIH1cblxuICAgIGlmIChwYXJhbXMuc3RhcnRUaW1lKSB7XG4gICAgICB0eEJ1aWxkZXIuc3RhcnRUaW1lKFV0aWxzLm5vcm1hbGl6ZVN0YXJ0dGltZShwYXJhbXMuc3RhcnRUaW1lKSk7XG4gICAgfVxuICAgIGlmIChpc1Vuc2lnbmVkU3dlZXApIHtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR4SGV4OiB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpLFxuICAgICAgICBjb2luOiB0aGlzLmdldENoYWluKCksXG4gICAgICAgIGlkOiB0eEpzb24uaWQsXG4gICAgICAgIHN0YXJ0VGltZTogdHhKc29uLnN0YXJ0VGltZSxcbiAgICAgICAgdmFsaWREdXJhdGlvbjogdHhKc29uLnZhbGlkRHVyYXRpb24sXG4gICAgICAgIG5vZGVJZDogdHhKc29uLm5vZGUsXG4gICAgICAgIG1lbW86IHR4SnNvbi5tZW1vLFxuICAgICAgICB1c2VyS2V5OiBwYXJhbXMudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBwYXJhbXMuYmFja3VwS2V5LFxuICAgICAgICBiaXRnb0tleTogcGFyYW1zLmJpdGdvS2V5LFxuICAgICAgICBtYXhGZWU6IGZlZSxcbiAgICAgICAgYWRkcmVzczogcGFyYW1zLnJvb3RBZGRyZXNzLFxuICAgICAgICByZWNpcGllbnRzOiB0eEpzb24uaW5zdHJ1Y3Rpb25zRGF0YS5wYXJhbXMucmVjaXBpZW50cyxcbiAgICAgICAgYW1vdW50OiB0eEpzb24uYW1vdW50LFxuICAgICAgICBqc29uOiB0eEpzb24sXG4gICAgICB9O1xuICAgIH1cblxuICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiB1c2VyUHJ2IH0pO1xuICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBiYWNrVXAgfSk7XG5cbiAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHR4OiB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpLFxuICAgICAgaWQ6IHR4LnRvSnNvbigpLmlkLFxuICAgICAgY29pbjogdGhpcy5nZXRDaGFpbigpLFxuICAgICAgc3RhcnRUaW1lOiB0eC50b0pzb24oKS5zdGFydFRpbWUsXG4gICAgICBub2RlSWQ6IHR4LnRvSnNvbigpLm5vZGUsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeHBsYWluIGEgSGVkZXJhIHRyYW5zYWN0aW9uIGZyb20gdHhIZXhcbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKi9cbiAgYXN5bmMgZXhwbGFpblRyYW5zYWN0aW9uKHBhcmFtczogRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8VHJhbnNhY3Rpb25FeHBsYW5hdGlvbj4ge1xuICAgIGNvbnN0IHR4SGV4ID0gcGFyYW1zLnR4SGV4IHx8IChwYXJhbXMuaGFsZlNpZ25lZCAmJiBwYXJhbXMuaGFsZlNpZ25lZC50eEhleCk7XG4gICAgaWYgKCF0eEhleCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIGV4cGxhaW4gdHggcGFyYW1ldGVycycpO1xuICAgIH1cblxuICAgIGNvbnN0IGZhY3RvcnkgPSB0aGlzLmdldEJ1aWxkZXJGYWN0b3J5KCk7XG4gICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5mcm9tKHR4SGV4KTtcbiAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgIGNvbnN0IHR4SnNvbiA9IHR4LnRvSnNvbigpO1xuXG4gICAgbGV0IG91dHB1dEFtb3VudCA9IG5ldyBCaWdOdW1iZXIoMCk7XG4gICAgY29uc3Qgb3V0cHV0czogeyBhZGRyZXNzOiBzdHJpbmc7IGFtb3VudDogc3RyaW5nOyBtZW1vOiBzdHJpbmc7IHRva2VuTmFtZT86IHN0cmluZyB9W10gPSBbXTtcbiAgICAvLyBUT0RPKEJHLTI0ODA5KTogZ2V0IHRoZSBtZW1vIGZyb20gdGhlIHRvSnNvblxuICAgIGxldCBtZW1vID0gJyc7XG4gICAgaWYgKHBhcmFtcy5tZW1vKSB7XG4gICAgICBtZW1vID0gcGFyYW1zLm1lbW8udmFsdWU7XG4gICAgfVxuXG4gICAgc3dpdGNoICh0eEpzb24uaW5zdHJ1Y3Rpb25zRGF0YS50eXBlKSB7XG4gICAgICBjYXNlICdjcnlwdG9UcmFuc2Zlcic6XG4gICAgICAgIGNvbnN0IHJlY2lwaWVudHMgPSB0eEpzb24uaW5zdHJ1Y3Rpb25zRGF0YS5wYXJhbXMucmVjaXBpZW50cyB8fCBbXTtcbiAgICAgICAgcmVjaXBpZW50cy5mb3JFYWNoKChyZWNpcGllbnQpID0+IHtcbiAgICAgICAgICBpZiAoIXJlY2lwaWVudC50b2tlbk5hbWUpIHtcbiAgICAgICAgICAgIC8vIHRva2VuIHRyYW5zZmVyIGRvZXNuJ3QgY2hhbmdlIG91dHB1dEFtb3VudFxuICAgICAgICAgICAgb3V0cHV0QW1vdW50ID0gb3V0cHV0QW1vdW50LnBsdXMocmVjaXBpZW50LmFtb3VudCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIG91dHB1dHMucHVzaCh7XG4gICAgICAgICAgICBhZGRyZXNzOiByZWNpcGllbnQuYWRkcmVzcyxcbiAgICAgICAgICAgIGFtb3VudDogcmVjaXBpZW50LmFtb3VudC50b1N0cmluZygpLFxuICAgICAgICAgICAgbWVtbyxcbiAgICAgICAgICAgIC4uLihyZWNpcGllbnQudG9rZW5OYW1lICYmIHtcbiAgICAgICAgICAgICAgdG9rZW5OYW1lOiByZWNpcGllbnQudG9rZW5OYW1lLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAndG9rZW5Bc3NvY2lhdGUnOlxuICAgICAgICBjb25zdCB0b2tlbnMgPSB0eEpzb24uaW5zdHJ1Y3Rpb25zRGF0YS5wYXJhbXMudG9rZW5OYW1lcyB8fCBbXTtcbiAgICAgICAgY29uc3QgYWNjb3VudElkID0gdHhKc29uLmluc3RydWN0aW9uc0RhdGEucGFyYW1zLmFjY291bnRJZDtcbiAgICAgICAgdG9rZW5zLmZvckVhY2goKHRva2VuKSA9PiB7XG4gICAgICAgICAgb3V0cHV0cy5wdXNoKHtcbiAgICAgICAgICAgIGFkZHJlc3M6IGFjY291bnRJZCxcbiAgICAgICAgICAgIGFtb3VudDogJzAnLFxuICAgICAgICAgICAgbWVtbyxcbiAgICAgICAgICAgIHRva2VuTmFtZTogdG9rZW4sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUcmFuc2FjdGlvbiBmb3JtYXQgb3V0c2lkZSBvZiBjcnlwdG9UcmFuc2ZlciBub3Qgc3VwcG9ydGVkIGZvciBleHBsYW5hdGlvbi4nKTtcbiAgICB9XG5cbiAgICBjb25zdCBkaXNwbGF5T3JkZXIgPSBbXG4gICAgICAnaWQnLFxuICAgICAgJ291dHB1dEFtb3VudCcsXG4gICAgICAnY2hhbmdlQW1vdW50JyxcbiAgICAgICdvdXRwdXRzJyxcbiAgICAgICdjaGFuZ2VPdXRwdXRzJyxcbiAgICAgICdmZWUnLFxuICAgICAgJ3RpbWVzdGFtcCcsXG4gICAgICAnZXhwaXJhdGlvbicsXG4gICAgICAnbWVtbycsXG4gICAgXTtcblxuICAgIHJldHVybiB7XG4gICAgICBkaXNwbGF5T3JkZXIsXG4gICAgICBpZDogdHhKc29uLmlkLFxuICAgICAgb3V0cHV0cyxcbiAgICAgIG91dHB1dEFtb3VudDogb3V0cHV0QW1vdW50LnRvU3RyaW5nKCksXG4gICAgICBjaGFuZ2VPdXRwdXRzOiBbXSwgLy8gYWNjb3VudCBiYXNlZCBkb2VzIG5vdCB1c2UgY2hhbmdlIG91dHB1dHNcbiAgICAgIGNoYW5nZUFtb3VudDogJzAnLCAvLyBhY2NvdW50IGJhc2UgZG9lcyBub3QgbWFrZSBjaGFuZ2VcbiAgICAgIGZlZTogcGFyYW1zLmZlZUluZm8/LmZlZSB8fCB0eEpzb24uZmVlLCAvLyBpbiB0aGUgaW5zdGFuY2Ugbm8gZmVlSW5mbyBpcyBwYXNzZWQgaW4gYXMgYSBwYXJhbSwgc2hvdyB0aGUgZmVlIGdpdmVuIGJ5IHRoZSB0eEpTT05cbiAgICAgIHRpbWVzdGFtcDogdHhKc29uLnN0YXJ0VGltZSxcbiAgICAgIGV4cGlyYXRpb246IHR4SnNvbi52YWxpZER1cmF0aW9uLFxuICAgIH0gYXMgYW55O1xuICB9XG5cbiAgaXNTdGVsbGFyU2VlZChzZWVkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gU2VlZFZhbGlkYXRvci5pc1ZhbGlkRWQyNTUxOVNlZWRGb3JDb2luKHNlZWQsIENvaW5GYW1pbHkuWExNKTtcbiAgfVxuXG4gIGNvbnZlcnRGcm9tU3RlbGxhclNlZWQoc2VlZDogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgLy8gYXNzdW1lIHRoaXMgaXMgYSB0cnVzdCBjdXN0b2RpYWwgc2VlZCBpZiBpdHMgYSB2YWxpZCBlZDI1NTE5IHBydlxuICAgIGlmICghdGhpcy5pc1N0ZWxsYXJTZWVkKHNlZWQpIHx8IFNlZWRWYWxpZGF0b3IuaGFzQ29tcGV0aW5nU2VlZEZvcm1hdHMoc2VlZCkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGlmIChTZWVkVmFsaWRhdG9yLmlzVmFsaWRFZDI1NTE5U2VlZEZvckNvaW4oc2VlZCwgQ29pbkZhbWlseS5YTE0pKSB7XG4gICAgICBjb25zdCBrZXlGcm9tU2VlZCA9IG5ldyBIYmFyS2V5UGFpcih7IHNlZWQ6IHN0ZWxsYXIuU3RyS2V5LmRlY29kZUVkMjU1MTlTZWNyZXRTZWVkKHNlZWQpIH0pO1xuICAgICAgY29uc3Qga2V5cyA9IGtleUZyb21TZWVkLmdldEtleXMoKTtcbiAgICAgIGlmIChrZXlzICE9PSB1bmRlZmluZWQgJiYga2V5cy5wcnYpIHtcbiAgICAgICAgcmV0dXJuIGtleXMucHJ2O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgaXNWYWxpZFB1YihwdWI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBVdGlscy5pc1ZhbGlkUHVibGljS2V5KHB1Yik7XG4gIH1cblxuICBzdXBwb3J0c0Rlcml2ZUtleVdpdGhTZWVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKiBpbmhlcml0ZWQgZG9jICovXG4gIGdldERlZmF1bHRNdWx0aXNpZ1R5cGUoKTogTXVsdGlzaWdUeXBlIHtcbiAgICByZXR1cm4gbXVsdGlzaWdUeXBlcy5vbmNoYWluO1xuICB9XG5cbiAgcHVibGljIGdldFRva2VuRW5hYmxlbWVudENvbmZpZygpOiBUb2tlbkVuYWJsZW1lbnRDb25maWcge1xuICAgIHJldHVybiB7XG4gICAgICByZXF1aXJlc1Rva2VuRW5hYmxlbWVudDogdHJ1ZSxcbiAgICAgIHN1cHBvcnRzTXVsdGlwbGVUb2tlbkVuYWJsZW1lbnRzOiB0cnVlLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGdldEJ1aWxkZXJGYWN0b3J5KCk6IFRyYW5zYWN0aW9uQnVpbGRlckZhY3Rvcnkge1xuICAgIHJldHVybiBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2lucy5nZXQodGhpcy5nZXRDaGFpbigpKSk7XG4gIH1cblxuICBwcml2YXRlIGdldEhiYXJDbGllbnQoKTogQ2xpZW50IHtcbiAgICBjb25zdCBjbGllbnQgPSB0aGlzLmJpdGdvLmdldEVudigpID09PSAncHJvZCcgPyBDbGllbnQuZm9yTWFpbm5ldCgpIDogQ2xpZW50LmZvclRlc3RuZXQoKTtcbiAgICByZXR1cm4gY2xpZW50O1xuICB9XG5cbiAgYXN5bmMgZ2V0QWNjb3VudEJhbGFuY2UoYWNjb3VudElkOiBzdHJpbmcsIGNsaWVudDogQ2xpZW50KTogUHJvbWlzZTxBY2NvdW50QmFsYW5jZUpzb24+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYmFsYW5jZSA9IGF3YWl0IG5ldyBBY2NvdW50QmFsYW5jZVF1ZXJ5KCkuc2V0QWNjb3VudElkKGFjY291bnRJZCkuZXhlY3V0ZShjbGllbnQpO1xuXG4gICAgICByZXR1cm4gYmFsYW5jZS50b0pTT04oKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBnZXQgYWNjb3VudCBiYWxhbmNlLCBlcnJvcjogJyArIGUubWVzc2FnZSk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYnJvYWRjYXN0VHJhbnNhY3Rpb24oe1xuICAgIHNlcmlhbGl6ZWRTaWduZWRUcmFuc2FjdGlvbixcbiAgICBzdGFydFRpbWUsXG4gIH06IEJyb2FkY2FzdFRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8QnJvYWRjYXN0VHJhbnNhY3Rpb25SZXN1bHQ+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgaGJhclR4ID0gSGJhclRyYW5zYWN0aW9uLmZyb21CeXRlcyhVdGlscy50b1VpbnQ4QXJyYXkoc2VyaWFsaXplZFNpZ25lZFRyYW5zYWN0aW9uKSk7XG5cbiAgICAgIGlmIChzdGFydFRpbWUpIHtcbiAgICAgICAgVXRpbHMuaXNWYWxpZFRpbWVTdHJpbmcoc3RhcnRUaW1lKTtcbiAgICAgICAgd2hpbGUgKCFVdGlscy5zaG91bGRCcm9hZGNhc3ROb3coc3RhcnRUaW1lKSkge1xuICAgICAgICAgIGF3YWl0IFV0aWxzLnNsZWVwKDEwMDApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLmNsaWVudEJyb2FkY2FzdFRyYW5zYWN0aW9uKGhiYXJUeCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gYnJvYWRjYXN0IHRyYW5zYWN0aW9uLCBlcnJvcjogJyArIGUubWVzc2FnZSk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgY2xpZW50QnJvYWRjYXN0VHJhbnNhY3Rpb24oaGJhclR4OiBIYmFyVHJhbnNhY3Rpb24pIHtcbiAgICBjb25zdCBjbGllbnQgPSB0aGlzLmdldEhiYXJDbGllbnQoKTtcbiAgICBjb25zdCB0cmFuc2FjdGlvblJlc3BvbnNlID0gYXdhaXQgaGJhclR4LmV4ZWN1dGUoY2xpZW50KTtcbiAgICBjb25zdCB0cmFuc2FjdGlvblJlY2VpcHQgPSBhd2FpdCB0cmFuc2FjdGlvblJlc3BvbnNlLmdldFJlY2VpcHQoY2xpZW50KTtcblxuICAgIHJldHVybiB7IHR4SWQ6IHRyYW5zYWN0aW9uUmVzcG9uc2UudHJhbnNhY3Rpb25JZC50b1N0cmluZygpLCBzdGF0dXM6IHRyYW5zYWN0aW9uUmVjZWlwdC5zdGF0dXMudG9TdHJpbmcoKSB9O1xuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICovXG4gIGF1ZGl0RGVjcnlwdGVkS2V5KHsgcHJ2LCBwdWJsaWNLZXksIG11bHRpU2lnVHlwZSB9OiBBdWRpdERlY3J5cHRlZEtleVBhcmFtcykge1xuICAgIGlmIChtdWx0aVNpZ1R5cGUgPT09ICd0c3MnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydGVkIG11bHRpU2lnVHlwZScpO1xuICAgIH1cblxuICAgIGxldCBoYmFyS2V5UGFpcjtcblxuICAgIHRyeSB7XG4gICAgICBoYmFyS2V5UGFpciA9IG5ldyBIYmFyS2V5UGFpcih7IHBydiB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcHJpdmF0ZSBrZXk6ICR7ZS5tZXNzYWdlfWApO1xuICAgIH1cbiAgICBjb25zdCBnZW5QdWJLZXkgPSBoYmFyS2V5UGFpci5nZXRLZXlzKCkucHViO1xuICAgIGlmIChwdWJsaWNLZXkgJiYgcHVibGljS2V5ICE9PSBnZW5QdWJLZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBwdWJsaWMga2V5Jyk7XG4gICAgfVxuICB9XG59XG4iXX0=Выполнить команду
Для локальной разработки. Не используйте в интернете!