PHP WebShell

Текущая директория: /opt/BitGoJS/modules/sdk-coin-sol/dist/test/unit/transactionBuilder

Просмотр файла: stakingActivateBuilder.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;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const should_1 = __importDefault(require("should"));
const testData = __importStar(require("../../resources/sol"));
const getBuilderFactory_1 = require("../getBuilderFactory");
const src_1 = require("../../../src");
const statics_1 = require("@bitgo/statics");
describe('Sol Staking Activate Builder', () => {
    const factory = (0, getBuilderFactory_1.getBuilderFactory)('tsol');
    const stakingBuilder = () => {
        const txBuilder = factory.getStakingActivateBuilder();
        txBuilder.nonce(recentBlockHash);
        txBuilder.sender(wallet.pub);
        return txBuilder;
    };
    // not valid data
    const invalidPubKey = testData.pubKeys.invalidPubKeys[0];
    const wrongAccount = new src_1.KeyPair({ prv: testData.prvKeys.prvKey1.base58 }).getKeys();
    // valid data
    const wallet = new src_1.KeyPair(testData.authAccount).getKeys();
    const stakeAccount = new src_1.KeyPair(testData.stakeAccount).getKeys();
    const validator = testData.validator;
    const recentBlockHash = 'GHtXQBsoZHVnNFa9YevAzFr17DJjgHXk3ycTKD5xD3Zi';
    const amount = '300000';
    describe('Succeed', () => {
        it('build a create and delegate staking signed tx', async () => {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder
                .amount(amount)
                .sender(wallet.pub)
                .stakingAddress(stakeAccount.pub)
                .validator(validator.pub)
                .nonce(recentBlockHash);
            txBuilder.sign({ key: wallet.prv });
            txBuilder.sign({ key: stakeAccount.prv });
            const tx = await txBuilder.build();
            tx.inputs.length.should.equal(1);
            tx.inputs[0].should.deepEqual({
                address: wallet.pub,
                value: amount,
                coin: 'tsol',
            });
            tx.outputs.length.should.equal(1);
            const rawTx = tx.toBroadcastFormat();
            should_1.default.equal(src_1.Utils.isValidRawTransaction(rawTx), true);
            should_1.default.equal(rawTx, testData.STAKING_ACTIVATE_SIGNED_TX);
            factory.from(testData.STAKING_ACTIVATE_SIGNED_TX);
            const coin = statics_1.coins.get('tsol');
            const tx2 = new src_1.Transaction(coin);
            tx2.fromRawTransaction(rawTx);
        });
        it('Marinade: build a create staking signed tx', async () => {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder
                .amount(amount)
                .sender(wallet.pub)
                .stakingAddress(stakeAccount.pub)
                .validator(validator.pub)
                .isMarinade(true)
                .nonce(recentBlockHash);
            txBuilder.sign({ key: wallet.prv });
            txBuilder.sign({ key: stakeAccount.prv });
            const tx = await txBuilder.build();
            const txJson = tx.toJson();
            txJson.instructionsData.should.deepEqual([
                {
                    type: 'Activate',
                    params: {
                        fromAddress: wallet.pub,
                        stakingAddress: stakeAccount.pub,
                        amount: amount,
                        validator: validator.pub,
                        isMarinade: true,
                    },
                },
            ]);
            tx.inputs.length.should.equal(1);
            tx.inputs[0].should.deepEqual({
                address: wallet.pub,
                value: amount,
                coin: 'tsol',
            });
            tx.outputs.length.should.equal(1);
            const rawTx = tx.toBroadcastFormat();
            should_1.default.equal(src_1.Utils.isValidRawTransaction(rawTx), true);
            should_1.default.equal(rawTx, testData.MARINADE_STAKING_ACTIVATE_SIGNED_TX);
            factory.from(testData.MARINADE_STAKING_ACTIVATE_SIGNED_TX);
            const coin = statics_1.coins.get('tsol');
            const tx2 = new src_1.Transaction(coin);
            tx2.fromRawTransaction(rawTx);
        });
        it('build a create and delegate staking signed tx with memo', async () => {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder
                .amount(amount)
                .sender(wallet.pub)
                .stakingAddress(stakeAccount.pub)
                .validator(validator.pub)
                .memo('test memo')
                .nonce(recentBlockHash);
            txBuilder.sign({ key: wallet.prv });
            txBuilder.sign({ key: stakeAccount.prv });
            const tx = await txBuilder.build();
            tx.inputs.length.should.equal(1);
            tx.inputs[0].should.deepEqual({
                address: wallet.pub,
                value: amount,
                coin: 'tsol',
            });
            tx.outputs.length.should.equal(1);
            tx.outputs[0].should.deepEqual({
                address: stakeAccount.pub,
                value: amount,
                coin: 'tsol',
            });
            const rawTx = tx.toBroadcastFormat();
            should_1.default.equal(src_1.Utils.isValidRawTransaction(rawTx), true);
            should_1.default.equal(rawTx, testData.STAKING_ACTIVATE_SIGNED_TX_WITH_MEMO);
        });
        it('Marinade: build a create staking signed tx with memo', async () => {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder
                .amount(amount)
                .sender(wallet.pub)
                .stakingAddress(stakeAccount.pub)
                .validator(validator.pub)
                .memo('test memo')
                .isMarinade(true)
                .nonce(recentBlockHash);
            txBuilder.sign({ key: wallet.prv });
            txBuilder.sign({ key: stakeAccount.prv });
            const tx = await txBuilder.build();
            const txJson = tx.toJson();
            txJson.instructionsData.should.deepEqual([
                {
                    type: 'Memo',
                    params: {
                        memo: 'test memo',
                    },
                },
                {
                    type: 'Activate',
                    params: {
                        fromAddress: wallet.pub,
                        stakingAddress: stakeAccount.pub,
                        amount: amount,
                        validator: validator.pub,
                        isMarinade: true,
                    },
                },
            ]);
            tx.inputs.length.should.equal(1);
            tx.inputs[0].should.deepEqual({
                address: wallet.pub,
                value: amount,
                coin: 'tsol',
            });
            tx.outputs.length.should.equal(1);
            tx.outputs[0].should.deepEqual({
                address: stakeAccount.pub,
                value: amount,
                coin: 'tsol',
            });
            const rawTx = tx.toBroadcastFormat();
            should_1.default.equal(src_1.Utils.isValidRawTransaction(rawTx), true);
            should_1.default.equal(rawTx, testData.MARINADE_STAKING_ACTIVATE_SIGNED_TX_WITH_MEMO);
        });
        it('build a create and delegate staking unsigned tx', async () => {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder
                .amount(amount)
                .sender(wallet.pub)
                .stakingAddress(stakeAccount.pub)
                .validator(validator.pub)
                .nonce(recentBlockHash);
            const tx = await txBuilder.build();
            tx.inputs.length.should.equal(1);
            tx.inputs[0].should.deepEqual({
                address: wallet.pub,
                value: amount,
                coin: 'tsol',
            });
            tx.outputs.length.should.equal(1);
            const rawTx = tx.toBroadcastFormat();
            should_1.default.equal(src_1.Utils.isValidRawTransaction(rawTx), true);
            should_1.default.equal(rawTx, testData.STAKING_ACTIVATE_UNSIGNED_TX);
        });
        it('Marinade: build a create staking unsigned tx', async () => {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder
                .amount(amount)
                .sender(wallet.pub)
                .stakingAddress(stakeAccount.pub)
                .validator(validator.pub)
                .isMarinade(true)
                .nonce(recentBlockHash);
            const tx = await txBuilder.build();
            const txJson = tx.toJson();
            txJson.instructionsData.should.deepEqual([
                {
                    type: 'Activate',
                    params: {
                        fromAddress: wallet.pub,
                        stakingAddress: stakeAccount.pub,
                        amount: amount,
                        validator: validator.pub,
                        isMarinade: true,
                    },
                },
            ]);
            tx.inputs.length.should.equal(1);
            tx.inputs[0].should.deepEqual({
                address: wallet.pub,
                value: amount,
                coin: 'tsol',
            });
            tx.outputs.length.should.equal(1);
            const rawTx = tx.toBroadcastFormat();
            should_1.default.equal(src_1.Utils.isValidRawTransaction(rawTx), true);
            should_1.default.equal(rawTx, testData.MARINADE_STAKING_ACTIVATE_UNSIGNED_TX);
        });
        it('build a create and delegate staking unsigned tx with memo', async () => {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder
                .amount(amount)
                .sender(wallet.pub)
                .stakingAddress(stakeAccount.pub)
                .validator(validator.pub)
                .memo('test memo')
                .nonce(recentBlockHash);
            const tx = await txBuilder.build();
            tx.inputs.length.should.equal(1);
            tx.inputs[0].should.deepEqual({
                address: wallet.pub,
                value: amount,
                coin: 'tsol',
            });
            tx.outputs.length.should.equal(1);
            const rawTx = tx.toBroadcastFormat();
            should_1.default.equal(src_1.Utils.isValidRawTransaction(rawTx), true);
            should_1.default.equal(rawTx, testData.STAKING_ACTIVATE_UNSIGNED_TX_WITH_MEMO);
        });
        it('Marinade: build a create staking unsigned tx with memo', async () => {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder
                .amount(amount)
                .sender(wallet.pub)
                .stakingAddress(stakeAccount.pub)
                .validator(validator.pub)
                .memo('test memo')
                .isMarinade(true)
                .nonce(recentBlockHash);
            const tx = await txBuilder.build();
            const txJson = tx.toJson();
            txJson.instructionsData.should.deepEqual([
                {
                    type: 'Memo',
                    params: {
                        memo: 'test memo',
                    },
                },
                {
                    type: 'Activate',
                    params: {
                        fromAddress: wallet.pub,
                        stakingAddress: stakeAccount.pub,
                        amount: amount,
                        validator: validator.pub,
                        isMarinade: true,
                    },
                },
            ]);
            tx.inputs.length.should.equal(1);
            tx.inputs[0].should.deepEqual({
                address: wallet.pub,
                value: amount,
                coin: 'tsol',
            });
            tx.outputs.length.should.equal(1);
            const rawTx = tx.toBroadcastFormat();
            should_1.default.equal(src_1.Utils.isValidRawTransaction(rawTx), true);
            should_1.default.equal(rawTx, testData.MARINADE_STAKING_ACTIVATE_UNSIGNED_TX_WITH_MEMO);
        });
    });
    describe('Fail', () => {
        it('for invalid sender address', () => {
            const txBuilder = stakingBuilder();
            (0, should_1.default)(() => txBuilder.sender(invalidPubKey)).throwError('Invalid or missing sender, got: ' + invalidPubKey);
        });
        it('for invalid staking address', () => {
            const txBuilder = stakingBuilder();
            (0, should_1.default)(() => txBuilder.stakingAddress(invalidPubKey)).throwError('Invalid or missing stakingAddress, got: ' + invalidPubKey);
        });
        it('for invalid validator address', () => {
            const txBuilder = stakingBuilder();
            (0, should_1.default)(() => txBuilder.validator(invalidPubKey)).throwError('Invalid or missing validator, got: ' + invalidPubKey);
        });
        it('build a staking activate tx when amount is invalid', () => {
            const txBuilder = stakingBuilder();
            (0, should_1.default)(() => txBuilder.amount('randomstring')).throwError('Value cannot be zero or less');
        });
        it('build a staking activate tx when amount is less than zero', () => {
            const txBuilder = stakingBuilder();
            (0, should_1.default)(() => txBuilder.amount('-1')).throwError('Value cannot be zero or less');
        });
        it('build a staking activate tx when amount is equal to zero', () => {
            const txBuilder = stakingBuilder();
            (0, should_1.default)(() => txBuilder.amount('0')).throwError('Value cannot be zero or less');
        });
        it('build a staking activate tx and sign with an incorrect account', async () => {
            const txBuilder = stakingBuilder();
            txBuilder.sender(wallet.pub);
            txBuilder.stakingAddress(stakeAccount.pub);
            txBuilder.validator(validator.pub);
            txBuilder.amount(amount);
            txBuilder.sign({ key: wrongAccount.prv });
            await txBuilder.build().should.rejectedWith('unknown signer: CP5Dpaa42RtJmMuKqCQsLwma5Yh3knuvKsYDFX85F41S');
        });
        it('build a staking activate tx with the same sender and staking address', async () => {
            const txBuilder = stakingBuilder();
            txBuilder.sender(wallet.pub);
            txBuilder.stakingAddress(wallet.pub);
            txBuilder.validator(validator.pub);
            txBuilder.amount(amount);
            txBuilder.sign({ key: wrongAccount.prv });
            await txBuilder.build().should.rejectedWith('Sender address cannot be the same as the Staking address');
        });
        it('build when nonce is not provided', async () => {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder.sender(wallet.pub);
            txBuilder.stakingAddress(stakeAccount.pub);
            txBuilder.amount(amount);
            txBuilder.validator(validator.pub);
            txBuilder.sign({ key: wallet.prv });
            await txBuilder.build().should.rejectedWith('Invalid transaction: missing nonce blockhash');
        });
        it('build when sender is not provided', async () => {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder.stakingAddress(stakeAccount.pub);
            txBuilder.amount(amount);
            txBuilder.validator(validator.pub);
            txBuilder.nonce(recentBlockHash);
            txBuilder.sign({ key: wallet.prv });
            await txBuilder.build().should.rejectedWith('Invalid transaction: missing sender');
        });
        it('build when stakingAddress is not provided', async () => {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder.sender(wallet.pub);
            txBuilder.amount(amount);
            txBuilder.validator(validator.pub);
            txBuilder.nonce(recentBlockHash);
            txBuilder.sign({ key: wallet.prv });
            await txBuilder.build().should.rejectedWith('Staking Address must be set before building the transaction');
        });
        it('build when validator is not provided', async () => {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder.stakingAddress(stakeAccount.pub);
            txBuilder.sender(wallet.pub);
            txBuilder.amount(amount);
            txBuilder.nonce(recentBlockHash);
            txBuilder.sign({ key: wallet.prv });
            await txBuilder.build().should.rejectedWith('Validator must be set before building the transaction');
        });
        it('to sign twice with the same key', () => {
            const txBuilder = factory.from(testData.STAKING_ACTIVATE_UNSIGNED_TX);
            txBuilder.sign({ key: wallet.prv });
            (0, should_1.default)(() => txBuilder.sign({ key: wallet.prv })).throwError('Duplicated signer: ' + wallet.prv?.toString());
        });
    });
    describe('From and sign', () => {
        describe('Succeed', () => {
            it('build from an unsigned staking activate and sign it', async () => {
                const txBuilder = factory.from(testData.STAKING_ACTIVATE_UNSIGNED_TX);
                txBuilder.sign({ key: wallet.prv });
                txBuilder.sign({ key: stakeAccount.prv });
                const tx = await txBuilder.build();
                tx.inputs.length.should.equal(1);
                tx.inputs[0].should.deepEqual({
                    address: wallet.pub,
                    value: amount,
                    coin: 'tsol',
                });
                tx.outputs.length.should.equal(1);
                const rawTx = tx.toBroadcastFormat();
                should_1.default.equal(src_1.Utils.isValidRawTransaction(rawTx), true);
                should_1.default.equal(rawTx, testData.STAKING_ACTIVATE_SIGNED_TX);
            });
            it('Marinade: build from an unsigned staking activate and sign it', async () => {
                const txBuilder = factory.from(testData.MARINADE_STAKING_ACTIVATE_UNSIGNED_TX);
                txBuilder.sign({ key: wallet.prv });
                txBuilder.sign({ key: stakeAccount.prv });
                const tx = await txBuilder.build();
                tx.inputs.length.should.equal(1);
                tx.inputs[0].should.deepEqual({
                    address: wallet.pub,
                    value: amount,
                    coin: 'tsol',
                });
                tx.outputs.length.should.equal(1);
                const rawTx = tx.toBroadcastFormat();
                should_1.default.equal(src_1.Utils.isValidRawTransaction(rawTx), true);
                should_1.default.equal(rawTx, testData.MARINADE_STAKING_ACTIVATE_SIGNED_TX);
            });
            it('build from an unsigned staking activate with memo and sign it', async () => {
                const txBuilder = factory.from(testData.STAKING_ACTIVATE_UNSIGNED_TX_WITH_MEMO);
                txBuilder.sign({ key: wallet.prv });
                txBuilder.sign({ key: stakeAccount.prv });
                const tx = await txBuilder.build();
                tx.inputs.length.should.equal(1);
                tx.inputs[0].should.deepEqual({
                    address: wallet.pub,
                    value: amount,
                    coin: 'tsol',
                });
                tx.outputs.length.should.equal(1);
                const rawTx = tx.toBroadcastFormat();
                should_1.default.equal(src_1.Utils.isValidRawTransaction(rawTx), true);
                should_1.default.equal(rawTx, testData.STAKING_ACTIVATE_SIGNED_TX_WITH_MEMO);
            });
        });
        describe('Fail', () => {
            it('build from an unsigned staking activate and fail to sign it', async () => {
                const txBuilder = factory.from(testData.STAKING_ACTIVATE_UNSIGNED_TX);
                txBuilder.sign({ key: wrongAccount.prv });
                await txBuilder.build().should.rejectedWith('unknown signer: CP5Dpaa42RtJmMuKqCQsLwma5Yh3knuvKsYDFX85F41S');
            });
            it('build from a signed staking activate and fail to sign it', async () => {
                const txBuilder = factory.from(testData.STAKING_ACTIVATE_SIGNED_TX);
                txBuilder.sign({ key: wrongAccount.prv });
                await txBuilder.build().should.rejectedWith('unknown signer: CP5Dpaa42RtJmMuKqCQsLwma5Yh3knuvKsYDFX85F41S');
            });
        });
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Rha2luZ0FjdGl2YXRlQnVpbGRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Rlc3QvdW5pdC90cmFuc2FjdGlvbkJ1aWxkZXIvc3Rha2luZ0FjdGl2YXRlQnVpbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG9EQUE0QjtBQUU1Qiw4REFBZ0Q7QUFDaEQsNERBQXlEO0FBQ3pELHNDQUEyRDtBQUMzRCw0Q0FBdUM7QUFFdkMsUUFBUSxDQUFDLDhCQUE4QixFQUFFLEdBQUcsRUFBRTtJQUM1QyxNQUFNLE9BQU8sR0FBRyxJQUFBLHFDQUFpQixFQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRTFDLE1BQU0sY0FBYyxHQUFHLEdBQUcsRUFBRTtRQUMxQixNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMseUJBQXlCLEVBQUUsQ0FBQztRQUN0RCxTQUFTLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ2pDLFNBQVMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdCLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUMsQ0FBQztJQUVGLGlCQUFpQjtJQUNqQixNQUFNLGFBQWEsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6RCxNQUFNLFlBQVksR0FBRyxJQUFJLGFBQU8sQ0FBQyxFQUFFLEdBQUcsRUFBRSxRQUFRLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBRXJGLGFBQWE7SUFDYixNQUFNLE1BQU0sR0FBRyxJQUFJLGFBQU8sQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDM0QsTUFBTSxZQUFZLEdBQUcsSUFBSSxhQUFPLENBQUMsUUFBUSxDQUFDLFlBQVks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O0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgc2hvdWxkIGZyb20gJ3Nob3VsZCc7XG5cbmltcG9ydCAqIGFzIHRlc3REYXRhIGZyb20gJy4uLy4uL3Jlc291cmNlcy9zb2wnO1xuaW1wb3J0IHsgZ2V0QnVpbGRlckZhY3RvcnkgfSBmcm9tICcuLi9nZXRCdWlsZGVyRmFjdG9yeSc7XG5pbXBvcnQgeyBLZXlQYWlyLCBVdGlscywgVHJhbnNhY3Rpb24gfSBmcm9tICcuLi8uLi8uLi9zcmMnO1xuaW1wb3J0IHsgY29pbnMgfSBmcm9tICdAYml0Z28vc3RhdGljcyc7XG5cbmRlc2NyaWJlKCdTb2wgU3Rha2luZyBBY3RpdmF0ZSBCdWlsZGVyJywgKCkgPT4ge1xuICBjb25zdCBmYWN0b3J5ID0gZ2V0QnVpbGRlckZhY3RvcnkoJ3Rzb2wnKTtcblxuICBjb25zdCBzdGFraW5nQnVpbGRlciA9ICgpID0+IHtcbiAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFN0YWtpbmdBY3RpdmF0ZUJ1aWxkZXIoKTtcbiAgICB0eEJ1aWxkZXIubm9uY2UocmVjZW50QmxvY2tIYXNoKTtcbiAgICB0eEJ1aWxkZXIuc2VuZGVyKHdhbGxldC5wdWIpO1xuICAgIHJldHVybiB0eEJ1aWxkZXI7XG4gIH07XG5cbiAgLy8gbm90IHZhbGlkIGRhdGFcbiAgY29uc3QgaW52YWxpZFB1YktleSA9IHRlc3REYXRhLnB1YktleXMuaW52YWxpZFB1YktleXNbMF07XG4gIGNvbnN0IHdyb25nQWNjb3VudCA9IG5ldyBLZXlQYWlyKHsgcHJ2OiB0ZXN0RGF0YS5wcnZLZXlzLnBydktleTEuYmFzZTU4IH0pLmdldEtleXMoKTtcblxuICAvLyB2YWxpZCBkYXRhXG4gIGNvbnN0IHdhbGxldCA9IG5ldyBLZXlQYWlyKHRlc3REYXRhLmF1dGhBY2NvdW50KS5nZXRLZXlzKCk7XG4gIGNvbnN0IHN0YWtlQWNjb3VudCA9IG5ldyBLZXlQYWlyKHRlc3REYXRhLnN0YWtlQWNjb3VudCkuZ2V0S2V5cygpO1xuICBjb25zdCB2YWxpZGF0b3IgPSB0ZXN0RGF0YS52YWxpZGF0b3I7XG5cbiAgY29uc3QgcmVjZW50QmxvY2tIYXNoID0gJ0dIdFhRQnNvWkhWbk5GYTlZZXZBekZyMTdESmpnSFhrM3ljVEtENXhEM1ppJztcbiAgY29uc3QgYW1vdW50ID0gJzMwMDAwMCc7XG5cbiAgZGVzY3JpYmUoJ1N1Y2NlZWQnLCAoKSA9PiB7XG4gICAgaXQoJ2J1aWxkIGEgY3JlYXRlIGFuZCBkZWxlZ2F0ZSBzdGFraW5nIHNpZ25lZCB0eCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0U3Rha2luZ0FjdGl2YXRlQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyXG4gICAgICAgIC5hbW91bnQoYW1vdW50KVxuICAgICAgICAuc2VuZGVyKHdhbGxldC5wdWIpXG4gICAgICAgIC5zdGFraW5nQWRkcmVzcyhzdGFrZUFjY291bnQucHViKVxuICAgICAgICAudmFsaWRhdG9yKHZhbGlkYXRvci5wdWIpXG4gICAgICAgIC5ub25jZShyZWNlbnRCbG9ja0hhc2gpO1xuICAgICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IHdhbGxldC5wcnYgfSk7XG4gICAgICB0eEJ1aWxkZXIuc2lnbih7IGtleTogc3Rha2VBY2NvdW50LnBydiB9KTtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICB0eC5pbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHR4LmlucHV0c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogd2FsbGV0LnB1YixcbiAgICAgICAgdmFsdWU6IGFtb3VudCxcbiAgICAgICAgY29pbjogJ3Rzb2wnLFxuICAgICAgfSk7XG4gICAgICB0eC5vdXRwdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwoVXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG4gICAgICBzaG91bGQuZXF1YWwocmF3VHgsIHRlc3REYXRhLlNUQUtJTkdfQUNUSVZBVEVfU0lHTkVEX1RYKTtcbiAgICAgIGZhY3RvcnkuZnJvbSh0ZXN0RGF0YS5TVEFLSU5HX0FDVElWQVRFX1NJR05FRF9UWCk7XG4gICAgICBjb25zdCBjb2luID0gY29pbnMuZ2V0KCd0c29sJyk7XG4gICAgICBjb25zdCB0eDIgPSBuZXcgVHJhbnNhY3Rpb24oY29pbik7XG4gICAgICB0eDIuZnJvbVJhd1RyYW5zYWN0aW9uKHJhd1R4KTtcbiAgICB9KTtcblxuICAgIGl0KCdNYXJpbmFkZTogYnVpbGQgYSBjcmVhdGUgc3Rha2luZyBzaWduZWQgdHgnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFN0YWtpbmdBY3RpdmF0ZUJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlclxuICAgICAgICAuYW1vdW50KGFtb3VudClcbiAgICAgICAgLnNlbmRlcih3YWxsZXQucHViKVxuICAgICAgICAuc3Rha2luZ0FkZHJlc3Moc3Rha2VBY2NvdW50LnB1YilcbiAgICAgICAgLnZhbGlkYXRvcih2YWxpZGF0b3IucHViKVxuICAgICAgICAuaXNNYXJpbmFkZSh0cnVlKVxuICAgICAgICAubm9uY2UocmVjZW50QmxvY2tIYXNoKTtcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiB3YWxsZXQucHJ2IH0pO1xuICAgICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IHN0YWtlQWNjb3VudC5wcnYgfSk7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG4gICAgICB0eEpzb24uaW5zdHJ1Y3Rpb25zRGF0YS5zaG91bGQuZGVlcEVxdWFsKFtcbiAgICAgICAge1xuICAgICAgICAgIHR5cGU6ICdBY3RpdmF0ZScsXG4gICAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgICBmcm9tQWRkcmVzczogd2FsbGV0LnB1YixcbiAgICAgICAgICAgIHN0YWtpbmdBZGRyZXNzOiBzdGFrZUFjY291bnQucHViLFxuICAgICAgICAgICAgYW1vdW50OiBhbW91bnQsXG4gICAgICAgICAgICB2YWxpZGF0b3I6IHZhbGlkYXRvci5wdWIsXG4gICAgICAgICAgICBpc01hcmluYWRlOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdKTtcbiAgICAgIHR4LmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHguaW5wdXRzWzBdLnNob3VsZC5kZWVwRXF1YWwoe1xuICAgICAgICBhZGRyZXNzOiB3YWxsZXQucHViLFxuICAgICAgICB2YWx1ZTogYW1vdW50LFxuICAgICAgICBjb2luOiAndHNvbCcsXG4gICAgICB9KTtcbiAgICAgIHR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbChVdGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICAgIHNob3VsZC5lcXVhbChyYXdUeCwgdGVzdERhdGEuTUFSSU5BREVfU1RBS0lOR19BQ1RJVkFURV9TSUdORURfVFgpO1xuICAgICAgZmFjdG9yeS5mcm9tKHRlc3REYXRhLk1BUklOQURFX1NUQUtJTkdfQUNUSVZBVEVfU0lHTkVEX1RYKTtcbiAgICAgIGNvbnN0IGNvaW4gPSBjb2lucy5nZXQoJ3Rzb2wnKTtcbiAgICAgIGNvbnN0IHR4MiA9IG5ldyBUcmFuc2FjdGlvbihjb2luKTtcbiAgICAgIHR4Mi5mcm9tUmF3VHJhbnNhY3Rpb24ocmF3VHgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2J1aWxkIGEgY3JlYXRlIGFuZCBkZWxlZ2F0ZSBzdGFraW5nIHNpZ25lZCB0eCB3aXRoIG1lbW8nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFN0YWtpbmdBY3RpdmF0ZUJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlclxuICAgICAgICAuYW1vdW50KGFtb3VudClcbiAgICAgICAgLnNlbmRlcih3YWxsZXQucHViKVxuICAgICAgICAuc3Rha2luZ0FkZHJlc3Moc3Rha2VBY2NvdW50LnB1YilcbiAgICAgICAgLnZhbGlkYXRvcih2YWxpZGF0b3IucHViKVxuICAgICAgICAubWVtbygndGVzdCBtZW1vJylcbiAgICAgICAgLm5vbmNlKHJlY2VudEJsb2NrSGFzaCk7XG4gICAgICB0eEJ1aWxkZXIuc2lnbih7IGtleTogd2FsbGV0LnBydiB9KTtcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBzdGFrZUFjY291bnQucHJ2IH0pO1xuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHR4LmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHguaW5wdXRzWzBdLnNob3VsZC5kZWVwRXF1YWwoe1xuICAgICAgICBhZGRyZXNzOiB3YWxsZXQucHViLFxuICAgICAgICB2YWx1ZTogYW1vdW50LFxuICAgICAgICBjb2luOiAndHNvbCcsXG4gICAgICB9KTtcbiAgICAgIHR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHR4Lm91dHB1dHNbMF0uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGFkZHJlc3M6IHN0YWtlQWNjb3VudC5wdWIsXG4gICAgICAgIHZhbHVlOiBhbW91bnQsXG4gICAgICAgIGNvaW46ICd0c29sJyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKFV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgICAgc2hvdWxkLmVxdWFsKHJhd1R4LCB0ZXN0RGF0YS5TVEFLSU5HX0FDVElWQVRFX1NJR05FRF9UWF9XSVRIX01FTU8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ01hcmluYWRlOiBidWlsZCBhIGNyZWF0ZSBzdGFraW5nIHNpZ25lZCB0eCB3aXRoIG1lbW8nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFN0YWtpbmdBY3RpdmF0ZUJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlclxuICAgICAgICAuYW1vdW50KGFtb3VudClcbiAgICAgICAgLnNlbmRlcih3YWxsZXQucHViKVxuICAgICAgICAuc3Rha2luZ0FkZHJlc3Moc3Rha2VBY2NvdW50LnB1YilcbiAgICAgICAgLnZhbGlkYXRvcih2YWxpZGF0b3IucHViKVxuICAgICAgICAubWVtbygndGVzdCBtZW1vJylcbiAgICAgICAgLmlzTWFyaW5hZGUodHJ1ZSlcbiAgICAgICAgLm5vbmNlKHJlY2VudEJsb2NrSGFzaCk7XG4gICAgICB0eEJ1aWxkZXIuc2lnbih7IGtleTogd2FsbGV0LnBydiB9KTtcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBzdGFrZUFjY291bnQucHJ2IH0pO1xuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IHR4SnNvbiA9IHR4LnRvSnNvbigpO1xuICAgICAgdHhKc29uLmluc3RydWN0aW9uc0RhdGEuc2hvdWxkLmRlZXBFcXVhbChbXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiAnTWVtbycsXG4gICAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgICBtZW1vOiAndGVzdCBtZW1vJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgdHlwZTogJ0FjdGl2YXRlJyxcbiAgICAgICAgICBwYXJhbXM6IHtcbiAgICAgICAgICAgIGZyb21BZGRyZXNzOiB3YWxsZXQucHViLFxuICAgICAgICAgICAgc3Rha2luZ0FkZHJlc3M6IHN0YWtlQWNjb3VudC5wdWIsXG4gICAgICAgICAgICBhbW91bnQ6IGFtb3VudCxcbiAgICAgICAgICAgIHZhbGlkYXRvcjogdmFsaWRhdG9yLnB1YixcbiAgICAgICAgICAgIGlzTWFyaW5hZGU6IHRydWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0pO1xuICAgICAgdHguaW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICB0eC5pbnB1dHNbMF0uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGFkZHJlc3M6IHdhbGxldC5wdWIsXG4gICAgICAgIHZhbHVlOiBhbW91bnQsXG4gICAgICAgIGNvaW46ICd0c29sJyxcbiAgICAgIH0pO1xuICAgICAgdHgub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHgub3V0cHV0c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogc3Rha2VBY2NvdW50LnB1YixcbiAgICAgICAgdmFsdWU6IGFtb3VudCxcbiAgICAgICAgY29pbjogJ3Rzb2wnLFxuICAgICAgfSk7XG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwoVXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG4gICAgICBzaG91bGQuZXF1YWwocmF3VHgsIHRlc3REYXRhLk1BUklOQURFX1NUQUtJTkdfQUNUSVZBVEVfU0lHTkVEX1RYX1dJVEhfTUVNTyk7XG4gICAgfSk7XG5cbiAgICBpdCgnYnVpbGQgYSBjcmVhdGUgYW5kIGRlbGVnYXRlIHN0YWtpbmcgdW5zaWduZWQgdHgnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFN0YWtpbmdBY3RpdmF0ZUJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlclxuICAgICAgICAuYW1vdW50KGFtb3VudClcbiAgICAgICAgLnNlbmRlcih3YWxsZXQucHViKVxuICAgICAgICAuc3Rha2luZ0FkZHJlc3Moc3Rha2VBY2NvdW50LnB1YilcbiAgICAgICAgLnZhbGlkYXRvcih2YWxpZGF0b3IucHViKVxuICAgICAgICAubm9uY2UocmVjZW50QmxvY2tIYXNoKTtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICB0eC5pbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHR4LmlucHV0c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogd2FsbGV0LnB1YixcbiAgICAgICAgdmFsdWU6IGFtb3VudCxcbiAgICAgICAgY29pbjogJ3Rzb2wnLFxuICAgICAgfSk7XG4gICAgICB0eC5vdXRwdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwoVXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG4gICAgICBzaG91bGQuZXF1YWwocmF3VHgsIHRlc3REYXRhLlNUQUtJTkdfQUNUSVZBVEVfVU5TSUdORURfVFgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ01hcmluYWRlOiBidWlsZCBhIGNyZWF0ZSBzdGFraW5nIHVuc2lnbmVkIHR4JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRTdGFraW5nQWN0aXZhdGVCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXJcbiAgICAgICAgLmFtb3VudChhbW91bnQpXG4gICAgICAgIC5zZW5kZXIod2FsbGV0LnB1YilcbiAgICAgICAgLnN0YWtpbmdBZGRyZXNzKHN0YWtlQWNjb3VudC5wdWIpXG4gICAgICAgIC52YWxpZGF0b3IodmFsaWRhdG9yLnB1YilcbiAgICAgICAgLmlzTWFyaW5hZGUodHJ1ZSlcbiAgICAgICAgLm5vbmNlKHJlY2VudEJsb2NrSGFzaCk7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG4gICAgICB0eEpzb24uaW5zdHJ1Y3Rpb25zRGF0YS5zaG91bGQuZGVlcEVxdWFsKFtcbiAgICAgICAge1xuICAgICAgICAgIHR5cGU6ICdBY3RpdmF0ZScsXG4gICAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgICBmcm9tQWRkcmVzczogd2FsbGV0LnB1YixcbiAgICAgICAgICAgIHN0YWtpbmdBZGRyZXNzOiBzdGFrZUFjY291bnQucHViLFxuICAgICAgICAgICAgYW1vdW50OiBhbW91bnQsXG4gICAgICAgICAgICB2YWxpZGF0b3I6IHZhbGlkYXRvci5wdWIsXG4gICAgICAgICAgICBpc01hcmluYWRlOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdKTtcbiAgICAgIHR4LmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHguaW5wdXRzWzBdLnNob3VsZC5kZWVwRXF1YWwoe1xuICAgICAgICBhZGRyZXNzOiB3YWxsZXQucHViLFxuICAgICAgICB2YWx1ZTogYW1vdW50LFxuICAgICAgICBjb2luOiAndHNvbCcsXG4gICAgICB9KTtcbiAgICAgIHR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbChVdGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICAgIHNob3VsZC5lcXVhbChyYXdUeCwgdGVzdERhdGEuTUFSSU5BREVfU1RBS0lOR19BQ1RJVkFURV9VTlNJR05FRF9UWCk7XG4gICAgfSk7XG5cbiAgICBpdCgnYnVpbGQgYSBjcmVhdGUgYW5kIGRlbGVnYXRlIHN0YWtpbmcgdW5zaWduZWQgdHggd2l0aCBtZW1vJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRTdGFraW5nQWN0aXZhdGVCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXJcbiAgICAgICAgLmFtb3VudChhbW91bnQpXG4gICAgICAgIC5zZW5kZXIod2FsbGV0LnB1YilcbiAgICAgICAgLnN0YWtpbmdBZGRyZXNzKHN0YWtlQWNjb3VudC5wdWIpXG4gICAgICAgIC52YWxpZGF0b3IodmFsaWRhdG9yLnB1YilcbiAgICAgICAgLm1lbW8oJ3Rlc3QgbWVtbycpXG4gICAgICAgIC5ub25jZShyZWNlbnRCbG9ja0hhc2gpO1xuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHR4LmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHguaW5wdXRzWzBdLnNob3VsZC5kZWVwRXF1YWwoe1xuICAgICAgICBhZGRyZXNzOiB3YWxsZXQucHViLFxuICAgICAgICB2YWx1ZTogYW1vdW50LFxuICAgICAgICBjb2luOiAndHNvbCcsXG4gICAgICB9KTtcbiAgICAgIHR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbChVdGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICAgIHNob3VsZC5lcXVhbChyYXdUeCwgdGVzdERhdGEuU1RBS0lOR19BQ1RJVkFURV9VTlNJR05FRF9UWF9XSVRIX01FTU8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ01hcmluYWRlOiBidWlsZCBhIGNyZWF0ZSBzdGFraW5nIHVuc2lnbmVkIHR4IHdpdGggbWVtbycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0U3Rha2luZ0FjdGl2YXRlQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyXG4gICAgICAgIC5hbW91bnQoYW1vdW50KVxuICAgICAgICAuc2VuZGVyKHdhbGxldC5wdWIpXG4gICAgICAgIC5zdGFraW5nQWRkcmVzcyhzdGFrZUFjY291bnQucHViKVxuICAgICAgICAudmFsaWRhdG9yKHZhbGlkYXRvci5wdWIpXG4gICAgICAgIC5tZW1vKCd0ZXN0IG1lbW8nKVxuICAgICAgICAuaXNNYXJpbmFkZSh0cnVlKVxuICAgICAgICAubm9uY2UocmVjZW50QmxvY2tIYXNoKTtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcbiAgICAgIHR4SnNvbi5pbnN0cnVjdGlvbnNEYXRhLnNob3VsZC5kZWVwRXF1YWwoW1xuICAgICAgICB7XG4gICAgICAgICAgdHlwZTogJ01lbW8nLFxuICAgICAgICAgIHBhcmFtczoge1xuICAgICAgICAgICAgbWVtbzogJ3Rlc3QgbWVtbycsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHR5cGU6ICdBY3RpdmF0ZScsXG4gICAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgICBmcm9tQWRkcmVzczogd2FsbGV0LnB1YixcbiAgICAgICAgICAgIHN0YWtpbmdBZGRyZXNzOiBzdGFrZUFjY291bnQucHViLFxuICAgICAgICAgICAgYW1vdW50OiBhbW91bnQsXG4gICAgICAgICAgICB2YWxpZGF0b3I6IHZhbGlkYXRvci5wdWIsXG4gICAgICAgICAgICBpc01hcmluYWRlOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdKTtcbiAgICAgIHR4LmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHguaW5wdXRzWzBdLnNob3VsZC5kZWVwRXF1YWwoe1xuICAgICAgICBhZGRyZXNzOiB3YWxsZXQucHViLFxuICAgICAgICB2YWx1ZTogYW1vdW50LFxuICAgICAgICBjb2luOiAndHNvbCcsXG4gICAgICB9KTtcbiAgICAgIHR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbChVdGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICAgIHNob3VsZC5lcXVhbChyYXdUeCwgdGVzdERhdGEuTUFSSU5BREVfU1RBS0lOR19BQ1RJVkFURV9VTlNJR05FRF9UWF9XSVRIX01FTU8pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnRmFpbCcsICgpID0+IHtcbiAgICBpdCgnZm9yIGludmFsaWQgc2VuZGVyIGFkZHJlc3MnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBzdGFraW5nQnVpbGRlcigpO1xuICAgICAgc2hvdWxkKCgpID0+IHR4QnVpbGRlci5zZW5kZXIoaW52YWxpZFB1YktleSkpLnRocm93RXJyb3IoJ0ludmFsaWQgb3IgbWlzc2luZyBzZW5kZXIsIGdvdDogJyArIGludmFsaWRQdWJLZXkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2ZvciBpbnZhbGlkIHN0YWtpbmcgYWRkcmVzcycsICgpID0+IHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IHN0YWtpbmdCdWlsZGVyKCk7XG4gICAgICBzaG91bGQoKCkgPT4gdHhCdWlsZGVyLnN0YWtpbmdBZGRyZXNzKGludmFsaWRQdWJLZXkpKS50aHJvd0Vycm9yKFxuICAgICAgICAnSW52YWxpZCBvciBtaXNzaW5nIHN0YWtpbmdBZGRyZXNzLCBnb3Q6ICcgKyBpbnZhbGlkUHViS2V5XG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ2ZvciBpbnZhbGlkIHZhbGlkYXRvciBhZGRyZXNzJywgKCkgPT4ge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gc3Rha2luZ0J1aWxkZXIoKTtcbiAgICAgIHNob3VsZCgoKSA9PiB0eEJ1aWxkZXIudmFsaWRhdG9yKGludmFsaWRQdWJLZXkpKS50aHJvd0Vycm9yKFxuICAgICAgICAnSW52YWxpZCBvciBtaXNzaW5nIHZhbGlkYXRvciwgZ290OiAnICsgaW52YWxpZFB1YktleVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdidWlsZCBhIHN0YWtpbmcgYWN0aXZhdGUgdHggd2hlbiBhbW91bnQgaXMgaW52YWxpZCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IHN0YWtpbmdCdWlsZGVyKCk7XG4gICAgICBzaG91bGQoKCkgPT4gdHhCdWlsZGVyLmFtb3VudCgncmFuZG9tc3RyaW5nJykpLnRocm93RXJyb3IoJ1ZhbHVlIGNhbm5vdCBiZSB6ZXJvIG9yIGxlc3MnKTtcbiAgICB9KTtcblxuICAgIGl0KCdidWlsZCBhIHN0YWtpbmcgYWN0aXZhdGUgdHggd2hlbiBhbW91bnQgaXMgbGVzcyB0aGFuIHplcm8nLCAoKSA9PiB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBzdGFraW5nQnVpbGRlcigpO1xuICAgICAgc2hvdWxkKCgpID0+IHR4QnVpbGRlci5hbW91bnQoJy0xJykpLnRocm93RXJyb3IoJ1ZhbHVlIGNhbm5vdCBiZSB6ZXJvIG9yIGxlc3MnKTtcbiAgICB9KTtcblxuICAgIGl0KCdidWlsZCBhIHN0YWtpbmcgYWN0aXZhdGUgdHggd2hlbiBhbW91bnQgaXMgZXF1YWwgdG8gemVybycsICgpID0+IHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IHN0YWtpbmdCdWlsZGVyKCk7XG4gICAgICBzaG91bGQoKCkgPT4gdHhCdWlsZGVyLmFtb3VudCgnMCcpKS50aHJvd0Vycm9yKCdWYWx1ZSBjYW5ub3QgYmUgemVybyBvciBsZXNzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnYnVpbGQgYSBzdGFraW5nIGFjdGl2YXRlIHR4IGFuZCBzaWduIHdpdGggYW4gaW5jb3JyZWN0IGFjY291bnQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBzdGFraW5nQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih3YWxsZXQucHViKTtcbiAgICAgIHR4QnVpbGRlci5zdGFraW5nQWRkcmVzcyhzdGFrZUFjY291bnQucHViKTtcbiAgICAgIHR4QnVpbGRlci52YWxpZGF0b3IodmFsaWRhdG9yLnB1Yik7XG4gICAgICB0eEJ1aWxkZXIuYW1vdW50KGFtb3VudCk7XG4gICAgICB0eEJ1aWxkZXIuc2lnbih7IGtleTogd3JvbmdBY2NvdW50LnBydiB9KTtcbiAgICAgIGF3YWl0IHR4QnVpbGRlci5idWlsZCgpLnNob3VsZC5yZWplY3RlZFdpdGgoJ3Vua25vd24gc2lnbmVyOiBDUDVEcGFhNDJSdEptTXVLcUNRc0x3bWE1WWgza251dktzWURGWDg1RjQxUycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2J1aWxkIGEgc3Rha2luZyBhY3RpdmF0ZSB0eCB3aXRoIHRoZSBzYW1lIHNlbmRlciBhbmQgc3Rha2luZyBhZGRyZXNzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gc3Rha2luZ0J1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIod2FsbGV0LnB1Yik7XG4gICAgICB0eEJ1aWxkZXIuc3Rha2luZ0FkZHJlc3Mod2FsbGV0LnB1Yik7XG4gICAgICB0eEJ1aWxkZXIudmFsaWRhdG9yKHZhbGlkYXRvci5wdWIpO1xuICAgICAgdHhCdWlsZGVyLmFtb3VudChhbW91bnQpO1xuICAgICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IHdyb25nQWNjb3VudC5wcnYgfSk7XG4gICAgICBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKS5zaG91bGQucmVqZWN0ZWRXaXRoKCdTZW5kZXIgYWRkcmVzcyBjYW5ub3QgYmUgdGhlIHNhbWUgYXMgdGhlIFN0YWtpbmcgYWRkcmVzcycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2J1aWxkIHdoZW4gbm9uY2UgaXMgbm90IHByb3ZpZGVkJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRTdGFraW5nQWN0aXZhdGVCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHdhbGxldC5wdWIpO1xuICAgICAgdHhCdWlsZGVyLnN0YWtpbmdBZGRyZXNzKHN0YWtlQWNjb3VudC5wdWIpO1xuICAgICAgdHhCdWlsZGVyLmFtb3VudChhbW91bnQpO1xuICAgICAgdHhCdWlsZGVyLnZhbGlkYXRvcih2YWxpZGF0b3IucHViKTtcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiB3YWxsZXQucHJ2IH0pO1xuICAgICAgYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkuc2hvdWxkLnJlamVjdGVkV2l0aCgnSW52YWxpZCB0cmFuc2FjdGlvbjogbWlzc2luZyBub25jZSBibG9ja2hhc2gnKTtcbiAgICB9KTtcblxuICAgIGl0KCdidWlsZCB3aGVuIHNlbmRlciBpcyBub3QgcHJvdmlkZWQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFN0YWtpbmdBY3RpdmF0ZUJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci5zdGFraW5nQWRkcmVzcyhzdGFrZUFjY291bnQucHViKTtcbiAgICAgIHR4QnVpbGRlci5hbW91bnQoYW1vdW50KTtcbiAgICAgIHR4QnVpbGRlci52YWxpZGF0b3IodmFsaWRhdG9yLnB1Yik7XG4gICAgICB0eEJ1aWxkZXIubm9uY2UocmVjZW50QmxvY2tIYXNoKTtcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiB3YWxsZXQucHJ2IH0pO1xuICAgICAgYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkuc2hvdWxkLnJlamVjdGVkV2l0aCgnSW52YWxpZCB0cmFuc2FjdGlvbjogbWlzc2luZyBzZW5kZXInKTtcbiAgICB9KTtcblxuICAgIGl0KCdidWlsZCB3aGVuIHN0YWtpbmdBZGRyZXNzIGlzIG5vdCBwcm92aWRlZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0U3Rha2luZ0FjdGl2YXRlQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih3YWxsZXQucHViKTtcbiAgICAgIHR4QnVpbGRlci5hbW91bnQoYW1vdW50KTtcbiAgICAgIHR4QnVpbGRlci52YWxpZGF0b3IodmFsaWRhdG9yLnB1Yik7XG4gICAgICB0eEJ1aWxkZXIubm9uY2UocmVjZW50QmxvY2tIYXNoKTtcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiB3YWxsZXQucHJ2IH0pO1xuICAgICAgYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkuc2hvdWxkLnJlamVjdGVkV2l0aCgnU3Rha2luZyBBZGRyZXNzIG11c3QgYmUgc2V0IGJlZm9yZSBidWlsZGluZyB0aGUgdHJhbnNhY3Rpb24nKTtcbiAgICB9KTtcblxuICAgIGl0KCdidWlsZCB3aGVuIHZhbGlkYXRvciBpcyBub3QgcHJvdmlkZWQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFN0YWtpbmdBY3RpdmF0ZUJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci5zdGFraW5nQWRkcmVzcyhzdGFrZUFjY291bnQucHViKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIod2FsbGV0LnB1Yik7XG4gICAgICB0eEJ1aWxkZXIuYW1vdW50KGFtb3VudCk7XG4gICAgICB0eEJ1aWxkZXIubm9uY2UocmVjZW50QmxvY2tIYXNoKTtcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiB3YWxsZXQucHJ2IH0pO1xuICAgICAgYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkuc2hvdWxkLnJlamVjdGVkV2l0aCgnVmFsaWRhdG9yIG11c3QgYmUgc2V0IGJlZm9yZSBidWlsZGluZyB0aGUgdHJhbnNhY3Rpb24nKTtcbiAgICB9KTtcblxuICAgIGl0KCd0byBzaWduIHR3aWNlIHdpdGggdGhlIHNhbWUga2V5JywgKCkgPT4ge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5mcm9tKHRlc3REYXRhLlNUQUtJTkdfQUNUSVZBVEVfVU5TSUdORURfVFgpO1xuICAgICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IHdhbGxldC5wcnYgfSk7XG4gICAgICBzaG91bGQoKCkgPT4gdHhCdWlsZGVyLnNpZ24oeyBrZXk6IHdhbGxldC5wcnYgfSkpLnRocm93RXJyb3IoJ0R1cGxpY2F0ZWQgc2lnbmVyOiAnICsgd2FsbGV0LnBydj8udG9TdHJpbmcoKSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdGcm9tIGFuZCBzaWduJywgKCkgPT4ge1xuICAgIGRlc2NyaWJlKCdTdWNjZWVkJywgKCkgPT4ge1xuICAgICAgaXQoJ2J1aWxkIGZyb20gYW4gdW5zaWduZWQgc3Rha2luZyBhY3RpdmF0ZSBhbmQgc2lnbiBpdCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5mcm9tKHRlc3REYXRhLlNUQUtJTkdfQUNUSVZBVEVfVU5TSUdORURfVFgpO1xuXG4gICAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiB3YWxsZXQucHJ2IH0pO1xuICAgICAgICB0eEJ1aWxkZXIuc2lnbih7IGtleTogc3Rha2VBY2NvdW50LnBydiB9KTtcbiAgICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgdHguaW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICAgIHR4LmlucHV0c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgICBhZGRyZXNzOiB3YWxsZXQucHViLFxuICAgICAgICAgIHZhbHVlOiBhbW91bnQsXG4gICAgICAgICAgY29pbjogJ3Rzb2wnLFxuICAgICAgICB9KTtcbiAgICAgICAgdHgub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICAgIHNob3VsZC5lcXVhbChVdGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICAgICAgc2hvdWxkLmVxdWFsKHJhd1R4LCB0ZXN0RGF0YS5TVEFLSU5HX0FDVElWQVRFX1NJR05FRF9UWCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ01hcmluYWRlOiBidWlsZCBmcm9tIGFuIHVuc2lnbmVkIHN0YWtpbmcgYWN0aXZhdGUgYW5kIHNpZ24gaXQnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZnJvbSh0ZXN0RGF0YS5NQVJJTkFERV9TVEFLSU5HX0FDVElWQVRFX1VOU0lHTkVEX1RYKTtcblxuICAgICAgICB0eEJ1aWxkZXIuc2lnbih7IGtleTogd2FsbGV0LnBydiB9KTtcbiAgICAgICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IHN0YWtlQWNjb3VudC5wcnYgfSk7XG4gICAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICAgIHR4LmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgICB0eC5pbnB1dHNbMF0uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgICAgYWRkcmVzczogd2FsbGV0LnB1YixcbiAgICAgICAgICB2YWx1ZTogYW1vdW50LFxuICAgICAgICAgIGNvaW46ICd0c29sJyxcbiAgICAgICAgfSk7XG4gICAgICAgIHR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgICBzaG91bGQuZXF1YWwoVXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG4gICAgICAgIHNob3VsZC5lcXVhbChyYXdUeCwgdGVzdERhdGEuTUFSSU5BREVfU1RBS0lOR19BQ1RJVkFURV9TSUdORURfVFgpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdidWlsZCBmcm9tIGFuIHVuc2lnbmVkIHN0YWtpbmcgYWN0aXZhdGUgd2l0aCBtZW1vIGFuZCBzaWduIGl0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmZyb20odGVzdERhdGEuU1RBS0lOR19BQ1RJVkFURV9VTlNJR05FRF9UWF9XSVRIX01FTU8pO1xuICAgICAgICB0eEJ1aWxkZXIuc2lnbih7IGtleTogd2FsbGV0LnBydiB9KTtcbiAgICAgICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IHN0YWtlQWNjb3VudC5wcnYgfSk7XG4gICAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICAgIHR4LmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgICB0eC5pbnB1dHNbMF0uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgICAgYWRkcmVzczogd2FsbGV0LnB1YixcbiAgICAgICAgICB2YWx1ZTogYW1vdW50LFxuICAgICAgICAgIGNvaW46ICd0c29sJyxcbiAgICAgICAgfSk7XG4gICAgICAgIHR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgICBzaG91bGQuZXF1YWwoVXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG4gICAgICAgIHNob3VsZC5lcXVhbChyYXdUeCwgdGVzdERhdGEuU1RBS0lOR19BQ1RJVkFURV9TSUdORURfVFhfV0lUSF9NRU1PKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ0ZhaWwnLCAoKSA9PiB7XG4gICAgICBpdCgnYnVpbGQgZnJvbSBhbiB1bnNpZ25lZCBzdGFraW5nIGFjdGl2YXRlIGFuZCBmYWlsIHRvIHNpZ24gaXQnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZnJvbSh0ZXN0RGF0YS5TVEFLSU5HX0FDVElWQVRFX1VOU0lHTkVEX1RYKTtcbiAgICAgICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IHdyb25nQWNjb3VudC5wcnYgfSk7XG4gICAgICAgIGF3YWl0IHR4QnVpbGRlci5idWlsZCgpLnNob3VsZC5yZWplY3RlZFdpdGgoJ3Vua25vd24gc2lnbmVyOiBDUDVEcGFhNDJSdEptTXVLcUNRc0x3bWE1WWgza251dktzWURGWDg1RjQxUycpO1xuICAgICAgfSk7XG4gICAgICBpdCgnYnVpbGQgZnJvbSBhIHNpZ25lZCBzdGFraW5nIGFjdGl2YXRlIGFuZCBmYWlsIHRvIHNpZ24gaXQnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZnJvbSh0ZXN0RGF0YS5TVEFLSU5HX0FDVElWQVRFX1NJR05FRF9UWCk7XG4gICAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiB3cm9uZ0FjY291bnQucHJ2IH0pO1xuICAgICAgICBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKS5zaG91bGQucmVqZWN0ZWRXaXRoKCd1bmtub3duIHNpZ25lcjogQ1A1RHBhYTQyUnRKbU11S3FDUXNMd21hNVloM2tudXZLc1lERlg4NUY0MVMnKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19

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


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