PHP WebShell

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

Просмотр файла: transaction.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 });
exports.Transaction = void 0;
const sdk_core_1 = require("@bitgo/sdk-core");
const constants_1 = require("./constants");
const utils_1 = __importDefault(require("./utils"));
const keyPair_1 = require("./keyPair");
const nearAPI = __importStar(require("near-api-js"));
const sha256 = __importStar(require("js-sha256"));
const bs58_1 = __importDefault(require("bs58"));
class Transaction extends sdk_core_1.BaseTransaction {
    constructor(coinConfig) {
        super(coinConfig);
    }
    get nearTransaction() {
        return this._nearTransaction;
    }
    set nearTransaction(tx) {
        this._nearTransaction = tx;
        this._id = utils_1.default.base58Encode(this.getTransactionHash());
    }
    /** @inheritdoc */
    canSign(key) {
        try {
            new keyPair_1.KeyPair({ prv: key.key });
            return true;
        }
        catch {
            return false;
        }
    }
    /** @inheritdoc */
    toBroadcastFormat() {
        if (!this._nearTransaction) {
            throw new sdk_core_1.InvalidTransactionError('Empty transaction data');
        }
        const txSeralized = this._nearSignedTransaction
            ? Buffer.from(this._nearSignedTransaction.encode()).toString('base64')
            : Buffer.from(this._nearTransaction.encode()).toString('base64');
        return txSeralized;
    }
    /** @inheritdoc */
    toJson() {
        if (!this._nearTransaction) {
            throw new sdk_core_1.InvalidTransactionError('Empty transaction data');
        }
        let parsedAction = {};
        if (this._nearTransaction.actions[0].enum === 'transfer') {
            parsedAction = { transfer: this._nearTransaction.actions[0].transfer };
        }
        else if (this._nearTransaction.actions[0].enum === 'functionCall') {
            const functionCallObject = this._nearTransaction.actions[0].functionCall;
            parsedAction = {
                functionCall: {
                    methodName: functionCallObject.methodName,
                    args: JSON.parse(Buffer.from(functionCallObject.args).toString()),
                    gas: functionCallObject.gas.toString(),
                    deposit: functionCallObject.deposit.toString(),
                },
            };
        }
        return {
            id: this._id,
            signerId: this._nearTransaction.signerId,
            publicKey: this._nearTransaction.publicKey.toString(),
            nonce: this._nearTransaction.nonce,
            receiverId: this._nearTransaction.receiverId,
            actions: [parsedAction],
            signature: typeof this._nearSignedTransaction === 'undefined' ? undefined : this._nearSignedTransaction.signature,
        };
    }
    /**
     * Set the transaction type.
     *
     * @param {TransactionType} transactionType The transaction type to be set.
     */
    setTransactionType(transactionType) {
        this._type = transactionType;
    }
    /**
     * Sets this transaction payload
     *
     * @param rawTx
     */
    fromRawTransaction(rawTx) {
        const bufferRawTransaction = constants_1.HEX_REGEX.test(rawTx) ? Buffer.from(rawTx, 'hex') : Buffer.from(rawTx, 'base64');
        try {
            const signedTx = nearAPI.utils.serialize.deserialize(nearAPI.transactions.SCHEMA, nearAPI.transactions.SignedTransaction, bufferRawTransaction);
            signedTx.transaction.nonce = parseInt(signedTx.transaction.nonce.toString(), 10);
            this._nearSignedTransaction = signedTx;
            this._nearTransaction = signedTx.transaction;
            this._id = utils_1.default.base58Encode(this.getTransactionHash());
        }
        catch (e) {
            try {
                const unsignedTx = nearAPI.utils.serialize.deserialize(nearAPI.transactions.SCHEMA, nearAPI.transactions.Transaction, bufferRawTransaction);
                unsignedTx.nonce = parseInt(unsignedTx.nonce.toString(), 10);
                this._nearTransaction = unsignedTx;
                this._id = utils_1.default.base58Encode(this.getTransactionHash());
            }
            catch (e) {
                throw new sdk_core_1.InvalidTransactionError('unable to build transaction from raw');
            }
        }
        this.loadInputsAndOutputs();
    }
    /**
     * Sign this transaction
     *
     * @param {KeyPair} signer key
     */
    sign(signer) {
        if (!this._nearTransaction) {
            throw new sdk_core_1.InvalidTransactionError('empty transaction to sign');
        }
        const serializedTxHash = this.getTransactionHash();
        const signature = signer.signMessageinUint8Array(serializedTxHash);
        this._nearSignedTransaction = new nearAPI.transactions.SignedTransaction({
            transaction: this._nearTransaction,
            signature: new nearAPI.transactions.Signature({
                keyType: this._nearTransaction.publicKey.keyType,
                data: signature,
            }),
        });
        this.loadInputsAndOutputs();
    }
    /**
     * set transaction type by staking contract method names.
     * @param methodName method name to match and set the transaction type
     */
    setTypeByStakingMethod(methodName) {
        switch (methodName) {
            case constants_1.StakingContractMethodNames.DepositAndStake:
                this.setTransactionType(sdk_core_1.TransactionType.StakingActivate);
                break;
            case constants_1.StakingContractMethodNames.Unstake:
                this.setTransactionType(sdk_core_1.TransactionType.StakingDeactivate);
                break;
            case constants_1.StakingContractMethodNames.Withdraw:
                this.setTransactionType(sdk_core_1.TransactionType.StakingWithdraw);
                break;
        }
    }
    /**
     * Check if method is allowed on Near account-lib implementation.
     * This method should check on all contracts added to Near.
     * @param methodName contract call method name to check if its allowed.
     */
    validateMethodAllowed(methodName) {
        if (!Object.values(constants_1.StakingContractMethodNames).some((item) => item === methodName)) {
            throw new sdk_core_1.InvalidTransactionError('unsupported function call in raw transaction');
        }
    }
    /**
     * Build input and output field for this transaction
     *
     */
    loadInputsAndOutputs() {
        if (this._nearTransaction.actions.length !== 1) {
            throw new sdk_core_1.InvalidTransactionError('too many actions in raw transaction');
        }
        const action = this._nearTransaction.actions[0];
        switch (action.enum) {
            case 'transfer':
                this.setTransactionType(sdk_core_1.TransactionType.Send);
                break;
            case 'functionCall':
                const methodName = action.functionCall.methodName;
                this.validateMethodAllowed(methodName);
                this.setTypeByStakingMethod(methodName);
                break;
            default:
                throw new sdk_core_1.InvalidTransactionError('unsupported action in raw transaction');
        }
        const outputs = [];
        const inputs = [];
        switch (this.type) {
            case sdk_core_1.TransactionType.Send:
                const amount = action.transfer.deposit.toString();
                inputs.push({
                    address: this._nearTransaction.signerId,
                    value: amount,
                    coin: this._coinConfig.name,
                });
                outputs.push({
                    address: this._nearTransaction.receiverId,
                    value: amount,
                    coin: this._coinConfig.name,
                });
                break;
            case sdk_core_1.TransactionType.StakingActivate:
                const stakingAmount = action.functionCall.deposit.toString();
                inputs.push({
                    address: this._nearTransaction.signerId,
                    value: stakingAmount,
                    coin: this._coinConfig.name,
                });
                outputs.push({
                    address: this._nearTransaction.receiverId,
                    value: stakingAmount,
                    coin: this._coinConfig.name,
                });
                break;
            case sdk_core_1.TransactionType.StakingWithdraw:
                const stakingWithdrawAmount = JSON.parse(Buffer.from(action.functionCall.args).toString()).amount;
                inputs.push({
                    address: this._nearTransaction.receiverId,
                    value: stakingWithdrawAmount,
                    coin: this._coinConfig.name,
                });
                outputs.push({
                    address: this._nearTransaction.signerId,
                    value: stakingWithdrawAmount,
                    coin: this._coinConfig.name,
                });
                break;
        }
        this._outputs = outputs;
        this._inputs = inputs;
    }
    /**
     * Returns a complete explanation for a transfer transaction
     * @param {TxData} json The transaction data in json format
     * @param {TransactionExplanation} explanationResult The transaction explanation to be completed
     * @returns {TransactionExplanation}
     */
    explainTransferTransaction(json, explanationResult) {
        return {
            ...explanationResult,
            outputAmount: json.actions[0].transfer?.deposit.toString() || '',
            outputs: [
                {
                    address: json.receiverId,
                    amount: json.actions[0].transfer?.deposit.toString() || '',
                },
            ],
        };
    }
    /**
     * Returns a complete explanation for a staking activate transaction
     * @param {TxData} json The transaction data in json format
     * @param {TransactionExplanation} explanationResult The transaction explanation to be completed
     * @returns {TransactionExplanation}
     */
    explainStakingActivateTransaction(json, explanationResult) {
        return {
            ...explanationResult,
            outputAmount: json.actions[0].functionCall?.deposit.toString() || '',
            outputs: [
                {
                    address: json.receiverId,
                    amount: json.actions[0].functionCall?.deposit.toString() || '',
                },
            ],
        };
    }
    /**
     * Returns a complete explanation for a staking withdraw transaction
     * @param {TxData} json The transaction data in json format
     * @param {TransactionExplanation} explanationResult The transaction explanation to be completed
     * @returns {TransactionExplanation}
     */
    explainStakingWithdrawTransaction(json, explanationResult) {
        const amount = json.actions[0].functionCall?.args.amount;
        return {
            ...explanationResult,
            outputAmount: amount,
            outputs: [
                {
                    address: json.signerId,
                    amount: amount,
                },
            ],
        };
    }
    /** @inheritdoc */
    explainTransaction() {
        const result = this.toJson();
        const displayOrder = ['outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type'];
        const outputs = [];
        const explanationResult = {
            // txhash used to identify the transactions
            id: result.id || '',
            displayOrder,
            outputAmount: '0',
            changeAmount: '0',
            changeOutputs: [],
            outputs,
            fee: { fee: '' },
            type: this.type,
        };
        switch (this.type) {
            case sdk_core_1.TransactionType.Send:
                return this.explainTransferTransaction(result, explanationResult);
            case sdk_core_1.TransactionType.StakingActivate:
                return this.explainStakingActivateTransaction(result, explanationResult);
            case sdk_core_1.TransactionType.StakingDeactivate:
                return explanationResult;
            case sdk_core_1.TransactionType.StakingWithdraw:
                return this.explainStakingWithdrawTransaction(result, explanationResult);
            default:
                throw new sdk_core_1.InvalidTransactionError('Transaction type not supported');
        }
    }
    getTransactionHash() {
        const serializedTx = nearAPI.utils.serialize.serialize(nearAPI.transactions.SCHEMA, this._nearTransaction);
        return new Uint8Array(sha256.sha256.array(serializedTx));
    }
    get signablePayload() {
        if (!this._nearTransaction) {
            throw new sdk_core_1.InvalidTransactionError('empty transaction');
        }
        return Buffer.from(this.getTransactionHash());
    }
    /**
     * Constructs a signed payload using construct.signTx
     * This method will be called during the build step if a TSS signature
     * is added and will set the signTransaction which is the txHex that will be broadcasted
     * As well as add the signature used to sign to the signature array in hex format
     *
     * @param {Buffer} signature The signature to be added to a near transaction
     */
    constructSignedPayload(signature) {
        this._nearSignedTransaction = new nearAPI.transactions.SignedTransaction({
            transaction: this._nearTransaction,
            signature: new nearAPI.transactions.Signature({
                keyType: this._nearTransaction.publicKey.keyType,
                data: signature,
            }),
        });
        this.loadInputsAndOutputs();
    }
    /** @inheritdoc **/
    get signature() {
        const signatures = [];
        if (this._nearSignedTransaction) {
            signatures.push(bs58_1.default.encode(this._nearSignedTransaction.signature.data));
        }
        return signatures;
    }
}
exports.Transaction = Transaction;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3RyYW5zYWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDhDQU95QjtBQUd6QiwyQ0FBb0U7QUFDcEUsb0RBQTRCO0FBQzVCLHVDQUFvQztBQUNwQyxxREFBdUM7QUFDdkMsa0RBQW9DO0FBQ3BDLGdEQUEwQjtBQUUxQixNQUFhLFdBQVksU0FBUSwwQkFBZTtJQUk5QyxZQUFZLFVBQWdDO1FBQzFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNwQixDQUFDO0lBRUQsSUFBSSxlQUFlO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDO0lBQy9CLENBQUM7SUFFRCxJQUFJLGVBQWUsQ0FBQyxFQUFvQztRQUN0RCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsRUFBRSxDQUFDO1FBQzNCLElBQUksQ0FBQyxHQUFHLEdBQUcsZUFBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsT0FBTyxDQUFDLEdBQVk7UUFDbEIsSUFBSSxDQUFDO1lBQ0gsSUFBSSxpQkFBTyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQzlCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztJQUNILENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsaUJBQWlCO1FBQ2YsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzNCLE1BQU0sSUFBSSxrQ0FBdUIsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBQzlELENBQUM7UUFDRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENB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Q0FBQyxTQUFpQjtRQUN0QyxJQUFJLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLGlCQUFpQixDQUFDO1lBQ3ZFLFdBQVcsRUFBRSxJQUFJLENBQUMsZ0JBQWdCO1lBQ2xDLFNBQVMsRUFBRSxJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDO2dCQUM1QyxPQUFPLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxPQUFPO2dCQUNoRCxJQUFJLEVBQUUsU0FBUzthQUNoQixDQUFDO1NBQ0gsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUNELG1CQUFtQjtJQUNuQixJQUFJLFNBQVM7UUFDWCxNQUFNLFVBQVUsR0FBYSxFQUFFLENBQUM7UUFFaEMsSUFBSSxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztZQUNoQyxVQUFVLENBQUMsSUFBSSxDQUFDLGNBQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQzdFLENBQUM7UUFFRCxPQUFPLFVBQVUsQ0FBQztJQUNwQixDQUFDO0NBQ0Y7QUE1V0Qsa0NBNFdDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQmFzZUtleSxcbiAgQmFzZVRyYW5zYWN0aW9uLFxuICBFbnRyeSxcbiAgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IsXG4gIFRyYW5zYWN0aW9uUmVjaXBpZW50LFxuICBUcmFuc2FjdGlvblR5cGUsXG59IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBCYXNlQ29pbiBhcyBDb2luQ29uZmlnIH0gZnJvbSAnQGJpdGdvL3N0YXRpY3MnO1xuaW1wb3J0IHsgVHJhbnNhY3Rpb25FeHBsYW5hdGlvbiwgVHhEYXRhLCBBY3Rpb24gfSBmcm9tICcuL2lmYWNlJztcbmltcG9ydCB7IEhFWF9SRUdFWCwgU3Rha2luZ0NvbnRyYWN0TWV0aG9kTmFtZXMgfSBmcm9tICcuL2NvbnN0YW50cyc7XG5pbXBvcnQgdXRpbHMgZnJvbSAnLi91dGlscyc7XG5pbXBvcnQgeyBLZXlQYWlyIH0gZnJvbSAnLi9rZXlQYWlyJztcbmltcG9ydCAqIGFzIG5lYXJBUEkgZnJvbSAnbmVhci1hcGktanMnO1xuaW1wb3J0ICogYXMgc2hhMjU2IGZyb20gJ2pzLXNoYTI1Nic7XG5pbXBvcnQgYmFzZTU4IGZyb20gJ2JzNTgnO1xuXG5leHBvcnQgY2xhc3MgVHJhbnNhY3Rpb24gZXh0ZW5kcyBCYXNlVHJhbnNhY3Rpb24ge1xuICBwcml2YXRlIF9uZWFyVHJhbnNhY3Rpb246IG5lYXJBUEkudHJhbnNhY3Rpb25zLlRyYW5zYWN0aW9uO1xuICBwcml2YXRlIF9uZWFyU2lnbmVkVHJhbnNhY3Rpb246IG5lYXJBUEkudHJhbnNhY3Rpb25zLlNpZ25lZFRyYW5zYWN0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKGNvaW5Db25maWc6IFJlYWRvbmx5PENvaW5Db25maWc+KSB7XG4gICAgc3VwZXIoY29pbkNvbmZpZyk7XG4gIH1cblxuICBnZXQgbmVhclRyYW5zYWN0aW9uKCk6IG5lYXJBUEkudHJhbnNhY3Rpb25zLlRyYW5zYWN0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5fbmVhclRyYW5zYWN0aW9uO1xuICB9XG5cbiAgc2V0IG5lYXJUcmFuc2FjdGlvbih0eDogbmVhckFQSS50cmFuc2FjdGlvbnMuVHJhbnNhY3Rpb24pIHtcbiAgICB0aGlzLl9uZWFyVHJhbnNhY3Rpb24gPSB0eDtcbiAgICB0aGlzLl9pZCA9IHV0aWxzLmJhc2U1OEVuY29kZSh0aGlzLmdldFRyYW5zYWN0aW9uSGFzaCgpKTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBjYW5TaWduKGtleTogQmFzZUtleSk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICBuZXcgS2V5UGFpcih7IHBydjoga2V5LmtleSB9KTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICB0b0Jyb2FkY2FzdEZvcm1hdCgpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5fbmVhclRyYW5zYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ0VtcHR5IHRyYW5zYWN0aW9uIGRhdGEnKTtcbiAgICB9XG4gICAgY29uc3QgdHhTZXJhbGl6ZWQgPSB0aGlzLl9uZWFyU2lnbmVkVHJhbnNhY3Rpb25cbiAgICAgID8gQnVmZmVyLmZyb20odGhpcy5fbmVhclNpZ25lZFRyYW5zYWN0aW9uLmVuY29kZSgpKS50b1N0cmluZygnYmFzZTY0JylcbiAgICAgIDogQnVmZmVyLmZyb20odGhpcy5fbmVhclRyYW5zYWN0aW9uLmVuY29kZSgpKS50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgcmV0dXJuIHR4U2VyYWxpemVkO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHRvSnNvbigpOiBUeERhdGEge1xuICAgIGlmICghdGhpcy5fbmVhclRyYW5zYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ0VtcHR5IHRyYW5zYWN0aW9uIGRhdGEnKTtcbiAgICB9XG5cbiAgICBsZXQgcGFyc2VkQWN0aW9uOiBBY3Rpb24gPSB7fTtcbiAgICBpZiAodGhpcy5fbmVhclRyYW5zYWN0aW9uLmFjdGlvbnNbMF0uZW51bSA9PT0gJ3RyYW5zZmVyJykge1xuICAgICAgcGFyc2VkQWN0aW9uID0geyB0cmFuc2ZlcjogdGhpcy5fbmVhclRyYW5zYWN0aW9uLmFjdGlvbnNbMF0udHJhbnNmZXIgfTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuX25lYXJUcmFuc2FjdGlvbi5hY3Rpb25zWzBdLmVudW0gPT09ICdmdW5jdGlvbkNhbGwnKSB7XG4gICAgICBjb25zdCBmdW5jdGlvbkNhbGxPYmplY3QgPSB0aGlzLl9uZWFyVHJhbnNhY3Rpb24uYWN0aW9uc1swXS5mdW5jdGlvbkNhbGw7XG4gICAgICBwYXJzZWRBY3Rpb24gPSB7XG4gICAgICAgIGZ1bmN0aW9uQ2FsbDoge1xuICAgICAgICAgIG1ldGhvZE5hbWU6IGZ1bmN0aW9uQ2FsbE9iamVjdC5tZXRob2ROYW1lLFxuICAgICAgICAgIGFyZ3M6IEpTT04ucGFyc2UoQnVmZmVyLmZyb20oZnVuY3Rpb25DYWxsT2JqZWN0LmFyZ3MpLnRvU3RyaW5nKCkpLFxuICAgICAgICAgIGdhczogZnVuY3Rpb25DYWxsT2JqZWN0Lmdhcy50b1N0cmluZygpLFxuICAgICAgICAgIGRlcG9zaXQ6IGZ1bmN0aW9uQ2FsbE9iamVjdC5kZXBvc2l0LnRvU3RyaW5nKCksXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBpZDogdGhpcy5faWQsXG4gICAgICBzaWduZXJJZDogdGhpcy5fbmVhclRyYW5zYWN0aW9uLnNpZ25lcklkLFxuICAgICAgcHVibGljS2V5OiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24ucHVibGljS2V5LnRvU3RyaW5nKCksXG4gICAgICBub25jZTogdGhpcy5fbmVhclRyYW5zYWN0aW9uLm5vbmNlLFxuICAgICAgcmVjZWl2ZXJJZDogdGhpcy5fbmVhclRyYW5zYWN0aW9uLnJlY2VpdmVySWQsXG4gICAgICBhY3Rpb25zOiBbcGFyc2VkQWN0aW9uXSxcbiAgICAgIHNpZ25hdHVyZTogdHlwZW9mIHRoaXMuX25lYXJTaWduZWRUcmFuc2FjdGlvbiA9PT0gJ3VuZGVmaW5lZCcgPyB1bmRlZmluZWQgOiB0aGlzLl9uZWFyU2lnbmVkVHJhbnNhY3Rpb24uc2lnbmF0dXJlLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSB0cmFuc2FjdGlvbiB0eXBlLlxuICAgKlxuICAgKiBAcGFyYW0ge1RyYW5zYWN0aW9uVHlwZX0gdHJhbnNhY3Rpb25UeXBlIFRoZSB0cmFuc2FjdGlvbiB0eXBlIHRvIGJlIHNldC5cbiAgICovXG4gIHNldFRyYW5zYWN0aW9uVHlwZSh0cmFuc2FjdGlvblR5cGU6IFRyYW5zYWN0aW9uVHlwZSk6IHZvaWQge1xuICAgIHRoaXMuX3R5cGUgPSB0cmFuc2FjdGlvblR5cGU7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGlzIHRyYW5zYWN0aW9uIHBheWxvYWRcbiAgICpcbiAgICogQHBhcmFtIHJhd1R4XG4gICAqL1xuICBmcm9tUmF3VHJhbnNhY3Rpb24ocmF3VHg6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGJ1ZmZlclJhd1RyYW5zYWN0aW9uID0gSEVYX1JFR0VYLnRlc3QocmF3VHgpID8gQnVmZmVyLmZyb20ocmF3VHgsICdoZXgnKSA6IEJ1ZmZlci5mcm9tKHJhd1R4LCAnYmFzZTY0Jyk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHNpZ25lZFR4ID0gbmVhckFQSS51dGlscy5zZXJpYWxpemUuZGVzZXJpYWxpemUoXG4gICAgICAgIG5lYXJBUEkudHJhbnNhY3Rpb25zLlNDSEVNQSxcbiAgICAgICAgbmVhckFQSS50cmFuc2FjdGlvbnMuU2lnbmVkVHJhbnNhY3Rpb24sXG4gICAgICAgIGJ1ZmZlclJhd1RyYW5zYWN0aW9uXG4gICAgICApO1xuICAgICAgc2lnbmVkVHgudHJhbnNhY3Rpb24ubm9uY2UgPSBwYXJzZUludChzaWduZWRUeC50cmFuc2FjdGlvbi5ub25jZS50b1N0cmluZygpLCAxMCk7XG4gICAgICB0aGlzLl9uZWFyU2lnbmVkVHJhbnNhY3Rpb24gPSBzaWduZWRUeDtcbiAgICAgIHRoaXMuX25lYXJUcmFuc2FjdGlvbiA9IHNpZ25lZFR4LnRyYW5zYWN0aW9uO1xuICAgICAgdGhpcy5faWQgPSB1dGlscy5iYXNlNThFbmNvZGUodGhpcy5nZXRUcmFuc2FjdGlvbkhhc2goKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgdW5zaWduZWRUeCA9IG5lYXJBUEkudXRpbHMuc2VyaWFsaXplLmRlc2VyaWFsaXplKFxuICAgICAgICAgIG5lYXJBUEkudHJhbnNhY3Rpb25zLlNDSEVNQSxcbiAgICAgICAgICBuZWFyQVBJLnRyYW5zYWN0aW9ucy5UcmFuc2FjdGlvbixcbiAgICAgICAgICBidWZmZXJSYXdUcmFuc2FjdGlvblxuICAgICAgICApO1xuICAgICAgICB1bnNpZ25lZFR4Lm5vbmNlID0gcGFyc2VJbnQodW5zaWduZWRUeC5ub25jZS50b1N0cmluZygpLCAxMCk7XG4gICAgICAgIHRoaXMuX25lYXJUcmFuc2FjdGlvbiA9IHVuc2lnbmVkVHg7XG4gICAgICAgIHRoaXMuX2lkID0gdXRpbHMuYmFzZTU4RW5jb2RlKHRoaXMuZ2V0VHJhbnNhY3Rpb25IYXNoKCkpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ3VuYWJsZSB0byBidWlsZCB0cmFuc2FjdGlvbiBmcm9tIHJhdycpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMubG9hZElucHV0c0FuZE91dHB1dHMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaWduIHRoaXMgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHtLZXlQYWlyfSBzaWduZXIga2V5XG4gICAqL1xuXG4gIHNpZ24oc2lnbmVyOiBLZXlQYWlyKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9uZWFyVHJhbnNhY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignZW1wdHkgdHJhbnNhY3Rpb24gdG8gc2lnbicpO1xuICAgIH1cbiAgICBjb25zdCBzZXJpYWxpemVkVHhIYXNoID0gdGhpcy5nZXRUcmFuc2FjdGlvbkhhc2goKTtcbiAgICBjb25zdCBzaWduYXR1cmUgPSBzaWduZXIuc2lnbk1lc3NhZ2VpblVpbnQ4QXJyYXkoc2VyaWFsaXplZFR4SGFzaCk7XG4gICAgdGhpcy5fbmVhclNpZ25lZFRyYW5zYWN0aW9uID0gbmV3IG5lYXJBUEkudHJhbnNhY3Rpb25zLlNpZ25lZFRyYW5zYWN0aW9uKHtcbiAgICAgIHRyYW5zYWN0aW9uOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24sXG4gICAgICBzaWduYXR1cmU6IG5ldyBuZWFyQVBJLnRyYW5zYWN0aW9ucy5TaWduYXR1cmUoe1xuICAgICAgICBrZXlUeXBlOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24ucHVibGljS2V5LmtleVR5cGUsXG4gICAgICAgIGRhdGE6IHNpZ25hdHVyZSxcbiAgICAgIH0pLFxuICAgIH0pO1xuICAgIHRoaXMubG9hZElucHV0c0FuZE91dHB1dHMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBzZXQgdHJhbnNhY3Rpb24gdHlwZSBieSBzdGFraW5nIGNvbnRyYWN0IG1ldGhvZCBuYW1lcy5cbiAgICogQHBhcmFtIG1ldGhvZE5hbWUgbWV0aG9kIG5hbWUgdG8gbWF0Y2ggYW5kIHNldCB0aGUgdHJhbnNhY3Rpb24gdHlwZVxuICAgKi9cbiAgcHJpdmF0ZSBzZXRUeXBlQnlTdGFraW5nTWV0aG9kKG1ldGhvZE5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHN3aXRjaCAobWV0aG9kTmFtZSkge1xuICAgICAgY2FzZSBTdGFraW5nQ29udHJhY3RNZXRob2ROYW1lcy5EZXBvc2l0QW5kU3Rha2U6XG4gICAgICAgIHRoaXMuc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nQWN0aXZhdGUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgU3Rha2luZ0NvbnRyYWN0TWV0aG9kTmFtZXMuVW5zdGFrZTpcbiAgICAgICAgdGhpcy5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdEZWFjdGl2YXRlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFN0YWtpbmdDb250cmFjdE1ldGhvZE5hbWVzLldpdGhkcmF3OlxuICAgICAgICB0aGlzLnNldFRyYW5zYWN0aW9uVHlwZShUcmFuc2FjdGlvblR5cGUuU3Rha2luZ1dpdGhkcmF3KTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIG1ldGhvZCBpcyBhbGxvd2VkIG9uIE5lYXIgYWNjb3VudC1saWIgaW1wbGVtZW50YXRpb24uXG4gICAqIFRoaXMgbWV0aG9kIHNob3VsZCBjaGVjayBvbiBhbGwgY29udHJhY3RzIGFkZGVkIHRvIE5lYXIuXG4gICAqIEBwYXJhbSBtZXRob2ROYW1lIGNvbnRyYWN0IGNhbGwgbWV0aG9kIG5hbWUgdG8gY2hlY2sgaWYgaXRzIGFsbG93ZWQuXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlTWV0aG9kQWxsb3dlZChtZXRob2ROYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIU9iamVjdC52YWx1ZXMoU3Rha2luZ0NvbnRyYWN0TWV0aG9kTmFtZXMpLnNvbWUoKGl0ZW0pID0+IGl0ZW0gPT09IG1ldGhvZE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ3Vuc3VwcG9ydGVkIGZ1bmN0aW9uIGNhbGwgaW4gcmF3IHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIGlucHV0IGFuZCBvdXRwdXQgZmllbGQgZm9yIHRoaXMgdHJhbnNhY3Rpb25cbiAgICpcbiAgICovXG4gIGxvYWRJbnB1dHNBbmRPdXRwdXRzKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9uZWFyVHJhbnNhY3Rpb24uYWN0aW9ucy5sZW5ndGggIT09IDEpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcigndG9vIG1hbnkgYWN0aW9ucyBpbiByYXcgdHJhbnNhY3Rpb24nKTtcbiAgICB9XG5cbiAgICBjb25zdCBhY3Rpb24gPSB0aGlzLl9uZWFyVHJhbnNhY3Rpb24uYWN0aW9uc1swXTtcblxuICAgIHN3aXRjaCAoYWN0aW9uLmVudW0pIHtcbiAgICAgIGNhc2UgJ3RyYW5zZmVyJzpcbiAgICAgICAgdGhpcy5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2Z1bmN0aW9uQ2FsbCc6XG4gICAgICAgIGNvbnN0IG1ldGhvZE5hbWUgPSBhY3Rpb24uZnVuY3Rpb25DYWxsLm1ldGhvZE5hbWU7XG4gICAgICAgIHRoaXMudmFsaWRhdGVNZXRob2RBbGxvd2VkKG1ldGhvZE5hbWUpO1xuICAgICAgICB0aGlzLnNldFR5cGVCeVN0YWtpbmdNZXRob2QobWV0aG9kTmFtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCd1bnN1cHBvcnRlZCBhY3Rpb24gaW4gcmF3IHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgb3V0cHV0czogRW50cnlbXSA9IFtdO1xuICAgIGNvbnN0IGlucHV0czogRW50cnlbXSA9IFtdO1xuICAgIHN3aXRjaCAodGhpcy50eXBlKSB7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TZW5kOlxuICAgICAgICBjb25zdCBhbW91bnQgPSBhY3Rpb24udHJhbnNmZXIuZGVwb3NpdC50b1N0cmluZygpO1xuICAgICAgICBpbnB1dHMucHVzaCh7XG4gICAgICAgICAgYWRkcmVzczogdGhpcy5fbmVhclRyYW5zYWN0aW9uLnNpZ25lcklkLFxuICAgICAgICAgIHZhbHVlOiBhbW91bnQsXG4gICAgICAgICAgY29pbjogdGhpcy5fY29pbkNvbmZpZy5uYW1lLFxuICAgICAgICB9KTtcbiAgICAgICAgb3V0cHV0cy5wdXNoKHtcbiAgICAgICAgICBhZGRyZXNzOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24ucmVjZWl2ZXJJZCxcbiAgICAgICAgICB2YWx1ZTogYW1vdW50LFxuICAgICAgICAgIGNvaW46IHRoaXMuX2NvaW5Db25maWcubmFtZSxcbiAgICAgICAgfSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0FjdGl2YXRlOlxuICAgICAgICBjb25zdCBzdGFraW5nQW1vdW50ID0gYWN0aW9uLmZ1bmN0aW9uQ2FsbC5kZXBvc2l0LnRvU3RyaW5nKCk7XG4gICAgICAgIGlucHV0cy5wdXNoKHtcbiAgICAgICAgICBhZGRyZXNzOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24uc2lnbmVySWQsXG4gICAgICAgICAgdmFsdWU6IHN0YWtpbmdBbW91bnQsXG4gICAgICAgICAgY29pbjogdGhpcy5fY29pbkNvbmZpZy5uYW1lLFxuICAgICAgICB9KTtcbiAgICAgICAgb3V0cHV0cy5wdXNoKHtcbiAgICAgICAgICBhZGRyZXNzOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24ucmVjZWl2ZXJJZCxcbiAgICAgICAgICB2YWx1ZTogc3Rha2luZ0Ftb3VudCxcbiAgICAgICAgICBjb2luOiB0aGlzLl9jb2luQ29uZmlnLm5hbWUsXG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdXaXRoZHJhdzpcbiAgICAgICAgY29uc3Qgc3Rha2luZ1dpdGhkcmF3QW1vdW50ID0gSlNPTi5wYXJzZShCdWZmZXIuZnJvbShhY3Rpb24uZnVuY3Rpb25DYWxsLmFyZ3MpLnRvU3RyaW5nKCkpLmFtb3VudDtcbiAgICAgICAgaW5wdXRzLnB1c2goe1xuICAgICAgICAgIGFkZHJlc3M6IHRoaXMuX25lYXJUcmFuc2FjdGlvbi5yZWNlaXZlcklkLFxuICAgICAgICAgIHZhbHVlOiBzdGFraW5nV2l0aGRyYXdBbW91bnQsXG4gICAgICAgICAgY29pbjogdGhpcy5fY29pbkNvbmZpZy5uYW1lLFxuICAgICAgICB9KTtcbiAgICAgICAgb3V0cHV0cy5wdXNoKHtcbiAgICAgICAgICBhZGRyZXNzOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24uc2lnbmVySWQsXG4gICAgICAgICAgdmFsdWU6IHN0YWtpbmdXaXRoZHJhd0Ftb3VudCxcbiAgICAgICAgICBjb2luOiB0aGlzLl9jb2luQ29uZmlnLm5hbWUsXG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gICAgdGhpcy5fb3V0cHV0cyA9IG91dHB1dHM7XG4gICAgdGhpcy5faW5wdXRzID0gaW5wdXRzO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBjb21wbGV0ZSBleHBsYW5hdGlvbiBmb3IgYSB0cmFuc2ZlciB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0ge1R4RGF0YX0ganNvbiBUaGUgdHJhbnNhY3Rpb24gZGF0YSBpbiBqc29uIGZvcm1hdFxuICAgKiBAcGFyYW0ge1RyYW5zYWN0aW9uRXhwbGFuYXRpb259IGV4cGxhbmF0aW9uUmVzdWx0IFRoZSB0cmFuc2FjdGlvbiBleHBsYW5hdGlvbiB0byBiZSBjb21wbGV0ZWRcbiAgICogQHJldHVybnMge1RyYW5zYWN0aW9uRXhwbGFuYXRpb259XG4gICAqL1xuICBleHBsYWluVHJhbnNmZXJUcmFuc2FjdGlvbihqc29uOiBUeERhdGEsIGV4cGxhbmF0aW9uUmVzdWx0OiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uKTogVHJhbnNhY3Rpb25FeHBsYW5hdGlvbiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmV4cGxhbmF0aW9uUmVzdWx0LFxuICAgICAgb3V0cHV0QW1vdW50OiBqc29uLmFjdGlvbnNbMF0udHJhbnNmZXI/LmRlcG9zaXQudG9TdHJpbmcoKSB8fCAnJyxcbiAgICAgIG91dHB1dHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6IGpzb24ucmVjZWl2ZXJJZCxcbiAgICAgICAgICBhbW91bnQ6IGpzb24uYWN0aW9uc1swXS50cmFuc2Zlcj8uZGVwb3NpdC50b1N0cmluZygpIHx8ICcnLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBjb21wbGV0ZSBleHBsYW5hdGlvbiBmb3IgYSBzdGFraW5nIGFjdGl2YXRlIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSB7VHhEYXRhfSBqc29uIFRoZSB0cmFuc2FjdGlvbiBkYXRhIGluIGpzb24gZm9ybWF0XG4gICAqIEBwYXJhbSB7VHJhbnNhY3Rpb25FeHBsYW5hdGlvbn0gZXhwbGFuYXRpb25SZXN1bHQgVGhlIHRyYW5zYWN0aW9uIGV4cGxhbmF0aW9uIHRvIGJlIGNvbXBsZXRlZFxuICAgKiBAcmV0dXJucyB7VHJhbnNhY3Rpb25FeHBsYW5hdGlvbn1cbiAgICovXG4gIGV4cGxhaW5TdGFraW5nQWN0aXZhdGVUcmFuc2FjdGlvbihqc29uOiBUeERhdGEsIGV4cGxhbmF0aW9uUmVzdWx0OiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uKTogVHJhbnNhY3Rpb25FeHBsYW5hdGlvbiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmV4cGxhbmF0aW9uUmVzdWx0LFxuICAgICAgb3V0cHV0QW1vdW50OiBqc29uLmFjdGlvbnNbMF0uZnVuY3Rpb25DYWxsPy5kZXBvc2l0LnRvU3RyaW5nKCkgfHwgJycsXG4gICAgICBvdXRwdXRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiBqc29uLnJlY2VpdmVySWQsXG4gICAgICAgICAgYW1vdW50OiBqc29uLmFjdGlvbnNbMF0uZnVuY3Rpb25DYWxsPy5kZXBvc2l0LnRvU3RyaW5nKCkgfHwgJycsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGNvbXBsZXRlIGV4cGxhbmF0aW9uIGZvciBhIHN0YWtpbmcgd2l0aGRyYXcgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHtUeERhdGF9IGpzb24gVGhlIHRyYW5zYWN0aW9uIGRhdGEgaW4ganNvbiBmb3JtYXRcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvbkV4cGxhbmF0aW9ufSBleHBsYW5hdGlvblJlc3VsdCBUaGUgdHJhbnNhY3Rpb24gZXhwbGFuYXRpb24gdG8gYmUgY29tcGxldGVkXG4gICAqIEByZXR1cm5zIHtUcmFuc2FjdGlvbkV4cGxhbmF0aW9ufVxuICAgKi9cbiAgZXhwbGFpblN0YWtpbmdXaXRoZHJhd1RyYW5zYWN0aW9uKGpzb246IFR4RGF0YSwgZXhwbGFuYXRpb25SZXN1bHQ6IFRyYW5zYWN0aW9uRXhwbGFuYXRpb24pOiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uIHtcbiAgICBjb25zdCBhbW91bnQgPSBqc29uLmFjdGlvbnNbMF0uZnVuY3Rpb25DYWxsPy5hcmdzLmFtb3VudCBhcyBzdHJpbmc7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmV4cGxhbmF0aW9uUmVzdWx0LFxuICAgICAgb3V0cHV0QW1vdW50OiBhbW91bnQsXG4gICAgICBvdXRwdXRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiBqc29uLnNpZ25lcklkLFxuICAgICAgICAgIGFtb3VudDogYW1vdW50LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIGV4cGxhaW5UcmFuc2FjdGlvbigpOiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uIHtcbiAgICBjb25zdCByZXN1bHQgPSB0aGlzLnRvSnNvbigpO1xuICAgIGNvbnN0IGRpc3BsYXlPcmRlciA9IFsnb3V0cHV0QW1vdW50JywgJ2NoYW5nZUFtb3VudCcsICdvdXRwdXRzJywgJ2NoYW5nZU91dHB1dHMnLCAnZmVlJywgJ3R5cGUnXTtcbiAgICBjb25zdCBvdXRwdXRzOiBUcmFuc2FjdGlvblJlY2lwaWVudFtdID0gW107XG4gICAgY29uc3QgZXhwbGFuYXRpb25SZXN1bHQ6IFRyYW5zYWN0aW9uRXhwbGFuYXRpb24gPSB7XG4gICAgICAvLyB0eGhhc2ggdXNlZCB0byBpZGVudGlmeSB0aGUgdHJhbnNhY3Rpb25zXG4gICAgICBpZDogcmVzdWx0LmlkIHx8ICcnLFxuICAgICAgZGlzcGxheU9yZGVyLFxuICAgICAgb3V0cHV0QW1vdW50OiAnMCcsXG4gICAgICBjaGFuZ2VBbW91bnQ6ICcwJyxcbiAgICAgIGNoYW5nZU91dHB1dHM6IFtdLFxuICAgICAgb3V0cHV0cyxcbiAgICAgIGZlZTogeyBmZWU6ICcnIH0sXG4gICAgICB0eXBlOiB0aGlzLnR5cGUsXG4gICAgfTtcbiAgICBzd2l0Y2ggKHRoaXMudHlwZSkge1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU2VuZDpcbiAgICAgICAgcmV0dXJuIHRoaXMuZXhwbGFpblRyYW5zZmVyVHJhbnNhY3Rpb24ocmVzdWx0LCBleHBsYW5hdGlvblJlc3VsdCk7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nQWN0aXZhdGU6XG4gICAgICAgIHJldHVybiB0aGlzLmV4cGxhaW5TdGFraW5nQWN0aXZhdGVUcmFuc2FjdGlvbihyZXN1bHQsIGV4cGxhbmF0aW9uUmVzdWx0KTtcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdEZWFjdGl2YXRlOlxuICAgICAgICByZXR1cm4gZXhwbGFuYXRpb25SZXN1bHQ7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nV2l0aGRyYXc6XG4gICAgICAgIHJldHVybiB0aGlzLmV4cGxhaW5TdGFraW5nV2l0aGRyYXdUcmFuc2FjdGlvbihyZXN1bHQsIGV4cGxhbmF0aW9uUmVzdWx0KTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignVHJhbnNhY3Rpb24gdHlwZSBub3Qgc3VwcG9ydGVkJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRUcmFuc2FjdGlvbkhhc2goKTogVWludDhBcnJheSB7XG4gICAgY29uc3Qgc2VyaWFsaXplZFR4ID0gbmVhckFQSS51dGlscy5zZXJpYWxpemUuc2VyaWFsaXplKG5lYXJBUEkudHJhbnNhY3Rpb25zLlNDSEVNQSwgdGhpcy5fbmVhclRyYW5zYWN0aW9uKTtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoc2hhMjU2LnNoYTI1Ni5hcnJheShzZXJpYWxpemVkVHgpKTtcbiAgfVxuXG4gIGdldCBzaWduYWJsZVBheWxvYWQoKTogQnVmZmVyIHtcbiAgICBpZiAoIXRoaXMuX25lYXJUcmFuc2FjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdlbXB0eSB0cmFuc2FjdGlvbicpO1xuICAgIH1cbiAgICByZXR1cm4gQnVmZmVyLmZyb20odGhpcy5nZXRUcmFuc2FjdGlvbkhhc2goKSk7XG4gIH1cblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHNpZ25lZCBwYXlsb2FkIHVzaW5nIGNvbnN0cnVjdC5zaWduVHhcbiAgICogVGhpcyBtZXRob2Qgd2lsbCBiZSBjYWxsZWQgZHVyaW5nIHRoZSBidWlsZCBzdGVwIGlmIGEgVFNTIHNpZ25hdHVyZVxuICAgKiBpcyBhZGRlZCBhbmQgd2lsbCBzZXQgdGhlIHNpZ25UcmFuc2FjdGlvbiB3aGljaCBpcyB0aGUgdHhIZXggdGhhdCB3aWxsIGJlIGJyb2FkY2FzdGVkXG4gICAqIEFzIHdlbGwgYXMgYWRkIHRoZSBzaWduYXR1cmUgdXNlZCB0byBzaWduIHRvIHRoZSBzaWduYXR1cmUgYXJyYXkgaW4gaGV4IGZvcm1hdFxuICAgKlxuICAgKiBAcGFyYW0ge0J1ZmZlcn0gc2lnbmF0dXJlIFRoZSBzaWduYXR1cmUgdG8gYmUgYWRkZWQgdG8gYSBuZWFyIHRyYW5zYWN0aW9uXG4gICAqL1xuICBjb25zdHJ1Y3RTaWduZWRQYXlsb2FkKHNpZ25hdHVyZTogQnVmZmVyKTogdm9pZCB7XG4gICAgdGhpcy5fbmVhclNpZ25lZFRyYW5zYWN0aW9uID0gbmV3IG5lYXJBUEkudHJhbnNhY3Rpb25zLlNpZ25lZFRyYW5zYWN0aW9uKHtcbiAgICAgIHRyYW5zYWN0aW9uOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24sXG4gICAgICBzaWduYXR1cmU6IG5ldyBuZWFyQVBJLnRyYW5zYWN0aW9ucy5TaWduYXR1cmUoe1xuICAgICAgICBrZXlUeXBlOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24ucHVibGljS2V5LmtleVR5cGUsXG4gICAgICAgIGRhdGE6IHNpZ25hdHVyZSxcbiAgICAgIH0pLFxuICAgIH0pO1xuICAgIHRoaXMubG9hZElucHV0c0FuZE91dHB1dHMoKTtcbiAgfVxuICAvKiogQGluaGVyaXRkb2MgKiovXG4gIGdldCBzaWduYXR1cmUoKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHNpZ25hdHVyZXM6IHN0cmluZ1tdID0gW107XG5cbiAgICBpZiAodGhpcy5fbmVhclNpZ25lZFRyYW5zYWN0aW9uKSB7XG4gICAgICBzaWduYXR1cmVzLnB1c2goYmFzZTU4LmVuY29kZSh0aGlzLl9uZWFyU2lnbmVkVHJhbnNhY3Rpb24uc2lnbmF0dXJlLmRhdGEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2lnbmF0dXJlcztcbiAgfVxufVxuIl19

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


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