PHP WebShell

Текущая директория: /opt/BitGoJS/modules/sdk-core/dist/src/bitgo/baseCoin

Просмотр файла: baseCoin.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 });
exports.BaseCoin = void 0;
/**
 * @prettier
 */
const crypto = __importStar(require("crypto"));
const utxo_lib_1 = require("@bitgo/utxo-lib");
const bignumber_js_1 = require("bignumber.js");
const utxolib = __importStar(require("@bitgo/utxo-lib"));
const bip32util_1 = require("../bip32util");
const account_lib_1 = require("../../account-lib");
const enterprise_1 = require("../enterprise");
const keychain_1 = require("../keychain");
const market_1 = require("../market");
const pendingApproval_1 = require("../pendingApproval");
const wallet_1 = require("../wallet");
const webhook_1 = require("../webhook");
class BaseCoin {
    constructor(bitgo) {
        this.bitgo = bitgo;
        this._url = this.bitgo.url('/', 2);
        this._wallets = new wallet_1.Wallets(this.bitgo, this);
        this._keychains = new keychain_1.Keychains(this.bitgo, this);
        this._webhooks = new webhook_1.Webhooks(this.bitgo, this);
        this._pendingApprovals = new pendingApproval_1.PendingApprovals(this.bitgo, this);
        this._enterprises = new enterprise_1.Enterprises(this.bitgo, this);
        this._markets = new market_1.Markets(this.bitgo, this);
    }
    url(suffix) {
        return this._url + this.getChain() + suffix;
    }
    wallets() {
        return this._wallets;
    }
    enterprises() {
        return this._enterprises;
    }
    keychains() {
        return this._keychains;
    }
    webhooks() {
        return this._webhooks;
    }
    pendingApprovals() {
        return this._pendingApprovals;
    }
    markets() {
        return this._markets;
    }
    static get coinTokenPatternSeparator() {
        return this._coinTokenPatternSeparator;
    }
    get type() {
        return this.getChain();
    }
    /**
     * Gets the statics coin object
     * @returns {Readonly<StaticsBaseCoin>} the statics coin object
     */
    getConfig() {
        return this._staticsCoin;
    }
    /**
     * Flag for sending value of 0.
     * @returns {boolean} True if okay to send 0 value, false otherwise
     */
    valuelessTransferAllowed() {
        return false;
    }
    /**
     * Use `sendMany()` to perform wallet sweep.
     * FIXME(BG-39738): add coin.sweepWallet() instead
     */
    sweepWithSendMany() {
        return false;
    }
    /**
     * Flag for sending data along with transactions
     * @returns {boolean} True if okay to send tx data (ETH), false otherwise
     */
    transactionDataAllowed() {
        return false;
    }
    /**
     * Flag for determining whether this coin supports account consolidations
     * from its receive addresses to the root address.
     * @returns {boolean} True if okay to consolidate over this coin; false, otherwise
     */
    allowsAccountConsolidations() {
        return false;
    }
    /**
     * Gets config for how token enablements work for this coin
     * @returns
     *    requiresTokenEnablement: True if tokens need to be enabled for this coin
     *    supportsMultipleTokenEnablements: True if multiple tokens can be enabled in one transaction
     */
    getTokenEnablementConfig() {
        return {
            requiresTokenEnablement: false,
            supportsMultipleTokenEnablements: false,
        };
    }
    /**
     * Flag indicating if this coin supports TSS wallets.
     * @returns {boolean} True if TSS Wallets can be created for this coin
     */
    supportsTss() {
        return false;
    }
    /**
     * Flag indicating if this coin supports MultiSig wallets.
     * @return {boolean} True if MultiSig wallets can be created for this coin
     */
    supportsMultisig() {
        return false;
    }
    /**
     * It will return the default multisig type value for coin
     * @return {MultisigType} return 'tss' if coin supports only TSS not MultiSig
     * else if coin supports MultiSig return 'onchain'
     * if coin supports both return 'onchain'
     * else undefined
     */
    getDefaultMultisigType() {
        return undefined;
    }
    /**
     * Flag indicating if the coin supports deriving a key with a seed (keyID)
     * to the user/backup keys.
     */
    supportsDeriveKeyWithSeed() {
        return true;
    }
    /**
     * Flag indicating if this blockchain runs on EVM architecture.
     * @returns {boolean} True if the blockchain runs on EVM architecture.
     */
    isEVM() {
        return false;
    }
    /**
     * Flag indicating if this coin supports BLS-DKG wallets.
     * @returns {boolean} True if BLS-DKG Wallets can be created for this coin
     */
    supportsBlsDkg() {
        return false;
    }
    /**
     * Convert a currency amount represented in base units (satoshi, wei, atoms, drops, stroops)
     * to big units (btc, eth, xrp, xlm)
     */
    baseUnitsToBigUnits(baseUnits) {
        bignumber_js_1.BigNumber.set({ DECIMAL_PLACES: 24 });
        const dividend = this.getBaseFactor();
        const bigNumber = new bignumber_js_1.BigNumber(baseUnits).dividedBy(dividend);
        // set the format so commas aren't added to large coin amounts
        return bigNumber.toFormat(null, null, { groupSeparator: '', decimalSeparator: '.' });
    }
    checkRecipient(recipient) {
        if (recipient.amount !== 'max') {
            const amount = new bignumber_js_1.BigNumber(recipient.amount);
            if (amount.isNegative()) {
                throw new Error('invalid argument for amount - positive number greater than zero or numeric string expected');
            }
            if (!this.valuelessTransferAllowed() && amount.isZero()) {
                throw new Error('invalid argument for amount - positive number greater than zero or numeric string expected');
            }
        }
    }
    /**
     * Convert a currency amount represented in big units (btc, eth, xrp, xlm)
     * to base units (satoshi, wei, atoms, drops, stroops)
     * @param bigUnits
     */
    bigUnitsToBaseUnits(bigUnits) {
        const multiplier = this.getBaseFactor();
        const bigNumber = new bignumber_js_1.BigNumber(bigUnits).times(multiplier);
        if (!bigNumber.isInteger()) {
            throw new Error(`non-integer output resulted from multiplying ${bigUnits} by ${multiplier}`);
        }
        return bigNumber.toFixed(0);
    }
    /**
     * Preprocess the build parameters before sending to the API
     * @param buildParams
     */
    preprocessBuildParams(buildParams) {
        return buildParams;
    }
    /**
     * Sign message with private key
     *
     * @param key
     * @param message
     */
    async signMessage(key, message) {
        return (0, bip32util_1.signMessage)(message, utxo_lib_1.bip32.fromBase58(key.prv), utxolib.networks.bitcoin);
    }
    /**
     * Create signatures for the backup and bitgo keys using the user key.
     * We can verify the signatures when fetching the keys from wallet-platform later.
     * Currently only `AbstractUtxoCoin` implements and uses the complementary `verifyKeySignature` method.
     * @param prv - the user private key
     * @param backupKeychain - contains the backup public key
     * @param bitgoKeychain - contains the bitgo public key
     */
    async createKeySignatures(prv, backupKeychain, bitgoKeychain) {
        return {
            backup: (await this.signMessage({ prv }, backupKeychain.pub)).toString('hex'),
            bitgo: (await this.signMessage({ prv }, bitgoKeychain.pub)).toString('hex'),
        };
    }
    /**
     * Decompose a raw transaction into useful information.
     * @param options - coin-specific
     */
    explainTransaction(options) {
        throw new Error(`not implemented`);
    }
    /**
     * @deprecated use {@see isWalletAddress} instead
     */
    verifyAddress(params) {
        return this.isWalletAddress(params);
    }
    /**
     * convert address into desired address format.
     * @param address
     * @param format
     */
    canonicalAddress(address, format) {
        return address;
    }
    /**
     * Check whether a coin supports blockTarget for transactions to be included in
     * @returns {boolean}
     */
    supportsBlockTarget() {
        return false;
    }
    /**
     * Check whether a coin supports lightning transactions
     * @returns {boolean}
     */
    supportsLightning() {
        return false;
    }
    /**
     * Check whether a coin supports message signing
     * @returns {boolean}
     */
    supportsMessageSigning() {
        return false;
    }
    /**
     * Check whether a coin supports signing of Typed data
     * @returns {boolean}
     */
    supportsSigningTypedData() {
        return false;
    }
    /**
     * Hook to add additional parameters to the wallet generation
     * @param walletParams
     * @param keychains
     * @return {*}
     */
    supplementGenerateWallet(walletParams, keychains) {
        return Promise.resolve(walletParams);
    }
    /**
     * Get extra parameters for prebuilding a tx. Add things like hop transaction params
     */
    getExtraPrebuildParams(buildParams) {
        return Promise.resolve({});
    }
    /**
     * Modify prebuild after receiving it from the server. Add things like nlocktime
     */
    postProcessPrebuild(prebuildResponse) {
        return Promise.resolve(prebuildResponse);
    }
    /**
     * Coin-specific things done before signing a transaction, i.e. verification
     */
    presignTransaction(params) {
        return Promise.resolve(params);
    }
    /**
     * Create a new wallet object from a wallet data object
     * @param walletParams
     */
    newWalletObject(walletParams) {
        return new wallet_1.Wallet(this.bitgo, this, walletParams);
    }
    /**
     * Fetch fee estimate information from the server
     * @param {Object} params The params passed into the function
     * @param {Integer} params.numBlocks The number of blocks to target for conformation (Only works for btc)
     * @returns {Object} The info returned from the merchant server
     */
    async feeEstimate(params) {
        const query = {};
        if (params && params.numBlocks) {
            query.numBlocks = params.numBlocks;
        }
        return this.bitgo.get(this.url('/tx/fee')).query(query).result();
    }
    /**
     * The cold wallet tool uses this function to derive an extended key that is based on the passed key and seed
     * @param key
     * @param seed
     * @returns {{key: string, derivationPath: string}}
     */
    static deriveKeyWithSeedBip32(key, seed) {
        function sha256(input) {
            return crypto.createHash('sha256').update(input).digest();
        }
        const derivationPathInput = sha256(sha256(`${seed}`)).toString('hex');
        const derivationPathParts = [
            parseInt(derivationPathInput.slice(0, 7), 16),
            parseInt(derivationPathInput.slice(7, 14), 16),
        ];
        const derivationPath = 'm/999999/' + derivationPathParts.join('/');
        return {
            key: key.derivePath(derivationPath),
            derivationPath,
        };
    }
    /** {@see deriveKeyWithSeedBip32} */
    deriveKeyWithSeed(params) {
        const { key, derivationPath } = BaseCoin.deriveKeyWithSeedBip32(utxo_lib_1.bip32.fromBase58(params.key), params.seed);
        return {
            key: key.toBase58(),
            derivationPath,
        };
    }
    /**
     * Specifies what key we will need for signing - right now we just need the
     * user key.
     */
    keyIdsForSigning() {
        return [keychain_1.KeyIndices.USER];
    }
    /**
     * Perform additional checks before adding a bitgo key. Base controller
     * is a no-op, but coin-specific controller may do something
     * @param params
     */
    preCreateBitGo(params) {
        return;
    }
    /**
     * @deprecated - use getBip32Keys() in conjunction with isValidAddress instead
     */
    initiateRecovery(params) {
        throw new Error('deprecated method');
    }
    /**
     * Generate a root key pair on the curve used by the coin
     * @param {Buffer} seed - seed to use for key pair generation
     * @returns {KeyPair} the generated key pair
     */
    generateRootKeyPair(seed) {
        throw new account_lib_1.NotImplementedError('generateRootKeyPair is not supported for this coin');
    }
    /**
     * Return wether the given m of n wallet signers/ key amounts are valid for the coin
     */
    isValidMofNSetup({ m, n }) {
        return m === 2 && n === 3;
    }
    /**
     * Returns the portion of the transaction that needs to be signed in Buffer format.
     * Only needed for coins that support adding signatures directly (e.g. TSS).
     *
     * @param {String} serializedTx - the unsigned transaction in broadcast format
     * @returns {Promise<Buffer>} - the portion of the transaction that needs to be signed
     */
    async getSignablePayload(serializedTx) {
        return Buffer.from(serializedTx);
    }
    /**
     * Returns the MPC algorithm (ecdsa or eddsa) used for coins that support TSS
     */
    getMPCAlgorithm() {
        throw new Error('no MPC algorithm is defined for this coin');
    }
    async recoverToken(params) {
        throw new account_lib_1.NotImplementedError('recoverToken is not supported for this coin');
    }
    getInscriptionBuilder(wallet) {
        throw new account_lib_1.NotImplementedError('Inscription Builder is not supported for this coin');
    }
    /**
     * Function to get coin specific hash function used to generate transaction digests.
     * @returns {@see Hash} hash function if implemented, otherwise throws exception
     */
    getHashFunction() {
        throw new account_lib_1.NotImplementedError('getHashFunction is not supported for this coin');
    }
    buildNftTransferData(params) {
        throw new account_lib_1.NotImplementedError('buildNftTransferData is not supported for this coin');
    }
    /**
     * Broadcast a transaction to the network
     * @param params options for broadcasting
     * @returns {Promise<BaseBroadcastTransactionResult>} result of broadcast
     * @throws {NotImplementedError} if not implemented
     */
    broadcastTransaction(params) {
        throw new account_lib_1.NotImplementedError('broadcastTransaction is not supported for this coin');
    }
    /**
     * Creates funds sweep recovery transaction(s) without BitGo
     *
     * @param {MPCSweepRecoveryOptions} params parameters needed to combine the signatures
     * and transactions to create broadcastable transactions
     *
     * @returns {MPCTxs} array of the serialized transaction hex strings and indices
     * of the addresses being swept
     */
    async createBroadcastableSweepTransaction(params) {
        throw new account_lib_1.NotImplementedError('createBroadcastableSweepTransaction is not supported for this coin');
    }
    /**
     * Sets coinspecific fields in intent from input params.
     * This method should be overridden in coin-specific classes
     * to configure these fields in the intent
     * @param intent - intent in which coinspecific fields are to be set
     * @param params
     */
    setCoinSpecificFieldsInIntent(intent, params) {
        return;
    }
}
exports.BaseCoin = BaseCoin;
BaseCoin._coinTokenPatternSeparator = ':';
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZUNvaW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYml0Z28vYmFzZUNvaW4vYmFzZUNvaW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7O0dBRUc7QUFDSCwrQ0FBaUM7QUFDakMsOENBQXdDO0FBQ3hDLCtDQUF5QztBQUV6Qyx5REFBMkM7QUFJM0MsNENBQTJDO0FBQzNDLG1EQUF3RDtBQUV4RCw4Q0FBNEM7QUFDNUMsMENBQW9EO0FBQ3BELHNDQUFvQztBQUNwQyx3REFBc0Q7QUFDdEQsc0NBQXFEO0FBQ3JELHdDQUFzQztBQWdDdEMsTUFBc0IsUUFBUTtJQVk1QixZQUFzQixLQUFnQjtRQUNwQyxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUNuQixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNuQyxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksZ0JBQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzlDLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxvQkFBUyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLGtCQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNoRCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxrQ0FBZ0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2hFLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSx3QkFBVyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDdEQsSUFBSSxDQUFDLFFBQVEsR0FBRyxJ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MGpCQztBQWpqQjJCLG1DQUEwQixHQUFHLEdBQUcsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQHByZXR0aWVyXG4gKi9cbmltcG9ydCAqIGFzIGNyeXB0byBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgYmlwMzIgfSBmcm9tICdAYml0Z28vdXR4by1saWInO1xuaW1wb3J0IHsgQmlnTnVtYmVyIH0gZnJvbSAnYmlnbnVtYmVyLmpzJztcblxuaW1wb3J0ICogYXMgdXR4b2xpYiBmcm9tICdAYml0Z28vdXR4by1saWInO1xuaW1wb3J0IHsgQmFzZUNvaW4gYXMgU3RhdGljc0Jhc2VDb2luIH0gZnJvbSAnQGJpdGdvL3N0YXRpY3MnO1xuXG5pbXBvcnQgeyBJbml0aWF0ZVJlY292ZXJ5T3B0aW9ucyB9IGZyb20gJy4uL3JlY292ZXJ5JztcbmltcG9ydCB7IHNpZ25NZXNzYWdlIH0gZnJvbSAnLi4vYmlwMzJ1dGlsJztcbmltcG9ydCB7IE5vdEltcGxlbWVudGVkRXJyb3IgfSBmcm9tICcuLi8uLi9hY2NvdW50LWxpYic7XG5pbXBvcnQgeyBCaXRHb0Jhc2UgfSBmcm9tICcuLi9iaXRnb0Jhc2UnO1xuaW1wb3J0IHsgRW50ZXJwcmlzZXMgfSBmcm9tICcuLi9lbnRlcnByaXNlJztcbmltcG9ydCB7IEtleWNoYWlucywgS2V5SW5kaWNlcyB9IGZyb20gJy4uL2tleWNoYWluJztcbmltcG9ydCB7IE1hcmtldHMgfSBmcm9tICcuLi9tYXJrZXQnO1xuaW1wb3J0IHsgUGVuZGluZ0FwcHJvdmFscyB9IGZyb20gJy4uL3BlbmRpbmdBcHByb3ZhbCc7XG5pbXBvcnQgeyBXYWxsZXRzLCBJV2FsbGV0LCBXYWxsZXQgfSBmcm9tICcuLi93YWxsZXQnO1xuaW1wb3J0IHsgV2ViaG9va3MgfSBmcm9tICcuLi93ZWJob29rJztcbmltcG9ydCB7XG4gIEV4dHJhUHJlYnVpbGRQYXJhbXNPcHRpb25zLFxuICBGZWVFc3RpbWF0ZU9wdGlvbnMsXG4gIElCYXNlQ29pbixcbiAgUGFyc2VkVHJhbnNhY3Rpb24sXG4gIElUcmFuc2FjdGlvbkV4cGxhbmF0aW9uLFxuICBLZXljaGFpbnNUcmlwbGV0LFxuICBLZXlQYWlyLFxuICBNUENBbGdvcml0aG0sXG4gIFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zLFxuICBQcmVjcmVhdGVCaXRHb09wdGlvbnMsXG4gIFByZXNpZ25UcmFuc2FjdGlvbk9wdGlvbnMsXG4gIFJlY292ZXJUb2tlblRyYW5zYWN0aW9uLFxuICBSZWNvdmVyV2FsbGV0VG9rZW5PcHRpb25zLFxuICBTaWduZWRUcmFuc2FjdGlvbixcbiAgU2lnblRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgU3VwcGxlbWVudEdlbmVyYXRlV2FsbGV0T3B0aW9ucyxcbiAgVG9rZW5FbmFibGVtZW50Q29uZmlnLFxuICBUcmFuc2FjdGlvblByZWJ1aWxkLFxuICBWZXJpZnlBZGRyZXNzT3B0aW9ucyxcbiAgVmVyaWZ5VHJhbnNhY3Rpb25PcHRpb25zLFxuICBCdWlsZE5mdFRyYW5zZmVyRGF0YU9wdGlvbnMsXG4gIEJhc2VCcm9hZGNhc3RUcmFuc2FjdGlvbk9wdGlvbnMsXG4gIEJhc2VCcm9hZGNhc3RUcmFuc2FjdGlvblJlc3VsdCxcbiAgRGVyaXZlS2V5V2l0aFNlZWRPcHRpb25zLFxuICBNdWx0aXNpZ1R5cGUsXG59IGZyb20gJy4vaUJhc2VDb2luJztcbmltcG9ydCB7IElJbnNjcmlwdGlvbkJ1aWxkZXIgfSBmcm9tICcuLi9pbnNjcmlwdGlvbkJ1aWxkZXInO1xuaW1wb3J0IHsgSGFzaCB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgeyBNUENTd2VlcFJlY292ZXJ5T3B0aW9ucywgTVBDVHhzLCBQb3B1bGF0ZWRJbnRlbnQsIFByZWJ1aWxkVHJhbnNhY3Rpb25XaXRoSW50ZW50T3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VDb2luIGltcGxlbWVudHMgSUJhc2VDb2luIHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGJpdGdvOiBCaXRHb0Jhc2U7XG4gIHByb3RlY3RlZCByZWFkb25seSBfdXJsOiBzdHJpbmc7XG4gIHByb3RlY3RlZCByZWFkb25seSBfZW50ZXJwcmlzZXM6IEVudGVycHJpc2VzO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgX3dhbGxldHM6IFdhbGxldHM7XG4gIHByb3RlY3RlZCByZWFkb25seSBfa2V5Y2hhaW5zOiBLZXljaGFpbnM7XG4gIHByb3RlY3RlZCByZWFkb25seSBfd2ViaG9va3M6IFdlYmhvb2tzO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgX3BlbmRpbmdBcHByb3ZhbHM6IFBlbmRpbmdBcHByb3ZhbHM7XG4gIHByb3RlY3RlZCByZWFkb25seSBfbWFya2V0czogTWFya2V0cztcbiAgcHJvdGVjdGVkIHN0YXRpYyByZWFkb25seSBfY29pblRva2VuUGF0dGVyblNlcGFyYXRvciA9ICc6JztcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IF9zdGF0aWNzQ29pbjogUmVhZG9ubHk8U3RhdGljc0Jhc2VDb2luPjtcblxuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoYml0Z286IEJpdEdvQmFzZSkge1xuICAgIHRoaXMuYml0Z28gPSBiaXRnbztcbiAgICB0aGlzLl91cmwgPSB0aGlzLmJpdGdvLnVybCgnLycsIDIpO1xuICAgIHRoaXMuX3dhbGxldHMgPSBuZXcgV2FsbGV0cyh0aGlzLmJpdGdvLCB0aGlzKTtcbiAgICB0aGlzLl9rZXljaGFpbnMgPSBuZXcgS2V5Y2hhaW5zKHRoaXMuYml0Z28sIHRoaXMpO1xuICAgIHRoaXMuX3dlYmhvb2tzID0gbmV3IFdlYmhvb2tzKHRoaXMuYml0Z28sIHRoaXMpO1xuICAgIHRoaXMuX3BlbmRpbmdBcHByb3ZhbHMgPSBuZXcgUGVuZGluZ0FwcHJvdmFscyh0aGlzLmJpdGdvLCB0aGlzKTtcbiAgICB0aGlzLl9lbnRlcnByaXNlcyA9IG5ldyBFbnRlcnByaXNlcyh0aGlzLmJpdGdvLCB0aGlzKTtcbiAgICB0aGlzLl9tYXJrZXRzID0gbmV3IE1hcmtldHModGhpcy5iaXRnbywgdGhpcyk7XG4gIH1cblxuICBwdWJsaWMgdXJsKHN1ZmZpeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fdXJsICsgdGhpcy5nZXRDaGFpbigpICsgc3VmZml4O1xuICB9XG5cbiAgcHVibGljIHdhbGxldHMoKTogV2FsbGV0cyB7XG4gICAgcmV0dXJuIHRoaXMuX3dhbGxldHM7XG4gIH1cblxuICBwdWJsaWMgZW50ZXJwcmlzZXMoKTogRW50ZXJwcmlzZXMge1xuICAgIHJldHVybiB0aGlzLl9lbnRlcnByaXNlcztcbiAgfVxuXG4gIHB1YmxpYyBrZXljaGFpbnMoKTogS2V5Y2hhaW5zIHtcbiAgICByZXR1cm4gdGhpcy5fa2V5Y2hhaW5zO1xuICB9XG5cbiAgcHVibGljIHdlYmhvb2tzKCk6IFdlYmhvb2tzIHtcbiAgICByZXR1cm4gdGhpcy5fd2ViaG9va3M7XG4gIH1cblxuICBwdWJsaWMgcGVuZGluZ0FwcHJvdmFscygpOiBQZW5kaW5nQXBwcm92YWxzIHtcbiAgICByZXR1cm4gdGhpcy5fcGVuZGluZ0FwcHJvdmFscztcbiAgfVxuXG4gIHB1YmxpYyBtYXJrZXRzKCk6IE1hcmtldHMge1xuICAgIHJldHVybiB0aGlzLl9tYXJrZXRzO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBnZXQgY29pblRva2VuUGF0dGVyblNlcGFyYXRvcigpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl9jb2luVG9rZW5QYXR0ZXJuU2VwYXJhdG9yO1xuICB9XG5cbiAgcHVibGljIGdldCB0eXBlKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0Q2hhaW4oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBzdGF0aWNzIGNvaW4gb2JqZWN0XG4gICAqIEByZXR1cm5zIHtSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+fSB0aGUgc3RhdGljcyBjb2luIG9iamVjdFxuICAgKi9cbiAgZ2V0Q29uZmlnKCk6IFJlYWRvbmx5PFN0YXRpY3NCYXNlQ29pbj4ge1xuICAgIHJldHVybiB0aGlzLl9zdGF0aWNzQ29pbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSBjaGFpbiB3aGljaCBzdXBwb3J0cyB0aGlzIGNvaW4gKGVnLCAnYnRjJywgJ2V0aCcpXG4gICAqL1xuICBhYnN0cmFjdCBnZXRDaGFpbigpOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIGNvaW4gZmFtaWx5IChlZy4gZm9yIHRidGMsIHRoaXMgd291bGQgYmUgYnRjKVxuICAgKi9cbiAgYWJzdHJhY3QgZ2V0RmFtaWx5KCk6IHN0cmluZztcblxuICAvKipcbiAgICogSHVtYW4gcmVhZGFibGUgZnVsbCBuYW1lIGZvciB0aGUgY29pblxuICAgKi9cbiAgYWJzdHJhY3QgZ2V0RnVsbE5hbWUoKTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBGbGFnIGZvciBzZW5kaW5nIHZhbHVlIG9mIDAuXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIG9rYXkgdG8gc2VuZCAwIHZhbHVlLCBmYWxzZSBvdGhlcndpc2VcbiAgICovXG4gIHZhbHVlbGVzc1RyYW5zZmVyQWxsb3dlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogVXNlIGBzZW5kTWFueSgpYCB0byBwZXJmb3JtIHdhbGxldCBzd2VlcC5cbiAgICogRklYTUUoQkctMzk3MzgpOiBhZGQgY29pbi5zd2VlcFdhbGxldCgpIGluc3RlYWRcbiAgICovXG4gIHN3ZWVwV2l0aFNlbmRNYW55KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGbGFnIGZvciBzZW5kaW5nIGRhdGEgYWxvbmcgd2l0aCB0cmFuc2FjdGlvbnNcbiAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgb2theSB0byBzZW5kIHR4IGRhdGEgKEVUSCksIGZhbHNlIG90aGVyd2lzZVxuICAgKi9cbiAgdHJhbnNhY3Rpb25EYXRhQWxsb3dlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogRmxhZyBmb3IgZGV0ZXJtaW5pbmcgd2hldGhlciB0aGlzIGNvaW4gc3VwcG9ydHMgYWNjb3VudCBjb25zb2xpZGF0aW9uc1xuICAgKiBmcm9tIGl0cyByZWNlaXZlIGFkZHJlc3NlcyB0byB0aGUgcm9vdCBhZGRyZXNzLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBva2F5IHRvIGNvbnNvbGlkYXRlIG92ZXIgdGhpcyBjb2luOyBmYWxzZSwgb3RoZXJ3aXNlXG4gICAqL1xuICBhbGxvd3NBY2NvdW50Q29uc29saWRhdGlvbnMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgY29uZmlnIGZvciBob3cgdG9rZW4gZW5hYmxlbWVudHMgd29yayBmb3IgdGhpcyBjb2luXG4gICAqIEByZXR1cm5zXG4gICAqICAgIHJlcXVpcmVzVG9rZW5FbmFibGVtZW50OiBUcnVlIGlmIHRva2VucyBuZWVkIHRvIGJlIGVuYWJsZWQgZm9yIHRoaXMgY29pblxuICAgKiAgICBzdXBwb3J0c011bHRpcGxlVG9rZW5FbmFibGVtZW50czogVHJ1ZSBpZiBtdWx0aXBsZSB0b2tlbnMgY2FuIGJlIGVuYWJsZWQgaW4gb25lIHRyYW5zYWN0aW9uXG4gICAqL1xuICBnZXRUb2tlbkVuYWJsZW1lbnRDb25maWcoKTogVG9rZW5FbmFibGVtZW50Q29uZmlnIHtcbiAgICByZXR1cm4ge1xuICAgICAgcmVxdWlyZXNUb2tlbkVuYWJsZW1lbnQ6IGZhbHNlLFxuICAgICAgc3VwcG9ydHNNdWx0aXBsZVRva2VuRW5hYmxlbWVudHM6IGZhbHNlLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRmxhZyBpbmRpY2F0aW5nIGlmIHRoaXMgY29pbiBzdXBwb3J0cyBUU1Mgd2FsbGV0cy5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgVFNTIFdhbGxldHMgY2FuIGJlIGNyZWF0ZWQgZm9yIHRoaXMgY29pblxuICAgKi9cbiAgc3VwcG9ydHNUc3MoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEZsYWcgaW5kaWNhdGluZyBpZiB0aGlzIGNvaW4gc3VwcG9ydHMgTXVsdGlTaWcgd2FsbGV0cy5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBNdWx0aVNpZyB3YWxsZXRzIGNhbiBiZSBjcmVhdGVkIGZvciB0aGlzIGNvaW5cbiAgICovXG4gIHN1cHBvcnRzTXVsdGlzaWcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEl0IHdpbGwgcmV0dXJuIHRoZSBkZWZhdWx0IG11bHRpc2lnIHR5cGUgdmFsdWUgZm9yIGNvaW5cbiAgICogQHJldHVybiB7TXVsdGlzaWdUeXBlfSByZXR1cm4gJ3RzcycgaWYgY29pbiBzdXBwb3J0cyBvbmx5IFRTUyBub3QgTXVsdGlTaWdcbiAgICogZWxzZSBpZiBjb2luIHN1cHBvcnRzIE11bHRpU2lnIHJldHVybiAnb25jaGFpbidcbiAgICogaWYgY29pbiBzdXBwb3J0cyBib3RoIHJldHVybiAnb25jaGFpbidcbiAgICogZWxzZSB1bmRlZmluZWRcbiAgICovXG4gIGdldERlZmF1bHRNdWx0aXNpZ1R5cGUoKTogTXVsdGlzaWdUeXBlIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIEZsYWcgaW5kaWNhdGluZyBpZiB0aGUgY29pbiBzdXBwb3J0cyBkZXJpdmluZyBhIGtleSB3aXRoIGEgc2VlZCAoa2V5SUQpXG4gICAqIHRvIHRoZSB1c2VyL2JhY2t1cCBrZXlzLlxuICAgKi9cbiAgc3VwcG9ydHNEZXJpdmVLZXlXaXRoU2VlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGbGFnIGluZGljYXRpbmcgaWYgdGhpcyBibG9ja2NoYWluIHJ1bnMgb24gRVZNIGFyY2hpdGVjdHVyZS5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIGJsb2NrY2hhaW4gcnVucyBvbiBFVk0gYXJjaGl0ZWN0dXJlLlxuICAgKi9cbiAgaXNFVk0oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEZsYWcgaW5kaWNhdGluZyBpZiB0aGlzIGNvaW4gc3VwcG9ydHMgQkxTLURLRyB3YWxsZXRzLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBCTFMtREtHIFdhbGxldHMgY2FuIGJlIGNyZWF0ZWQgZm9yIHRoaXMgY29pblxuICAgKi9cbiAgc3VwcG9ydHNCbHNEa2coKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGZhY3RvciBiZXR3ZWVuIHRoZSBiYXNlIHVuaXQgYW5kIGl0cyBzbWFsbGVzdCBzdWJkaXZpc29uXG4gICAqIEByZXR1cm4ge251bWJlcn1cbiAgICovXG4gIGFic3RyYWN0IGdldEJhc2VGYWN0b3IoKTogbnVtYmVyIHwgc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDb252ZXJ0IGEgY3VycmVuY3kgYW1vdW50IHJlcHJlc2VudGVkIGluIGJhc2UgdW5pdHMgKHNhdG9zaGksIHdlaSwgYXRvbXMsIGRyb3BzLCBzdHJvb3BzKVxuICAgKiB0byBiaWcgdW5pdHMgKGJ0YywgZXRoLCB4cnAsIHhsbSlcbiAgICovXG4gIGJhc2VVbml0c1RvQmlnVW5pdHMoYmFzZVVuaXRzOiBzdHJpbmcgfCBudW1iZXIpOiBzdHJpbmcge1xuICAgIEJpZ051bWJlci5zZXQoeyBERUNJTUFMX1BMQUNFUzogMjQgfSk7XG4gICAgY29uc3QgZGl2aWRlbmQgPSB0aGlzLmdldEJhc2VGYWN0b3IoKTtcbiAgICBjb25zdCBiaWdOdW1iZXIgPSBuZXcgQmlnTnVtYmVyKGJhc2VVbml0cykuZGl2aWRlZEJ5KGRpdmlkZW5kKTtcbiAgICAvLyBzZXQgdGhlIGZvcm1hdCBzbyBjb21tYXMgYXJlbid0IGFkZGVkIHRvIGxhcmdlIGNvaW4gYW1vdW50c1xuICAgIHJldHVybiBiaWdOdW1iZXIudG9Gb3JtYXQobnVsbCBhcyBhbnksIG51bGwgYXMgYW55LCB7IGdyb3VwU2VwYXJhdG9yOiAnJywgZGVjaW1hbFNlcGFyYXRvcjogJy4nIH0pO1xuICB9XG5cbiAgY2hlY2tSZWNpcGllbnQocmVjaXBpZW50OiB7IGFkZHJlc3M6IHN0cmluZzsgYW1vdW50OiBzdHJpbmcgfCBudW1iZXIgfSk6IHZvaWQge1xuICAgIGlmIChyZWNpcGllbnQuYW1vdW50ICE9PSAnbWF4Jykge1xuICAgICAgY29uc3QgYW1vdW50ID0gbmV3IEJpZ051bWJlcihyZWNpcGllbnQuYW1vdW50KTtcbiAgICAgIGlmIChhbW91bnQuaXNOZWdhdGl2ZSgpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBhcmd1bWVudCBmb3IgYW1vdW50IC0gcG9zaXRpdmUgbnVtYmVyIGdyZWF0ZXIgdGhhbiB6ZXJvIG9yIG51bWVyaWMgc3RyaW5nIGV4cGVjdGVkJyk7XG4gICAgICB9XG4gICAgICBpZiAoIXRoaXMudmFsdWVsZXNzVHJhbnNmZXJBbGxvd2VkKCkgJiYgYW1vdW50LmlzWmVybygpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBhcmd1bWVudCBmb3IgYW1vdW50IC0gcG9zaXRpdmUgbnVtYmVyIGdyZWF0ZXIgdGhhbiB6ZXJvIG9yIG51bWVyaWMgc3RyaW5nIGV4cGVjdGVkJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnQgYSBjdXJyZW5jeSBhbW91bnQgcmVwcmVzZW50ZWQgaW4gYmlnIHVuaXRzIChidGMsIGV0aCwgeHJwLCB4bG0pXG4gICAqIHRvIGJhc2UgdW5pdHMgKHNhdG9zaGksIHdlaSwgYXRvbXMsIGRyb3BzLCBzdHJvb3BzKVxuICAgKiBAcGFyYW0gYmlnVW5pdHNcbiAgICovXG4gIGJpZ1VuaXRzVG9CYXNlVW5pdHMoYmlnVW5pdHM6IHN0cmluZyB8IG51bWJlcik6IHN0cmluZyB7XG4gICAgY29uc3QgbXVsdGlwbGllciA9IHRoaXMuZ2V0QmFzZUZhY3RvcigpO1xuICAgIGNvbnN0IGJpZ051bWJlciA9IG5ldyBCaWdOdW1iZXIoYmlnVW5pdHMpLnRpbWVzKG11bHRpcGxpZXIpO1xuICAgIGlmICghYmlnTnVtYmVyLmlzSW50ZWdlcigpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYG5vbi1pbnRlZ2VyIG91dHB1dCByZXN1bHRlZCBmcm9tIG11bHRpcGx5aW5nICR7YmlnVW5pdHN9IGJ5ICR7bXVsdGlwbGllcn1gKTtcbiAgICB9XG4gICAgcmV0dXJuIGJpZ051bWJlci50b0ZpeGVkKDApO1xuICB9XG5cbiAgLyoqXG4gICAqIFByZXByb2Nlc3MgdGhlIGJ1aWxkIHBhcmFtZXRlcnMgYmVmb3JlIHNlbmRpbmcgdG8gdGhlIEFQSVxuICAgKiBAcGFyYW0gYnVpbGRQYXJhbXNcbiAgICovXG4gIHByZXByb2Nlc3NCdWlsZFBhcmFtcyhidWlsZFBhcmFtczogUmVjb3JkPHN0cmluZywgYW55Pik6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuICAgIHJldHVybiBidWlsZFBhcmFtcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTaWduIG1lc3NhZ2Ugd2l0aCBwcml2YXRlIGtleVxuICAgKlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBtZXNzYWdlXG4gICAqL1xuICBhc3luYyBzaWduTWVzc2FnZShrZXk6IHsgcHJ2OiBzdHJpbmcgfSwgbWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxCdWZmZXI+IHtcbiAgICByZXR1cm4gc2lnbk1lc3NhZ2UobWVzc2FnZSwgYmlwMzIuZnJvbUJhc2U1OChrZXkucHJ2KSwgdXR4b2xpYi5uZXR3b3Jrcy5iaXRjb2luKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgc2lnbmF0dXJlcyBmb3IgdGhlIGJhY2t1cCBhbmQgYml0Z28ga2V5cyB1c2luZyB0aGUgdXNlciBrZXkuXG4gICAqIFdlIGNhbiB2ZXJpZnkgdGhlIHNpZ25hdHVyZXMgd2hlbiBmZXRjaGluZyB0aGUga2V5cyBmcm9tIHdhbGxldC1wbGF0Zm9ybSBsYXRlci5cbiAgICogQ3VycmVudGx5IG9ubHkgYEFic3RyYWN0VXR4b0NvaW5gIGltcGxlbWVudHMgYW5kIHVzZXMgdGhlIGNvbXBsZW1lbnRhcnkgYHZlcmlmeUtleVNpZ25hdHVyZWAgbWV0aG9kLlxuICAgKiBAcGFyYW0gcHJ2IC0gdGhlIHVzZXIgcHJpdmF0ZSBrZXlcbiAgICogQHBhcmFtIGJhY2t1cEtleWNoYWluIC0gY29udGFpbnMgdGhlIGJhY2t1cCBwdWJsaWMga2V5XG4gICAqIEBwYXJhbSBiaXRnb0tleWNoYWluIC0gY29udGFpbnMgdGhlIGJpdGdvIHB1YmxpYyBrZXlcbiAgICovXG4gIHB1YmxpYyBhc3luYyBjcmVhdGVLZXlTaWduYXR1cmVzKFxuICAgIHBydjogc3RyaW5nLFxuICAgIGJhY2t1cEtleWNoYWluOiB7IHB1Yjogc3RyaW5nIH0sXG4gICAgYml0Z29LZXljaGFpbjogeyBwdWI6IHN0cmluZyB9XG4gICk6IFByb21pc2U8e1xuICAgIGJhY2t1cDogc3RyaW5nO1xuICAgIGJpdGdvOiBzdHJpbmc7XG4gIH0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgYmFja3VwOiAoYXdhaXQgdGhpcy5zaWduTWVzc2FnZSh7IHBydiB9LCBiYWNrdXBLZXljaGFpbi5wdWIpKS50b1N0cmluZygnaGV4JyksXG4gICAgICBiaXRnbzogKGF3YWl0IHRoaXMuc2lnbk1lc3NhZ2UoeyBwcnYgfSwgYml0Z29LZXljaGFpbi5wdWIpKS50b1N0cmluZygnaGV4JyksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNvbXBvc2UgYSByYXcgdHJhbnNhY3Rpb24gaW50byB1c2VmdWwgaW5mb3JtYXRpb24uXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gY29pbi1zcGVjaWZpY1xuICAgKi9cbiAgZXhwbGFpblRyYW5zYWN0aW9uKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQcm9taXNlPElUcmFuc2FjdGlvbkV4cGxhbmF0aW9uPGFueSwgc3RyaW5nIHwgbnVtYmVyPiB8IHVuZGVmaW5lZD4ge1xuICAgIHRocm93IG5ldyBFcnJvcihgbm90IGltcGxlbWVudGVkYCk7XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZ5IHRoYXQgYSB0cmFuc2FjdGlvbiBwcmVidWlsZCBjb21wbGllcyB3aXRoIHRoZSBvcmlnaW5hbCBpbnRlbnRpb25cbiAgICovXG4gIGFic3RyYWN0IHZlcmlmeVRyYW5zYWN0aW9uKHBhcmFtczogVmVyaWZ5VHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxib29sZWFuPjtcblxuICAvKipcbiAgICogQGRlcHJlY2F0ZWQgdXNlIHtAc2VlIGlzV2FsbGV0QWRkcmVzc30gaW5zdGVhZFxuICAgKi9cbiAgdmVyaWZ5QWRkcmVzcyhwYXJhbXM6IFZlcmlmeUFkZHJlc3NPcHRpb25zKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMuaXNXYWxsZXRBZGRyZXNzKHBhcmFtcyk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKiBAcmV0dXJuIHRydWUgaWZmIGFkZHJlc3MgaXMgYSB3YWxsZXQgYWRkcmVzcy4gTXVzdCByZXR1cm4gZmFsc2UgaWYgYWRkcmVzcyBpcyBvdXRzaWRlIHdhbGxldC5cbiAgICovXG4gIGFic3RyYWN0IGlzV2FsbGV0QWRkcmVzcyhwYXJhbXM6IFZlcmlmeUFkZHJlc3NPcHRpb25zKTogUHJvbWlzZTxib29sZWFuPjtcblxuICAvKipcbiAgICogY29udmVydCBhZGRyZXNzIGludG8gZGVzaXJlZCBhZGRyZXNzIGZvcm1hdC5cbiAgICogQHBhcmFtIGFkZHJlc3NcbiAgICogQHBhcmFtIGZvcm1hdFxuICAgKi9cbiAgY2Fub25pY2FsQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcsIGZvcm1hdD86IHVua25vd24pOiBzdHJpbmcge1xuICAgIHJldHVybiBhZGRyZXNzO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIHdoZXRoZXIgYSBjb2luIHN1cHBvcnRzIGJsb2NrVGFyZ2V0IGZvciB0cmFuc2FjdGlvbnMgdG8gYmUgaW5jbHVkZWQgaW5cbiAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAqL1xuICBzdXBwb3J0c0Jsb2NrVGFyZ2V0KCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayB3aGV0aGVyIGEgY29pbiBzdXBwb3J0cyBsaWdodG5pbmcgdHJhbnNhY3Rpb25zXG4gICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgKi9cbiAgc3VwcG9ydHNMaWdodG5pbmcoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIHdoZXRoZXIgYSBjb2luIHN1cHBvcnRzIG1lc3NhZ2Ugc2lnbmluZ1xuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIHN1cHBvcnRzTWVzc2FnZVNpZ25pbmcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIHdoZXRoZXIgYSBjb2luIHN1cHBvcnRzIHNpZ25pbmcgb2YgVHlwZWQgZGF0YVxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIHN1cHBvcnRzU2lnbmluZ1R5cGVkRGF0YSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogSG9vayB0byBhZGQgYWRkaXRpb25hbCBwYXJhbWV0ZXJzIHRvIHRoZSB3YWxsZXQgZ2VuZXJhdGlvblxuICAgKiBAcGFyYW0gd2FsbGV0UGFyYW1zXG4gICAqIEBwYXJhbSBrZXljaGFpbnNcbiAgICogQHJldHVybiB7Kn1cbiAgICovXG4gIHN1cHBsZW1lbnRHZW5lcmF0ZVdhbGxldCh3YWxsZXRQYXJhbXM6IFN1cHBsZW1lbnRHZW5lcmF0ZVdhbGxldE9wdGlvbnMsIGtleWNoYWluczogS2V5Y2hhaW5zVHJpcGxldCk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh3YWxsZXRQYXJhbXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBleHRyYSBwYXJhbWV0ZXJzIGZvciBwcmVidWlsZGluZyBhIHR4LiBBZGQgdGhpbmdzIGxpa2UgaG9wIHRyYW5zYWN0aW9uIHBhcmFtc1xuICAgKi9cbiAgZ2V0RXh0cmFQcmVidWlsZFBhcmFtcyhidWlsZFBhcmFtczogRXh0cmFQcmVidWlsZFBhcmFtc09wdGlvbnMpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHVua25vd24+PiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7fSk7XG4gIH1cblxuICAvKipcbiAgICogTW9kaWZ5IHByZWJ1aWxkIGFmdGVyIHJlY2VpdmluZyBpdCBmcm9tIHRoZSBzZXJ2ZXIuIEFkZCB0aGluZ3MgbGlrZSBubG9ja3RpbWVcbiAgICovXG4gIHBvc3RQcm9jZXNzUHJlYnVpbGQocHJlYnVpbGRSZXNwb25zZTogVHJhbnNhY3Rpb25QcmVidWlsZCk6IFByb21pc2U8VHJhbnNhY3Rpb25QcmVidWlsZD4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocHJlYnVpbGRSZXNwb25zZSk7XG4gIH1cblxuICAvKipcbiAgICogQ29pbi1zcGVjaWZpYyB0aGluZ3MgZG9uZSBiZWZvcmUgc2lnbmluZyBhIHRyYW5zYWN0aW9uLCBpLmUuIHZlcmlmaWNhdGlvblxuICAgKi9cbiAgcHJlc2lnblRyYW5zYWN0aW9uKHBhcmFtczogUHJlc2lnblRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8UHJlc2lnblRyYW5zYWN0aW9uT3B0aW9ucz4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgd2FsbGV0IG9iamVjdCBmcm9tIGEgd2FsbGV0IGRhdGEgb2JqZWN0XG4gICAqIEBwYXJhbSB3YWxsZXRQYXJhbXNcbiAgICovXG4gIG5ld1dhbGxldE9iamVjdCh3YWxsZXRQYXJhbXM6IGFueSk6IElXYWxsZXQge1xuICAgIHJldHVybiBuZXcgV2FsbGV0KHRoaXMuYml0Z28sIHRoaXMsIHdhbGxldFBhcmFtcyk7XG4gIH1cblxuICAvKipcbiAgICogRmV0Y2ggZmVlIGVzdGltYXRlIGluZm9ybWF0aW9uIGZyb20gdGhlIHNlcnZlclxuICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zIFRoZSBwYXJhbXMgcGFzc2VkIGludG8gdGhlIGZ1bmN0aW9uXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gcGFyYW1zLm51bUJsb2NrcyBUaGUgbnVtYmVyIG9mIGJsb2NrcyB0byB0YXJnZXQgZm9yIGNvbmZvcm1hdGlvbiAoT25seSB3b3JrcyBmb3IgYnRjKVxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgaW5mbyByZXR1cm5lZCBmcm9tIHRoZSBtZXJjaGFudCBzZXJ2ZXJcbiAgICovXG4gIGFzeW5jIGZlZUVzdGltYXRlKHBhcmFtczogRmVlRXN0aW1hdGVPcHRpb25zKTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCBxdWVyeTogYW55ID0ge307XG4gICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMubnVtQmxvY2tzKSB7XG4gICAgICBxdWVyeS5udW1CbG9ja3MgPSBwYXJhbXMubnVtQmxvY2tzO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmJpdGdvLmdldCh0aGlzLnVybCgnL3R4L2ZlZScpKS5xdWVyeShxdWVyeSkucmVzdWx0KCk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGNvbGQgd2FsbGV0IHRvb2wgdXNlcyB0aGlzIGZ1bmN0aW9uIHRvIGRlcml2ZSBhbiBleHRlbmRlZCBrZXkgdGhhdCBpcyBiYXNlZCBvbiB0aGUgcGFzc2VkIGtleSBhbmQgc2VlZFxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBzZWVkXG4gICAqIEByZXR1cm5zIHt7a2V5OiBzdHJpbmcsIGRlcml2YXRpb25QYXRoOiBzdHJpbmd9fVxuICAgKi9cbiAgc3RhdGljIGRlcml2ZUtleVdpdGhTZWVkQmlwMzIoXG4gICAga2V5OiB1dHhvbGliLkJJUDMySW50ZXJmYWNlLFxuICAgIHNlZWQ6IHN0cmluZ1xuICApOiB7XG4gICAga2V5OiB1dHhvbGliLkJJUDMySW50ZXJmYWNlO1xuICAgIGRlcml2YXRpb25QYXRoOiBzdHJpbmc7XG4gIH0ge1xuICAgIGZ1bmN0aW9uIHNoYTI1NihpbnB1dCkge1xuICAgICAgcmV0dXJuIGNyeXB0by5jcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoaW5wdXQpLmRpZ2VzdCgpO1xuICAgIH1cbiAgICBjb25zdCBkZXJpdmF0aW9uUGF0aElucHV0ID0gc2hhMjU2KHNoYTI1NihgJHtzZWVkfWApKS50b1N0cmluZygnaGV4Jyk7XG4gICAgY29uc3QgZGVyaXZhdGlvblBhdGhQYXJ0cyA9IFtcbiAgICAgIHBhcnNlSW50KGRlcml2YXRpb25QYXRoSW5wdXQuc2xpY2UoMCwgNyksIDE2KSxcbiAgICAgIHBhcnNlSW50KGRlcml2YXRpb25QYXRoSW5wdXQuc2xpY2UoNywgMTQpLCAxNiksXG4gICAgXTtcbiAgICBjb25zdCBkZXJpdmF0aW9uUGF0aCA9ICdtLzk5OTk5OS8nICsgZGVyaXZhdGlvblBhdGhQYXJ0cy5qb2luKCcvJyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGtleToga2V5LmRlcml2ZVBhdGgoZGVyaXZhdGlvblBhdGgpLFxuICAgICAgZGVyaXZhdGlvblBhdGgsXG4gICAgfTtcbiAgfVxuXG4gIC8qKiB7QHNlZSBkZXJpdmVLZXlXaXRoU2VlZEJpcDMyfSAqL1xuICBkZXJpdmVLZXlXaXRoU2VlZChwYXJhbXM6IERlcml2ZUtleVdpdGhTZWVkT3B0aW9ucyk6IHtcbiAgICBrZXk6IHN0cmluZztcbiAgICBkZXJpdmF0aW9uUGF0aDogc3RyaW5nO1xuICB9IHtcbiAgICBjb25zdCB7IGtleSwgZGVyaXZhdGlvblBhdGggfSA9IEJhc2VDb2luLmRlcml2ZUtleVdpdGhTZWVkQmlwMzIoYmlwMzIuZnJvbUJhc2U1OChwYXJhbXMua2V5KSwgcGFyYW1zLnNlZWQpO1xuICAgIHJldHVybiB7XG4gICAgICBrZXk6IGtleS50b0Jhc2U1OCgpLFxuICAgICAgZGVyaXZhdGlvblBhdGgsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgd2hhdCBrZXkgd2Ugd2lsbCBuZWVkIGZvciBzaWduaW5nIC0gcmlnaHQgbm93IHdlIGp1c3QgbmVlZCB0aGVcbiAgICogdXNlciBrZXkuXG4gICAqL1xuICBrZXlJZHNGb3JTaWduaW5nKCk6IG51bWJlcltdIHtcbiAgICByZXR1cm4gW0tleUluZGljZXMuVVNFUl07XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybSBhZGRpdGlvbmFsIGNoZWNrcyBiZWZvcmUgYWRkaW5nIGEgYml0Z28ga2V5LiBCYXNlIGNvbnRyb2xsZXJcbiAgICogaXMgYSBuby1vcCwgYnV0IGNvaW4tc3BlY2lmaWMgY29udHJvbGxlciBtYXkgZG8gc29tZXRoaW5nXG4gICAqIEBwYXJhbSBwYXJhbXNcbiAgICovXG4gIHByZUNyZWF0ZUJpdEdvKHBhcmFtczogUHJlY3JlYXRlQml0R29PcHRpb25zKTogdm9pZCB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIC0gdXNlIGdldEJpcDMyS2V5cygpIGluIGNvbmp1bmN0aW9uIHdpdGggaXNWYWxpZEFkZHJlc3MgaW5zdGVhZFxuICAgKi9cbiAgaW5pdGlhdGVSZWNvdmVyeShwYXJhbXM6IEluaXRpYXRlUmVjb3ZlcnlPcHRpb25zKTogbmV2ZXIge1xuICAgIHRocm93IG5ldyBFcnJvcignZGVwcmVjYXRlZCBtZXRob2QnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPbmx5IHVzZWQgaW4gUGVuZGluZ0FwcHJvdmFsIGZvciBjb21wYXJpbmcgUEFZR28gZmVlcyBwdXJwb3NlXG4gICAqIEBwYXJhbSBwYXJhbXMgb3B0aW9ucyBmb3IgcGFyc2luZ1xuICAgKi9cbiAgYWJzdHJhY3QgcGFyc2VUcmFuc2FjdGlvbihwYXJhbXM6IFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxQYXJzZWRUcmFuc2FjdGlvbj47XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIGEga2V5IHBhaXIgb24gdGhlIGN1cnZlIHVzZWQgYnkgdGhlIGNvaW5cbiAgICogQHBhcmFtIHtCdWZmZXJ9IHNlZWQgLSBzZWVkIHRvIHVzZSBmb3Iga2V5IHBhaXIgZ2VuZXJhdGlvblxuICAgKiBAcmV0dXJucyB7S2V5UGFpcn0gdGhlIGdlbmVyYXRlZCBrZXkgcGFpclxuICAgKi9cbiAgYWJzdHJhY3QgZ2VuZXJhdGVLZXlQYWlyKHNlZWQ/OiBCdWZmZXIpOiBLZXlQYWlyO1xuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSBhIHJvb3Qga2V5IHBhaXIgb24gdGhlIGN1cnZlIHVzZWQgYnkgdGhlIGNvaW5cbiAgICogQHBhcmFtIHtCdWZmZXJ9IHNlZWQgLSBzZWVkIHRvIHVzZSBmb3Iga2V5IHBhaXIgZ2VuZXJhdGlvblxuICAgKiBAcmV0dXJucyB7S2V5UGFpcn0gdGhlIGdlbmVyYXRlZCBrZXkgcGFpclxuICAgKi9cbiAgZ2VuZXJhdGVSb290S2V5UGFpcihzZWVkPzogQnVmZmVyKTogS2V5UGFpciB7XG4gICAgdGhyb3cgbmV3IE5vdEltcGxlbWVudGVkRXJyb3IoJ2dlbmVyYXRlUm9vdEtleVBhaXIgaXMgbm90IHN1cHBvcnRlZCBmb3IgdGhpcyBjb2luJyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGJvb2xlYW4gaW5kaWNhdGluZyB3aGV0aGVyIGlucHV0IGlzIHZhbGlkIHB1YmxpYyBrZXkgZm9yIHRoZSBjb2luLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHViIHRoZSBwdWIgdG8gYmUgY2hlY2tlZFxuICAgKiBAcmV0dXJucyB7Qm9vbGVhbn0gaXMgaXQgdmFsaWQ/XG4gICAqL1xuICBhYnN0cmFjdCBpc1ZhbGlkUHViKHB1Yjogc3RyaW5nKTogYm9vbGVhbjtcblxuICAvKipcbiAgICogUmV0dXJuIHdldGhlciB0aGUgZ2l2ZW4gbSBvZiBuIHdhbGxldCBzaWduZXJzLyBrZXkgYW1vdW50cyBhcmUgdmFsaWQgZm9yIHRoZSBjb2luXG4gICAqL1xuICBpc1ZhbGlkTW9mTlNldHVwKHsgbSwgbiB9OiB7IG0/OiBudW1iZXI7IG4/OiBudW1iZXIgfSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBtID09PSAyICYmIG4gPT09IDM7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgYGFkZHJlc3NgIGlzIGEgcGxhdXNpYmx5IHZhbGlkIGFkZHJlc3MgZm9yIHRoZSBnaXZlbiBjb2luLlxuICAgKlxuICAgKiBEb2VzIG5vdCB2ZXJpZnkgdGhhdCB0aGUgYWRkcmVzcyBiZWxvbmdzIHRvIGEgd2FsbGV0LiBGb3IgdGhhdCxcbiAgICogdXNlIFtbdmVyaWZ5QWRkcmVzc11dXG4gICAqIEBwYXJhbSBhZGRyZXNzXG4gICAqL1xuICBhYnN0cmFjdCBpc1ZhbGlkQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBTaWduIGEgdHJhbnNhY3Rpb25cbiAgICovXG4gIGFic3RyYWN0IHNpZ25UcmFuc2FjdGlvbihwYXJhbXM6IFNpZ25UcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPFNpZ25lZFRyYW5zYWN0aW9uPjtcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgcG9ydGlvbiBvZiB0aGUgdHJhbnNhY3Rpb24gdGhhdCBuZWVkcyB0byBiZSBzaWduZWQgaW4gQnVmZmVyIGZvcm1hdC5cbiAgICogT25seSBuZWVkZWQgZm9yIGNvaW5zIHRoYXQgc3VwcG9ydCBhZGRpbmcgc2lnbmF0dXJlcyBkaXJlY3RseSAoZS5nLiBUU1MpLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc2VyaWFsaXplZFR4IC0gdGhlIHVuc2lnbmVkIHRyYW5zYWN0aW9uIGluIGJyb2FkY2FzdCBmb3JtYXRcbiAgICogQHJldHVybnMge1Byb21pc2U8QnVmZmVyPn0gLSB0aGUgcG9ydGlvbiBvZiB0aGUgdHJhbnNhY3Rpb24gdGhhdCBuZWVkcyB0byBiZSBzaWduZWRcbiAgICovXG4gIGFzeW5jIGdldFNpZ25hYmxlUGF5bG9hZChzZXJpYWxpemVkVHg6IHN0cmluZyk6IFByb21pc2U8QnVmZmVyPiB7XG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKHNlcmlhbGl6ZWRUeCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgTVBDIGFsZ29yaXRobSAoZWNkc2Egb3IgZWRkc2EpIHVzZWQgZm9yIGNvaW5zIHRoYXQgc3VwcG9ydCBUU1NcbiAgICovXG4gIGdldE1QQ0FsZ29yaXRobSgpOiBNUENBbGdvcml0aG0ge1xuICAgIHRocm93IG5ldyBFcnJvcignbm8gTVBDIGFsZ29yaXRobSBpcyBkZWZpbmVkIGZvciB0aGlzIGNvaW4nKTtcbiAgfVxuXG4gIGFzeW5jIHJlY292ZXJUb2tlbihwYXJhbXM6IFJlY292ZXJXYWxsZXRUb2tlbk9wdGlvbnMpOiBQcm9taXNlPFJlY292ZXJUb2tlblRyYW5zYWN0aW9uPiB7XG4gICAgdGhyb3cgbmV3IE5vdEltcGxlbWVudGVkRXJyb3IoJ3JlY292ZXJUb2tlbiBpcyBub3Qgc3VwcG9ydGVkIGZvciB0aGlzIGNvaW4nKTtcbiAgfVxuXG4gIGdldEluc2NyaXB0aW9uQnVpbGRlcih3YWxsZXQ6IFdhbGxldCk6IElJbnNjcmlwdGlvbkJ1aWxkZXIge1xuICAgIHRocm93IG5ldyBOb3RJbXBsZW1lbnRlZEVycm9yKCdJbnNjcmlwdGlvbiBCdWlsZGVyIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIHRoaXMgY29pbicpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZ1bmN0aW9uIHRvIGdldCBjb2luIHNwZWNpZmljIGhhc2ggZnVuY3Rpb24gdXNlZCB0byBnZW5lcmF0ZSB0cmFuc2FjdGlvbiBkaWdlc3RzLlxuICAgKiBAcmV0dXJucyB7QHNlZSBIYXNofSBoYXNoIGZ1bmN0aW9uIGlmIGltcGxlbWVudGVkLCBvdGhlcndpc2UgdGhyb3dzIGV4Y2VwdGlvblxuICAgKi9cbiAgZ2V0SGFzaEZ1bmN0aW9uKCk6IEhhc2gge1xuICAgIHRocm93IG5ldyBOb3RJbXBsZW1lbnRlZEVycm9yKCdnZXRIYXNoRnVuY3Rpb24gaXMgbm90IHN1cHBvcnRlZCBmb3IgdGhpcyBjb2luJyk7XG4gIH1cblxuICBidWlsZE5mdFRyYW5zZmVyRGF0YShwYXJhbXM6IEJ1aWxkTmZ0VHJhbnNmZXJEYXRhT3B0aW9ucyk6IHN0cmluZyB7XG4gICAgdGhyb3cgbmV3IE5vdEltcGxlbWVudGVkRXJyb3IoJ2J1aWxkTmZ0VHJhbnNmZXJEYXRhIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIHRoaXMgY29pbicpO1xuICB9XG5cbiAgLyoqXG4gICAqIEJyb2FkY2FzdCBhIHRyYW5zYWN0aW9uIHRvIHRoZSBuZXR3b3JrXG4gICAqIEBwYXJhbSBwYXJhbXMgb3B0aW9ucyBmb3IgYnJvYWRjYXN0aW5nXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPEJhc2VCcm9hZGNhc3RUcmFuc2FjdGlvblJlc3VsdD59IHJlc3VsdCBvZiBicm9hZGNhc3RcbiAgICogQHRocm93cyB7Tm90SW1wbGVtZW50ZWRFcnJvcn0gaWYgbm90IGltcGxlbWVudGVkXG4gICAqL1xuICBicm9hZGNhc3RUcmFuc2FjdGlvbihwYXJhbXM6IEJhc2VCcm9hZGNhc3RUcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPEJhc2VCcm9hZGNhc3RUcmFuc2FjdGlvblJlc3VsdD4ge1xuICAgIHRocm93IG5ldyBOb3RJbXBsZW1lbnRlZEVycm9yKCdicm9hZGNhc3RUcmFuc2FjdGlvbiBpcyBub3Qgc3VwcG9ydGVkIGZvciB0aGlzIGNvaW4nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGZ1bmRzIHN3ZWVwIHJlY292ZXJ5IHRyYW5zYWN0aW9uKHMpIHdpdGhvdXQgQml0R29cbiAgICpcbiAgICogQHBhcmFtIHtNUENTd2VlcFJlY292ZXJ5T3B0aW9uc30gcGFyYW1zIHBhcmFtZXRlcnMgbmVlZGVkIHRvIGNvbWJpbmUgdGhlIHNpZ25hdHVyZXNcbiAgICogYW5kIHRyYW5zYWN0aW9ucyB0byBjcmVhdGUgYnJvYWRjYXN0YWJsZSB0cmFuc2FjdGlvbnNcbiAgICpcbiAgICogQHJldHVybnMge01QQ1R4c30gYXJyYXkgb2YgdGhlIHNlcmlhbGl6ZWQgdHJhbnNhY3Rpb24gaGV4IHN0cmluZ3MgYW5kIGluZGljZXNcbiAgICogb2YgdGhlIGFkZHJlc3NlcyBiZWluZyBzd2VwdFxuICAgKi9cbiAgYXN5bmMgY3JlYXRlQnJvYWRjYXN0YWJsZVN3ZWVwVHJhbnNhY3Rpb24ocGFyYW1zOiBNUENTd2VlcFJlY292ZXJ5T3B0aW9ucyk6IFByb21pc2U8TVBDVHhzPiB7XG4gICAgdGhyb3cgbmV3IE5vdEltcGxlbWVudGVkRXJyb3IoJ2NyZWF0ZUJyb2FkY2FzdGFibGVTd2VlcFRyYW5zYWN0aW9uIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIHRoaXMgY29pbicpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgY29pbnNwZWNpZmljIGZpZWxkcyBpbiBpbnRlbnQgZnJvbSBpbnB1dCBwYXJhbXMuXG4gICAqIFRoaXMgbWV0aG9kIHNob3VsZCBiZSBvdmVycmlkZGVuIGluIGNvaW4tc3BlY2lmaWMgY2xhc3Nlc1xuICAgKiB0byBjb25maWd1cmUgdGhlc2UgZmllbGRzIGluIHRoZSBpbnRlbnRcbiAgICogQHBhcmFtIGludGVudCAtIGludGVudCBpbiB3aGljaCBjb2luc3BlY2lmaWMgZmllbGRzIGFyZSB0byBiZSBzZXRcbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKi9cbiAgc2V0Q29pblNwZWNpZmljRmllbGRzSW5JbnRlbnQoaW50ZW50OiBQb3B1bGF0ZWRJbnRlbnQsIHBhcmFtczogUHJlYnVpbGRUcmFuc2FjdGlvbldpdGhJbnRlbnRPcHRpb25zKTogdm9pZCB7XG4gICAgcmV0dXJuO1xuICB9XG59XG4iXX0=

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


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