PHP WebShell

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

Просмотр файла: utils.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.IslmUtils = void 0;
const sdk_core_1 = require("@bitgo/sdk-core");
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const abstract_cosmos_1 = require("@bitgo/abstract-cosmos");
const constants = __importStar(require("./constants"));
const encoding_1 = require("@cosmjs/encoding");
const any_1 = require("cosmjs-types/google/protobuf/any");
const ethSecp256k1_1 = require("../../resources/types/ethSecp256k1");
const keccak_1 = __importDefault(require("keccak"));
class IslmUtils extends abstract_cosmos_1.CosmosUtils {
    /** @inheritdoc */
    isValidAddress(address) {
        return this.isValidCosmosLikeAddressWithMemoId(address, constants.accountAddressRegex);
    }
    /** @inheritdoc */
    isValidValidatorAddress(address) {
        return constants.validatorAddressRegex.test(address);
    }
    /** @inheritdoc */
    validateAmount(amount) {
        const amountBig = (0, bignumber_js_1.default)(amount.amount);
        if (amountBig.isLessThanOrEqualTo(0)) {
            throw new sdk_core_1.InvalidTransactionError('transactionBuilder: validateAmount: Invalid amount: ' + amount.amount);
        }
        if (!constants.validDenoms.find((denom) => denom === amount.denom)) {
            throw new sdk_core_1.InvalidTransactionError('transactionBuilder: validateAmount: Invalid denom: ' + amount.denom);
        }
    }
    /** @inheritdoc */
    getPublicKeyFromDecodedTx(decodedTx) {
        const publicKeyUInt8Array = decodedTx.authInfo.signerInfos?.[0].publicKey?.value;
        if (publicKeyUInt8Array) {
            return (0, encoding_1.toHex)((0, encoding_1.fromBase64)(this.decodePubkey(decodedTx.authInfo.signerInfos?.[0].publicKey)?.value));
        }
        return undefined;
    }
    /**
     * Decodes a single pubkey from ptotobuf `Any` into `Pubkey`.
     * @param {Any} pubkey
     * @returns {Pubkey} the Amino JSON representation (type/value wrapper) of the pubkey
     */
    decodePubkey(pubkey) {
        if (!pubkey || !pubkey.value) {
            return null;
        }
        const { key } = ethSecp256k1_1.PubKey.decode(pubkey.value);
        return this.encodeEthSecp256k1Pubkey(key);
    }
    /** @inheritdoc */
    getEncodedPubkey(pubkey) {
        return this.encodePubkey(this.encodeEthSecp256k1Pubkey((0, encoding_1.fromHex)(pubkey)));
    }
    /**
     * Takes a pubkey in the Amino JSON object style (type/value wrapper)
     * and convertes it into a protobuf `Any`.
     * @param {Pubkey} pubkey Amino JSON object style pubkey
     * @returns {Any} pubkey encoded as protobuf `Any`
     */
    encodePubkey(pubkey) {
        const pubkeyProto = ethSecp256k1_1.PubKey.fromPartial({
            key: (0, encoding_1.fromBase64)(pubkey.value),
        });
        return any_1.Any.fromPartial({
            typeUrl: abstract_cosmos_1.PubKeyTypeUrl.ethSecp256k1,
            value: Uint8Array.from(ethSecp256k1_1.PubKey.encode(pubkeyProto).finish()),
        });
    }
    /**
     * Takes a public key as raw bytes and returns the Amino JSON
     * representation of it (type/value wrapper).
     * @param {Uint8Array} pubkey public key as raw bytes
     * @returns {Any} Amino JSON style pubkey
     */
    encodeEthSecp256k1Pubkey(pubkey) {
        if (pubkey.length !== 33 || (pubkey[0] !== 0x02 && pubkey[0] !== 0x03)) {
            throw new Error('Public key must be compressed ethSecp256k1, i.e. 33 bytes starting with 0x02 or 0x03');
        }
        return {
            type: abstract_cosmos_1.PubKeyType.ethSecp256k1,
            value: (0, encoding_1.toBase64)(pubkey),
        };
    }
    /** @inheritdoc */
    getHashFunction() {
        return (0, keccak_1.default)('keccak256');
    }
}
exports.IslmUtils = IslmUtils;
const islmUtils = new IslmUtils();
exports.default = islmUtils;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDhDQUEwRDtBQUUxRCxnRUFBcUM7QUFFckMsNERBQWdGO0FBQ2hGLHVEQUF5QztBQUV6QywrQ0FBd0U7QUFFeEUsMERBQXVEO0FBQ3ZELHFFQUE0RDtBQUU1RCxvREFBNEI7QUFFNUIsTUFBYSxTQUFVLFNBQVEsNkJBQVc7SUFDeEMsa0JBQWtCO0lBQ2xCLGNBQWMsQ0FBQyxPQUFlO1FBQzVCLE9BQU8sSUFBSSxDQUFDLGtDQUFrQyxDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsbUJBQW1CLENBQUMsQ0FBQztJQUN6RixDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLHVCQUF1QixDQUFDLE9BQWU7UUFDckMsT0FBTyxTQUFTLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsY0FBYyxDQUFDLE1BQVk7UUFDekIsTUFBTSxTQUFTLEdBQUcsSUFBQSxzQkFBUyxFQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMzQyxJQUFJLFNBQVMsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3JDLE1BQU0sSUFBSSxrQ0FBdUIsQ0FBQyxzREFBc0QsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDNUcsQ0FBQztRQUNELElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxLQUFLLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ25FLE1BQU0sSUFBSSxrQ0FBdUIsQ0FBQyxxREFBcUQsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDMUcsQ0FBQztJQUNILENBQUM7SUFFRCxrQkFBa0I7SUFDbEIseUJBQXlCLENBQUMsU0FBdUI7UUFDL0MsTUFBTSxtQkFBbUIsR0FBRyxTQUFTLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUM7UUFDakYsSUFBSSxtQkFBbUIsRUFBRSxDQUFDO1lBQ3hCLE9BQU8sSUFBQSxnQkFBSyxFQUFDLElBQUEscUJBQVUsRUFBQyxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUNwRyxDQUFDO1FBQ0QsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxZQUFZLENBQUMsTUFBbUI7UUFDOUIsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUM3QixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcscUJBQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzVDLE9BQU8sSUFBSSxDQUFDLHdCQUF3QixDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsZ0JBQWdCLENBQUMsTUFBYztRQUM3QixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLHdCQUF3QixDQUFDLElBQUEsa0JBQU8sRUFBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0UsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsWUFBWSxDQUFDLE1BQWM7UUFDekIsTUFBTSxXQUFXLEdBQUcscUJBQU0sQ0FBQyxXQUFXLENBQUM7WUFDckMsR0FBRyxFQUFFLElBQUEscUJBQVUsRUFBQyxNQUFNLENBQUMsS0FBSyxDQUFDO1NBQzlCLENBQUMsQ0FBQztRQUNILE9BQU8sU0FBRyxDQUFDLFdBQVcsQ0FBQztZQUNyQixPQUFPLEVBQUUsK0JBQWEsQ0FBQyxZQUFZO1lBQ25DLEtBQUssRUFBRSxVQUFVLENBQUMsSUFBSSxDQUFDLHFCQUFNLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQzVELENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILHdCQUF3QixDQUFDLE1BQWtCO1FBQ3pDLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ3ZFLE1BQU0sSUFBSSxLQUFLLENBQUMsc0ZBQXNGLENBQUMsQ0FBQztRQUMxRyxDQUFDO1FBQ0QsT0FBTztZQUNMLElBQUksRUFBRSw0QkFBVSxDQUFDLFlBQVk7WUFDN0IsS0FBSyxFQUFFLElBQUEsbUJBQVEsRUFBQyxNQUFNLENBQUM7U0FDeEIsQ0FBQztJQUNKLENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsZUFBZTtRQUNiLE9BQU8sSUFBQSxnQkFBTSxFQUFDLFdBQVcsQ0FBUyxDQUFDO0lBQ3JDLENBQUM7Q0FDRjtBQXJGRCw4QkFxRkM7QUFFRCxNQUFNLFNBQVMsR0FBZ0IsSUFBSSxTQUFTLEVBQUUsQ0FBQztBQUUvQyxrQkFBZSxTQUFTLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvciB9IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBDb2luIH0gZnJvbSAnQGNvc21qcy9zdGFyZ2F0ZSc7XG5pbXBvcnQgQmlnTnVtYmVyIGZyb20gJ2JpZ251bWJlci5qcyc7XG5cbmltcG9ydCB7IENvc21vc1V0aWxzLCBQdWJLZXlUeXBlLCBQdWJLZXlUeXBlVXJsIH0gZnJvbSAnQGJpdGdvL2Fic3RyYWN0LWNvc21vcyc7XG5pbXBvcnQgKiBhcyBjb25zdGFudHMgZnJvbSAnLi9jb25zdGFudHMnO1xuaW1wb3J0IHsgRGVjb2RlZFR4UmF3IH0gZnJvbSAnQGNvc21qcy9wcm90by1zaWduaW5nJztcbmltcG9ydCB7IGZyb21CYXNlNjQsIHRvQmFzZTY0LCB0b0hleCwgZnJvbUhleCB9IGZyb20gJ0Bjb3NtanMvZW5jb2RpbmcnO1xuaW1wb3J0IHsgUHVia2V5IH0gZnJvbSAnQGNvc21qcy9hbWlubyc7XG5pbXBvcnQgeyBBbnkgfSBmcm9tICdjb3NtanMtdHlwZXMvZ29vZ2xlL3Byb3RvYnVmL2FueSc7XG5pbXBvcnQgeyBQdWJLZXkgfSBmcm9tICcuLi8uLi9yZXNvdXJjZXMvdHlwZXMvZXRoU2VjcDI1NmsxJztcbmltcG9ydCB7IEhhc2ggfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IEtlY2NhayBmcm9tICdrZWNjYWsnO1xuXG5leHBvcnQgY2xhc3MgSXNsbVV0aWxzIGV4dGVuZHMgQ29zbW9zVXRpbHMge1xuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgaXNWYWxpZEFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZENvc21vc0xpa2VBZGRyZXNzV2l0aE1lbW9JZChhZGRyZXNzLCBjb25zdGFudHMuYWNjb3VudEFkZHJlc3NSZWdleCk7XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgaXNWYWxpZFZhbGlkYXRvckFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGNvbnN0YW50cy52YWxpZGF0b3JBZGRyZXNzUmVnZXgudGVzdChhZGRyZXNzKTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICB2YWxpZGF0ZUFtb3VudChhbW91bnQ6IENvaW4pOiB2b2lkIHtcbiAgICBjb25zdCBhbW91bnRCaWcgPSBCaWdOdW1iZXIoYW1vdW50LmFtb3VudCk7XG4gICAgaWYgKGFtb3VudEJpZy5pc0xlc3NUaGFuT3JFcXVhbFRvKDApKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ3RyYW5zYWN0aW9uQnVpbGRlcjogdmFsaWRhdGVBbW91bnQ6IEludmFsaWQgYW1vdW50OiAnICsgYW1vdW50LmFtb3VudCk7XG4gICAgfVxuICAgIGlmICghY29uc3RhbnRzLnZhbGlkRGVub21zLmZpbmQoKGRlbm9tKSA9PiBkZW5vbSA9PT0gYW1vdW50LmRlbm9tKSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCd0cmFuc2FjdGlvbkJ1aWxkZXI6IHZhbGlkYXRlQW1vdW50OiBJbnZhbGlkIGRlbm9tOiAnICsgYW1vdW50LmRlbm9tKTtcbiAgICB9XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgZ2V0UHVibGljS2V5RnJvbURlY29kZWRUeChkZWNvZGVkVHg6IERlY29kZWRUeFJhdyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgcHVibGljS2V5VUludDhBcnJheSA9IGRlY29kZWRUeC5hdXRoSW5mby5zaWduZXJJbmZvcz8uWzBdLnB1YmxpY0tleT8udmFsdWU7XG4gICAgaWYgKHB1YmxpY0tleVVJbnQ4QXJyYXkpIHtcbiAgICAgIHJldHVybiB0b0hleChmcm9tQmFzZTY0KHRoaXMuZGVjb2RlUHVia2V5KGRlY29kZWRUeC5hdXRoSW5mby5zaWduZXJJbmZvcz8uWzBdLnB1YmxpY0tleSk/LnZhbHVlKSk7XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogRGVjb2RlcyBhIHNpbmdsZSBwdWJrZXkgZnJvbSBwdG90b2J1ZiBgQW55YCBpbnRvIGBQdWJrZXlgLlxuICAgKiBAcGFyYW0ge0FueX0gcHVia2V5XG4gICAqIEByZXR1cm5zIHtQdWJrZXl9IHRoZSBBbWlubyBKU09OIHJlcHJlc2VudGF0aW9uICh0eXBlL3ZhbHVlIHdyYXBwZXIpIG9mIHRoZSBwdWJrZXlcbiAgICovXG4gIGRlY29kZVB1YmtleShwdWJrZXk/OiBBbnkgfCBudWxsKTogUHVia2V5IHwgbnVsbCB7XG4gICAgaWYgKCFwdWJrZXkgfHwgIXB1YmtleS52YWx1ZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGNvbnN0IHsga2V5IH0gPSBQdWJLZXkuZGVjb2RlKHB1YmtleS52YWx1ZSk7XG4gICAgcmV0dXJuIHRoaXMuZW5jb2RlRXRoU2VjcDI1NmsxUHVia2V5KGtleSk7XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgZ2V0RW5jb2RlZFB1YmtleShwdWJrZXk6IHN0cmluZyk6IEFueSB7XG4gICAgcmV0dXJuIHRoaXMuZW5jb2RlUHVia2V5KHRoaXMuZW5jb2RlRXRoU2VjcDI1NmsxUHVia2V5KGZyb21IZXgocHVia2V5KSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRha2VzIGEgcHVia2V5IGluIHRoZSBBbWlubyBKU09OIG9iamVjdCBzdHlsZSAodHlwZS92YWx1ZSB3cmFwcGVyKVxuICAgKiBhbmQgY29udmVydGVzIGl0IGludG8gYSBwcm90b2J1ZiBgQW55YC5cbiAgICogQHBhcmFtIHtQdWJrZXl9IHB1YmtleSBBbWlubyBKU09OIG9iamVjdCBzdHlsZSBwdWJrZXlcbiAgICogQHJldHVybnMge0FueX0gcHVia2V5IGVuY29kZWQgYXMgcHJvdG9idWYgYEFueWBcbiAgICovXG4gIGVuY29kZVB1YmtleShwdWJrZXk6IFB1YmtleSk6IEFueSB7XG4gICAgY29uc3QgcHVia2V5UHJvdG8gPSBQdWJLZXkuZnJvbVBhcnRpYWwoe1xuICAgICAga2V5OiBmcm9tQmFzZTY0KHB1YmtleS52YWx1ZSksXG4gICAgfSk7XG4gICAgcmV0dXJuIEFueS5mcm9tUGFydGlhbCh7XG4gICAgICB0eXBlVXJsOiBQdWJLZXlUeXBlVXJsLmV0aFNlY3AyNTZrMSxcbiAgICAgIHZhbHVlOiBVaW50OEFycmF5LmZyb20oUHViS2V5LmVuY29kZShwdWJrZXlQcm90bykuZmluaXNoKCkpLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRha2VzIGEgcHVibGljIGtleSBhcyByYXcgYnl0ZXMgYW5kIHJldHVybnMgdGhlIEFtaW5vIEpTT05cbiAgICogcmVwcmVzZW50YXRpb24gb2YgaXQgKHR5cGUvdmFsdWUgd3JhcHBlcikuXG4gICAqIEBwYXJhbSB7VWludDhBcnJheX0gcHVia2V5IHB1YmxpYyBrZXkgYXMgcmF3IGJ5dGVzXG4gICAqIEByZXR1cm5zIHtBbnl9IEFtaW5vIEpTT04gc3R5bGUgcHVia2V5XG4gICAqL1xuICBlbmNvZGVFdGhTZWNwMjU2azFQdWJrZXkocHVia2V5OiBVaW50OEFycmF5KTogUHVia2V5IHtcbiAgICBpZiAocHVia2V5Lmxlbmd0aCAhPT0gMzMgfHwgKHB1YmtleVswXSAhPT0gMHgwMiAmJiBwdWJrZXlbMF0gIT09IDB4MDMpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1B1YmxpYyBrZXkgbXVzdCBiZSBjb21wcmVzc2VkIGV0aFNlY3AyNTZrMSwgaS5lLiAzMyBieXRlcyBzdGFydGluZyB3aXRoIDB4MDIgb3IgMHgwMycpO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogUHViS2V5VHlwZS5ldGhTZWNwMjU2azEsXG4gICAgICB2YWx1ZTogdG9CYXNlNjQocHVia2V5KSxcbiAgICB9O1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIGdldEhhc2hGdW5jdGlvbigpOiBIYXNoIHtcbiAgICByZXR1cm4gS2VjY2FrKCdrZWNjYWsyNTYnKSBhcyBIYXNoO1xuICB9XG59XG5cbmNvbnN0IGlzbG1VdGlsczogQ29zbW9zVXRpbHMgPSBuZXcgSXNsbVV0aWxzKCk7XG5cbmV4cG9ydCBkZWZhdWx0IGlzbG1VdGlscztcbiJdfQ==

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


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