PHP WebShell

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

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

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const crypto_1 = __importDefault(require("crypto"));
const statics_1 = require("@bitgo/statics");
const algosdk_1 = __importDefault(require("algosdk"));
const assert_1 = __importDefault(require("assert"));
const should_1 = __importDefault(require("should"));
const sinon_1 = __importStar(require("sinon"));
const lib_1 = require("../../../../src/lib");
const AlgoResources = __importStar(require("../../../fixtures/resources"));
const STANDARD_REQUIRED_NUMBER_OF_SIGNERS = 2;
class StubTransactionBuilder extends lib_1.TransactionBuilder {
    constructor(coinConfig) {
        super(coinConfig);
    }
    getFee() {
        return this._fee;
    }
    getSender() {
        return this._sender;
    }
    getGenesisHash() {
        return this._genesisHash;
    }
    getGenesisId() {
        return this._genesisId;
    }
    getFirstRound() {
        return this._firstRound;
    }
    getLastRound() {
        return this._lastRound;
    }
    getLease() {
        return this._lease;
    }
    getNote() {
        return this._note;
    }
    getReKeyTo() {
        return this._reKeyTo;
    }
    getKeyPairs() {
        return this._keyPairs;
    }
    getTransaction() {
        return this._transaction;
    }
    buildImplementation() {
        return super.buildImplementation();
    }
    fromImplementation(rawTransaction) {
        return super.fromImplementation(rawTransaction);
    }
    signImplementation(key) {
        return super.signImplementation(key);
    }
    getSuggestedParams() {
        return this.suggestedParams;
    }
    buildAlgoTxn() {
        throw new Error('Method not implemented.');
    }
    get transactionType() {
        throw new Error('Method not implemented.');
    }
}
describe('Algo Transaction Builder', () => {
    let txnBuilder;
    const { accounts: { account1, account2, account3 }, networks: { testnet }, } = AlgoResources;
    beforeEach(() => {
        const config = statics_1.coins.get('algo');
        txnBuilder = new StubTransactionBuilder(config);
    });
    describe('setter validation', () => {
        it('should validate fee is not lt 1000 microalgos if flat fee is set to true', () => {
            txnBuilder.isFlatFee(true);
            assert_1.default.throws(() => txnBuilder.fee({ fee: '999' }), (e) => e.name === lib_1.InsufficientFeeError.name);
            should_1.default.doesNotThrow(() => txnBuilder.fee({ fee: '1000' }));
        });
        it('should validate sender address is a valid algo address', () => {
            const spy = sinon_1.default.spy(txnBuilder, 'validateAddress');
            assert_1.default.throws(() => txnBuilder.sender({ address: 'asdf' }), (e) => e.name === lib_1.AddressValidationError.name);
            should_1.default.doesNotThrow(() => txnBuilder.sender({ address: account1.address }));
            sinon_1.assert.calledTwice(spy);
        });
        it('should validate number of signers is not less than 0', () => {
            assert_1.default.throws(() => txnBuilder.numberOfRequiredSigners(-1), /Number of signers: '-1' cannot be negative/);
            for (let i = 0; i < STANDARD_REQUIRED_NUMBER_OF_SIGNERS; i++) {
                should_1.default.doesNotThrow(() => txnBuilder.numberOfRequiredSigners(i));
            }
        });
    });
    describe('suggested params verification', () => {
        it('should retrieve the suggested parameters as they have been set', () => {
            const isFlatFee = true;
            const fee = 1000;
            const firstRound = 1;
            const lastRound = 10;
            const genesisId = 'testnet-v1.0';
            const genesisHash = 'SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=';
            txnBuilder
                .isFlatFee(isFlatFee)
                .fee({ fee: fee.toString() })
                .firstRound(firstRound)
                .lastRound(lastRound)
                .genesisId(genesisId)
                .genesisHash(genesisHash);
            const suggestedParams = txnBuilder.getSuggestedParams();
            should_1.default.equal(isFlatFee, suggestedParams.flatFee);
            should_1.default.equal(fee, suggestedParams.fee);
            should_1.default.equal(firstRound, suggestedParams.firstRound);
            should_1.default.equal(lastRound, suggestedParams.lastRound);
            should_1.default.equal(genesisId, suggestedParams.genesisID);
            should_1.default.equal(genesisHash, suggestedParams.genesisHash);
        });
    });
    describe('private key validation', () => {
        it('validates byte arrays', () => {
            should_1.default.doesNotThrow(() => txnBuilder.validateKey({ key: account1.secretKey }));
        });
        it('validates hex encoded strings', () => {
            should_1.default.doesNotThrow(() => txnBuilder.validateKey({ key: account1.secretKey.toString('hex') }));
        });
        it('validates base64 encoded strings', () => {
            should_1.default.doesNotThrow(() => txnBuilder.validateKey({ key: account1.secretKey.toString('base64') }));
        });
    });
    describe('implementation functions', () => {
        const to = account1.address;
        const from = account2.address;
        const reKeyTo = account3.address;
        const amount = 1000;
        const firstRound = 1;
        const lastRound = 10;
        const closeRemainderTo = account3.address;
        // Uint8array conversion required because algosdk checks if the constructor
        // is Uint8Array.
        const lease = new Uint8Array(crypto_1.default.randomBytes(32));
        const note = new Uint8Array(Buffer.from('note', 'utf-8'));
        const fee = 1000;
        const algoTxn = algosdk_1.default.makePaymentTxnWithSuggestedParams(from, to, amount, closeRemainderTo, note, {
            fee,
            flatFee: true,
            firstRound,
            lastRound,
            genesisID: testnet.genesisID,
            genesisHash: testnet.genesisHash,
        }, reKeyTo);
        algoTxn.fee = fee;
        algoTxn.flatFee = true;
        algoTxn.addLease(lease);
        it('should assign all decoded fields into transaction builder', () => {
            txnBuilder.fromImplementation(algosdk_1.default.encodeUnsignedTransaction(algoTxn));
            (0, should_1.default)(txnBuilder.getFee()).equal(fee);
            (0, should_1.default)(txnBuilder.getSender()).equal(from);
            (0, should_1.default)(txnBuilder.getGenesisHash()).equal(testnet.genesisHash);
            (0, should_1.default)(txnBuilder.getGenesisId()).equal(testnet.genesisID);
            (0, should_1.default)(txnBuilder.getFirstRound()).equal(firstRound);
            (0, should_1.default)(txnBuilder.getLastRound()).equal(lastRound);
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            (0, should_1.default)(Buffer.from(txnBuilder.getLease()).toString('hex')).equal(Buffer.from(lease).toString('hex'));
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            (0, should_1.default)(Buffer.from(txnBuilder.getNote()).toString('hex')).equal(Buffer.from(note).toString('hex'));
            (0, should_1.default)(txnBuilder.getReKeyTo()).equal(reKeyTo);
            (0, should_1.default)(txnBuilder.getTransaction().getAlgoTransaction()).not.be.undefined();
        });
        it('should assign signers into transaction builder', () => {
            sinon_1.default.stub(lib_1.algoUtils, 'decodeAlgoTxn').callsFake((txnBytes) => {
                return {
                    rawTransaction: Buffer.from([]),
                    signed: true,
                    signers: [
                        '25NJQAMCWEFLPVKL73J4SZAHHIHOC4XT3KTCGJNPAINGR5YHKENMEF5QTE',
                        '7RI43DTCDCQ2HDNEP3IAEMHQLAEBN3ITXIZQHLC55OIRKSEQQAS52OYKJE',
                    ],
                    txn: algoTxn,
                };
            });
            txnBuilder.fromImplementation(algosdk_1.default.encodeUnsignedTransaction(algoTxn));
            (0, should_1.default)(txnBuilder.getTransaction().signers).deepEqual([
                '25NJQAMCWEFLPVKL73J4SZAHHIHOC4XT3KTCGJNPAINGR5YHKENMEF5QTE',
                '7RI43DTCDCQ2HDNEP3IAEMHQLAEBN3ITXIZQHLC55OIRKSEQQAS52OYKJE',
            ]);
            sinon_1.default.restore();
        });
        it('transaction builder should fail when signers are incorrect', () => {
            sinon_1.default.stub(lib_1.algoUtils, 'decodeAlgoTxn').callsFake((txnBytes) => {
                return {
                    rawTransaction: Buffer.from([]),
                    signed: true,
                    signers: [
                        '25NJQAMCWEFLPVKL73J4SZAHHIHOC4XT3KTCGJNPAINGR5YHKENMEF5AAA',
                        '7RI43DTCDCQ2HDNEP3IAEMHQLAEBN3ITXIZQHLC55OIRKSEQQAS52OYKJE',
                    ],
                    txn: algoTxn,
                };
            });
            (0, should_1.default)(() => txnBuilder.fromImplementation(algosdk_1.default.encodeUnsignedTransaction(algoTxn))).throw("The address '25NJQAMCWEFLPVKL73J4SZAHHIHOC4XT3KTCGJNPAINGR5YHKENMEF5AAA' is not a well-formed algorand address");
            sinon_1.default.restore();
        });
        it('should not sign the transaction', () => {
            const txn = txnBuilder.getTransaction();
            txn.setAlgoTransaction(algoTxn);
            txn.setNumberOfRequiredSigners(1);
            assert_1.default.throws(() => txnBuilder.signImplementation({ key: Buffer.from(account1.prvKey).toString('hex') }), new RegExp('Invalid base32 characters'));
        });
        it('should sign the transaction', () => {
            const { prv, pub } = new lib_1.KeyPair().recordKeysFromPrivateKeyInProtocolFormat(account1.prvKey);
            const prvKey = lib_1.algoUtils.encodeSeed(Buffer.from(prv + pub));
            const txn = txnBuilder.getTransaction();
            txn.setAlgoTransaction(algoTxn);
            txn.setNumberOfRequiredSigners(1);
            should_1.default.doesNotThrow(() => txnBuilder.signImplementation({ key: prvKey }));
        });
    });
    describe('transaction validation', () => {
        it('should validate a normal transaction', () => {
            txnBuilder
                .fee({ fee: '1000' })
                .isFlatFee(true)
                .firstRound(1)
                .lastRound(10)
                .sender({ address: account1.address })
                .genesisId(testnet.genesisID)
                .genesisHash(testnet.genesisHash);
            should_1.default.doesNotThrow(() => txnBuilder.validateTransaction(txnBuilder.getTransaction()));
        });
        it('should validate last round is after first round', () => {
            txnBuilder
                .fee({ fee: '1000' })
                .isFlatFee(true)
                .firstRound(10)
                .lastRound(1)
                .sender({ address: account1.address })
                .genesisId(testnet.genesisID)
                .genesisHash(testnet.genesisHash);
            assert_1.default.throws(() => txnBuilder.validateTransaction(txnBuilder.getTransaction()), new RegExp('Transaction validation failed: "value" failed custom validation because lastRound cannot be greater than or equal to firstRound'));
        });
        it('should build a normal transaction with correct signers', () => {
            txnBuilder
                .fee({ fee: '1000' })
                .isFlatFee(true)
                .firstRound(1)
                .lastRound(10)
                .sender({ address: account1.address })
                .setSigners([
                '25NJQAMCWEFLPVKL73J4SZAHHIHOC4XT3KTCGJNPAINGR5YHKENMEF5QTE',
                '7RI43DTCDCQ2HDNEP3IAEMHQLAEBN3ITXIZQHLC55OIRKSEQQAS52OYKJE',
            ])
                .genesisId(testnet.genesisID)
                .genesisHash(testnet.genesisHash);
            (0, should_1.default)(txnBuilder.getTransaction().signers).deepEqual([
                '25NJQAMCWEFLPVKL73J4SZAHHIHOC4XT3KTCGJNPAINGR5YHKENMEF5QTE',
                '7RI43DTCDCQ2HDNEP3IAEMHQLAEBN3ITXIZQHLC55OIRKSEQQAS52OYKJE',
            ]);
        });
        it('should not build a normal transaction with incorrect signers', () => {
            (0, should_1.default)(() => txnBuilder
                .fee({ fee: '1000' })
                .isFlatFee(true)
                .firstRound(1)
                .lastRound(10)
                .sender({ address: account1.address })
                .setSigners([
                '25NJQAMCWEFLPVKL73J4SZAHHIHOC4XT3KTCGJNPAINGR5YHKENMEF5AAA',
                '7RI43DTCDCQ2HDNEP3IAEMHQLAEBN3ITXIZQHLC55OIRKSEQQAS52OYKJE',
            ])
                .genesisId(testnet.genesisID)
                .genesisHash(testnet.genesisHash)).throw("The address '25NJQAMCWEFLPVKL73J4SZAHHIHOC4XT3KTCGJNPAINGR5YHKENMEF5AAA' is not a well-formed algorand address");
        });
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Rlc3QvdW5pdC9saWIvdHJhbnNhY3Rpb25CdWlsZGVyL2Jhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxvREFBNEI7QUFDNUIsNENBQStEO0FBQy9ELHNEQUE4QjtBQUM5QixvREFBNEI7QUFDNUIsb0RBQTRCO0FBQzVCLCtDQUFxRDtBQUNyRCw2Q0FNNkI7QUFHN0IsMkVBQTZEO0FBSTdELE1BQU0sbUNBQW1DLEdBQUcsQ0FBQyxDQUFDO0FBRTlDLE1BQU0sc0JBQXVCLFNBQVEsd0JBQWtCO0lBQ3JELFlBQVksVUFBZ0M7UUFDMUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3BCLENBQUM7SUFFRCxNQUFNO1FBQ0osT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDO0lBQ25CLENBQUM7SUFFRCxTQUFTO1FBQ1AsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3RCLENBQUM7SUFFRCxjQUFjO1FBQ1osT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQzNCLENBQUM7SUFFRCxZQUFZO1FBQ1YsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDO0lBQ3pCLENBQUM7SUFFRCxhQUFhO1FBQ1gsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDO0lBQzFCLENBQUM7SUFFRCxZQUFZO1FBQ1YsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDO0lBQ3pCLENBQUM7SUFFRCxRQUFRO1FBQ04sT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3JCLENBQUM7SUFFRCxPQUFPO1FBQ0wsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3BCLENBQUM7SUFFRCxVQUFVO1FBQ1IsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxXQUFXO1FBQ1QsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFD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R0FBRyxFQUFFLENBQ1YsVUFBVTtpQkFDUCxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLENBQUM7aUJBQ3BCLFNBQVMsQ0FBQyxJQUFJLENBQUM7aUJBQ2YsVUFBVSxDQUFDLENBQUMsQ0FBQztpQkFDYixTQUFTLENBQUMsRUFBRSxDQUFDO2lCQUNiLE1BQU0sQ0FBQyxFQUFFLE9BQU8sRUFBRSxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7aUJBQ3JDLFVBQVUsQ0FBQztnQkFDViw0REFBNEQ7Z0JBQzVELDREQUE0RDthQUM3RCxDQUFDO2lCQUNELFNBQVMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDO2lCQUM1QixXQUFXLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUNwQyxDQUFDLEtBQUssQ0FDTCxnSEFBZ0gsQ0FDakgsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjcnlwdG8gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB7IEJhc2VDb2luIGFzIENvaW5Db25maWcsIGNvaW5zIH0gZnJvbSAnQGJpdGdvL3N0YXRpY3MnO1xuaW1wb3J0IGFsZ29zZGsgZnJvbSAnYWxnb3Nkayc7XG5pbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgc2hvdWxkIGZyb20gJ3Nob3VsZCc7XG5pbXBvcnQgc2lub24sIHsgYXNzZXJ0IGFzIFNpbm9uQXNzZXJ0IH0gZnJvbSAnc2lub24nO1xuaW1wb3J0IHtcbiAgQWRkcmVzc1ZhbGlkYXRpb25FcnJvcixcbiAgSW5zdWZmaWNpZW50RmVlRXJyb3IsXG4gIEtleVBhaXIsXG4gIFRyYW5zYWN0aW9uQnVpbGRlcixcbiAgYWxnb1V0aWxzLFxufSBmcm9tICcuLi8uLi8uLi8uLi9zcmMvbGliJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uIH0gZnJvbSAnLi4vLi4vLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbic7XG5cbmltcG9ydCAqIGFzIEFsZ29SZXNvdXJjZXMgZnJvbSAnLi4vLi4vLi4vZml4dHVyZXMvcmVzb3VyY2VzJztcbmltcG9ydCB7IEJhc2VLZXksIFRyYW5zYWN0aW9uVHlwZSB9IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBFbmNvZGVkVHggfSBmcm9tICcuLi8uLi8uLi8uLi9zcmMvbGliL2lmYWNlcyc7XG5cbmNvbnN0IFNUQU5EQVJEX1JFUVVJUkVEX05VTUJFUl9PRl9TSUdORVJTID0gMjtcblxuY2xhc3MgU3R1YlRyYW5zYWN0aW9uQnVpbGRlciBleHRlbmRzIFRyYW5zYWN0aW9uQnVpbGRlciB7XG4gIGNvbnN0cnVjdG9yKGNvaW5Db25maWc6IFJlYWRvbmx5PENvaW5Db25maWc+KSB7XG4gICAgc3VwZXIoY29pbkNvbmZpZyk7XG4gIH1cblxuICBnZXRGZWUoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fZmVlO1xuICB9XG5cbiAgZ2V0U2VuZGVyKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX3NlbmRlcjtcbiAgfVxuXG4gIGdldEdlbmVzaXNIYXNoKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2dlbmVzaXNIYXNoO1xuICB9XG5cbiAgZ2V0R2VuZXNpc0lkKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2dlbmVzaXNJZDtcbiAgfVxuXG4gIGdldEZpcnN0Um91bmQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fZmlyc3RSb3VuZDtcbiAgfVxuXG4gIGdldExhc3RSb3VuZCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9sYXN0Um91bmQ7XG4gIH1cblxuICBnZXRMZWFzZSgpOiBVaW50OEFycmF5IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fbGVhc2U7XG4gIH1cblxuICBnZXROb3RlKCk6IFVpbnQ4QXJyYXkgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9ub3RlO1xuICB9XG5cbiAgZ2V0UmVLZXlUbygpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9yZUtleVRvO1xuICB9XG5cbiAgZ2V0S2V5UGFpcnMoKTogS2V5UGFpcltdIHtcbiAgICByZXR1cm4gdGhpcy5fa2V5UGFpcnM7XG4gIH1cblxuICBnZXRUcmFuc2FjdGlvbigpOiBUcmFuc2FjdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuX3RyYW5zYWN0aW9uO1xuICB9XG5cbiAgYnVpbGRJbXBsZW1lbnRhdGlvbigpOiBQcm9taXNlPFRyYW5zYWN0aW9uPiB7XG4gICAgcmV0dXJuIHN1cGVyLmJ1aWxkSW1wbGVtZW50YXRpb24oKTtcbiAgfVxuXG4gIGZyb21JbXBsZW1lbnRhdGlvbihyYXdUcmFuc2FjdGlvbjogVWludDhBcnJheSB8IHN0cmluZyk6IFRyYW5zYWN0aW9uIHtcbiAgICByZXR1cm4gc3VwZXIuZnJvbUltcGxlbWVudGF0aW9uKHJhd1RyYW5zYWN0aW9uKTtcbiAgfVxuXG4gIHNpZ25JbXBsZW1lbnRhdGlvbihrZXk6IEJhc2VLZXkpOiBUcmFuc2FjdGlvbiB7XG4gICAgcmV0dXJuIHN1cGVyLnNpZ25JbXBsZW1lbnRhdGlvbihrZXkpO1xuICB9XG5cbiAgZ2V0U3VnZ2VzdGVkUGFyYW1zKCk6IGFsZ29zZGsuU3VnZ2VzdGVkUGFyYW1zIHtcbiAgICByZXR1cm4gdGhpcy5zdWdnZXN0ZWRQYXJhbXM7XG4gIH1cblxuICBwcm90ZWN0ZWQgYnVpbGRBbGdvVHhuKCk6IGFsZ29zZGsuVHJhbnNhY3Rpb24ge1xuICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgfVxuICBwcm90ZWN0ZWQgZ2V0IHRyYW5zYWN0aW9uVHlwZSgpOiBUcmFuc2FjdGlvblR5cGUge1xuICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgfVxufVxuXG5kZXNjcmliZSgnQWxnbyBUcmFuc2FjdGlvbiBCdWlsZGVyJywgKCkgPT4ge1xuICBsZXQgdHhuQnVpbGRlcjogU3R1YlRyYW5zYWN0aW9uQnVpbGRlcjtcbiAgY29uc3Qge1xuICAgIGFjY291bnRzOiB7IGFjY291bnQxLCBhY2NvdW50MiwgYWNjb3VudDMgfSxcbiAgICBuZXR3b3JrczogeyB0ZXN0bmV0IH0sXG4gIH0gPSBBbGdvUmVzb3VyY2VzO1xuXG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIGNvbnN0IGNvbmZpZyA9IGNvaW5zLmdldCgnYWxnbycpO1xuICAgIHR4bkJ1aWxkZXIgPSBuZXcgU3R1YlRyYW5zYWN0aW9uQnVpbGRlcihjb25maWcpO1xuICB9KTtcblxuICBkZXNjcmliZSgnc2V0dGVyIHZhbGlkYXRpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCB2YWxpZGF0ZSBmZWUgaXMgbm90IGx0IDEwMDAgbWljcm9hbGdvcyBpZiBmbGF0IGZlZSBpcyBzZXQgdG8gdHJ1ZScsICgpID0+IHtcbiAgICAgIHR4bkJ1aWxkZXIuaXNGbGF0RmVlKHRydWUpO1xuXG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PiB0eG5CdWlsZGVyLmZlZSh7IGZlZTogJzk5OScgfSksXG4gICAgICAgIChlOiBFcnJvcikgPT4gZS5uYW1lID09PSBJbnN1ZmZpY2llbnRGZWVFcnJvci5uYW1lXG4gICAgICApO1xuICAgICAgc2hvdWxkLmRvZXNOb3RUaHJvdygoKSA9PiB0eG5CdWlsZGVyLmZlZSh7IGZlZTogJzEwMDAnIH0pKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgc2VuZGVyIGFkZHJlc3MgaXMgYSB2YWxpZCBhbGdvIGFkZHJlc3MnLCAoKSA9PiB7XG4gICAgICBjb25zdCBzcHkgPSBzaW5vbi5zcHkodHhuQnVpbGRlciwgJ3ZhbGlkYXRlQWRkcmVzcycpO1xuICAgICAgYXNzZXJ0LnRocm93cyhcbiAgICAgICAgKCkgPT4gdHhuQnVpbGRlci5zZW5kZXIoeyBhZGRyZXNzOiAnYXNkZicgfSksXG4gICAgICAgIChlOiBFcnJvcikgPT4gZS5uYW1lID09PSBBZGRyZXNzVmFsaWRhdGlvbkVycm9yLm5hbWVcbiAgICAgICk7XG4gICAgICBzaG91bGQuZG9lc05vdFRocm93KCgpID0+IHR4bkJ1aWxkZXIuc2VuZGVyKHsgYWRkcmVzczogYWNjb3VudDEuYWRkcmVzcyB9KSk7XG4gICAgICBTaW5vbkFzc2VydC5jYWxsZWRUd2ljZShzcHkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2YWxpZGF0ZSBudW1iZXIgb2Ygc2lnbmVycyBpcyBub3QgbGVzcyB0aGFuIDAnLCAoKSA9PiB7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IHR4bkJ1aWxkZXIubnVtYmVyT2ZSZXF1aXJlZFNpZ25lcnMoLTEpLCAvTnVtYmVyIG9mIHNpZ25lcnM6ICctMScgY2Fubm90IGJlIG5lZ2F0aXZlLyk7XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgU1RBTkRBUkRfUkVRVUlSRURfTlVNQkVSX09GX1NJR05FUlM7IGkrKykge1xuICAgICAgICBzaG91bGQuZG9lc05vdFRocm93KCgpID0+IHR4bkJ1aWxkZXIubnVtYmVyT2ZSZXF1aXJlZFNpZ25lcnMoaSkpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc3VnZ2VzdGVkIHBhcmFtcyB2ZXJpZmljYXRpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCByZXRyaWV2ZSB0aGUgc3VnZ2VzdGVkIHBhcmFtZXRlcnMgYXMgdGhleSBoYXZlIGJlZW4gc2V0JywgKCkgPT4ge1xuICAgICAgY29uc3QgaXNGbGF0RmVlID0gdHJ1ZTtcbiAgICAgIGNvbnN0IGZlZSA9IDEwMDA7XG4gICAgICBjb25zdCBmaXJzdFJvdW5kID0gMTtcbiAgICAgIGNvbnN0IGxhc3RSb3VuZCA9IDEwO1xuICAgICAgY29uc3QgZ2VuZXNpc0lkID0gJ3Rlc3RuZXQtdjEuMCc7XG4gICAgICBjb25zdCBnZW5lc2lzSGFzaCA9ICdTR08xR0tTenlFN0lFUEl0VHhDQnl3OXg4Rm1uckNEZXhpOS9jT1VKT2lJPSc7XG5cbiAgICAgIHR4bkJ1aWxkZXJcbiAgICAgICAgLmlzRmxhdEZlZShpc0ZsYXRGZWUpXG4gICAgICAgIC5mZWUoeyBmZWU6IGZlZS50b1N0cmluZygpIH0pXG4gICAgICAgIC5maXJzdFJvdW5kKGZpcnN0Um91bmQpXG4gICAgICAgIC5sYXN0Um91bmQobGFzdFJvdW5kKVxuICAgICAgICAuZ2VuZXNpc0lkKGdlbmVzaXNJZClcbiAgICAgICAgLmdlbmVzaXNIYXNoKGdlbmVzaXNIYXNoKTtcblxuICAgICAgY29uc3Qgc3VnZ2VzdGVkUGFyYW1zID0gdHhuQnVpbGRlci5nZXRTdWdnZXN0ZWRQYXJhbXMoKTtcbiAgICAgIHNob3VsZC5lcXVhbChpc0ZsYXRGZWUsIHN1Z2dlc3RlZFBhcmFtcy5mbGF0RmVlKTtcbiAgICAgIHNob3VsZC5lcXVhbChmZWUsIHN1Z2dlc3RlZFBhcmFtcy5mZWUpO1xuICAgICAgc2hvdWxkLmVxdWFsKGZpcnN0Um91bmQsIHN1Z2dlc3RlZFBhcmFtcy5maXJzdFJvdW5kKTtcbiAgICAgIHNob3VsZC5lcXVhbChsYXN0Um91bmQsIHN1Z2dlc3RlZFBhcmFtcy5sYXN0Um91bmQpO1xuICAgICAgc2hvdWxkLmVxdWFsKGdlbmVzaXNJZCwgc3VnZ2VzdGVkUGFyYW1zLmdlbmVzaXNJRCk7XG4gICAgICBzaG91bGQuZXF1YWwoZ2VuZXNpc0hhc2gsIHN1Z2dlc3RlZFBhcmFtcy5nZW5lc2lzSGFzaCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdwcml2YXRlIGtleSB2YWxpZGF0aW9uJywgKCkgPT4ge1xuICAgIGl0KCd2YWxpZGF0ZXMgYnl0ZSBhcnJheXMnLCAoKSA9PiB7XG4gICAgICBzaG91bGQuZG9lc05vdFRocm93KCgpID0+IHR4bkJ1aWxkZXIudmFsaWRhdGVLZXkoeyBrZXk6IGFjY291bnQxLnNlY3JldEtleSB9KSk7XG4gICAgfSk7XG5cbiAgICBpdCgndmFsaWRhdGVzIGhleCBlbmNvZGVkIHN0cmluZ3MnLCAoKSA9PiB7XG4gICAgICBzaG91bGQuZG9lc05vdFRocm93KCgpID0+IHR4bkJ1aWxkZXIudmFsaWRhdGVLZXkoeyBrZXk6IGFjY291bnQxLnNlY3JldEtleS50b1N0cmluZygnaGV4JykgfSkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3ZhbGlkYXRlcyBiYXNlNjQgZW5jb2RlZCBzdHJpbmdzJywgKCkgPT4ge1xuICAgICAgc2hvdWxkLmRvZXNOb3RUaHJvdygoKSA9PiB0eG5CdWlsZGVyLnZhbGlkYXRlS2V5KHsga2V5OiBhY2NvdW50MS5zZWNyZXRLZXkudG9TdHJpbmcoJ2Jhc2U2NCcpIH0pKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2ltcGxlbWVudGF0aW9uIGZ1bmN0aW9ucycsICgpID0+IHtcbiAgICBjb25zdCB0byA9IGFjY291bnQxLmFkZHJlc3M7XG4gICAgY29uc3QgZnJvbSA9IGFjY291bnQyLmFkZHJlc3M7XG4gICAgY29uc3QgcmVLZXlUbyA9IGFjY291bnQzLmFkZHJlc3M7XG4gICAgY29uc3QgYW1vdW50ID0gMTAwMDtcbiAgICBjb25zdCBmaXJzdFJvdW5kID0gMTtcbiAgICBjb25zdCBsYXN0Um91bmQgPSAxMDtcbiAgICBjb25zdCBjbG9zZVJlbWFpbmRlclRvID0gYWNjb3VudDMuYWRkcmVzcztcblxuICAgIC8vIFVpbnQ4YXJyYXkgY29udmVyc2lvbiByZXF1aXJlZCBiZWNhdXNlIGFsZ29zZGsgY2hlY2tzIGlmIHRoZSBjb25zdHJ1Y3RvclxuICAgIC8vIGlzIFVpbnQ4QXJyYXkuXG4gICAgY29uc3QgbGVhc2UgPSBuZXcgVWludDhBcnJheShjcnlwdG8ucmFuZG9tQnl0ZXMoMzIpKTtcbiAgICBjb25zdCBub3RlID0gbmV3IFVpbnQ4QXJyYXkoQnVmZmVyLmZyb20oJ25vdGUnLCAndXRmLTgnKSk7XG5cbiAgICBjb25zdCBmZWUgPSAxMDAwO1xuXG4gICAgY29uc3QgYWxnb1R4biA9IGFsZ29zZGsubWFrZVBheW1lbnRUeG5XaXRoU3VnZ2VzdGVkUGFyYW1zKFxuICAgICAgZnJvbSxcbiAgICAgIHRvLFxuICAgICAgYW1vdW50LFxuICAgICAgY2xvc2VSZW1haW5kZXJUbyxcbiAgICAgIG5vdGUsXG4gICAgICB7XG4gICAgICAgIGZlZSxcbiAgICAgICAgZmxhdEZlZTogdHJ1ZSxcbiAgICAgICAgZmlyc3RSb3VuZCxcbiAgICAgICAgbGFzdFJvdW5kLFxuICAgICAgICBnZW5lc2lzSUQ6IHRlc3RuZXQuZ2VuZXNpc0lELFxuICAgICAgICBnZW5lc2lzSGFzaDogdGVzdG5ldC5nZW5lc2lzSGFzaCxcbiAgICAgIH0sXG4gICAgICByZUtleVRvXG4gICAgKTtcbiAgICBhbGdvVHhuLmZlZSA9IGZlZTtcbiAgICBhbGdvVHhuLmZsYXRGZWUgPSB0cnVlO1xuICAgIGFsZ29UeG4uYWRkTGVhc2UobGVhc2UpO1xuXG4gICAgaXQoJ3Nob3VsZCBhc3NpZ24gYWxsIGRlY29kZWQgZmllbGRzIGludG8gdHJhbnNhY3Rpb24gYnVpbGRlcicsICgpID0+IHtcbiAgICAgIHR4bkJ1aWxkZXIuZnJvbUltcGxlbWVudGF0aW9uKGFsZ29zZGsuZW5jb2RlVW5zaWduZWRUcmFuc2FjdGlvbihhbGdvVHhuKSk7XG5cbiAgICAgIHNob3VsZCh0eG5CdWlsZGVyLmdldEZlZSgpKS5lcXVhbChmZWUpO1xuICAgICAgc2hvdWxkKHR4bkJ1aWxkZXIuZ2V0U2VuZGVyKCkpLmVxdWFsKGZyb20pO1xuICAgICAgc2hvdWxkKHR4bkJ1aWxkZXIuZ2V0R2VuZXNpc0hhc2goKSkuZXF1YWwodGVzdG5ldC5nZW5lc2lzSGFzaCk7XG4gICAgICBzaG91bGQodHhuQnVpbGRlci5nZXRHZW5lc2lzSWQoKSkuZXF1YWwodGVzdG5ldC5nZW5lc2lzSUQpO1xuICAgICAgc2hvdWxkKHR4bkJ1aWxkZXIuZ2V0Rmlyc3RSb3VuZCgpKS5lcXVhbChmaXJzdFJvdW5kKTtcbiAgICAgIHNob3VsZCh0eG5CdWlsZGVyLmdldExhc3RSb3VuZCgpKS5lcXVhbChsYXN0Um91bmQpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgIHNob3VsZChCdWZmZXIuZnJvbSh0eG5CdWlsZGVyLmdldExlYXNlKCkhKS50b1N0cmluZygnaGV4JykpLmVxdWFsKEJ1ZmZlci5mcm9tKGxlYXNlKS50b1N0cmluZygnaGV4JykpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgIHNob3VsZChCdWZmZXIuZnJvbSh0eG5CdWlsZGVyLmdldE5vdGUoKSEpLnRvU3RyaW5nKCdoZXgnKSkuZXF1YWwoQnVmZmVyLmZyb20obm90ZSkudG9TdHJpbmcoJ2hleCcpKTtcbiAgICAgIHNob3VsZCh0eG5CdWlsZGVyLmdldFJlS2V5VG8oKSkuZXF1YWwocmVLZXlUbyk7XG5cbiAgICAgIHNob3VsZCh0eG5CdWlsZGVyLmdldFRyYW5zYWN0aW9uKCkuZ2V0QWxnb1RyYW5zYWN0aW9uKCkpLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYXNzaWduIHNpZ25lcnMgaW50byB0cmFuc2FjdGlvbiBidWlsZGVyJywgKCkgPT4ge1xuICAgICAgc2lub24uc3R1YihhbGdvVXRpbHMsICdkZWNvZGVBbGdvVHhuJykuY2FsbHNGYWtlKCh0eG5CeXRlczogVWludDhBcnJheSB8IHN0cmluZyk6IEVuY29kZWRUeCA9PiB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgcmF3VHJhbnNhY3Rpb246IEJ1ZmZlci5mcm9tKFtdKSxcbiAgICAgICAgICBzaWduZWQ6IHRydWUsXG4gICAgICAgICAgc2lnbmVyczogW1xuICAgICAgICAgICAgJzI1TkpRQU1DV0VGTFBWS0w3M0o0U1pBSEhJSE9DNFhUM0tUQ0dKTlBBSU5HUjVZSEtFTk1FRjVRVEUnLFxuICAgICAgICAgICAgJzdSSTQzRFRDRENRMkhETkVQM0lBRU1IUUxBRUJOM0lUWElaUUhMQzU1T0lSS1NFUVFBUzUyT1lLSkUnLFxuICAgICAgICAgIF0sXG4gICAgICAgICAgdHhuOiBhbGdvVHhuLFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgICB0eG5CdWlsZGVyLmZyb21JbXBsZW1lbnRhdGlvbihhbGdvc2RrLmVuY29kZVVuc2lnbmVkVHJhbnNhY3Rpb24oYWxnb1R4bikpO1xuICAgICAgc2hvdWxkKHR4bkJ1aWxkZXIuZ2V0VHJhbnNhY3Rpb24oKS5zaWduZXJzKS5kZWVwRXF1YWwoW1xuICAgICAgICAnMjVOSlFBTUNXRUZMUFZLTDczSjRTWkFISElIT0M0WFQzS1RDR0pOUEFJTkdSNVlIS0VOTUVGNVFURScsXG4gICAgICAgICc3Ukk0M0RUQ0RDUTJIRE5FUDNJQUVNSFFMQUVCTjNJVFhJWlFITEM1NU9JUktTRVFRQVM1Mk9ZS0pFJyxcbiAgICAgIF0pO1xuICAgICAgc2lub24ucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3RyYW5zYWN0aW9uIGJ1aWxkZXIgc2hvdWxkIGZhaWwgd2hlbiBzaWduZXJzIGFyZSBpbmNvcnJlY3QnLCAoKSA9PiB7XG4gICAgICBzaW5vbi5zdHViKGFsZ29VdGlscywgJ2RlY29kZUFsZ29UeG4nKS5jYWxsc0Zha2UoKHR4bkJ5dGVzOiBVaW50OEFycmF5IHwgc3RyaW5nKTogRW5jb2RlZFR4ID0+IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICByYXdUcmFuc2FjdGlvbjogQnVmZmVyLmZyb20oW10pLFxuICAgICAgICAgIHNpZ25lZDogdHJ1ZSxcbiAgICAgICAgICBzaWduZXJzOiBbXG4gICAgICAgICAgICAnMjVOSlFBTUNXRUZMUFZLTDczSjRTWkFISElIT0M0WFQzS1RDR0pOUEFJTkdSNVlIS0VOTUVGNUFBQScsXG4gICAgICAgICAgICAnN1JJNDNEVENEQ1EySERORVAzSUFFTUhRTEFFQk4zSVRYSVpRSExDNTVPSVJLU0VRUUFTNTJPWUtKRScsXG4gICAgICAgICAgXSxcbiAgICAgICAgICB0eG46IGFsZ29UeG4sXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICAgIHNob3VsZCgoKSA9PiB0eG5CdWlsZGVyLmZyb21JbXBsZW1lbnRhdGlvbihhbGdvc2RrLmVuY29kZVVuc2lnbmVkVHJhbnNhY3Rpb24oYWxnb1R4bikpKS50aHJvdyhcbiAgICAgICAgXCJUaGUgYWRkcmVzcyAnMjVOSlFBTUNXRUZMUFZLTDczSjRTWkFISElIT0M0WFQzS1RDR0pOUEFJTkdSNVlIS0VOTUVGNUFBQScgaXMgbm90IGEgd2VsbC1mb3JtZWQgYWxnb3JhbmQgYWRkcmVzc1wiXG4gICAgICApO1xuICAgICAgc2lub24ucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBub3Qgc2lnbiB0aGUgdHJhbnNhY3Rpb24nLCAoKSA9PiB7XG4gICAgICBjb25zdCB0eG4gPSB0eG5CdWlsZGVyLmdldFRyYW5zYWN0aW9uKCk7XG4gICAgICB0eG4uc2V0QWxnb1RyYW5zYWN0aW9uKGFsZ29UeG4pO1xuICAgICAgdHhuLnNldE51bWJlck9mUmVxdWlyZWRTaWduZXJzKDEpO1xuXG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PiB0eG5CdWlsZGVyLnNpZ25JbXBsZW1lbnRhdGlvbih7IGtleTogQnVmZmVyLmZyb20oYWNjb3VudDEucHJ2S2V5KS50b1N0cmluZygnaGV4JykgfSksXG4gICAgICAgIG5ldyBSZWdFeHAoJ0ludmFsaWQgYmFzZTMyIGNoYXJhY3RlcnMnKVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2lnbiB0aGUgdHJhbnNhY3Rpb24nLCAoKSA9PiB7XG4gICAgICBjb25zdCB7IHBydiwgcHViIH0gPSBuZXcgS2V5UGFpcigpLnJlY29yZEtleXNGcm9tUHJpdmF0ZUtleUluUHJvdG9jb2xGb3JtYXQoYWNjb3VudDEucHJ2S2V5KTtcbiAgICAgIGNvbnN0IHBydktleSA9IGFsZ29VdGlscy5lbmNvZGVTZWVkKEJ1ZmZlci5mcm9tKHBydiArIHB1YikpO1xuICAgICAgY29uc3QgdHhuID0gdHhuQnVpbGRlci5nZXRUcmFuc2FjdGlvbigpO1xuICAgICAgdHhuLnNldEFsZ29UcmFuc2FjdGlvbihhbGdvVHhuKTtcbiAgICAgIHR4bi5zZXROdW1iZXJPZlJlcXVpcmVkU2lnbmVycygxKTtcblxuICAgICAgc2hvdWxkLmRvZXNOb3RUaHJvdygoKSA9PiB0eG5CdWlsZGVyLnNpZ25JbXBsZW1lbnRhdGlvbih7IGtleTogcHJ2S2V5IH0pKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3RyYW5zYWN0aW9uIHZhbGlkYXRpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCB2YWxpZGF0ZSBhIG5vcm1hbCB0cmFuc2FjdGlvbicsICgpID0+IHtcbiAgICAgIHR4bkJ1aWxkZXJcbiAgICAgICAgLmZlZSh7IGZlZTogJzEwMDAnIH0pXG4gICAgICAgIC5pc0ZsYXRGZWUodHJ1ZSlcbiAgICAgICAgLmZpcnN0Um91bmQoMSlcbiAgICAgICAgLmxhc3RSb3VuZCgxMClcbiAgICAgICAgLnNlbmRlcih7IGFkZHJlc3M6IGFjY291bnQxLmFkZHJlc3MgfSlcbiAgICAgICAgLmdlbmVzaXNJZCh0ZXN0bmV0LmdlbmVzaXNJRClcbiAgICAgICAgLmdlbmVzaXNIYXNoKHRlc3RuZXQuZ2VuZXNpc0hhc2gpO1xuXG4gICAgICBzaG91bGQuZG9lc05vdFRocm93KCgpID0+IHR4bkJ1aWxkZXIudmFsaWRhdGVUcmFuc2FjdGlvbih0eG5CdWlsZGVyLmdldFRyYW5zYWN0aW9uKCkpKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgbGFzdCByb3VuZCBpcyBhZnRlciBmaXJzdCByb3VuZCcsICgpID0+IHtcbiAgICAgIHR4bkJ1aWxkZXJcbiAgICAgICAgLmZlZSh7IGZlZTogJzEwMDAnIH0pXG4gICAgICAgIC5pc0ZsYXRGZWUodHJ1ZSlcbiAgICAgICAgLmZpcnN0Um91bmQoMTApXG4gICAgICAgIC5sYXN0Um91bmQoMSlcbiAgICAgICAgLnNlbmRlcih7IGFkZHJlc3M6IGFjY291bnQxLmFkZHJlc3MgfSlcbiAgICAgICAgLmdlbmVzaXNJZCh0ZXN0bmV0LmdlbmVzaXNJRClcbiAgICAgICAgLmdlbmVzaXNIYXNoKHRlc3RuZXQuZ2VuZXNpc0hhc2gpO1xuXG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PiB0eG5CdWlsZGVyLnZhbGlkYXRlVHJhbnNhY3Rpb24odHhuQnVpbGRlci5nZXRUcmFuc2FjdGlvbigpKSxcbiAgICAgICAgbmV3IFJlZ0V4cChcbiAgICAgICAgICAnVHJhbnNhY3Rpb24gdmFsaWRhdGlvbiBmYWlsZWQ6IFwidmFsdWVcIiBmYWlsZWQgY3VzdG9tIHZhbGlkYXRpb24gYmVjYXVzZSBsYXN0Um91bmQgY2Fubm90IGJlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byBmaXJzdFJvdW5kJ1xuICAgICAgICApXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhIG5vcm1hbCB0cmFuc2FjdGlvbiB3aXRoIGNvcnJlY3Qgc2lnbmVycycsICgpID0+IHtcbiAgICAgIHR4bkJ1aWxkZXJcbiAgICAgICAgLmZlZSh7IGZlZTogJzEwMDAnIH0pXG4gICAgICAgIC5pc0ZsYXRGZWUodHJ1ZSlcbiAgICAgICAgLmZpcnN0Um91bmQoMSlcbiAgICAgICAgLmxhc3RSb3VuZCgxMClcbiAgICAgICAgLnNlbmRlcih7IGFkZHJlc3M6IGFjY291bnQxLmFkZHJlc3MgfSlcbiAgICAgICAgLnNldFNpZ25lcnMoW1xuICAgICAgICAgICcyNU5KUUFNQ1dFRkxQVktMNzNKNFNaQUhISUhPQzRYVDNLVENHSk5QQUlOR1I1WUhLRU5NRUY1UVRFJyxcbiAgICAgICAgICAnN1JJNDNEVENEQ1EySERORVAzSUFFTUhRTEFFQk4zSVRYSVpRSExDNTVPSVJLU0VRUUFTNTJPWUtKRScsXG4gICAgICAgIF0pXG4gICAgICAgIC5nZW5lc2lzSWQodGVzdG5ldC5nZW5lc2lzSUQpXG4gICAgICAgIC5nZW5lc2lzSGFzaCh0ZXN0bmV0LmdlbmVzaXNIYXNoKTtcbiAgICAgIHNob3VsZCh0eG5CdWlsZGVyLmdldFRyYW5zYWN0aW9uKCkuc2lnbmVycykuZGVlcEVxdWFsKFtcbiAgICAgICAgJzI1TkpRQU1DV0VGTFBWS0w3M0o0U1pBSEhJSE9DNFhUM0tUQ0dKTlBBSU5HUjVZSEtFTk1FRjVRVEUnLFxuICAgICAgICAnN1JJNDNEVENEQ1EySERORVAzSUFFTUhRTEFFQk4zSVRYSVpRSExDNTVPSVJLU0VRUUFTNTJPWUtKRScsXG4gICAgICBdKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbm90IGJ1aWxkIGEgbm9ybWFsIHRyYW5zYWN0aW9uIHdpdGggaW5jb3JyZWN0IHNpZ25lcnMnLCAoKSA9PiB7XG4gICAgICBzaG91bGQoKCkgPT5cbiAgICAgICAgdHhuQnVpbGRlclxuICAgICAgICAgIC5mZWUoeyBmZWU6ICcxMDAwJyB9KVxuICAgICAgICAgIC5pc0ZsYXRGZWUodHJ1ZSlcbiAgICAgICAgICAuZmlyc3RSb3VuZCgxKVxuICAgICAgICAgIC5sYXN0Um91bmQoMTApXG4gICAgICAgICAgLnNlbmRlcih7IGFkZHJlc3M6IGFjY291bnQxLmFkZHJlc3MgfSlcbiAgICAgICAgICAuc2V0U2lnbmVycyhbXG4gICAgICAgICAgICAnMjVOSlFBTUNXRUZMUFZLTDczSjRTWkFISElIT0M0WFQzS1RDR0pOUEFJTkdSNVlIS0VOTUVGNUFBQScsXG4gICAgICAgICAgICAnN1JJNDNEVENEQ1EySERORVAzSUFFTUhRTEFFQk4zSVRYSVpRSExDNTVPSVJLU0VRUUFTNTJPWUtKRScsXG4gICAgICAgICAgXSlcbiAgICAgICAgICAuZ2VuZXNpc0lkKHRlc3RuZXQuZ2VuZXNpc0lEKVxuICAgICAgICAgIC5nZW5lc2lzSGFzaCh0ZXN0bmV0LmdlbmVzaXNIYXNoKVxuICAgICAgKS50aHJvdyhcbiAgICAgICAgXCJUaGUgYWRkcmVzcyAnMjVOSlFBTUNXRUZMUFZLTDczSjRTWkFISElIT0M0WFQzS1RDR0pOUEFJTkdSNVlIS0VOTUVGNUFBQScgaXMgbm90IGEgd2VsbC1mb3JtZWQgYWxnb3JhbmQgYWRkcmVzc1wiXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19

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


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