PHP WebShell

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

Просмотр файла: near.js

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
const should = require("should");
const sdk_test_1 = require("@bitgo/sdk-test");
const sdk_api_1 = require("@bitgo/sdk-api");
const crypto_1 = require("crypto");
const near_1 = require("../fixtures/near");
const _ = __importStar(require("lodash"));
const sinon = __importStar(require("sinon"));
const src_1 = require("../../src");
const getBuilderFactory_1 = require("./getBuilderFactory");
const statics_1 = require("@bitgo/statics");
describe('NEAR:', function () {
    let bitgo;
    let basecoin;
    let newTxPrebuild;
    let newTxParams;
    const factory = (0, getBuilderFactory_1.getBuilderFactory)('tnear');
    const txPrebuild = {
        txHex: near_1.rawTx.transfer.unsigned,
        txInfo: {},
    };
    const txParams = {
        recipients: [
            {
                address: '9f7b0675db59d19b4bd9c8c72eaabba75a9863d02b30115b8b3c3ca5c20f0254',
                amount: '1000000000000000000000000',
            },
        ],
    };
    before(function () {
        bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
        bitgo.initializeTestVars();
        bitgo.safeRegister('tnear', src_1.Near.createInstance);
        bitgo.safeRegister('near', src_1.TNear.createInstance);
        basecoin = bitgo.coin('tnear');
        newTxPrebuild = () => {
            return _.cloneDeep(txPrebuild);
        };
        newTxParams = () => {
            return _.cloneDeep(txParams);
        };
    });
    it('should retun the right info', function () {
        const near = bitgo.coin('near');
        const tnear = bitgo.coin('tnear');
        near.getChain().should.equal('near');
        near.getFamily().should.equal('near');
        near.getFullName().should.equal('Near');
        near.getBaseFactor().should.equal(1e24);
        tnear.getChain().should.equal('tnear');
        tnear.getFamily().should.equal('near');
        tnear.getFullName().should.equal('Testnet Near');
        tnear.getBaseFactor().should.equal(1e24);
    });
    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(signature)).should.equals(true);
        });
        it('should fail with missing private key', async () => {
            const keyPair = new src_1.KeyPair({
                pub: '7788327c695dca4b3e649a0db45bc3e703a2c67428fce360e61800cc4248f4f7',
            }).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', () => {
        it('should sign transaction', async function () {
            const signed = await basecoin.signTransaction({
                txPrebuild: {
                    txHex: near_1.rawTx.transfer.unsigned,
                },
                pubs: [near_1.accounts.account1.publicKey],
                prv: near_1.accounts.account1.secretKey,
            });
            signed.txHex.should.equal(near_1.rawTx.transfer.signed);
        });
        it('should fail to sign transaction with an invalid key', async function () {
            try {
                await basecoin.signTransaction({
                    txPrebuild: {
                        txHex: near_1.rawTx.transfer.unsigned,
                    },
                    pubs: [near_1.accounts.account2.publicKey],
                    prv: near_1.accounts.account1.secretKey,
                });
            }
            catch (e) {
                should.equal(e.message, 'Private key cannot sign the transaction');
            }
        });
        it('should fail to build transaction with missing params', async function () {
            try {
                await basecoin.signTransaction({
                    txPrebuild: {
                        txHex: near_1.rawTx.transfer.unsigned,
                        key: near_1.accounts.account1.publicKey,
                    },
                    prv: near_1.accounts.account1.secretKey,
                });
            }
            catch (e) {
                should.notEqual(e, null);
            }
        });
    });
    describe('Generate wallet key pair: ', () => {
        it('should generate key pair', () => {
            const kp = basecoin.generateKeyPair();
            basecoin.isValidPub(kp.pub).should.equal(true);
            basecoin.isValidPrv(kp.prv).should.equal(true);
        });
        it('should generate key pair from seed', () => {
            const seed = Buffer.from('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60', 'hex');
            const kp = basecoin.generateKeyPair(seed);
            basecoin.isValidPub(kp.pub).should.equal(true);
            basecoin.isValidPrv(kp.prv).should.equal(true);
        });
    });
    describe('Verify transaction: ', () => {
        const amount = '1000000';
        const gas = '125000000000000';
        it('should succeed to verify unsigned transaction in base64 encoding', async () => {
            const txPrebuild = newTxPrebuild();
            const txParams = newTxParams();
            const verification = {};
            const isTransactionVerified = await basecoin.verifyTransaction({ txParams, txPrebuild, verification });
            isTransactionVerified.should.equal(true);
        });
        it('should succeed to verify signed transaction in base64 encoding', async () => {
            const txPrebuild = {
                txHex: near_1.rawTx.transfer.signed,
                txInfo: {},
            };
            const txParams = newTxParams();
            const verification = {};
            const isTransactionVerified = await basecoin.verifyTransaction({ txParams, txPrebuild, verification });
            isTransactionVerified.should.equal(true);
        });
        it('should fail verify transactions when have different recipients', async () => {
            const txPrebuild = newTxPrebuild();
            const txParams = {
                recipients: [
                    {
                        address: '9f7b0675db59d19b4bd9c8c72eaabba75a9863d02b30115b8b3c3ca5c20f0254',
                        amount: '1000000000000000000000000',
                    },
                    {
                        address: '9f7b0675db59d19b4bd9c8c72eaabba75a9863d02b30115b8b3c3ca5c20f0254',
                        amount: '2000000000000000000000000',
                    },
                ],
            };
            const verification = {};
            await basecoin
                .verifyTransaction({ txParams, txPrebuild, verification })
                .should.be.rejectedWith('Tx outputs does not match with expected txParams recipients');
        });
        it('should fail verify transactions when total amount does not match with expected total amount field', async () => {
            const explainedTx = {
                id: '5jTEPuDcMCeEgp1iyEbNBKsnhYz4F4c1EPDtRmxm3wCw',
                displayOrder: ['outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type'],
                outputAmount: '90000',
                changeAmount: '0',
                changeOutputs: [],
                outputs: [
                    {
                        address: '9f7b0675db59d19b4bd9c8c72eaabba75a9863d02b30115b8b3c3ca5c20f0254',
                        amount: '1000000000000000000000000',
                    },
                ],
                fee: {
                    fee: '',
                },
                type: 0,
            };
            const stub = sinon.stub(src_1.Transaction.prototype, 'explainTransaction');
            const txPrebuild = newTxPrebuild();
            const txParams = newTxParams();
            const verification = {};
            stub.returns(explainedTx);
            await basecoin
                .verifyTransaction({ txParams, txPrebuild, verification })
                .should.be.rejectedWith('Tx total amount does not match with expected total amount field');
            stub.restore();
        });
        it('should succeed to verify transaction in hex encoding', async () => {
            const txParams = newTxParams();
            const txPrebuild = newTxPrebuild();
            const verification = {};
            const isTransactionVerified = await basecoin.verifyTransaction({ txParams, txPrebuild, verification });
            isTransactionVerified.should.equal(true);
        });
        it('should convert serialized hex string to base64', async function () {
            const txParams = newTxParams();
            const txPrebuild = newTxPrebuild();
            const verification = {};
            txPrebuild.txHex = Buffer.from(txPrebuild.txHex, 'base64').toString('hex');
            const validTransaction = await basecoin.verifyTransaction({ txParams, txPrebuild, verification });
            validTransaction.should.equal(true);
        });
        it('should verify when input `recipients` is absent', async function () {
            const txParams = newTxParams();
            txParams.recipients = undefined;
            const txPrebuild = newTxPrebuild();
            const validTransaction = await basecoin.verifyTransaction({ txParams, txPrebuild });
            validTransaction.should.equal(true);
        });
        it('should fail verify when txHex is invalid', async function () {
            const txParams = newTxParams();
            txParams.recipients = undefined;
            const txPrebuild = {};
            await basecoin
                .verifyTransaction({ txParams, txPrebuild })
                .should.rejectedWith('missing required tx prebuild property txHex');
        });
        it('should succeed to verify transactions when recipients has extra data', async function () {
            const txPrebuild = newTxPrebuild();
            const txParams = newTxParams();
            txParams.data = 'data';
            const validTransaction = await basecoin.verifyTransaction({ txParams, txPrebuild });
            validTransaction.should.equal(true);
        });
        it('should verify activate staking transaction', async function () {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder
                .amount(amount)
                .gas(gas)
                .sender(near_1.accounts.account1.address, near_1.accounts.account1.publicKey)
                .receiverId(near_1.validatorContractAddress)
                .recentBlockHash(near_1.blockHash.block1)
                .nonce(1);
            txBuilder.sign({ key: near_1.accounts.account1.secretKey });
            const tx = await txBuilder.build();
            const txToBroadcastFormat = tx.toBroadcastFormat();
            const txPrebuild = {
                txHex: txToBroadcastFormat,
            };
            const txParams = {
                recipients: [
                    {
                        address: 'lavenderfive.pool.f863973.m0',
                        amount: '1000000',
                    },
                ],
            };
            const validTransaction = await basecoin.verifyTransaction({ txParams, txPrebuild });
            validTransaction.should.equal(true);
        });
        it('should verify deactivate staking transaction', async function () {
            const txBuilder = factory.getStakingDeactivateBuilder();
            txBuilder
                .amount(amount)
                .gas(gas)
                .sender(near_1.accounts.account1.address, near_1.accounts.account1.publicKey)
                .receiverId(near_1.validatorContractAddress)
                .recentBlockHash(near_1.blockHash.block1)
                .nonce(1);
            txBuilder.sign({ key: near_1.accounts.account1.secretKey });
            const tx = await txBuilder.build();
            const txToBroadcastFormat = tx.toBroadcastFormat();
            const txPrebuild = {
                txHex: txToBroadcastFormat,
            };
            const txParams = {
                recipients: [],
            };
            const validTransaction = await basecoin.verifyTransaction({ txParams, txPrebuild });
            validTransaction.should.equal(true);
        });
        it('should verify withdraw staking transaction', async function () {
            const txBuilder = factory.getStakingWithdrawBuilder();
            txBuilder
                .amount(amount)
                .gas(gas)
                .sender(near_1.accounts.account1.address, near_1.accounts.account1.publicKey)
                .receiverId(near_1.validatorContractAddress)
                .recentBlockHash(near_1.blockHash.block1)
                .nonce(1);
            txBuilder.sign({ key: near_1.accounts.account1.secretKey });
            const tx = await txBuilder.build();
            const txToBroadcastFormat = tx.toBroadcastFormat();
            const txPrebuild = {
                txHex: txToBroadcastFormat,
            };
            const txParams = {
                recipients: [
                    {
                        address: '61b18c6dc02ddcabdeac56cb4f21a971cc41cc97640f6f85b073480008c53a0d',
                        amount: '1000000',
                    },
                ],
            };
            const validTransaction = await basecoin.verifyTransaction({ txParams, txPrebuild });
            validTransaction.should.equal(true);
        });
    });
    describe('Explain Transactions:', () => {
        const amount = '1000000';
        const gas = '125000000000000';
        it('should explain an unsigned transfer transaction', async function () {
            const explainedTransaction = await basecoin.explainTransaction({
                txPrebuild: {
                    txHex: near_1.rawTx.transfer.signed,
                },
            });
            explainedTransaction.should.deepEqual({
                displayOrder: ['outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type'],
                id: '5jTEPuDcMCeEgp1iyEbNBKsnhYz4F4c1EPDtRmxm3wCw',
                type: 0,
                changeOutputs: [],
                changeAmount: '0',
                outputAmount: '1000000000000000000000000',
                outputs: [
                    {
                        address: '9f7b0675db59d19b4bd9c8c72eaabba75a9863d02b30115b8b3c3ca5c20f0254',
                        amount: '1000000000000000000000000',
                    },
                ],
                fee: {
                    fee: '',
                },
            });
        });
        it('should explain a signed transfer transaction', async function () {
            const explainedTransaction = await basecoin.explainTransaction({
                txPrebuild: {
                    txHex: near_1.rawTx.transfer.signed,
                },
            });
            explainedTransaction.should.deepEqual({
                displayOrder: ['outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type'],
                id: '5jTEPuDcMCeEgp1iyEbNBKsnhYz4F4c1EPDtRmxm3wCw',
                type: 0,
                changeOutputs: [],
                changeAmount: '0',
                outputAmount: '1000000000000000000000000',
                outputs: [
                    {
                        address: '9f7b0675db59d19b4bd9c8c72eaabba75a9863d02b30115b8b3c3ca5c20f0254',
                        amount: '1000000000000000000000000',
                    },
                ],
                fee: {
                    fee: '',
                },
            });
        });
        it('should explain activate staking transaction', async function () {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder
                .amount(amount)
                .gas(gas)
                .sender(near_1.accounts.account1.address, near_1.accounts.account1.publicKey)
                .receiverId(near_1.validatorContractAddress)
                .recentBlockHash(near_1.blockHash.block1)
                .nonce(1);
            txBuilder.sign({ key: near_1.accounts.account1.secretKey });
            const tx = await txBuilder.build();
            const txToBroadcastFormat = tx.toBroadcastFormat();
            const explainedTransaction = await basecoin.explainTransaction({
                txPrebuild: {
                    txHex: txToBroadcastFormat,
                },
            });
            explainedTransaction.should.deepEqual({
                displayOrder: ['outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type'],
                id: 'GpiLLaGs2Fk2bd7SQvhkJaZjj74UnPPdF7cUa9pw15je',
                type: 13,
                changeOutputs: [],
                changeAmount: '0',
                outputAmount: '1000000',
                outputs: [
                    {
                        address: 'lavenderfive.pool.f863973.m0',
                        amount: '1000000',
                    },
                ],
                fee: {
                    fee: '',
                },
            });
        });
        it('should explain deactivate staking transaction', async function () {
            const txBuilder = factory.getStakingDeactivateBuilder();
            txBuilder
                .amount(amount)
                .gas(gas)
                .sender(near_1.accounts.account1.address, near_1.accounts.account1.publicKey)
                .receiverId(near_1.validatorContractAddress)
                .recentBlockHash(near_1.blockHash.block1)
                .nonce(1);
            txBuilder.sign({ key: near_1.accounts.account1.secretKey });
            const tx = await txBuilder.build();
            const txToBroadcastFormat = tx.toBroadcastFormat();
            const explainedTransaction = await basecoin.explainTransaction({
                txPrebuild: {
                    txHex: txToBroadcastFormat,
                },
            });
            explainedTransaction.should.deepEqual({
                displayOrder: ['outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type'],
                id: 'CDxPRP3DgHN8gYmRDagk5TRuX7fsCRYHcuqoNULyQPUW',
                type: 17,
                changeOutputs: [],
                changeAmount: '0',
                outputAmount: '0',
                outputs: [],
                fee: {
                    fee: '',
                },
            });
        });
        it('should explain withdraw staking transaction', async function () {
            const txBuilder = factory.getStakingWithdrawBuilder();
            txBuilder
                .amount(amount)
                .gas(gas)
                .sender(near_1.accounts.account1.address, near_1.accounts.account1.publicKey)
                .receiverId(near_1.validatorContractAddress)
                .recentBlockHash(near_1.blockHash.block1)
                .nonce(1);
            txBuilder.sign({ key: near_1.accounts.account1.secretKey });
            const tx = await txBuilder.build();
            const txToBroadcastFormat = tx.toBroadcastFormat();
            const explainedTransaction = await basecoin.explainTransaction({
                txPrebuild: {
                    txHex: txToBroadcastFormat,
                },
            });
            explainedTransaction.should.deepEqual({
                displayOrder: ['outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type'],
                id: '52ZX8MUwmYc6WQ67riUBpmntkcSxxT5aKkJYt5CtCZub',
                type: 15,
                changeOutputs: [],
                changeAmount: '0',
                outputAmount: '1000000',
                outputs: [
                    {
                        address: '61b18c6dc02ddcabdeac56cb4f21a971cc41cc97640f6f85b073480008c53a0d',
                        amount: '1000000',
                    },
                ],
                fee: {
                    fee: '',
                },
            });
        });
        it('should fail to explain transaction with missing params', async function () {
            try {
                await basecoin.explainTransaction({
                    txPrebuild: {},
                });
            }
            catch (error) {
                should.equal(error.message, 'Invalid transaction');
            }
        });
        it('should fail to explain transaction with wrong params', async function () {
            try {
                await basecoin.explainTransaction({
                    txPrebuild: {
                        txHex: 'invalidTxHex',
                    },
                });
            }
            catch (error) {
                should.equal(error.message, 'Invalid transaction');
            }
        });
    });
    describe('Parse Transactions:', () => {
        const TEN_MILLION_NEAR = '10000000000000000000000000000000';
        const ONE_MILLION_NEAR = '1000000000000000000000000';
        const amount = TEN_MILLION_NEAR;
        const gas = '125000000000000';
        const response1 = {
            address: '9f7b0675db59d19b4bd9c8c72eaabba75a9863d02b30115b8b3c3ca5c20f0254',
            amount: ONE_MILLION_NEAR,
        };
        const response2 = {
            address: 'lavenderfive.pool.f863973.m0',
            amount: TEN_MILLION_NEAR,
        };
        const response3 = {
            address: '61b18c6dc02ddcabdeac56cb4f21a971cc41cc97640f6f85b073480008c53a0d',
            amount: TEN_MILLION_NEAR,
        };
        it('should parse an unsigned transfer transaction', async function () {
            const parsedTransaction = await basecoin.parseTransaction({
                txPrebuild: {
                    txHex: near_1.rawTx.transfer.unsigned,
                },
                feeInfo: {
                    fee: '5000',
                },
            });
            parsedTransaction.should.deepEqual({
                inputs: [response1],
                outputs: [response1],
            });
        });
        it('should parse a signed transfer transaction', async function () {
            const parsedTransaction = await basecoin.parseTransaction({
                txPrebuild: {
                    txHex: near_1.rawTx.transfer.signed,
                },
                feeInfo: {
                    fee: '',
                },
            });
            parsedTransaction.should.deepEqual({
                inputs: [response1],
                outputs: [response1],
            });
        });
        it('should fail parse a signed transfer transaction when explainTransaction response is undefined', async function () {
            const stub = sinon.stub(src_1.Near.prototype, 'explainTransaction');
            stub.resolves(undefined);
            await basecoin
                .parseTransaction({
                txPrebuild: {
                    txHex: near_1.rawTx.transfer.signed,
                },
                feeInfo: {
                    fee: '',
                },
            })
                .should.be.rejectedWith('Invalid transaction');
            stub.restore();
        });
        it('should parse activate staking transaction', async function () {
            const txBuilder = factory.getStakingActivateBuilder();
            txBuilder
                .amount(amount)
                .gas(gas)
                .sender(near_1.accounts.account1.address, near_1.accounts.account1.publicKey)
                .receiverId(near_1.validatorContractAddress)
                .recentBlockHash(near_1.blockHash.block1)
                .nonce(1);
            txBuilder.sign({ key: near_1.accounts.account1.secretKey });
            const tx = await txBuilder.build();
            const txToBroadcastFormat = tx.toBroadcastFormat();
            const parsedTransaction = await basecoin.parseTransaction({
                txPrebuild: {
                    txHex: txToBroadcastFormat,
                },
            });
            parsedTransaction.should.deepEqual({
                inputs: [response2],
                outputs: [response2],
            });
        });
        it('should parse deactivate staking transaction', async function () {
            const txBuilder = factory.getStakingDeactivateBuilder();
            txBuilder
                .amount(amount)
                .gas(gas)
                .sender(near_1.accounts.account1.address, near_1.accounts.account1.publicKey)
                .receiverId(near_1.validatorContractAddress)
                .recentBlockHash(near_1.blockHash.block1)
                .nonce(1);
            txBuilder.sign({ key: near_1.accounts.account1.secretKey });
            const tx = await txBuilder.build();
            const txToBroadcastFormat = tx.toBroadcastFormat();
            const parsedTransaction = await basecoin.parseTransaction({
                txPrebuild: {
                    txHex: txToBroadcastFormat,
                },
            });
            parsedTransaction.should.deepEqual({
                inputs: [],
                outputs: [],
            });
        });
        it('should parse withdraw staking transaction', async function () {
            const txBuilder = factory.getStakingWithdrawBuilder();
            txBuilder
                .amount(amount)
                .gas(gas)
                .sender(near_1.accounts.account1.address, near_1.accounts.account1.publicKey)
                .receiverId(near_1.validatorContractAddress)
                .recentBlockHash(near_1.blockHash.block1)
                .nonce(1);
            txBuilder.sign({ key: near_1.accounts.account1.secretKey });
            const tx = await txBuilder.build();
            const txToBroadcastFormat = tx.toBroadcastFormat();
            const parsedTransaction = await basecoin.parseTransaction({
                txPrebuild: {
                    txHex: txToBroadcastFormat,
                },
            });
            parsedTransaction.should.deepEqual({
                inputs: [response3],
                outputs: [response3],
            });
        });
    });
    describe('Recover Transactions:', () => {
        const sandBox = sinon.createSandbox();
        const coin = statics_1.coins.get('tnear');
        beforeEach(() => {
            const callBack = sandBox.stub(src_1.Near.prototype, 'getDataFromNode');
            callBack
                .withArgs({
                payload: {
                    jsonrpc: '2.0',
                    id: 'dontcare',
                    method: 'query',
                    params: {
                        request_type: 'view_access_key',
                        finality: 'final',
                        account_id: near_1.accountInfo.accountId,
                        public_key: near_1.accountInfo.bs58EncodedPublicKey,
                    },
                },
            })
                .resolves(near_1.NearResponses.getAccessKeyResponse);
            callBack
                .withArgs({
                payload: {
                    jsonrpc: '2.0',
                    id: 'dontcare',
                    method: 'query',
                    params: {
                        request_type: 'view_account',
                        finality: 'final',
                        account_id: near_1.accountInfo.accountId,
                    },
                },
            })
                .resolves(near_1.NearResponses.getAccountResponse);
            callBack.withArgs().resolves(near_1.NearResponses.getProtocolConfigResp);
            callBack
                .withArgs({
                payload: {
                    jsonrpc: '2.0',
                    id: 'dontcare',
                    method: 'gas_price',
                    params: [near_1.accountInfo.blockHash],
                },
            })
                .resolves(near_1.NearResponses.getGasPriceResponse);
        });
        afterEach(() => {
            sandBox.restore();
        });
        it('should recover a txn for non-bitgo recoveries', async function () {
            const res = await basecoin.recover({
                userKey: near_1.keys.userKey,
                backupKey: near_1.keys.backupKey,
                bitgoKey: near_1.keys.bitgoKey,
                recoveryDestination: 'abhay-near.testnet',
                walletPassphrase: 'Ghghjkg!455544llll',
            });
            res.should.not.be.empty();
            res.should.hasOwnProperty('serializedTx');
            const NonBitGoTxnDeserialize = new src_1.Transaction(coin);
            NonBitGoTxnDeserialize.fromRawTransaction(res.serializedTx);
            const NonBitGoTxnJson = NonBitGoTxnDeserialize.toJson();
            should.equal(NonBitGoTxnJson.nonce, near_1.nonce);
            should.equal(NonBitGoTxnJson.signerId, near_1.accountInfo.accountId);
            should.equal(NonBitGoTxnJson.publicKey, 'ed25519:' + near_1.accountInfo.bs58EncodedPublicKey);
            sandBox.assert.callCount(basecoin.getDataFromNode, 4);
        });
        it('should recover a txn for unsigned sweep recoveries', async function () {
            const res = await basecoin.recover({
                bitgoKey: near_1.keys.bitgoKey,
                recoveryDestination: 'abhay-near.testnet',
            });
            // Assertions for the structure of the result
            should.exist(res);
            res.should.have.property('txRequests').which.is.an.Array();
            res.txRequests[0].should.have.property('transactions').which.is.an.Array();
            res.txRequests[0].transactions[0].should.have.property('unsignedTx');
            // Assertions for the unsigned transaction
            const unsignedTx = res.txRequests[0].transactions[0].unsignedTx;
            unsignedTx.should.have.property('serializedTx').which.is.a.String();
            unsignedTx.should.have.property('scanIndex', 0);
            unsignedTx.should.have.property('coin', 'tnear');
            unsignedTx.should.have.property('signableHex', 'c27d684b6f09c4b603d9bf8a08baedf12b8bb951f314acd747b16bb75cfbf687');
            unsignedTx.should.have.property('derivationPath', 'm/0');
            // Assertions for parsed transaction
            const parsedTx = unsignedTx.parsedTx;
            parsedTx.should.have.property('inputs').which.is.an.Array();
            parsedTx.inputs[0].should.have.property('address', 'f256196dae617aa348149c1e61e997272492668d517506d7a6e2392e06ea532c');
            parsedTx.inputs[0].should.have.property('valueString', '1.97885506094866269650000001e+26');
            parsedTx.inputs[0].should.have.property('value', 1.9788550609486627e26);
            parsedTx.should.have.property('outputs').which.is.an.Array();
            parsedTx.outputs[0].should.have.property('address', 'abhay-near.testnet');
            parsedTx.outputs[0].should.have.property('valueString', '1.97885506094866269650000001e+26');
            parsedTx.outputs[0].should.have.property('coinName', 'tnear');
            parsedTx.should.have.property('spendAmount', '1.97885506094866269650000001e+26');
            parsedTx.should.have.property('type', '');
            // Assertions for fee info
            unsignedTx.should.have.property('feeInfo');
            unsignedTx.feeInfo.should.have.property('fee', 68628637968750000000);
            unsignedTx.feeInfo.should.have.property('feeString', '68628637968750000000');
            // Assertions for coin-specific data
            unsignedTx.should.have.property('coinSpecific');
            unsignedTx.coinSpecific.should.have.property('commonKeychain', '8699d2e05d60a3f7ab733a74ccf707f3407494b60f4253616187f5262e20737519a1763de0bcc4d165a7fa0e4dde67a1426ec4cc9fcd0820d749e6589dcfa08e');
        });
        it('should take OVC output and generate a signed sweep transaction for NEAR', async function () {
            const params = near_1.ovcResponse; // NEAR-specific response fixture
            const recoveryTxn = await basecoin.createBroadcastableSweepTransaction(params);
            // Validate the serialized transaction
            recoveryTxn.transactions[0].serializedTx.should.equal('QAAAAGIzODNjYWM2ZjNjZDY0OTViZDZhYjg3NzMwMGE4NzliN2RiYzRhMTZhYjBlZjE5NzlkZTZmNzNkYjAyNDlmYWEAs4PKxvPNZJW9arh3MAqHm328SharDvGXneb3PbAkn6oBuZUj6a0AAEAAAABlYWRiMzIwOGZiOWU5MWY2MGQ3NmUzYzUxNzEzZDA1Y2I0YTU5NDFlNWYzNTVlMWZmOThlMTQwYTcxMjNlODRl2hbJtC4rwLyWAbMzTgTcRmr5xpWlrXOXbzxMWcP7wwcBAAAAA9A1oVfvpz3o4hcAAAAAAAAAvAIWOj2c1QhqbWcClZ8dW7KQcfG9gYFkimbRDyI8t8L4TUiUyRXMYv5U8jaEsNFWteBcUGolFcLQSbbD5MCpDw==');
            // Validate the scan index
            recoveryTxn.transactions[0].scanIndex.should.equal(0);
            recoveryTxn.lastScanIndex.should.equal(0);
        });
    });
    describe('Recover Transactions for wallet with multiple addresses:', () => {
        const destAddr = 'abhay-near.testnet';
        const sandBox = sinon.createSandbox();
        const coin = statics_1.coins.get('tnear');
        const address1Info = {
            accountId: 'f6842bf4a8e980704fbd9fb799bfbe0a116fd5d8d06f6774e792c68c907d9b20',
            bs58EncodedPublicKey: 'HbJBqyagBqtSNUR74fLMQSjQ8HyQVs66fyMySPhZLXz7',
            blockHash: '844N9aWefd4TvJwdiBgXDVPz4W9z436kohTiXnp5y4fq',
        };
        beforeEach(function () {
            const callBack = sandBox.stub(src_1.Near.prototype, 'getDataFromNode');
            callBack
                .withArgs({
                payload: {
                    jsonrpc: '2.0',
                    id: 'dontcare',
                    method: 'query',
                    params: {
                        request_type: 'view_access_key',
                        finality: 'final',
                        account_id: address1Info.accountId,
                        public_key: address1Info.bs58EncodedPublicKey,
                    },
                },
            })
                .resolves(near_1.NearResponses.getAccessKeyResponse);
            callBack
                .withArgs({
                payload: {
                    jsonrpc: '2.0',
                    id: 'dontcare',
                    method: 'query',
                    params: {
                        request_type: 'view_account',
                        finality: 'final',
                        account_id: near_1.accountInfo.accountId,
                    },
                },
            })
                .resolves(near_1.NearResponses.getZeroBalanceAccountResponse);
            callBack
                .withArgs({
                payload: {
                    jsonrpc: '2.0',
                    id: 'dontcare',
                    method: 'query',
                    params: {
                        request_type: 'view_account',
                        finality: 'final',
                        account_id: address1Info.accountId,
                    },
                },
            })
                .resolves(near_1.NearResponses.getAccountResponse);
            callBack.withArgs().resolves(near_1.NearResponses.getProtocolConfigResp);
            callBack
                .withArgs({
                payload: {
                    jsonrpc: '2.0',
                    id: 'dontcare',
                    method: 'gas_price',
                    params: [address1Info.blockHash],
                },
            })
                .resolves(near_1.NearResponses.getGasPriceResponse);
        });
        afterEach(function () {
            sandBox.restore();
        });
        it('should recover a txn for non-bitgo recoveries at address 1 but search from address 0', async function () {
            const res = await basecoin.recover({
                userKey: near_1.keys.userKey,
                backupKey: near_1.keys.backupKey,
                bitgoKey: near_1.keys.bitgoKey,
                recoveryDestination: destAddr,
                walletPassphrase: 'Ghghjkg!455544llll',
            });
            res.should.not.be.empty();
            res.should.hasOwnProperty('serializedTx');
            res.should.hasOwnProperty('scanIndex');
            res.scanIndex.should.equal(1);
            sandBox.assert.callCount(basecoin.getDataFromNode, 5);
            const tx = new src_1.Transaction(coin);
            tx.fromRawTransaction(res.serializedTx);
            const txJson = tx.toJson();
            should.equal(txJson.nonce, near_1.nonce);
            should.equal(txJson.signerId, address1Info.accountId);
            should.equal(txJson.publicKey, 'ed25519:' + address1Info.bs58EncodedPublicKey);
        });
        it('should recover a txn for non-bitgo recoveries at address 1 but search from address 1', async function () {
            const res = await basecoin.recover({
                userKey: near_1.keys.userKey,
                backupKey: near_1.keys.backupKey,
                bitgoKey: near_1.keys.bitgoKey,
                recoveryDestination: destAddr,
                walletPassphrase: 'Ghghjkg!455544llll',
                startingScanIndex: 1,
            });
            res.should.not.be.empty();
            res.should.hasOwnProperty('serializedTx');
            res.should.hasOwnProperty('scanIndex');
            res.scanIndex.should.equal(1);
            sandBox.assert.callCount(basecoin.getDataFromNode, 4);
            const tx = new src_1.Transaction(coin);
            tx.fromRawTransaction(res.serializedTx);
            const txJson = tx.toJson();
            should.equal(txJson.nonce, near_1.nonce);
            should.equal(txJson.signerId, address1Info.accountId);
            should.equal(txJson.publicKey, 'ed25519:' + address1Info.bs58EncodedPublicKey);
        });
    });
    describe('Recover Transaction Failures:', () => {
        const sandBox = sinon.createSandbox();
        const destAddr = 'abhay-near.testnet';
        const numIteration = 10;
        beforeEach(function () {
            const callBack = sandBox.stub(src_1.Near.prototype, 'getDataFromNode');
            callBack
                .withArgs(sinon.match.hasNested('payload.method', 'EXPERIMENTAL_protocol_config'))
                .resolves(near_1.NearResponses.getProtocolConfigResp);
            callBack.resolves(near_1.NearResponses.getZeroBalanceAccountResponse);
        });
        afterEach(function () {
            sandBox.restore();
        });
        it('should fail to recover due to not finding an address with funds', async function () {
            await basecoin
                .recover({
                userKey: near_1.keys.userKey,
                backupKey: near_1.keys.backupKey,
                bitgoKey: near_1.keys.bitgoKey,
                walletPassphrase: 'Ghghjkg!455544llll',
                recoveryDestination: destAddr,
                scan: numIteration,
            })
                .should.rejectedWith('Did not find an address with funds to recover');
            // getDataFromNode should be called numIteration + 1 times since we initially
            // call getProtocolConfig
            sandBox.assert.callCount(basecoin.getDataFromNode, numIteration + 1);
        });
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmVhci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvdW5pdC9uZWFyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsaUNBQWtDO0FBQ2xDLDhDQUEwRDtBQUMxRCw0Q0FBMEM7QUFDMUMsbUNBQXFDO0FBQ3JDLDJDQVUwQjtBQUMxQiwwQ0FBNEI7QUFDNUIsNkNBQStCO0FBQy9CLG1DQUE4RDtBQUM5RCwyREFBd0Q7QUFDeEQsNENBQXVDO0FBRXZDLFFBQVEsQ0FBQyxPQUFPLEVBQUU7SUFDaEIsSUFBSSxLQUFtQixDQUFDO0lBQ3hCLElBQUksUUFBUSxDQUFDO0lBQ2IsSUFBSSxhQUFhLENBQUM7SUFDbEIsSUFBSSxXQUFXLENBQUM7SUFDaEIsTUFBTSxPQUFPLEdBQUcsSUFBQSxxQ0FBaUIsRUFBQyxPQUFPLENBQUMsQ0FBQztJQUUzQyxNQUFNLFVBQVUsR0FBRztRQUNqQixLQUFLLEVBQUUsWUFBSyxDQUFDLFFBQVEsQ0FBQyxRQUFRO1FBQzlCLE1BQU0sRUFBRSxFQUFFO0tBQ1gsQ0FBQztJQUVGLE1BQU0sUUFBUSxHQUFHO1FBQ2YsVUFBVSxFQUFFO1lBQ1Y7Z0JBQ0UsT0FBTyxFQUFFLGtFQUFrRTtnQkFDM0UsTUFBTSxFQUFFLDJCQUEyQjthQUNwQztTQUNGO0tBQ0YsQ0FBQztJQUVGLE1BQU0sQ0FBQztRQUNMLEtBQUssR0FBRyxvQkFBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBUSxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDdEQsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDM0IsS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsVUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ2pELEtBQUssQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLFdBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNqRCxRQUFR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QUFJLENBQUMsT0FBTztnQkFDckIsU0FBUyxFQUFFLFdBQUksQ0FBQyxTQUFTO2dCQUN6QixRQUFRLEVBQUUsV0FBSSxDQUFDLFFBQVE7Z0JBQ3ZCLGdCQUFnQixFQUFFLG9CQUFvQjtnQkFDdEMsbUJBQW1CLEVBQUUsUUFBUTtnQkFDN0IsSUFBSSxFQUFFLFlBQVk7YUFDbkIsQ0FBQztpQkFDRCxNQUFNLENBQUMsWUFBWSxDQUFDLCtDQUErQyxDQUFDLENBQUM7WUFDeEUsNkVBQTZFO1lBQzdFLHlCQUF5QjtZQUN6QixPQUFPLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsZUFBZSxFQUFFLFlBQVksR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN2RSxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgc2hvdWxkID0gcmVxdWlyZSgnc2hvdWxkJyk7XG5pbXBvcnQgeyBUZXN0Qml0R28sIFRlc3RCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby9zZGstdGVzdCc7XG5pbXBvcnQgeyBCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby9zZGstYXBpJztcbmltcG9ydCB7IHJhbmRvbUJ5dGVzIH0gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB7XG4gIHJhd1R4LFxuICBhY2NvdW50cyxcbiAgdmFsaWRhdG9yQ29udHJhY3RBZGRyZXNzLFxuICBibG9ja0hhc2gsXG4gIE5lYXJSZXNwb25zZXMsXG4gIGtleXMsXG4gIGFjY291bnRJbmZvLFxuICBub25jZSxcbiAgb3ZjUmVzcG9uc2UsXG59IGZyb20gJy4uL2ZpeHR1cmVzL25lYXInO1xuaW1wb3J0ICogYXMgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0ICogYXMgc2lub24gZnJvbSAnc2lub24nO1xuaW1wb3J0IHsgS2V5UGFpciwgTmVhciwgVE5lYXIsIFRyYW5zYWN0aW9uIH0gZnJvbSAnLi4vLi4vc3JjJztcbmltcG9ydCB7IGdldEJ1aWxkZXJGYWN0b3J5IH0gZnJvbSAnLi9nZXRCdWlsZGVyRmFjdG9yeSc7XG5pbXBvcnQgeyBjb2lucyB9IGZyb20gJ0BiaXRnby9zdGF0aWNzJztcblxuZGVzY3JpYmUoJ05FQVI6JywgZnVuY3Rpb24gKCkge1xuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IGJhc2Vjb2luO1xuICBsZXQgbmV3VHhQcmVidWlsZDtcbiAgbGV0IG5ld1R4UGFyYW1zO1xuICBjb25zdCBmYWN0b3J5ID0gZ2V0QnVpbGRlckZhY3RvcnkoJ3RuZWFyJyk7XG5cbiAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICB0eEhleDogcmF3VHgudHJhbnNmZXIudW5zaWduZWQsXG4gICAgdHhJbmZvOiB7fSxcbiAgfTtcblxuICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICByZWNpcGllbnRzOiBbXG4gICAgICB7XG4gICAgICAgIGFkZHJlc3M6ICc5ZjdiMDY3NWRiNTlkMTliNGJkOWM4YzcyZWFhYmJhNzVhOTg2M2QwMmIzMDExNWI4YjNjM2NhNWMyMGYwMjU0JyxcbiAgICAgICAgYW1vdW50OiAnMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCcsXG4gICAgICB9LFxuICAgIF0sXG4gIH07XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICBiaXRnby5zYWZlUmVnaXN0ZXIoJ3RuZWFyJywgTmVhci5jcmVhdGVJbnN0YW5jZSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCduZWFyJywgVE5lYXIuY3JlYXRlSW5zdGFuY2UpO1xuICAgIGJhc2Vjb2luID0gYml0Z28uY29pbigndG5lYXInKTtcbiAgICBuZXdUeFByZWJ1aWxkID0gKCkgPT4ge1xuICAgICAgcmV0dXJuIF8uY2xvbmVEZWVwKHR4UHJlYnVpbGQpO1xuICAgIH07XG4gICAgbmV3VHhQYXJhbXMgPSAoKSA9PiB7XG4gICAgICByZXR1cm4gXy5jbG9uZURlZXAodHhQYXJhbXMpO1xuICAgIH07XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dW4gdGhlIHJpZ2h0IGluZm8nLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgbmVhciA9IGJpdGdvLmNvaW4oJ25lYXInKTtcbiAgICBjb25zdCB0bmVhciA9IGJpdGdvLmNvaW4oJ3RuZWFyJyk7XG5cbiAgICBuZWFyLmdldENoYWluKCkuc2hvdWxkLmVxdWFsKCduZWFyJyk7XG4gICAgbmVhci5nZXRGYW1pbHkoKS5zaG91bGQuZXF1YWwoJ25lYXInKTtcbiAgICBuZWFyLmdldEZ1bGxOYW1lKCkuc2hvdWxkLmVxdWFsKCdOZWFyJyk7XG4gICAgbmVhci5nZXRCYXNlRmFjdG9yKCkuc2hvdWxkLmVxdWFsKDFlMjQpO1xuXG4gICAgdG5lYXIuZ2V0Q2hhaW4oKS5zaG91bGQuZXF1YWwoJ3RuZWFyJyk7XG4gICAgdG5lYXIuZ2V0RmFtaWx5KCkuc2hvdWxkLmVxdWFsKCduZWFyJyk7XG4gICAgdG5lYXIuZ2V0RnVsbE5hbWUoKS5zaG91bGQuZXF1YWwoJ1Rlc3RuZXQgTmVhcicpO1xuICAgIHRuZWFyLmdldEJhc2VGYWN0b3IoKS5zaG91bGQuZXF1YWwoMWUyNCk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdTaWduIE1lc3NhZ2UnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBiZSBwZXJmb3JtZWQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBrZXlQYWlyID0gbmV3IEtleVBhaXIoKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2VUb1NpZ24gPSBCdWZmZXIuZnJvbShyYW5kb21CeXRlcygzMikpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IGF3YWl0IGJhc2Vjb2luLnNpZ25NZXNzYWdlKGtleVBhaXIuZ2V0S2V5cygpLCBtZXNzYWdlVG9TaWduKTtcbiAgICAgIGtleVBhaXIudmVyaWZ5U2lnbmF0dXJlKG1lc3NhZ2VUb1NpZ24sIFVpbnQ4QXJyYXkuZnJvbShzaWduYXR1cmUpKS5zaG91bGQuZXF1YWxzKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHdpdGggbWlzc2luZyBwcml2YXRlIGtleScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGtleVBhaXIgPSBuZXcgS2V5UGFpcih7XG4gICAgICAgIHB1YjogJzc3ODgzMjdjNjk1ZGNhNGIzZTY0OWEwZGI0NWJjM2U3MDNhMmM2NzQyOGZjZTM2MGU2MTgwMGNjNDI0OGY0ZjcnLFxuICAgICAgfSkuZ2V0S2V5cygpO1xuICAgICAgY29uc3QgbWVzc2FnZVRvU2lnbiA9IEJ1ZmZlci5mcm9tKHJhbmRvbUJ5dGVzKDMyKSkudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgYXdhaXQgYmFzZWNvaW4uc2lnbk1lc3NhZ2Uoa2V5UGFpciwgbWVzc2FnZVRvU2lnbikuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnSW52YWxpZCBrZXkgcGFpciBvcHRpb25zJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdTaWduIHRyYW5zYWN0aW9uJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgc2lnbiB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZ25lZCA9IGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICB0eEhleDogcmF3VHgudHJhbnNmZXIudW5zaWduZWQsXG4gICAgICAgIH0sXG4gICAgICAgIHB1YnM6IFthY2NvdW50cy5hY2NvdW50MS5wdWJsaWNLZXldLFxuICAgICAgICBwcnY6IGFjY291bnRzLmFjY291bnQxLnNlY3JldEtleSxcbiAgICAgIH0pO1xuICAgICAgc2lnbmVkLnR4SGV4LnNob3VsZC5lcXVhbChyYXdUeC50cmFuc2Zlci5zaWduZWQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIHNpZ24gdHJhbnNhY3Rpb24gd2l0aCBhbiBpbnZhbGlkIGtleScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgICAgdHhIZXg6IHJhd1R4LnRyYW5zZmVyLnVuc2lnbmVkLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcHViczogW2FjY291bnRzLmFjY291bnQyLnB1YmxpY0tleV0sXG4gICAgICAgICAgcHJ2OiBhY2NvdW50cy5hY2NvdW50MS5zZWNyZXRLZXksXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBzaG91bGQuZXF1YWwoZS5tZXNzYWdlLCAnUHJpdmF0ZSBrZXkgY2Fubm90IHNpZ24gdGhlIHRyYW5zYWN0aW9uJyk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gYnVpbGQgdHJhbnNhY3Rpb24gd2l0aCBtaXNzaW5nIHBhcmFtcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgICAgdHhIZXg6IHJhd1R4LnRyYW5zZmVyLnVuc2lnbmVkLFxuICAgICAgICAgICAga2V5OiBhY2NvdW50cy5hY2NvdW50MS5wdWJsaWNLZXksXG4gICAgICAgICAgfSxcbiAgICAgICAgICBwcnY6IGFjY291bnRzLmFjY291bnQxLnNlY3JldEtleSxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHNob3VsZC5ub3RFcXVhbChlLCBudWxsKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0dlbmVyYXRlIHdhbGxldCBrZXkgcGFpcjogJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgZ2VuZXJhdGUga2V5IHBhaXInLCAoKSA9PiB7XG4gICAgICBjb25zdCBrcCA9IGJhc2Vjb2luLmdlbmVyYXRlS2V5UGFpcigpO1xuICAgICAgYmFzZWNvaW4uaXNWYWxpZFB1YihrcC5wdWIpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIGJhc2Vjb2luLmlzVmFsaWRQcnYoa3AucHJ2KS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGtleSBwYWlyIGZyb20gc2VlZCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHNlZWQgPSBCdWZmZXIuZnJvbSgnOWQ2MWIxOWRlZmZkNWE2MGJhODQ0YWY0OTJlYzJjYzQ0NDQ5YzU2OTdiMzI2OTE5NzAzYmFjMDMxY2FlN2Y2MCcsICdoZXgnKTtcbiAgICAgIGNvbnN0IGtwID0gYmFzZWNvaW4uZ2VuZXJhdGVLZXlQYWlyKHNlZWQpO1xuICAgICAgYmFzZWNvaW4uaXNWYWxpZFB1YihrcC5wdWIpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIGJhc2Vjb2luLmlzVmFsaWRQcnYoa3AucHJ2KS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdWZXJpZnkgdHJhbnNhY3Rpb246ICcsICgpID0+IHtcbiAgICBjb25zdCBhbW91bnQgPSAnMTAwMDAwMCc7XG4gICAgY29uc3QgZ2FzID0gJzEyNTAwMDAwMDAwMDAwMCc7XG5cbiAgICBpdCgnc2hvdWxkIHN1Y2NlZWQgdG8gdmVyaWZ5IHVuc2lnbmVkIHRyYW5zYWN0aW9uIGluIGJhc2U2NCBlbmNvZGluZycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG5ld1R4UGFyYW1zKCk7XG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcbiAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHZlcmlmaWNhdGlvbiB9KTtcbiAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHN1Y2NlZWQgdG8gdmVyaWZ5IHNpZ25lZCB0cmFuc2FjdGlvbiBpbiBiYXNlNjQgZW5jb2RpbmcnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICB0eEhleDogcmF3VHgudHJhbnNmZXIuc2lnbmVkLFxuICAgICAgICB0eEluZm86IHt9LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSBuZXdUeFBhcmFtcygpO1xuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHZlcmlmaWNhdGlvbiB9KTtcbiAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdmVyaWZ5IHRyYW5zYWN0aW9ucyB3aGVuIGhhdmUgZGlmZmVyZW50IHJlY2lwaWVudHMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0gbmV3VHhQcmVidWlsZCgpO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICc5ZjdiMDY3NWRiNTlkMTliNGJkOWM4YzcyZWFhYmJhNzVhOTg2M2QwMmIzMDExNWI4YjNjM2NhNWMyMGYwMjU0JyxcbiAgICAgICAgICAgIGFtb3VudDogJzEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogJzlmN2IwNjc1ZGI1OWQxOWI0YmQ5YzhjNzJlYWFiYmE3NWE5ODYzZDAyYjMwMTE1YjhiM2MzY2E1YzIwZjAyNTQnLFxuICAgICAgICAgICAgYW1vdW50OiAnMjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgdmVyaWZpY2F0aW9uIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdUeCBvdXRwdXRzIGRvZXMgbm90IG1hdGNoIHdpdGggZXhwZWN0ZWQgdHhQYXJhbXMgcmVjaXBpZW50cycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHZlcmlmeSB0cmFuc2FjdGlvbnMgd2hlbiB0b3RhbCBhbW91bnQgZG9lcyBub3QgbWF0Y2ggd2l0aCBleHBlY3RlZCB0b3RhbCBhbW91bnQgZmllbGQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBleHBsYWluZWRUeCA9IHtcbiAgICAgICAgaWQ6ICc1alRFUHVEY01DZUVncDFpeUViTkJLc25oWXo0RjRjMUVQRHRSbXhtM3dDdycsXG4gICAgICAgIGRpc3BsYXlPcmRlcjogWydvdXRwdXRBbW91bnQnLCAnY2hhbmdlQW1vdW50JywgJ291dHB1dHMnLCAnY2hhbmdlT3V0cHV0cycsICdmZWUnLCAndHlwZSddLFxuICAgICAgICBvdXRwdXRBbW91bnQ6ICc5MDAwMCcsXG4gICAgICAgIGNoYW5nZUFtb3VudDogJzAnLFxuICAgICAgICBjaGFuZ2VPdXRwdXRzOiBbXSxcbiAgICAgICAgb3V0cHV0czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICc5ZjdiMDY3NWRiNTlkMTliNGJkOWM4YzcyZWFhYmJhNzVhOTg2M2QwMmIzMDExNWI4YjNjM2NhNWMyMGYwMjU0JyxcbiAgICAgICAgICAgIGFtb3VudDogJzEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIGZlZToge1xuICAgICAgICAgIGZlZTogJycsXG4gICAgICAgIH0sXG4gICAgICAgIHR5cGU6IDAsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBzdHViID0gc2lub24uc3R1YihUcmFuc2FjdGlvbi5wcm90b3R5cGUsICdleHBsYWluVHJhbnNhY3Rpb24nKTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG5ld1R4UGFyYW1zKCk7XG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcbiAgICAgIHN0dWIucmV0dXJucyhleHBsYWluZWRUeCk7XG5cbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ1R4IHRvdGFsIGFtb3VudCBkb2VzIG5vdCBtYXRjaCB3aXRoIGV4cGVjdGVkIHRvdGFsIGFtb3VudCBmaWVsZCcpO1xuICAgICAgc3R1Yi5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHN1Y2NlZWQgdG8gdmVyaWZ5IHRyYW5zYWN0aW9uIGluIGhleCBlbmNvZGluZycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbmV3VHhQYXJhbXMoKTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgdmVyaWZpY2F0aW9uIH0pO1xuICAgICAgaXNUcmFuc2FjdGlvblZlcmlmaWVkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY29udmVydCBzZXJpYWxpemVkIGhleCBzdHJpbmcgdG8gYmFzZTY0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQYXJhbXMgPSBuZXdUeFBhcmFtcygpO1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IG5ld1R4UHJlYnVpbGQoKTtcbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuICAgICAgdHhQcmVidWlsZC50eEhleCA9IEJ1ZmZlci5mcm9tKHR4UHJlYnVpbGQudHhIZXgsICdiYXNlNjQnKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICBjb25zdCB2YWxpZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgdmVyaWZpY2F0aW9uIH0pO1xuICAgICAgdmFsaWRUcmFuc2FjdGlvbi5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZlcmlmeSB3aGVuIGlucHV0IGByZWNpcGllbnRzYCBpcyBhYnNlbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG5ld1R4UGFyYW1zKCk7XG4gICAgICB0eFBhcmFtcy5yZWNpcGllbnRzID0gdW5kZWZpbmVkO1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IG5ld1R4UHJlYnVpbGQoKTtcbiAgICAgIGNvbnN0IHZhbGlkVHJhbnNhY3Rpb24gPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkIH0pO1xuICAgICAgdmFsaWRUcmFuc2FjdGlvbi5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdmVyaWZ5IHdoZW4gdHhIZXggaXMgaW52YWxpZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbmV3VHhQYXJhbXMoKTtcbiAgICAgIHR4UGFyYW1zLnJlY2lwaWVudHMgPSB1bmRlZmluZWQ7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge307XG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCB9KVxuICAgICAgICAuc2hvdWxkLnJlamVjdGVkV2l0aCgnbWlzc2luZyByZXF1aXJlZCB0eCBwcmVidWlsZCBwcm9wZXJ0eSB0eEhleCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzdWNjZWVkIHRvIHZlcmlmeSB0cmFuc2FjdGlvbnMgd2hlbiByZWNpcGllbnRzIGhhcyBleHRyYSBkYXRhJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IG5ld1R4UHJlYnVpbGQoKTtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbmV3VHhQYXJhbXMoKTtcbiAgICAgIHR4UGFyYW1zLmRhdGEgPSAnZGF0YSc7XG5cbiAgICAgIGNvbnN0IHZhbGlkVHJhbnNhY3Rpb24gPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkIH0pO1xuICAgICAgdmFsaWRUcmFuc2FjdGlvbi5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZlcmlmeSBhY3RpdmF0ZSBzdGFraW5nIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRTdGFraW5nQWN0aXZhdGVCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXJcbiAgICAgICAgLmFtb3VudChhbW91bnQpXG4gICAgICAgIC5nYXMoZ2FzKVxuICAgICAgICAuc2VuZGVyKGFjY291bnRzLmFjY291bnQxLmFkZHJlc3MsIGFjY291bnRzLmFjY291bnQxLnB1YmxpY0tleSlcbiAgICAgICAgLnJlY2VpdmVySWQodmFsaWRhdG9yQ29udHJhY3RBZGRyZXNzKVxuICAgICAgICAucmVjZW50QmxvY2tIYXNoKGJsb2NrSGFzaC5ibG9jazEpXG4gICAgICAgIC5ub25jZSgxKTtcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBhY2NvdW50cy5hY2NvdW50MS5zZWNyZXRLZXkgfSk7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgdHhUb0Jyb2FkY2FzdEZvcm1hdCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICB0eEhleDogdHhUb0Jyb2FkY2FzdEZvcm1hdCxcbiAgICAgIH07XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICdsYXZlbmRlcmZpdmUucG9vbC5mODYzOTczLm0wJyxcbiAgICAgICAgICAgIGFtb3VudDogJzEwMDAwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgICAgY29uc3QgdmFsaWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQgfSk7XG4gICAgICB2YWxpZFRyYW5zYWN0aW9uLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IGRlYWN0aXZhdGUgc3Rha2luZyB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0U3Rha2luZ0RlYWN0aXZhdGVCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXJcbiAgICAgICAgLmFtb3VudChhbW91bnQpXG4gICAgICAgIC5nYXMoZ2FzKVxuICAgICAgICAuc2VuZGVyKGFjY291bnRzLmFjY291bnQxLmFkZHJlc3MsIGFjY291bnRzLmFjY291bnQxLnB1YmxpY0tleSlcbiAgICAgICAgLnJlY2VpdmVySWQodmFsaWRhdG9yQ29udHJhY3RBZGRyZXNzKVxuICAgICAgICAucmVjZW50QmxvY2tIYXNoKGJsb2NrSGFzaC5ibG9jazEpXG4gICAgICAgIC5ub25jZSgxKTtcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBhY2NvdW50cy5hY2NvdW50MS5zZWNyZXRLZXkgfSk7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgdHhUb0Jyb2FkY2FzdEZvcm1hdCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICB0eEhleDogdHhUb0Jyb2FkY2FzdEZvcm1hdCxcbiAgICAgIH07XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW10sXG4gICAgICB9O1xuICAgICAgY29uc3QgdmFsaWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQgfSk7XG4gICAgICB2YWxpZFRyYW5zYWN0aW9uLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IHdpdGhkcmF3IHN0YWtpbmcgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFN0YWtpbmdXaXRoZHJhd0J1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlclxuICAgICAgICAuYW1vdW50KGFtb3VudClcbiAgICAgICAgLmdhcyhnYXMpXG4gICAgICAgIC5zZW5kZXIoYWNjb3VudHMuYWNjb3VudDEuYWRkcmVzcywgYWNjb3VudHMuYWNjb3VudDEucHVibGljS2V5KVxuICAgICAgICAucmVjZWl2ZXJJZCh2YWxpZGF0b3JDb250cmFjdEFkZHJlc3MpXG4gICAgICAgIC5yZWNlbnRCbG9ja0hhc2goYmxvY2tIYXNoLmJsb2NrMSlcbiAgICAgICAgLm5vbmNlKDEpO1xuICAgICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IGFjY291bnRzLmFjY291bnQxLnNlY3JldEtleSB9KTtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCB0eFRvQnJvYWRjYXN0Rm9ybWF0ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHR4SGV4OiB0eFRvQnJvYWRjYXN0Rm9ybWF0LFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogJzYxYjE4YzZkYzAyZGRjYWJkZWFjNTZjYjRmMjFhOTcxY2M0MWNjOTc2NDBmNmY4NWIwNzM0ODAwMDhjNTNhMGQnLFxuICAgICAgICAgICAgYW1vdW50OiAnMTAwMDAwMCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgICBjb25zdCB2YWxpZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCB9KTtcbiAgICAgIHZhbGlkVHJhbnNhY3Rpb24uc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnRXhwbGFpbiBUcmFuc2FjdGlvbnM6JywgKCkgPT4ge1xuICAgIGNvbnN0IGFtb3VudCA9ICcxMDAwMDAwJztcbiAgICBjb25zdCBnYXMgPSAnMTI1MDAwMDAwMDAwMDAwJztcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhbiB1bnNpZ25lZCB0cmFuc2ZlciB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGxhaW5lZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHR4SGV4OiByYXdUeC50cmFuc2Zlci5zaWduZWQsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIGV4cGxhaW5lZFRyYW5zYWN0aW9uLnNob3VsZC5kZWVwRXF1YWwoe1xuICAgICAgICBkaXNwbGF5T3JkZXI6IFsnb3V0cHV0QW1vdW50JywgJ2NoYW5nZUFtb3VudCcsICdvdXRwdXRzJywgJ2NoYW5nZU91dHB1dHMnLCAnZmVlJywgJ3R5cGUnXSxcbiAgICAgICAgaWQ6ICc1alRFUHVEY01DZUVncDFpeUViTkJLc25oWXo0RjRjMUVQRHRSbXhtM3dDdycsXG4gICAgICAgIHR5cGU6IDAsXG4gICAgICAgIGNoYW5nZU91dHB1dHM6IFtdLFxuICAgICAgICBjaGFuZ2VBbW91bnQ6ICcwJyxcbiAgICAgICAgb3V0cHV0QW1vdW50OiAnMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCcsXG4gICAgICAgIG91dHB1dHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhZGRyZXNzOiAnOWY3YjA2NzVkYjU5ZDE5YjRiZDljOGM3MmVhYWJiYTc1YTk4NjNkMDJiMzAxMTViOGIzYzNjYTVjMjBmMDI1NCcsXG4gICAgICAgICAgICBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBmZWU6IHtcbiAgICAgICAgICBmZWU6ICcnLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGV4cGxhaW4gYSBzaWduZWQgdHJhbnNmZXIgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBleHBsYWluZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICB0eEhleDogcmF3VHgudHJhbnNmZXIuc2lnbmVkLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICBleHBsYWluZWRUcmFuc2FjdGlvbi5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgZGlzcGxheU9yZGVyOiBbJ291dHB1dEFtb3VudCcsICdjaGFuZ2VBbW91bnQnLCAnb3V0cHV0cycsICdjaGFuZ2VPdXRwdXRzJywgJ2ZlZScsICd0eXBlJ10sXG4gICAgICAgIGlkOiAnNWpURVB1RGNNQ2VFZ3AxaXlFYk5CS3NuaFl6NEY0YzFFUER0Um14bTN3Q3cnLFxuICAgICAgICB0eXBlOiAwLFxuICAgICAgICBjaGFuZ2VPdXRwdXRzOiBbXSxcbiAgICAgICAgY2hhbmdlQW1vdW50OiAnMCcsXG4gICAgICAgIG91dHB1dEFtb3VudDogJzEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAnLFxuICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogJzlmN2IwNjc1ZGI1OWQxOWI0YmQ5YzhjNzJlYWFiYmE3NWE5ODYzZDAyYjMwMTE1YjhiM2MzY2E1YzIwZjAyNTQnLFxuICAgICAgICAgICAgYW1vdW50OiAnMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgZmVlOiB7XG4gICAgICAgICAgZmVlOiAnJyxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBleHBsYWluIGFjdGl2YXRlIHN0YWtpbmcgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFN0YWtpbmdBY3RpdmF0ZUJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlclxuICAgICAgICAuYW1vdW50KGFtb3VudClcbiAgICAgICAgLmdhcyhnYXMpXG4gICAgICAgIC5zZW5kZXIoYWNjb3VudHMuYWNjb3VudDEuYWRkcmVzcywgYWNjb3VudHMuYWNjb3VudDEucHVibGljS2V5KVxuICAgICAgICAucmVjZWl2ZXJJZCh2YWxpZGF0b3JDb250cmFjdEFkZHJlc3MpXG4gICAgICAgIC5yZWNlbnRCbG9ja0hhc2goYmxvY2tIYXNoLmJsb2NrMSlcbiAgICAgICAgLm5vbmNlKDEpO1xuICAgICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IGFjY291bnRzLmFjY291bnQxLnNlY3JldEtleSB9KTtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCB0eFRvQnJvYWRjYXN0Rm9ybWF0ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIGNvbnN0IGV4cGxhaW5lZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHR4SGV4OiB0eFRvQnJvYWRjYXN0Rm9ybWF0LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICBleHBsYWluZWRUcmFuc2FjdGlvbi5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgZGlzcGxheU9yZGVyOiBbJ291dHB1dEFtb3VudCcsICdjaGFuZ2VBbW91bnQnLCAnb3V0cHV0cycsICdjaGFuZ2VPdXRwdXRzJywgJ2ZlZScsICd0eXBlJ10sXG4gICAgICAgIGlkOiAnR3BpTExhR3MyRmsyYmQ3U1F2aGtKYVpqajc0VW5QUGRGN2NVYTlwdzE1amUnLFxuICAgICAgICB0eXBlOiAxMyxcbiAgICAgICAgY2hhbmdlT3V0cHV0czogW10sXG4gICAgICAgIGNoYW5nZUFtb3VudDogJzAnLFxuICAgICAgICBvdXRwdXRBbW91bnQ6ICcxMDAwMDAwJyxcbiAgICAgICAgb3V0cHV0czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICdsYXZlbmRlcmZpdmUucG9vbC5mODYzOTczLm0wJyxcbiAgICAgICAgICAgIGFtb3VudDogJzEwMDAwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIGZlZToge1xuICAgICAgICAgIGZlZTogJycsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBkZWFjdGl2YXRlIHN0YWtpbmcgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFN0YWtpbmdEZWFjdGl2YXRlQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyXG4gICAgICAgIC5hbW91bnQoYW1vdW50KVxuICAgICAgICAuZ2FzKGdhcylcbiAgICAgICAgLnNlbmRlcihhY2NvdW50cy5hY2NvdW50MS5hZGRyZXNzLCBhY2NvdW50cy5hY2NvdW50MS5wdWJsaWNLZXkpXG4gICAgICAgIC5yZWNlaXZlcklkKHZhbGlkYXRvckNvbnRyYWN0QWRkcmVzcylcbiAgICAgICAgLnJlY2VudEJsb2NrSGFzaChibG9ja0hhc2guYmxvY2sxKVxuICAgICAgICAubm9uY2UoMSk7XG4gICAgICB0eEJ1aWxkZXIuc2lnbih7IGtleTogYWNjb3VudHMuYWNjb3VudDEuc2VjcmV0S2V5IH0pO1xuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IHR4VG9Ccm9hZGNhc3RGb3JtYXQgPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgY29uc3QgZXhwbGFpbmVkVHJhbnNhY3Rpb24gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHR4VG9Ccm9hZGNhc3RGb3JtYXQsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIGV4cGxhaW5lZFRyYW5zYWN0aW9uLnNob3VsZC5kZWVwRXF1YWwoe1xuICAgICAgICBkaXNwbGF5T3JkZXI6IFsnb3V0cHV0QW1vdW50JywgJ2NoYW5nZUFtb3VudCcsICdvdXRwdXRzJywgJ2NoYW5nZU91dHB1dHMnLCAnZmVlJywgJ3R5cGUnXSxcbiAgICAgICAgaWQ6ICdDRHhQUlAzRGdITjhnWW1SRGFnazVUUnVYN2ZzQ1JZSGN1cW9OVUx5UVBVVycsXG4gICAgICAgIHR5cGU6IDE3LFxuICAgICAgICBjaGFuZ2VPdXRwdXRzOiBbXSxcbiAgICAgICAgY2hhbmdlQW1vdW50OiAnMCcsXG4gICAgICAgIG91dHB1dEFtb3VudDogJzAnLFxuICAgICAgICBvdXRwdXRzOiBbXSxcbiAgICAgICAgZmVlOiB7XG4gICAgICAgICAgZmVlOiAnJyxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBleHBsYWluIHdpdGhkcmF3IHN0YWtpbmcgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFN0YWtpbmdXaXRoZHJhd0J1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlclxuICAgICAgICAuYW1vdW50KGFtb3VudClcbiAgICAgICAgLmdhcyhnYXMpXG4gICAgICAgIC5zZW5kZXIoYWNjb3VudHMuYWNjb3VudDEuYWRkcmVzcywgYWNjb3VudHMuYWNjb3VudDEucHVibGljS2V5KVxuICAgICAgICAucmVjZWl2ZXJJZCh2YWxpZGF0b3JDb250cmFjdEFkZHJlc3MpXG4gICAgICAgIC5yZWNlbnRCbG9ja0hhc2goYmxvY2tIYXNoLmJsb2NrMSlcbiAgICAgICAgLm5vbmNlKDEpO1xuICAgICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IGFjY291bnRzLmFjY291bnQxLnNlY3JldEtleSB9KTtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCB0eFRvQnJvYWRjYXN0Rm9ybWF0ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIGNvbnN0IGV4cGxhaW5lZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHR4SGV4OiB0eFRvQnJvYWRjYXN0Rm9ybWF0LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICBleHBsYWluZWRUcmFuc2FjdGlvbi5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgZGlzcGxheU9yZGVyOiBbJ291dHB1dEFtb3VudCcsICdjaGFuZ2VBbW91bnQnLCAnb3V0cHV0cycsICdjaGFuZ2VPdXRwdXRzJywgJ2ZlZScsICd0eXBlJ10sXG4gICAgICAgIGlkOiAnNTJaWDhNVXdtWWM2V1E2N3JpVUJwbW50a2NTeHhUNWFLa0pZdDVDdENadWInLFxuICAgICAgICB0eXBlOiAxNSxcbiAgICAgICAgY2hhbmdlT3V0cHV0czogW10sXG4gICAgICAgIGNoYW5nZUFtb3VudDogJzAnLFxuICAgICAgICBvdXRwdXRBbW91bnQ6ICcxMDAwMDAwJyxcbiAgICAgICAgb3V0cHV0czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICc2MWIxOGM2ZGMwMmRkY2FiZGVhYzU2Y2I0ZjIxYTk3MWNjNDFjYzk3NjQwZjZmODViMDczNDgwMDA4YzUzYTBkJyxcbiAgICAgICAgICAgIGFtb3VudDogJzEwMDAwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIGZlZToge1xuICAgICAgICAgIGZlZTogJycsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBleHBsYWluIHRyYW5zYWN0aW9uIHdpdGggbWlzc2luZyBwYXJhbXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UHJlYnVpbGQ6IHt9LFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHNob3VsZC5lcXVhbChlcnJvci5tZXNzYWdlLCAnSW52YWxpZCB0cmFuc2FjdGlvbicpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIGV4cGxhaW4gdHJhbnNhY3Rpb24gd2l0aCB3cm9uZyBwYXJhbXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICAgIHR4SGV4OiAnaW52YWxpZFR4SGV4JyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHNob3VsZC5lcXVhbChlcnJvci5tZXNzYWdlLCAnSW52YWxpZCB0cmFuc2FjdGlvbicpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUGFyc2UgVHJhbnNhY3Rpb25zOicsICgpID0+IHtcbiAgICBjb25zdCBURU5fTUlMTElPTl9ORUFSID0gJzEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJztcbiAgICBjb25zdCBPTkVfTUlMTElPTl9ORUFSID0gJzEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAnO1xuXG4gICAgY29uc3QgYW1vdW50ID0gVEVOX01JTExJT05fTkVBUjtcbiAgICBjb25zdCBnYXMgPSAnMTI1MDAwMDAwMDAwMDAwJztcblxuICAgIGNvbnN0IHJlc3BvbnNlMSA9IHtcbiAgICAgIGFkZHJlc3M6ICc5ZjdiMDY3NWRiNTlkMTliNGJkOWM4YzcyZWFhYmJhNzVhOTg2M2QwMmIzMDExNWI4YjNjM2NhNWMyMGYwMjU0JyxcbiAgICAgIGFtb3VudDogT05FX01JTExJT05fTkVBUixcbiAgICB9O1xuXG4gICAgY29uc3QgcmVzcG9uc2UyID0ge1xuICAgICAgYWRkcmVzczogJ2xhdmVuZGVyZml2ZS5wb29sLmY4NjM5NzMubTAnLFxuICAgICAgYW1vdW50OiBURU5fTUlMTElPTl9ORUFSLFxuICAgIH07XG5cbiAgICBjb25zdCByZXNwb25zZTMgPSB7XG4gICAgICBhZGRyZXNzOiAnNjFiMThjNmRjMDJkZGNhYmRlYWM1NmNiNGYyMWE5NzFjYzQxY2M5NzY0MGY2Zjg1YjA3MzQ4MDAwOGM1M2EwZCcsXG4gICAgICBhbW91bnQ6IFRFTl9NSUxMSU9OX05FQVIsXG4gICAgfTtcblxuICAgIGl0KCdzaG91bGQgcGFyc2UgYW4gdW5zaWduZWQgdHJhbnNmZXIgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJzZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLnBhcnNlVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHJhd1R4LnRyYW5zZmVyLnVuc2lnbmVkLFxuICAgICAgICB9LFxuICAgICAgICBmZWVJbmZvOiB7XG4gICAgICAgICAgZmVlOiAnNTAwMCcsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgcGFyc2VkVHJhbnNhY3Rpb24uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGlucHV0czogW3Jlc3BvbnNlMV0sXG4gICAgICAgIG91dHB1dHM6IFtyZXNwb25zZTFdLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHBhcnNlIGEgc2lnbmVkIHRyYW5zZmVyIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcGFyc2VkVHJhbnNhY3Rpb24gPSBhd2FpdCBiYXNlY29pbi5wYXJzZVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHR4SGV4OiByYXdUeC50cmFuc2Zlci5zaWduZWQsXG4gICAgICAgIH0sXG4gICAgICAgIGZlZUluZm86IHtcbiAgICAgICAgICBmZWU6ICcnLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIHBhcnNlZFRyYW5zYWN0aW9uLnNob3VsZC5kZWVwRXF1YWwoe1xuICAgICAgICBpbnB1dHM6IFtyZXNwb25zZTFdLFxuICAgICAgICBvdXRwdXRzOiBbcmVzcG9uc2UxXSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHBhcnNlIGEgc2lnbmVkIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdoZW4gZXhwbGFpblRyYW5zYWN0aW9uIHJlc3BvbnNlIGlzIHVuZGVmaW5lZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHN0dWIgPSBzaW5vbi5zdHViKE5lYXIucHJvdG90eXBlLCAnZXhwbGFpblRyYW5zYWN0aW9uJyk7XG4gICAgICBzdHViLnJlc29sdmVzKHVuZGVmaW5lZCk7XG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAucGFyc2VUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgICAgdHhIZXg6IHJhd1R4LnRyYW5zZmVyLnNpZ25lZCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGZlZUluZm86IHtcbiAgICAgICAgICAgIGZlZTogJycsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0ludmFsaWQgdHJhbnNhY3Rpb24nKTtcbiAgICAgIHN0dWIucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwYXJzZSBhY3RpdmF0ZSBzdGFraW5nIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRTdGFraW5nQWN0aXZhdGVCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXJcbiAgICAgICAgLmFtb3VudChhbW91bnQpXG4gICAgICAgIC5nYXMoZ2FzKVxuICAgICAgICAuc2VuZGVyKGFjY291bnRzLmFjY291bnQxLmFkZHJlc3MsIGFjY291bnRzLmFjY291bnQxLnB1YmxpY0tleSlcbiAgICAgICAgLnJlY2VpdmVySWQodmFsaWRhdG9yQ29udHJhY3RBZGRyZXNzKVxuICAgICAgICAucmVjZW50QmxvY2tIYXNoKGJsb2NrSGFzaC5ibG9jazEpXG4gICAgICAgIC5ub25jZSgxKTtcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBhY2NvdW50cy5hY2NvdW50MS5zZWNyZXRLZXkgfSk7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgdHhUb0Jyb2FkY2FzdEZvcm1hdCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBjb25zdCBwYXJzZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLnBhcnNlVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHR4VG9Ccm9hZGNhc3RGb3JtYXQsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgcGFyc2VkVHJhbnNhY3Rpb24uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGlucHV0czogW3Jlc3BvbnNlMl0sXG4gICAgICAgIG91dHB1dHM6IFtyZXNwb25zZTJdLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHBhcnNlIGRlYWN0aXZhdGUgc3Rha2luZyB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0U3Rha2luZ0RlYWN0aXZhdGVCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXJcbiAgICAgICAgLmFtb3VudChhbW91bnQpXG4gICAgICAgIC5nYXMoZ2FzKVxuICAgICAgICAuc2VuZGVyKGFjY291bnRzLmFjY291bnQxLmFkZHJlc3MsIGFjY291bnRzLmFjY291bnQxLnB1YmxpY0tleSlcbiAgICAgICAgLnJlY2VpdmVySWQodmFsaWRhdG9yQ29udHJhY3RBZGRyZXNzKVxuICAgICAgICAucmVjZW50QmxvY2tIYXNoKGJsb2NrSGFzaC5ibG9jazEpXG4gICAgICAgIC5ub25jZSgxKTtcbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBhY2NvdW50cy5hY2NvdW50MS5zZWNyZXRLZXkgfSk7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgdHhUb0Jyb2FkY2FzdEZvcm1hdCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBjb25zdCBwYXJzZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLnBhcnNlVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHR4VG9Ccm9hZGNhc3RGb3JtYXQsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgcGFyc2VkVHJhbnNhY3Rpb24uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGlucHV0czogW10sXG4gICAgICAgIG91dHB1dHM6IFtdLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHBhcnNlIHdpdGhkcmF3IHN0YWtpbmcgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFN0YWtpbmdXaXRoZHJhd0J1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlclxuICAgICAgICAuYW1vdW50KGFtb3VudClcbiAgICAgICAgLmdhcyhnYXMpXG4gICAgICAgIC5zZW5kZXIoYWNjb3VudHMuYWNjb3VudDEuYWRkcmVzcywgYWNjb3VudHMuYWNjb3VudDEucHVibGljS2V5KVxuICAgICAgICAucmVjZWl2ZXJJZCh2YWxpZGF0b3JDb250cmFjdEFkZHJlc3MpXG4gICAgICAgIC5yZWNlbnRCbG9ja0hhc2goYmxvY2tIYXNoLmJsb2NrMSlcbiAgICAgICAgLm5vbmNlKDEpO1xuICAgICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IGFjY291bnRzLmFjY291bnQxLnNlY3JldEtleSB9KTtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCB0eFRvQnJvYWRjYXN0Rm9ybWF0ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgY29uc3QgcGFyc2VkVHJhbnNhY3Rpb24gPSBhd2FpdCBiYXNlY29pbi5wYXJzZVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHR4SGV4OiB0eFRvQnJvYWRjYXN0Rm9ybWF0LFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIHBhcnNlZFRyYW5zYWN0aW9uLnNob3VsZC5kZWVwRXF1YWwoe1xuICAgICAgICBpbnB1dHM6IFtyZXNwb25zZTNdLFxuICAgICAgICBvdXRwdXRzOiBbcmVzcG9uc2UzXSxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUmVjb3ZlciBUcmFuc2FjdGlvbnM6JywgKCkgPT4ge1xuICAgIGNvbnN0IHNhbmRCb3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG4gICAgY29uc3QgY29pbiA9IGNvaW5zLmdldCgndG5lYXInKTtcbiAgICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICAgIGNvbnN0IGNhbGxCYWNrID0gc2FuZEJveC5zdHViKE5lYXIucHJvdG90eXBlLCAnZ2V0RGF0YUZyb21Ob2RlJyBhcyBrZXlvZiBOZWFyKTtcbiAgICAgIGNhbGxCYWNrXG4gICAgICAgIC53aXRoQXJncyh7XG4gICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAganNvbnJwYzogJzIuMCcsXG4gICAgICAgICAgICBpZDogJ2RvbnRjYXJlJyxcbiAgICAgICAgICAgIG1ldGhvZDogJ3F1ZXJ5JyxcbiAgICAgICAgICAgIHBhcmFtczoge1xuICAgICAgICAgICAgICByZXF1ZXN0X3R5cGU6ICd2aWV3X2FjY2Vzc19rZXknLFxuICAgICAgICAgICAgICBmaW5hbGl0eTogJ2ZpbmFsJyxcbiAgICAgICAgICAgICAgYWNjb3VudF9pZDogYWNjb3VudEluZm8uYWNjb3VudElkLFxuICAgICAgICAgICAgICBwdWJsaWNfa2V5OiBhY2NvdW50SW5mby5iczU4RW5jb2RlZFB1YmxpY0tleSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICAgLnJlc29sdmVzKE5lYXJSZXNwb25zZXMuZ2V0QWNjZXNzS2V5UmVzcG9uc2UpO1xuICAgICAgY2FsbEJhY2tcbiAgICAgICAgLndpdGhBcmdzKHtcbiAgICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgICBqc29ucnBjOiAnMi4wJyxcbiAgICAgICAgICAgIGlkOiAnZG9udGNhcmUnLFxuICAgICAgICAgICAgbWV0aG9kOiAncXVlcnknLFxuICAgICAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgICAgIHJlcXVlc3RfdHlwZTogJ3ZpZXdfYWNjb3VudCcsXG4gICAgICAgICAgICAgIGZpbmFsaXR5OiAnZmluYWwnLFxuICAgICAgICAgICAgICBhY2NvdW50X2lkOiBhY2NvdW50SW5mby5hY2NvdW50SWQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXNvbHZlcyhOZWFyUmVzcG9uc2VzLmdldEFjY291bnRSZXNwb25zZSk7XG4gICAgICBjYWxsQmFjay53aXRoQXJncygpLnJlc29sdmVzKE5lYXJSZXNwb25zZXMuZ2V0UHJvdG9jb2xDb25maWdSZXNwKTtcbiAgICAgIGNhbGxCYWNrXG4gICAgICAgIC53aXRoQXJncyh7XG4gICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAganNvbnJwYzogJzIuMCcsXG4gICAgICAgICAgICBpZDogJ2RvbnRjYXJlJyxcbiAgICAgICAgICAgIG1ldGhvZDogJ2dhc19wcmljZScsXG4gICAgICAgICAgICBwYXJhbXM6IFthY2NvdW50SW5mby5ibG9ja0hhc2hdLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXNvbHZlcyhOZWFyUmVzcG9uc2VzLmdldEdhc1ByaWNlUmVzcG9uc2UpO1xuICAgIH0pO1xuXG4gICAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICAgIHNhbmRCb3gucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWNvdmVyIGEgdHhuIGZvciBub24tYml0Z28gcmVjb3ZlcmllcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICB1c2VyS2V5OiBrZXlzLnVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleToga2V5cy5iYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiBrZXlzLmJpdGdvS2V5LFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiAnYWJoYXktbmVhci50ZXN0bmV0JyxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ0doZ2hqa2chNDU1NTQ0bGxsbCcsXG4gICAgICB9KTtcbiAgICAgIHJlcy5zaG91bGQubm90LmJlLmVtcHR5KCk7XG4gICAgICByZXMuc2hvdWxkLmhhc093blByb3BlcnR5KCdzZXJpYWxpemVkVHgnKTtcblxuICAgICAgY29uc3QgTm9uQml0R29UeG5EZXNlcmlhbGl6ZSA9IG5ldyBUcmFuc2FjdGlvbihjb2luKTtcbiAgICAgIE5vbkJpdEdvVHhuRGVzZXJpYWxpemUuZnJvbVJhd1RyYW5zYWN0aW9uKHJlcy5zZXJpYWxpemVkVHgpO1xuICAgICAgY29uc3QgTm9uQml0R29UeG5Kc29uID0gTm9uQml0R29UeG5EZXNlcmlhbGl6ZS50b0pzb24oKTtcblxuICAgICAgc2hvdWxkLmVxdWFsKE5vbkJpdEdvVHhuSnNvbi5ub25jZSwgbm9uY2UpO1xuICAgICAgc2hvdWxkLmVxdWFsKE5vbkJpdEdvVHhuSnNvbi5zaWduZXJJZCwgYWNjb3VudEluZm8uYWNjb3VudElkKTtcbiAgICAgIHNob3VsZC5lcXVhbChOb25CaXRHb1R4bkpzb24ucHVibGljS2V5LCAnZWQyNTUxOTonICsgYWNjb3VudEluZm8uYnM1OEVuY29kZWRQdWJsaWNLZXkpO1xuICAgICAgc2FuZEJveC5hc3NlcnQuY2FsbENvdW50KGJhc2Vjb2luLmdldERhdGFGcm9tTm9kZSwgNCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgYSB0eG4gZm9yIHVuc2lnbmVkIHN3ZWVwIHJlY292ZXJpZXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgYml0Z29LZXk6IGtleXMuYml0Z29LZXksXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246ICdhYmhheS1uZWFyLnRlc3RuZXQnLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIEFzc2VydGlvbnMgZm9yIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIHJlc3VsdFxuICAgICAgc2hvdWxkLmV4aXN0KHJlcyk7XG4gICAgICByZXMuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4UmVxdWVzdHMnKS53aGljaC5pcy5hbi5BcnJheSgpO1xuICAgICAgcmVzLnR4UmVxdWVzdHNbMF0uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3RyYW5zYWN0aW9ucycpLndoaWNoLmlzLmFuLkFycmF5KCk7XG4gICAgICByZXMudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3Vuc2lnbmVkVHgnKTtcblxuICAgICAgLy8gQXNzZXJ0aW9ucyBmb3IgdGhlIHVuc2lnbmVkIHRyYW5zYWN0aW9uXG4gICAgICBjb25zdCB1bnNpZ25lZFR4ID0gcmVzLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHg7XG4gICAgICB1bnNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdzZXJpYWxpemVkVHgnKS53aGljaC5pcy5hLlN0cmluZygpO1xuICAgICAgdW5zaWduZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc2NhbkluZGV4JywgMCk7XG4gICAgICB1bnNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb2luJywgJ3RuZWFyJyk7XG4gICAgICB1bnNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KFxuICAgICAgICAnc2lnbmFibGVIZXgnLFxuICAgICAgICAnYzI3ZDY4NGI2ZjA5YzRiNjAzZDliZjhhMDhiYWVkZjEyYjhiYjk1MWYzMTRhY2Q3NDdiMTZiYjc1Y2ZiZjY4NydcbiAgICAgICk7XG4gICAgICB1bnNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdkZXJpdmF0aW9uUGF0aCcsICdtLzAnKTtcblxuICAgICAgLy8gQXNzZXJ0aW9ucyBmb3IgcGFyc2VkIHRyYW5zYWN0aW9uXG4gICAgICBjb25zdCBwYXJzZWRUeCA9IHVuc2lnbmVkVHgucGFyc2VkVHg7XG4gICAgICBwYXJzZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaW5wdXRzJykud2hpY2guaXMuYW4uQXJyYXkoKTtcbiAgICAgIHBhcnNlZFR4LmlucHV0c1swXS5zaG91bGQuaGF2ZS5wcm9wZXJ0eShcbiAgICAgICAgJ2FkZHJlc3MnLFxuICAgICAgICAnZjI1NjE5NmRhZTYxN2FhMzQ4MTQ5YzFlNjFlOTk3MjcyNDkyNjY4ZDUxNzUwNmQ3YTZlMjM5MmUwNmVhNTMyYydcbiAgICAgICk7XG4gICAgICBwYXJzZWRUeC5pbnB1dHNbMF0uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3ZhbHVlU3RyaW5nJywgJzEuOTc4ODU1MDYwOTQ4NjYyNjk2NTAwMDAwMDFlKzI2Jyk7XG4gICAgICBwYXJzZWRUeC5pbnB1dHNbMF0uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3ZhbHVlJywgMS45Nzg4NTUwNjA5NDg2NjI3ZTI2KTtcblxuICAgICAgcGFyc2VkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ291dHB1dHMnKS53aGljaC5pcy5hbi5BcnJheSgpO1xuICAgICAgcGFyc2VkVHgub3V0cHV0c1swXS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYWRkcmVzcycsICdhYmhheS1uZWFyLnRlc3RuZXQnKTtcbiAgICAgIHBhcnNlZFR4Lm91dHB1dHNbMF0uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3ZhbHVlU3RyaW5nJywgJzEuOTc4ODU1MDYwOTQ4NjYyNjk2NTAwMDAwMDFlKzI2Jyk7XG4gICAgICBwYXJzZWRUeC5vdXRwdXRzWzBdLnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb2luTmFtZScsICd0bmVhcicpO1xuXG4gICAgICBwYXJzZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3BlbmRBbW91bnQnLCAnMS45Nzg4NTUwNjA5NDg2NjI2OTY1MDAwMDAwMWUrMjYnKTtcbiAgICAgIHBhcnNlZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eXBlJywgJycpO1xuXG4gICAgICAvLyBBc3NlcnRpb25zIGZvciBmZWUgaW5mb1xuICAgICAgdW5zaWduZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZmVlSW5mbycpO1xuICAgICAgdW5zaWduZWRUeC5mZWVJbmZvLnNob3VsZC5oYXZlLnByb3BlcnR5KCdmZWUnLCA2ODYyODYzNzk2ODc1MDAwMDAwMCk7XG4gICAgICB1bnNpZ25lZFR4LmZlZUluZm8uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2ZlZVN0cmluZycsICc2ODYyODYzNzk2ODc1MDAwMDAwMCcpO1xuXG4gICAgICAvLyBBc3NlcnRpb25zIGZvciBjb2luLXNwZWNpZmljIGRhdGFcbiAgICAgIHVuc2lnbmVkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ2NvaW5TcGVjaWZpYycpO1xuICAgICAgdW5zaWduZWRUeC5jb2luU3BlY2lmaWMuc2hvdWxkLmhhdmUucHJvcGVydHkoXG4gICAgICAgICdjb21tb25LZXljaGFpbicsXG4gICAgICAgICc4Njk5ZDJlMDVkNjBhM2Y3YWI3MzNhNzRjY2Y3MDdmMzQwNzQ5NGI2MGY0MjUzNjE2MTg3ZjUyNjJlMjA3Mzc1MTlhMTc2M2RlMGJjYzRkMTY1YTdmYTBlNGRkZTY3YTE0MjZlYzRjYzlmY2QwODIwZDc0OWU2NTg5ZGNmYTA4ZSdcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRha2UgT1ZDIG91dHB1dCBhbmQgZ2VuZXJhdGUgYSBzaWduZWQgc3dlZXAgdHJhbnNhY3Rpb24gZm9yIE5FQVInLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJhbXMgPSBvdmNSZXNwb25zZTsgLy8gTkVBUi1zcGVjaWZpYyByZXNwb25zZSBmaXh0dXJlXG4gICAgICBjb25zdCByZWNvdmVyeVR4biA9IGF3YWl0IGJhc2Vjb2luLmNyZWF0ZUJyb2FkY2FzdGFibGVTd2VlcFRyYW5zYWN0aW9uKHBhcmFtcyk7XG5cbiAgICAgIC8vIFZhbGlkYXRlIHRoZSBzZXJpYWxpemVkIHRyYW5zYWN0aW9uXG4gICAgICByZWNvdmVyeVR4bi50cmFuc2FjdGlvbnNbMF0uc2VyaWFsaXplZFR4LnNob3VsZC5lcXVhbChcbiAgICAgICAgJ1FBQUFBR0l6T0ROallXTTJaak5qWkRZME9UVmlaRFpoWWpnM056TXdNR0U0TnpsaU4yUmlZelJoTVRaaFlqQmxaakU1Tnpsa1pUWm1Oek5rWWpBeU5EbG1ZV0VBczRQS3h2UE5aSlc5YXJoM01BcUhtMzI4U2hhckR2R1huZWIzUGJBa242b0J1WlVqNmEwQUFFQUFBQUJsWVdSaU16SXdPR1ppT1dVNU1XWTJNR1EzTm1Vell6VXhOekV6WkRBMVkySTBZVFU1TkRGbE5XWXpOVFZsTVdabU9UaGxNVFF3WVRjeE1qTmxPRFJsMmhiSnRDNHJ3THlXQWJNelRnVGNSbXI1eHBXbHJYT1hienhNV2NQN3d3Y0JBQUFBQTlBMW9WZnZwejNvNGhjQUFBQUFBQUFBdkFJV09qMmMxUWhxYldjQ2xaOGRXN0tRY2ZHOWdZRmtpbWJSRHlJOHQ4TDRUVWlVeVJYTVl2NVU4amFFc05GV3RlQmNVR29sRmNMUVNiYkQ1TUNwRHc9PSdcbiAgICAgICk7XG5cbiAgICAgIC8vIFZhbGlkYXRlIHRoZSBzY2FuIGluZGV4XG4gICAgICByZWNvdmVyeVR4bi50cmFuc2FjdGlvbnNbMF0uc2NhbkluZGV4LnNob3VsZC5lcXVhbCgwKTtcbiAgICAgIHJlY292ZXJ5VHhuLmxhc3RTY2FuSW5kZXguc2hvdWxkLmVxdWFsKDApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUmVjb3ZlciBUcmFuc2FjdGlvbnMgZm9yIHdhbGxldCB3aXRoIG11bHRpcGxlIGFkZHJlc3NlczonLCAoKSA9PiB7XG4gICAgY29uc3QgZGVzdEFkZHIgPSAnYWJoYXktbmVhci50ZXN0bmV0JztcbiAgICBjb25zdCBzYW5kQm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuICAgIGNvbnN0IGNvaW4gPSBjb2lucy5nZXQoJ3RuZWFyJyk7XG4gICAgY29uc3QgYWRkcmVzczFJbmZvID0ge1xuICAgICAgYWNjb3VudElkOiAnZjY4NDJiZjRhOGU5ODA3MDRmYmQ5ZmI3OTliZmJlMGExMTZmZDVkOGQwNmY2Nzc0ZTc5MmM2OGM5MDdkOWIyMCcsXG4gICAgICBiczU4RW5jb2RlZFB1YmxpY0tleTogJ0hiSkJxeWFnQnF0U05VUjc0ZkxNUVNqUThIeVFWczY2ZnlNeVNQaFpMWHo3JyxcbiAgICAgIGJsb2NrSGFzaDogJzg0NE45YVdlZmQ0VHZKd2RpQmdYRFZQejRXOXo0MzZrb2hUaVhucDV5NGZxJyxcbiAgICB9O1xuXG4gICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjYWxsQmFjayA9IHNhbmRCb3guc3R1YihOZWFyLnByb3RvdHlwZSwgJ2dldERhdGFGcm9tTm9kZScgYXMga2V5b2YgTmVhcik7XG4gICAgICBjYWxsQmFja1xuICAgICAgICAud2l0aEFyZ3Moe1xuICAgICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICAgIGpzb25ycGM6ICcyLjAnLFxuICAgICAgICAgICAgaWQ6ICdkb250Y2FyZScsXG4gICAgICAgICAgICBtZXRob2Q6ICdxdWVyeScsXG4gICAgICAgICAgICBwYXJhbXM6IHtcbiAgICAgICAgICAgICAgcmVxdWVzdF90eXBlOiAndmlld19hY2Nlc3Nfa2V5JyxcbiAgICAgICAgICAgICAgZmluYWxpdHk6ICdmaW5hbCcsXG4gICAgICAgICAgICAgIGFjY291bnRfaWQ6IGFkZHJlc3MxSW5mby5hY2NvdW50SWQsXG4gICAgICAgICAgICAgIHB1YmxpY19rZXk6IGFkZHJlc3MxSW5mby5iczU4RW5jb2RlZFB1YmxpY0tleSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICAgLnJlc29sdmVzKE5lYXJSZXNwb25zZXMuZ2V0QWNjZXNzS2V5UmVzcG9uc2UpO1xuICAgICAgY2FsbEJhY2tcbiAgICAgICAgLndpdGhBcmdzKHtcbiAgICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgICBqc29ucnBjOiAnMi4wJyxcbiAgICAgICAgICAgIGlkOiAnZG9udGNhcmUnLFxuICAgICAgICAgICAgbWV0aG9kOiAncXVlcnknLFxuICAgICAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgICAgIHJlcXVlc3RfdHlwZTogJ3ZpZXdfYWNjb3VudCcsXG4gICAgICAgICAgICAgIGZpbmFsaXR5OiAnZmluYWwnLFxuICAgICAgICAgICAgICBhY2NvdW50X2lkOiBhY2NvdW50SW5mby5hY2NvdW50SWQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXNvbHZlcyhOZWFyUmVzcG9uc2VzLmdldFplcm9CYWxhbmNlQWNjb3VudFJlc3BvbnNlKTtcbiAgICAgIGNhbGxCYWNrXG4gICAgICAgIC53aXRoQXJncyh7XG4gICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAganNvbnJwYzogJzIuMCcsXG4gICAgICAgICAgICBpZDogJ2RvbnRjYXJlJyxcbiAgICAgICAgICAgIG1ldGhvZDogJ3F1ZXJ5JyxcbiAgICAgICAgICAgIHBhcmFtczoge1xuICAgICAgICAgICAgICByZXF1ZXN0X3R5cGU6ICd2aWV3X2FjY291bnQnLFxuICAgICAgICAgICAgICBmaW5hbGl0eTogJ2ZpbmFsJyxcbiAgICAgICAgICAgICAgYWNjb3VudF9pZDogYWRkcmVzczFJbmZvLmFjY291bnRJZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICAgLnJlc29sdmVzKE5lYXJSZXNwb25zZXMuZ2V0QWNjb3VudFJlc3BvbnNlKTtcbiAgICAgIGNhbGxCYWNrLndpdGhBcmdzKCkucmVzb2x2ZXMoTmVhclJlc3BvbnNlcy5nZXRQcm90b2NvbENvbmZpZ1Jlc3ApO1xuICAgICAgY2FsbEJhY2tcbiAgICAgICAgLndpdGhBcmdzKHtcbiAgICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgICBqc29ucnBjOiAnMi4wJyxcbiAgICAgICAgICAgIGlkOiAnZG9udGNhcmUnLFxuICAgICAgICAgICAgbWV0aG9kOiAnZ2FzX3ByaWNlJyxcbiAgICAgICAgICAgIHBhcmFtczogW2FkZHJlc3MxSW5mby5ibG9ja0hhc2hdLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXNvbHZlcyhOZWFyUmVzcG9uc2VzLmdldEdhc1ByaWNlUmVzcG9uc2UpO1xuICAgIH0pO1xuXG4gICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNhbmRCb3gucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWNvdmVyIGEgdHhuIGZvciBub24tYml0Z28gcmVjb3ZlcmllcyBhdCBhZGRyZXNzIDEgYnV0IHNlYXJjaCBmcm9tIGFkZHJlc3MgMCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICB1c2VyS2V5OiBrZXlzLnVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleToga2V5cy5iYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiBrZXlzLmJpdGdvS2V5LFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0QWRkcixcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ0doZ2hqa2chNDU1NTQ0bGxsbCcsXG4gICAgICB9KTtcbiAgICAgIHJlcy5zaG91bGQubm90LmJlLmVtcHR5KCk7XG4gICAgICByZXMuc2hvdWxkLmhhc093blByb3BlcnR5KCdzZXJpYWxpemVkVHgnKTtcbiAgICAgIHJlcy5zaG91bGQuaGFzT3duUHJvcGVydHkoJ3NjYW5JbmRleCcpO1xuICAgICAgcmVzLnNjYW5JbmRleC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBzYW5kQm94LmFzc2VydC5jYWxsQ291bnQoYmFzZWNvaW4uZ2V0RGF0YUZyb21Ob2RlLCA1KTtcblxuICAgICAgY29uc3QgdHggPSBuZXcgVHJhbnNhY3Rpb24oY29pbik7XG4gICAgICB0eC5mcm9tUmF3VHJhbnNhY3Rpb24ocmVzLnNlcmlhbGl6ZWRUeCk7XG4gICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcblxuICAgICAgc2hvdWxkLmVxdWFsKHR4SnNvbi5ub25jZSwgbm9uY2UpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4SnNvbi5zaWduZXJJZCwgYWRkcmVzczFJbmZvLmFjY291bnRJZCk7XG4gICAgICBzaG91bGQuZXF1YWwodHhKc29uLnB1YmxpY0tleSwgJ2VkMjU1MTk6JyArIGFkZHJlc3MxSW5mby5iczU4RW5jb2RlZFB1YmxpY0tleSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgYSB0eG4gZm9yIG5vbi1iaXRnbyByZWNvdmVyaWVzIGF0IGFkZHJlc3MgMSBidXQgc2VhcmNoIGZyb20gYWRkcmVzcyAxJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIHVzZXJLZXk6IGtleXMudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBrZXlzLmJhY2t1cEtleSxcbiAgICAgICAgYml0Z29LZXk6IGtleXMuYml0Z29LZXksXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IGRlc3RBZGRyLFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnR2hnaGprZyE0NTU1NDRsbGxsJyxcbiAgICAgICAgc3RhcnRpbmdTY2FuSW5kZXg6IDEsXG4gICAgICB9KTtcbiAgICAgIHJlcy5zaG91bGQubm90LmJlLmVtcHR5KCk7XG4gICAgICByZXMuc2hvdWxkLmhhc093blByb3BlcnR5KCdzZXJpYWxpemVkVHgnKTtcbiAgICAgIHJlcy5zaG91bGQuaGFzT3duUHJvcGVydHkoJ3NjYW5JbmRleCcpO1xuICAgICAgcmVzLnNjYW5JbmRleC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBzYW5kQm94LmFzc2VydC5jYWxsQ291bnQoYmFzZWNvaW4uZ2V0RGF0YUZyb21Ob2RlLCA0KTtcblxuICAgICAgY29uc3QgdHggPSBuZXcgVHJhbnNhY3Rpb24oY29pbik7XG4gICAgICB0eC5mcm9tUmF3VHJhbnNhY3Rpb24ocmVzLnNlcmlhbGl6ZWRUeCk7XG4gICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcblxuICAgICAgc2hvdWxkLmVxdWFsKHR4SnNvbi5ub25jZSwgbm9uY2UpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4SnNvbi5zaWduZXJJZCwgYWRkcmVzczFJbmZvLmFjY291bnRJZCk7XG4gICAgICBzaG91bGQuZXF1YWwodHhKc29uLnB1YmxpY0tleSwgJ2VkMjU1MTk6JyArIGFkZHJlc3MxSW5mby5iczU4RW5jb2RlZFB1YmxpY0tleSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdSZWNvdmVyIFRyYW5zYWN0aW9uIEZhaWx1cmVzOicsICgpID0+IHtcbiAgICBjb25zdCBzYW5kQm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuICAgIGNvbnN0IGRlc3RBZGRyID0gJ2FiaGF5LW5lYXIudGVzdG5ldCc7XG4gICAgY29uc3QgbnVtSXRlcmF0aW9uID0gMTA7XG5cbiAgICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNhbGxCYWNrID0gc2FuZEJveC5zdHViKE5lYXIucHJvdG90eXBlLCAnZ2V0RGF0YUZyb21Ob2RlJyBhcyBrZXlvZiBOZWFyKTtcbiAgICAgIGNhbGxCYWNrXG4gICAgICAgIC53aXRoQXJncyhzaW5vbi5tYXRjaC5oYXNOZXN0ZWQoJ3BheWxvYWQubWV0aG9kJywgJ0VYUEVSSU1FTlRBTF9wcm90b2NvbF9jb25maWcnKSlcbiAgICAgICAgLnJlc29sdmVzKE5lYXJSZXNwb25zZXMuZ2V0UHJvdG9jb2xDb25maWdSZXNwKTtcbiAgICAgIGNhbGxCYWNrLnJlc29sdmVzKE5lYXJSZXNwb25zZXMuZ2V0WmVyb0JhbGFuY2VBY2NvdW50UmVzcG9uc2UpO1xuICAgIH0pO1xuXG4gICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNhbmRCb3gucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIHJlY292ZXIgZHVlIHRvIG5vdCBmaW5kaW5nIGFuIGFkZHJlc3Mgd2l0aCBmdW5kcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5OiBrZXlzLnVzZXJLZXksXG4gICAgICAgICAgYmFja3VwS2V5OiBrZXlzLmJhY2t1cEtleSxcbiAgICAgICAgICBiaXRnb0tleToga2V5cy5iaXRnb0tleSxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnR2hnaGprZyE0NTU1NDRsbGxsJyxcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0QWRkcixcbiAgICAgICAgICBzY2FuOiBudW1JdGVyYXRpb24sXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQucmVqZWN0ZWRXaXRoKCdEaWQgbm90IGZpbmQgYW4gYWRkcmVzcyB3aXRoIGZ1bmRzIHRvIHJlY292ZXInKTtcbiAgICAgIC8vIGdldERhdGFGcm9tTm9kZSBzaG91bGQgYmUgY2FsbGVkIG51bUl0ZXJhdGlvbiArIDEgdGltZXMgc2luY2Ugd2UgaW5pdGlhbGx5XG4gICAgICAvLyBjYWxsIGdldFByb3RvY29sQ29uZmlnXG4gICAgICBzYW5kQm94LmFzc2VydC5jYWxsQ291bnQoYmFzZWNvaW4uZ2V0RGF0YUZyb21Ob2RlLCBudW1JdGVyYXRpb24gKyAxKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==

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


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