PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@bitgo/sdk-coin-eth/dist/src
Просмотр файла: erc20Token.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.Erc20Token = void 0;
/**
* @prettier
*/
const sdk_core_1 = require("@bitgo/sdk-core");
const bignumber_js_1 = require("bignumber.js");
const statics_1 = require("@bitgo/statics");
const secp256k1_1 = require("@bitgo/secp256k1");
const _ = __importStar(require("lodash"));
const eth_1 = require("./eth");
const lib_1 = require("./lib");
class Erc20Token extends eth_1.Eth {
constructor(bitgo, tokenConfig) {
const staticsCoin = statics_1.coins.get(Erc20Token.coinNames[tokenConfig.network]);
super(bitgo, staticsCoin);
this.tokenConfig = tokenConfig;
this.sendMethodName = 'sendMultiSigToken';
}
static createTokenConstructor(config) {
return (bitgo) => new Erc20Token(bitgo, config);
}
static createTokenConstructors(tokenConfigs = [...statics_1.tokens.bitcoin.eth.tokens, ...statics_1.tokens.testnet.eth.tokens]) {
const tokensCtors = [];
for (const token of tokenConfigs) {
const tokenConstructor = Erc20Token.createTokenConstructor(token);
tokensCtors.push({ name: token.type, coinConstructor: tokenConstructor });
tokensCtors.push({ name: token.tokenContractAddress, coinConstructor: tokenConstructor });
}
return tokensCtors;
}
get type() {
return this.tokenConfig.type;
}
get name() {
return this.tokenConfig.name;
}
get coin() {
return this.tokenConfig.coin;
}
get network() {
return this.tokenConfig.network;
}
get tokenContractAddress() {
return this.tokenConfig.tokenContractAddress;
}
get decimalPlaces() {
return this.tokenConfig.decimalPlaces;
}
getChain() {
return this.tokenConfig.type;
}
getFullName() {
return 'ERC20 Token';
}
getBaseFactor() {
return Math.pow(10, this.tokenConfig.decimalPlaces);
}
/**
* Flag for sending value of 0
* @returns {boolean} True if okay to send 0 value, false otherwise
*/
valuelessTransferAllowed() {
return false;
}
/**
* Flag for sending data along with transactions
* @returns {boolean} True if okay to send tx data (ETH), false otherwise
*/
transactionDataAllowed() {
return false;
}
/** @inheritDoc */
supportsTss() {
return true;
}
/** @inheritDoc */
getMPCAlgorithm() {
return 'ecdsa';
}
getTransactionBuilder() {
return new lib_1.TransactionBuilder(statics_1.coins.get(this.getBaseChain()));
}
/**
* Builds a token recovery transaction without BitGo
* @param params
* @param params.userKey {String} [encrypted] xprv
* @param params.backupKey {String} [encrypted] xprv or xpub if the xprv is held by a KRS providers
* @param params.walletPassphrase {String} used to decrypt userKey and backupKey
* @param params.walletContractAddress {String} the ETH address of the wallet contract
* @param params.recoveryDestination {String} target address to send recovered funds to
* @param params.krsProvider {String} necessary if backup key is held by KRS
*/
async recover(params) {
if (_.isUndefined(params.userKey)) {
throw new Error('missing userKey');
}
if (_.isUndefined(params.backupKey)) {
throw new Error('missing backupKey');
}
if (_.isUndefined(params.walletPassphrase) && !params.userKey.startsWith('xpub')) {
throw new Error('missing wallet passphrase');
}
if (_.isUndefined(params.walletContractAddress) || !this.isValidAddress(params.walletContractAddress)) {
throw new Error('invalid walletContractAddress');
}
if (_.isUndefined(params.recoveryDestination) || !this.isValidAddress(params.recoveryDestination)) {
throw new Error('invalid recoveryDestination');
}
const isKrsRecovery = (0, sdk_core_1.getIsKrsRecovery)(params);
const isUnsignedSweep = (0, sdk_core_1.getIsUnsignedSweep)(params);
if (isKrsRecovery) {
(0, sdk_core_1.checkKrsProvider)(this, params.krsProvider, { checkCoinFamilySupport: false });
}
// Clean up whitespace from entered values
const userKey = params.userKey.replace(/\s/g, '');
const backupKey = params.backupKey.replace(/\s/g, '');
// Set new eth tx fees (default to using platform values if none are provided)
const gasPrice = params.eip1559
? new eth_1.optionalDeps.ethUtil.BN(params.eip1559.maxFeePerGas)
: new eth_1.optionalDeps.ethUtil.BN(this.setGasPrice(params.gasPrice));
const gasLimit = new eth_1.optionalDeps.ethUtil.BN(this.setGasLimit(params.gasLimit));
// Decrypt private keys from KeyCard values
let userPrv;
if (!userKey.startsWith('xpub') && !userKey.startsWith('xprv')) {
try {
userPrv = this.bitgo.decrypt({
input: userKey,
password: params.walletPassphrase,
});
}
catch (e) {
throw new Error(`Error decrypting user keychain: ${e.message}`);
}
}
let backupKeyAddress;
let backupSigningKey;
if (isKrsRecovery || isUnsignedSweep) {
const backupHDNode = secp256k1_1.bip32.fromBase58(backupKey);
backupSigningKey = backupHDNode.publicKey;
backupKeyAddress = `0x${eth_1.optionalDeps.ethUtil.publicToAddress(backupSigningKey, true).toString('hex')}`;
}
else {
let backupPrv;
try {
backupPrv = this.bitgo.decrypt({
input: backupKey,
password: params.walletPassphrase,
});
}
catch (e) {
throw new Error(`Error decrypting backup keychain: ${e.message}`);
}
const backupHDNode = secp256k1_1.bip32.fromBase58(backupPrv);
backupSigningKey = backupHDNode.privateKey;
backupKeyAddress = `0x${eth_1.optionalDeps.ethUtil.privateToAddress(backupSigningKey).toString('hex')}`;
}
// Get nonce for backup key (should be 0)
let backupKeyNonce = 0;
const result = await this.recoveryBlockchainExplorerQuery({
chainid: this.getChainId().toString(),
module: 'account',
action: 'txlist',
address: backupKeyAddress,
}, params.apiKey);
const backupKeyTxList = result.result;
if (backupKeyTxList.length > 0) {
// Calculate last nonce used
const outgoingTxs = backupKeyTxList.filter((tx) => tx.from === backupKeyAddress);
backupKeyNonce = outgoingTxs.length;
}
// get balance of backup key and make sure we can afford gas
const backupKeyBalance = await this.queryAddressBalance(backupKeyAddress, params.apiKey);
if (backupKeyBalance.lt(gasPrice.mul(gasLimit))) {
throw new Error(`Backup key address ${backupKeyAddress} has balance ${backupKeyBalance.toString(10)}. This address must have a balance of at least 0.01 ETH to perform recoveries`);
}
// get token balance of wallet
const txAmount = await this.queryAddressTokenBalance(this.tokenContractAddress, params.walletContractAddress, params.apiKey);
if (new bignumber_js_1.BigNumber(txAmount).isLessThanOrEqualTo(0)) {
throw new Error('Wallet does not have enough funds to recover');
}
// build recipients object
const recipients = [
{
address: params.recoveryDestination,
amount: txAmount.toString(10),
},
];
// Get sequence ID using contract call
const sequenceId = await this.querySequenceId(params.walletContractAddress, params.apiKey);
let operationHash, signature;
if (!isUnsignedSweep) {
// Get operation hash and sign it
operationHash = this.getOperationSha3ForExecuteAndConfirm(recipients, this.getDefaultExpireTime(), sequenceId);
signature = sdk_core_1.Util.ethSignMsgHash(operationHash, sdk_core_1.Util.xprvToEthPrivateKey(userPrv));
try {
sdk_core_1.Util.ecRecoverEthAddress(operationHash, signature);
}
catch (e) {
throw new Error('Invalid signature');
}
}
const txInfo = {
recipient: recipients[0],
expireTime: this.getDefaultExpireTime(),
contractSequenceId: sequenceId,
signature: signature,
gasLimit: gasLimit.toString(10),
tokenContractAddress: this.tokenContractAddress,
};
// calculate send data
const sendMethodArgs = this.getSendMethodArgs(txInfo);
const methodSignature = eth_1.optionalDeps.ethAbi.methodID(this.sendMethodName, _.map(sendMethodArgs, 'type'));
const encodedArgs = eth_1.optionalDeps.ethAbi.rawEncode(_.map(sendMethodArgs, 'type'), _.map(sendMethodArgs, 'value'));
const sendData = Buffer.concat([methodSignature, encodedArgs]);
let tx = eth_1.Eth.buildTransaction({
to: params.walletContractAddress,
nonce: backupKeyNonce,
value: 0,
gasPrice: gasPrice,
gasLimit: gasLimit,
data: sendData,
eip1559: params.eip1559,
replayProtectionOptions: params.replayProtectionOptions,
});
if (isUnsignedSweep) {
return this.formatForOfflineVault(txInfo, tx, userKey, backupKey, gasPrice, gasLimit, params.eip1559, params.replayProtectionOptions, params.apiKey);
}
if (!isKrsRecovery) {
tx = tx.sign(backupSigningKey);
}
const signedTx = {
id: eth_1.optionalDeps.ethUtil.bufferToHex(tx.hash()),
tx: tx.serialize().toString('hex'),
};
if (isKrsRecovery) {
signedTx.backupKey = backupKey;
signedTx.coin = 'erc20';
}
return signedTx;
}
getOperation(recipient, expireTime, contractSequenceId) {
return [
['string', 'address', 'uint', 'address', 'uint', 'uint'],
[
'ERC20',
new eth_1.optionalDeps.ethUtil.BN(eth_1.optionalDeps.ethUtil.stripHexPrefix(recipient.address), 16),
recipient.amount,
new eth_1.optionalDeps.ethUtil.BN(eth_1.optionalDeps.ethUtil.stripHexPrefix(this.tokenContractAddress), 16),
expireTime,
contractSequenceId,
],
];
}
getSendMethodArgs(txInfo) {
// Method signature is
// sendMultiSigToken(address toAddress, uint value, address tokenContractAddress, uint expireTime, uint sequenceId, bytes signature)
return [
{
name: 'toAddress',
type: 'address',
value: txInfo.recipient.address,
},
{
name: 'value',
type: 'uint',
value: txInfo.recipient.amount,
},
{
name: 'tokenContractAddress',
type: 'address',
value: this.tokenContractAddress,
},
{
name: 'expireTime',
type: 'uint',
value: txInfo.expireTime,
},
{
name: 'sequenceId',
type: 'uint',
value: txInfo.contractSequenceId,
},
{
name: 'signature',
type: 'bytes',
value: eth_1.optionalDeps.ethUtil.toBuffer(eth_1.optionalDeps.ethUtil.addHexPrefix(txInfo.signature)),
},
];
}
verifyCoin(txPrebuild) {
return txPrebuild.coin === this.tokenConfig.coin && txPrebuild.token === this.tokenConfig.type;
}
}
exports.Erc20Token = Erc20Token;
Erc20Token.coinNames = {
Mainnet: 'eth',
Testnet: 'hteth',
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJjMjBUb2tlbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9lcmMyMFRva2VuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBOztHQUVHO0FBQ0gsOENBU3lCO0FBQ3pCLCtDQUF5QztBQUV6Qyw0Q0FBcUY7QUFFckYsZ0RBQXlDO0FBQ3pDLDBDQUE0QjtBQUU1QiwrQkFBNkY7QUFDN0YsK0JBQTJDO0FBRzNDLE1BQWEsVUFBVyxTQUFRLFNBQUc7SUFRakMsWUFBWSxLQUFnQixFQUFFLFdBQTZCO1FBQ3pELE1BQU0sV0FBVyxHQUFHLGVBQUssQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUN6RSxLQUFLLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQzFCLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBQy9CLElBQUksQ0FBQyxjQUFjLEdBQUcsbUJBQW1CLENBQUM7SUFDNUMsQ0FBQztJQUVELE1BQU0sQ0FBQyxzQkFBc0IsQ0FBQyxNQUF3QjtRQUNwRCxPQUFPLENBQUMsS0FBZ0IsRUFBRSxFQUFFLENBQUMsSUFBSSxVQUFVLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFFRCxNQUFNLENBQUMsdUJBQXVCLENBQzVCLGVBQW1DLENBQUMsR0FBRyxnQkFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEdBQUcsZ0JBQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQztRQUUvRixNQUFNLFdBQVcsR0FBMkIsRUFBRSxDQUFDO1FBQy9DLEtBQUssTUFBTSxLQUFLLElBQUksWUFBWSxFQUFFLENBQUM7WUFDakMsTUFBTSxnQkFBZ0IsR0FBRyxVQUFVLENBQUMsc0JBQXNCLENBQUMsS0FBSyxDQUFD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TUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2FBQzFGO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFFRCxVQUFVLENBQUMsVUFBK0I7UUFDeEMsT0FBTyxVQUFVLENBQUMsSUFBSSxLQUFLLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxJQUFJLFVBQVUsQ0FBQyxLQUFLLEtBQUssSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUM7SUFDakcsQ0FBQzs7QUFwV0gsZ0NBcVdDO0FBbFdRLG9CQUFTLEdBQWM7SUFDNUIsT0FBTyxFQUFFLEtBQUs7SUFDZCxPQUFPLEVBQUUsT0FBTztDQUNqQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcHJldHRpZXJcbiAqL1xuaW1wb3J0IHtcbiAgQml0R29CYXNlLFxuICBDb2luQ29uc3RydWN0b3IsXG4gIFV0aWwsXG4gIGNoZWNrS3JzUHJvdmlkZXIsXG4gIGdldElzS3JzUmVjb3ZlcnksXG4gIGdldElzVW5zaWduZWRTd2VlcCxcbiAgTVBDQWxnb3JpdGhtLFxuICBOYW1lZENvaW5Db25zdHJ1Y3Rvcixcbn0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcbmltcG9ydCB7IEJpZ051bWJlciB9IGZyb20gJ2JpZ251bWJlci5qcyc7XG5cbmltcG9ydCB7IGNvaW5zLCBFdGhMaWtlVG9rZW5Db25maWcsIEVyYzIwVG9rZW5Db25maWcsIHRva2VucyB9IGZyb20gJ0BiaXRnby9zdGF0aWNzJztcbmltcG9ydCB7IENvaW5OYW1lcyB9IGZyb20gJ0BiaXRnby9hYnN0cmFjdC1ldGgnO1xuaW1wb3J0IHsgYmlwMzIgfSBmcm9tICdAYml0Z28vc2VjcDI1NmsxJztcbmltcG9ydCAqIGFzIF8gZnJvbSAnbG9kYXNoJztcblxuaW1wb3J0IHsgRXRoLCBSZWNvdmVyT3B0aW9ucywgUmVjb3ZlcnlJbmZvLCBvcHRpb25hbERlcHMsIFRyYW5zYWN0aW9uUHJlYnVpbGQgfSBmcm9tICcuL2V0aCc7XG5pbXBvcnQgeyBUcmFuc2FjdGlvbkJ1aWxkZXIgfSBmcm9tICcuL2xpYic7XG5cbmV4cG9ydCB7IEVyYzIwVG9rZW5Db25maWcgfTtcbmV4cG9ydCBjbGFzcyBFcmMyMFRva2VuIGV4dGVuZHMgRXRoIHtcbiAgcHVibGljIHJlYWRvbmx5IHRva2VuQ29uZmlnOiBFdGhMaWtlVG9rZW5Db25maWc7XG4gIHByb3RlY3RlZCByZWFkb25seSBzZW5kTWV0aG9kTmFtZTogJ3NlbmRNdWx0aVNpZycgfCAnc2VuZE11bHRpU2lnVG9rZW4nO1xuICBzdGF0aWMgY29pbk5hbWVzOiBDb2luTmFtZXMgPSB7XG4gICAgTWFpbm5ldDogJ2V0aCcsXG4gICAgVGVzdG5ldDogJ2h0ZXRoJyxcbiAgfTtcblxuICBjb25zdHJ1Y3RvcihiaXRnbzogQml0R29CYXNlLCB0b2tlbkNvbmZpZzogRXJjMjBUb2tlbkNvbmZpZykge1xuICAgIGNvbnN0IHN0YXRpY3NDb2luID0gY29pbnMuZ2V0KEVyYzIwVG9rZW4uY29pbk5hbWVzW3Rva2VuQ29uZmlnLm5ldHdvcmtdKTtcbiAgICBzdXBlcihiaXRnbywgc3RhdGljc0NvaW4pO1xuICAgIHRoaXMudG9rZW5Db25maWcgPSB0b2tlbkNvbmZpZztcbiAgICB0aGlzLnNlbmRNZXRob2ROYW1lID0gJ3NlbmRNdWx0aVNpZ1Rva2VuJztcbiAgfVxuXG4gIHN0YXRpYyBjcmVhdGVUb2tlbkNvbnN0cnVjdG9yKGNvbmZpZzogRXJjMjBUb2tlbkNvbmZpZyk6IENvaW5Db25zdHJ1Y3RvciB7XG4gICAgcmV0dXJuIChiaXRnbzogQml0R29CYXNlKSA9PiBuZXcgRXJjMjBUb2tlbihiaXRnbywgY29uZmlnKTtcbiAgfVxuXG4gIHN0YXRpYyBjcmVhdGVUb2tlbkNvbnN0cnVjdG9ycyhcbiAgICB0b2tlbkNvbmZpZ3M6IEVyYzIwVG9rZW5Db25maWdbXSA9IFsuLi50b2tlbnMuYml0Y29pbi5ldGgudG9rZW5zLCAuLi50b2tlbnMudGVzdG5ldC5ldGgudG9rZW5zXVxuICApOiBOYW1lZENvaW5Db25zdHJ1Y3RvcltdIHtcbiAgICBjb25zdCB0b2tlbnNDdG9yczogTmFtZWRDb2luQ29uc3RydWN0b3JbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgdG9rZW4gb2YgdG9rZW5Db25maWdzKSB7XG4gICAgICBjb25zdCB0b2tlbkNvbnN0cnVjdG9yID0gRXJjMjBUb2tlbi5jcmVhdGVUb2tlbkNvbnN0cnVjdG9yKHRva2VuKTtcbiAgICAgIHRva2Vuc0N0b3JzLnB1c2goeyBuYW1lOiB0b2tlbi50eXBlLCBjb2luQ29uc3RydWN0b3I6IHRva2VuQ29uc3RydWN0b3IgfSk7XG4gICAgICB0b2tlbnNDdG9ycy5wdXNoKHsgbmFtZTogdG9rZW4udG9rZW5Db250cmFjdEFkZHJlc3MsIGNvaW5Db25zdHJ1Y3RvcjogdG9rZW5Db25zdHJ1Y3RvciB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHRva2Vuc0N0b3JzO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudG9rZW5Db25maWcudHlwZTtcbiAgfVxuXG4gIGdldCBuYW1lKCkge1xuICAgIHJldHVybiB0aGlzLnRva2VuQ29uZmlnLm5hbWU7XG4gIH1cblxuICBnZXQgY29pbigpIHtcbiAgICByZXR1cm4gdGhpcy50b2tlbkNvbmZpZy5jb2luO1xuICB9XG5cbiAgZ2V0IG5ldHdvcmsoKSB7XG4gICAgcmV0dXJuIHRoaXMudG9rZW5Db25maWcubmV0d29yaztcbiAgfVxuXG4gIGdldCB0b2tlbkNvbnRyYWN0QWRkcmVzcygpIHtcbiAgICByZXR1cm4gdGhpcy50b2tlbkNvbmZpZy50b2tlbkNvbnRyYWN0QWRkcmVzcztcbiAgfVxuXG4gIGdldCBkZWNpbWFsUGxhY2VzKCkge1xuICAgIHJldHVybiB0aGlzLnRva2VuQ29uZmlnLmRlY2ltYWxQbGFjZXM7XG4gIH1cblxuICBnZXRDaGFpbigpIHtcbiAgICByZXR1cm4gdGhpcy50b2tlbkNvbmZpZy50eXBlO1xuICB9XG5cbiAgZ2V0RnVsbE5hbWUoKSB7XG4gICAgcmV0dXJuICdFUkMyMCBUb2tlbic7XG4gIH1cblxuICBnZXRCYXNlRmFjdG9yKCkge1xuICAgIHJldHVybiBNYXRoLnBvdygxMCwgdGhpcy50b2tlbkNvbmZpZy5kZWNpbWFsUGxhY2VzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGbGFnIGZvciBzZW5kaW5nIHZhbHVlIG9mIDBcbiAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgb2theSB0byBzZW5kIDAgdmFsdWUsIGZhbHNlIG90aGVyd2lzZVxuICAgKi9cbiAgdmFsdWVsZXNzVHJhbnNmZXJBbGxvd2VkKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGbGFnIGZvciBzZW5kaW5nIGRhdGEgYWxvbmcgd2l0aCB0cmFuc2FjdGlvbnNcbiAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgb2theSB0byBzZW5kIHR4IGRhdGEgKEVUSCksIGZhbHNlIG90aGVyd2lzZVxuICAgKi9cbiAgdHJhbnNhY3Rpb25EYXRhQWxsb3dlZCgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKi9cbiAgc3VwcG9ydHNUc3MoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKi9cbiAgZ2V0TVBDQWxnb3JpdGhtKCk6IE1QQ0FsZ29yaXRobSB7XG4gICAgcmV0dXJuICdlY2RzYSc7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0VHJhbnNhY3Rpb25CdWlsZGVyKCk6IFRyYW5zYWN0aW9uQnVpbGRlciB7XG4gICAgcmV0dXJuIG5ldyBUcmFuc2FjdGlvbkJ1aWxkZXIoY29pbnMuZ2V0KHRoaXMuZ2V0QmFzZUNoYWluKCkpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgYSB0b2tlbiByZWNvdmVyeSB0cmFuc2FjdGlvbiB3aXRob3V0IEJpdEdvXG4gICAqIEBwYXJhbSBwYXJhbXNcbiAgICogQHBhcmFtIHBhcmFtcy51c2VyS2V5IHtTdHJpbmd9IFtlbmNyeXB0ZWRdIHhwcnZcbiAgICogQHBhcmFtIHBhcmFtcy5iYWNrdXBLZXkge1N0cmluZ30gW2VuY3J5cHRlZF0geHBydiBvciB4cHViIGlmIHRoZSB4cHJ2IGlzIGhlbGQgYnkgYSBLUlMgcHJvdmlkZXJzXG4gICAqIEBwYXJhbSBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSB7U3RyaW5nfSB1c2VkIHRvIGRlY3J5cHQgdXNlcktleSBhbmQgYmFja3VwS2V5XG4gICAqIEBwYXJhbSBwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzIHtTdHJpbmd9IHRoZSBFVEggYWRkcmVzcyBvZiB0aGUgd2FsbGV0IGNvbnRyYWN0XG4gICAqIEBwYXJhbSBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbiB7U3RyaW5nfSB0YXJnZXQgYWRkcmVzcyB0byBzZW5kIHJlY292ZXJlZCBmdW5kcyB0b1xuICAgKiBAcGFyYW0gcGFyYW1zLmtyc1Byb3ZpZGVyIHtTdHJpbmd9IG5lY2Vzc2FyeSBpZiBiYWNrdXAga2V5IGlzIGhlbGQgYnkgS1JTXG4gICAqL1xuICBhc3luYyByZWNvdmVyKHBhcmFtczogUmVjb3Zlck9wdGlvbnMpOiBQcm9taXNlPFJlY292ZXJ5SW5mbz4ge1xuICAgIGlmIChfLmlzVW5kZWZpbmVkKHBhcmFtcy51c2VyS2V5KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHVzZXJLZXknKTtcbiAgICB9XG5cbiAgICBpZiAoXy5pc1VuZGVmaW5lZChwYXJhbXMuYmFja3VwS2V5KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIGJhY2t1cEtleScpO1xuICAgIH1cblxuICAgIGlmIChfLmlzVW5kZWZpbmVkKHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlKSAmJiAhcGFyYW1zLnVzZXJLZXkuc3RhcnRzV2l0aCgneHB1YicpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3Npbmcgd2FsbGV0IHBhc3NwaHJhc2UnKTtcbiAgICB9XG5cbiAgICBpZiAoXy5pc1VuZGVmaW5lZChwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzKSB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHdhbGxldENvbnRyYWN0QWRkcmVzcycpO1xuICAgIH1cblxuICAgIGlmIChfLmlzVW5kZWZpbmVkKHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uKSB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCByZWNvdmVyeURlc3RpbmF0aW9uJyk7XG4gICAgfVxuXG4gICAgY29uc3QgaXNLcnNSZWNvdmVyeSA9IGdldElzS3JzUmVjb3ZlcnkocGFyYW1zKTtcbiAgICBjb25zdCBpc1Vuc2lnbmVkU3dlZXAgPSBnZXRJc1Vuc2lnbmVkU3dlZXAocGFyYW1zKTtcblxuICAgIGlmIChpc0tyc1JlY292ZXJ5KSB7XG4gICAgICBjaGVja0tyc1Byb3ZpZGVyKHRoaXMsIHBhcmFtcy5rcnNQcm92aWRlciwgeyBjaGVja0NvaW5GYW1pbHlTdXBwb3J0OiBmYWxzZSB9KTtcbiAgICB9XG5cbiAgICAvLyBDbGVhbiB1cCB3aGl0ZXNwYWNlIGZyb20gZW50ZXJlZCB2YWx1ZXNcbiAgICBjb25zdCB1c2VyS2V5ID0gcGFyYW1zLnVzZXJLZXkucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICBjb25zdCBiYWNrdXBLZXkgPSBwYXJhbXMuYmFja3VwS2V5LnJlcGxhY2UoL1xccy9nLCAnJyk7XG5cbiAgICAvLyBTZXQgbmV3IGV0aCB0eCBmZWVzIChkZWZhdWx0IHRvIHVzaW5nIHBsYXRmb3JtIHZhbHVlcyBpZiBub25lIGFyZSBwcm92aWRlZClcbiAgICBjb25zdCBnYXNQcmljZSA9IHBhcmFtcy5laXAxNTU5XG4gICAgICA/IG5ldyBvcHRpb25hbERlcHMuZXRoVXRpbC5CTihwYXJhbXMuZWlwMTU1OS5tYXhGZWVQZXJHYXMpXG4gICAgICA6IG5ldyBvcHRpb25hbERlcHMuZXRoVXRpbC5CTih0aGlzLnNldEdhc1ByaWNlKHBhcmFtcy5nYXNQcmljZSkpO1xuICAgIGNvbnN0IGdhc0xpbWl0ID0gbmV3IG9wdGlvbmFsRGVwcy5ldGhVdGlsLkJOKHRoaXMuc2V0R2FzTGltaXQocGFyYW1zLmdhc0xpbWl0KSk7XG5cbiAgICAvLyBEZWNyeXB0IHByaXZhdGUga2V5cyBmcm9tIEtleUNhcmQgdmFsdWVzXG4gICAgbGV0IHVzZXJQcnY7XG4gICAgaWYgKCF1c2VyS2V5LnN0YXJ0c1dpdGgoJ3hwdWInKSAmJiAhdXNlcktleS5zdGFydHNXaXRoKCd4cHJ2JykpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHVzZXJQcnYgPSB0aGlzLmJpdGdvLmRlY3J5cHQoe1xuICAgICAgICAgIGlucHV0OiB1c2VyS2V5LFxuICAgICAgICAgIHBhc3N3b3JkOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZGVjcnlwdGluZyB1c2VyIGtleWNoYWluOiAke2UubWVzc2FnZX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgYmFja3VwS2V5QWRkcmVzcztcbiAgICBsZXQgYmFja3VwU2lnbmluZ0tleTtcblxuICAgIGlmIChpc0tyc1JlY292ZXJ5IHx8IGlzVW5zaWduZWRTd2VlcCkge1xuICAgICAgY29uc3QgYmFja3VwSEROb2RlID0gYmlwMzIuZnJvbUJhc2U1OChiYWNrdXBLZXkpO1xuICAgICAgYmFja3VwU2lnbmluZ0tleSA9IGJhY2t1cEhETm9kZS5wdWJsaWNLZXk7XG4gICAgICBiYWNrdXBLZXlBZGRyZXNzID0gYDB4JHtvcHRpb25hbERlcHMuZXRoVXRpbC5wdWJsaWNUb0FkZHJlc3MoYmFja3VwU2lnbmluZ0tleSwgdHJ1ZSkudG9TdHJpbmcoJ2hleCcpfWA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBiYWNrdXBQcnY7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGJhY2t1cFBydiA9IHRoaXMuYml0Z28uZGVjcnlwdCh7XG4gICAgICAgICAgaW5wdXQ6IGJhY2t1cEtleSxcbiAgICAgICAgICBwYXNzd29yZDogcGFyYW1zLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGRlY3J5cHRpbmcgYmFja3VwIGtleWNoYWluOiAke2UubWVzc2FnZX1gKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYmFja3VwSEROb2RlID0gYmlwMzIuZnJvbUJhc2U1OChiYWNrdXBQcnYpO1xuICAgICAgYmFja3VwU2lnbmluZ0tleSA9IGJhY2t1cEhETm9kZS5wcml2YXRlS2V5O1xuICAgICAgYmFja3VwS2V5QWRkcmVzcyA9IGAweCR7b3B0aW9uYWxEZXBzLmV0aFV0aWwucHJpdmF0ZVRvQWRkcmVzcyhiYWNrdXBTaWduaW5nS2V5KS50b1N0cmluZygnaGV4Jyl9YDtcbiAgICB9XG5cbiAgICAvLyBHZXQgbm9uY2UgZm9yIGJhY2t1cCBrZXkgKHNob3VsZCBiZSAwKVxuICAgIGxldCBiYWNrdXBLZXlOb25jZSA9IDA7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnJlY292ZXJ5QmxvY2tjaGFpbkV4cGxvcmVyUXVlcnkoXG4gICAgICB7XG4gICAgICAgIGNoYWluaWQ6IHRoaXMuZ2V0Q2hhaW5JZCgpLnRvU3RyaW5nKCksXG4gICAgICAgIG1vZHVsZTogJ2FjY291bnQnLFxuICAgICAgICBhY3Rpb246ICd0eGxpc3QnLFxuICAgICAgICBhZGRyZXNzOiBiYWNrdXBLZXlBZGRyZXNzLFxuICAgICAgfSxcbiAgICAgIHBhcmFtcy5hcGlLZXlcbiAgICApO1xuICAgIGNvbnN0IGJhY2t1cEtleVR4TGlzdCA9IHJlc3VsdC5yZXN1bHQ7XG4gICAgaWYgKGJhY2t1cEtleVR4TGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBDYWxjdWxhdGUgbGFzdCBub25jZSB1c2VkXG4gICAgICBjb25zdCBvdXRnb2luZ1R4cyA9IGJhY2t1cEtleVR4TGlzdC5maWx0ZXIoKHR4KSA9PiB0eC5mcm9tID09PSBiYWNrdXBLZXlBZGRyZXNzKTtcbiAgICAgIGJhY2t1cEtleU5vbmNlID0gb3V0Z29pbmdUeHMubGVuZ3RoO1xuICAgIH1cblxuICAgIC8vIGdldCBiYWxhbmNlIG9mIGJhY2t1cCBrZXkgYW5kIG1ha2Ugc3VyZSB3ZSBjYW4gYWZmb3JkIGdhc1xuICAgIGNvbnN0IGJhY2t1cEtleUJhbGFuY2UgPSBhd2FpdCB0aGlzLnF1ZXJ5QWRkcmVzc0JhbGFuY2UoYmFja3VwS2V5QWRkcmVzcywgcGFyYW1zLmFwaUtleSk7XG5cbiAgICBpZiAoYmFja3VwS2V5QmFsYW5jZS5sdChnYXNQcmljZS5tdWwoZ2FzTGltaXQpKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQmFja3VwIGtleSBhZGRyZXNzICR7YmFja3VwS2V5QWRkcmVzc30gaGFzIGJhbGFuY2UgJHtiYWNrdXBLZXlCYWxhbmNlLnRvU3RyaW5nKFxuICAgICAgICAgIDEwXG4gICAgICAgICl9LiBUaGlzIGFkZHJlc3MgbXVzdCBoYXZlIGEgYmFsYW5jZSBvZiBhdCBsZWFzdCAwLjAxIEVUSCB0byBwZXJmb3JtIHJlY292ZXJpZXNgXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIGdldCB0b2tlbiBiYWxhbmNlIG9mIHdhbGxldFxuICAgIGNvbnN0IHR4QW1vdW50ID0gYXdhaXQgdGhpcy5xdWVyeUFkZHJlc3NUb2tlbkJhbGFuY2UoXG4gICAgICB0aGlzLnRva2VuQ29udHJhY3RBZGRyZXNzLFxuICAgICAgcGFyYW1zLndhbGxldENvbnRyYWN0QWRkcmVzcyxcbiAgICAgIHBhcmFtcy5hcGlLZXlcbiAgICApO1xuICAgIGlmIChuZXcgQmlnTnVtYmVyKHR4QW1vdW50KS5pc0xlc3NUaGFuT3JFcXVhbFRvKDApKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dhbGxldCBkb2VzIG5vdCBoYXZlIGVub3VnaCBmdW5kcyB0byByZWNvdmVyJyk7XG4gICAgfVxuXG4gICAgLy8gYnVpbGQgcmVjaXBpZW50cyBvYmplY3RcbiAgICBjb25zdCByZWNpcGllbnRzID0gW1xuICAgICAge1xuICAgICAgICBhZGRyZXNzOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgYW1vdW50OiB0eEFtb3VudC50b1N0cmluZygxMCksXG4gICAgICB9LFxuICAgIF07XG5cbiAgICAvLyBHZXQgc2VxdWVuY2UgSUQgdXNpbmcgY29udHJhY3QgY2FsbFxuICAgIGNvbnN0IHNlcXVlbmNlSWQgPSBhd2FpdCB0aGlzLnF1ZXJ5U2VxdWVuY2VJZChwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzLCBwYXJhbXMuYXBpS2V5KTtcblxuICAgIGxldCBvcGVyYXRpb25IYXNoLCBzaWduYXR1cmU7XG4gICAgaWYgKCFpc1Vuc2lnbmVkU3dlZXApIHtcbiAgICAgIC8vIEdldCBvcGVyYXRpb24gaGFzaCBhbmQgc2lnbiBpdFxuICAgICAgb3BlcmF0aW9uSGFzaCA9IHRoaXMuZ2V0T3BlcmF0aW9uU2hhM0ZvckV4ZWN1dGVBbmRDb25maXJtKHJlY2lwaWVudHMsIHRoaXMuZ2V0RGVmYXVsdEV4cGlyZVRpbWUoKSwgc2VxdWVuY2VJZCk7XG4gICAgICBzaWduYXR1cmUgPSBVdGlsLmV0aFNpZ25Nc2dIYXNoKG9wZXJhdGlvbkhhc2gsIFV0aWwueHBydlRvRXRoUHJpdmF0ZUtleSh1c2VyUHJ2KSk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIFV0aWwuZWNSZWNvdmVyRXRoQWRkcmVzcyhvcGVyYXRpb25IYXNoLCBzaWduYXR1cmUpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc2lnbmF0dXJlJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgdHhJbmZvID0ge1xuICAgICAgcmVjaXBpZW50OiByZWNpcGllbnRzWzBdLFxuICAgICAgZXhwaXJlVGltZTogdGhpcy5nZXREZWZhdWx0RXhwaXJlVGltZSgpLFxuICAgICAgY29udHJhY3RTZXF1ZW5jZUlkOiBzZXF1ZW5jZUlkLFxuICAgICAgc2lnbmF0dXJlOiBzaWduYXR1cmUsXG4gICAgICBnYXNMaW1pdDogZ2FzTGltaXQudG9TdHJpbmcoMTApLFxuICAgICAgdG9rZW5Db250cmFjdEFkZHJlc3M6IHRoaXMudG9rZW5Db250cmFjdEFkZHJlc3MsXG4gICAgfTtcblxuICAgIC8vIGNhbGN1bGF0ZSBzZW5kIGRhdGFcbiAgICBjb25zdCBzZW5kTWV0aG9kQXJncyA9IHRoaXMuZ2V0U2VuZE1ldGhvZEFyZ3ModHhJbmZvKTtcbiAgICBjb25zdCBtZXRob2RTaWduYXR1cmUgPSBvcHRpb25hbERlcHMuZXRoQWJpLm1ldGhvZElEKHRoaXMuc2VuZE1ldGhvZE5hbWUsIF8ubWFwKHNlbmRNZXRob2RBcmdzLCAndHlwZScpKTtcbiAgICBjb25zdCBlbmNvZGVkQXJncyA9IG9wdGlvbmFsRGVwcy5ldGhBYmkucmF3RW5jb2RlKF8ubWFwKHNlbmRNZXRob2RBcmdzLCAndHlwZScpLCBfLm1hcChzZW5kTWV0aG9kQXJncywgJ3ZhbHVlJykpO1xuICAgIGNvbnN0IHNlbmREYXRhID0gQnVmZmVyLmNvbmNhdChbbWV0aG9kU2lnbmF0dXJlLCBlbmNvZGVkQXJnc10pO1xuXG4gICAgbGV0IHR4ID0gRXRoLmJ1aWxkVHJhbnNhY3Rpb24oe1xuICAgICAgdG86IHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3MsXG4gICAgICBub25jZTogYmFja3VwS2V5Tm9uY2UsXG4gICAgICB2YWx1ZTogMCxcbiAgICAgIGdhc1ByaWNlOiBnYXNQcmljZSxcbiAgICAgIGdhc0xpbWl0OiBnYXNMaW1pdCxcbiAgICAgIGRhdGE6IHNlbmREYXRhLFxuICAgICAgZWlwMTU1OTogcGFyYW1zLmVpcDE1NTksXG4gICAgICByZXBsYXlQcm90ZWN0aW9uT3B0aW9uczogcGFyYW1zLnJlcGxheVByb3RlY3Rpb25PcHRpb25zLFxuICAgIH0pO1xuXG4gICAgaWYgKGlzVW5zaWduZWRTd2VlcCkge1xuICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0Rm9yT2ZmbGluZVZhdWx0KFxuICAgICAgICB0eEluZm8sXG4gICAgICAgIHR4LFxuICAgICAgICB1c2VyS2V5LFxuICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgIGdhc1ByaWNlLFxuICAgICAgICBnYXNMaW1pdCxcbiAgICAgICAgcGFyYW1zLmVpcDE1NTksXG4gICAgICAgIHBhcmFtcy5yZXBsYXlQcm90ZWN0aW9uT3B0aW9ucyxcbiAgICAgICAgcGFyYW1zLmFwaUtleVxuICAgICAgKSBhcyBhbnk7XG4gICAgfVxuXG4gICAgaWYgKCFpc0tyc1JlY292ZXJ5KSB7XG4gICAgICB0eCA9IHR4LnNpZ24oYmFja3VwU2lnbmluZ0tleSk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2lnbmVkVHg6IFJlY292ZXJ5SW5mbyA9IHtcbiAgICAgIGlkOiBvcHRpb25hbERlcHMuZXRoVXRpbC5idWZmZXJUb0hleCh0eC5oYXNoKCkpLFxuICAgICAgdHg6IHR4LnNlcmlhbGl6ZSgpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICB9O1xuXG4gICAgaWYgKGlzS3JzUmVjb3ZlcnkpIHtcbiAgICAgIHNpZ25lZFR4LmJhY2t1cEtleSA9IGJhY2t1cEtleTtcbiAgICAgIHNpZ25lZFR4LmNvaW4gPSAnZXJjMjAnO1xuICAgIH1cblxuICAgIHJldHVybiBzaWduZWRUeDtcbiAgfVxuXG4gIGdldE9wZXJhdGlvbihyZWNpcGllbnQsIGV4cGlyZVRpbWUsIGNvbnRyYWN0U2VxdWVuY2VJZCkge1xuICAgIHJldHVybiBbXG4gICAgICBbJ3N0cmluZycsICdhZGRyZXNzJywgJ3VpbnQnLCAnYWRkcmVzcycsICd1aW50JywgJ3VpbnQnXSxcbiAgICAgIFtcbiAgICAgICAgJ0VSQzIwJyxcbiAgICAgICAgbmV3IG9wdGlvbmFsRGVwcy5ldGhVdGlsLkJOKG9wdGlvbmFsRGVwcy5ldGhVdGlsLnN0cmlwSGV4UHJlZml4KHJlY2lwaWVudC5hZGRyZXNzKSwgMTYpLFxuICAgICAgICByZWNpcGllbnQuYW1vdW50LFxuICAgICAgICBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4ob3B0aW9uYWxEZXBzLmV0aFV0aWwuc3RyaXBIZXhQcmVmaXgodGhpcy50b2tlbkNvbnRyYWN0QWRkcmVzcyksIDE2KSxcbiAgICAgICAgZXhwaXJlVGltZSxcbiAgICAgICAgY29udHJhY3RTZXF1ZW5jZUlkLFxuICAgICAgXSxcbiAgICBdO1xuICB9XG5cbiAgZ2V0U2VuZE1ldGhvZEFyZ3ModHhJbmZvKSB7XG4gICAgLy8gTWV0aG9kIHNpZ25hdHVyZSBpc1xuICAgIC8vIHNlbmRNdWx0aVNpZ1Rva2VuKGFkZHJlc3MgdG9BZGRyZXNzLCB1aW50IHZhbHVlLCBhZGRyZXNzIHRva2VuQ29udHJhY3RBZGRyZXNzLCB1aW50IGV4cGlyZVRpbWUsIHVpbnQgc2VxdWVuY2VJZCwgYnl0ZXMgc2lnbmF0dXJlKVxuICAgIHJldHVybiBbXG4gICAgICB7XG4gICAgICAgIG5hbWU6ICd0b0FkZHJlc3MnLFxuICAgICAgICB0eXBlOiAnYWRkcmVzcycsXG4gICAgICAgIHZhbHVlOiB0eEluZm8ucmVjaXBpZW50LmFkZHJlc3MsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBuYW1lOiAndmFsdWUnLFxuICAgICAgICB0eXBlOiAndWludCcsXG4gICAgICAgIHZhbHVlOiB0eEluZm8ucmVjaXBpZW50LmFtb3VudCxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIG5hbWU6ICd0b2tlbkNvbnRyYWN0QWRkcmVzcycsXG4gICAgICAgIHR5cGU6ICdhZGRyZXNzJyxcbiAgICAgICAgdmFsdWU6IHRoaXMudG9rZW5Db250cmFjdEFkZHJlc3MsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBuYW1lOiAnZXhwaXJlVGltZScsXG4gICAgICAgIHR5cGU6ICd1aW50JyxcbiAgICAgICAgdmFsdWU6IHR4SW5mby5leHBpcmVUaW1lLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbmFtZTogJ3NlcXVlbmNlSWQnLFxuICAgICAgICB0eXBlOiAndWludCcsXG4gICAgICAgIHZhbHVlOiB0eEluZm8uY29udHJhY3RTZXF1ZW5jZUlkLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbmFtZTogJ3NpZ25hdHVyZScsXG4gICAgICAgIHR5cGU6ICdieXRlcycsXG4gICAgICAgIHZhbHVlOiBvcHRpb25hbERlcHMuZXRoVXRpbC50b0J1ZmZlcihvcHRpb25hbERlcHMuZXRoVXRpbC5hZGRIZXhQcmVmaXgodHhJbmZvLnNpZ25hdHVyZSkpLFxuICAgICAgfSxcbiAgICBdO1xuICB9XG5cbiAgdmVyaWZ5Q29pbih0eFByZWJ1aWxkOiBUcmFuc2FjdGlvblByZWJ1aWxkKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHR4UHJlYnVpbGQuY29pbiA9PT0gdGhpcy50b2tlbkNvbmZpZy5jb2luICYmIHR4UHJlYnVpbGQudG9rZW4gPT09IHRoaXMudG9rZW5Db25maWcudHlwZTtcbiAgfVxufVxuIl19Выполнить команду
Для локальной разработки. Не используйте в интернете!