UNPKG

bitgo

Version:
380 lines • 67 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const _ = require("lodash");
const nock = require("nock");
const stakingWallet_1 = require("../../fixtures/staking/stakingWallet");
const opethFixtures = require("../../fixtures/staking/topethStakingFixtures");
const avaxpStakingFixtures = require("../../fixtures/staking/tavaxpStakingFixtures");
const sdk_core_1 = require("@bitgo/sdk-core");
const sdk_test_1 = require("@bitgo/sdk-test");
const src_1 = require("../../../../src");
const sinon = require("sinon");
describe('non-TSS Staking Wallet', function () {
    const microservicesUri = sdk_core_1.Environments['mock'].uri;
    let bitgo;
    let ethBaseCoin;
    let maticBaseCoin;
    let btcBaseCoin;
    let topethWctBaseCoin;
    let tavaxpBaseCoin;
    let enterprise;
    let ethWalletData;
    let btcWalletData;
    let topethWctStakingWalletData;
    let tavaxpStakingWalletData;
    let btcDescriptorWalletData;
    let ethStakingWallet;
    let maticStakingWallet;
    let btcStakingWallet;
    let topethWctStakingWallet;
    let tavaxpStakingWallet;
    before(function () {
        bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock', microservicesUri });
        bitgo.initializeTestVars();
        ethBaseCoin = bitgo.coin('eth');
        ethBaseCoin.keychains();
        maticBaseCoin = bitgo.coin('matic');
        maticBaseCoin.keychains();
        btcBaseCoin = bitgo.coin('btc');
        btcBaseCoin.keychains();
        topethWctBaseCoin = bitgo.coin('topeth:wct');
        tavaxpBaseCoin = bitgo.coin('tavaxp');
        enterprise = new sdk_core_1.Enterprise(bitgo, ethBaseCoin, {
            id: '5cf940949449412d00f53b3d92dbcaa3',
            name: 'Test Enterprise',
        });
        ethWalletData = {
            id: 'walletId',
            coin: 'eth',
            enterprise: enterprise.id,
            keys: ['5b3424f91bf349930e340175'],
            coinSpecific: { walletVersion: 2 },
        };
        const maticWalletData = {
            id: 'maticWalletId',
            coin: 'matic',
            enterprise: enterprise.id,
            keys: ['5b3424f91bf349930e340175'],
        };
        btcWalletData = {
            id: 'btcWalletId',
            coin: 'btc',
            enterprise: enterprise.id,
            keys: ['5b3424f91bf349930e340175'],
            coinSpecific: {},
        };
        btcDescriptorWalletData = {
            id: 'btcDescriptorWalletId',
            coin: 'btc',
            enterprise: enterprise.id,
            keys: ['5b3424f91bf349930e340175'],
            coinSpecific: {},
        };
        topethWctStakingWalletData = {
            approvalsRequired: 0,
            balance: 0,
            balanceString: '',
            coinSpecific: {},
            confirmedBalance: 0,
            confirmedBalanceString: '',
            keys: [],
            label: '',
            multisigType: 'onchain',
            pendingApprovals: [],
            spendableBalance: 0,
            spendableBalanceString: '',
            id: 'topethWctStakingWalletId',
            coin: 'topeth:wct',
            enterprise: enterprise.id,
        };
        tavaxpStakingWalletData = {
            approvalsRequired: 0,
            balance: 0,
            balanceString: '',
            coinSpecific: {},
            confirmedBalance: 0,
            confirmedBalanceString: '',
            keys: [],
            label: '',
            multisigType: 'onchain',
            pendingApprovals: [],
            spendableBalance: 0,
            spendableBalanceString: '',
            id: 'tavaxpStakingWalletId',
            coin: 'tavaxp',
            enterprise: enterprise.id,
        };
        const ethWallet = new sdk_core_1.Wallet(bitgo, ethBaseCoin, ethWalletData);
        const maticWallet = new sdk_core_1.Wallet(bitgo, maticBaseCoin, maticWalletData);
        const btcWallet = new sdk_core_1.Wallet(bitgo, btcBaseCoin, btcWalletData);
        topethWctStakingWallet = new sdk_core_1.Wallet(bitgo, topethWctBaseCoin, topethWctStakingWalletData).toStakingWallet();
        tavaxpStakingWallet = new sdk_core_1.Wallet(bitgo, tavaxpBaseCoin, tavaxpStakingWalletData).toStakingWallet();
        ethStakingWallet = ethWallet.toStakingWallet();
        maticStakingWallet = maticWallet.toStakingWallet();
        btcStakingWallet = btcWallet.toStakingWallet();
    });
    const sandbox = sinon.createSandbox();
    afterEach(function () {
        sandbox.verifyAndRestore();
    });
    describe('buildSignAndSend', function () {
        it('should build, sign and send transaction', async function () {
            const walletPassphrase = 'passphrase';
            const transaction = stakingWallet_1.default.transaction('READY', stakingWallet_1.default.buildParams);
            // BUILD
            nock(microservicesUri)
                .get(`/api/staking/v1/${ethStakingWallet.coin}/wallets/${ethStakingWallet.walletId}/requests/${transaction.stakingRequestId}/transactions/${transaction.id}`)
                .query({ expandBuildParams: true })
                .reply(200, transaction);
            const prebuildTransaction = sandbox.stub(sdk_core_1.Wallet.prototype, 'prebuildTransaction');
            const txPrebuild = {
                walletId: ethStakingWallet.walletId,
                txHex: 'hex',
                buildParams: transaction.buildParams,
            };
            prebuildTransaction.resolves(txPrebuild);
            prebuildTransaction.calledOnceWithExactly(transaction.buildParams);
            // SIGN
            const getKeysForSigning = sandbox.stub(sdk_core_1.Keychains.prototype, 'getKeysForSigning');
            const keyChain = {
                id: 'id',
                pub: 'pub',
                type: 'independent',
            };
            getKeysForSigning.resolves([keyChain]);
            getKeysForSigning.calledOnce;
            const signTransaction = sandbox.stub(sdk_core_1.Wallet.prototype, 'signTransaction');
            const signed = {
                halfSigned: {
                    txHex: 'hex',
                    payload: 'payload',
                    txBase64: 'base64',
                },
            };
            signTransaction.resolves(signed);
            signTransaction.calledOnceWithExactly({
                txPrebuild: txPrebuild,
                walletPassphrase: walletPassphrase,
                keychain: keyChain,
            });
            // SEND
            nock(microservicesUri)
                .post(`/api/staking/v1/${ethStakingWallet.coin}/wallets/${ethStakingWallet.walletId}/requests/${transaction.stakingRequestId}/transactions/${transaction.id}`, _.matches(signed))
                .reply(200, transaction);
            // skipping validation because mock data is not a valid transaction
            sinon.stub(sdk_core_1.StakingWallet.prototype, 'validateBuiltStakingTransaction').resolves();
            const stakingTransaction = await ethStakingWallet.buildSignAndSend({ walletPassphrase: walletPassphrase }, transaction);
            stakingTransaction.should.deepEqual(transaction);
            sinon.restore();
        });
        it('should throw error when buildParams are not expanded', async function () {
            const walletPassphrase = 'passphrase';
            const transaction = stakingWallet_1.default.transaction('READY');
            // BUILD
            nock(microservicesUri)
                .get(`/api/staking/v1/${ethStakingWallet.coin}/wallets/${ethStakingWallet.walletId}/requests/${transaction.stakingRequestId}/transactions/${transaction.id}`)
                .query({ expandBuildParams: true })
                .reply(200, transaction);
            await ethStakingWallet
                .buildSignAndSend({ walletPassphrase: walletPassphrase }, transaction)
                .should.rejectedWith(`Staking transaction ${transaction.id} build params not expanded`);
        });
    });
    describe('token buildSignAndSend', function () {
        afterEach(function () {
            sandbox.verifyAndRestore();
        });
        it('should build, sign and send transaction', async function () {
            const walletPassphrase = 'passphrase';
            const transaction = stakingWallet_1.default.transaction('READY', stakingWallet_1.default.buildParams);
            // BUILD
            nock(microservicesUri)
                .get(`/api/staking/v1/${maticStakingWallet.coin}/wallets/${maticStakingWallet.walletId}/requests/${transaction.stakingRequestId}/transactions/${transaction.id}`)
                .query({ expandBuildParams: true })
                .reply(200, transaction);
            const prebuildTransaction = sandbox.stub(sdk_core_1.Wallet.prototype, 'prebuildTransaction');
            const txPrebuild = {
                walletId: maticStakingWallet.walletId,
                txHex: 'hex',
                buildParams: transaction.buildParams,
            };
            prebuildTransaction.resolves(txPrebuild);
            prebuildTransaction.calledOnceWithExactly(transaction.buildParams);
            // SIGN
            const getKeysForSigning = sandbox.stub(sdk_core_1.Keychains.prototype, 'getKeysForSigning');
            const keyChain = {
                id: 'id',
                pub: 'pub',
                type: 'independent',
            };
            getKeysForSigning.resolves([keyChain]);
            getKeysForSigning.calledOnce;
            const signTransaction = sandbox.stub(sdk_core_1.Wallet.prototype, 'signTransaction');
            const signed = {
                halfSigned: {
                    txHex: 'hex',
                    payload: 'payload',
                    txBase64: 'base64',
                },
            };
            signTransaction.resolves(signed);
            signTransaction.calledOnceWithExactly({
                txPrebuild: txPrebuild,
                walletPassphrase: walletPassphrase,
                keychain: keyChain,
            });
            const type = maticStakingWallet.wallet.baseCoin.tokenConfig?.type;
            const coin = maticStakingWallet.wallet.baseCoin.tokenConfig?.coin;
            // get wallet for building and signing
            nock(microservicesUri).get(`/api/v2/${coin}/wallet/${maticStakingWallet.walletId}`).reply(200, ethWalletData);
            // SEND
            nock(microservicesUri)
                .post(`/api/staking/v1/${type}/wallets/${maticStakingWallet.walletId}/requests/${transaction.stakingRequestId}/transactions/${transaction.id}`, _.matches(signed))
                .reply(200, transaction);
            // skipping validation because mock data is not a valid transaction
            sinon.stub(sdk_core_1.StakingWallet.prototype, 'validateBuiltStakingTransaction').resolves();
            const stakingTransaction = await maticStakingWallet.buildSignAndSend({ walletPassphrase: walletPassphrase }, transaction);
            stakingTransaction.should.deepEqual(transaction);
            sinon.restore();
        });
    });
    describe('BTC staking', function () {
        it('btc delegation transaction', async function () {
            const transaction = stakingWallet_1.default.transaction('READY', stakingWallet_1.default.buildParams, false);
            nock(microservicesUri)
                .get(`/api/staking/v1/${btcStakingWallet.coin}/wallets/${btcStakingWallet.walletId}/requests/${transaction.stakingRequestId}/transactions/${transaction.id}`)
                .query({ expandBuildParams: true })
                .reply(200, transaction);
            const prebuildTransaction = sandbox.stub(sdk_core_1.Wallet.prototype, 'prebuildTransaction');
            const descriptor = sandbox.stub(sdk_core_1.StakingWallet.prototype, 'getDescriptorWallet');
            await btcStakingWallet.build(transaction);
            prebuildTransaction.calledOnceWithExactly(transaction.buildParams).should.be.true;
            descriptor.notCalled.should.be.true;
        });
        it('btc undelegation transaction', async function () {
            const transaction = stakingWallet_1.default.transaction('READY', stakingWallet_1.default.btcUnstakingBuildParams, false, 'undelegate_withdraw');
            nock(microservicesUri)
                .get(`/api/staking/v1/${btcStakingWallet.coin}/wallets/${btcStakingWallet.walletId}/requests/${transaction.stakingRequestId}/transactions/${transaction.id}`)
                .query({ expandBuildParams: true })
                .reply(200, transaction);
            nock(microservicesUri)
                .get(`/api/v2/btc/wallet/${btcDescriptorWalletData.id}`)
                .reply(200, btcDescriptorWalletData);
            const prebuildTransaction = sandbox.stub(sdk_core_1.Wallet.prototype, 'prebuildTransaction');
            await btcStakingWallet.build(transaction);
            prebuildTransaction.calledOnceWithExactly(transaction.buildParams).should.be.true;
        });
    });
    describe('Opeth:WCT Staking', function () {
        it('should skip transaction validation when skipTransactionVerification is true', async function () {
            const unsignedTransaction = {
                walletId: topethWctStakingWallet.walletId,
                ...opethFixtures.unsignedStakingTransaction,
                // Using a modified txHex that would normally cause validation to fail
                txHex: '0x02f9019083aa37dc718206a882089e83030d40941d1a245741bd7d603747a23d30f4c91682a2992680b901643912521500000000000000000000000086bb6dca2cd6f9a0189c478bbb8f7ee2fef07c89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000067ebedc3000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000140d63efb5b24314f6f62dbadb383dba2e49d7ee0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0808080',
            };
            const stakingTransaction = opethFixtures.updatedStakingRequest;
            nock(microservicesUri)
                .get(`/api/staking/v1/${topethWctStakingWallet.coin}/wallets/${topethWctStakingWallet.walletId}/requests/${stakingTransaction.stakingRequestId}/transactions/${stakingTransaction.id}`)
                .query({ expandBuildParams: true })
                .reply(200, stakingTransaction);
            nock(microservicesUri)
                .get(`/api/v2/topeth/wallet/${topethWctStakingWallet.walletId}`)
                .reply(200, topethWctStakingWalletData);
            nock(microservicesUri)
                .post(`/api/v2/topeth/wallet/${topethWctStakingWallet.walletId}/tx/build`)
                .reply(200, unsignedTransaction);
            // Mock the sign method to verify we reach it without validation error
            const signStub = sinon.stub(topethWctStakingWallet, 'sign').resolves({
                transaction: stakingTransaction,
                signed: { halfSigned: { txHex: 'signed-hex' } },
            });
            // Mock validateBuiltStakingTransaction to verify it's not called
            const validateStub = sinon.stub(sdk_core_1.StakingWallet.prototype, 'validateBuiltStakingTransaction');
            // Call buildAndSign with skipTransactionVerification=true
            await topethWctStakingWallet.buildAndSign({
                walletPassphrase: 'passphrase',
                transactionVerificationOptions: { skipTransactionVerification: true },
            }, stakingTransaction);
            // Verify that validation was skipped
            validateStub.called.should.be.false;
            signStub.calledOnce.should.be.true;
            // Restore stubs
            validateStub.restore();
            signStub.restore();
        });
        it('should return true for isSendCallRequired for topethWctStakingWallet', function () {
            // Access the private method using type assertion
            const isSendCallRequired = topethWctStakingWallet.isSendCallRequired();
            // Check that isSendCallRequired returns true because this is not ETH TSS
            isSendCallRequired.should.equal(true);
        });
        it('should build and validate transaction', async function () {
            const unsignedTransaction = {
                walletId: topethWctStakingWallet.walletId,
                ...opethFixtures.unsignedStakingTransaction,
            };
            const stakingTransaction = opethFixtures.updatedStakingRequest;
            nock(microservicesUri)
                .get(`/api/staking/v1/${topethWctStakingWallet.coin}/wallets/${topethWctStakingWallet.walletId}/requests/${stakingTransaction.stakingRequestId}/transactions/${stakingTransaction.id}`)
                .query({ expandBuildParams: true })
                .reply(200, stakingTransaction);
            nock(microservicesUri)
                .get(`/api/v2/topeth/wallet/${topethWctStakingWallet.walletId}`)
                .reply(200, topethWctStakingWalletData);
            nock(microservicesUri)
                .post(`/api/v2/topeth/wallet/${topethWctStakingWallet.walletId}/tx/build`)
                .reply(200, unsignedTransaction);
            // tx validation happens before signing, so we can skip it
            sinon.stub(topethWctStakingWallet, 'sign').resolves();
            await topethWctStakingWallet.buildAndSign({ walletPassphrase: 'passphrase' }, stakingTransaction);
        });
        it('should throw an error if unsigned transaction does not match the staking transaction', async function () {
            const unsignedTransaction = {
                walletId: topethWctStakingWallet.walletId,
                ...opethFixtures.unsignedStakingTransaction,
                txHex: '0x02f9019083aa37dc718206a882089e83030d40941d1a245741bd7d603747a23d30f4c91682a2992680b901643912521500000000000000000000000086bb6dca2cd6f9a0189c478bbb8f7ee2fef07c89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000067ebedc3000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000140d63efb5b24314f6f62dbadb383dba2e49d7ee0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0808080',
            };
            const stakingTransaction = opethFixtures.updatedStakingRequest;
            nock(microservicesUri)
                .get(`/api/staking/v1/${topethWctStakingWallet.coin}/wallets/${topethWctStakingWallet.walletId}/requests/${stakingTransaction.stakingRequestId}/transactions/${stakingTransaction.id}`)
                .query({ expandBuildParams: true })
                .reply(200, stakingTransaction);
            nock(microservicesUri)
                .get(`/api/v2/topeth/wallet/${topethWctStakingWallet.walletId}`)
                .reply(200, topethWctStakingWalletData);
            nock(microservicesUri)
                .post(`/api/v2/topeth/wallet/${topethWctStakingWallet.walletId}/tx/build`)
                .reply(200, unsignedTransaction);
            const expectedErrorMessage = 'Staking transaction validation failed before signing: ' +
                'Unexpected recipient address found in built transaction: 0x86bb6dca2cd6f9a0189c478bbb8f7ee2fef07c89; ' +
                'Expected recipient address not found in built transaction: 0x75bb6dca2cd6f9a0189c478bbb8f7ee2fef07c78';
            await topethWctStakingWallet
                .buildAndSign({ walletPassphrase: 'passphrase' }, stakingTransaction)
                .should.be.rejectedWith(expectedErrorMessage);
        });
    });
    describe('TAVAXP Staking', function () {
        it('should build and validate transaction', async function () {
            const unsignedTransaction = {
                walletId: tavaxpStakingWallet.walletId,
                ...avaxpStakingFixtures.unsignedStakingTransaction,
            };
            const stakingTransaction = avaxpStakingFixtures.updatedStakingRequest;
            nock(microservicesUri)
                .get(`/api/staking/v1/${tavaxpStakingWallet.coin}/wallets/${tavaxpStakingWallet.walletId}/requests/${stakingTransaction.stakingRequestId}/transactions/${stakingTransaction.id}`)
                .query({ expandBuildParams: true })
                .reply(200, stakingTransaction);
            nock(microservicesUri)
                .get(`/api/v2/tavaxp/wallet/${tavaxpStakingWallet.walletId}`)
                .reply(200, tavaxpStakingWalletData);
            nock(microservicesUri)
                .post(`/api/v2/tavaxp/wallet/${tavaxpStakingWallet.walletId}/tx/build`)
                .reply(200, unsignedTransaction);
            // tx validation happens before signing, so we can skip it
            sinon.stub(tavaxpStakingWallet, 'sign').resolves();
            await tavaxpStakingWallet.buildAndSign({ walletPassphrase: 'passphrase' }, stakingTransaction);
        });
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Rha2luZ1dhbGxldE5vblRTUy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Rlc3QvdjIvdW5pdC9zdGFraW5nL3N0YWtpbmdXYWxsZXROb25UU1MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw0QkFBNEI7QUFFNUIsNkJBQThCO0FBQzlCLHdFQUE0RDtBQUM1RCw4RUFBOEU7QUFDOUUscUZBQXFGO0FBRXJGLDhDQVd5QjtBQUN6Qiw4Q0FBNEM7QUFDNUMseUNBQXdDO0FBQ3hDLCtCQUErQjtBQUUvQixRQUFRLENBQUMsd0JBQXdCLEVBQUU7SUFDakMsTUFBTSxnQkFBZ0IsR0FBRyx1QkFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUNsRCxJQUFJLEtBQUssQ0FBQztJQUNWLElBQUksV0FBVyxDQUFDO0lBQ2hCLElBQUksYUFBYSxDQUFDO0lBQ2xCLElBQUksV0FBVyxDQUFDO0lBQ2hCLElBQUksaUJBQWlCLENBQUM7SUFDdEIsSUFBSSxjQUFjLENBQUM7SUFDbkIsSUFBSSxVQUFVLENBQUM7SUFDZixJQUFJLGFBQWtCLENBQUM7SUFDdkIsSUFBSSxhQUFrQixDQUFDO0lBQ3ZCLElBQUksMEJBQXNDLENBQUM7SUFDM0MsSUFBSSx1QkFBbUMsQ0FBQztJQUN4QyxJQUFJLHVCQUE0QixDQUFDO0lBQ2pDLElBQUksZ0JBQStCLENBQUM7SUFDcEMsSUFBSSxrQkFBaUMsQ0FBQztJQUN0QyxJQUFJLGdCQUErQixDQUFDO0lBQ3BDLElBQUksc0JBQXFDLENBQUM7SUFDMUMsSUFBSSxtQkFBa0MsQ0FBQztJQUV2QyxNQUFNLENBQUM7UUFDTCxLQUFLLEdBQUcsb0JBQVMsQ0FBQyxRQUFRLENBQUMsV0FBSyxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxnQkFBZ0IsRUFBUyxDQUFDLENBQUM7UUFDNUUsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDM0IsV0FBVyxHQUFHLEtBQUss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bUIsQ0FBQyxDQUFDO1lBRW5DLDBEQUEwRDtZQUMxRCxLQUFLLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLE1BQU0sQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBRW5ELE1BQU0sbUJBQW1CLENBQUMsWUFBWSxDQUFDLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxFQUFFLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztRQUNqRyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5cbmltcG9ydCBub2NrID0gcmVxdWlyZSgnbm9jaycpO1xuaW1wb3J0IGZpeHR1cmVzIGZyb20gJy4uLy4uL2ZpeHR1cmVzL3N0YWtpbmcvc3Rha2luZ1dhbGxldCc7XG5pbXBvcnQgKiBhcyBvcGV0aEZpeHR1cmVzIGZyb20gJy4uLy4uL2ZpeHR1cmVzL3N0YWtpbmcvdG9wZXRoU3Rha2luZ0ZpeHR1cmVzJztcbmltcG9ydCAqIGFzIGF2YXhwU3Rha2luZ0ZpeHR1cmVzIGZyb20gJy4uLy4uL2ZpeHR1cmVzL3N0YWtpbmcvdGF2YXhwU3Rha2luZ0ZpeHR1cmVzJztcblxuaW1wb3J0IHtcbiAgRW50ZXJwcmlzZSxcbiAgRW52aXJvbm1lbnRzLFxuICBLZXljaGFpbixcbiAgS2V5Y2hhaW5zLFxuICBQcmVidWlsZFRyYW5zYWN0aW9uUmVzdWx0LFxuICBTdGFraW5nVHJhbnNhY3Rpb24sXG4gIFN0YWtpbmdXYWxsZXQsXG4gIFdhbGxldCxcbiAgV2FsbGV0Q29pblNwZWNpZmljLFxuICBXYWxsZXREYXRhLFxufSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuaW1wb3J0IHsgVGVzdEJpdEdvIH0gZnJvbSAnQGJpdGdvL3Nkay10ZXN0JztcbmltcG9ydCB7IEJpdEdvIH0gZnJvbSAnLi4vLi4vLi4vLi4vc3JjJztcbmltcG9ydCAqIGFzIHNpbm9uIGZyb20gJ3Npbm9uJztcblxuZGVzY3JpYmUoJ25vbi1UU1MgU3Rha2luZyBXYWxsZXQnLCBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IG1pY3Jvc2VydmljZXNVcmkgPSBFbnZpcm9ubWVudHNbJ21vY2snXS51cmk7XG4gIGxldCBiaXRnbztcbiAgbGV0IGV0aEJhc2VDb2luO1xuICBsZXQgbWF0aWNCYXNlQ29pbjtcbiAgbGV0IGJ0Y0Jhc2VDb2luO1xuICBsZXQgdG9wZXRoV2N0QmFzZUNvaW47XG4gIGxldCB0YXZheHBCYXNlQ29pbjtcbiAgbGV0IGVudGVycHJpc2U7XG4gIGxldCBldGhXYWxsZXREYXRhOiBhbnk7XG4gIGxldCBidGNXYWxsZXREYXRhOiBhbnk7XG4gIGxldCB0b3BldGhXY3RTdGFraW5nV2FsbGV0RGF0YTogV2FsbGV0RGF0YTtcbiAgbGV0IHRhdmF4cFN0YWtpbmdXYWxsZXREYXRhOiBXYWxsZXREYXRhO1xuICBsZXQgYnRjRGVzY3JpcHRvcldhbGxldERhdGE6IGFueTtcbiAgbGV0IGV0aFN0YWtpbmdXYWxsZXQ6IFN0YWtpbmdXYWxsZXQ7XG4gIGxldCBtYXRpY1N0YWtpbmdXYWxsZXQ6IFN0YWtpbmdXYWxsZXQ7XG4gIGxldCBidGNTdGFraW5nV2FsbGV0OiBTdGFraW5nV2FsbGV0O1xuICBsZXQgdG9wZXRoV2N0U3Rha2luZ1dhbGxldDogU3Rha2luZ1dhbGxldDtcbiAgbGV0IHRhdmF4cFN0YWtpbmdXYWxsZXQ6IFN0YWtpbmdXYWxsZXQ7XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJywgbWljcm9zZXJ2aWNlc1VyaSB9IGFzIGFueSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgZXRoQmFzZUNvaW4gPSBiaXRnby5jb2luKCdldGgnKTtcbiAgICBldGhCYXNlQ29pbi5rZXljaGFpbnMoKTtcbiAgICBtYXRpY0Jhc2VDb2luID0gYml0Z28uY29pbignbWF0aWMnKTtcbiAgICBtYXRpY0Jhc2VDb2luLmtleWNoYWlucygpO1xuICAgIGJ0Y0Jhc2VDb2luID0gYml0Z28uY29pbignYnRjJyk7XG4gICAgYnRjQmFzZUNvaW4ua2V5Y2hhaW5zKCk7XG4gICAgdG9wZXRoV2N0QmFzZUNvaW4gPSBiaXRnby5jb2luKCd0b3BldGg6d2N0Jyk7XG4gICAgdGF2YXhwQmFzZUNvaW4gPSBiaXRnby5jb2luKCd0YXZheHAnKTtcblxuICAgIGVudGVycHJpc2UgPSBuZXcgRW50ZXJwcmlzZShiaXRnbywgZXRoQmFzZUNvaW4sIHtcbiAgICAgIGlkOiAnNWNmOTQwOTQ5NDQ5NDEyZDAwZjUzYjNkOTJkYmNhYTMnLFxuICAgICAgbmFtZTogJ1Rlc3QgRW50ZXJwcmlzZScsXG4gICAgfSk7XG4gICAgZXRoV2FsbGV0RGF0YSA9IHtcbiAgICAgIGlkOiAnd2FsbGV0SWQnLFxuICAgICAgY29pbjogJ2V0aCcsXG4gICAgICBlbnRlcnByaXNlOiBlbnRlcnByaXNlLmlkLFxuICAgICAga2V5czogWyc1YjM0MjRmOTFiZjM0OTkzMGUzNDAxNzUnXSxcbiAgICAgIGNvaW5TcGVjaWZpYzogeyB3YWxsZXRWZXJzaW9uOiAyIH0sXG4gICAgfTtcbiAgICBjb25zdCBtYXRpY1dhbGxldERhdGEgPSB7XG4gICAgICBpZDogJ21hdGljV2FsbGV0SWQnLFxuICAgICAgY29pbjogJ21hdGljJyxcbiAgICAgIGVudGVycHJpc2U6IGVudGVycHJpc2UuaWQsXG4gICAgICBrZXlzOiBbJzViMzQyNGY5MWJmMzQ5OTMwZTM0MDE3NSddLFxuICAgIH07XG4gICAgYnRjV2FsbGV0RGF0YSA9IHtcbiAgICAgIGlkOiAnYnRjV2FsbGV0SWQnLFxuICAgICAgY29pbjogJ2J0YycsXG4gICAgICBlbnRlcnByaXNlOiBlbnRlcnByaXNlLmlkLFxuICAgICAga2V5czogWyc1YjM0MjRmOTFiZjM0OTkzMGUzNDAxNzUnXSxcbiAgICAgIGNvaW5TcGVjaWZpYzoge30sXG4gICAgfTtcbiAgICBidGNEZXNjcmlwdG9yV2FsbGV0RGF0YSA9IHtcbiAgICAgIGlkOiAnYnRjRGVzY3JpcHRvcldhbGxldElkJyxcbiAgICAgIGNvaW46ICdidGMnLFxuICAgICAgZW50ZXJwcmlzZTogZW50ZXJwcmlzZS5pZCxcbiAgICAgIGtleXM6IFsnNWIzNDI0ZjkxYmYzNDk5MzBlMzQwMTc1J10sXG4gICAgICBjb2luU3BlY2lmaWM6IHt9LFxuICAgIH07XG5cbiAgICB0b3BldGhXY3RTdGFraW5nV2FsbGV0RGF0YSA9IHtcbiAgICAgIGFwcHJvdmFsc1JlcXVpcmVkOiAwLFxuICAgICAgYmFsYW5jZTogMCxcbiAgICAgIGJhbGFuY2VTdHJpbmc6ICcnLFxuICAgICAgY29pblNwZWNpZmljOiB7fSBhcyBXYWxsZXRDb2luU3BlY2lmaWMsXG4gICAgICBjb25maXJtZWRCYWxhbmNlOiAwLFxuICAgICAgY29uZmlybWVkQmFsYW5jZVN0cmluZzogJycsXG4gICAgICBrZXlzOiBbXSxcbiAgICAgIGxhYmVsOiAnJyxcbiAgICAgIG11bHRpc2lnVHlwZTogJ29uY2hhaW4nLFxuICAgICAgcGVuZGluZ0FwcHJvdmFsczogW10sXG4gICAgICBzcGVuZGFibGVCYWxhbmNlOiAwLFxuICAgICAgc3BlbmRhYmxlQmFsYW5jZVN0cmluZzogJycsXG4gICAgICBpZDogJ3RvcGV0aFdjdFN0YWtpbmdXYWxsZXRJZCcsXG4gICAgICBjb2luOiAndG9wZXRoOndjdCcsXG4gICAgICBlbnRlcnByaXNlOiBlbnRlcnByaXNlLmlkLFxuICAgIH07XG5cbiAgICB0YXZheHBTdGFraW5nV2FsbGV0RGF0YSA9IHtcbiAgICAgIGFwcHJvdmFsc1JlcXVpcmVkOiAwLFxuICAgICAgYmFsYW5jZTogMCxcbiAgICAgIGJhbGFuY2VTdHJpbmc6ICcnLFxuICAgICAgY29pblNwZWNpZmljOiB7fSBhcyBXYWxsZXRDb2luU3BlY2lmaWMsXG4gICAgICBjb25maXJtZWRCYWxhbmNlOiAwLFxuICAgICAgY29uZmlybWVkQmFsYW5jZVN0cmluZzogJycsXG4gICAgICBrZXlzOiBbXSxcbiAgICAgIGxhYmVsOiAnJyxcbiAgICAgIG11bHRpc2lnVHlwZTogJ29uY2hhaW4nLFxuICAgICAgcGVuZGluZ0FwcHJvdmFsczogW10sXG4gICAgICBzcGVuZGFibGVCYWxhbmNlOiAwLFxuICAgICAgc3BlbmRhYmxlQmFsYW5jZVN0cmluZzogJycsXG4gICAgICBpZDogJ3RhdmF4cFN0YWtpbmdXYWxsZXRJZCcsXG4gICAgICBjb2luOiAndGF2YXhwJyxcbiAgICAgIGVudGVycHJpc2U6IGVudGVycHJpc2UuaWQsXG4gICAgfTtcblxuICAgIGNvbnN0IGV0aFdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGV0aEJhc2VDb2luLCBldGhXYWxsZXREYXRhKTtcbiAgICBjb25zdCBtYXRpY1dhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIG1hdGljQmFzZUNvaW4sIG1hdGljV2FsbGV0RGF0YSk7XG4gICAgY29uc3QgYnRjV2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYnRjQmFzZUNvaW4sIGJ0Y1dhbGxldERhdGEpO1xuICAgIHRvcGV0aFdjdFN0YWtpbmdXYWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0b3BldGhXY3RCYXNlQ29pbiwgdG9wZXRoV2N0U3Rha2luZ1dhbGxldERhdGEpLnRvU3Rha2luZ1dhbGxldCgpO1xuICAgIHRhdmF4cFN0YWtpbmdXYWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0YXZheHBCYXNlQ29pbiwgdGF2YXhwU3Rha2luZ1dhbGxldERhdGEpLnRvU3Rha2luZ1dhbGxldCgpO1xuXG4gICAgZXRoU3Rha2luZ1dhbGxldCA9IGV0aFdhbGxldC50b1N0YWtpbmdXYWxsZXQoKTtcbiAgICBtYXRpY1N0YWtpbmdXYWxsZXQgPSBtYXRpY1dhbGxldC50b1N0YWtpbmdXYWxsZXQoKTtcbiAgICBidGNTdGFraW5nV2FsbGV0ID0gYnRjV2FsbGV0LnRvU3Rha2luZ1dhbGxldCgpO1xuICB9KTtcblxuICBjb25zdCBzYW5kYm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuXG4gIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgc2FuZGJveC52ZXJpZnlBbmRSZXN0b3JlKCk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdidWlsZFNpZ25BbmRTZW5kJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgYnVpbGQsIHNpZ24gYW5kIHNlbmQgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXRQYXNzcGhyYXNlID0gJ3Bhc3NwaHJhc2UnO1xuICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSBmaXh0dXJlcy50cmFuc2FjdGlvbignUkVBRFknLCBmaXh0dXJlcy5idWlsZFBhcmFtcyk7XG5cbiAgICAgIC8vIEJVSUxEXG4gICAgICBub2NrKG1pY3Jvc2VydmljZXNVcmkpXG4gICAgICAgIC5nZXQoXG4gICAgICAgICAgYC9hcGkvc3Rha2luZy92MS8ke2V0aFN0YWtpbmdXYWxsZXQuY29pbn0vd2FsbGV0cy8ke2V0aFN0YWtpbmdXYWxsZXQud2FsbGV0SWR9L3JlcXVlc3RzLyR7dHJhbnNhY3Rpb24uc3Rha2luZ1JlcXVlc3RJZH0vdHJhbnNhY3Rpb25zLyR7dHJhbnNhY3Rpb24uaWR9YFxuICAgICAgICApXG4gICAgICAgIC5xdWVyeSh7IGV4cGFuZEJ1aWxkUGFyYW1zOiB0cnVlIH0pXG4gICAgICAgIC5yZXBseSgyMDAsIHRyYW5zYWN0aW9uKTtcblxuICAgICAgY29uc3QgcHJlYnVpbGRUcmFuc2FjdGlvbiA9IHNhbmRib3guc3R1YihXYWxsZXQucHJvdG90eXBlLCAncHJlYnVpbGRUcmFuc2FjdGlvbicpO1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgd2FsbGV0SWQ6IGV0aFN0YWtpbmdXYWxsZXQud2FsbGV0SWQsXG4gICAgICAgIHR4SGV4OiAnaGV4JyxcbiAgICAgICAgYnVpbGRQYXJhbXM6IHRyYW5zYWN0aW9uLmJ1aWxkUGFyYW1zLFxuICAgICAgfTtcbiAgICAgIHByZWJ1aWxkVHJhbnNhY3Rpb24ucmVzb2x2ZXModHhQcmVidWlsZCk7XG4gICAgICBwcmVidWlsZFRyYW5zYWN0aW9uLmNhbGxlZE9uY2VXaXRoRXhhY3RseSh0cmFuc2FjdGlvbi5idWlsZFBhcmFtcyk7XG5cbiAgICAgIC8vIFNJR05cbiAgICAgIGNvbnN0IGdldEtleXNGb3JTaWduaW5nID0gc2FuZGJveC5zdHViKEtleWNoYWlucy5wcm90b3R5cGUsICdnZXRLZXlzRm9yU2lnbmluZycpO1xuICAgICAgY29uc3Qga2V5Q2hhaW46IEtleWNoYWluID0ge1xuICAgICAgICBpZDogJ2lkJyxcbiAgICAgICAgcHViOiAncHViJyxcbiAgICAgICAgdHlwZTogJ2luZGVwZW5kZW50JyxcbiAgICAgIH07XG4gICAgICBnZXRLZXlzRm9yU2lnbmluZy5yZXNvbHZlcyhba2V5Q2hhaW5dKTtcbiAgICAgIGdldEtleXNGb3JTaWduaW5nLmNhbGxlZE9uY2U7XG5cbiAgICAgIGNvbnN0IHNpZ25UcmFuc2FjdGlvbiA9IHNhbmRib3guc3R1YihXYWxsZXQucHJvdG90eXBlLCAnc2lnblRyYW5zYWN0aW9uJyk7XG4gICAgICBjb25zdCBzaWduZWQgPSB7XG4gICAgICAgIGhhbGZTaWduZWQ6IHtcbiAgICAgICAgICB0eEhleDogJ2hleCcsXG4gICAgICAgICAgcGF5bG9hZDogJ3BheWxvYWQnLFxuICAgICAgICAgIHR4QmFzZTY0OiAnYmFzZTY0JyxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICBzaWduVHJhbnNhY3Rpb24ucmVzb2x2ZXMoc2lnbmVkKTtcbiAgICAgIHNpZ25UcmFuc2FjdGlvbi5jYWxsZWRPbmNlV2l0aEV4YWN0bHkoe1xuICAgICAgICB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkLFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICBrZXljaGFpbjoga2V5Q2hhaW4sXG4gICAgICB9KTtcblxuICAgICAgLy8gU0VORFxuICAgICAgbm9jayhtaWNyb3NlcnZpY2VzVXJpKVxuICAgICAgICAucG9zdChcbiAgICAgICAgICBgL2FwaS9zdGFraW5nL3YxLyR7ZXRoU3Rha2luZ1dhbGxldC5jb2lufS93YWxsZXRzLyR7ZXRoU3Rha2luZ1dhbGxldC53YWxsZXRJZH0vcmVxdWVzdHMvJHt0cmFuc2FjdGlvbi5zdGFraW5nUmVxdWVzdElkfS90cmFuc2FjdGlvbnMvJHt0cmFuc2FjdGlvbi5pZH1gLFxuICAgICAgICAgIF8ubWF0Y2hlcyhzaWduZWQpXG4gICAgICAgIClcbiAgICAgICAgLnJlcGx5KDIwMCwgdHJhbnNhY3Rpb24pO1xuXG4gICAgICAvLyBza2lwcGluZyB2YWxpZGF0aW9uIGJlY2F1c2UgbW9jayBkYXRhIGlzIG5vdCBhIHZhbGlkIHRyYW5zYWN0aW9uXG4gICAgICBzaW5vbi5zdHViKFN0YWtpbmdXYWxsZXQucHJvdG90eXBlLCA8YW55Pid2YWxpZGF0ZUJ1aWx0U3Rha2luZ1RyYW5zYWN0aW9uJykucmVzb2x2ZXMoKTtcblxuICAgICAgY29uc3Qgc3Rha2luZ1RyYW5zYWN0aW9uID0gYXdhaXQgZXRoU3Rha2luZ1dhbGxldC5idWlsZFNpZ25BbmRTZW5kKFxuICAgICAgICB7IHdhbGxldFBhc3NwaHJhc2U6IHdhbGxldFBhc3NwaHJhc2UgfSxcbiAgICAgICAgdHJhbnNhY3Rpb25cbiAgICAgICk7XG5cbiAgICAgIHN0YWtpbmdUcmFuc2FjdGlvbi5zaG91bGQuZGVlcEVxdWFsKHRyYW5zYWN0aW9uKTtcbiAgICAgIHNpbm9uLnJlc3RvcmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiBidWlsZFBhcmFtcyBhcmUgbm90IGV4cGFuZGVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0UGFzc3BocmFzZSA9ICdwYXNzcGhyYXNlJztcbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gZml4dHVyZXMudHJhbnNhY3Rpb24oJ1JFQURZJyk7XG5cbiAgICAgIC8vIEJVSUxEXG4gICAgICBub2NrKG1pY3Jvc2VydmljZXNVcmkpXG4gICAgICAgIC5nZXQoXG4gICAgICAgICAgYC9hcGkvc3Rha2luZy92MS8ke2V0aFN0YWtpbmdXYWxsZXQuY29pbn0vd2FsbGV0cy8ke2V0aFN0YWtpbmdXYWxsZXQud2FsbGV0SWR9L3JlcXVlc3RzLyR7dHJhbnNhY3Rpb24uc3Rha2luZ1JlcXVlc3RJZH0vdHJhbnNhY3Rpb25zLyR7dHJhbnNhY3Rpb24uaWR9YFxuICAgICAgICApXG4gICAgICAgIC5xdWVyeSh7IGV4cGFuZEJ1aWxkUGFyYW1zOiB0cnVlIH0pXG4gICAgICAgIC5yZXBseSgyMDAsIHRyYW5zYWN0aW9uKTtcblxuICAgICAgYXdhaXQgZXRoU3Rha2luZ1dhbGxldFxuICAgICAgICAuYnVpbGRTaWduQW5kU2VuZCh7IHdhbGxldFBhc3NwaHJhc2U6IHdhbGxldFBhc3NwaHJhc2UgfSwgdHJhbnNhY3Rpb24pXG4gICAgICAgIC5zaG91bGQucmVqZWN0ZWRXaXRoKGBTdGFraW5nIHRyYW5zYWN0aW9uICR7dHJhbnNhY3Rpb24uaWR9IGJ1aWxkIHBhcmFtcyBub3QgZXhwYW5kZWRgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3Rva2VuIGJ1aWxkU2lnbkFuZFNlbmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNhbmRib3gudmVyaWZ5QW5kUmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCwgc2lnbiBhbmQgc2VuZCB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSAncGFzc3BocmFzZSc7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IGZpeHR1cmVzLnRyYW5zYWN0aW9uKCdSRUFEWScsIGZpeHR1cmVzLmJ1aWxkUGFyYW1zKTtcblxuICAgICAgLy8gQlVJTERcbiAgICAgIG5vY2sobWljcm9zZXJ2aWNlc1VyaSlcbiAgICAgICAgLmdldChcbiAgICAgICAgICBgL2FwaS9zdGFraW5nL3YxLyR7bWF0aWNTdGFraW5nV2FsbGV0LmNvaW59L3dhbGxldHMvJHttYXRpY1N0YWtpbmdXYWxsZXQud2FsbGV0SWR9L3JlcXVlc3RzLyR7dHJhbnNhY3Rpb24uc3Rha2luZ1JlcXVlc3RJZH0vdHJhbnNhY3Rpb25zLyR7dHJhbnNhY3Rpb24uaWR9YFxuICAgICAgICApXG4gICAgICAgIC5xdWVyeSh7IGV4cGFuZEJ1aWxkUGFyYW1zOiB0cnVlIH0pXG4gICAgICAgIC5yZXBseSgyMDAsIHRyYW5zYWN0aW9uKTtcblxuICAgICAgY29uc3QgcHJlYnVpbGRUcmFuc2FjdGlvbiA9IHNhbmRib3guc3R1YihXYWxsZXQucHJvdG90eXBlLCAncHJlYnVpbGRUcmFuc2FjdGlvbicpO1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgd2FsbGV0SWQ6IG1hdGljU3Rha2luZ1dhbGxldC53YWxsZXRJZCxcbiAgICAgICAgdHhIZXg6ICdoZXgnLFxuICAgICAgICBidWlsZFBhcmFtczogdHJhbnNhY3Rpb24uYnVpbGRQYXJhbXMsXG4gICAgICB9O1xuICAgICAgcHJlYnVpbGRUcmFuc2FjdGlvbi5yZXNvbHZlcyh0eFByZWJ1aWxkKTtcbiAgICAgIHByZWJ1aWxkVHJhbnNhY3Rpb24uY2FsbGVkT25jZVdpdGhFeGFjdGx5KHRyYW5zYWN0aW9uLmJ1aWxkUGFyYW1zKTtcblxuICAgICAgLy8gU0lHTlxuICAgICAgY29uc3QgZ2V0S2V5c0ZvclNpZ25pbmcgPSBzYW5kYm94LnN0dWIoS2V5Y2hhaW5zLnByb3RvdHlwZSwgJ2dldEtleXNGb3JTaWduaW5nJyk7XG4gICAgICBjb25zdCBrZXlDaGFpbjogS2V5Y2hhaW4gPSB7XG4gICAgICAgIGlkOiAnaWQnLFxuICAgICAgICBwdWI6ICdwdWInLFxuICAgICAgICB0eXBlOiAnaW5kZXBlbmRlbnQnLFxuICAgICAgfTtcbiAgICAgIGdldEtleXNGb3JTaWduaW5nLnJlc29sdmVzKFtrZXlDaGFpbl0pO1xuICAgICAgZ2V0S2V5c0ZvclNpZ25pbmcuY2FsbGVkT25jZTtcblxuICAgICAgY29uc3Qgc2lnblRyYW5zYWN0aW9uID0gc2FuZGJveC5zdHViKFdhbGxldC5wcm90b3R5cGUsICdzaWduVHJhbnNhY3Rpb24nKTtcbiAgICAgIGNvbnN0IHNpZ25lZCA9IHtcbiAgICAgICAgaGFsZlNpZ25lZDoge1xuICAgICAgICAgIHR4SGV4OiAnaGV4JyxcbiAgICAgICAgICBwYXlsb2FkOiAncGF5bG9hZCcsXG4gICAgICAgICAgdHhCYXNlNjQ6ICdiYXNlNjQnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICAgIHNpZ25UcmFuc2FjdGlvbi5yZXNvbHZlcyhzaWduZWQpO1xuICAgICAgc2lnblRyYW5zYWN0aW9uLmNhbGxlZE9uY2VXaXRoRXhhY3RseSh7XG4gICAgICAgIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIGtleWNoYWluOiBrZXlDaGFpbixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0eXBlID0gbWF0aWNTdGFraW5nV2FsbGV0LndhbGxldC5iYXNlQ29pbi50b2tlbkNvbmZpZz8udHlwZTtcbiAgICAgIGNvbnN0IGNvaW4gPSBtYXRpY1N0YWtpbmdXYWxsZXQud2FsbGV0LmJhc2VDb2luLnRva2VuQ29uZmlnPy5jb2luO1xuICAgICAgLy8gZ2V0IHdhbGxldCBmb3IgYnVpbGRpbmcgYW5kIHNpZ25pbmdcbiAgICAgIG5vY2sobWljcm9zZXJ2aWNlc1VyaSkuZ2V0KGAvYXBpL3YyLyR7Y29pbn0vd2FsbGV0LyR7bWF0aWNTdGFraW5nV2FsbGV0LndhbGxldElkfWApLnJlcGx5KDIwMCwgZXRoV2FsbGV0RGF0YSk7XG4gICAgICAvLyBTRU5EXG4gICAgICBub2NrKG1pY3Jvc2VydmljZXNVcmkpXG4gICAgICAgIC5wb3N0KFxuICAgICAgICAgIGAvYXBpL3N0YWtpbmcvdjEvJHt0eXBlfS93YWxsZXRzLyR7bWF0aWNTdGFraW5nV2FsbGV0LndhbGxldElkfS9yZXF1ZXN0cy8ke3RyYW5zYWN0aW9uLnN0YWtpbmdSZXF1ZXN0SWR9L3RyYW5zYWN0aW9ucy8ke3RyYW5zYWN0aW9uLmlkfWAsXG4gICAgICAgICAgXy5tYXRjaGVzKHNpZ25lZClcbiAgICAgICAgKVxuICAgICAgICAucmVwbHkoMjAwLCB0cmFuc2FjdGlvbik7XG5cbiAgICAgIC8vIHNraXBwaW5nIHZhbGlkYXRpb24gYmVjYXVzZSBtb2NrIGRhdGEgaXMgbm90IGEgdmFsaWQgdHJhbnNhY3Rpb25cbiAgICAgIHNpbm9uLnN0dWIoU3Rha2luZ1dhbGxldC5wcm90b3R5cGUsIDxhbnk+J3ZhbGlkYXRlQnVpbHRTdGFraW5nVHJhbnNhY3Rpb24nKS5yZXNvbHZlcygpO1xuICAgICAgY29uc3Qgc3Rha2luZ1RyYW5zYWN0aW9uID0gYXdhaXQgbWF0aWNTdGFraW5nV2FsbGV0LmJ1aWxkU2lnbkFuZFNlbmQoXG4gICAgICAgIHsgd2FsbGV0UGFzc3BocmFzZTogd2FsbGV0UGFzc3BocmFzZSB9LFxuICAgICAgICB0cmFuc2FjdGlvblxuICAgICAgKTtcblxuICAgICAgc3Rha2luZ1RyYW5zYWN0aW9uLnNob3VsZC5kZWVwRXF1YWwodHJhbnNhY3Rpb24pO1xuICAgICAgc2lub24ucmVzdG9yZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQlRDIHN0YWtpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ2J0YyBkZWxlZ2F0aW9uIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSBmaXh0dXJlcy50cmFuc2FjdGlvbignUkVBRFknLCBmaXh0dXJlcy5idWlsZFBhcmFtcywgZmFsc2UpO1xuXG4gICAgICBub2NrKG1pY3Jvc2VydmljZXNVcmkpXG4gICAgICAgIC5nZXQoXG4gICAgICAgICAgYC9hcGkvc3Rha2luZy92MS8ke2J0Y1N0YWtpbmdXYWxsZXQuY29pbn0vd2FsbGV0cy8ke2J0Y1N0YWtpbmdXYWxsZXQud2FsbGV0SWR9L3JlcXVlc3RzLyR7dHJhbnNhY3Rpb24uc3Rha2luZ1JlcXVlc3RJZH0vdHJhbnNhY3Rpb25zLyR7dHJhbnNhY3Rpb24uaWR9YFxuICAgICAgICApXG4gICAgICAgIC5xdWVyeSh7IGV4cGFuZEJ1aWxkUGFyYW1zOiB0cnVlIH0pXG4gICAgICAgIC5yZXBseSgyMDAsIHRyYW5zYWN0aW9uKTtcblxuICAgICAgY29uc3QgcHJlYnVpbGRUcmFuc2FjdGlvbiA9IHNhbmRib3guc3R1YihXYWxsZXQucHJvdG90eXBlLCAncHJlYnVpbGRUcmFuc2FjdGlvbicpO1xuICAgICAgY29uc3QgZGVzY3JpcHRvciA9IHNhbmRib3guc3R1YihTdGFraW5nV2FsbGV0LnByb3RvdHlwZSwgJ2dldERlc2NyaXB0b3JXYWxsZXQnIGFzIGFueSk7XG4gICAgICBhd2FpdCBidGNTdGFraW5nV2FsbGV0LmJ1aWxkKHRyYW5zYWN0aW9uKTtcbiAgICAgIHByZWJ1aWxkVHJhbnNhY3Rpb24uY2FsbGVkT25jZVdpdGhFeGFjdGx5KHRyYW5zYWN0aW9uLmJ1aWxkUGFyYW1zKS5zaG91bGQuYmUudHJ1ZTtcbiAgICAgIGRlc2NyaXB0b3Iubm90Q2FsbGVkLnNob3VsZC5iZS50cnVlO1xuICAgIH0pO1xuXG4gICAgaXQoJ2J0YyB1bmRlbGVnYXRpb24gdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IGZpeHR1cmVzLnRyYW5zYWN0aW9uKCdSRUFEWScsIGZpeHR1cmVzLmJ0Y1Vuc3Rha2luZ0J1aWxkUGFyYW1zLCBmYWxzZSwgJ3VuZGVsZWdhdGVfd2l0aGRyYXcnKTtcblxuICAgICAgbm9jayhtaWNyb3NlcnZpY2VzVXJpKVxuICAgICAgICAuZ2V0KFxuICAgICAgICAgIGAvYXBpL3N0YWtpbmcvdjEvJHtidGNTdGFraW5nV2FsbGV0LmNvaW59L3dhbGxldHMvJHtidGNTdGFraW5nV2FsbGV0LndhbGxldElkfS9yZXF1ZXN0cy8ke3RyYW5zYWN0aW9uLnN0YWtpbmdSZXF1ZXN0SWR9L3RyYW5zYWN0aW9ucy8ke3RyYW5zYWN0aW9uLmlkfWBcbiAgICAgICAgKVxuICAgICAgICAucXVlcnkoeyBleHBhbmRCdWlsZFBhcmFtczogdHJ1ZSB9KVxuICAgICAgICAucmVwbHkoMjAwLCB0cmFuc2FjdGlvbik7XG4gICAgICBub2NrKG1pY3Jvc2VydmljZXNVcmkpXG4gICAgICAgIC5nZXQoYC9hcGkvdjIvYnRjL3dhbGxldC8ke2J0Y0Rlc2NyaXB0b3JXYWxsZXREYXRhLmlkfWApXG4gICAgICAgIC5yZXBseSgyMDAsIGJ0Y0Rlc2NyaXB0b3JXYWxsZXREYXRhKTtcblxuICAgICAgY29uc3QgcHJlYnVpbGRUcmFuc2FjdGlvbiA9IHNhbmRib3guc3R1YihXYWxsZXQucHJvdG90eXBlLCAncHJlYnVpbGRUcmFuc2FjdGlvbicpO1xuICAgICAgYXdhaXQgYnRjU3Rha2luZ1dhbGxldC5idWlsZCh0cmFuc2FjdGlvbik7XG4gICAgICBwcmVidWlsZFRyYW5zYWN0aW9uLmNhbGxlZE9uY2VXaXRoRXhhY3RseSh0cmFuc2FjdGlvbi5idWlsZFBhcmFtcykuc2hvdWxkLmJlLnRydWU7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdPcGV0aDpXQ1QgU3Rha2luZycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHNraXAgdHJhbnNhY3Rpb24gdmFsaWRhdGlvbiB3aGVuIHNraXBUcmFuc2FjdGlvblZlcmlmaWNhdGlvbiBpcyB0cnVlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdW5zaWduZWRUcmFuc2FjdGlvbjogUHJlYnVpbGRUcmFuc2FjdGlvblJlc3VsdCA9IHtcbiAgICAgICAgd2FsbGV0SWQ6IHRvcGV0aFdjdFN0YWtpbmdXYWxsZXQud2FsbGV0SWQsXG4gICAgICAgIC4uLm9wZXRoRml4dHVyZXMudW5zaWduZWRTdGFraW5nVHJhbnNhY3Rpb24sXG4gICAgICAgIC8vIFVzaW5nIGEgbW9kaWZpZWQgdHhIZXggdGhhdCB3b3VsZCBub3JtYWxseSBjYXVzZSB2YWxpZGF0aW9uIHRvIGZhaWxcbiAgICAgICAgdHhIZXg6XG4gICAgICAgICAgJzB4MDJmOTAxOTA4M2FhMzdkYzcxODIwNmE4ODIwODllODMwMzBkNDA5NDFkMWEyNDU3NDFiZDdkNjAzNzQ3YTIzZDMwZjRjOTE2ODJhMjk5MjY4MGI5MDE2NDM5MTI1MjE1MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwODZiYjZkY2EyY2Q2ZjlhMDE4OWM0NzhiYmI4ZjdlZTJmZWYwN2M4OTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGMwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA2N2ViZWRjMzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA0NDA5NWVhN2IzMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTQwZDYzZWZiNWIyNDMxNGY2ZjYyZGJhZGIzODNkYmEyZTQ5ZDdlZTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBkZTBiNmIzYTc2NDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBjMDgwODA4MCcsXG4gICAgICB9IGFzIFByZWJ1aWxkVHJhbnNhY3Rpb25SZXN1bHQ7XG4gICAgICBjb25zdCBzdGFraW5nVHJhbnNhY3Rpb246IFN0YWtpbmdUcmFuc2FjdGlvbiA9IG9wZXRoRml4dHVyZXMudXBkYXRlZFN0YWtpbmdSZXF1ZXN0O1xuXG4gICAgICBub2NrKG1pY3Jvc2VydmljZXNVcmkpXG4gICAgICAgIC5nZXQoXG4gICAgICAgICAgYC9hcGkvc3Rha2luZy92MS8ke3RvcGV0aFdjdFN0YWtpbmdXYWxsZXQuY29pbn0vd2FsbGV0cy8ke3RvcGV0aFdjdFN0YWtpbmdXYWxsZXQud2FsbGV0SWR9L3JlcXVlc3RzLyR7c3Rha2luZ1RyYW5zYWN0aW9uLnN0YWtpbmdSZXF1ZXN0SWR9L3RyYW5zYWN0aW9ucy8ke3N0YWtpbmdUcmFuc2FjdGlvbi5pZH1gXG4gICAgICAgIClcbiAgICAgICAgLnF1ZXJ5KHsgZXhwYW5kQnVpbGRQYXJhbXM6IHRydWUgfSlcbiAgICAgICAgLnJlcGx5KDIwMCwgc3Rha2luZ1RyYW5zYWN0aW9uKTtcblxuICAgICAgbm9jayhtaWNyb3NlcnZpY2VzVXJpKVxuICAgICAgICAuZ2V0KGAvYXBpL3YyL3RvcGV0aC93YWxsZXQvJHt0b3BldGhXY3RTdGFraW5nV2FsbGV0LndhbGxldElkfWApXG4gICAgICAgIC5yZXBseSgyMDAsIHRvcGV0aFdjdFN0YWtpbmdXYWxsZXREYXRhKTtcblxuICAgICAgbm9jayhtaWNyb3NlcnZpY2VzVXJpKVxuICAgICAgICAucG9zdChgL2FwaS92Mi90b3BldGgvd2FsbGV0LyR7dG9wZXRoV2N0U3Rha2luZ1dhbGxldC53YWxsZXRJZH0vdHgvYnVpbGRgKVxuICAgICAgICAucmVwbHkoMjAwLCB1bnNpZ25lZFRyYW5zYWN0aW9uKTtcblxuICAgICAgLy8gTW9jayB0aGUgc2lnbiBtZXRob2QgdG8gdmVyaWZ5IHdlIHJlYWNoIGl0IHdpdGhvdXQgdmFsaWRhdGlvbiBlcnJvclxuICAgICAgY29uc3Qgc2lnblN0dWIgPSBzaW5vbi5zdHViKHRvcGV0aFdjdFN0YWtpbmdXYWxsZXQsICdzaWduJykucmVzb2x2ZXMoe1xuICAgICAgICB0cmFuc2FjdGlvbjogc3Rha2luZ1RyYW5zYWN0aW9uLFxuICAgICAgICBzaWduZWQ6IHsgaGFsZlNpZ25lZDogeyB0eEhleDogJ3NpZ25lZC1oZXgnIH0gfSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBNb2NrIHZhbGlkYXRlQnVpbHRTdGFraW5nVHJhbnNhY3Rpb24gdG8gdmVyaWZ5IGl0J3Mgbm90IGNhbGxlZFxuICAgICAgY29uc3QgdmFsaWRhdGVTdHViID0gc2lub24uc3R1YihTdGFraW5nV2FsbGV0LnByb3RvdHlwZSwgPGFueT4ndmFsaWRhdGVCdWlsdFN0YWtpbmdUcmFuc2FjdGlvbicpO1xuXG4gICAgICAvLyBDYWxsIGJ1aWxkQW5kU2lnbiB3aXRoIHNraXBUcmFuc2FjdGlvblZlcmlmaWNhdGlvbj10cnVlXG4gICAgICBhd2FpdCB0b3BldGhXY3RTdGFraW5nV2FsbGV0LmJ1aWxkQW5kU2lnbihcbiAgICAgICAge1xuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdwYXNzcGhyYXNlJyxcbiAgICAgICAgICB0cmFuc2FjdGlvblZlcmlmaWNhdGlvbk9wdGlvbnM6IHsgc2tpcFRyYW5zYWN0aW9uVmVyaWZpY2F0aW9uOiB0cnVlIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHN0YWtpbmdUcmFuc2FjdGlvblxuICAgICAgKTtcblxuICAgICAgLy8gVmVyaWZ5IHRoYXQgdmFsaWRhdGlvbiB3YXMgc2tpcHBlZFxuICAgICAgdmFsaWRhdGVTdHViLmNhbGxlZC5zaG91bGQuYmUuZmFsc2U7XG4gICAgICBzaWduU3R1Yi5jYWxsZWRPbmNlLnNob3VsZC5iZS50cnVlO1xuXG4gICAgICAvLyBSZXN0b3JlIHN0dWJzXG4gICAgICB2YWxpZGF0ZVN0dWIucmVzdG9yZSgpO1xuICAgICAgc2lnblN0dWIucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSBmb3IgaXNTZW5kQ2FsbFJlcXVpcmVkIGZvciB0b3BldGhXY3RTdGFraW5nV2FsbGV0JywgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gQWNjZXNzIHRoZSBwcml2YXRlIG1ldGhvZCB1c2luZyB0eXBlIGFzc2VydGlvblxuICAgICAgY29uc3QgaXNTZW5kQ2FsbFJlcXVpcmVkID0gKHRvcGV0aFdjdFN0YWtpbmdXYWxsZXQgYXMgYW55KS5pc1NlbmRDYWxsUmVxdWlyZWQoKTtcblxuICAgICAgLy8gQ2hlY2sgdGhhdCBpc1NlbmRDYWxsUmVxdWlyZWQgcmV0dXJucyB0cnVlIGJlY2F1c2UgdGhpcyBpcyBub3QgRVRIIFRTU1xuICAgICAgaXNTZW5kQ2FsbFJlcXVpcmVkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYW5kIHZhbGlkYXRlIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdW5zaWduZWRUcmFuc2FjdGlvbjogUHJlYnVpbGRUcmFuc2FjdGlvblJlc3VsdCA9IHtcbiAgICAgICAgd2FsbGV0SWQ6IHRvcGV0aFdjdFN0YWtpbmdXYWxsZXQud2FsbGV0SWQsXG4gICAgICAgIC4uLm9wZXRoRml4dHVyZXMudW5zaWduZWRTdGFraW5nVHJhbnNhY3Rpb24sXG4gICAgICB9IGFzIFByZWJ1aWxkVHJhbnNhY3Rpb25SZXN1bHQ7XG4gICAgICBjb25zdCBzdGFraW5nVHJhbnNhY3Rpb246IFN0YWtpbmdUcmFuc2FjdGlvbiA9IG9wZXRoRml4dHVyZXMudXBkYXRlZFN0YWtpbmdSZXF1ZXN0O1xuXG4gICAgICBub2NrKG1pY3Jvc2VydmljZXNVcmkpXG4gICAgICAgIC5nZXQoXG4gICAgICAgICAgYC9hcGkvc3Rha2luZy92MS8ke3RvcGV0aFdjdFN0YWtpbmdXYWxsZXQuY29pbn0vd2FsbGV0cy8ke3RvcGV0aFdjdFN0YWtpbmdXYWxsZXQud2FsbGV0SWR9L3JlcXVlc3RzLyR7c3Rha2luZ1RyYW5zYWN0aW9uLnN0YWtpbmdSZXF1ZXN0SWR9L3RyYW5zYWN0aW9ucy8ke3N0YWtpbmdUcmFuc2FjdGlvbi5pZH1gXG4gICAgICAgIClcbiAgICAgICAgLnF1ZXJ5KHsgZXhwYW5kQnVpbGRQYXJhbXM6IHRydWUgfSlcbiAgICAgICAgLnJlcGx5KDIwMCwgc3Rha2luZ1RyYW5zYWN0aW9uKTtcblxuICAgICAgbm9jayhtaWNyb3NlcnZpY2VzVXJpKVxuICAgICAgICAuZ2V0KGAvYXBpL3YyL3RvcGV0aC93YWxsZXQvJHt0b3BldGhXY3RTdGFraW5nV2FsbGV0LndhbGxldElkfWApXG4gICAgICAgIC5yZXBseSgyMDAsIHRvcGV0aFdjdFN0YWtpbmdXYWxsZXREYXRhKTtcblxuICAgICAgbm9jayhtaWNyb3NlcnZpY2VzVXJpKVxuICAgICAgICAucG9zdChgL2FwaS92Mi90b3BldGgvd2FsbGV0LyR7dG9wZXRoV2N0U3Rha2luZ1dhbGxldC53YWxsZXRJZH0vdHgvYnVpbGRgKVxuICAgICAgICAucmVwbHkoMjAwLCB1bnNpZ25lZFRyYW5zYWN0aW9uKTtcblxuICAgICAgLy8gdHggdmFsaWRhdGlvbiBoYXBwZW5zIGJlZm9yZSBzaWduaW5nLCBzbyB3ZSBjYW4gc2tpcCBpdFxuICAgICAgc2lub24uc3R1Yih0b3BldGhXY3RTdGFraW5nV2FsbGV0LCAnc2lnbicpLnJlc29sdmVzKCk7XG5cbiAgICAgIGF3YWl0IHRvcGV0aFdjdFN0YWtpbmdXYWxsZXQuYnVpbGRBbmRTaWduKHsgd2FsbGV0UGFzc3BocmFzZTogJ3Bhc3NwaHJhc2UnIH0sIHN0YWtpbmdUcmFuc2FjdGlvbik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGFuIGVycm9yIGlmIHVuc2lnbmVkIHRyYW5zYWN0aW9uIGRvZXMgbm90IG1hdGNoIHRoZSBzdGFraW5nIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdW5zaWduZWRUcmFuc2FjdGlvbjogUHJlYnVpbGRUcmFuc2FjdGlvblJlc3VsdCA9IHtcbiAgICAgICAgd2FsbGV0SWQ6IHRvcGV0aFdjdFN0YWtpbmdXYWxsZXQud2FsbGV0SWQsXG4gICAgICAgIC4uLm9wZXRoRml4dHVyZXMudW5zaWduZWRTdGFraW5nVHJhbnNhY3Rpb24sXG4gICAgICAgIHR4SGV4OlxuICAgICAgICAgICcweDAyZjkwMTkwODNhYTM3ZGM3MTgyMDZhODgyMDg5ZTgzMDMwZDQwOTQxZDFhMjQ1NzQxYmQ3ZDYwMzc0N2EyM2QzMGY0YzkxNjgyYTI5OTI2ODBiOTAxNjQzOTEyNTIxNTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDg2YmI2ZGNhMmNkNmY5YTAxODljNDc4YmJiOGY3ZWUyZmVmMDdjODkwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBjMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNjdlYmVkYzMwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA2MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDE0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNDQwOTVlYTdiMzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDE0MGQ2M2VmYjViMjQzMTRmNmY2MmRiYWRiMzgzZGJhMmU0OWQ3ZWUwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwZGUwYjZiM2E3NjQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwYzA4MDgwODAnLFxuICAgICAgfSBhcyBQcmVidWlsZFRyYW5zYWN0aW9uUmVzdWx0O1xuICAgICAgY29uc3Qgc3Rha2luZ1RyYW5zYWN0aW9uOiBTdGFraW5nVHJhbnNhY3Rpb24gPSBvcGV0aEZpeHR1cmVzLnVwZGF0ZWRTdGFraW5nUmVxdWVzdDtcblxuICAgICAgbm9jayhtaWNyb3NlcnZpY2VzVXJpKVxuICAgICAgICAuZ2V0KFxuICAgICAgICAgIGAvYXBpL3N0YWtpbmcvdjEvJHt0b3BldGhXY3RTdGFraW5nV2FsbGV0LmNvaW59L3dhbGxldHMvJHt0b3BldGhXY3RTdGFraW5nV2FsbGV0LndhbGxldElkfS9yZXF1ZXN0cy8ke3N0YWtpbmdUcmFuc2FjdGlvbi5zdGFraW5nUmVxdWVzdElkfS90cmFuc2FjdGlvbnMvJHtzdGFraW5nVHJhbnNhY3Rpb24uaWR9YFxuICAgICAgICApXG4gICAgICAgIC5xdWVyeSh7IGV4cGFuZEJ1aWxkUGFyYW1zOiB0cnVlIH0pXG4gICAgICAgIC5yZXBseSgyMDAsIHN0YWtpbmdUcmFuc2FjdGlvbik7XG5cbiAgICAgIG5vY2sobWljcm9zZXJ2aWNlc1VyaSlcbiAgICAgICAgLmdldChgL2FwaS92Mi90b3BldGgvd2FsbGV0LyR7dG9wZXRoV2N0U3Rha2luZ1dhbGxldC53YWxsZXRJZH1gKVxuICAgICAgICAucmVwbHkoMjAwLCB0b3BldGhXY3RTdGFraW5nV2FsbGV0RGF0YSk7XG5cbiAgICAgIG5vY2sobWljcm9zZXJ2aWNlc1VyaSlcbiAgICAgICAgLnBvc3QoYC9hcGkvdjIvdG9wZXRoL3dhbGxldC8ke3RvcGV0aFdjdFN0YWtpbmdXYWxsZXQud2FsbGV0SWR9L3R4L2J1aWxkYClcbiAgICAgICAgLnJlcGx5KDIwMCwgdW5zaWduZWRUcmFuc2FjdGlvbik7XG5cbiAgICAgIGNvbnN0IGV4cGVjdGVkRXJyb3JNZXNzYWdlID1cbiAgICAgICAgJ1N0YWtpbmcgdHJhbnNhY3Rpb24gdmFsaWRhdGlvbiBmYWlsZWQgYmVmb3JlIHNpZ25pbmc6ICcgK1xuICAgICAgICAnVW5leHBlY3RlZCByZWNpcGllbnQgYWRkcmVzcyBmb3VuZCBpbiBidWlsdCB0cmFuc2FjdGlvbjogMHg4NmJiNmRjYTJjZDZmOWEwMTg5YzQ3OGJiYjhmN2VlMmZlZjA3Yzg5OyAnICtcbiAgICAgICAgJ0V4cGVjdGVkIHJlY2lwaWVudCBhZGRyZXNzIG5vdCBmb3VuZCBpbiBidWlsdCB0cmFuc2FjdGlvbjogMHg3NWJiNmRjYTJjZDZmOWEwMTg5YzQ3OGJiYjhmN2VlMmZlZjA3Yzc4JztcblxuICAgICAgYXdhaXQgdG9wZXRoV2N0U3Rha2luZ1dhbGxldFxuICAgICAgICAuYnVpbGRBbmRTaWduKHsgd2FsbGV0UGFzc3BocmFzZTogJ3Bhc3NwaHJhc2UnIH0sIHN0YWtpbmdUcmFuc2FjdGlvbilcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoZXhwZWN0ZWRFcnJvck1lc3NhZ2UpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVEFWQVhQIFN0YWtpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhbmQgdmFsaWRhdGUgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB1bnNpZ25lZFRyYW5zYWN0aW9uOiBQcmVidWlsZFRyYW5zYWN0aW9uUmVzdWx0ID0ge1xuICAgICAgICB3YWxsZXRJZDogdGF2YXhwU3Rha2luZ1dhbGxldC53YWxsZXRJZCxcbiAgICAgICAgLi4uYXZheHBTdGFraW5nRml4dHVyZXMudW5zaWduZWRTdGFraW5nVHJhbnNhY3Rpb24sXG4gICAgICB9IGFzIFByZWJ1aWxkVHJhbnNhY3Rpb25SZXN1bHQ7XG4gICAgICBjb25zdCBzdGFraW5nVHJhbnNhY3Rpb246IFN0YWtpbmdUcmFuc2FjdGlvbiA9IGF2YXhwU3Rha2luZ0ZpeHR1cmVzLnVwZGF0ZWRTdGFraW5nUmVxdWVzdDtcblxuICAgICAgbm9jayhtaWNyb3NlcnZpY2VzVXJpKVxuICAgICAgICAuZ2V0KFxuICAgICAgICAgIGAvYXBpL3N0YWtpbmcvdjEvJHt0YXZheHBTdGFraW5nV2FsbGV0LmNvaW59L3dhbGxldHMvJHt0YXZheHBTdGFraW5nV2FsbGV0LndhbGxldElkfS9yZXF1ZXN0cy8ke3N0YWtpbmdUcmFuc2FjdGlvbi5zdGFraW5nUmVxdWVzdElkfS90cmFuc2FjdGlvbnMvJHtzdGFraW5nVHJhbnNhY3Rpb24uaWR9YFxuICAgICAgICApXG4gICAgICAgIC5xdWVyeSh7IGV4cGFuZEJ1aWxkUGFyYW1zOiB0cnVlIH0pXG4gICAgICAgIC5yZXBseSgyMDAsIHN0YWtpbmdUcmFuc2FjdGlvbik7XG5cbiAgICAgIG5vY2sobWljcm9zZXJ2aWNlc1VyaSlcbiAgICAgICAgLmdldChgL2FwaS92Mi90YXZheHAvd2FsbGV0LyR7dGF2YXhwU3Rha2luZ1dhbGxldC53YWxsZXRJZH1gKVxuICAgICAgICAucmVwbHkoMjAwLCB0YXZheHBTdGFraW5nV2FsbGV0RGF0YSk7XG5cbiAgICAgIG5vY2sobWljcm9zZXJ2aWNlc1VyaSlcbiAgICAgICAgLnBvc3QoYC9hcGkvdjIvdGF2YXhwL3dhbGxldC8ke3RhdmF4cFN0YWtpbmdXYWxsZXQud2FsbGV0SWR9L3R4L2J1aWxkYClcbiAgICAgICAgLnJlcGx5KDIwMCwgdW5zaWduZWRUcmFuc2FjdGlvbik7XG5cbiAgICAgIC8vIHR4IHZhbGlkYXRpb24gaGFwcGVucyBiZWZvcmUgc2lnbmluZywgc28gd2UgY2FuIHNraXAgaXRcbiAgICAgIHNpbm9uLnN0dWIodGF2YXhwU3Rha2luZ1dhbGxldCwgJ3NpZ24nKS5yZXNvbHZlcygpO1xuXG4gICAgICBhd2FpdCB0YXZheHBTdGFraW5nV2FsbGV0LmJ1aWxkQW5kU2lnbih7IHdhbGxldFBhc3NwaHJhc2U6ICdwYXNzcGhyYXNlJyB9LCBzdGFraW5nVHJhbnNhY3Rpb24pO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19