PHP WebShell

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

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

"use strict";
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 iface_1 = require("./iface");
const utils_1 = __importDefault(require("./utils"));
class Transaction extends sdk_core_1.BaseTransaction {
    constructor(_coinConfig) {
        super(_coinConfig);
    }
    get icpTransactionData() {
        return this._icpTransactionData;
    }
    set icpTransactionData(icpTransactionData) {
        this._icpTransactionData = icpTransactionData;
    }
    get icpTransaction() {
        return this._icpTransaction;
    }
    set icpTransaction(icpTransaction) {
        this._icpTransaction = icpTransaction;
    }
    get unsignedTransaction() {
        return this._payloadsData.unsigned_transaction;
    }
    get signaturePayload() {
        return this._signaturePayload;
    }
    set signedTransaction(signature) {
        this._signedTransaction = signature;
    }
    get signedTransaction() {
        return this._signedTransaction;
    }
    set payloadsData(payloadsData) {
        this._payloadsData = payloadsData;
    }
    get payloadsData() {
        return this._payloadsData;
    }
    set createdTimestamp(createdTimestamp) {
        this._createdTimestamp = createdTimestamp;
    }
    get createdTimestamp() {
        return this._createdTimestamp;
    }
    async fromRawTransaction(rawTransaction) {
        try {
            const serializedTxFormatBuffer = Buffer.from(rawTransaction, 'hex');
            const serializedTxFormatJsonString = serializedTxFormatBuffer.toString('utf-8');
            const jsonRawTransaction = JSON.parse(serializedTxFormatJsonString);
            const payloadsData = jsonRawTransaction.serializedTxHex;
            this._payloadsData = payloadsData;
            const parsedTx = await this.parseUnsignedTransaction(payloadsData.unsigned_transaction);
            const senderPublicKeyHex = jsonRawTransaction.publicKey;
            const transactionType = parsedTx.operations[0].type;
            switch (transactionType) {
                case iface_1.OperationType.TRANSACTION:
                    this._icpTransactionData = {
                        senderAddress: parsedTx.operations[0].account.address,
                        receiverAddress: parsedTx.operations[1].account.address,
                        amount: parsedTx.operations[1].amount.value,
                        fee: parsedTx.operations[2].amount.value,
                        senderPublicKeyHex: senderPublicKeyHex,
                        transactionType: transactionType,
                        expiryTime: Number(parsedTx.metadata.ingress_end ?? parsedTx.metadata.created_at_time + iface_1.MAX_INGRESS_TTL),
                        memo: parsedTx.metadata.memo,
                    };
                    utils_1.default.validateRawTransaction(this._icpTransactionData);
                    this._id = this.generateTransactionId();
                    break;
                default:
                    throw new Error('Invalid transaction type');
            }
        }
        catch (error) {
            throw new sdk_core_1.InvalidTransactionError(`Invalid transaction: ${error.message}`);
        }
    }
    addSignature(signaturePayloads) {
        if (!signaturePayloads) {
            throw new Error('signatures not provided');
        }
        if (signaturePayloads.length !== this._payloadsData.payloads.length) {
            throw new Error('signatures length is not matching');
        }
        this._signaturePayload = signaturePayloads;
        if (this._id === undefined || this._id === null) {
            this._id = this.generateTransactionId();
        }
    }
    /** @inheritdoc */
    toJson() {
        if (!this._icpTransactionData) {
            throw new sdk_core_1.InvalidTransactionError('Empty transaction');
        }
        switch (this._icpTransactionData.transactionType) {
            case iface_1.OperationType.TRANSACTION:
                const txData = {
                    id: this._id,
                    sender: this._icpTransactionData.senderAddress,
                    senderPublicKey: this._icpTransactionData.senderPublicKeyHex,
                    recipient: this._icpTransactionData.receiverAddress,
                    memo: this._icpTransactionData.memo,
                    feeAmount: this._icpTransactionData.fee,
                    expirationTime: this._icpTransactionData.expiryTime,
                    type: sdk_core_1.TransactionType.Send,
                };
                if (this._icpTransactionData.memo !== undefined) {
                    txData.memo = this._icpTransactionData.memo;
                }
                return txData;
            default:
                throw new Error(`Unsupported transaction type: ${this._icpTransactionData.transactionType}`);
        }
    }
    /** @inheritDoc */
    explainTransaction() {
        const result = this.toJson();
        const displayOrder = ['id', 'outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee'];
        const outputs = [];
        const explanationResult = {
            displayOrder,
            id: this.id,
            outputs,
            outputAmount: '0',
            fee: { fee: '0' },
            type: result.type,
            changeOutputs: [], // account based does not use change outputs
            changeAmount: '0', // account based does not make change
        };
        switch (explanationResult.type) {
            case sdk_core_1.TransactionType.Send:
                return this.explainTransferTransaction(explanationResult);
            default:
                throw new sdk_core_1.InvalidTransactionError('Transaction type not supported');
        }
    }
    /**
     * Explains a transfer transaction by providing details about the recipients and the total output amount.
     *
     * @param {IcpTransactionExplanation} explanationResult - The initial explanation result to be extended.
     * @returns {IcpTransactionExplanation} The extended explanation result including the output amount and recipients.
     */
    explainTransferTransaction(explanationResult) {
        explanationResult.fee = { fee: this.icpTransactionData.fee };
        const recipients = utils_1.default.getRecipients(this.icpTransactionData);
        const outputs = [recipients];
        const outputAmountBN = recipients.amount;
        const outputAmount = outputAmountBN.toString();
        return {
            ...explanationResult,
            outputAmount,
            outputs,
        };
    }
    /** @inheritdoc */
    toBroadcastFormat() {
        if (!this._signedTransaction) {
            throw new sdk_core_1.InvalidTransactionError('Empty transaction');
        }
        return this.serialize();
    }
    serialize() {
        return this._signedTransaction;
    }
    async parseUnsignedTransaction(rawTransaction) {
        const unsignedTransaction = utils_1.default.cborDecode(utils_1.default.blobFromHex(rawTransaction));
        const update = unsignedTransaction.updates[0];
        const httpCanisterUpdate = update[1];
        httpCanisterUpdate.ingress_expiry = BigInt(unsignedTransaction.ingress_expiries[0]);
        return await this.getParsedTransactionFromUpdate(httpCanisterUpdate, false);
    }
    async getParsedTransactionFromUpdate(httpCanisterUpdate, isSigned) {
        const senderPrincipal = utils_1.default.convertSenderBlobToPrincipal(httpCanisterUpdate.sender);
        const ACCOUNT_ID_PREFIX = utils_1.default.getAccountIdPrefix();
        const subAccount = new Uint8Array(32);
        const senderAccount = utils_1.default.getAccountIdFromPrincipalBytes(ACCOUNT_ID_PREFIX, Buffer.from(senderPrincipal.buffer), subAccount);
        const args = await utils_1.default.fromArgs(httpCanisterUpdate.arg);
        const senderOperation = {
            type: iface_1.OperationType.TRANSACTION,
            account: { address: senderAccount },
            amount: {
                value: `-${args.payment.receiverGets.e8s.toString()}`,
                currency: {
                    symbol: this._coinConfig.family,
                    decimals: this._coinConfig.decimalPlaces,
                },
            },
        };
        const receiverOperation = {
            type: iface_1.OperationType.TRANSACTION,
            account: { address: args.to.hash.toString('hex') },
            amount: {
                value: args.payment.receiverGets.e8s.toString(),
                currency: {
                    symbol: this._coinConfig.family,
                    decimals: this._coinConfig.decimalPlaces,
                },
            },
        };
        const feeOperation = {
            type: iface_1.OperationType.FEE,
            account: { address: senderAccount },
            amount: {
                value: `-${args.maxFee.e8s.toString()}`,
                currency: {
                    symbol: this._coinConfig.family,
                    decimals: this._coinConfig.decimalPlaces,
                },
            },
        };
        const accountIdentifierSigners = [];
        if (isSigned) {
            accountIdentifierSigners.push({ address: senderAccount });
        }
        const parsedTxn = {
            operations: [senderOperation, receiverOperation, feeOperation],
            metadata: {
                created_at_time: args.createdAtTime.timestampNanos,
                memo: Number(args.memo.memo),
                ingress_end: Number(httpCanisterUpdate.ingress_expiry) + iface_1.PERMITTED_DRIFT,
            },
            account_identifier_signers: accountIdentifierSigners,
        };
        this.createdTimestamp = args.createdAtTime.timestampNanos;
        return parsedTxn;
    }
    async parseSignedTransaction(rawTransaction) {
        const signedTransaction = utils_1.default.cborDecode(utils_1.default.blobFromHex(rawTransaction));
        const httpCanisterUpdate = signedTransaction.content;
        httpCanisterUpdate.ingress_expiry = BigInt(signedTransaction.content.ingress_expiry);
        return await this.getParsedTransactionFromUpdate(httpCanisterUpdate, true);
    }
    /** @inheritdoc */
    canSign(key) {
        return true;
    }
    /**
     * Generates a unique transaction ID for the current transaction.
     * The transaction ID is derived using the unsigned transaction data,
     * the sender's address, and the receiver's address.
     *
     * @returns {string} The generated transaction ID.
     */
    generateTransactionId() {
        const id = utils_1.default.getTransactionId(this.unsignedTransaction, this.icpTransactionData.senderAddress, this.icpTransactionData.receiverAddress);
        return id;
    }
}
exports.Transaction = Transaction;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3RyYW5zYWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDhDQU95QjtBQUV6QixtQ0FpQmlCO0FBQ2pCLG9EQUE0QjtBQUU1QixNQUFhLFdBQVksU0FBUSwwQkFBZTtJQVE5QyxZQUFZLFdBQWlDO1FBQzNDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNyQixDQUFDO0lBRUQsSUFBSSxrQkFBa0I7UUFDcEIsT0FBTyxJQUFJLENBQUMsbUJBQW1CLENBQUM7SUFDbEMsQ0FBQztJQUVELElBQUksa0JBQWtCLENBQUMsa0JBQXNDO1FBQzNELElBQUksQ0FBQyxtQkFBbUIsR0FBRyxrQkFBa0IsQ0FBQztJQUNoRCxDQUFDO0lBRUQsSUFBSSxjQUFjO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQztJQUM5QixDQUFDO0lBRUQsSUFBSSxjQUFjLENBQUMsY0FBOEI7UUFDL0MsSUFBSSxDQUFDLGVBQWUsR0FBRyxjQUFjLENBQUM7SUFDeEMsQ0FBQztJQUVELElBQUksbUJBQW1CO1FBQ3JCLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxvQkFBb0IsQ0FBQztJQUNqRCxDQUFDO0lBRUQsSUFBSSxnQkFBZ0I7UUFDbEIsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUM7SUFDaEMsQ0FBQztJQUVELElBQUksaUJBQWlCLENBQUMsU0FBaUI7UUFDckMsSUFBSSxDQUFDLGtCQUFrQixHQUFHLFNBQVMsQ0FBQztJQUN0QyxDQUFDO0lBRUQsSUFBSSxpQkFBaUI7UUFDbkIsT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUM7SUFDakMsQ0FBQztJQUVELElBQUksWUFBWSxDQUFDLFlBQTBCO1FBQ3pDLElBQUksQ0FBQyxhQUFhLEdBQUcsWUFBWSxDQUFDO0lBQ3BDLENBQUM7SUFFRCxJQUFJLFlBQVk7UUFDZCxPQUFPLElBQUksQ0FB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SyxDQUFDLFVBQVUsQ0FBQyxlQUFLLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7UUFDOUUsTUFBTSxrQkFBa0IsR0FBSSxpQkFBb0MsQ0FBQyxPQUE2QixDQUFDO1FBQy9GLGtCQUFrQixDQUFDLGNBQWMsR0FBRyxNQUFNLENBQUUsaUJBQW9DLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3pHLE9BQU8sTUFBTSxJQUFJLENBQUMsOEJBQThCLENBQUMsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDN0UsQ0FBQztJQUVELGtCQUFrQjtJQUNsQixPQUFPLENBQUMsR0FBWTtRQUNsQixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSyxxQkFBcUI7UUFDM0IsTUFBTSxFQUFFLEdBQUcsZUFBSyxDQUFDLGdCQUFnQixDQUMvQixJQUFJLENBQUMsbUJBQW1CLEVBQ3hCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLEVBQ3JDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxlQUFlLENBQ3hDLENBQUM7UUFDRixPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7Q0FDRjtBQWpTRCxrQ0FpU0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBCYXNlS2V5LFxuICBCYXNlVHJhbnNhY3Rpb24sXG4gIFRyYW5zYWN0aW9uUmVjaXBpZW50LFxuICBUcmFuc2FjdGlvblR5cGUsXG4gIEludmFsaWRUcmFuc2FjdGlvbkVycm9yLFxuICBUcmFuc2FjdGlvblR5cGUgYXMgQml0R29UcmFuc2FjdGlvblR5cGUsXG59IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBCYXNlQ29pbiBhcyBDb2luQ29uZmlnIH0gZnJvbSAnQGJpdGdvL3N0YXRpY3MnO1xuaW1wb3J0IHtcbiAgSWNwVHJhbnNhY3Rpb24sXG4gIEljcFRyYW5zYWN0aW9uRGF0YSxcbiAgUGF5bG9hZHNEYXRhLFxuICBPcGVyYXRpb25UeXBlLFxuICBTaWduYXR1cmVzLFxuICBUeERhdGEsXG4gIEljcFRyYW5zYWN0aW9uRXhwbGFuYXRpb24sXG4gIENib3JVbnNpZ25lZFRyYW5zYWN0aW9uLFxuICBIdHRwQ2FuaXN0ZXJVcGRhdGUsXG4gIFBhcnNlZFRyYW5zYWN0aW9uLFxuICBJY3BPcGVyYXRpb24sXG4gIFVwZGF0ZUVudmVsb3BlLFxuICBJY3BBY2NvdW50LFxuICBNQVhfSU5HUkVTU19UVEwsXG4gIFBFUk1JVFRFRF9EUklGVCxcbiAgUmF3VHJhbnNhY3Rpb24sXG59IGZyb20gJy4vaWZhY2UnO1xuaW1wb3J0IHV0aWxzIGZyb20gJy4vdXRpbHMnO1xuXG5leHBvcnQgY2xhc3MgVHJhbnNhY3Rpb24gZXh0ZW5kcyBCYXNlVHJhbnNhY3Rpb24ge1xuICBwcm90ZWN0ZWQgX2ljcFRyYW5zYWN0aW9uRGF0YTogSWNwVHJhbnNhY3Rpb25EYXRhO1xuICBwcm90ZWN0ZWQgX2ljcFRyYW5zYWN0aW9uOiBJY3BUcmFuc2FjdGlvbjtcbiAgcHJvdGVjdGVkIF9wYXlsb2Fkc0RhdGE6IFBheWxvYWRzRGF0YTtcbiAgcHJvdGVjdGVkIF9zaWduZWRUcmFuc2FjdGlvbjogc3RyaW5nO1xuICBwcm90ZWN0ZWQgX3NpZ25hdHVyZVBheWxvYWQ6IFNpZ25hdHVyZXNbXTtcbiAgcHJvdGVjdGVkIF9jcmVhdGVkVGltZXN0YW1wOiBudW1iZXIgfCBiaWdpbnQgfCB1bmRlZmluZWQ7XG5cbiAgY29uc3RydWN0b3IoX2NvaW5Db25maWc6IFJlYWRvbmx5PENvaW5Db25maWc+KSB7XG4gICAgc3VwZXIoX2NvaW5Db25maWcpO1xuICB9XG5cbiAgZ2V0IGljcFRyYW5zYWN0aW9uRGF0YSgpOiBJY3BUcmFuc2FjdGlvbkRhdGEge1xuICAgIHJldHVybiB0aGlzLl9pY3BUcmFuc2FjdGlvbkRhdGE7XG4gIH1cblxuICBzZXQgaWNwVHJhbnNhY3Rpb25EYXRhKGljcFRyYW5zYWN0aW9uRGF0YTogSWNwVHJhbnNhY3Rpb25EYXRhKSB7XG4gICAgdGhpcy5faWNwVHJhbnNhY3Rpb25EYXRhID0gaWNwVHJhbnNhY3Rpb25EYXRhO1xuICB9XG5cbiAgZ2V0IGljcFRyYW5zYWN0aW9uKCk6IEljcFRyYW5zYWN0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5faWNwVHJhbnNhY3Rpb247XG4gIH1cblxuICBzZXQgaWNwVHJhbnNhY3Rpb24oaWNwVHJhbnNhY3Rpb246IEljcFRyYW5zYWN0aW9uKSB7XG4gICAgdGhpcy5faWNwVHJhbnNhY3Rpb24gPSBpY3BUcmFuc2FjdGlvbjtcbiAgfVxuXG4gIGdldCB1bnNpZ25lZFRyYW5zYWN0aW9uKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX3BheWxvYWRzRGF0YS51bnNpZ25lZF90cmFuc2FjdGlvbjtcbiAgfVxuXG4gIGdldCBzaWduYXR1cmVQYXlsb2FkKCk6IFNpZ25hdHVyZXNbXSB7XG4gICAgcmV0dXJuIHRoaXMuX3NpZ25hdHVyZVBheWxvYWQ7XG4gIH1cblxuICBzZXQgc2lnbmVkVHJhbnNhY3Rpb24oc2lnbmF0dXJlOiBzdHJpbmcpIHtcbiAgICB0aGlzLl9zaWduZWRUcmFuc2FjdGlvbiA9IHNpZ25hdHVyZTtcbiAgfVxuXG4gIGdldCBzaWduZWRUcmFuc2FjdGlvbigpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl9zaWduZWRUcmFuc2FjdGlvbjtcbiAgfVxuXG4gIHNldCBwYXlsb2Fkc0RhdGEocGF5bG9hZHNEYXRhOiBQYXlsb2Fkc0RhdGEpIHtcbiAgICB0aGlzLl9wYXlsb2Fkc0RhdGEgPSBwYXlsb2Fkc0RhdGE7XG4gIH1cblxuICBnZXQgcGF5bG9hZHNEYXRhKCk6IFBheWxvYWRzRGF0YSB7XG4gICAgcmV0dXJuIHRoaXMuX3BheWxvYWRzRGF0YTtcbiAgfVxuXG4gIHNldCBjcmVhdGVkVGltZXN0YW1wKGNyZWF0ZWRUaW1lc3RhbXA6IG51bWJlcikge1xuICAgIHRoaXMuX2NyZWF0ZWRUaW1lc3RhbXAgPSBjcmVhdGVkVGltZXN0YW1wO1xuICB9XG5cbiAgZ2V0IGNyZWF0ZWRUaW1lc3RhbXAoKTogbnVtYmVyIHwgYmlnaW50IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fY3JlYXRlZFRpbWVzdGFtcDtcbiAgfVxuXG4gIGFzeW5jIGZyb21SYXdUcmFuc2FjdGlvbihyYXdUcmFuc2FjdGlvbjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRUeEZvcm1hdEJ1ZmZlciA9IEJ1ZmZlci5mcm9tKHJhd1RyYW5zYWN0aW9uLCAnaGV4Jyk7XG4gICAgICBjb25zdCBzZXJpYWxpemVkVHhGb3JtYXRKc29uU3RyaW5nID0gc2VyaWFsaXplZFR4Rm9ybWF0QnVmZmVyLnRvU3RyaW5nKCd1dGYtOCcpO1xuICAgICAgY29uc3QganNvblJhd1RyYW5zYWN0aW9uOiBSYXdUcmFuc2FjdGlvbiA9IEpTT04ucGFyc2Uoc2VyaWFsaXplZFR4Rm9ybWF0SnNvblN0cmluZyk7XG4gICAgICBjb25zdCBwYXlsb2Fkc0RhdGEgPSBqc29uUmF3VHJhbnNhY3Rpb24uc2VyaWFsaXplZFR4SGV4O1xuICAgICAgdGhpcy5fcGF5bG9hZHNEYXRhID0gcGF5bG9hZHNEYXRhO1xuICAgICAgY29uc3QgcGFyc2VkVHggPSBhd2FpdCB0aGlzLnBhcnNlVW5zaWduZWRUcmFuc2FjdGlvbihwYXlsb2Fkc0RhdGEudW5zaWduZWRfdHJhbnNhY3Rpb24pO1xuICAgICAgY29uc3Qgc2VuZGVyUHVibGljS2V5SGV4ID0ganNvblJhd1RyYW5zYWN0aW9uLnB1YmxpY0tleTtcbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uVHlwZSA9IHBhcnNlZFR4Lm9wZXJhdGlvbnNbMF0udHlwZTtcbiAgICAgIHN3aXRjaCAodHJhbnNhY3Rpb25UeXBlKSB7XG4gICAgICAgIGNhc2UgT3BlcmF0aW9uVHlwZS5UUkFOU0FDVElPTjpcbiAgICAgICAgICB0aGlzLl9pY3BUcmFuc2FjdGlvbkRhdGEgPSB7XG4gICAgICAgICAgICBzZW5kZXJBZGRyZXNzOiBwYXJzZWRUeC5vcGVyYXRpb25zWzBdLmFjY291bnQuYWRkcmVzcyxcbiAgICAgICAgICAgIHJlY2VpdmVyQWRkcmVzczogcGFyc2VkVHgub3BlcmF0aW9uc1sxXS5hY2NvdW50LmFkZHJlc3MsXG4gICAgICAgICAgICBhbW91bnQ6IHBhcnNlZFR4Lm9wZXJhdGlvbnNbMV0uYW1vdW50LnZhbHVlLFxuICAgICAgICAgICAgZmVlOiBwYXJzZWRUeC5vcGVyYXRpb25zWzJdLmFtb3VudC52YWx1ZSxcbiAgICAgICAgICAgIHNlbmRlclB1YmxpY0tleUhleDogc2VuZGVyUHVibGljS2V5SGV4LFxuICAgICAgICAgICAgdHJhbnNhY3Rpb25UeXBlOiB0cmFuc2FjdGlvblR5cGUsXG4gICAgICAgICAgICBleHBpcnlUaW1lOiBOdW1iZXIocGFyc2VkVHgubWV0YWRhdGEuaW5ncmVzc19lbmQgPz8gcGFyc2VkVHgubWV0YWRhdGEuY3JlYXRlZF9hdF90aW1lICsgTUFYX0lOR1JFU1NfVFRMKSxcbiAgICAgICAgICAgIG1lbW86IHBhcnNlZFR4Lm1ldGFkYXRhLm1lbW8sXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIHV0aWxzLnZhbGlkYXRlUmF3VHJhbnNhY3Rpb24odGhpcy5faWNwVHJhbnNhY3Rpb25EYXRhKTtcbiAgICAgICAgICB0aGlzLl9pZCA9IHRoaXMuZ2VuZXJhdGVUcmFuc2FjdGlvbklkKCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uIHR5cGUnKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKGBJbnZhbGlkIHRyYW5zYWN0aW9uOiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgfVxuICB9XG5cbiAgYWRkU2lnbmF0dXJlKHNpZ25hdHVyZVBheWxvYWRzOiBTaWduYXR1cmVzW10pOiB2b2lkIHtcbiAgICBpZiAoIXNpZ25hdHVyZVBheWxvYWRzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NpZ25hdHVyZXMgbm90IHByb3ZpZGVkJyk7XG4gICAgfVxuICAgIGlmIChzaWduYXR1cmVQYXlsb2Fkcy5sZW5ndGggIT09IHRoaXMuX3BheWxvYWRzRGF0YS5wYXlsb2Fkcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignc2lnbmF0dXJlcyBsZW5ndGggaXMgbm90IG1hdGNoaW5nJyk7XG4gICAgfVxuICAgIHRoaXMuX3NpZ25hdHVyZVBheWxvYWQgPSBzaWduYXR1cmVQYXlsb2FkcztcbiAgICBpZiAodGhpcy5faWQgPT09IHVuZGVmaW5lZCB8fCB0aGlzLl9pZCA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5faWQgPSB0aGlzLmdlbmVyYXRlVHJhbnNhY3Rpb25JZCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICB0b0pzb24oKTogVHhEYXRhIHtcbiAgICBpZiAoIXRoaXMuX2ljcFRyYW5zYWN0aW9uRGF0YSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdFbXB0eSB0cmFuc2FjdGlvbicpO1xuICAgIH1cbiAgICBzd2l0Y2ggKHRoaXMuX2ljcFRyYW5zYWN0aW9uRGF0YS50cmFuc2FjdGlvblR5cGUpIHtcbiAgICAgIGNhc2UgT3BlcmF0aW9uVHlwZS5UUkFOU0FDVElPTjpcbiAgICAgICAgY29uc3QgdHhEYXRhOiBUeERhdGEgPSB7XG4gICAgICAgICAgaWQ6IHRoaXMuX2lkLFxuICAgICAgICAgIHNlbmRlcjogdGhpcy5faWNwVHJhbnNhY3Rpb25EYXRhLnNlbmRlckFkZHJlc3MsXG4gICAgICAgICAgc2VuZGVyUHVibGljS2V5OiB0aGlzLl9pY3BUcmFuc2FjdGlvbkRhdGEuc2VuZGVyUHVibGljS2V5SGV4LFxuICAgICAgICAgIHJlY2lwaWVudDogdGhpcy5faWNwVHJhbnNhY3Rpb25EYXRhLnJlY2VpdmVyQWRkcmVzcyxcbiAgICAgICAgICBtZW1vOiB0aGlzLl9pY3BUcmFuc2FjdGlvbkRhdGEubWVtbyxcbiAgICAgICAgICBmZWVBbW91bnQ6IHRoaXMuX2ljcFRyYW5zYWN0aW9uRGF0YS5mZWUsXG4gICAgICAgICAgZXhwaXJhdGlvblRpbWU6IHRoaXMuX2ljcFRyYW5zYWN0aW9uRGF0YS5leHBpcnlUaW1lLFxuICAgICAgICAgIHR5cGU6IEJpdEdvVHJhbnNhY3Rpb25UeXBlLlNlbmQsXG4gICAgICAgIH07XG4gICAgICAgIGlmICh0aGlzLl9pY3BUcmFuc2FjdGlvbkRhdGEubWVtbyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdHhEYXRhLm1lbW8gPSB0aGlzLl9pY3BUcmFuc2FjdGlvbkRhdGEubWVtbztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHhEYXRhO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCB0cmFuc2FjdGlvbiB0eXBlOiAke3RoaXMuX2ljcFRyYW5zYWN0aW9uRGF0YS50cmFuc2FjdGlvblR5cGV9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICovXG4gIGV4cGxhaW5UcmFuc2FjdGlvbigpOiBJY3BUcmFuc2FjdGlvbkV4cGxhbmF0aW9uIHtcbiAgICBjb25zdCByZXN1bHQgPSB0aGlzLnRvSnNvbigpO1xuICAgIGNvbnN0IGRpc3BsYXlPcmRlciA9IFsnaWQnLCAnb3V0cHV0QW1vdW50JywgJ2NoYW5nZUFtb3VudCcsICdvdXRwdXRzJywgJ2NoYW5nZU91dHB1dHMnLCAnZmVlJ107XG4gICAgY29uc3Qgb3V0cHV0czogVHJhbnNhY3Rpb25SZWNpcGllbnRbXSA9IFtdO1xuXG4gICAgY29uc3QgZXhwbGFuYXRpb25SZXN1bHQgPSB7XG4gICAgICBkaXNwbGF5T3JkZXIsXG4gICAgICBpZDogdGhpcy5pZCxcbiAgICAgIG91dHB1dHMsXG4gICAgICBvdXRwdXRBbW91bnQ6ICcwJyxcbiAgICAgIGZlZTogeyBmZWU6ICcwJyB9LFxuICAgICAgdHlwZTogcmVzdWx0LnR5cGUsXG4gICAgICBjaGFuZ2VPdXRwdXRzOiBbXSwgLy8gYWNjb3VudCBiYXNlZCBkb2VzIG5vdCB1c2UgY2hhbmdlIG91dHB1dHNcbiAgICAgIGNoYW5nZUFtb3VudDogJzAnLCAvLyBhY2NvdW50IGJhc2VkIGRvZXMgbm90IG1ha2UgY2hhbmdlXG4gICAgfTtcblxuICAgIHN3aXRjaCAoZXhwbGFuYXRpb25SZXN1bHQudHlwZSkge1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU2VuZDpcbiAgICAgICAgcmV0dXJuIHRoaXMuZXhwbGFpblRyYW5zZmVyVHJhbnNhY3Rpb24oZXhwbGFuYXRpb25SZXN1bHQpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdUcmFuc2FjdGlvbiB0eXBlIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRXhwbGFpbnMgYSB0cmFuc2ZlciB0cmFuc2FjdGlvbiBieSBwcm92aWRpbmcgZGV0YWlscyBhYm91dCB0aGUgcmVjaXBpZW50cyBhbmQgdGhlIHRvdGFsIG91dHB1dCBhbW91bnQuXG4gICAqXG4gICAqIEBwYXJhbSB7SWNwVHJhbnNhY3Rpb25FeHBsYW5hdGlvbn0gZXhwbGFuYXRpb25SZXN1bHQgLSBUaGUgaW5pdGlhbCBleHBsYW5hdGlvbiByZXN1bHQgdG8gYmUgZXh0ZW5kZWQuXG4gICAqIEByZXR1cm5zIHtJY3BUcmFuc2FjdGlvbkV4cGxhbmF0aW9ufSBUaGUgZXh0ZW5kZWQgZXhwbGFuYXRpb24gcmVzdWx0IGluY2x1ZGluZyB0aGUgb3V0cHV0IGFtb3VudCBhbmQgcmVjaXBpZW50cy5cbiAgICovXG4gIGV4cGxhaW5UcmFuc2ZlclRyYW5zYWN0aW9uKGV4cGxhbmF0aW9uUmVzdWx0OiBJY3BUcmFuc2FjdGlvbkV4cGxhbmF0aW9uKTogSWNwVHJhbnNhY3Rpb25FeHBsYW5hdGlvbiB7XG4gICAgZXhwbGFuYXRpb25SZXN1bHQuZmVlID0geyBmZWU6IHRoaXMuaWNwVHJhbnNhY3Rpb25EYXRhLmZlZSB9O1xuICAgIGNvbnN0IHJlY2lwaWVudHMgPSB1dGlscy5nZXRSZWNpcGllbnRzKHRoaXMuaWNwVHJhbnNhY3Rpb25EYXRhKTtcbiAgICBjb25zdCBvdXRwdXRzOiBUcmFuc2FjdGlvblJlY2lwaWVudFtdID0gW3JlY2lwaWVudHNdO1xuICAgIGNvbnN0IG91dHB1dEFtb3VudEJOID0gcmVjaXBpZW50cy5hbW91bnQ7XG4gICAgY29uc3Qgb3V0cHV0QW1vdW50ID0gb3V0cHV0QW1vdW50Qk4udG9TdHJpbmcoKTtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi5leHBsYW5hdGlvblJlc3VsdCxcbiAgICAgIG91dHB1dEFtb3VudCxcbiAgICAgIG91dHB1dHMsXG4gICAgfTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICB0b0Jyb2FkY2FzdEZvcm1hdCgpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5fc2lnbmVkVHJhbnNhY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignRW1wdHkgdHJhbnNhY3Rpb24nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2VyaWFsaXplKCk7XG4gIH1cblxuICBzZXJpYWxpemUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fc2lnbmVkVHJhbnNhY3Rpb247XG4gIH1cblxuICBhc3luYyBwYXJzZVVuc2lnbmVkVHJhbnNhY3Rpb24ocmF3VHJhbnNhY3Rpb246IHN0cmluZyk6IFByb21pc2U8UGFyc2VkVHJhbnNhY3Rpb24+IHtcbiAgICBjb25zdCB1bnNpZ25lZFRyYW5zYWN0aW9uID0gdXRpbHMuY2JvckRlY29kZSh1dGlscy5ibG9iRnJvbUhleChyYXdUcmFuc2FjdGlvbikpIGFzIENib3JVbnNpZ25lZFRyYW5zYWN0aW9uO1xuICAgIGNvbnN0IHVwZGF0ZSA9IHVuc2lnbmVkVHJhbnNhY3Rpb24udXBkYXRlc1swXTtcbiAgICBjb25zdCBodHRwQ2FuaXN0ZXJVcGRhdGUgPSAodXBkYXRlIGFzIHVua25vd24gYXMgW3N0cmluZywgSHR0cENhbmlzdGVyVXBkYXRlXSlbMV07XG4gICAgaHR0cENhbmlzdGVyVXBkYXRlLmluZ3Jlc3NfZXhwaXJ5ID0gQmlnSW50KHVuc2lnbmVkVHJhbnNhY3Rpb24uaW5ncmVzc19leHBpcmllc1swXSk7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0UGFyc2VkVHJhbnNhY3Rpb25Gcm9tVXBkYXRlKGh0dHBDYW5pc3RlclVwZGF0ZSwgZmFsc2UpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBnZXRQYXJzZWRUcmFuc2FjdGlvbkZyb21VcGRhdGUoXG4gICAgaHR0cENhbmlzdGVyVXBkYXRlOiBIdHRwQ2FuaXN0ZXJVcGRhdGUsXG4gICAgaXNTaWduZWQ6IGJvb2xlYW5cbiAgKTogUHJvbWlzZTxQYXJzZWRUcmFuc2FjdGlvbj4ge1xuICAgIGNvbnN0IHNlbmRlclByaW5jaXBhbCA9IHV0aWxzLmNvbnZlcnRTZW5kZXJCbG9iVG9QcmluY2lwYWwoaHR0cENhbmlzdGVyVXBkYXRlLnNlbmRlcik7XG4gICAgY29uc3QgQUNDT1VOVF9JRF9QUkVGSVggPSB1dGlscy5nZXRBY2NvdW50SWRQcmVmaXgoKTtcbiAgICBjb25zdCBzdWJBY2NvdW50ID0gbmV3IFVpbnQ4QXJyYXkoMzIpO1xuICAgIGNvbnN0IHNlbmRlckFjY291bnQgPSB1dGlscy5nZXRBY2NvdW50SWRGcm9tUHJpbmNpcGFsQnl0ZXMoXG4gICAgICBBQ0NPVU5UX0lEX1BSRUZJWCxcbiAgICAgIEJ1ZmZlci5mcm9tKHNlbmRlclByaW5jaXBhbC5idWZmZXIpLFxuICAgICAgc3ViQWNjb3VudFxuICAgICk7XG4gICAgY29uc3QgYXJncyA9IGF3YWl0IHV0aWxzLmZyb21BcmdzKGh0dHBDYW5pc3RlclVwZGF0ZS5hcmcpO1xuICAgIGNvbnN0IHNlbmRlck9wZXJhdGlvbjogSWNwT3BlcmF0aW9uID0ge1xuICAgICAgdHlwZTogT3BlcmF0aW9uVHlwZS5UUkFOU0FDVElPTixcbiAgICAgIGFjY291bnQ6IHsgYWRkcmVzczogc2VuZGVyQWNjb3VudCB9LFxuICAgICAgYW1vdW50OiB7XG4gICAgICAgIHZhbHVlOiBgLSR7YXJncy5wYXltZW50LnJlY2VpdmVyR2V0cy5lOHMudG9TdHJpbmcoKX1gLFxuICAgICAgICBjdXJyZW5jeToge1xuICAgICAgICAgIHN5bWJvbDogdGhpcy5fY29pbkNvbmZpZy5mYW1pbHksXG4gICAgICAgICAgZGVjaW1hbHM6IHRoaXMuX2NvaW5Db25maWcuZGVjaW1hbFBsYWNlcyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfTtcbiAgICBjb25zdCByZWNlaXZlck9wZXJhdGlvbjogSWNwT3BlcmF0aW9uID0ge1xuICAgICAgdHlwZTogT3BlcmF0aW9uVHlwZS5UUkFOU0FDVElPTixcbiAgICAgIGFjY291bnQ6IHsgYWRkcmVzczogYXJncy50by5oYXNoLnRvU3RyaW5nKCdoZXgnKSB9LFxuICAgICAgYW1vdW50OiB7XG4gICAgICAgIHZhbHVlOiBhcmdzLnBheW1lbnQucmVjZWl2ZXJHZXRzLmU4cy50b1N0cmluZygpLFxuICAgICAgICBjdXJyZW5jeToge1xuICAgICAgICAgIHN5bWJvbDogdGhpcy5fY29pbkNvbmZpZy5mYW1pbHksXG4gICAgICAgICAgZGVjaW1hbHM6IHRoaXMuX2NvaW5Db25maWcuZGVjaW1hbFBsYWNlcyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIGNvbnN0IGZlZU9wZXJhdGlvbjogSWNwT3BlcmF0aW9uID0ge1xuICAgICAgdHlwZTogT3BlcmF0aW9uVHlwZS5GRUUsXG4gICAgICBhY2NvdW50OiB7IGFkZHJlc3M6IHNlbmRlckFjY291bnQgfSxcbiAgICAgIGFtb3VudDoge1xuICAgICAgICB2YWx1ZTogYC0ke2FyZ3MubWF4RmVlLmU4cy50b1N0cmluZygpfWAsXG4gICAgICAgIGN1cnJlbmN5OiB7XG4gICAgICAgICAgc3ltYm9sOiB0aGlzLl9jb2luQ29uZmlnLmZhbWlseSxcbiAgICAgICAgICBkZWNpbWFsczogdGhpcy5fY29pbkNvbmZpZy5kZWNpbWFsUGxhY2VzLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9O1xuICAgIGNvbnN0IGFjY291bnRJZGVudGlmaWVyU2lnbmVyczogSWNwQWNjb3VudFtdID0gW107XG4gICAgaWYgKGlzU2lnbmVkKSB7XG4gICAgICBhY2NvdW50SWRlbnRpZmllclNpZ25lcnMucHVzaCh7IGFkZHJlc3M6IHNlbmRlckFjY291bnQgfSk7XG4gICAgfVxuICAgIGNvbnN0IHBhcnNlZFR4bjogUGFyc2VkVHJhbnNhY3Rpb24gPSB7XG4gICAgICBvcGVyYXRpb25zOiBbc2VuZGVyT3BlcmF0aW9uLCByZWNlaXZlck9wZXJhdGlvbiwgZmVlT3BlcmF0aW9uXSxcbiAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgIGNyZWF0ZWRfYXRfdGltZTogYXJncy5jcmVhdGVkQXRUaW1lLnRpbWVzdGFtcE5hbm9zLFxuICAgICAgICBtZW1vOiBOdW1iZXIoYXJncy5tZW1vLm1lbW8pLFxuICAgICAgICBpbmdyZXNzX2VuZDogTnVtYmVyKGh0dHBDYW5pc3RlclVwZGF0ZS5pbmdyZXNzX2V4cGlyeSkgKyBQRVJNSVRURURfRFJJRlQsXG4gICAgICB9LFxuICAgICAgYWNjb3VudF9pZGVudGlmaWVyX3NpZ25lcnM6IGFjY291bnRJZGVudGlmaWVyU2lnbmVycyxcbiAgICB9O1xuICAgIHRoaXMuY3JlYXRlZFRpbWVzdGFtcCA9IGFyZ3MuY3JlYXRlZEF0VGltZS50aW1lc3RhbXBOYW5vcztcbiAgICByZXR1cm4gcGFyc2VkVHhuO1xuICB9XG5cbiAgYXN5bmMgcGFyc2VTaWduZWRUcmFuc2FjdGlvbihyYXdUcmFuc2FjdGlvbjogc3RyaW5nKTogUHJvbWlzZTxQYXJzZWRUcmFuc2FjdGlvbj4ge1xuICAgIGNvbnN0IHNpZ25lZFRyYW5zYWN0aW9uID0gdXRpbHMuY2JvckRlY29kZSh1dGlscy5ibG9iRnJvbUhleChyYXdUcmFuc2FjdGlvbikpO1xuICAgIGNvbnN0IGh0dHBDYW5pc3RlclVwZGF0ZSA9IChzaWduZWRUcmFuc2FjdGlvbiBhcyBVcGRhdGVFbnZlbG9wZSkuY29udGVudCBhcyBIdHRwQ2FuaXN0ZXJVcGRhdGU7XG4gICAgaHR0cENhbmlzdGVyVXBkYXRlLmluZ3Jlc3NfZXhwaXJ5ID0gQmlnSW50KChzaWduZWRUcmFuc2FjdGlvbiBhcyBVcGRhdGVFbnZlbG9wZSkuY29udGVudC5pbmdyZXNzX2V4cGlyeSk7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0UGFyc2VkVHJhbnNhY3Rpb25Gcm9tVXBkYXRlKGh0dHBDYW5pc3RlclVwZGF0ZSwgdHJ1ZSk7XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgY2FuU2lnbihrZXk6IEJhc2VLZXkpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgYSB1bmlxdWUgdHJhbnNhY3Rpb24gSUQgZm9yIHRoZSBjdXJyZW50IHRyYW5zYWN0aW9uLlxuICAgKiBUaGUgdHJhbnNhY3Rpb24gSUQgaXMgZGVyaXZlZCB1c2luZyB0aGUgdW5zaWduZWQgdHJhbnNhY3Rpb24gZGF0YSxcbiAgICogdGhlIHNlbmRlcidzIGFkZHJlc3MsIGFuZCB0aGUgcmVjZWl2ZXIncyBhZGRyZXNzLlxuICAgKlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZ2VuZXJhdGVkIHRyYW5zYWN0aW9uIElELlxuICAgKi9cbiAgcHJpdmF0ZSBnZW5lcmF0ZVRyYW5zYWN0aW9uSWQoKTogc3RyaW5nIHtcbiAgICBjb25zdCBpZCA9IHV0aWxzLmdldFRyYW5zYWN0aW9uSWQoXG4gICAgICB0aGlzLnVuc2lnbmVkVHJhbnNhY3Rpb24sXG4gICAgICB0aGlzLmljcFRyYW5zYWN0aW9uRGF0YS5zZW5kZXJBZGRyZXNzLFxuICAgICAgdGhpcy5pY3BUcmFuc2FjdGlvbkRhdGEucmVjZWl2ZXJBZGRyZXNzXG4gICAgKTtcbiAgICByZXR1cm4gaWQ7XG4gIH1cbn1cbiJdfQ==

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


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