PHP WebShell

Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@bitgo/sdk-coin-trx/dist/src/lib

Просмотр файла: transactionBuilder.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.TransactionBuilder = void 0;
const crypto_1 = require("crypto");
const _ = __importStar(require("lodash"));
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const sdk_core_1 = require("@bitgo/sdk-core");
const utils_1 = require("./utils");
const transaction_1 = require("./transaction");
const keyPair_1 = require("./keyPair");
/**
 * Tron transaction builder.
 */
class TransactionBuilder extends sdk_core_1.BaseTransactionBuilder {
    /**
     * Public constructor.
     *
     * @param {CoinConfig} _coinConfig Configuration object
     */
    constructor(_coinConfig) {
        super(_coinConfig);
    }
    /** @inheritdoc */
    get transaction() {
        return this._transaction;
    }
    /** @inheritdoc */
    set transaction(transaction) {
        this._transaction = transaction;
    }
    /**
     * Set the source address for the transaction
     *
     * @param {Address} address The source address
     * @returns the builder with the new parameter set
     */
    source(address) {
        this.validateAddress(address);
        this._ownerAddress = (0, utils_1.getHexAddressFromBase58Address)(address.address);
        return this;
    }
    /**
     * Set the timestamp for the transaction
     *
     * @param {number} time the timestamp in milliseconds
     * @returns the builder with the new parameter set
     */
    timestamp(time) {
        this._timestamp = time;
        return this;
    }
    /**
     * Set the block values,
     *
     * @param {Block} block the object containing number and hash of the block
     * @returns the builder with the new parameter set
     */
    block(block) {
        const blockBytes = Buffer.alloc(8);
        blockBytes.writeInt32BE(block.number, 4);
        this._refBlockBytes = blockBytes.slice(6, 8).toString('hex');
        this._refBlockHash = Buffer.from(block.hash, 'hex').slice(8, 16).toString('hex');
        return this;
    }
    /**
     * Set the expiration time for the transaction, set timestamp if it was not set previously
     *
     * @param {number} time the expiration time in milliseconds
     * @returns the builder with the new parameter set
     */
    expiration(time) {
        if (this.transaction.id) {
            throw new sdk_core_1.ExtendTransactionError('Expiration is already set, it can only be extended');
        }
        this._timestamp = this._timestamp || Date.now();
        this.validateExpirationTime(time);
        this._expiration = time;
        return this;
    }
    /**
     * Parse transaction takes in raw JSON directly from the node.
     *
     * @param {TransactionReceipt} rawTransaction The Tron transaction in JSON format as returned by the Tron lib or a stringifyed version of such JSON.
     * @returns {Transaction} Tron transaction
     */
    fromImplementation(rawTransaction) {
        let tx;
        if (typeof rawTransaction === 'string') {
            const transaction = JSON.parse(rawTransaction);
            tx = new transaction_1.Transaction(this._coinConfig, transaction);
        }
        else {
            tx = new transaction_1.Transaction(this._coinConfig, rawTransaction);
        }
        return tx;
    }
    /** @inheritdoc */
    signImplementation(key) {
        if (!this.transaction.inputs) {
            throw new sdk_core_1.SigningError('Transaction has no sender');
        }
        if (!this.transaction.outputs) {
            throw new sdk_core_1.SigningError('Transaction has no receiver');
        }
        return this.applySignature(key);
    }
    applySignature(key) {
        const oldTransaction = this.transaction.toJson();
        // Store the original signatures to compare them with the new ones in a later step. Signatures
        // can be undefined if this is the first time the transaction is being signed
        const oldSignatureCount = oldTransaction.signature ? oldTransaction.signature.length : 0;
        let signedTransaction;
        try {
            const keyPair = new keyPair_1.KeyPair({ prv: key.key });
            // Since the key pair was generated using a private key, it will always have a prv attribute,
            // hence it is safe to use non-null operator
            signedTransaction = (0, utils_1.signTransaction)(keyPair.getKeys().prv, this.transaction.toJson());
        }
        catch (e) {
            throw new sdk_core_1.SigningError('Failed to sign transaction via helper.');
        }
        // Ensure that we have more signatures than what we started with
        if (!signedTransaction.signature || oldSignatureCount >= signedTransaction.signature.length) {
            throw new sdk_core_1.SigningError('Transaction signing did not return an additional signature.');
        }
        return new transaction_1.Transaction(this._coinConfig, signedTransaction);
    }
    /** @inheritdoc */
    async buildImplementation() {
        // This is a no-op since Tron transactions are built from
        if (!this.transaction.id) {
            throw new sdk_core_1.BuildTransactionError('A valid transaction must have an id');
        }
        return Promise.resolve(this.transaction);
    }
    initBuilder(tx) {
        this.transaction = this.fromImplementation(tx);
    }
    /**
     * Extend the validity of this transaction by the given amount of time
     *
     * @param {number} extensionMs The number of milliseconds to extend the validTo time
     * @returns {undefined}
     */
    extendValidTo(extensionMs) {
        this.transaction.extendExpiration(extensionMs);
    }
    /** @inheritdoc */
    validateValue(value) {
        if (value.isLessThanOrEqualTo(0)) {
            throw new Error('Value cannot be below zero.');
        }
        // max long in Java - assumed upper limit for a TRX transaction
        if (value.isGreaterThan(new bignumber_js_1.default('9223372036854775807'))) {
            throw new Error('Value cannot be greater than handled by the javatron node.');
        }
    }
    /** @inheritdoc */
    validateAddress(address) {
        // assumes a base 58 address for our addresses
        if (!(0, utils_1.isBase58Address)(address.address)) {
            throw new Error(address.address + ' is not a valid base58 address.');
        }
    }
    /**
     * Helper method to validate the resource type
     * @param resource The resource type to be validated
     */
    validateResource(resource) {
        if (!utils_1.VALID_RESOURCE_TYPES.includes(resource)) {
            throw new Error(resource + ' is not a valid resource type.');
        }
    }
    /** @inheritdoc */
    validateKey(key) {
        try {
            new keyPair_1.KeyPair({ prv: key.key });
        }
        catch (err) {
            throw new Error('The provided key is not valid');
        }
    }
    /**
     * Validate the contents of a raw transaction. The validation
     * phase is to compare the raw-data-hex to the raw-data of the
     * transaction.
     *
     * The contents to be validated are
     * 1. The transaction id
     * 2. The expiration date
     * 3. The timestamp
     * 4. The contract
     *
     * @param {TransactionReceipt | string} rawTransaction The raw transaction to be validated
     */
    validateRawTransaction(rawTransaction) {
        // TODO: Validation of signature
        if (!rawTransaction) {
            throw new sdk_core_1.InvalidTransactionError('Raw transaction is empty');
        }
        let currTransaction;
        // rawTransaction can be either Stringified JSON OR
        // it can be a regular JSON object (not stringified).
        if (typeof rawTransaction === 'string') {
            try {
                currTransaction = JSON.parse(rawTransaction);
            }
            catch (e) {
                throw new sdk_core_1.ParseTransactionError('There was error in parsing the JSON string');
            }
        }
        else if (_.isObject(rawTransaction)) {
            currTransaction = rawTransaction;
        }
        else {
            throw new sdk_core_1.InvalidTransactionError('Transaction is not an object or stringified json');
        }
        const decodedRawDataHex = (0, utils_1.decodeTransaction)(currTransaction.raw_data_hex);
        if (!currTransaction.txID) {
            throw new sdk_core_1.InvalidTransactionError('Transaction ID is empty');
        }
        // Validate the transaction ID from the raw data hex
        const hexBuffer = Buffer.from(currTransaction.raw_data_hex, 'hex');
        const currTxID = (0, crypto_1.createHash)('sha256').update(hexBuffer).digest('hex');
        if (currTransaction.txID !== currTxID) {
            throw new sdk_core_1.InvalidTransactionError('Transaction has not have a valid id');
        }
        // Validate the expiration time from the raw-data-hex
        if (currTransaction.raw_data.expiration !== decodedRawDataHex.expiration) {
            throw new sdk_core_1.InvalidTransactionError('Transaction has not have a valid expiration');
        }
        // Validate the timestamp from the raw-data-hex
        if (currTransaction.raw_data.timestamp !== decodedRawDataHex.timestamp) {
            throw new sdk_core_1.InvalidTransactionError('Transaction has not have a valid timetamp');
        }
        // Transaction contract must exist
        if (!currTransaction.raw_data.contract) {
            throw new sdk_core_1.InvalidTransactionError('Transaction contracts are empty');
        }
    }
    /** @inheritdoc */
    validateTransaction(transaction) {
        const hexBuffer = Buffer.from(transaction.toJson().raw_data_hex, 'hex');
        const txId = (0, crypto_1.createHash)('sha256').update(hexBuffer).digest('hex');
        if (transaction.id !== txId) {
            throw new sdk_core_1.InvalidTransactionError(transaction.id + ' is not a valid transaction id. Expecting: ' + txId);
        }
    }
    /**
     * Validate the expiration time of the transaction
     *
     * @param {number} value The expiration time in milliseconds
     * @throws {InvalidParameterValueError} If the expiration time is invalid
     */
    validateExpirationTime(value) {
        if (value < this._timestamp) {
            throw new sdk_core_1.InvalidParameterValueError('Expiration must be greater than timestamp');
        }
        if (value < Date.now()) {
            throw new sdk_core_1.InvalidParameterValueError('Expiration must be greater than current time');
        }
        if (value - this._timestamp > utils_1.TRANSACTION_MAX_EXPIRATION) {
            throw new sdk_core_1.InvalidParameterValueError('Expiration must not be greater than one day');
        }
    }
}
exports.TransactionBuilder = TransactionBuilder;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25CdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbkJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsbUNBQW9DO0FBQ3BDLDBDQUE0QjtBQUM1QixnRUFBcUM7QUFFckMsOENBU3lCO0FBR3pCLG1DQU9pQjtBQUNqQiwrQ0FBNEM7QUFDNUMsdUNBQW9DO0FBRXBDOztHQUVHO0FBQ0gsTUFBYSxrQkFBbUIsU0FBUSxpQ0FBc0I7SUFTNUQ7Ozs7T0FJRztJQUNILFlBQVksV0FBaUM7UUFDM0MsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3JCLENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsSUFBYyxXQUFXO1FBQ3ZCLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQztJQUMzQixDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLElBQWMsV0FBVyxDQUFDLFdBQXdCO1FBQ2hELElBQUksQ0FBQyxZQUFZLEdBQUcsV0FBVyxDQUFDO0lBQ2xDLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILE1BQU0sQ0FBQyxPQUFnQjtRQUNyQixJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzlCLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBQSxzQ0FBOEIsRUFBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDckUsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxTQUFTLENBQUMsSUFBWTtRQUNwQixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztRQUN2QixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILEtBQUssQ0FBQyxLQUFZO1FBQ2hCLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7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QUFDLFVBQVUsR0FBRyxrQ0FBMEIsRUFBRSxDQUFDO1lBQ3pELE1BQU0sSUFBSSxxQ0FBMEIsQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO1FBQ3RGLENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUF4UkQsZ0RBd1JDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgQmlnTnVtYmVyIGZyb20gJ2JpZ251bWJlci5qcyc7XG5pbXBvcnQgeyBCYXNlQ29pbiBhcyBDb2luQ29uZmlnIH0gZnJvbSAnQGJpdGdvL3N0YXRpY3MnO1xuaW1wb3J0IHtcbiAgQmFzZUtleSxcbiAgQmFzZVRyYW5zYWN0aW9uQnVpbGRlcixcbiAgQnVpbGRUcmFuc2FjdGlvbkVycm9yLFxuICBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcixcbiAgUGFyc2VUcmFuc2FjdGlvbkVycm9yLFxuICBTaWduaW5nRXJyb3IsXG4gIEV4dGVuZFRyYW5zYWN0aW9uRXJyb3IsXG4gIEludmFsaWRQYXJhbWV0ZXJWYWx1ZUVycm9yLFxufSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuaW1wb3J0IHsgVHJhbnNhY3Rpb25SZWNlaXB0LCBCbG9jayB9IGZyb20gJy4vaWZhY2UnO1xuaW1wb3J0IHsgQWRkcmVzcyB9IGZyb20gJy4vYWRkcmVzcyc7XG5pbXBvcnQge1xuICBzaWduVHJhbnNhY3Rpb24sXG4gIGlzQmFzZTU4QWRkcmVzcyxcbiAgZGVjb2RlVHJhbnNhY3Rpb24sXG4gIFZBTElEX1JFU09VUkNFX1RZUEVTLFxuICBnZXRIZXhBZGRyZXNzRnJvbUJhc2U1OEFkZHJlc3MsXG4gIFRSQU5TQUNUSU9OX01BWF9FWFBJUkFUSU9OLFxufSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uIH0gZnJvbSAnLi90cmFuc2FjdGlvbic7XG5pbXBvcnQgeyBLZXlQYWlyIH0gZnJvbSAnLi9rZXlQYWlyJztcblxuLyoqXG4gKiBUcm9uIHRyYW5zYWN0aW9uIGJ1aWxkZXIuXG4gKi9cbmV4cG9ydCBjbGFzcyBUcmFuc2FjdGlvbkJ1aWxkZXIgZXh0ZW5kcyBCYXNlVHJhbnNhY3Rpb25CdWlsZGVyIHtcbiAgLy8gdHJhbnNhY3Rpb24gYmVpbmcgYnVpbHRcbiAgcHJpdmF0ZSBfdHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uO1xuICBwcm90ZWN0ZWQgX293bmVyQWRkcmVzczogc3RyaW5nO1xuICBwcm90ZWN0ZWQgX3JlZkJsb2NrQnl0ZXM6IHN0cmluZztcbiAgcHJvdGVjdGVkIF9yZWZCbG9ja0hhc2g6IHN0cmluZztcbiAgcHJvdGVjdGVkIF9leHBpcmF0aW9uOiBudW1iZXI7XG4gIHByb3RlY3RlZCBfdGltZXN0YW1wOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFB1YmxpYyBjb25zdHJ1Y3Rvci5cbiAgICpcbiAgICogQHBhcmFtIHtDb2luQ29uZmlnfSBfY29pbkNvbmZpZyBDb25maWd1cmF0aW9uIG9iamVjdFxuICAgKi9cbiAgY29uc3RydWN0b3IoX2NvaW5Db25maWc6IFJlYWRvbmx5PENvaW5Db25maWc+KSB7XG4gICAgc3VwZXIoX2NvaW5Db25maWcpO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHByb3RlY3RlZCBnZXQgdHJhbnNhY3Rpb24oKTogVHJhbnNhY3Rpb24ge1xuICAgIHJldHVybiB0aGlzLl90cmFuc2FjdGlvbjtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgc2V0IHRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uOiBUcmFuc2FjdGlvbikge1xuICAgIHRoaXMuX3RyYW5zYWN0aW9uID0gdHJhbnNhY3Rpb247XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBzb3VyY2UgYWRkcmVzcyBmb3IgdGhlIHRyYW5zYWN0aW9uXG4gICAqXG4gICAqIEBwYXJhbSB7QWRkcmVzc30gYWRkcmVzcyBUaGUgc291cmNlIGFkZHJlc3NcbiAgICogQHJldHVybnMgdGhlIGJ1aWxkZXIgd2l0aCB0aGUgbmV3IHBhcmFtZXRlciBzZXRcbiAgICovXG4gIHNvdXJjZShhZGRyZXNzOiBBZGRyZXNzKTogdGhpcyB7XG4gICAgdGhpcy52YWxpZGF0ZUFkZHJlc3MoYWRkcmVzcyk7XG4gICAgdGhpcy5fb3duZXJBZGRyZXNzID0gZ2V0SGV4QWRkcmVzc0Zyb21CYXNlNThBZGRyZXNzKGFkZHJlc3MuYWRkcmVzcyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSB0aW1lc3RhbXAgZm9yIHRoZSB0cmFuc2FjdGlvblxuICAgKlxuICAgKiBAcGFyYW0ge251bWJlcn0gdGltZSB0aGUgdGltZXN0YW1wIGluIG1pbGxpc2Vjb25kc1xuICAgKiBAcmV0dXJucyB0aGUgYnVpbGRlciB3aXRoIHRoZSBuZXcgcGFyYW1ldGVyIHNldFxuICAgKi9cbiAgdGltZXN0YW1wKHRpbWU6IG51bWJlcik6IHRoaXMge1xuICAgIHRoaXMuX3RpbWVzdGFtcCA9IHRpbWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBibG9jayB2YWx1ZXMsXG4gICAqXG4gICAqIEBwYXJhbSB7QmxvY2t9IGJsb2NrIHRoZSBvYmplY3QgY29udGFpbmluZyBudW1iZXIgYW5kIGhhc2ggb2YgdGhlIGJsb2NrXG4gICAqIEByZXR1cm5zIHRoZSBidWlsZGVyIHdpdGggdGhlIG5ldyBwYXJhbWV0ZXIgc2V0XG4gICAqL1xuICBibG9jayhibG9jazogQmxvY2spOiB0aGlzIHtcbiAgICBjb25zdCBibG9ja0J5dGVzID0gQnVmZmVyLmFsbG9jKDgpO1xuICAgIGJsb2NrQnl0ZXMud3JpdGVJbnQzMkJFKGJsb2NrLm51bWJlciwgNCk7XG4gICAgdGhpcy5fcmVmQmxvY2tCeXRlcyA9IGJsb2NrQnl0ZXMuc2xpY2UoNiwgOCkudG9TdHJpbmcoJ2hleCcpO1xuICAgIHRoaXMuX3JlZkJsb2NrSGFzaCA9IEJ1ZmZlci5mcm9tKGJsb2NrLmhhc2gsICdoZXgnKS5zbGljZSg4LCAxNikudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBleHBpcmF0aW9uIHRpbWUgZm9yIHRoZSB0cmFuc2FjdGlvbiwgc2V0IHRpbWVzdGFtcCBpZiBpdCB3YXMgbm90IHNldCBwcmV2aW91c2x5XG4gICAqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB0aW1lIHRoZSBleHBpcmF0aW9uIHRpbWUgaW4gbWlsbGlzZWNvbmRzXG4gICAqIEByZXR1cm5zIHRoZSBidWlsZGVyIHdpdGggdGhlIG5ldyBwYXJhbWV0ZXIgc2V0XG4gICAqL1xuICBleHBpcmF0aW9uKHRpbWU6IG51bWJlcik6IHRoaXMge1xuICAgIGlmICh0aGlzLnRyYW5zYWN0aW9uLmlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXh0ZW5kVHJhbnNhY3Rpb25FcnJvcignRXhwaXJhdGlvbiBpcyBhbHJlYWR5IHNldCwgaXQgY2FuIG9ubHkgYmUgZXh0ZW5kZWQnKTtcbiAgICB9XG4gICAgdGhpcy5fdGltZXN0YW1wID0gdGhpcy5fdGltZXN0YW1wIHx8IERhdGUubm93KCk7XG4gICAgdGhpcy52YWxpZGF0ZUV4cGlyYXRpb25UaW1lKHRpbWUpO1xuICAgIHRoaXMuX2V4cGlyYXRpb24gPSB0aW1lO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlIHRyYW5zYWN0aW9uIHRha2VzIGluIHJhdyBKU09OIGRpcmVjdGx5IGZyb20gdGhlIG5vZGUuXG4gICAqXG4gICAqIEBwYXJhbSB7VHJhbnNhY3Rpb25SZWNlaXB0fSByYXdUcmFuc2FjdGlvbiBUaGUgVHJvbiB0cmFuc2FjdGlvbiBpbiBKU09OIGZvcm1hdCBhcyByZXR1cm5lZCBieSB0aGUgVHJvbiBsaWIgb3IgYSBzdHJpbmdpZnllZCB2ZXJzaW9uIG9mIHN1Y2ggSlNPTi5cbiAgICogQHJldHVybnMge1RyYW5zYWN0aW9ufSBUcm9uIHRyYW5zYWN0aW9uXG4gICAqL1xuICBwcm90ZWN0ZWQgZnJvbUltcGxlbWVudGF0aW9uKHJhd1RyYW5zYWN0aW9uOiBUcmFuc2FjdGlvblJlY2VpcHQgfCBzdHJpbmcpOiBUcmFuc2FjdGlvbiB7XG4gICAgbGV0IHR4O1xuICAgIGlmICh0eXBlb2YgcmF3VHJhbnNhY3Rpb24gPT09ICdzdHJpbmcnKSB7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IEpTT04ucGFyc2UocmF3VHJhbnNhY3Rpb24pO1xuICAgICAgdHggPSBuZXcgVHJhbnNhY3Rpb24odGhpcy5fY29pbkNvbmZpZywgdHJhbnNhY3Rpb24pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0eCA9IG5ldyBUcmFuc2FjdGlvbih0aGlzLl9jb2luQ29uZmlnLCByYXdUcmFuc2FjdGlvbik7XG4gICAgfVxuICAgIHJldHVybiB0eDtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgc2lnbkltcGxlbWVudGF0aW9uKGtleTogQmFzZUtleSk6IFRyYW5zYWN0aW9uIHtcbiAgICBpZiAoIXRoaXMudHJhbnNhY3Rpb24uaW5wdXRzKSB7XG4gICAgICB0aHJvdyBuZXcgU2lnbmluZ0Vycm9yKCdUcmFuc2FjdGlvbiBoYXMgbm8gc2VuZGVyJyk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLnRyYW5zYWN0aW9uLm91dHB1dHMpIHtcbiAgICAgIHRocm93IG5ldyBTaWduaW5nRXJyb3IoJ1RyYW5zYWN0aW9uIGhhcyBubyByZWNlaXZlcicpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5hcHBseVNpZ25hdHVyZShrZXkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFwcGx5U2lnbmF0dXJlKGtleTogQmFzZUtleSk6IFRyYW5zYWN0aW9uIHtcbiAgICBjb25zdCBvbGRUcmFuc2FjdGlvbiA9IHRoaXMudHJhbnNhY3Rpb24udG9Kc29uKCk7XG4gICAgLy8gU3RvcmUgdGhlIG9yaWdpbmFsIHNpZ25hdHVyZXMgdG8gY29tcGFyZSB0aGVtIHdpdGggdGhlIG5ldyBvbmVzIGluIGEgbGF0ZXIgc3RlcC4gU2lnbmF0dXJlc1xuICAgIC8vIGNhbiBiZSB1bmRlZmluZWQgaWYgdGhpcyBpcyB0aGUgZmlyc3QgdGltZSB0aGUgdHJhbnNhY3Rpb24gaXMgYmVpbmcgc2lnbmVkXG4gICAgY29uc3Qgb2xkU2lnbmF0dXJlQ291bnQgPSBvbGRUcmFuc2FjdGlvbi5zaWduYXR1cmUgPyBvbGRUcmFuc2FjdGlvbi5zaWduYXR1cmUubGVuZ3RoIDogMDtcbiAgICBsZXQgc2lnbmVkVHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uUmVjZWlwdDtcbiAgICB0cnkge1xuICAgICAgY29uc3Qga2V5UGFpciA9IG5ldyBLZXlQYWlyKHsgcHJ2OiBrZXkua2V5IH0pO1xuICAgICAgLy8gU2luY2UgdGhlIGtleSBwYWlyIHdhcyBnZW5lcmF0ZWQgdXNpbmcgYSBwcml2YXRlIGtleSwgaXQgd2lsbCBhbHdheXMgaGF2ZSBhIHBydiBhdHRyaWJ1dGUsXG4gICAgICAvLyBoZW5jZSBpdCBpcyBzYWZlIHRvIHVzZSBub24tbnVsbCBvcGVyYXRvclxuICAgICAgc2lnbmVkVHJhbnNhY3Rpb24gPSBzaWduVHJhbnNhY3Rpb24oa2V5UGFpci5nZXRLZXlzKCkucHJ2ISwgdGhpcy50cmFuc2FjdGlvbi50b0pzb24oKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgbmV3IFNpZ25pbmdFcnJvcignRmFpbGVkIHRvIHNpZ24gdHJhbnNhY3Rpb24gdmlhIGhlbHBlci4nKTtcbiAgICB9XG5cbiAgICAvLyBFbnN1cmUgdGhhdCB3ZSBoYXZlIG1vcmUgc2lnbmF0dXJlcyB0aGFuIHdoYXQgd2Ugc3RhcnRlZCB3aXRoXG4gICAgaWYgKCFzaWduZWRUcmFuc2FjdGlvbi5zaWduYXR1cmUgfHwgb2xkU2lnbmF0dXJlQ291bnQgPj0gc2lnbmVkVHJhbnNhY3Rpb24uc2lnbmF0dXJlLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IFNpZ25pbmdFcnJvcignVHJhbnNhY3Rpb24gc2lnbmluZyBkaWQgbm90IHJldHVybiBhbiBhZGRpdGlvbmFsIHNpZ25hdHVyZS4nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFRyYW5zYWN0aW9uKHRoaXMuX2NvaW5Db25maWcsIHNpZ25lZFRyYW5zYWN0aW9uKTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgYnVpbGRJbXBsZW1lbnRhdGlvbigpOiBQcm9taXNlPFRyYW5zYWN0aW9uPiB7XG4gICAgLy8gVGhpcyBpcyBhIG5vLW9wIHNpbmNlIFRyb24gdHJhbnNhY3Rpb25zIGFyZSBidWlsdCBmcm9tXG4gICAgaWYgKCF0aGlzLnRyYW5zYWN0aW9uLmlkKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdBIHZhbGlkIHRyYW5zYWN0aW9uIG11c3QgaGF2ZSBhbiBpZCcpO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMudHJhbnNhY3Rpb24pO1xuICB9XG5cbiAgaW5pdEJ1aWxkZXIodHg6IFRyYW5zYWN0aW9uUmVjZWlwdCB8IHN0cmluZykge1xuICAgIHRoaXMudHJhbnNhY3Rpb24gPSB0aGlzLmZyb21JbXBsZW1lbnRhdGlvbih0eCk7XG4gIH1cblxuICAvKipcbiAgICogRXh0ZW5kIHRoZSB2YWxpZGl0eSBvZiB0aGlzIHRyYW5zYWN0aW9uIGJ5IHRoZSBnaXZlbiBhbW91bnQgb2YgdGltZVxuICAgKlxuICAgKiBAcGFyYW0ge251bWJlcn0gZXh0ZW5zaW9uTXMgVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gZXh0ZW5kIHRoZSB2YWxpZFRvIHRpbWVcbiAgICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAgICovXG4gIGV4dGVuZFZhbGlkVG8oZXh0ZW5zaW9uTXM6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMudHJhbnNhY3Rpb24uZXh0ZW5kRXhwaXJhdGlvbihleHRlbnNpb25Ncyk7XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgdmFsaWRhdGVWYWx1ZSh2YWx1ZTogQmlnTnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHZhbHVlLmlzTGVzc1RoYW5PckVxdWFsVG8oMCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVmFsdWUgY2Fubm90IGJlIGJlbG93IHplcm8uJyk7XG4gICAgfVxuXG4gICAgLy8gbWF4IGxvbmcgaW4gSmF2YSAtIGFzc3VtZWQgdXBwZXIgbGltaXQgZm9yIGEgVFJYIHRyYW5zYWN0aW9uXG4gICAgaWYgKHZhbHVlLmlzR3JlYXRlclRoYW4obmV3IEJpZ051bWJlcignOTIyMzM3MjAzNjg1NDc3NTgwNycpKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdWYWx1ZSBjYW5ub3QgYmUgZ3JlYXRlciB0aGFuIGhhbmRsZWQgYnkgdGhlIGphdmF0cm9uIG5vZGUuJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHZhbGlkYXRlQWRkcmVzcyhhZGRyZXNzOiBBZGRyZXNzKTogdm9pZCB7XG4gICAgLy8gYXNzdW1lcyBhIGJhc2UgNTggYWRkcmVzcyBmb3Igb3VyIGFkZHJlc3Nlc1xuICAgIGlmICghaXNCYXNlNThBZGRyZXNzKGFkZHJlc3MuYWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihhZGRyZXNzLmFkZHJlc3MgKyAnIGlzIG5vdCBhIHZhbGlkIGJhc2U1OCBhZGRyZXNzLicpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgbWV0aG9kIHRvIHZhbGlkYXRlIHRoZSByZXNvdXJjZSB0eXBlXG4gICAqIEBwYXJhbSByZXNvdXJjZSBUaGUgcmVzb3VyY2UgdHlwZSB0byBiZSB2YWxpZGF0ZWRcbiAgICovXG4gIHZhbGlkYXRlUmVzb3VyY2UocmVzb3VyY2U6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghVkFMSURfUkVTT1VSQ0VfVFlQRVMuaW5jbHVkZXMocmVzb3VyY2UpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IocmVzb3VyY2UgKyAnIGlzIG5vdCBhIHZhbGlkIHJlc291cmNlIHR5cGUuJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHZhbGlkYXRlS2V5KGtleTogQmFzZUtleSk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBuZXcgS2V5UGFpcih7IHBydjoga2V5LmtleSB9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIHByb3ZpZGVkIGtleSBpcyBub3QgdmFsaWQnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhlIGNvbnRlbnRzIG9mIGEgcmF3IHRyYW5zYWN0aW9uLiBUaGUgdmFsaWRhdGlvblxuICAgKiBwaGFzZSBpcyB0byBjb21wYXJlIHRoZSByYXctZGF0YS1oZXggdG8gdGhlIHJhdy1kYXRhIG9mIHRoZVxuICAgKiB0cmFuc2FjdGlvbi5cbiAgICpcbiAgICogVGhlIGNvbnRlbnRzIHRvIGJlIHZhbGlkYXRlZCBhcmVcbiAgICogMS4gVGhlIHRyYW5zYWN0aW9uIGlkXG4gICAqIDIuIFRoZSBleHBpcmF0aW9uIGRhdGVcbiAgICogMy4gVGhlIHRpbWVzdGFtcFxuICAgKiA0LiBUaGUgY29udHJhY3RcbiAgICpcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvblJlY2VpcHQgfCBzdHJpbmd9IHJhd1RyYW5zYWN0aW9uIFRoZSByYXcgdHJhbnNhY3Rpb24gdG8gYmUgdmFsaWRhdGVkXG4gICAqL1xuICB2YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKHJhd1RyYW5zYWN0aW9uOiBUcmFuc2FjdGlvblJlY2VpcHQgfCBzdHJpbmcpOiB2b2lkIHtcbiAgICAvLyBUT0RPOiBWYWxpZGF0aW9uIG9mIHNpZ25hdHVyZVxuICAgIGlmICghcmF3VHJhbnNhY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignUmF3IHRyYW5zYWN0aW9uIGlzIGVtcHR5Jyk7XG4gICAgfVxuICAgIGxldCBjdXJyVHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uUmVjZWlwdDtcbiAgICAvLyByYXdUcmFuc2FjdGlvbiBjYW4gYmUgZWl0aGVyIFN0cmluZ2lmaWVkIEpTT04gT1JcbiAgICAvLyBpdCBjYW4gYmUgYSByZWd1bGFyIEpTT04gb2JqZWN0IChub3Qgc3RyaW5naWZpZWQpLlxuICAgIGlmICh0eXBlb2YgcmF3VHJhbnNhY3Rpb24gPT09ICdzdHJpbmcnKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjdXJyVHJhbnNhY3Rpb24gPSBKU09OLnBhcnNlKHJhd1RyYW5zYWN0aW9uKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlVHJhbnNhY3Rpb25FcnJvcignVGhlcmUgd2FzIGVycm9yIGluIHBhcnNpbmcgdGhlIEpTT04gc3RyaW5nJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChfLmlzT2JqZWN0KHJhd1RyYW5zYWN0aW9uKSkge1xuICAgICAgY3VyclRyYW5zYWN0aW9uID0gcmF3VHJhbnNhY3Rpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignVHJhbnNhY3Rpb24gaXMgbm90IGFuIG9iamVjdCBvciBzdHJpbmdpZmllZCBqc29uJyk7XG4gICAgfVxuICAgIGNvbnN0IGRlY29kZWRSYXdEYXRhSGV4ID0gZGVjb2RlVHJhbnNhY3Rpb24oY3VyclRyYW5zYWN0aW9uLnJhd19kYXRhX2hleCk7XG4gICAgaWYgKCFjdXJyVHJhbnNhY3Rpb24udHhJRCkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdUcmFuc2FjdGlvbiBJRCBpcyBlbXB0eScpO1xuICAgIH1cbiAgICAvLyBWYWxpZGF0ZSB0aGUgdHJhbnNhY3Rpb24gSUQgZnJvbSB0aGUgcmF3IGRhdGEgaGV4XG4gICAgY29uc3QgaGV4QnVmZmVyID0gQnVmZmVyLmZyb20oY3VyclRyYW5zYWN0aW9uLnJhd19kYXRhX2hleCwgJ2hleCcpO1xuICAgIGNvbnN0IGN1cnJUeElEID0gY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKGhleEJ1ZmZlcikuZGlnZXN0KCdoZXgnKTtcbiAgICBpZiAoY3VyclRyYW5zYWN0aW9uLnR4SUQgIT09IGN1cnJUeElEKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ1RyYW5zYWN0aW9uIGhhcyBub3QgaGF2ZSBhIHZhbGlkIGlkJyk7XG4gICAgfVxuICAgIC8vIFZhbGlkYXRlIHRoZSBleHBpcmF0aW9uIHRpbWUgZnJvbSB0aGUgcmF3LWRhdGEtaGV4XG4gICAgaWYgKGN1cnJUcmFuc2FjdGlvbi5yYXdfZGF0YS5leHBpcmF0aW9uICE9PSBkZWNvZGVkUmF3RGF0YUhleC5leHBpcmF0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ1RyYW5zYWN0aW9uIGhhcyBub3QgaGF2ZSBhIHZhbGlkIGV4cGlyYXRpb24nKTtcbiAgICB9XG4gICAgLy8gVmFsaWRhdGUgdGhlIHRpbWVzdGFtcCBmcm9tIHRoZSByYXctZGF0YS1oZXhcbiAgICBpZiAoY3VyclRyYW5zYWN0aW9uLnJhd19kYXRhLnRpbWVzdGFtcCAhPT0gZGVjb2RlZFJhd0RhdGFIZXgudGltZXN0YW1wKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ1RyYW5zYWN0aW9uIGhhcyBub3QgaGF2ZSBhIHZhbGlkIHRpbWV0YW1wJyk7XG4gICAgfVxuICAgIC8vIFRyYW5zYWN0aW9uIGNvbnRyYWN0IG11c3QgZXhpc3RcbiAgICBpZiAoIWN1cnJUcmFuc2FjdGlvbi5yYXdfZGF0YS5jb250cmFjdCkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdUcmFuc2FjdGlvbiBjb250cmFjdHMgYXJlIGVtcHR5Jyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHZhbGlkYXRlVHJhbnNhY3Rpb24odHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uKTogdm9pZCB7XG4gICAgY29uc3QgaGV4QnVmZmVyID0gQnVmZmVyLmZyb20odHJhbnNhY3Rpb24udG9Kc29uKCkucmF3X2RhdGFfaGV4LCAnaGV4Jyk7XG4gICAgY29uc3QgdHhJZCA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShoZXhCdWZmZXIpLmRpZ2VzdCgnaGV4Jyk7XG4gICAgaWYgKHRyYW5zYWN0aW9uLmlkICE9PSB0eElkKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IodHJhbnNhY3Rpb24uaWQgKyAnIGlzIG5vdCBhIHZhbGlkIHRyYW5zYWN0aW9uIGlkLiBFeHBlY3Rpbmc6ICcgKyB0eElkKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhlIGV4cGlyYXRpb24gdGltZSBvZiB0aGUgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFRoZSBleHBpcmF0aW9uIHRpbWUgaW4gbWlsbGlzZWNvbmRzXG4gICAqIEB0aHJvd3Mge0ludmFsaWRQYXJhbWV0ZXJWYWx1ZUVycm9yfSBJZiB0aGUgZXhwaXJhdGlvbiB0aW1lIGlzIGludmFsaWRcbiAgICovXG4gIHZhbGlkYXRlRXhwaXJhdGlvblRpbWUodmFsdWU6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICh2YWx1ZSA8IHRoaXMuX3RpbWVzdGFtcCkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRQYXJhbWV0ZXJWYWx1ZUVycm9yKCdFeHBpcmF0aW9uIG11c3QgYmUgZ3JlYXRlciB0aGFuIHRpbWVzdGFtcCcpO1xuICAgIH1cblxuICAgIGlmICh2YWx1ZSA8IERhdGUubm93KCkpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkUGFyYW1ldGVyVmFsdWVFcnJvcignRXhwaXJhdGlvbiBtdXN0IGJlIGdyZWF0ZXIgdGhhbiBjdXJyZW50IHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodmFsdWUgLSB0aGlzLl90aW1lc3RhbXAgPiBUUkFOU0FDVElPTl9NQVhfRVhQSVJBVElPTikge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRQYXJhbWV0ZXJWYWx1ZUVycm9yKCdFeHBpcmF0aW9uIG11c3Qgbm90IGJlIGdyZWF0ZXIgdGhhbiBvbmUgZGF5Jyk7XG4gICAgfVxuICB9XG59XG4iXX0=

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


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