PHP WebShell

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

Просмотр файла: 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;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const assert_1 = __importDefault(require("assert"));
const _ = __importStar(require("lodash"));
const sinon_1 = __importDefault(require("sinon"));
const crypto_1 = require("crypto");
const bignumber_js_1 = require("bignumber.js");
const sdk_test_1 = require("@bitgo/sdk-test");
const sdk_api_1 = require("@bitgo/sdk-api");
const sdk_core_1 = require("@bitgo/sdk-core");
const TestData = __importStar(require("../fixtures/hbar"));
const src_1 = require("../../src");
const getBuilderFactory_1 = require("./getBuilderFactory");
describe('Hedera Hashgraph:', function () {
    let bitgo;
    let basecoin;
    let token;
    before(function () {
        bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
        bitgo.safeRegister('thbar', src_1.Thbar.createInstance);
        bitgo.safeRegister('hbar', src_1.Hbar.createInstance);
        src_1.HbarToken.createTokenConstructors().forEach(({ name, coinConstructor }) => {
            bitgo.safeRegister(name, coinConstructor);
        });
        bitgo.initializeTestVars();
        basecoin = bitgo.coin('thbar');
        token = bitgo.coin('thbar:usdc');
    });
    it('should instantiate the coin', function () {
        const basecoin = bitgo.coin('hbar');
        basecoin.should.be.an.instanceof(src_1.Hbar);
    });
    it('should check valid addresses', async function () {
        const badAddresses = [
            '',
            '0.0',
            'YZ09fd-',
            '0.0.0.a',
            'sadasdfggg',
            '0.2.a.b',
            '0.0.100?=sksjd',
            '0.0.41098?memoId=',
        ];
        const goodAddresses = [
            '0',
            '0.0.0',
            '0.0.41098',
            '0.0.0?memoId=84',
            '0.0.41098',
            '0.0.41098?memoId=2aaaaa',
            '0.0.41098?memoId=1',
        ];
        badAddresses.map((addr) => {
            basecoin.isValidAddress(addr).should.equal(false);
        });
        goodAddresses.map((addr) => {
            basecoin.isValidAddress(addr).should.equal(true);
        });
        const hexAddress = '0x23C3E227BE97281A70A549c7dDB8d5Caad3E7C84';
        basecoin.isValidAddress(hexAddress).should.equal(false);
    });
    it('should explain a transaction', async function () {
        const tx = JSON.parse(TestData.rawTransactionForExplain);
        const explain = await basecoin.explainTransaction(tx);
        explain.id.should.equal('0.0.43285@1600529800.643093586');
        explain.outputAmount.should.equal('2200000000');
        explain.timestamp.should.equal('1600529800.643093586');
        explain.expiration.should.equal('180');
        explain.outputs[0].amount.should.equal('2200000000');
        explain.outputs[0].address.should.equal('0.0.43283');
        explain.outputs[0].memo.should.equal('1');
        explain.fee.should.equal(1160407);
        explain.changeAmount.should.equal('0');
    });
    it('should explain a token transfer transaction', async function () {
        const tokenTransferParam = {
            txHex: TestData.UNSIGNED_TOKEN_TRANSFER,
            feeInfo: {
                size: 1000,
                fee: 1160407,
                feeRate: 1160407,
            },
        };
        const explain = await basecoin.explainTransaction(tokenTransferParam);
        explain.id.should.equal('0.0.81320@1596110493.372646570');
        explain.outputAmount.should.equal('0');
        explain.timestamp.should.equal('1596110493.372646570');
        explain.expiration.should.equal('180');
        explain.outputs[0].amount.should.equal('10');
        explain.outputs[0].address.should.equal('0.0.75861');
        explain.outputs[0].memo.should.equal('');
        explain.outputs[0].tokenName.should.equal('thbar:usdc');
        explain.fee.should.equal(1160407);
        explain.changeAmount.should.equal('0');
    });
    it('should explain a multirecipients transfer transaction', async function () {
        const multiTransferParam = {
            txHex: TestData.UNSIGNED_MULTI_TRANSFER,
            feeInfo: {
                size: 1000,
                fee: 1160407,
                feeRate: 1160407,
            },
        };
        const explain = await basecoin.explainTransaction(multiTransferParam);
        explain.id.should.equal('0.0.81320@1596110493.372646570');
        explain.outputAmount.should.equal('25');
        explain.expiration.should.equal('180');
        explain.outputs[0].amount.should.equal('10');
        explain.outputs[0].address.should.equal('0.0.75861');
        explain.outputs[0].memo.should.equal('');
        explain.outputs[1].amount.should.equal('15');
        explain.outputs[1].address.should.equal('0.0.78963');
        explain.fee.should.equal(1160407);
        explain.changeAmount.should.equal('0');
    });
    it('should explain a multirecipients token transfer transaction', async function () {
        const tokenMultiTransferParam = {
            txHex: TestData.UNSIGNED_TOKEN_MULTI_TRANSFER,
            feeInfo: {
                size: 1000,
                fee: 1160407,
                feeRate: 1160407,
            },
        };
        const explain = await basecoin.explainTransaction(tokenMultiTransferParam);
        explain.id.should.equal('0.0.81320@1596110493.372646570');
        explain.outputAmount.should.equal('0');
        explain.timestamp.should.equal('1596110493.372646570');
        explain.expiration.should.equal('180');
        explain.outputs[0].amount.should.equal('10');
        explain.outputs[0].address.should.equal('0.0.75861');
        explain.outputs[0].memo.should.equal('');
        explain.outputs[0].tokenName.should.equal('thbar:usdc');
        explain.outputs[1].amount.should.equal('15');
        explain.outputs[1].address.should.equal('0.0.78963');
        explain.outputs[1].tokenName.should.equal('thbar:usdc');
        explain.fee.should.equal(1160407);
        explain.changeAmount.should.equal('0');
    });
    it('should explain a token associate transaction', async function () {
        const tokenAssociateParam = {
            txHex: TestData.UNSIGNED_TOKEN_ASSOCIATE,
            feeInfo: {
                size: 1000,
                fee: 1160407,
                feeRate: 1160407,
            },
        };
        const explain = await basecoin.explainTransaction(tokenAssociateParam);
        explain.id.should.equal('0.0.81320@1596110493.372646570');
        explain.outputAmount.should.equal('0');
        explain.timestamp.should.equal('1596110493.372646570');
        explain.expiration.should.equal('180');
        explain.outputs[0].amount.should.equal('0');
        explain.outputs[0].address.should.equal('0.0.81320');
        explain.outputs[0].memo.should.equal('');
        explain.outputs[0].tokenName.should.equal('thbar:usdc');
        explain.fee.should.equal(1160407);
        explain.changeAmount.should.equal('0');
    });
    it('should verify isWalletAddress', async function () {
        const baseAddress = '0.0.41098';
        const validAddress1 = '0.0.41098?memoId=1';
        const validAddress2 = '0.0.41098?memoId=2';
        const unrelatedValidAddress = '0.1.41098?memoId=1';
        const invalidAddress = '0.0.0.a';
        (await basecoin.isWalletAddress({ address: validAddress1, baseAddress })).should.true();
        (await basecoin.isWalletAddress({ address: validAddress2, baseAddress })).should.true();
        (await basecoin.isWalletAddress({ address: validAddress2, baseAddress: validAddress1 })).should.true();
        (await basecoin.isWalletAddress({ address: unrelatedValidAddress, baseAddress })).should.false();
        assert_1.default.rejects(async () => basecoin.isWalletAddress({ address: invalidAddress, baseAddress }), `invalid address ${invalidAddress}`);
    });
    describe('Keypairs:', () => {
        it('should generate a keypair from random seed', function () {
            const keyPair = basecoin.generateKeyPair();
            keyPair.should.have.property('pub');
            keyPair.should.have.property('prv');
            basecoin.isValidPub(keyPair.pub).should.equal(true);
        });
        it('should generate a keypair from a seed', function () {
            const seedText = '80350b4208d381fbfe2276a326603049fe500731c46d3c9936b5ce036b51377f';
            const seed = Buffer.from(seedText, 'hex');
            const keyPair = basecoin.generateKeyPair(seed);
            keyPair.prv.should.equal('302e020100300506032b65700422042080350b4208d381fbfe2276a326603049fe500731c46d3c9936b5ce036b51377f');
            keyPair.pub.should.equal('302a300506032b65700321009cc402b5c75214269c2826e3c6119377cab6c367601338661c87a4e07c6e0333');
        });
        it('should validate a stellar seed', function () {
            basecoin.isStellarSeed('SBMWLNV75BPI2VB4G27RWOMABVRTSSF7352CCYGVELZDSHCXWCYFKXIX').should.ok();
        });
        it('should convert a stellar seed to an hbar prv', function () {
            const seed = basecoin.convertFromStellarSeed('SBMWLNV75BPI2VB4G27RWOMABVRTSSF7352CCYGVELZDSHCXWCYFKXIX');
            seed.should.equal('302e020100300506032b6570042204205965b6bfe85e8d543c36bf1b39800d633948bfdf742160d522f2391c57b0b055');
        });
    });
    describe('Verify Transaction:', () => {
        let newTxPrebuild;
        let newTxParams;
        let newTxParamsWithError;
        let newTxParamsWithExtraData;
        const txPrebuild = {
            recipients: [
                {
                    address: 'lionteste212',
                    amount: '1000',
                },
            ],
            txHex: TestData.UNSIGNED_MULTI_TRANSFER,
            txid: '586c5b59b10b134d04c16ac1b273fe3c5529f34aef75db4456cd469c5cdac7e2',
            isVotingTransaction: false,
            coin: 'thbar',
            feeInfo: {
                size: 1000,
                fee: 1160407,
                feeRate: 1160407,
            },
        };
        const txParams = {
            txPrebuild,
            recipients: [
                {
                    address: '0.0.75861',
                    amount: '10',
                },
                {
                    address: '0.0.78963',
                    amount: '15',
                },
            ],
        };
        const memo = { value: '' };
        const txParamsWithError = {
            txPrebuild,
            recipients: [
                {
                    address: '0.0.75861',
                    amount: '1000',
                },
            ],
        };
        const txParamsWithExtraData = {
            txPrebuild,
            recipients: [
                {
                    address: '0.0.75861',
                    amount: '10',
                    data: undefined,
                },
                {
                    address: '0.0.78963',
                    amount: '15',
                    data: undefined,
                },
            ],
        };
        const walletData = {
            id: '5b34252f1bf349930e34020a00000000',
            coin: 'thbar',
            keys: [
                '5b3424f91bf349930e34017500000000',
                '5b3424f91bf349930e34017600000000',
                '5b3424f91bf349930e34017700000000',
            ],
            coinSpecific: {
                baseAddress: '0.0.2935',
            },
            multisigType: 'onchain',
        };
        const walletObj = new sdk_core_1.Wallet(bitgo, basecoin, walletData);
        before(function () {
            newTxPrebuild = () => {
                return _.cloneDeep(txPrebuild);
            };
            newTxParams = () => {
                return _.cloneDeep(txParams);
            };
            newTxParamsWithError = () => {
                return _.cloneDeep(txParamsWithError);
            };
            newTxParamsWithExtraData = () => {
                return _.cloneDeep(txParamsWithExtraData);
            };
        });
        it('should verify native transfer transactions', async function () {
            const txParams = newTxParams();
            const txPrebuild = newTxPrebuild();
            const validTransaction = await basecoin.verifyTransaction({
                txParams,
                txPrebuild,
                memo,
                wallet: walletObj,
            });
            validTransaction.should.equal(true);
        });
        it('should fail verify when input `recipients` is absent', async function () {
            const txParams = newTxParams();
            txParams.recipients = undefined;
            const txPrebuild = newTxPrebuild();
            await basecoin
                .verifyTransaction({ txParams, txPrebuild, memo: memo, wallet: walletObj })
                .should.be.rejectedWith('missing required tx params property recipients');
        });
        it('should fail verify transactions when have different recipients', async function () {
            const txParams = newTxParamsWithError();
            const txPrebuild = newTxPrebuild();
            await basecoin
                .verifyTransaction({ txParams, txPrebuild, memo, wallet: walletObj })
                .should.be.rejectedWith('Tx outputs does not match with expected txParams recipients');
        });
        it('should succeed to verify transactions when recipients has extra data', async function () {
            const txParams = newTxParamsWithExtraData();
            const txPrebuild = newTxPrebuild();
            const validTransaction = await basecoin.verifyTransaction({
                txParams,
                txPrebuild,
                memo,
                wallet: walletObj,
            });
            validTransaction.should.equal(true);
        });
        it('should verify create associated token account transaction', async function () {
            const txParams = newTxParams();
            const txPrebuild = newTxPrebuild();
            txPrebuild.txHex = TestData.UNSIGNED_TOKEN_ASSOCIATE;
            txParams.recipients = [
                {
                    address: '0.0.81320',
                    amount: '0',
                    tokenName: 'thbar:usdc',
                },
            ];
            const validTransaction = await basecoin.verifyTransaction({
                txParams,
                txPrebuild,
                memo,
                wallet: walletObj,
            });
            validTransaction.should.equal(true);
        });
        it('should fail verify create associated token account transaction with mismatch recipients', async function () {
            const txParams = newTxParams();
            const txPrebuild = newTxPrebuild();
            txPrebuild.txHex = TestData.UNSIGNED_TOKEN_ASSOCIATE;
            txParams.recipients = [
                {
                    address: '0.0.81321',
                    amount: '0',
                    tokenName: 'thbar:usdc',
                },
            ];
            await basecoin
                .verifyTransaction({ txParams, txPrebuild, memo, wallet: walletObj })
                .should.be.rejectedWith('Tx outputs does not match with expected txParams recipients');
        });
        it('should verify token transfer transaction', async function () {
            const txParams = newTxParams();
            const txPrebuild = newTxPrebuild();
            txPrebuild.txHex = TestData.UNSIGNED_TOKEN_MULTI_TRANSFER;
            txParams.recipients = [
                {
                    address: '0.0.75861',
                    amount: '10',
                    tokenName: 'thbar:usdc',
                },
                {
                    address: '0.0.78963',
                    amount: '15',
                    tokenName: 'thbar:usdc',
                },
            ];
            const validTransaction = await token.verifyTransaction({
                txParams,
                txPrebuild,
                memo,
                wallet: walletObj,
            });
            validTransaction.should.equal(true);
        });
        it('should verify token transfer transaction with any token name on token base coin', async function () {
            const txParams = newTxParams();
            const txPrebuild = newTxPrebuild();
            txPrebuild.txHex = TestData.UNSIGNED_TOKEN_MULTI_TRANSFER;
            txParams.recipients = [
                {
                    address: '0.0.75861',
                    amount: '10',
                    tokenName: 'thbar:usdc',
                },
                {
                    address: '0.0.78963',
                    amount: '15',
                },
            ];
            (await token.verifyTransaction({ txParams, txPrebuild, memo, wallet: walletObj })).should.equal(true);
        });
        it('should fail to verify token transfer with mismatched recipients', async function () {
            const txParams = newTxParams();
            const txPrebuild = newTxPrebuild();
            txPrebuild.txHex = TestData.UNSIGNED_TOKEN_MULTI_TRANSFER;
            txParams.recipients = [
                {
                    address: '0.0.75861',
                    amount: '11',
                    tokenName: 'thbar:usdc',
                },
                {
                    address: '0.0.78963',
                    amount: '15',
                },
            ];
            await token
                .verifyTransaction({ txParams, txPrebuild, memo, wallet: walletObj })
                .should.be.rejectedWith('Tx outputs does not match with expected txParams recipients');
        });
        it('should fail to verify token transfer with incorrect token name', async function () {
            const txParams = newTxParams();
            const txPrebuild = newTxPrebuild();
            txPrebuild.txHex = TestData.UNSIGNED_TOKEN_MULTI_TRANSFER;
            txParams.recipients = [
                {
                    address: '0.0.75861',
                    amount: '11',
                    tokenName: 'thbar:usdc',
                },
                {
                    address: '0.0.78963',
                    amount: '15',
                    tokenName: 'invalidtoken',
                },
            ];
            await token
                .verifyTransaction({ txParams, txPrebuild, memo, wallet: walletObj })
                .should.be.rejectedWith('Incorrect token name specified in recipients');
        });
    });
    describe('Sign Message', () => {
        it('should be performed', async () => {
            const keyPair = new src_1.KeyPair();
            const messageToSign = Buffer.from((0, crypto_1.randomBytes)(32)).toString('hex');
            const signature = await basecoin.signMessage(keyPair.getKeys(), messageToSign);
            keyPair.verifySignature(messageToSign, Uint8Array.from(Buffer.from(signature, 'hex'))).should.equals(true);
        });
        it('should fail with missing private key', async () => {
            const keyPair = new src_1.KeyPair({
                pub: '302a300506032b6570032100d8fd745361df270776a3ab1b55d5590ec00a26ab45eea37197dc9894a81fcb82',
            }).getKeys();
            const messageToSign = Buffer.from((0, crypto_1.randomBytes)(32)).toString('hex');
            await basecoin.signMessage(keyPair, messageToSign).should.be.rejectedWith('Invalid key pair options');
        });
    });
    describe('Sign transaction:', () => {
        const destination = '0.0.129369';
        const source = '0.0.1234';
        const amount = '100000';
        /**
         * Build an unsigned account-lib multi-signature send transaction
         * @param destination The destination address of the transaction
         * @param source The account sending thist ransaction
         * @param amount The amount to send to the recipient
         */
        const buildUnsignedTransaction = async function ({ destination, source, amount = '100000' }) {
            const factory = (0, getBuilderFactory_1.getBuilderFactory)('thbar');
            const txBuilder = factory.getTransferBuilder();
            txBuilder.fee({
                fee: '100000',
            });
            txBuilder.source({ address: source });
            txBuilder.send({ address: destination, amount });
            return await txBuilder.build();
        };
        it('should sign transaction', async function () {
            const key = new src_1.KeyPair();
            const unsignedTransaction = await buildUnsignedTransaction({
                destination,
                source,
                amount,
            });
            const tx = await basecoin.signTransaction({
                prv: key.getKeys().prv.toString(),
                txPrebuild: {
                    txHex: unsignedTransaction.toBroadcastFormat(),
                },
            });
            const factory = (0, getBuilderFactory_1.getBuilderFactory)('thbar');
            const txBuilder = factory.from(tx.halfSigned.txHex);
            const signedTx = await txBuilder.build();
            const txJson = signedTx.toJson();
            txJson.should.have.properties('to', 'amount');
            txJson.to?.should.equal(destination);
            txJson.from.should.equal(source);
            txJson.amount?.should.equal(amount);
            txJson.instructionsData.params.recipients[0].should.deepEqual({
                address: destination,
                amount,
            });
            signedTx.signature.length.should.equal(1);
        });
        it('should fully sign transaction with root key', async function () {
            const key1 = basecoin.generateRootKeyPair();
            const key2 = basecoin.generateRootKeyPair();
            const unsignedTransaction = await buildUnsignedTransaction({
                destination,
                source,
                amount,
            });
            const txHalfSigned = await basecoin.signTransaction({
                prv: key1.prv,
                txPrebuild: {
                    txHex: unsignedTransaction.toBroadcastFormat(),
                },
            });
            const factory = (0, getBuilderFactory_1.getBuilderFactory)('thbar');
            const txBuilderHalfSigned = factory.from(txHalfSigned.halfSigned.txHex);
            const halfSignedTx = await txBuilderHalfSigned.build();
            const halfSignedTxJson = halfSignedTx.toJson();
            halfSignedTxJson.should.have.properties('to', 'amount');
            halfSignedTxJson.to?.should.equal(destination);
            halfSignedTxJson.from.should.equal(source);
            halfSignedTxJson.amount?.should.equal(amount);
            halfSignedTxJson.instructionsData.params.recipients[0].should.deepEqual({
                address: destination,
                amount,
            });
            halfSignedTx.signature.length.should.equal(1);
            const txSigned = await basecoin.signTransaction({
                prv: key2.prv,
                txPrebuild: {
                    txHex: halfSignedTx.toBroadcastFormat(),
                },
            });
            const txBuilderSigned = factory.from(txSigned.txHex);
            const signedTx = await txBuilderSigned.build();
            const signedTxJson = signedTx.toJson();
            signedTxJson.should.have.properties('to', 'amount');
            signedTxJson.to?.should.equal(destination);
            signedTxJson.from.should.equal(source);
            signedTxJson.amount?.should.equal(amount);
            signedTxJson.instructionsData.params.recipients[0].should.deepEqual({
                address: destination,
                amount,
            });
            signedTx.signature.length.should.equal(2);
        });
    });
    describe('Recovery', function () {
        const defaultValidDuration = '180';
        const defaultFee = 10000000;
        const defaultNodeId = '0.0.3';
        const userKey = '{"iv":"WlPuJOejRWgj/NTd3UMgrw==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"6yAVFvreHSQ=","ct":"8j/lBVkFByKlVhaS9JWmmLja5yTokjaIiLDxMIDjMojVEim9T36WAm5qW6v1V0A7QcEuGiVl3PKMDa+Gr6tI/HT58DW5RE+pHzya9MUQpAgNrJr8VEWjrXWqZECVtra1/bKCyB+mozc="}';
        const userPub = '302a300506032b6570032100ddd53a1591d72b181109bd3e57b18603740490b9ab4d37bc7fa27480e6b8c911';
        const backupKey = '{"iv":"D5DVDozQx9B02JeFV0/OVA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"7FUNF8M35bo=","ct":"ZiPsu5Qe/AIS4JQXt+rrusHnYCy4CqurM16R5wJrd4CEx7u85y3yy5ErnsdyYYcc3txyNmUIQ2/CBq/LKoKO/VIeU++CnKxzGuHGcNI47BPk3RQK42a66uIQn/yTR++XgdK1KhvUL3U="}';
        const backupPub = '302a300506032b65700321006293e4ec9bf1b2d8fae631119107248a65e2207a05d32a11f42cc3d9a3005d4a';
        const rootAddress = '0.0.7671186';
        const walletPassphrase = 'TestPasswordPleaseIgnore';
        const recoveryDestination = '0.0.7651908';
        const bitgoKey = '5a93b01ea87e963f61c974a89d62e3841392f1ba020fbbcc65a8089ca025abbb';
        const memo = '4';
        const balance = '1000000000';
        const formatBalanceResponse = (balance) => new bignumber_js_1.BigNumber(balance).dividedBy(basecoin.getBaseFactor()).toFixed(9) + ' ℏ';
        const tokenId = '0.0.13078';
        describe('Non-BitGo', async function () {
            const sandBox = sinon_1.default.createSandbox();
            afterEach(function () {
                sandBox.verifyAndRestore();
            });
            it('should build and sign the recovery tx', async function () {
                const expectedAmount = new bignumber_js_1.BigNumber(balance).minus(defaultFee).toString();
                const getBalanceStub = sandBox
                    .stub(src_1.Hbar.prototype, 'getAccountBalance')
                    .resolves({ hbars: formatBalanceResponse(balance), tokens: [] });
                const recovery = await basecoin.recover({
                    userKey,
                    backupKey,
                    rootAddress,
                    walletPassphrase,
                    recoveryDestination: recoveryDestination + '?memoId=' + memo,
                });
                recovery.should.not.be.undefined();
                recovery.should.have.property('id');
                recovery.should.have.property('tx');
                recovery.should.have.property('coin', 'thbar');
                recovery.should.have.property('nodeId', defaultNodeId);
                getBalanceStub.callCount.should.equal(1);
                const txBuilder = basecoin.getBuilderFactory().from(recovery.tx);
                const tx = await txBuilder.build();
                tx.toBroadcastFormat().should.equal(recovery.tx);
                const txJson = tx.toJson();
                txJson.amount.should.equal(expectedAmount);
                txJson.to.should.equal(recoveryDestination);
                txJson.from.should.equal(rootAddress);
                txJson.fee.should.equal(defaultFee);
                txJson.node.should.equal(defaultNodeId);
                txJson.memo.should.equal(memo);
                txJson.validDuration.should.equal(defaultValidDuration);
                txJson.should.have.property('startTime');
                recovery.should.have.property('startTime', txJson.startTime);
                recovery.should.have.property('id', rootAddress + '@' + txJson.startTime);
            });
            it('should throw for invalid rootAddress', async function () {
                const invalidRootAddress = 'randomstring';
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey,
                        backupKey,
                        rootAddress: 'randomstring',
                        walletPassphrase,
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                    });
                }, { message: 'invalid rootAddress, got: ' + invalidRootAddress });
            });
            it('should throw for invalid recoveryDestination', async function () {
                const invalidRecoveryDestination = 'randomstring';
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey,
                        backupKey,
                        rootAddress,
                        walletPassphrase,
                        recoveryDestination: 'randomstring',
                    });
                }, { message: 'invalid recoveryDestination, got: ' + invalidRecoveryDestination });
            });
            it('should throw for invalid nodeId', async function () {
                const invalidNodeId = 'a.2.3';
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey,
                        backupKey,
                        rootAddress,
                        walletPassphrase,
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                        nodeId: invalidNodeId,
                    });
                }, { message: 'invalid nodeId, got: ' + invalidNodeId });
            });
            it('should throw for invalid maxFee', async function () {
                const invalidMaxFee = '-32';
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey,
                        backupKey,
                        rootAddress,
                        walletPassphrase,
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                        maxFee: invalidMaxFee,
                    });
                }, { message: 'invalid maxFee, got: ' + invalidMaxFee });
            });
            it('should throw if there is no enough balance to recover', async function () {
                const getBalanceStub = sandBox
                    .stub(src_1.Hbar.prototype, 'getAccountBalance')
                    .resolves({ hbars: formatBalanceResponse('100'), tokens: [] });
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey,
                        backupKey,
                        rootAddress,
                        walletPassphrase,
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                    });
                }, { message: 'Insufficient balance to recover, got balance: 100 fee: 10000000' });
                getBalanceStub.callCount.should.equal(1);
            });
            it('should throw if the walletPassphrase is undefined', async function () {
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey,
                        backupKey,
                        rootAddress,
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                    });
                }, { message: 'walletPassphrase is required for non-bitgo recovery' });
            });
            it('should throw if the walletPassphrase is wrong', async function () {
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey,
                        backupKey,
                        rootAddress,
                        walletPassphrase: 'randompassword',
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                    });
                }, {
                    message: "unable to decrypt userKey or backupKey with the walletPassphrase provided, got error: password error - ccm: tag doesn't match",
                });
            });
            it('should build and sign the recovery tx for tokens', async function () {
                const balance = '100';
                const data = {
                    hbars: '1',
                    tokens: [{ tokenId: tokenId, balance: balance, decimals: 6 }],
                };
                const getBalanceStub = sandBox.stub(src_1.Hbar.prototype, 'getAccountBalance').resolves(data);
                const recovery = await basecoin.recover({
                    userKey,
                    backupKey,
                    rootAddress,
                    walletPassphrase,
                    recoveryDestination: recoveryDestination + '?memoId=' + memo,
                    tokenId: tokenId,
                });
                recovery.should.not.be.undefined();
                recovery.should.have.property('id');
                recovery.should.have.property('tx');
                recovery.should.have.property('coin', 'thbar');
                recovery.should.have.property('nodeId', defaultNodeId);
                getBalanceStub.callCount.should.equal(1);
                const txBuilder = basecoin.getBuilderFactory().from(recovery.tx);
                const tx = await txBuilder.build();
                tx.toBroadcastFormat().should.equal(recovery.tx);
                const txJson = tx.toJson();
                txJson.amount.should.equal(balance);
                txJson.to.should.equal(recoveryDestination);
                txJson.from.should.equal(rootAddress);
                txJson.fee.should.equal(defaultFee);
                txJson.node.should.equal(defaultNodeId);
                txJson.memo.should.equal(memo);
                txJson.validDuration.should.equal(defaultValidDuration);
                txJson.should.have.property('startTime');
                recovery.should.have.property('startTime', txJson.startTime);
                recovery.should.have.property('id', rootAddress + '@' + txJson.startTime);
            });
            it('should throw error for non supported invalid tokenId', async function () {
                const invalidTokenId = 'randomstring';
                const data = {
                    hbars: '1',
                    tokens: [{ tokenId: tokenId, balance: '100', decimals: 6 }],
                };
                sandBox.stub(src_1.Hbar.prototype, 'getAccountBalance').resolves(data);
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey,
                        backupKey,
                        rootAddress: rootAddress,
                        walletPassphrase,
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                        tokenId: invalidTokenId,
                    });
                }, { message: 'Unsupported token: ' + invalidTokenId });
            });
            it('should throw error for insufficient balance for tokenId if token balance not exist', async function () {
                const data = {
                    hbars: '100',
                    tokens: [{ tokenId: 'randomString', balance: '100', decimals: 6 }],
                };
                sandBox.stub(src_1.Hbar.prototype, 'getAccountBalance').resolves(data);
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey,
                        backupKey,
                        rootAddress: rootAddress,
                        walletPassphrase,
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                        tokenId: tokenId,
                    });
                }, { message: 'Insufficient balance to recover token: ' + tokenId + ' for account: ' + rootAddress });
            });
            it('should throw error for insufficient balance for tokenId if token balance exist with 0 amount', async function () {
                const data = {
                    hbars: '100',
                    tokens: [{ tokenId: 'randomString', balance: '0', decimals: 6 }],
                };
                sandBox.stub(src_1.Hbar.prototype, 'getAccountBalance').resolves(data);
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey,
                        backupKey,
                        rootAddress: rootAddress,
                        walletPassphrase,
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                        tokenId: tokenId,
                    });
                }, { message: 'Insufficient balance to recover token: ' + tokenId + ' for account: ' + rootAddress });
            });
            it('should throw error for insufficient native balance for token transfer', async function () {
                const data = {
                    hbars: '0.01',
                    tokens: [{ tokenId: tokenId, balance: '10', decimals: 6 }],
                };
                sandBox.stub(src_1.Hbar.prototype, 'getAccountBalance').resolves(data);
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey,
                        backupKey,
                        rootAddress: rootAddress,
                        walletPassphrase,
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                        tokenId: tokenId,
                    });
                }, { message: 'Insufficient native balance to recover tokens, got native balance: 1000000 fee: ' + defaultFee });
            });
        });
        describe('Unsigned Sweep', function () {
            const sandBox = sinon_1.default.createSandbox();
            let getBalanceStub;
            afterEach(function () {
                sandBox.verifyAndRestore();
            });
            it('should build unsigned sweep tx', async function () {
                getBalanceStub = sandBox
                    .stub(src_1.Hbar.prototype, 'getAccountBalance')
                    .resolves({ hbars: formatBalanceResponse(balance), tokens: [] });
                const startTime = (Date.now() / 1000 + 10).toFixed(); // timestamp in seconds, 10 seconds from now
                const expectedAmount = new bignumber_js_1.BigNumber(balance).minus(defaultFee).toString();
                const recovery = await basecoin.recover({
                    userKey: userPub,
                    backupKey: backupPub,
                    rootAddress,
                    bitgoKey,
                    recoveryDestination: recoveryDestination + '?memoId=' + memo,
                    startTime,
                });
                getBalanceStub.callCount.should.equal(1);
                recovery.should.not.be.undefined();
                recovery.should.have.property('txHex');
                recovery.should.have.property('id', rootAddress + '@' + startTime + '.0');
                recovery.should.have.property('userKey', userPub);
                recovery.should.have.property('backupKey', backupPub);
                recovery.should.have.property('bitgoKey', bitgoKey);
                recovery.should.have.property('address', rootAddress);
                recovery.should.have.property('coin', 'thbar');
                recovery.should.have.property('maxFee', defaultFee.toString());
                recovery.should.have.property('recipients', [{ address: recoveryDestination, amount: expectedAmount }]);
                recovery.should.have.property('amount', expectedAmount);
                recovery.should.have.property('validDuration', defaultValidDuration);
                recovery.should.have.property('nodeId', defaultNodeId);
                recovery.should.have.property('memo', memo);
                recovery.should.have.property('startTime', startTime + '.0');
                const txBuilder = basecoin.getBuilderFactory().from(recovery.txHex);
                const tx = await txBuilder.build();
                const txJson = tx.toJson();
                txJson.id.should.equal(rootAddress + '@' + startTime + '.0');
                txJson.amount.should.equal(expectedAmount);
                txJson.to.should.equal(recoveryDestination);
                txJson.from.should.equal(rootAddress);
                txJson.fee.should.equal(defaultFee);
                txJson.node.should.equal(defaultNodeId);
                txJson.memo.should.equal(memo);
                txJson.validDuration.should.equal(defaultValidDuration);
                txJson.startTime.should.equal(startTime + '.0');
                txJson.validDuration.should.equal(defaultValidDuration);
            });
            it('should build unsigned sweep tx for tokens', async function () {
                const balance = '100';
                const data = {
                    hbars: '1',
                    tokens: [{ tokenId: tokenId, balance: balance, decimals: 6 }],
                };
                getBalanceStub = sandBox.stub(src_1.Hbar.prototype, 'getAccountBalance').resolves(data);
                const startTime = (Date.now() / 1000 + 10).toFixed(); // timestamp in seconds, 10 seconds from now
                const recovery = await basecoin.recover({
                    userKey: userPub,
                    backupKey: backupPub,
                    rootAddress,
                    bitgoKey,
                    recoveryDestination: recoveryDestination + '?memoId=' + memo,
                    startTime,
                    tokenId: tokenId,
                });
                getBalanceStub.callCount.should.equal(1);
                recovery.should.not.be.undefined();
                recovery.should.have.property('txHex');
                recovery.should.have.property('id', rootAddress + '@' + startTime + '.0');
                recovery.should.have.property('userKey', userPub);
                recovery.should.have.property('backupKey', backupPub);
                recovery.should.have.property('bitgoKey', bitgoKey);
                recovery.should.have.property('address', rootAddress);
                recovery.should.have.property('coin', 'thbar');
                recovery.should.have.property('maxFee', defaultFee.toString());
                recovery.should.have.property('recipients', [
                    { address: recoveryDestination, amount: balance, tokenName: 'thbar:usdc' },
                ]);
                recovery.should.have.property('amount', balance);
                recovery.should.have.property('validDuration', defaultValidDuration);
                recovery.should.have.property('nodeId', defaultNodeId);
                recovery.should.have.property('memo', memo);
                recovery.should.have.property('startTime', startTime + '.0');
                const txBuilder = basecoin.getBuilderFactory().from(recovery.txHex);
                const tx = await txBuilder.build();
                const txJson = tx.toJson();
                txJson.id.should.equal(rootAddress + '@' + startTime + '.0');
                txJson.amount.should.equal(balance);
                txJson.to.should.equal(recoveryDestination);
                txJson.from.should.equal(rootAddress);
                txJson.fee.should.equal(defaultFee);
                txJson.node.should.equal(defaultNodeId);
                txJson.memo.should.equal(memo);
                txJson.validDuration.should.equal(defaultValidDuration);
                txJson.startTime.should.equal(startTime + '.0');
                txJson.validDuration.should.equal(defaultValidDuration);
            });
            it('should throw if startTime is undefined', async function () {
                const startTime = undefined;
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey: userPub,
                        backupKey: backupPub,
                        rootAddress,
                        bitgoKey,
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                        startTime,
                    });
                }, { message: 'start time is required for unsigned sweep' });
            });
            it('should throw for invalid userKey', async function () {
                const startTime = (Date.now() / 1000 + 10).toFixed();
                const invalidUserPub = '302a300506032b6570032100randomstring';
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey: invalidUserPub,
                        backupKey: backupPub,
                        bitgoKey,
                        rootAddress,
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                        startTime,
                    });
                }, { message: 'invalid userKey, got: ' + invalidUserPub });
            });
            it('should throw for invalid backupKey', async function () {
                const invalidBackupPub = '302a300506032b6570032100randomstring';
                const startTime = (Date.now() / 1000 + 10).toFixed();
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey: userPub,
                        backupKey: invalidBackupPub,
                        bitgoKey,
                        rootAddress,
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                        startTime,
                    });
                }, { message: 'invalid backupKey, got: ' + invalidBackupPub });
            });
            it('should throw if startTime is a valid timestamp', async function () {
                const startTime = 'asd';
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey: userPub,
                        backupKey: backupPub,
                        rootAddress,
                        bitgoKey,
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                        startTime,
                    });
                }, { message: 'invalid startTime, got: ' + startTime });
            });
            it('should throw if startTime is not a future date', async function () {
                const startTime = (Date.now() / 1000 - 1).toString(); // timestamp in seconds, 1 second ago
                await assert_1.default.rejects(async () => {
                    await basecoin.recover({
                        userKey: userPub,
                        backupKey: backupPub,
                        rootAddress,
                        bitgoKey,
                        recoveryDestination: recoveryDestination + '?memoId=' + memo,
                        startTime,
                    });
                }, { message: 'startTime must be a future timestamp, got: ' + startTime });
            });
        });
        describe('Recovery with root keys', function () {
            const sandBox = sinon_1.default.createSandbox();
            let getBalanceStub;
            const walletPassphrase = 'testbtcpassword1999';
            const userEddsaRootXPrv = '{"iv":"lHOTkiuucR2JWFD1x1gqpQ==","v":1,"iter":10000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"HkFrDVH++d8=","ct":"NBtbYdFEK84oH9uxwl/UrhRsW5nGJPnMSpRAo8Blrc7WTSPxGXmVS/EpUYEV03HG06/EnyBR0/Y6bjLQz4gkL6cGJD9hgyKqDvc9RtKHagEbo75oxPr0zP+r1HMUGBW38Ttgor674gBeb1Myew69xcS9KgguNxwz77X6fdeBhrfogLY22vcuLA=="}';
            const userEddsaRootPub = 'd9cb9c9c617cfa0b715849516bb054a2b5d78c0e3eeef011176fb8bc0108c531';
            const backupEddsaRootXprv = '{"iv":"sBoEFBBNoi2YVICPf16/BQ==","v":1,"iter":10000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"HkFrDVH++d8=","ct":"GscOqJC+Iq+Lr39plQp5ZCamVlpJHOltGTZ7/UnUunIhFmZWMBLxjEVnMOtPreb0NZ4/SFqO/N3mZvq6JbB7vWRxJuqkBIiVcIRwkSWdW55cboKx2ec3ajg8+uO2pbvNDs26Q+9NtZ4jZnKNqSUXiCmtJXLRHQ32oyD+olKRpIR2NQo2+7kIEw=="}';
            const backupEddsaRootPub = 'f163b1b8ee4c3343a97ac1d2470b967e967ac7b4e3731cacf02f28a1434a2f99';
            const rootAddress = '0.0.3644667';
            const memoId = '0';
            beforeEach(function () {
                getBalanceStub = sandBox
                    .stub(src_1.Hbar.prototype, 'getAccountBalance')
                    .resolves({ hbars: formatBalanceResponse(balance), tokens: [] });
            });
            afterEach(function () {
                sandBox.verifyAndRestore();
            });
            it('should build and sign non-bitgo recovery tx with root keys', async function () {
                const expectedAmount = new bignumber_js_1.BigNumber(balance).minus(defaultFee).toString();
                const recovery = await basecoin.recover({
                    userKey: userEddsaRootXPrv,
                    backupKey: backupEddsaRootXprv,
                    rootAddress,
                    walletPassphrase,
                    recoveryDestination: recoveryDestination + '?memoId=' + memoId,
                });
                getBalanceStub.callCount.should.equal(1);
                recovery.should.not.be.undefined();
                recovery.should.have.property('id');
                recovery.should.have.property('tx');
                recovery.should.have.property('coin', 'thbar');
                recovery.should.have.property('nodeId', defaultNodeId);
                getBalanceStub.callCount.should.equal(1);
                const txBuilder = basecoin.getBuilderFactory().from(recovery.tx);
                const tx = await txBuilder.build();
                tx.toBroadcastFormat().should.equal(recovery.tx);
                const txJson = tx.toJson();
                txJson.amount.should.equal(expectedAmount);
                txJson.to.should.equal(recoveryDestination);
                txJson.from.should.equal(rootAddress);
                txJson.fee.should.equal(defaultFee);
                txJson.node.should.equal(defaultNodeId);
                txJson.memo.should.equal(memoId);
                txJson.validDuration.should.equal(defaultValidDuration);
                txJson.should.have.property('startTime');
                recovery.should.have.property('startTime', txJson.startTime);
                recovery.should.have.property('id', rootAddress + '@' + txJson.startTime);
            });
            it('should build unsigned sweep tx', async function () {
                const startTime = (Date.now() / 1000 + 10).toFixed(); // timestamp in seconds, 10 seconds from now
                const expectedAmount = new bignumber_js_1.BigNumber(balance).minus(defaultFee).toString();
                const recovery = await basecoin.recover({
                    userKey: userEddsaRootPub,
                    backupKey: backupEddsaRootPub,
                    rootAddress,
                    bitgoKey,
                    recoveryDestination: recoveryDestination + '?memoId=' + memoId,
                    startTime,
                });
                getBalanceStub.callCount.should.equal(1);
                recovery.should.not.be.undefined();
                recovery.should.have.property('txHex');
                recovery.should.have.property('id', rootAddress + '@' + startTime + '.0');
                recovery.should.have.property('userKey', userEddsaRootPub);
                recovery.should.have.property('backupKey', backupEddsaRootPub);
                recovery.should.have.property('bitgoKey', bitgoKey);
                recovery.should.have.property('address', rootAddress);
                recovery.should.have.property('coin', 'thbar');
                recovery.should.have.property('maxFee', defaultFee.toString());
                recovery.should.have.property('recipients', [{ address: recoveryDestination, amount: expectedAmount }]);
                recovery.should.have.property('amount', expectedAmount);
                recovery.should.have.property('validDuration', defaultValidDuration);
                recovery.should.have.property('nodeId', defaultNodeId);
                recovery.should.have.property('memo', memoId);
                recovery.should.have.property('startTime', startTime + '.0');
                const txBuilder = basecoin.getBuilderFactory().from(recovery.txHex);
                const tx = await txBuilder.build();
                const txJson = tx.toJson();
                txJson.id.should.equal(rootAddress + '@' + startTime + '.0');
                txJson.amount.should.equal(expectedAmount);
                txJson.to.should.equal(recoveryDestination);
                txJson.from.should.equal(rootAddress);
                txJson.fee.should.equal(defaultFee);
                txJson.node.should.equal(defaultNodeId);
                txJson.memo.should.equal(memoId);
                txJson.validDuration.should.equal(defaultValidDuration);
                txJson.startTime.should.equal(startTime + '.0');
                txJson.validDuration.should.equal(defaultValidDuration);
            });
        });
    });
    describe('broadcastTransaction', function () {
        const sandBox = sinon_1.default.createSandbox();
        afterEach(function () {
            sandBox.verifyAndRestore();
        });
        it('should succeed if the startTime and serializedSignedTransaction are valid', async function () {
            const startTime = (Date.now() / 1000 - 3).toFixed(); // timestamp in seconds, -3 seconds from now so it's valid after 2 seconds
            const expectedResponse = { txId: '0.0.7668465@' + startTime + '.0', status: 'SUCCESS' };
            const broadcastStub = sandBox.stub(src_1.Hbar.prototype, 'clientBroadcastTransaction').resolves(expectedResponse);
            const serializedSignedTransaction = '1acc010a640a20592a4fbb7263c59d450e651df96620dc9208ee7c7d9d6f2fdcb91c53f88312611a40105b7d250c81f3705bc0b85168ce3fd00330131bb7701378681c8c2e6a09a91828715e7334f4ef28d20ff09887c6e87c0a5c693e23824c26f3ba161fce0448050a640a20a6905095616c3cfaa1bf61b53de30e938ce4112c3cc4d25393ec6b9bf4dea0631a40bf98c5b89b7a08544edaa1f4c08a0dfa6ec3f78b7e2fd27049283984050f38ccf0303ee57a377cc0a725ffd99d69e9fd914770ab0949ba556d84b3b00cb07e0d22500a130a0608cea8c1ad0612090800100018f185d40312060800100018031880c2d72f220308b40132013472240a220a0f0a090800100018f185d40310d3b0510a0f0a090800100018c484d30310d4b051';
            const result = await basecoin.broadcastTransaction({ serializedSignedTransaction, startTime });
            broadcastStub.callCount.should.equal(1);
            result.should.deepEqual(expectedResponse);
        });
        it('should throw if the startTime is expired', async function () {
            const startTime = (Date.now() / 1000 - 2000).toFixed(); // timestamp in seconds, 2000 seconds from now
            const serializedSignedTransaction = '1acc010a640a20592a4fbb7263c59d450e651df96620dc9208ee7c7d9d6f2fdcb91c53f88312611a40105b7d250c81f3705bc0b85168ce3fd00330131bb7701378681c8c2e6a09a91828715e7334f4ef28d20ff09887c6e87c0a5c693e23824c26f3ba161fce0448050a640a20a6905095616c3cfaa1bf61b53de30e938ce4112c3cc4d25393ec6b9bf4dea0631a40bf98c5b89b7a08544edaa1f4c08a0dfa6ec3f78b7e2fd27049283984050f38ccf0303ee57a377cc0a725ffd99d69e9fd914770ab0949ba556d84b3b00cb07e0d22500a130a0608cea8c1ad0612090800100018f185d40312060800100018031880c2d72f220308b40132013472240a220a0f0a090800100018f185d40310d3b0510a0f0a090800100018c484d30310d4b051';
            await assert_1.default.rejects(async () => {
                await basecoin.broadcastTransaction({ serializedSignedTransaction, startTime });
            }, (error) => {
                assert_1.default.ok(error.message.includes('Failed to broadcast transaction, error: startTime window expired'));
                return true;
            });
        });
        it('should throw if the serializedSignedTransaction is invalid', async function () {
            const startTime = (Date.now() / 1000 - 10).toFixed(); // timestamp in seconds, 10 seconds from now
            const serializedSignedTransaction = 'randomstring';
            await assert_1.default.rejects(async () => {
                await basecoin.broadcastTransaction({ serializedSignedTransaction, startTime });
            });
        });
        it('should throw if the startTime in the tx is invalid', async function () {
            const expectedResponse = 'transaction 0.0.7668465@1706056301.000000000 failed precheck with status INVALID_TRANSACTION_START';
            sandBox.stub(src_1.Hbar.prototype, 'clientBroadcastTransaction').rejects(new Error(expectedResponse));
            const serializedSignedTransaction = '1acc010a640a20592a4fbb7263c59d450e651df96620dc9208ee7c7d9d6f2fdcb91c53f88312611a40105b7d250c81f3705bc0b85168ce3fd00330131bb7701378681c8c2e6a09a91828715e7334f4ef28d20ff09887c6e87c0a5c693e23824c26f3ba161fce0448050a640a20a6905095616c3cfaa1bf61b53de30e938ce4112c3cc4d25393ec6b9bf4dea0631a40bf98c5b89b7a08544edaa1f4c08a0dfa6ec3f78b7e2fd27049283984050f38ccf0303ee57a377cc0a725ffd99d69e9fd914770ab0949ba556d84b3b00cb07e0d22500a130a0608cea8c1ad0612090800100018f185d40312060800100018031880c2d72f220308b40132013472240a220a0f0a090800100018f185d40310d3b0510a0f0a090800100018c484d30310d4b051';
            await assert_1.default.rejects(async () => {
                await basecoin.broadcastTransaction({ serializedSignedTransaction });
            }, { message: expectedResponse });
        });
    });
    describe('deriveKeyWithSeed', function () {
        it('should derive key with seed', function () {
            (() => {
                basecoin.deriveKeyWithSeed('test');
            }).should.throw('method deriveKeyWithSeed not supported for eddsa curve');
        });
    });
    describe('Generate wallet Root key pair: ', () => {
        it('should generate key pair', () => {
            const kp = basecoin.generateRootKeyPair();
            basecoin.isValidPub(kp.pub).should.equal(true);
            const keypair = new src_1.KeyPair({ prv: kp.prv }).getKeys(true);
            keypair.should.have.property('prv');
            keypair.prv?.should.equal(kp.prv.slice(0, 64));
            keypair.pub.should.equal(kp.pub);
        });
        it('should generate key pair from seed', () => {
            const seed = Buffer.from('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60', 'hex');
            const kp = basecoin.generateRootKeyPair(seed);
            basecoin.isValidPub(kp.pub).should.equal(true);
            kp.pub.should.equal('d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a');
            kp.prv.should.equal('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a');
            const keypair = new src_1.KeyPair({ prv: kp.prv }).getKeys(true);
            keypair.should.have.property('prv');
            keypair.prv?.should.equal(kp.prv.slice(0, 64));
            keypair.pub.should.equal(kp.pub);
        });
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGJhci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvdW5pdC9oYmFyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsb0RBQTRCO0FBRTVCLDBDQUE0QjtBQUM1QixrREFBeUM7QUFDekMsbUNBQXFDO0FBQ3JDLCtDQUF5QztBQUN6Qyw4Q0FBMEQ7QUFDMUQsNENBQTBDO0FBRTFDLDhDQUF5QztBQUV6QywyREFBNkM7QUFDN0MsbUNBQTREO0FBQzVELDJEQUF3RDtBQUV4RCxRQUFRLENBQUMsbUJBQW1CLEVBQUU7SUFDNUIsSUFBSSxLQUFtQixDQUFDO0lBQ3hCLElBQUksUUFBUSxDQUFDO0lBQ2IsSUFBSSxLQUFLLENBQUM7SUFFVixNQUFNLENBQUM7UUFDTCxLQUFLLEdBQUcsb0JBQVMsQ0FBQyxRQUFRLENBQUMsa0JBQVEsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3RELEtBQUssQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLFdBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNsRCxLQUFLLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxVQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDaEQsZUFBUyxDQUFDLHVCQUF1QixFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsZUFBZSxFQUFFLEVBQUUsRUFBRTtZQUN4RSxLQUFLLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxlQUFlLENBQUMsQ0FBQztRQUM1QyxDQUFDLENBQUMsQ0FBQztRQUNILEtBQUssQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQzNCLFFBQVEsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQy9CLEtBQUssR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ25DLENBQUMs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LENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnO1xuXG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgU2lub24sIHsgU2lub25TdHViIH0gZnJvbSAnc2lub24nO1xuaW1wb3J0IHsgcmFuZG9tQnl0ZXMgfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgQmlnTnVtYmVyIH0gZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCB7IFRlc3RCaXRHbywgVGVzdEJpdEdvQVBJIH0gZnJvbSAnQGJpdGdvL3Nkay10ZXN0JztcbmltcG9ydCB7IEJpdEdvQVBJIH0gZnJvbSAnQGJpdGdvL3Nkay1hcGknO1xuaW1wb3J0IHsgVHhEYXRhLCBUcmFuc2ZlciB9IGZyb20gJy4uLy4uL3NyYy9saWIvaWZhY2UnO1xuaW1wb3J0IHsgV2FsbGV0IH0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcblxuaW1wb3J0ICogYXMgVGVzdERhdGEgZnJvbSAnLi4vZml4dHVyZXMvaGJhcic7XG5pbXBvcnQgeyBIYmFyLCBUaGJhciwgS2V5UGFpciwgSGJhclRva2VuIH0gZnJvbSAnLi4vLi4vc3JjJztcbmltcG9ydCB7IGdldEJ1aWxkZXJGYWN0b3J5IH0gZnJvbSAnLi9nZXRCdWlsZGVyRmFjdG9yeSc7XG5cbmRlc2NyaWJlKCdIZWRlcmEgSGFzaGdyYXBoOicsIGZ1bmN0aW9uICgpIHtcbiAgbGV0IGJpdGdvOiBUZXN0Qml0R29BUEk7XG4gIGxldCBiYXNlY29pbjtcbiAgbGV0IHRva2VuO1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAnbW9jaycgfSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCd0aGJhcicsIFRoYmFyLmNyZWF0ZUluc3RhbmNlKTtcbiAgICBiaXRnby5zYWZlUmVnaXN0ZXIoJ2hiYXInLCBIYmFyLmNyZWF0ZUluc3RhbmNlKTtcbiAgICBIYmFyVG9rZW4uY3JlYXRlVG9rZW5Db25zdHJ1Y3RvcnMoKS5mb3JFYWNoKCh7IG5hbWUsIGNvaW5Db25zdHJ1Y3RvciB9KSA9PiB7XG4gICAgICBiaXRnby5zYWZlUmVnaXN0ZXIobmFtZSwgY29pbkNvbnN0cnVjdG9yKTtcbiAgICB9KTtcbiAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICBiYXNlY29pbiA9IGJpdGdvLmNvaW4oJ3RoYmFyJyk7XG4gICAgdG9rZW4gPSBiaXRnby5jb2luKCd0aGJhcjp1c2RjJyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgaW5zdGFudGlhdGUgdGhlIGNvaW4nLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgYmFzZWNvaW4gPSBiaXRnby5jb2luKCdoYmFyJyk7XG4gICAgYmFzZWNvaW4uc2hvdWxkLmJlLmFuLmluc3RhbmNlb2YoSGJhcik7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgY2hlY2sgdmFsaWQgYWRkcmVzc2VzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGJhZEFkZHJlc3NlcyA9IFtcbiAgICAgICcnLFxuICAgICAgJzAuMCcsXG4gICAgICAnWVowOWZkLScsXG4gICAgICAnMC4wLjAuYScsXG4gICAgICAnc2FkYXNkZmdnZycsXG4gICAgICAnMC4yLmEuYicsXG4gICAgICAnMC4wLjEwMD89c2tzamQnLFxuICAgICAgJzAuMC40MTA5OD9tZW1vSWQ9JyxcbiAgICBdO1xuICAgIGNvbnN0IGdvb2RBZGRyZXNzZXMgPSBbXG4gICAgICAnMCcsXG4gICAgICAnMC4wLjAnLFxuICAgICAgJzAuMC40MTA5OCcsXG4gICAgICAnMC4wLjA/bWVtb0lkPTg0JyxcbiAgICAgICcwLjAuNDEwOTgnLFxuICAgICAgJzAuMC40MTA5OD9tZW1vSWQ9MmFhYWFhJyxcbiAgICAgICcwLjAuNDEwOTg/bWVtb0lkPTEnLFxuICAgIF07XG5cbiAgICBiYWRBZGRyZXNzZXMubWFwKChhZGRyKSA9PiB7XG4gICAgICBiYXNlY29pbi5pc1ZhbGlkQWRkcmVzcyhhZGRyKS5zaG91bGQuZXF1YWwoZmFsc2UpO1xuICAgIH0pO1xuICAgIGdvb2RBZGRyZXNzZXMubWFwKChhZGRyKSA9PiB7XG4gICAgICBiYXNlY29pbi5pc1ZhbGlkQWRkcmVzcyhhZGRyKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBoZXhBZGRyZXNzID0gJzB4MjNDM0UyMjdCRTk3MjgxQTcwQTU0OWM3ZERCOGQ1Q2FhZDNFN0M4NCc7XG4gICAgYmFzZWNvaW4uaXNWYWxpZEFkZHJlc3MoaGV4QWRkcmVzcykuc2hvdWxkLmVxdWFsKGZhbHNlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBleHBsYWluIGEgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdHggPSBKU09OLnBhcnNlKFRlc3REYXRhLnJhd1RyYW5zYWN0aW9uRm9yRXhwbGFpbik7XG4gICAgY29uc3QgZXhwbGFpbiA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih0eCk7XG5cbiAgICBleHBsYWluLmlkLnNob3VsZC5lcXVhbCgnMC4wLjQzMjg1QDE2MDA1Mjk4MDAuNjQzMDkzNTg2Jyk7XG4gICAgZXhwbGFpbi5vdXRwdXRBbW91bnQuc2hvdWxkLmVxdWFsKCcyMjAwMDAwMDAwJyk7XG4gICAgZXhwbGFpbi50aW1lc3RhbXAuc2hvdWxkLmVxdWFsKCcxNjAwNTI5ODAwLjY0MzA5MzU4NicpO1xuICAgIGV4cGxhaW4uZXhwaXJhdGlvbi5zaG91bGQuZXF1YWwoJzE4MCcpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKCcyMjAwMDAwMDAwJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKCcwLjAuNDMyODMnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0ubWVtby5zaG91bGQuZXF1YWwoJzEnKTtcbiAgICBleHBsYWluLmZlZS5zaG91bGQuZXF1YWwoMTE2MDQwNyk7XG4gICAgZXhwbGFpbi5jaGFuZ2VBbW91bnQuc2hvdWxkLmVxdWFsKCcwJyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgZXhwbGFpbiBhIHRva2VuIHRyYW5zZmVyIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHRva2VuVHJhbnNmZXJQYXJhbSA9IHtcbiAgICAgIHR4SGV4OiBUZXN0RGF0YS5VTlNJR05FRF9UT0tFTl9UUkFOU0ZFUixcbiAgICAgIGZlZUluZm86IHtcbiAgICAgICAgc2l6ZTogMTAwMCxcbiAgICAgICAgZmVlOiAxMTYwNDA3LFxuICAgICAgICBmZWVSYXRlOiAxMTYwNDA3LFxuICAgICAgfSxcbiAgICB9O1xuICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24odG9rZW5UcmFuc2ZlclBhcmFtKTtcblxuICAgIGV4cGxhaW4uaWQuc2hvdWxkLmVxdWFsKCcwLjAuODEzMjBAMTU5NjExMDQ5My4zNzI2NDY1NzAnKTtcbiAgICBleHBsYWluLm91dHB1dEFtb3VudC5zaG91bGQuZXF1YWwoJzAnKTtcbiAgICBleHBsYWluLnRpbWVzdGFtcC5zaG91bGQuZXF1YWwoJzE1OTYxMTA0OTMuMzcyNjQ2NTcwJyk7XG4gICAgZXhwbGFpbi5leHBpcmF0aW9uLnNob3VsZC5lcXVhbCgnMTgwJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoJzEwJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKCcwLjAuNzU4NjEnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0ubWVtby5zaG91bGQuZXF1YWwoJycpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS50b2tlbk5hbWUuc2hvdWxkLmVxdWFsKCd0aGJhcjp1c2RjJyk7XG4gICAgZXhwbGFpbi5mZWUuc2hvdWxkLmVxdWFsKDExNjA0MDcpO1xuICAgIGV4cGxhaW4uY2hhbmdlQW1vdW50LnNob3VsZC5lcXVhbCgnMCcpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGV4cGxhaW4gYSBtdWx0aXJlY2lwaWVudHMgdHJhbnNmZXIgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgbXVsdGlUcmFuc2ZlclBhcmFtID0ge1xuICAgICAgdHhIZXg6IFRlc3REYXRhLlVOU0lHTkVEX01VTFRJX1RSQU5TRkVSLFxuICAgICAgZmVlSW5mbzoge1xuICAgICAgICBzaXplOiAxMDAwLFxuICAgICAgICBmZWU6IDExNjA0MDcsXG4gICAgICAgIGZlZVJhdGU6IDExNjA0MDcsXG4gICAgICB9LFxuICAgIH07XG4gICAgY29uc3QgZXhwbGFpbiA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbihtdWx0aVRyYW5zZmVyUGFyYW0pO1xuXG4gICAgZXhwbGFpbi5pZC5zaG91bGQuZXF1YWwoJzAuMC44MTMyMEAxNTk2MTEwNDkzLjM3MjY0NjU3MCcpO1xuICAgIGV4cGxhaW4ub3V0cHV0QW1vdW50LnNob3VsZC5lcXVhbCgnMjUnKTtcbiAgICBleHBsYWluLmV4cGlyYXRpb24uc2hvdWxkLmVxdWFsKCcxODAnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0uYW1vdW50LnNob3VsZC5lcXVhbCgnMTAnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwoJzAuMC43NTg2MScpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS5tZW1vLnNob3VsZC5lcXVhbCgnJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzFdLmFtb3VudC5zaG91bGQuZXF1YWwoJzE1Jyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzFdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKCcwLjAuNzg5NjMnKTtcbiAgICBleHBsYWluLmZlZS5zaG91bGQuZXF1YWwoMTE2MDQwNyk7XG4gICAgZXhwbGFpbi5jaGFuZ2VBbW91bnQuc2hvdWxkLmVxdWFsKCcwJyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgZXhwbGFpbiBhIG11bHRpcmVjaXBpZW50cyB0b2tlbiB0cmFuc2ZlciB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0b2tlbk11bHRpVHJhbnNmZXJQYXJhbSA9IHtcbiAgICAgIHR4SGV4OiBUZXN0RGF0YS5VTlNJR05FRF9UT0tFTl9NVUxUSV9UUkFOU0ZFUixcbiAgICAgIGZlZUluZm86IHtcbiAgICAgICAgc2l6ZTogMTAwMCxcbiAgICAgICAgZmVlOiAxMTYwNDA3LFxuICAgICAgICBmZWVSYXRlOiAxMTYwNDA3LFxuICAgICAgfSxcbiAgICB9O1xuICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24odG9rZW5NdWx0aVRyYW5zZmVyUGFyYW0pO1xuXG4gICAgZXhwbGFpbi5pZC5zaG91bGQuZXF1YWwoJzAuMC44MTMyMEAxNTk2MTEwNDkzLjM3MjY0NjU3MCcpO1xuICAgIGV4cGxhaW4ub3V0cHV0QW1vdW50LnNob3VsZC5lcXVhbCgnMCcpO1xuICAgIGV4cGxhaW4udGltZXN0YW1wLnNob3VsZC5lcXVhbCgnMTU5NjExMDQ5My4zNzI2NDY1NzAnKTtcbiAgICBleHBsYWluLmV4cGlyYXRpb24uc2hvdWxkLmVxdWFsKCcxODAnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0uYW1vdW50LnNob3VsZC5lcXVhbCgnMTAnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwoJzAuMC43NTg2MScpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS5tZW1vLnNob3VsZC5lcXVhbCgnJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLnRva2VuTmFtZS5zaG91bGQuZXF1YWwoJ3RoYmFyOnVzZGMnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMV0uYW1vdW50LnNob3VsZC5lcXVhbCgnMTUnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMV0uYWRkcmVzcy5zaG91bGQuZXF1YWwoJzAuMC43ODk2MycpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1sxXS50b2tlbk5hbWUuc2hvdWxkLmVxdWFsKCd0aGJhcjp1c2RjJyk7XG4gICAgZXhwbGFpbi5mZWUuc2hvdWxkLmVxdWFsKDExNjA0MDcpO1xuICAgIGV4cGxhaW4uY2hhbmdlQW1vdW50LnNob3VsZC5lcXVhbCgnMCcpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGV4cGxhaW4gYSB0b2tlbiBhc3NvY2lhdGUgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdG9rZW5Bc3NvY2lhdGVQYXJhbSA9IHtcbiAgICAgIHR4SGV4OiBUZXN0RGF0YS5VTlNJR05FRF9UT0tFTl9BU1NPQ0lBVEUsXG4gICAgICBmZWVJbmZvOiB7XG4gICAgICAgIHNpemU6IDEwMDAsXG4gICAgICAgIGZlZTogMTE2MDQwNyxcbiAgICAgICAgZmVlUmF0ZTogMTE2MDQwNyxcbiAgICAgIH0sXG4gICAgfTtcbiAgICBjb25zdCBleHBsYWluID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHRva2VuQXNzb2NpYXRlUGFyYW0pO1xuXG4gICAgZXhwbGFpbi5pZC5zaG91bGQuZXF1YWwoJzAuMC44MTMyMEAxNTk2MTEwNDkzLjM3MjY0NjU3MCcpO1xuICAgIGV4cGxhaW4ub3V0cHV0QW1vdW50LnNob3VsZC5lcXVhbCgnMCcpO1xuICAgIGV4cGxhaW4udGltZXN0YW1wLnNob3VsZC5lcXVhbCgnMTU5NjExMDQ5My4zNzI2NDY1NzAnKTtcbiAgICBleHBsYWluLmV4cGlyYXRpb24uc2hvdWxkLmVxdWFsKCcxODAnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0uYW1vdW50LnNob3VsZC5lcXVhbCgnMCcpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbCgnMC4wLjgxMzIwJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLm1lbW8uc2hvdWxkLmVxdWFsKCcnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0udG9rZW5OYW1lLnNob3VsZC5lcXVhbCgndGhiYXI6dXNkYycpO1xuICAgIGV4cGxhaW4uZmVlLnNob3VsZC5lcXVhbCgxMTYwNDA3KTtcbiAgICBleHBsYWluLmNoYW5nZUFtb3VudC5zaG91bGQuZXF1YWwoJzAnKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB2ZXJpZnkgaXNXYWxsZXRBZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGJhc2VBZGRyZXNzID0gJzAuMC40MTA5OCc7XG4gICAgY29uc3QgdmFsaWRBZGRyZXNzMSA9ICcwLjAuNDEwOTg/bWVtb0lkPTEnO1xuICAgIGNvbnN0IHZhbGlkQWRkcmVzczIgPSAnMC4wLjQxMDk4P21lbW9JZD0yJztcbiAgICBjb25zdCB1bnJlbGF0ZWRWYWxpZEFkZHJlc3MgPSAnMC4xLjQxMDk4P21lbW9JZD0xJztcbiAgICBjb25zdCBpbnZhbGlkQWRkcmVzcyA9ICcwLjAuMC5hJztcbiAgICAoYXdhaXQgYmFzZWNvaW4uaXNXYWxsZXRBZGRyZXNzKHsgYWRkcmVzczogdmFsaWRBZGRyZXNzMSwgYmFzZUFkZHJlc3MgfSkpLnNob3VsZC50cnVlKCk7XG4gICAgKGF3YWl0IGJhc2Vjb2luLmlzV2FsbGV0QWRkcmVzcyh7IGFkZHJlc3M6IHZhbGlkQWRkcmVzczIsIGJhc2VBZGRyZXNzIH0pKS5zaG91bGQudHJ1ZSgpO1xuICAgIChhd2FpdCBiYXNlY29pbi5pc1dhbGxldEFkZHJlc3MoeyBhZGRyZXNzOiB2YWxpZEFkZHJlc3MyLCBiYXNlQWRkcmVzczogdmFsaWRBZGRyZXNzMSB9KSkuc2hvdWxkLnRydWUoKTtcbiAgICAoYXdhaXQgYmFzZWNvaW4uaXNXYWxsZXRBZGRyZXNzKHsgYWRkcmVzczogdW5yZWxhdGVkVmFsaWRBZGRyZXNzLCBiYXNlQWRkcmVzcyB9KSkuc2hvdWxkLmZhbHNlKCk7XG5cbiAgICBhc3NlcnQucmVqZWN0cyhcbiAgICAgIGFzeW5jICgpID0+IGJhc2Vjb2luLmlzV2FsbGV0QWRkcmVzcyh7IGFkZHJlc3M6IGludmFsaWRBZGRyZXNzLCBiYXNlQWRkcmVzcyB9KSxcbiAgICAgIGBpbnZhbGlkIGFkZHJlc3MgJHtpbnZhbGlkQWRkcmVzc31gXG4gICAgKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0tleXBhaXJzOicsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGEga2V5cGFpciBmcm9tIHJhbmRvbSBzZWVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qga2V5UGFpciA9IGJhc2Vjb2luLmdlbmVyYXRlS2V5UGFpcigpO1xuICAgICAga2V5UGFpci5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncHViJyk7XG4gICAgICBrZXlQYWlyLnNob3VsZC5oYXZlLnByb3BlcnR5KCdwcnYnKTtcblxuICAgICAgYmFzZWNvaW4uaXNWYWxpZFB1YihrZXlQYWlyLnB1Yikuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBhIGtleXBhaXIgZnJvbSBhIHNlZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzZWVkVGV4dCA9ICc4MDM1MGI0MjA4ZDM4MWZiZmUyMjc2YTMyNjYwMzA0OWZlNTAwNzMxYzQ2ZDNjOTkzNmI1Y2UwMzZiNTEzNzdmJztcbiAgICAgIGNvbnN0IHNlZWQgPSBCdWZmZXIuZnJvbShzZWVkVGV4dCwgJ2hleCcpO1xuICAgICAgY29uc3Qga2V5UGFpciA9IGJhc2Vjb2luLmdlbmVyYXRlS2V5UGFpcihzZWVkKTtcblxuICAgICAga2V5UGFpci5wcnYuc2hvdWxkLmVxdWFsKFxuICAgICAgICAnMzAyZTAyMDEwMDMwMDUwNjAzMmI2NTcwMDQyMjA0MjA4MDM1MGI0MjA4ZDM4MWZiZmUyMjc2YTMyNjYwMzA0OWZlNTAwNzMxYzQ2ZDNjOTkzNmI1Y2UwMzZiNTEzNzdmJ1xuICAgICAgKTtcbiAgICAgIGtleVBhaXIucHViLnNob3VsZC5lcXVhbChcbiAgICAgICAgJzMwMmEzMDA1MDYwMzJiNjU3MDAzMjEwMDljYzQwMmI1Yzc1MjE0MjY5YzI4MjZlM2M2MTE5Mzc3Y2FiNmMzNjc2MDEzMzg2NjFjODdhNGUwN2M2ZTAzMzMnXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2YWxpZGF0ZSBhIHN0ZWxsYXIgc2VlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGJhc2Vjb2luLmlzU3RlbGxhclNlZWQoJ1NCTVdMTlY3NUJQSTJWQjRHMjdSV09NQUJWUlRTU0Y3MzUyQ0NZR1ZFTFpEU0hDWFdDWUZLWElYJykuc2hvdWxkLm9rKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNvbnZlcnQgYSBzdGVsbGFyIHNlZWQgdG8gYW4gaGJhciBwcnYnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzZWVkID0gYmFzZWNvaW4uY29udmVydEZyb21TdGVsbGFyU2VlZCgnU0JNV0xOVjc1QlBJMlZCNEcyN1JXT01BQlZSVFNTRjczNTJDQ1lHVkVMWkRTSENYV0NZRktYSVgnKTtcbiAgICAgIHNlZWQuc2hvdWxkLmVxdWFsKFxuICAgICAgICAnMzAyZTAyMDEwMDMwMDUwNjAzMmI2NTcwMDQyMjA0MjA1OTY1YjZiZmU4NWU4ZDU0M2MzNmJmMWIzOTgwMGQ2MzM5NDhiZmRmNzQyMTYwZDUyMmYyMzkxYzU3YjBiMDU1J1xuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1ZlcmlmeSBUcmFuc2FjdGlvbjonLCAoKSA9PiB7XG4gICAgbGV0IG5ld1R4UHJlYnVpbGQ7XG4gICAgbGV0IG5ld1R4UGFyYW1zO1xuICAgIGxldCBuZXdUeFBhcmFtc1dpdGhFcnJvcjtcbiAgICBsZXQgbmV3VHhQYXJhbXNXaXRoRXh0cmFEYXRhO1xuICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiAnbGlvbnRlc3RlMjEyJyxcbiAgICAgICAgICBhbW91bnQ6ICcxMDAwJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICB0eEhleDogVGVzdERhdGEuVU5TSUdORURfTVVMVElfVFJBTlNGRVIsXG4gICAgICB0eGlkOiAnNTg2YzViNTliMTBiMTM0ZDA0YzE2YWMxYjI3M2ZlM2M1NTI5ZjM0YWVmNzVkYjQ0NTZjZDQ2OWM1Y2RhYzdlMicsXG4gICAgICBpc1ZvdGluZ1RyYW5zYWN0aW9uOiBmYWxzZSxcbiAgICAgIGNvaW46ICd0aGJhcicsXG4gICAgICBmZWVJbmZvOiB7XG4gICAgICAgIHNpemU6IDEwMDAsXG4gICAgICAgIGZlZTogMTE2MDQwNyxcbiAgICAgICAgZmVlUmF0ZTogMTE2MDQwNyxcbiAgICAgIH0sXG4gICAgfTtcbiAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgIHR4UHJlYnVpbGQsXG4gICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiAnMC4wLjc1ODYxJyxcbiAgICAgICAgICBhbW91bnQ6ICcxMCcsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiAnMC4wLjc4OTYzJyxcbiAgICAgICAgICBhbW91bnQ6ICcxNScsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH07XG4gICAgY29uc3QgbWVtbyA9IHsgdmFsdWU6ICcnIH07XG4gICAgY29uc3QgdHhQYXJhbXNXaXRoRXJyb3IgPSB7XG4gICAgICB0eFByZWJ1aWxkLFxuICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogJzAuMC43NTg2MScsXG4gICAgICAgICAgYW1vdW50OiAnMTAwMCcsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH07XG4gICAgY29uc3QgdHhQYXJhbXNXaXRoRXh0cmFEYXRhID0ge1xuICAgICAgdHhQcmVidWlsZCxcbiAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6ICcwLjAuNzU4NjEnLFxuICAgICAgICAgIGFtb3VudDogJzEwJyxcbiAgICAgICAgICBkYXRhOiB1bmRlZmluZWQsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiAnMC4wLjc4OTYzJyxcbiAgICAgICAgICBhbW91bnQ6ICcxNScsXG4gICAgICAgICAgZGF0YTogdW5kZWZpbmVkLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuICAgIGNvbnN0IHdhbGxldERhdGEgPSB7XG4gICAgICBpZDogJzViMzQyNTJmMWJmMzQ5OTMwZTM0MDIwYTAwMDAwMDAwJyxcbiAgICAgIGNvaW46ICd0aGJhcicsXG4gICAgICBrZXlzOiBbXG4gICAgICAgICc1YjM0MjRmOTFiZjM0OTkzMGUzNDAxNzUwMDAwMDAwMCcsXG4gICAgICAgICc1YjM0MjRmOTFiZjM0OTkzMGUzNDAxNzYwMDAwMDAwMCcsXG4gICAgICAgICc1YjM0MjRmOTFiZjM0OTkzMGUzNDAxNzcwMDAwMDAwMCcsXG4gICAgICBdLFxuICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgIGJhc2VBZGRyZXNzOiAnMC4wLjI5MzUnLFxuICAgICAgfSxcbiAgICAgIG11bHRpc2lnVHlwZTogJ29uY2hhaW4nLFxuICAgIH07XG4gICAgY29uc3Qgd2FsbGV0T2JqID0gbmV3IFdhbGxldChiaXRnbywgYmFzZWNvaW4sIHdhbGxldERhdGEpO1xuXG4gICAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICAgIG5ld1R4UHJlYnVpbGQgPSAoKSA9PiB7XG4gICAgICAgIHJldHVybiBfLmNsb25lRGVlcCh0eFByZWJ1aWxkKTtcbiAgICAgIH07XG4gICAgICBuZXdUeFBhcmFtcyA9ICgpID0+IHtcbiAgICAgICAgcmV0dXJuIF8uY2xvbmVEZWVwKHR4UGFyYW1zKTtcbiAgICAgIH07XG4gICAgICBuZXdUeFBhcmFtc1dpdGhFcnJvciA9ICgpID0+IHtcbiAgICAgICAgcmV0dXJuIF8uY2xvbmVEZWVwKHR4UGFyYW1zV2l0aEVycm9yKTtcbiAgICAgIH07XG4gICAgICBuZXdUeFBhcmFtc1dpdGhFeHRyYURhdGEgPSAoKSA9PiB7XG4gICAgICAgIHJldHVybiBfLmNsb25lRGVlcCh0eFBhcmFtc1dpdGhFeHRyYURhdGEpO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IG5hdGl2ZSB0cmFuc2ZlciB0cmFuc2FjdGlvbnMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG5ld1R4UGFyYW1zKCk7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0gbmV3VHhQcmVidWlsZCgpO1xuICAgICAgY29uc3QgdmFsaWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXMsXG4gICAgICAgIHR4UHJlYnVpbGQsXG4gICAgICAgIG1lbW8sXG4gICAgICAgIHdhbGxldDogd2FsbGV0T2JqLFxuICAgICAgfSBhcyBhbnkpO1xuICAgICAgdmFsaWRUcmFuc2FjdGlvbi5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdmVyaWZ5IHdoZW4gaW5wdXQgYHJlY2lwaWVudHNgIGlzIGFic2VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbmV3VHhQYXJhbXMoKTtcbiAgICAgIHR4UGFyYW1zLnJlY2lwaWVudHMgPSB1bmRlZmluZWQ7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0gbmV3VHhQcmVidWlsZCgpO1xuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIG1lbW86IG1lbW8sIHdhbGxldDogd2FsbGV0T2JqIH0gYXMgYW55KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbWlzc2luZyByZXF1aXJlZCB0eCBwYXJhbXMgcHJvcGVydHkgcmVjaXBpZW50cycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHZlcmlmeSB0cmFuc2FjdGlvbnMgd2hlbiBoYXZlIGRpZmZlcmVudCByZWNpcGllbnRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQYXJhbXMgPSBuZXdUeFBhcmFtc1dpdGhFcnJvcigpO1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IG5ld1R4UHJlYnVpbGQoKTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCBtZW1vLCB3YWxsZXQ6IHdhbGxldE9iaiB9IGFzIGFueSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ1R4IG91dHB1dHMgZG9lcyBub3QgbWF0Y2ggd2l0aCBleHBlY3RlZCB0eFBhcmFtcyByZWNpcGllbnRzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHN1Y2NlZWQgdG8gdmVyaWZ5IHRyYW5zYWN0aW9ucyB3aGVuIHJlY2lwaWVudHMgaGFzIGV4dHJhIGRhdGEnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG5ld1R4UGFyYW1zV2l0aEV4dHJhRGF0YSgpO1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IG5ld1R4UHJlYnVpbGQoKTtcbiAgICAgIGNvbnN0IHZhbGlkVHJhbnNhY3Rpb24gPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zLFxuICAgICAgICB0eFByZWJ1aWxkLFxuICAgICAgICBtZW1vLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldE9iaixcbiAgICAgIH0gYXMgYW55KTtcbiAgICAgIHZhbGlkVHJhbnNhY3Rpb24uc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgY3JlYXRlIGFzc29jaWF0ZWQgdG9rZW4gYWNjb3VudCB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbmV3VHhQYXJhbXMoKTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG4gICAgICB0eFByZWJ1aWxkLnR4SGV4ID0gVGVzdERhdGEuVU5TSUdORURfVE9LRU5fQVNTT0NJQVRFO1xuICAgICAgdHhQYXJhbXMucmVjaXBpZW50cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6ICcwLjAuODEzMjAnLFxuICAgICAgICAgIGFtb3VudDogJzAnLFxuICAgICAgICAgIHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnLFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICAgIGNvbnN0IHZhbGlkVHJhbnNhY3Rpb24gPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zLFxuICAgICAgICB0eFByZWJ1aWxkLFxuICAgICAgICBtZW1vLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldE9iaixcbiAgICAgIH0gYXMgYW55KTtcbiAgICAgIHZhbGlkVHJhbnNhY3Rpb24uc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHZlcmlmeSBjcmVhdGUgYXNzb2NpYXRlZCB0b2tlbiBhY2NvdW50IHRyYW5zYWN0aW9uIHdpdGggbWlzbWF0Y2ggcmVjaXBpZW50cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbmV3VHhQYXJhbXMoKTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG4gICAgICB0eFByZWJ1aWxkLnR4SGV4ID0gVGVzdERhdGEuVU5TSUdORURfVE9LRU5fQVNTT0NJQVRFO1xuICAgICAgdHhQYXJhbXMucmVjaXBpZW50cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6ICcwLjAuODEzMjEnLFxuICAgICAgICAgIGFtb3VudDogJzAnLFxuICAgICAgICAgIHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnLFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCBtZW1vLCB3YWxsZXQ6IHdhbGxldE9iaiB9IGFzIGFueSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ1R4IG91dHB1dHMgZG9lcyBub3QgbWF0Y2ggd2l0aCBleHBlY3RlZCB0eFBhcmFtcyByZWNpcGllbnRzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZlcmlmeSB0b2tlbiB0cmFuc2ZlciB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbmV3VHhQYXJhbXMoKTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG4gICAgICB0eFByZWJ1aWxkLnR4SGV4ID0gVGVzdERhdGEuVU5TSUdORURfVE9LRU5fTVVMVElfVFJBTlNGRVI7XG4gICAgICB0eFBhcmFtcy5yZWNpcGllbnRzID0gW1xuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogJzAuMC43NTg2MScsXG4gICAgICAgICAgYW1vdW50OiAnMTAnLFxuICAgICAgICAgIHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogJzAuMC43ODk2MycsXG4gICAgICAgICAgYW1vdW50OiAnMTUnLFxuICAgICAgICAgIHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnLFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICAgIGNvbnN0IHZhbGlkVHJhbnNhY3Rpb24gPSBhd2FpdCB0b2tlbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zLFxuICAgICAgICB0eFByZWJ1aWxkLFxuICAgICAgICBtZW1vLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldE9iaixcbiAgICAgIH0gYXMgYW55KTtcbiAgICAgIHZhbGlkVHJhbnNhY3Rpb24uc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgdG9rZW4gdHJhbnNmZXIgdHJhbnNhY3Rpb24gd2l0aCBhbnkgdG9rZW4gbmFtZSBvbiB0b2tlbiBiYXNlIGNvaW4nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG5ld1R4UGFyYW1zKCk7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0gbmV3VHhQcmVidWlsZCgpO1xuICAgICAgdHhQcmVidWlsZC50eEhleCA9IFRlc3REYXRhLlVOU0lHTkVEX1RPS0VOX01VTFRJX1RSQU5TRkVSO1xuICAgICAgdHhQYXJhbXMucmVjaXBpZW50cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6ICcwLjAuNzU4NjEnLFxuICAgICAgICAgIGFtb3VudDogJzEwJyxcbiAgICAgICAgICB0b2tlbk5hbWU6ICd0aGJhcjp1c2RjJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6ICcwLjAuNzg5NjMnLFxuICAgICAgICAgIGFtb3VudDogJzE1JyxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgICAoYXdhaXQgdG9rZW4udmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgbWVtbywgd2FsbGV0OiB3YWxsZXRPYmogfSBhcyBhbnkpKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gdmVyaWZ5IHRva2VuIHRyYW5zZmVyIHdpdGggbWlzbWF0Y2hlZCByZWNpcGllbnRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQYXJhbXMgPSBuZXdUeFBhcmFtcygpO1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IG5ld1R4UHJlYnVpbGQoKTtcbiAgICAgIHR4UHJlYnVpbGQudHhIZXggPSBUZXN0RGF0YS5VTlNJR05FRF9UT0tFTl9NVUxUSV9UUkFOU0ZFUjtcbiAgICAgIHR4UGFyYW1zLnJlY2lwaWVudHMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiAnMC4wLjc1ODYxJyxcbiAgICAgICAgICBhbW91bnQ6ICcxMScsXG4gICAgICAgICAgdG9rZW5OYW1lOiAndGhiYXI6dXNkYycsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiAnMC4wLjc4OTYzJyxcbiAgICAgICAgICBhbW91bnQ6ICcxNScsXG4gICAgICAgIH0sXG4gICAgICBdO1xuICAgICAgYXdhaXQgdG9rZW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIG1lbW8sIHdhbGxldDogd2FsbGV0T2JqIH0gYXMgYW55KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnVHggb3V0cHV0cyBkb2VzIG5vdCBtYXRjaCB3aXRoIGV4cGVjdGVkIHR4UGFyYW1zIHJlY2lwaWVudHMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byB2ZXJpZnkgdG9rZW4gdHJhbnNmZXIgd2l0aCBpbmNvcnJlY3QgdG9rZW4gbmFtZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbmV3VHhQYXJhbXMoKTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG4gICAgICB0eFByZWJ1aWxkLnR4SGV4ID0gVGVzdERhdGEuVU5TSUdORURfVE9LRU5fTVVMVElfVFJBTlNGRVI7XG4gICAgICB0eFBhcmFtcy5yZWNpcGllbnRzID0gW1xuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogJzAuMC43NTg2MScsXG4gICAgICAgICAgYW1vdW50OiAnMTEnLFxuICAgICAgICAgIHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogJzAuMC43ODk2MycsXG4gICAgICAgICAgYW1vdW50OiAnMTUnLFxuICAgICAgICAgIHRva2VuTmFtZTogJ2ludmFsaWR0b2tlbicsXG4gICAgICAgIH0sXG4gICAgICBdO1xuICAgICAgYXdhaXQgdG9rZW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIG1lbW8sIHdhbGxldDogd2FsbGV0T2JqIH0gYXMgYW55KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnSW5jb3JyZWN0IHRva2VuIG5hbWUgc3BlY2lmaWVkIGluIHJlY2lwaWVudHMnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1NpZ24gTWVzc2FnZScsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGJlIHBlcmZvcm1lZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGtleVBhaXIgPSBuZXcgS2V5UGFpcigpO1xuICAgICAgY29uc3QgbWVzc2FnZVRvU2lnbiA9IEJ1ZmZlci5mcm9tKHJhbmRvbUJ5dGVzKDMyKSkudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gYXdhaXQgYmFzZWNvaW4uc2lnbk1lc3NhZ2Uoa2V5UGFpci5nZXRLZXlzKCksIG1lc3NhZ2VUb1NpZ24pO1xuICAgICAga2V5UGFpci52ZXJpZnlTaWduYXR1cmUobWVzc2FnZVRvU2lnbiwgVWludDhBcnJheS5mcm9tKEJ1ZmZlci5mcm9tKHNpZ25hdHVyZSwgJ2hleCcpKSkuc2hvdWxkLmVxdWFscyh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB3aXRoIG1pc3NpbmcgcHJpdmF0ZSBrZXknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBrZXlQYWlyID0gbmV3IEtleVBhaXIoe1xuICAgICAgICBwdWI6ICczMDJhMzAwNTA2MDMyYjY1NzAwMzIxMDBkOGZkNzQ1MzYxZGYyNzA3NzZhM2FiMWI1NWQ1NTkwZWMwMGEyNmFiNDVlZWEzNzE5N2RjOTg5NGE4MWZjYjgyJyxcbiAgICAgIH0pLmdldEtleXMoKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2VUb1NpZ24gPSBCdWZmZXIuZnJvbShyYW5kb21CeXRlcygzMikpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luLnNpZ25NZXNzYWdlKGtleVBhaXIsIG1lc3NhZ2VUb1NpZ24pLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0ludmFsaWQga2V5IHBhaXIgb3B0aW9ucycpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnU2lnbiB0cmFuc2FjdGlvbjonLCAoKSA9PiB7XG4gICAgY29uc3QgZGVzdGluYXRpb24gPSAnMC4wLjEyOTM2OSc7XG4gICAgY29uc3Qgc291cmNlID0gJzAuMC4xMjM0JztcbiAgICBjb25zdCBhbW91bnQgPSAnMTAwMDAwJztcbiAgICAvKipcbiAgICAgKiBCdWlsZCBhbiB1bnNpZ25lZCBhY2NvdW50LWxpYiBtdWx0aS1zaWduYXR1cmUgc2VuZCB0cmFuc2FjdGlvblxuICAgICAqIEBwYXJhbSBkZXN0aW5hdGlvbiBUaGUgZGVzdGluYXRpb24gYWRkcmVzcyBvZiB0aGUgdHJhbnNhY3Rpb25cbiAgICAgKiBAcGFyYW0gc291cmNlIFRoZSBhY2NvdW50IHNlbmRpbmcgdGhpc3QgcmFuc2FjdGlvblxuICAgICAqIEBwYXJhbSBhbW91bnQgVGhlIGFtb3VudCB0byBzZW5kIHRvIHRoZSByZWNpcGllbnRcbiAgICAgKi9cbiAgICBjb25zdCBidWlsZFVuc2lnbmVkVHJhbnNhY3Rpb24gPSBhc3luYyBmdW5jdGlvbiAoeyBkZXN0aW5hdGlvbiwgc291cmNlLCBhbW91bnQgPSAnMTAwMDAwJyB9KSB7XG4gICAgICBjb25zdCBmYWN0b3J5ID0gZ2V0QnVpbGRlckZhY3RvcnkoJ3RoYmFyJyk7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLmZlZSh7XG4gICAgICAgIGZlZTogJzEwMDAwMCcsXG4gICAgICB9KTtcbiAgICAgIHR4QnVpbGRlci5zb3VyY2UoeyBhZGRyZXNzOiBzb3VyY2UgfSk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZCh7IGFkZHJlc3M6IGRlc3RpbmF0aW9uLCBhbW91bnQgfSk7XG5cbiAgICAgIHJldHVybiBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICB9O1xuXG4gICAgaXQoJ3Nob3VsZCBzaWduIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qga2V5ID0gbmV3IEtleVBhaXIoKTtcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHJhbnNhY3Rpb24gPSBhd2FpdCBidWlsZFVuc2lnbmVkVHJhbnNhY3Rpb24oe1xuICAgICAgICBkZXN0aW5hdGlvbixcbiAgICAgICAgc291cmNlLFxuICAgICAgICBhbW91bnQsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCBiYXNlY29pbi5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICBwcnY6IGtleS5nZXRLZXlzKCkucHJ2IS50b1N0cmluZygpLFxuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHVuc2lnbmVkVHJhbnNhY3Rpb24udG9Ccm9hZGNhc3RGb3JtYXQoKSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBmYWN0b3J5ID0gZ2V0QnVpbGRlckZhY3RvcnkoJ3RoYmFyJyk7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmZyb20odHguaGFsZlNpZ25lZC50eEhleCk7XG4gICAgICBjb25zdCBzaWduZWRUeCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgdHhKc29uID0gc2lnbmVkVHgudG9Kc29uKCkgYXMgVHhEYXRhO1xuICAgICAgdHhKc29uLnNob3VsZC5oYXZlLnByb3BlcnRpZXMoJ3RvJywgJ2Ftb3VudCcpO1xuICAgICAgdHhKc29uLnRvPy5zaG91bGQuZXF1YWwoZGVzdGluYXRpb24pO1xuICAgICAgdHhKc29uLmZyb20uc2hvdWxkLmVxdWFsKHNvdXJjZSk7XG4gICAgICB0eEpzb24uYW1vdW50Py5zaG91bGQuZXF1YWwoYW1vdW50KTtcbiAgICAgICh0eEpzb24uaW5zdHJ1Y3Rpb25zRGF0YSBhcyBUcmFuc2ZlcikucGFyYW1zLnJlY2lwaWVudHNbMF0uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGFkZHJlc3M6IGRlc3RpbmF0aW9uLFxuICAgICAgICBhbW91bnQsXG4gICAgICB9KTtcbiAgICAgIHNpZ25lZFR4LnNpZ25hdHVyZS5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmdWxseSBzaWduIHRyYW5zYWN0aW9uIHdpdGggcm9vdCBrZXknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBrZXkxID0gYmFzZWNvaW4uZ2VuZXJhdGVSb290S2V5UGFpcigpO1xuICAgICAgY29uc3Qga2V5MiA9IGJhc2Vjb2luLmdlbmVyYXRlUm9vdEtleVBhaXIoKTtcblxuICAgICAgY29uc3QgdW5zaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJ1aWxkVW5zaWduZWRUcmFuc2FjdGlvbih7XG4gICAgICAgIGRlc3RpbmF0aW9uLFxuICAgICAgICBzb3VyY2UsXG4gICAgICAgIGFtb3VudCxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0eEhhbGZTaWduZWQgPSBhd2FpdCBiYXNlY29pbi5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICBwcnY6IGtleTEucHJ2LFxuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHVuc2lnbmVkVHJhbnNhY3Rpb24udG9Ccm9hZGNhc3RGb3JtYXQoKSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBmYWN0b3J5ID0gZ2V0QnVpbGRlckZhY3RvcnkoJ3RoYmFyJyk7XG4gICAgICBjb25zdCB0eEJ1aWxkZXJIYWxmU2lnbmVkID0gZmFjdG9yeS5mcm9tKHR4SGFsZlNpZ25lZC5oYWxmU2lnbmVkLnR4SGV4KTtcbiAgICAgIGNvbnN0IGhhbGZTaWduZWRUeCA9IGF3YWl0IHR4QnVpbGRlckhhbGZTaWduZWQuYnVpbGQoKTtcbiAgICAgIGNvbnN0IGhhbGZTaWduZWRUeEpzb24gPSBoYWxmU2lnbmVkVHgudG9Kc29uKCkgYXMgVHhEYXRhO1xuICAgICAgaGFsZlNpZ25lZFR4SnNvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0aWVzKCd0bycsICdhbW91bnQnKTtcbiAgICAgIGhhbGZTaWduZWRUeEpzb24udG8/LnNob3VsZC5lcXVhbChkZXN0aW5hdGlvbik7XG4gICAgICBoYWxmU2lnbmVkVHhKc29uLmZyb20uc2hvdWxkLmVxdWFsKHNvdXJjZSk7XG4gICAgICBoYWxmU2lnbmVkVHhKc29uLmFtb3VudD8uc2hvdWxkLmVxdWFsKGFtb3VudCk7XG4gICAgICAoaGFsZlNpZ25lZFR4SnNvbi5pbnN0cnVjdGlvbnNEYXRhIGFzIFRyYW5zZmVyKS5wYXJhbXMucmVjaXBpZW50c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogZGVzdGluYXRpb24sXG4gICAgICAgIGFtb3VudCxcbiAgICAgIH0pO1xuICAgICAgaGFsZlNpZ25lZFR4LnNpZ25hdHVyZS5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuXG4gICAgICBjb25zdCB0eFNpZ25lZCA9IGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgIHBydjoga2V5Mi5wcnYsXG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICB0eEhleDogaGFsZlNpZ25lZFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCksXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyU2lnbmVkID0gZmFjdG9yeS5mcm9tKHR4U2lnbmVkLnR4SGV4KTtcbiAgICAgIGNvbnN0IHNpZ25lZFR4ID0gYXdhaXQgdHhCdWlsZGVyU2lnbmVkLmJ1aWxkKCk7XG4gICAgICBjb25zdCBzaWduZWRUeEpzb24gPSBzaWduZWRUeC50b0pzb24oKSBhcyBUeERhdGE7XG4gICAgICBzaWduZWRUeEpzb24uc2hvdWxkLmhhdmUucHJvcGVydGllcygndG8nLCAnYW1vdW50Jyk7XG4gICAgICBzaWduZWRUeEpzb24udG8/LnNob3VsZC5lcXVhbChkZXN0aW5hdGlvbik7XG4gICAgICBzaWduZWRUeEpzb24uZnJvbS5zaG91bGQuZXF1YWwoc291cmNlKTtcbiAgICAgIHNpZ25lZFR4SnNvbi5hbW91bnQ/LnNob3VsZC5lcXVhbChhbW91bnQpO1xuICAgICAgKHNpZ25lZFR4SnNvbi5pbnN0cnVjdGlvbnNEYXRhIGFzIFRyYW5zZmVyKS5wYXJhbXMucmVjaXBpZW50c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogZGVzdGluYXRpb24sXG4gICAgICAgIGFtb3VudCxcbiAgICAgIH0pO1xuICAgICAgc2lnbmVkVHguc2lnbmF0dXJlLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdSZWNvdmVyeScsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBkZWZhdWx0VmFsaWREdXJhdGlvbiA9ICcxODAnO1xuICAgIGNvbnN0IGRlZmF1bHRGZWUgPSAxMDAwMDAwMDtcbiAgICBjb25zdCBkZWZhdWx0Tm9kZUlkID0gJzAuMC4zJztcbiAgICBjb25zdCB1c2VyS2V5ID1cbiAgICAgICd7XCJpdlwiOlwiV2xQdUpPZWpSV2dqL05UZDNVTWdydz09XCIsXCJ2XCI6MSxcIml0ZXJcIjoxMDAwMCxcImtzXCI6MjU2LFwidHNcIjo2NCxcIm1vZGVcIjpcImNjbVwiLFwiYWRhdGFcIjpcIlwiLFwiY2lwaGVyXCI6XCJhZXNcIixcInNhbHRcIjpcIjZ5QVZGdnJlSFNRPVwiLFwiY3RcIjpcIjhqL2xCVmtGQnlLbFZoYVM5SldtbUxqYTV5VG9ramFJaUxEeE1JRGpNb2pWRWltOVQzNldBbTVxVzZ2MVYwQTdRY0V1R2lWbDNQS01EYStHcjZ0SS9IVDU4RFc1UkUrcEh6eWE5TVVRcEFnTnJKcjhWRVdqclhXcVpFQ1Z0cmExL2JLQ3lCK21vemM9XCJ9JztcbiAgICBjb25zdCB1c2VyUHViID0gJzMwMmEzMDA1MDYwMzJiNjU3MDAzMjEwMGRkZDUzYTE1OTFkNzJiMTgxMTA5YmQzZTU3YjE4NjAzNzQwNDkwYjlhYjRkMzdiYzdmYTI3NDgwZTZiOGM5MTEnO1xuICAgIGNvbnN0IGJhY2t1cEtleSA9XG4gICAgICAne1wiaXZcIjpcIkQ1RFZEb3pReDlCMDJKZUZWMC9PVkE9PVwiLFwidlwiOjEsXCJpdGVyXCI6MTAwMDAsXCJrc1wiOjI1NixcInRzXCI6NjQsXCJtb2RlXCI6XCJjY21cIixcImFkYXRhXCI6XCJcIixcImNpcGhlclwiOlwiYWVzXCIsXCJzYWx0XCI6XCI3RlVORjhNMzVibz1cIixcImN0XCI6XCJaaVBzdTVRZS9BSVM0SlFYdCtycnVzSG5ZQ3k0Q3F1ck0xNlI1d0pyZDRDRXg3dTg1eTN5eTVFcm5zZHlZWWNjM3R4eU5tVUlRMi9DQnEvTEtvS08vVkllVSsrQ25LeHpHdUhHY05JNDdCUGszUlFLNDJhNjZ1SVFuL3lUUisrWGdkSzFLaHZVTDNVPVwifSc7XG4gICAgY29uc3QgYmFja3VwUHViID0gJzMwMmEzMDA1MDYwMzJiNjU3MDAzMjEwMDYyOTNlNGVjOWJmMWIyZDhmYWU2MzExMTkxMDcyNDhhNjVlMjIwN2EwNWQzMmExMWY0MmNjM2Q5YTMwMDVkNGEnO1xuICAgIGNvbnN0IHJvb3RBZGRyZXNzID0gJzAuMC43NjcxMTg2JztcbiAgICBjb25zdCB3YWxsZXRQYXNzcGhyYXNlID0gJ1Rlc3RQYXNzd29yZFBsZWFzZUlnbm9yZSc7XG4gICAgY29uc3QgcmVjb3ZlcnlEZXN0aW5hdGlvbiA9ICcwLjAuNzY1MTkwOCc7XG4gICAgY29uc3QgYml0Z29LZXkgPSAnNWE5M2IwMWVhODdlOTYzZjYxYzk3NGE4OWQ2MmUzODQxMzkyZjFiYTAyMGZiYmNjNjVhODA4OWNhMDI1YWJiYic7XG4gICAgY29uc3QgbWVtbyA9ICc0JztcbiAgICBjb25zdCBiYWxhbmNlID0gJzEwMDAwMDAwMDAnO1xuICAgIGNvbnN0IGZvcm1hdEJhbGFuY2VSZXNwb25zZSA9IChiYWxhbmNlOiBzdHJpbmcpID0+XG4gICAgICBuZXcgQmlnTnVtYmVyKGJhbGFuY2UpLmRpdmlkZWRCeShiYXNlY29pbi5nZXRCYXNlRmFjdG9yKCkpLnRvRml4ZWQoOSkgKyAnIOKEjyc7XG4gICAgY29uc3QgdG9rZW5JZCA9ICcwLjAuMTMwNzgnO1xuXG4gICAgZGVzY3JpYmUoJ05vbi1CaXRHbycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNhbmRCb3ggPSBTaW5vbi5jcmVhdGVTYW5kYm94KCk7XG5cbiAgICAgIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHNhbmRCb3gudmVyaWZ5QW5kUmVzdG9yZSgpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgYnVpbGQgYW5kIHNpZ24gdGhlIHJlY292ZXJ5IHR4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBleHBlY3RlZEFtb3VudCA9IG5ldyBCaWdOdW1iZXIoYmFsYW5jZSkubWludXMoZGVmYXVsdEZlZSkudG9TdHJpbmcoKTtcbiAgICAgICAgY29uc3QgZ2V0QmFsYW5jZVN0dWIgPSBzYW5kQm94XG4gICAgICAgICAgLnN0dWIoSGJhci5wcm90b3R5cGUsICdnZXRBY2NvdW50QmFsYW5jZScpXG4gICAgICAgICAgLnJlc29sdmVzKHsgaGJhcnM6IGZvcm1hdEJhbGFuY2VSZXNwb25zZShiYWxhbmNlKSwgdG9rZW5zOiBbXSB9KTtcblxuICAgICAgICBjb25zdCByZWNvdmVyeSA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgIHVzZXJLZXksXG4gICAgICAgICAgYmFja3VwS2V5LFxuICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcmVjb3ZlcnlEZXN0aW5hdGlvbiArICc/bWVtb0lkPScgKyBtZW1vLFxuICAgICAgICB9KTtcblxuICAgICAgICByZWNvdmVyeS5zaG91bGQubm90LmJlLnVuZGVmaW5lZCgpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaWQnKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4Jyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb2luJywgJ3RoYmFyJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdub2RlSWQnLCBkZWZhdWx0Tm9kZUlkKTtcbiAgICAgICAgZ2V0QmFsYW5jZVN0dWIuY2FsbENvdW50LnNob3VsZC5lcXVhbCgxKTtcbiAgICAgICAgY29uc3QgdHhCdWlsZGVyID0gYmFzZWNvaW4uZ2V0QnVpbGRlckZhY3RvcnkoKS5mcm9tKHJlY292ZXJ5LnR4KTtcbiAgICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgdHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmVjb3ZlcnkudHgpO1xuICAgICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcbiAgICAgICAgdHhKc29uLmFtb3VudC5zaG91bGQuZXF1YWwoZXhwZWN0ZWRBbW91bnQpO1xuICAgICAgICB0eEpzb24udG8uc2hvdWxkLmVxdWFsKHJlY292ZXJ5RGVzdGluYXRpb24pO1xuICAgICAgICB0eEpzb24uZnJvbS5zaG91bGQuZXF1YWwocm9vdEFkZHJlc3MpO1xuICAgICAgICB0eEpzb24uZmVlLnNob3VsZC5lcXVhbChkZWZhdWx0RmVlKTtcbiAgICAgICAgdHhKc29uLm5vZGUuc2hvdWxkLmVxdWFsKGRlZmF1bHROb2RlSWQpO1xuICAgICAgICB0eEpzb24ubWVtby5zaG91bGQuZXF1YWwobWVtbyk7XG4gICAgICAgIHR4SnNvbi52YWxpZER1cmF0aW9uLnNob3VsZC5lcXVhbChkZWZhdWx0VmFsaWREdXJhdGlvbik7XG4gICAgICAgIHR4SnNvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3RhcnRUaW1lJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdzdGFydFRpbWUnLCB0eEpzb24uc3RhcnRUaW1lKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2lkJywgcm9vdEFkZHJlc3MgKyAnQCcgKyB0eEpzb24uc3RhcnRUaW1lKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRocm93IGZvciBpbnZhbGlkIHJvb3RBZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBpbnZhbGlkUm9vdEFkZHJlc3MgPSAncmFuZG9tc3RyaW5nJztcbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgICAgIHVzZXJLZXksXG4gICAgICAgICAgICAgIGJhY2t1cEtleSxcbiAgICAgICAgICAgICAgcm9vdEFkZHJlc3M6ICdyYW5kb21zdHJpbmcnLFxuICAgICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uICsgJz9tZW1vSWQ9JyArIG1lbW8sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbWVzc2FnZTogJ2ludmFsaWQgcm9vdEFkZHJlc3MsIGdvdDogJyArIGludmFsaWRSb290QWRkcmVzcyB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgaW52YWxpZCByZWNvdmVyeURlc3RpbmF0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBpbnZhbGlkUmVjb3ZlcnlEZXN0aW5hdGlvbiA9ICdyYW5kb21zdHJpbmcnO1xuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICAgICAgdXNlcktleSxcbiAgICAgICAgICAgICAgYmFja3VwS2V5LFxuICAgICAgICAgICAgICByb290QWRkcmVzcyxcbiAgICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogJ3JhbmRvbXN0cmluZycsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbWVzc2FnZTogJ2ludmFsaWQgcmVjb3ZlcnlEZXN0aW5hdGlvbiwgZ290OiAnICsgaW52YWxpZFJlY292ZXJ5RGVzdGluYXRpb24gfVxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgZm9yIGludmFsaWQgbm9kZUlkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBpbnZhbGlkTm9kZUlkID0gJ2EuMi4zJztcbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgICAgIHVzZXJLZXksXG4gICAgICAgICAgICAgIGJhY2t1cEtleSxcbiAgICAgICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICAgICAgbm9kZUlkOiBpbnZhbGlkTm9kZUlkLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IG1lc3NhZ2U6ICdpbnZhbGlkIG5vZGVJZCwgZ290OiAnICsgaW52YWxpZE5vZGVJZCB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgaW52YWxpZCBtYXhGZWUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGludmFsaWRNYXhGZWUgPSAnLTMyJztcbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgICAgIHVzZXJLZXksXG4gICAgICAgICAgICAgIGJhY2t1cEtleSxcbiAgICAgICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICAgICAgbWF4RmVlOiBpbnZhbGlkTWF4RmVlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IG1lc3NhZ2U6ICdpbnZhbGlkIG1heEZlZSwgZ290OiAnICsgaW52YWxpZE1heEZlZSB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiB0aGVyZSBpcyBubyBlbm91Z2ggYmFsYW5jZSB0byByZWNvdmVyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBnZXRCYWxhbmNlU3R1YiA9IHNhbmRCb3hcbiAgICAgICAgICAuc3R1YihIYmFyLnByb3RvdHlwZSwgJ2dldEFjY291bnRCYWxhbmNlJylcbiAgICAgICAgICAucmVzb2x2ZXMoeyBoYmFyczogZm9ybWF0QmFsYW5jZVJlc3BvbnNlKCcxMDAnKSwgdG9rZW5zOiBbXSB9KTtcbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgICAgIHVzZXJLZXksXG4gICAgICAgICAgICAgIGJhY2t1cEtleSxcbiAgICAgICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgeyBtZXNzYWdlOiAnSW5zdWZmaWNpZW50IGJhbGFuY2UgdG8gcmVjb3ZlciwgZ290IGJhbGFuY2U6IDEwMCBmZWU6IDEwMDAwMDAwJyB9XG4gICAgICAgICk7XG5cbiAgICAgICAgZ2V0QmFsYW5jZVN0dWIuY2FsbENvdW50LnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRocm93IGlmIHRoZSB3YWxsZXRQYXNzcGhyYXNlIGlzIHVuZGVmaW5lZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgICAgIHVzZXJLZXksXG4gICAgICAgICAgICAgIGJhY2t1cEtleSxcbiAgICAgICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgeyBtZXNzYWdlOiAnd2FsbGV0UGFzc3BocmFzZSBpcyByZXF1aXJlZCBmb3Igbm9uLWJpdGdvIHJlY292ZXJ5JyB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiB0aGUgd2FsbGV0UGFzc3BocmFzZSBpcyB3cm9uZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgICAgIHVzZXJLZXksXG4gICAgICAgICAgICAgIGJhY2t1cEtleSxcbiAgICAgICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdyYW5kb21wYXNzd29yZCcsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbWVzc2FnZTpcbiAgICAgICAgICAgICAgXCJ1bmFibGUgdG8gZGVjcnlwdCB1c2VyS2V5IG9yIGJhY2t1cEtleSB3aXRoIHRoZSB3YWxsZXRQYXNzcGhyYXNlIHByb3ZpZGVkLCBnb3QgZXJyb3I6IHBhc3N3b3JkIGVycm9yIC0gY2NtOiB0YWcgZG9lc24ndCBtYXRjaFwiLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGJ1aWxkIGFuZCBzaWduIHRoZSByZWNvdmVyeSB0eCBmb3IgdG9rZW5zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBiYWxhbmNlID0gJzEwMCc7XG4gICAgICAgIGNvbnN0IGRhdGEgPSB7XG4gICAgICAgICAgaGJhcnM6ICcxJyxcbiAgICAgICAgICB0b2tlbnM6IFt7IHRva2VuSWQ6IHRva2VuSWQsIGJhbGFuY2U6IGJhbGFuY2UsIGRlY2ltYWxzOiA2IH1dLFxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBnZXRCYWxhbmNlU3R1YiA9IHNhbmRCb3guc3R1YihIYmFyLnByb3RvdHlwZSwgJ2dldEFjY291bnRCYWxhbmNlJykucmVzb2x2ZXMoZGF0YSk7XG5cbiAgICAgICAgY29uc3QgcmVjb3ZlcnkgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgIGJhY2t1cEtleSxcbiAgICAgICAgICByb290QWRkcmVzcyxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICB0b2tlbklkOiB0b2tlbklkLFxuICAgICAgICB9KTtcblxuICAgICAgICByZWNvdmVyeS5zaG91bGQubm90LmJlLnVuZGVmaW5lZCgpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaWQnKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4Jyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb2luJywgJ3RoYmFyJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdub2RlSWQnLCBkZWZhdWx0Tm9kZUlkKTtcbiAgICAgICAgZ2V0QmFsYW5jZVN0dWIuY2FsbENvdW50LnNob3VsZC5lcXVhbCgxKTtcbiAgICAgICAgY29uc3QgdHhCdWlsZGVyID0gYmFzZWNvaW4uZ2V0QnVpbGRlckZhY3RvcnkoKS5mcm9tKHJlY292ZXJ5LnR4KTtcbiAgICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgdHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmVjb3ZlcnkudHgpO1xuICAgICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcbiAgICAgICAgdHhKc29uLmFtb3VudC5zaG91bGQuZXF1YWwoYmFsYW5jZSk7XG4gICAgICAgIHR4SnNvbi50by5zaG91bGQuZXF1YWwocmVjb3ZlcnlEZXN0aW5hdGlvbik7XG4gICAgICAgIHR4SnNvbi5mcm9tLnNob3VsZC5lcXVhbChyb290QWRkcmVzcyk7XG4gICAgICAgIHR4SnNvbi5mZWUuc2hvdWxkLmVxdWFsKGRlZmF1bHRGZWUpO1xuICAgICAgICB0eEpzb24ubm9kZS5zaG91bGQuZXF1YWwoZGVmYXVsdE5vZGVJZCk7XG4gICAgICAgIHR4SnNvbi5tZW1vLnNob3VsZC5lcXVhbChtZW1vKTtcbiAgICAgICAgdHhKc29uLnZhbGlkRHVyYXRpb24uc2hvdWxkLmVxdWFsKGRlZmF1bHRWYWxpZER1cmF0aW9uKTtcbiAgICAgICAgdHhKc29uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdzdGFydFRpbWUnKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3N0YXJ0VGltZScsIHR4SnNvbi5zdGFydFRpbWUpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaWQnLCByb290QWRkcmVzcyArICdAJyArIHR4SnNvbi5zdGFydFRpbWUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIG5vbiBzdXBwb3J0ZWQgaW52YWxpZCB0b2tlbklkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBpbnZhbGlkVG9rZW5JZCA9ICdyYW5kb21zdHJpbmcnO1xuICAgICAgICBjb25zdCBkYXRhID0ge1xuICAgICAgICAgIGhiYXJzOiAnMScsXG4gICAgICAgICAgdG9rZW5zOiBbeyB0b2tlbklkOiB0b2tlbklkLCBiYWxhbmNlOiAnMTAwJywgZGVjaW1hbHM6IDYgfV0sXG4gICAgICAgIH07XG4gICAgICAgIHNhbmRCb3guc3R1YihIYmFyLnByb3RvdHlwZSwgJ2dldEFjY291bnRCYWxhbmNlJykucmVzb2x2ZXMoZGF0YSk7XG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzOiByb290QWRkcmVzcyxcbiAgICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcmVjb3ZlcnlEZXN0aW5hdGlvbiArICc/bWVtb0lkPScgKyBtZW1vLFxuICAgICAgICAgICAgICB0b2tlbklkOiBpbnZhbGlkVG9rZW5JZCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgeyBtZXNzYWdlOiAnVW5zdXBwb3J0ZWQgdG9rZW46ICcgKyBpbnZhbGlkVG9rZW5JZCB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3IgaW5zdWZmaWNpZW50IGJhbGFuY2UgZm9yIHRva2VuSWQgaWYgdG9rZW4gYmFsYW5jZSBub3QgZXhpc3QnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSB7XG4gICAgICAgICAgaGJhcnM6ICcxMDAnLFxuICAgICAgICAgIHRva2VuczogW3sgdG9rZW5JZDogJ3JhbmRvbVN0cmluZycsIGJhbGFuY2U6ICcxMDAnLCBkZWNpbWFsczogNiB9XSxcbiAgICAgICAgfTtcbiAgICAgICAgc2FuZEJveC5zdHViKEhiYXIucHJvdG90eXBlLCAnZ2V0QWNjb3VudEJhbGFuY2UnKS5yZXNvbHZlcyhkYXRhKTtcbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgICAgIHVzZXJLZXksXG4gICAgICAgICAgICAgIGJhY2t1cEtleSxcbiAgICAgICAgICAgICAgcm9vdEFkZHJlc3M6IHJvb3RBZGRyZXNzLFxuICAgICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uICsgJz9tZW1vSWQ9JyArIG1lbW8sXG4gICAgICAgICAgICAgIHRva2VuSWQ6IHRva2VuSWQsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbWVzc2FnZTogJ0luc3VmZmljaWVudCBiYWxhbmNlIHRvIHJlY292ZXIgdG9rZW46ICcgKyB0b2tlbklkICsgJyBmb3IgYWNjb3VudDogJyArIHJvb3RBZGRyZXNzIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGZvciBpbnN1ZmZpY2llbnQgYmFsYW5jZSBmb3IgdG9rZW5JZCBpZiB0b2tlbiBiYWxhbmNlIGV4aXN0IHdpdGggMCBhbW91bnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSB7XG4gICAgICAgICAgaGJhcnM6ICcxMDAnLFxuICAgICAgICAgIHRva2VuczogW3sgdG9rZW5JZDogJ3JhbmRvbVN0cmluZycsIGJhbGFuY2U6ICcwJywgZGVjaW1hbHM6IDYgfV0sXG4gICAgICAgIH07XG4gICAgICAgIHNhbmRCb3guc3R1YihIYmFyLnByb3RvdHlwZSwgJ2dldEFjY291bnRCYWxhbmNlJykucmVzb2x2ZXMoZGF0YSk7XG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzOiByb290QWRkcmVzcyxcbiAgICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcmVjb3ZlcnlEZXN0aW5hdGlvbiArICc/bWVtb0lkPScgKyBtZW1vLFxuICAgICAgICAgICAgICB0b2tlbklkOiB0b2tlbklkLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IG1lc3NhZ2U6ICdJbnN1ZmZpY2llbnQgYmFsYW5jZSB0byByZWNvdmVyIHRva2VuOiAnICsgdG9rZW5JZCArICcgZm9yIGFjY291bnQ6ICcgKyByb290QWRkcmVzcyB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3IgaW5zdWZmaWNpZW50IG5hdGl2ZSBiYWxhbmNlIGZvciB0b2tlbiB0cmFuc2ZlcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IHtcbiAgICAgICAgICBoYmFyczogJzAuMDEnLFxuICAgICAgICAgIHRva2VuczogW3sgdG9rZW5JZDogdG9rZW5JZCwgYmFsYW5jZTogJzEwJywgZGVjaW1hbHM6IDYgfV0sXG4gICAgICAgIH07XG4gICAgICAgIHNhbmRCb3guc3R1YihIYmFyLnByb3RvdHlwZSwgJ2dldEFjY291bnRCYWxhbmNlJykucmVzb2x2ZXMoZGF0YSk7XG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzOiByb290QWRkcmVzcyxcbiAgICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcmVjb3ZlcnlEZXN0aW5hdGlvbiArICc/bWVtb0lkPScgKyBtZW1vLFxuICAgICAgICAgICAgICB0b2tlbklkOiB0b2tlbklkLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IG1lc3NhZ2U6ICdJbnN1ZmZpY2llbnQgbmF0aXZlIGJhbGFuY2UgdG8gcmVjb3ZlciB0b2tlbnMsIGdvdCBuYXRpdmUgYmFsYW5jZTogMTAwMDAwMCBmZWU6ICcgKyBkZWZhdWx0RmVlIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ1Vuc2lnbmVkIFN3ZWVwJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2FuZEJveCA9IFNpbm9uLmNyZWF0ZVNhbmRib3goKTtcbiAgICAgIGxldCBnZXRCYWxhbmNlU3R1YjogU2lub25TdHViO1xuXG4gICAgICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICBzYW5kQm94LnZlcmlmeUFuZFJlc3RvcmUoKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGJ1aWxkIHVuc2lnbmVkIHN3ZWVwIHR4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBnZXRCYWxhbmNlU3R1YiA9IHNhbmRCb3hcbiAgICAgICAgICAuc3R1YihIYmFyLnByb3RvdHlwZSwgJ2dldEFjY291bnRCYWxhbmNlJylcbiAgICAgICAgICAucmVzb2x2ZXMoeyBoYmFyczogZm9ybWF0QmFsYW5jZVJlc3BvbnNlKGJhbGFuY2UpLCB0b2tlbnM6IFtdIH0pO1xuICAgICAgICBjb25zdCBzdGFydFRpbWUgPSAoRGF0ZS5ub3coKSAvIDEwMDAgKyAxMCkudG9GaXhlZCgpOyAvLyB0aW1lc3RhbXAgaW4gc2Vjb25kcywgMTAgc2Vjb25kcyBmcm9tIG5vd1xuICAgICAgICBjb25zdCBleHBlY3RlZEFtb3VudCA9IG5ldyBCaWdOdW1iZXIoYmFsYW5jZSkubWludXMoZGVmYXVsdEZlZSkudG9TdHJpbmcoKTtcblxuICAgICAgICBjb25zdCByZWNvdmVyeSA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgIHVzZXJLZXk6IHVzZXJQdWIsXG4gICAgICAgICAgYmFja3VwS2V5OiBiYWNrdXBQdWIsXG4gICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgYml0Z29LZXksXG4gICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcmVjb3ZlcnlEZXN0aW5hdGlvbiArICc/bWVtb0lkPScgKyBtZW1vLFxuICAgICAgICAgIHN0YXJ0VGltZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZ2V0QmFsYW5jZVN0dWIuY2FsbENvdW50LnNob3VsZC5lcXVhbCgxKTtcblxuICAgICAgICByZWNvdmVyeS5zaG91bGQubm90LmJlLnVuZGVmaW5lZCgpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHhIZXgnKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2lkJywgcm9vdEFkZHJlc3MgKyAnQCcgKyBzdGFydFRpbWUgKyAnLjAnKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3VzZXJLZXknLCB1c2VyUHViKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2JhY2t1cEtleScsIGJhY2t1cFB1Yik7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdiaXRnb0tleScsIGJpdGdvS2V5KTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2FkZHJlc3MnLCByb290QWRkcmVzcyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb2luJywgJ3RoYmFyJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdtYXhGZWUnLCBkZWZhdWx0RmVlLnRvU3RyaW5nKCkpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncmVjaXBpZW50cycsIFt7IGFkZHJlc3M6IHJlY292ZXJ5RGVzdGluYXRpb24sIGFtb3VudDogZXhwZWN0ZWRBbW91bnQgfV0pO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYW1vdW50JywgZXhwZWN0ZWRBbW91bnQpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndmFsaWREdXJhdGlvbicsIGRlZmF1bHRWYWxpZER1cmF0aW9uKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ25vZGVJZCcsIGRlZmF1bHROb2RlSWQpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnbWVtbycsIG1lbW8pO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3RhcnRUaW1lJywgc3RhcnRUaW1lICsgJy4wJyk7XG4gICAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGJhc2Vjb2luLmdldEJ1aWxkZXJGYWN0b3J5KCkuZnJvbShyZWNvdmVyeS50eEhleCk7XG4gICAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICAgIGNvbnN0IHR4SnNvbiA9IHR4LnRvSnNvbigpO1xuICAgICAgICB0eEpzb24uaWQuc2hvdWxkLmVxdWFsKHJvb3RBZGRyZXNzICsgJ0AnICsgc3RhcnRUaW1lICsgJy4wJyk7XG4gICAgICAgIHR4SnNvbi5hbW91bnQuc2hvdWxkLmVxdWFsKGV4cGVjdGVkQW1vdW50KTtcbiAgICAgICAgdHhKc29uLnRvLnNob3VsZC5lcXVhbChyZWNvdmVyeURlc3RpbmF0aW9uKTtcbiAgICAgICAgdHhKc29uLmZyb20uc2hvdWxkLmVxdWFsKHJvb3RBZGRyZXNzKTtcbiAgICAgICAgdHhKc29uLmZlZS5zaG91bGQuZXF1YWwoZGVmYXVsdEZlZSk7XG4gICAgICAgIHR4SnNvbi5ub2RlLnNob3VsZC5lcXVhbChkZWZhdWx0Tm9kZUlkKTtcbiAgICAgICAgdHhKc29uLm1lbW8uc2hvdWxkLmVxdWFsKG1lbW8pO1xuICAgICAgICB0eEpzb24udmFsaWREdXJhdGlvbi5zaG91bGQuZXF1YWwoZGVmYXVsdFZhbGlkRHVyYXRpb24pO1xuICAgICAgICB0eEpzb24uc3RhcnRUaW1lLnNob3VsZC5lcXVhbChzdGFydFRpbWUgKyAnLjAnKTtcbiAgICAgICAgdHhKc29uLnZhbGlkRHVyYXRpb24uc2hvdWxkLmVxdWFsKGRlZmF1bHRWYWxpZER1cmF0aW9uKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGJ1aWxkIHVuc2lnbmVkIHN3ZWVwIHR4IGZvciB0b2tlbnMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGJhbGFuY2UgPSAnMTAwJztcbiAgICAgICAgY29uc3QgZGF0YSA9IHtcbiAgICAgICAgICBoYmFyczogJzEnLFxuICAgICAgICAgIHRva2VuczogW3sgdG9rZW5JZDogdG9rZW5JZCwgYmFsYW5jZTogYmFsYW5jZSwgZGVjaW1hbHM6IDYgfV0sXG4gICAgICAgIH07XG4gICAgICAgIGdldEJhbGFuY2VTdHViID0gc2FuZEJveC5zdHViKEhiYXIucHJvdG90eXBlLCAnZ2V0QWNjb3VudEJhbGFuY2UnKS5yZXNvbHZlcyhkYXRhKTtcbiAgICAgICAgY29uc3Qgc3RhcnRUaW1lID0gKERhdGUubm93KCkgLyAxMDAwICsgMTApLnRvRml4ZWQoKTsgLy8gdGltZXN0YW1wIGluIHNlY29uZHMsIDEwIHNlY29uZHMgZnJvbSBub3dcbiAgICAgICAgY29uc3QgcmVjb3ZlcnkgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5OiB1c2VyUHViLFxuICAgICAgICAgIGJhY2t1cEtleTogYmFja3VwUHViLFxuICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgIGJpdGdvS2V5LFxuICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICBzdGFydFRpbWUsXG4gICAgICAgICAgdG9rZW5JZDogdG9rZW5JZCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZ2V0QmFsYW5jZVN0dWIuY2FsbENvdW50LnNob3VsZC5lcXVhbCgxKTtcblxuICAgICAgICByZWNvdmVyeS5zaG91bGQubm90LmJlLnVuZGVmaW5lZCgpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHhIZXgnKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2lkJywgcm9vdEFkZHJlc3MgKyAnQCcgKyBzdGFydFRpbWUgKyAnLjAnKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3VzZXJLZXknLCB1c2VyUHViKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2JhY2t1cEtleScsIGJhY2t1cFB1Yik7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdiaXRnb0tleScsIGJpdGdvS2V5KTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2FkZHJlc3MnLCByb290QWRkcmVzcyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb2luJywgJ3RoYmFyJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdtYXhGZWUnLCBkZWZhdWx0RmVlLnRvU3RyaW5nKCkpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncmVjaXBpZW50cycsIFtcbiAgICAgICAgICB7IGFkZHJlc3M6IHJlY292ZXJ5RGVzdGluYXRpb24sIGFtb3VudDogYmFsYW5jZSwgdG9rZW5OYW1lOiAndGhiYXI6dXNkYycgfSxcbiAgICAgICAgXSk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdhbW91bnQnLCBiYWxhbmNlKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3ZhbGlkRHVyYXRpb24nLCBkZWZhdWx0VmFsaWREdXJhdGlvbik7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdub2RlSWQnLCBkZWZhdWx0Tm9kZUlkKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ21lbW8nLCBtZW1vKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3N0YXJ0VGltZScsIHN0YXJ0VGltZSArICcuMCcpO1xuICAgICAgICBjb25zdCB0eEJ1aWxkZXIgPSBiYXNlY29pbi5nZXRCdWlsZGVyRmFjdG9yeSgpLmZyb20ocmVjb3ZlcnkudHhIZXgpO1xuICAgICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcbiAgICAgICAgdHhKc29uLmlkLnNob3VsZC5lcXVhbChyb290QWRkcmVzcyArICdAJyArIHN0YXJ0VGltZSArICcuMCcpO1xuICAgICAgICB0eEpzb24uYW1vdW50LnNob3VsZC5lcXVhbChiYWxhbmNlKTtcbiAgICAgICAgdHhKc29uLnRvLnNob3VsZC5lcXVhbChyZWNvdmVyeURlc3RpbmF0aW9uKTtcbiAgICAgICAgdHhKc29uLmZyb20uc2hvdWxkLmVxdWFsKHJvb3RBZGRyZXNzKTtcbiAgICAgICAgdHhKc29uLmZlZS5zaG91bGQuZXF1YWwoZGVmYXVsdEZlZSk7XG4gICAgICAgIHR4SnNvbi5ub2RlLnNob3VsZC5lcXVhbChkZWZhdWx0Tm9kZUlkKTtcbiAgICAgICAgdHhKc29uLm1lbW8uc2hvdWxkLmVxdWFsKG1lbW8pO1xuICAgICAgICB0eEpzb24udmFsaWREdXJhdGlvbi5zaG91bGQuZXF1YWwoZGVmYXVsdFZhbGlkRHVyYXRpb24pO1xuICAgICAgICB0eEpzb24uc3RhcnRUaW1lLnNob3VsZC5lcXVhbChzdGFydFRpbWUgKyAnLjAnKTtcbiAgICAgICAgdHhKc29uLnZhbGlkRHVyYXRpb24uc2hvdWxkLmVxdWFsKGRlZmF1bHRWYWxpZER1cmF0aW9uKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRocm93IGlmIHN0YXJ0VGltZSBpcyB1bmRlZmluZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IHVuZGVmaW5lZDtcblxuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICAgICAgdXNlcktleTogdXNlclB1YixcbiAgICAgICAgICAgICAgYmFja3VwS2V5OiBiYWNrdXBQdWIsXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgICAgICBiaXRnb0tleSxcbiAgICAgICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcmVjb3ZlcnlEZXN0aW5hdGlvbiArICc/bWVtb0lkPScgKyBtZW1vLFxuICAgICAgICAgICAgICBzdGFydFRpbWUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbWVzc2FnZTogJ3N0YXJ0IHRpbWUgaXMgcmVxdWlyZWQgZm9yIHVuc2lnbmVkIHN3ZWVwJyB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgaW52YWxpZCB1c2VyS2V5JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBzdGFydFRpbWUgPSAoRGF0ZS5ub3coKSAvIDEwMDAgKyAxMCkudG9GaXhlZCgpO1xuICAgICAgICBjb25zdCBpbnZhbGlkVXNlclB1YiA9ICczMDJhMzAwNTA2MDMyYjY1NzAwMzIxMDByYW5kb21zdHJpbmcnO1xuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICAgICAgdXNlcktleTogaW52YWxpZFVzZXJQdWIsXG4gICAgICAgICAgICAgIGJhY2t1cEtleTogYmFja3VwUHViLFxuICAgICAgICAgICAgICBiaXRnb0tleSxcbiAgICAgICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICAgICAgc3RhcnRUaW1lLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IG1lc3NhZ2U6ICdpbnZhbGlkIHVzZXJLZXksIGdvdDogJyArIGludmFsaWRVc2VyUHViIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRocm93IGZvciBpbnZhbGlkIGJhY2t1cEtleScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgaW52YWxpZEJhY2t1cFB1YiA9ICczMDJhMzAwNTA2MDMyYjY1NzAwMzIxMDByYW5kb21zdHJpbmcnO1xuICAgICAgICBjb25zdCBzdGFydFRpbWUgPSAoRGF0ZS5ub3coKSAvIDEwMDAgKyAxMCkudG9GaXhlZCgpO1xuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICAgICAgdXNlcktleTogdXNlclB1YixcbiAgICAgICAgICAgICAgYmFja3VwS2V5OiBpbnZhbGlkQmFja3VwUHViLFxuICAgICAgICAgICAgICBiaXRnb0tleSxcbiAgICAgICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICAgICAgc3RhcnRUaW1lLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IG1lc3NhZ2U6ICdpbnZhbGlkIGJhY2t1cEtleSwgZ290OiAnICsgaW52YWxpZEJhY2t1cFB1YiB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiBzdGFydFRpbWUgaXMgYSB2YWxpZCB0aW1lc3RhbXAnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9ICdhc2QnO1xuXG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5OiB1c2VyUHViLFxuICAgICAgICAgICAgICBiYWNrdXBLZXk6IGJhY2t1cFB1YixcbiAgICAgICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgICAgIGJpdGdvS2V5LFxuICAgICAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uICsgJz9tZW1vSWQ9JyArIG1lbW8sXG4gICAgICAgICAgICAgIHN0YXJ0VGltZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgeyBtZXNzYWdlOiAnaW52YWxpZCBzdGFydFRpbWUsIGdvdDogJyArIHN0YXJ0VGltZSB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiBzdGFydFRpbWUgaXMgbm90IGEgZnV0dXJlIGRhdGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IChEYXRlLm5vdygpIC8gMTAwMCAtIDEpLnRvU3RyaW5nKCk7IC8vIHRpbWVzdGFtcCBpbiBzZWNvbmRzLCAxIHNlY29uZCBhZ29cblxuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICAgICAgdXNlcktleTogdXNlclB1YixcbiAgICAgICAgICAgICAgYmFja3VwS2V5OiBiYWNrdXBQdWIsXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgICAgICBiaXRnb0tleSxcbiAgICAgICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcmVjb3ZlcnlEZXN0aW5hdGlvbiArICc/bWVtb0lkPScgKyBtZW1vLFxuICAgICAgICAgICAgICBzdGFydFRpbWUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbWVzc2FnZTogJ3N0YXJ0VGltZSBtdXN0IGJlIGEgZnV0dXJlIHRpbWVzdGFtcCwgZ290OiAnICsgc3RhcnRUaW1lIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ1JlY292ZXJ5IHdpdGggcm9vdCBrZXlzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2FuZEJveCA9IFNpbm9uLmNyZWF0ZVNhbmRib3goKTtcbiAgICAgIGxldCBnZXRCYWxhbmNlU3R1YjogU2lub25TdHViO1xuICAgICAgY29uc3Qgd2FsbGV0UGFzc3BocmFzZSA9ICd0ZXN0YnRjcGFzc3dvcmQxOTk5JztcbiAgICAgIGNvbnN0IHVzZXJFZGRzYVJvb3RYUHJ2ID1cbiAgICAgICAgJ3tcIml2XCI6XCJsSE9Ua2l1dWNSMkpXRkQxeDFncXBRPT1cIixcInZcIjoxLFwiaXRlclwiOjEwMDAwLFwia3NcIjoxMjgsXCJ0c1wiOjY0LFwibW9kZVwiOlwiY2NtXCIsXCJhZGF0YVwiOlwiXCIsXCJjaXBoZXJcIjpcImFlc1wiLFwic2FsdFwiOlwiSGtGckRWSCsrZDg9XCIsXCJjdFwiOlwiTkJ0YllkRkVLODRvSDl1eHdsL1VyaFJzVzVuR0pQbk1TcFJBbzhCbHJjN1dUU1B4R1htVlMvRXBVWUVWMDNIRzA2L0VueUJSMC9ZNmJqTFF6NGdrTDZjR0pEOWhneUtxRHZjOVJ0S0hhZ0Vibzc1b3hQcjB6UCtyMUhNVUdCVzM4VHRnb3I2NzRnQmViMU15ZXc2OXhjUzlLZ2d1Tnh3ejc3WDZmZGVCaHJmb2dMWTIydmN1TEE9PVwifSc7XG4gICAgICBjb25zdCB1c2VyRWRkc2FSb290UHViID0gJ2Q5Y2I5YzljNjE3Y2ZhMGI3MTU4NDk1MTZiYjA1NGEyYjVkNzhjMGUzZWVlZjAxMTE3NmZiOGJjMDEwOGM1MzEnO1xuICAgICAgY29uc3QgYmFja3VwRWRkc2FSb290WHBydiA9XG4gICAgICAgICd7XCJpdlwiOlwic0JvRUZCQk5vaTJZVklDUGYxNi9CUT09XCIsXCJ2XCI6MSxcIml0ZXJcIjoxMDAwMCxcImtzXCI6MTI4LFwidHNcIjo2NCxcIm1vZGVcIjpcImNjbVwiLFwiYWRhdGFcIjpcIlwiLFwiY2lwaGVyXCI6XCJhZXNcIixcInNhbHRcIjpcIkhrRnJEVkgrK2Q4PVwiLFwiY3RcIjpcIkdzY09xSkMrSXErTHIzOXBsUXA1WkNhbVZscEpIT2x0R1RaNy9VblV1bkloRm1aV01CTHhqRVZuTU90UHJlYjBOWjQvU0ZxTy9OM21adnE2SmJCN3ZXUnhKdXFrQklpVmNJUndrU1dkVzU1Y2JvS3gyZWMzYWpnOCt1TzJwYnZORHMyNlErOU50WjRqWm5LTnFTVVhpQ210SlhMUkhRMzJveUQrb2xLUnBJUjJOUW8yKzdrSUV3PT1cIn0nO1xuICAgICAgY29uc3QgYmFja3VwRWRkc2FSb290UHViID0gJ2YxNjNiMWI4ZWU0YzMzNDNhOTdhYzFkMjQ3MGI5NjdlOTY3YWM3YjRlMzczMWNhY2YwMmYyOGExNDM0YTJmOTknO1xuICAgICAgY29uc3Qgcm9vdEFkZHJlc3MgPSAnMC4wLjM2NDQ2NjcnO1xuICAgICAgY29uc3QgbWVtb0lkID0gJzAnO1xuXG4gICAgICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0QmFsYW5jZVN0dWIgPSBzYW5kQm94XG4gICAgICAgICAgLnN0dWIoSGJhci5wcm90b3R5cGUsICdnZXRBY2NvdW50QmFsYW5jZScpXG4gICAgICAgICAgLnJlc29sdmVzKHsgaGJhcnM6IGZvcm1hdEJhbGFuY2VSZXNwb25zZShiYWxhbmNlKSwgdG9rZW5zOiBbXSB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICBzYW5kQm94LnZlcmlmeUFuZFJlc3RvcmUoKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGJ1aWxkIGFuZCBzaWduIG5vbi1iaXRnbyByZWNvdmVyeSB0eCB3aXRoIHJvb3Qga2V5cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgZXhwZWN0ZWRBbW91bnQgPSBuZXcgQmlnTnVtYmVyKGJhbGFuY2UpLm1pbnVzKGRlZmF1bHRGZWUpLnRvU3RyaW5nKCk7XG5cbiAgICAgICAgY29uc3QgcmVjb3ZlcnkgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5OiB1c2VyRWRkc2FSb290WFBydixcbiAgICAgICAgICBiYWNrdXBLZXk6IGJhY2t1cEVkZHNhUm9vdFhwcnYsXG4gICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uICsgJz9tZW1vSWQ9JyArIG1lbW9JZCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZ2V0QmFsYW5jZVN0dWIuY2FsbENvdW50LnNob3VsZC5lcXVhbCgxKTtcblxuICAgICAgICByZWNvdmVyeS5zaG91bGQubm90LmJlLnVuZGVmaW5lZCgpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaWQnKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4Jyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb2luJywgJ3RoYmFyJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdub2RlSWQnLCBkZWZhdWx0Tm9kZUlkKTtcbiAgICAgICAgZ2V0QmFsYW5jZVN0dWIuY2FsbENvdW50LnNob3VsZC5lcXVhbCgxKTtcbiAgICAgICAgY29uc3QgdHhCdWlsZGVyID0gYmFzZWNvaW4uZ2V0QnVpbGRlckZhY3RvcnkoKS5mcm9tKHJlY292ZXJ5LnR4KTtcbiAgICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgdHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmVjb3ZlcnkudHgpO1xuICAgICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcbiAgICAgICAgdHhKc29uLmFtb3VudC5zaG91bGQuZXF1YWwoZXhwZWN0ZWRBbW91bnQpO1xuICAgICAgICB0eEpzb24udG8uc2hvdWxkLmVxdWFsKHJlY292ZXJ5RGVzdGluYXRpb24pO1xuICAgICAgICB0eEpzb24uZnJvbS5zaG91bGQuZXF1YWwocm9vdEFkZHJlc3MpO1xuICAgICAgICB0eEpzb24uZmVlLnNob3VsZC5lcXVhbChkZWZhdWx0RmVlKTtcbiAgICAgICAgdHhKc29uLm5vZGUuc2hvdWxkLmVxdWFsKGRlZmF1bHROb2RlSWQpO1xuICAgICAgICB0eEpzb24ubWVtby5zaG91bGQuZXF1YWwobWVtb0lkKTtcbiAgICAgICAgdHhKc29uLnZhbGlkRHVyYXRpb24uc2hvdWxkLmVxdWFsKGRlZmF1bHRWYWxpZER1cmF0aW9uKTtcbiAgICAgICAgdHhKc29uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdzdGFydFRpbWUnKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3N0YXJ0VGltZScsIHR4SnNvbi5zdGFydFRpbWUpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaWQnLCByb290QWRkcmVzcyArICdAJyArIHR4SnNvbi5zdGFydFRpbWUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgYnVpbGQgdW5zaWduZWQgc3dlZXAgdHgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IChEYXRlLm5vdygpIC8gMTAwMCArIDEwKS50b0ZpeGVkKCk7IC8vIHRpbWVzdGFtcCBpbiBzZWNvbmRzLCAxMCBzZWNvbmRzIGZyb20gbm93XG4gICAgICAgIGNvbnN0IGV4cGVjdGVkQW1vdW50ID0gbmV3IEJpZ051bWJlcihiYWxhbmNlKS5taW51cyhkZWZhdWx0RmVlKS50b1N0cmluZygpO1xuXG4gICAgICAgIGNvbnN0IHJlY292ZXJ5ID0gYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgdXNlcktleTogdXNlckVkZHNhUm9vdFB1YixcbiAgICAgICAgICBiYWNrdXBLZXk6IGJhY2t1cEVkZHNhUm9vdFB1YixcbiAgICAgICAgICByb290QWRkcmVzcyxcbiAgICAgICAgICBiaXRnb0tleSxcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uICsgJz9tZW1vSWQ9JyArIG1lbW9JZCxcbiAgICAgICAgICBzdGFydFRpbWUsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGdldEJhbGFuY2VTdHViLmNhbGxDb3VudC5zaG91bGQuZXF1YWwoMSk7XG5cbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4SGV4Jyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdpZCcsIHJvb3RBZGRyZXNzICsgJ0AnICsgc3RhcnRUaW1lICsgJy4wJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCd1c2VyS2V5JywgdXNlckVkZHNhUm9vdFB1Yik7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdiYWNrdXBLZXknLCBiYWNrdXBFZGRzYVJvb3RQdWIpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYml0Z29LZXknLCBiaXRnb0tleSk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdhZGRyZXNzJywgcm9vdEFkZHJlc3MpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnY29pbicsICd0aGJhcicpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnbWF4RmVlJywgZGVmYXVsdEZlZS50b1N0cmluZygpKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3JlY2lwaWVudHMnLCBbeyBhZGRyZXNzOiByZWNvdmVyeURlc3RpbmF0aW9uLCBhbW91bnQ6IGV4cGVjdGVkQW1vdW50IH1dKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2Ftb3VudCcsIGV4cGVjdGVkQW1vdW50KTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3ZhbGlkRHVyYXRpb24nLCBkZWZhdWx0VmFsaWREdXJhdGlvbik7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdub2RlSWQnLCBkZWZhdWx0Tm9kZUlkKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ21lbW8nLCBtZW1vSWQpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3RhcnRUaW1lJywgc3RhcnRUaW1lICsgJy4wJyk7XG4gICAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGJhc2Vjb2luLmdldEJ1aWxkZXJGYWN0b3J5KCkuZnJvbShyZWNvdmVyeS50eEhleCk7XG4gICAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICAgIGNvbnN0IHR4SnNvbiA9IHR4LnRvSnNvbigpO1xuICAgICAgICB0eEpzb24uaWQuc2hvdWxkLmVxdWFsKHJvb3RBZGRyZXNzICsgJ0AnICsgc3RhcnRUaW1lICsgJy4wJyk7XG4gICAgICAgIHR4SnNvbi5hbW91bnQuc2hvdWxkLmVxdWFsKGV4cGVjdGVkQW1vdW50KTtcbiAgICAgICAgdHhKc29uLnRvLnNob3VsZC5lcXVhbChyZWNvdmVyeURlc3RpbmF0aW9uKTtcbiAgICAgICAgdHhKc29uLmZyb20uc2hvdWxkLmVxdWFsKHJvb3RBZGRyZXNzKTtcbiAgICAgICAgdHhKc29uLmZlZS5zaG91bGQuZXF1YWwoZGVmYXVsdEZlZSk7XG4gICAgICAgIHR4SnNvbi5ub2RlLnNob3VsZC5lcXVhbChkZWZhdWx0Tm9kZUlkKTtcbiAgICAgICAgdHhKc29uLm1lbW8uc2hvdWxkLmVxdWFsKG1lbW9JZCk7XG4gICAgICAgIHR4SnNvbi52YWxpZER1cmF0aW9uLnNob3VsZC5lcXVhbChkZWZhdWx0VmFsaWREdXJhdGlvbik7XG4gICAgICAgIHR4SnNvbi5zdGFydFRpbWUuc2hvdWxkLmVxdWFsKHN0YXJ0VGltZSArICcuMCcpO1xuICAgICAgICB0eEpzb24udmFsaWREdXJhdGlvbi5zaG91bGQuZXF1YWwoZGVmYXVsdFZhbGlkRHVyYXRpb24pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdicm9hZGNhc3RUcmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBzYW5kQm94ID0gU2lub24uY3JlYXRlU2FuZGJveCgpO1xuXG4gICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNhbmRCb3gudmVyaWZ5QW5kUmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzdWNjZWVkIGlmIHRoZSBzdGFydFRpbWUgYW5kIHNlcmlhbGl6ZWRTaWduZWRUcmFuc2FjdGlvbiBhcmUgdmFsaWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzdGFydFRpbWUgPSAoRGF0ZS5ub3coKSAvIDEwMDAgLSAzKS50b0ZpeGVkKCk7IC8vIHRpbWVzdGFtcCBpbiBzZWNvbmRzLCAtMyBzZWNvbmRzIGZyb20gbm93IHNvIGl0J3MgdmFsaWQgYWZ0ZXIgMiBzZWNvbmRzXG4gICAgICBjb25zdCBleHBlY3RlZFJlc3BvbnNlID0geyB0eElkOiAnMC4wLjc2Njg0NjVAJyArIHN0YXJ0VGltZSArICcuMCcsIHN0YXR1czogJ1NVQ0NFU1MnIH07XG4gICAgICBjb25zdCBicm9hZGNhc3RTdHViID0gc2FuZEJveC5zdHViKEhiYXIucHJvdG90eXBlLCAnY2xpZW50QnJvYWRjYXN0VHJhbnNhY3Rpb24nKS5yZXNvbHZlcyhleHBlY3RlZFJlc3BvbnNlKTtcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRTaWduZWRUcmFuc2FjdGlvbiA9XG4gICAgICAgICcxYWNjMDEwYTY0MGEyMDU5MmE0ZmJiNzI2M2M1OWQ0NTBlNjUxZGY5NjYyMGRjOTIwOGVlN2M3ZDlkNmYyZmRjYjkxYzUzZjg4MzEyNjExYTQwMTA1YjdkMjUwYzgxZjM3MDViYzBiODUxNjhjZTNmZDAwMzMwMTMxYmI3NzAxMzc4NjgxYzhjMmU2YTA5YTkxODI4NzE1ZTczMzRmNGVmMjhkMjBmZjA5ODg3YzZlODdjMGE1YzY5M2UyMzgyNGMyNmYzYmExNjFmY2UwNDQ4MDUwYTY0MGEyMGE2OTA1MDk1NjE2YzNjZmFhMWJmNjFiNTNkZTMwZTkzOGNlNDExMmMzY2M0ZDI1MzkzZWM2YjliZjRkZWEwNjMxYTQwYmY5OGM1Yjg5YjdhMDg1NDRlZGFhMWY0YzA4YTBkZmE2ZWMzZjc4YjdlMmZkMjcwNDkyODM5ODQwNTBmMzhjY2YwMzAzZWU1N2EzNzdjYzBhNzI1ZmZkOTlkNjllOWZkOTE0NzcwYWIwOTQ5YmE1NTZkODRiM2IwMGNiMDdlMGQyMjUwMGExMzBhMDYwOGNlYThjMWFkMDYxMjA5MDgwMDEwMDAxOGYxODVkNDAzMTIwNjA4MDAxMDAwMTgwMzE4ODBjMmQ3MmYyMjAzMDhiNDAxMzIwMTM0NzIyNDBhMjIwYTBmMGEwOTA4MDAxMDAwMThmMTg1ZDQwMzEwZDNiMDUxMGEwZjBhMDkwODAwMTAwMDE4YzQ4NGQzMDMxMGQ0YjA1MSc7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBiYXNlY29pbi5icm9hZGNhc3RUcmFuc2FjdGlvbih7IHNlcmlhbGl6ZWRTaWduZWRUcmFuc2FjdGlvbiwgc3RhcnRUaW1lIH0pO1xuICAgICAgYnJvYWRjYXN0U3R1Yi5jYWxsQ291bnQuc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgcmVzdWx0LnNob3VsZC5kZWVwRXF1YWwoZXhwZWN0ZWRSZXNwb25zZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGlmIHRoZSBzdGFydFRpbWUgaXMgZXhwaXJlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IChEYXRlLm5vdygpIC8gMTAwMCAtIDIwMDApLnRvRml4ZWQoKTsgLy8gdGltZXN0YW1wIGluIHNlY29uZHMsIDIwMDAgc2Vjb25kcyBmcm9tIG5vd1xuICAgICAgY29uc3Qgc2VyaWFsaXplZFNpZ25lZFRyYW5zYWN0aW9uID1cbiAgICAgICAgJzFhY2MwMTBhNjQwYTIwNTkyYTRmYmI3MjYzYzU5ZDQ1MGU2NTFkZjk2NjIwZGM5MjA4ZWU3YzdkOWQ2ZjJmZGNiOTFjNTNmODgzMTI2MTFhNDAxMDViN2QyNTBjODFmMzcwNWJjMGI4NTE2OGNlM2ZkMDAzMzAxMzFiYjc3MDEzNzg2ODFjOGMyZTZhMDlhOTE4Mjg3MTVlNzMzNGY0ZWYyOGQyMGZmMDk4ODdjNmU4N2MwYTVjNjkzZTIzODI0YzI2ZjNiYTE2MWZjZTA0NDgwNTBhNjQwYTIwYTY5MDUwOTU2MTZjM2NmYWExYmY2MWI1M2RlMzBlOTM4Y2U0MTEyYzNjYzRkMjUzOTNlYzZiOWJmNGRlYTA2MzFhNDBiZjk4YzViODliN2EwODU0NGVkYWExZjRjMDhhMGRmYTZlYzNmNzhiN2UyZmQyNzA0OTI4Mzk4NDA1MGYzOGNjZjAzMDNlZTU3YTM3N2NjMGE3MjVmZmQ5OWQ2OWU5ZmQ5MTQ3NzBhYjA5NDliYTU1NmQ4NGIzYjAwY2IwN2UwZDIyNTAwYTEzMGEwNjA4Y2VhOGMxYWQwNjEyMDkwODAwMTAwMDE4ZjE4NWQ0MDMxMjA2MDgwMDEwMDAxODAzMTg4MGMyZDcyZjIyMDMwOGI0MDEzMjAxMzQ3MjI0MGEyMjBhMGYwYTA5MDgwMDEwMDAxOGYxODVkNDAzMTBkM2IwNTEwYTBmMGEwOTA4MDAxMDAwMThjNDg0ZDMwMzEwZDRiMDUxJztcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgYXdhaXQgYmFzZWNvaW4uYnJvYWRjYXN0VHJhbnNhY3Rpb24oeyBzZXJpYWxpemVkU2lnbmVkVHJhbnNhY3Rpb24sIHN0YXJ0VGltZSB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgKGVycm9yOiBhbnkpID0+IHtcbiAgICAgICAgICBhc3NlcnQub2soZXJyb3IubWVzc2FnZS5pbmNsdWRlcygnRmFpbGVkIHRvIGJyb2FkY2FzdCB0cmFuc2FjdGlvbiwgZXJyb3I6IHN0YXJ0VGltZSB3aW5kb3cgZXhwaXJlZCcpKTtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgdGhlIHNlcmlhbGl6ZWRTaWduZWRUcmFuc2FjdGlvbiBpcyBpbnZhbGlkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3RhcnRUaW1lID0gKERhdGUubm93KCkgLyAxMDAwIC0gMTApLnRvRml4ZWQoKTsgLy8gdGltZXN0YW1wIGluIHNlY29uZHMsIDEwIHNlY29uZHMgZnJvbSBub3dcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRTaWduZWRUcmFuc2FjdGlvbiA9ICdyYW5kb21zdHJpbmcnO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCBiYXNlY29pbi5icm9hZGNhc3RUcmFuc2FjdGlvbih7IHNlcmlhbGl6ZWRTaWduZWRUcmFuc2FjdGlvbiwgc3RhcnRUaW1lIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGlmIHRoZSBzdGFydFRpbWUgaW4gdGhlIHR4IGlzIGludmFsaWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBleHBlY3RlZFJlc3BvbnNlID1cbiAgICAgICAgJ3RyYW5zYWN0aW9uIDAuMC43NjY4NDY1QDE3MDYwNTYzMDEuMDAwMDAwMDAwIGZhaWxlZCBwcmVjaGVjayB3aXRoIHN0YXR1cyBJTlZBTElEX1RSQU5TQUNUSU9OX1NUQVJUJztcbiAgICAgIHNhbmRCb3guc3R1YihIYmFyLnByb3RvdHlwZSwgJ2NsaWVudEJyb2FkY2FzdFRyYW5zYWN0aW9uJykucmVqZWN0cyhuZXcgRXJyb3IoZXhwZWN0ZWRSZXNwb25zZSkpO1xuICAgICAgY29uc3Qgc2VyaWFsaXplZFNpZ25lZFRyYW5zYWN0aW9uID1cbiAgICAgICAgJzFhY2MwMTBhNjQwYTIwNTkyYTRmYmI3MjYzYzU5ZDQ1MGU2NTFkZjk2NjIwZGM5MjA4ZWU3YzdkOWQ2ZjJmZGNiOTFjNTNmODgzMTI2MTFhNDAxMDViN2QyNTBjODFmMzcwNWJjMGI4NTE2OGNlM2ZkMDAzMzAxMzFiYjc3MDEzNzg2ODFjOGMyZTZhMDlhOTE4Mjg3MTVlNzMzNGY0ZWYyOGQyMGZmMDk4ODdjNmU4N2MwYTVjNjkzZTIzODI0YzI2ZjNiYTE2MWZjZTA0NDgwNTBhNjQwYTIwYTY5MDUwOTU2MTZjM2NmYWExYmY2MWI1M2RlMzBlOTM4Y2U0MTEyYzNjYzRkMjUzOTNlYzZiOWJmNGRlYTA2MzFhNDBiZjk4YzViODliN2EwODU0NGVkYWExZjRjMDhhMGRmYTZlYzNmNzhiN2UyZmQyNzA0OTI4Mzk4NDA1MGYzOGNjZjAzMDNlZTU3YTM3N2NjMGE3MjVmZmQ5OWQ2OWU5ZmQ5MTQ3NzBhYjA5NDliYTU1NmQ4NGIzYjAwY2IwN2UwZDIyNTAwYTEzMGEwNjA4Y2VhOGMxYWQwNjEyMDkwODAwMTAwMDE4ZjE4NWQ0MDMxMjA2MDgwMDEwMDAxODAzMTg4MGMyZDcyZjIyMDMwOGI0MDEzMjAxMzQ3MjI0MGEyMjBhMGYwYTA5MDgwMDEwMDAxOGYxODVkNDAzMTBkM2IwNTEwYTBmMGEwOTA4MDAxMDAwMThjNDg0ZDMwMzEwZDRiMDUxJztcblxuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICBhd2FpdCBiYXNlY29pbi5icm9hZGNhc3RUcmFuc2FjdGlvbih7IHNlcmlhbGl6ZWRTaWduZWRUcmFuc2FjdGlvbiB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgeyBtZXNzYWdlOiBleHBlY3RlZFJlc3BvbnNlIH1cbiAgICAgICk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdkZXJpdmVLZXlXaXRoU2VlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGRlcml2ZSBrZXkgd2l0aCBzZWVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgKCgpID0+IHtcbiAgICAgICAgYmFzZWNvaW4uZGVyaXZlS2V5V2l0aFNlZWQoJ3Rlc3QnKTtcbiAgICAgIH0pLnNob3VsZC50aHJvdygnbWV0aG9kIGRlcml2ZUtleVdpdGhTZWVkIG5vdCBzdXBwb3J0ZWQgZm9yIGVkZHNhIGN1cnZlJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdHZW5lcmF0ZSB3YWxsZXQgUm9vdCBrZXkgcGFpcjogJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgZ2VuZXJhdGUga2V5IHBhaXInLCAoKSA9PiB7XG4gICAgICBjb25zdCBrcCA9IGJhc2Vjb2luLmdlbmVyYXRlUm9vdEtleVBhaXIoKTtcbiAgICAgIGJhc2Vjb2luLmlzVmFsaWRQdWIoa3AucHViKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICBjb25zdCBrZXlwYWlyID0gbmV3IEtleVBhaXIoeyBwcnY6IGtwLnBydiB9KS5nZXRLZXlzKHRydWUpO1xuICAgICAga2V5cGFpci5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncHJ2Jyk7XG4gICAgICBrZXlwYWlyLnBydj8uc2hvdWxkLmVxdWFsKGtwLnBydi5zbGljZSgwLCA2NCkpO1xuICAgICAga2V5cGFpci5wdWIuc2hvdWxkLmVxdWFsKGtwLnB1Yik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGtleSBwYWlyIGZyb20gc2VlZCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHNlZWQgPSBCdWZmZXIuZnJvbSgnOWQ2MWIxOWRlZmZkNWE2MGJhODQ0YWY0OTJlYzJjYzQ0NDQ5YzU2OTdiMzI2OTE5NzAzYmFjMDMxY2FlN2Y2MCcsICdoZXgnKTtcbiAgICAgIGNvbnN0IGtwID0gYmFzZWNvaW4uZ2VuZXJhdGVSb290S2V5UGFpcihzZWVkKTtcbiAgICAgIGJhc2Vjb2luLmlzVmFsaWRQdWIoa3AucHViKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICBrcC5wdWIuc2hvdWxkLmVxdWFsKCdkNzVhOTgwMTgyYjEwYWI3ZDU0YmZlZDNjOTY0MDczYTBlZTE3MmYzZGFhNjIzMjVhZjAyMWE2OGY3MDc1MTFhJyk7XG4gICAgICBrcC5wcnYuc2hvdWxkLmVxdWFsKFxuICAgICAgICAnOWQ2MWIxOWRlZmZkNWE2MGJhODQ0YWY0OTJlYzJjYzQ0NDQ5YzU2OTdiMzI2OTE5NzAzYmFjMDMxY2FlN2Y2MGQ3NWE5ODAxODJiMTBhYjdkNTRiZmVkM2M5NjQwNzNhMGVlMTcyZjNkYWE2MjMyNWFmMDIxYTY4ZjcwNzUxMWEnXG4gICAgICApO1xuXG4gICAgICBjb25zdCBrZXlwYWlyID0gbmV3IEtleVBhaXIoeyBwcnY6IGtwLnBydiB9KS5nZXRLZXlzKHRydWUpO1xuICAgICAga2V5cGFpci5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncHJ2Jyk7XG4gICAgICBrZXlwYWlyLnBydj8uc2hvdWxkLmVxdWFsKGtwLnBydi5zbGljZSgwLCA2NCkpO1xuICAgICAga2V5cGFpci5wdWIuc2hvdWxkLmVxdWFsKGtwLnB1Yik7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=

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


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