PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@bitgo/sdk-coin-xrp/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 });
const sdk_core_1 = require("@bitgo/sdk-core");
const statics_1 = require("@bitgo/statics");
const querystring = __importStar(require("querystring"));
const rippleKeypairs = __importStar(require("ripple-keypairs"));
const url = __importStar(require("url"));
const xrpl = __importStar(require("xrpl"));
const constants_1 = require("./constants");
const keyPair_1 = require("./keyPair");
const assert_1 = __importDefault(require("assert"));
class Utils {
isValidAddress(address) {
try {
const addressDetails = this.getAddressDetails(address);
return address === this.normalizeAddress(addressDetails);
}
catch (e) {
return false;
}
}
isValidTransactionId(txId) {
return this.isValidHex(txId);
}
isValidPublicKey(key) {
try {
new keyPair_1.KeyPair({ pub: key });
return true;
}
catch {
return false;
}
}
isValidPrivateKey(key) {
try {
new keyPair_1.KeyPair({ prv: key });
return true;
}
catch {
return false;
}
}
isValidSignature(signature) {
return this.isValidHex(signature);
}
isValidBlockId(hash) {
return this.isValidHex(hash);
}
isValidHex(hex) {
return /^([a-fA-F0-9])+$/.test(hex);
}
/**
* Parse an address string into address and destination tag
*/
getAddressDetails(address) {
const destinationDetails = url.parse(address);
const destinationAddress = destinationDetails.pathname;
if (!destinationAddress || !xrpl.isValidClassicAddress(destinationAddress)) {
throw new sdk_core_1.InvalidAddressError(`destination address "${destinationAddress}" is not valid`);
}
// there are no other properties like destination tags
if (destinationDetails.pathname === address) {
return {
address: address,
destinationTag: undefined,
};
}
if (!destinationDetails.query) {
throw new sdk_core_1.InvalidAddressError('no query params present');
}
const queryDetails = querystring.parse(destinationDetails.query);
if (!queryDetails.dt) {
// if there are more properties, the query details need to contain the destination tag property.
throw new sdk_core_1.InvalidAddressError('destination tag missing');
}
if (Array.isArray(queryDetails.dt)) {
// if queryDetails.dt is an array, that means dt was given multiple times, which is not valid
throw new sdk_core_1.InvalidAddressError(`destination tag can appear at most once, but ${queryDetails.dt.length} destination tags were found`);
}
const parsedTag = parseInt(queryDetails.dt, 10);
if (!Number.isSafeInteger(parsedTag)) {
throw new sdk_core_1.InvalidAddressError('invalid destination tag');
}
if (parsedTag > 0xffffffff || parsedTag < 0) {
throw new sdk_core_1.InvalidAddressError('destination tag out of range');
}
return {
address: destinationAddress,
destinationTag: parsedTag,
};
}
/**
* Construct a full, normalized address from an address and destination tag
*/
normalizeAddress({ address, destinationTag }) {
if (typeof address !== 'string') {
throw new sdk_core_1.InvalidAddressError('invalid address, expected string');
}
if (typeof destinationTag === 'undefined' || destinationTag === null) {
return address;
}
if (!Number.isInteger(destinationTag)) {
throw new sdk_core_1.InvalidAddressError('invalid destination tag, expected integer');
}
if (destinationTag > 0xffffffff || destinationTag < 0) {
throw new sdk_core_1.InvalidAddressError('destination tag out of range');
}
return `${address}?dt=${destinationTag}`;
}
/**
* @param message hex encoded string
* @param privateKey
* return hex encoded signature string, throws if any of the inputs are invalid
*/
signString(message, privateKey) {
if (!this.isValidHex(message)) {
throw new sdk_core_1.UtilsError('message must be a hex encoded string');
}
if (!this.isValidPrivateKey(privateKey)) {
throw new sdk_core_1.UtilsError('invalid private key');
}
return rippleKeypairs.sign(message, privateKey);
}
/**
* @param message hex encoded string
* @param signature hex encooded signature string
* @param publicKey
* return boolean, throws if any of the inputs are invalid
*/
verifySignature(message, signature, publicKey) {
if (!this.isValidHex(message)) {
throw new sdk_core_1.UtilsError('message must be a hex encoded string');
}
if (!this.isValidSignature(signature)) {
throw new sdk_core_1.UtilsError('invalid signature');
}
if (!this.isValidPublicKey(publicKey)) {
throw new sdk_core_1.UtilsError('invalid public key');
}
try {
return rippleKeypairs.verify(message, signature, publicKey);
}
catch (e) {
return false;
}
}
/**
* Check the raw transaction has a valid format in the blockchain context, throw otherwise.
*
* @param {string} rawTransaction - Transaction in hex string format
*/
validateRawTransaction(rawTransaction) {
if (!rawTransaction) {
throw new sdk_core_1.InvalidTransactionError('Invalid raw transaction: Undefined');
}
if (!this.isValidHex(rawTransaction)) {
throw new sdk_core_1.InvalidTransactionError('Invalid raw transaction: Hex string expected');
}
if (!this.isValidRawTransaction(rawTransaction)) {
throw new sdk_core_1.InvalidTransactionError('Invalid raw transaction');
}
}
/**
* Checks if raw transaction can be deserialized
*
* @param {string} rawTransaction - transaction in base64 string format
* @returns {boolean} - the validation result
*/
isValidRawTransaction(rawTransaction) {
try {
const jsonTx = xrpl.decode(rawTransaction);
xrpl.validate(jsonTx);
return true;
}
catch (e) {
return false;
}
}
validateAccountSetFlag(setFlag) {
if (typeof setFlag !== 'number') {
throw new sdk_core_1.UtilsError(`setFlag ${setFlag} is not valid`);
}
if (!constants_1.VALID_ACCOUNT_SET_FLAGS.includes(setFlag)) {
throw new sdk_core_1.UtilsError(`setFlag ${setFlag} is not a valid account set flag`);
}
}
validateSigner(signer) {
if (!signer.address) {
throw new sdk_core_1.UtilsError('signer must have an address');
}
if (!this.isValidAddress(signer.address)) {
throw new sdk_core_1.UtilsError(`signer address ${signer.address} is invalid`);
}
if (typeof signer.weight !== 'number' || signer.weight < 0) {
throw new sdk_core_1.UtilsError(`signer weight ${signer.weight} is not valid`);
}
}
/**
* Determines if the provided `amount` is for a token payment
*/
isIssuedCurrencyAmount(amount) {
return (!!amount &&
typeof amount === 'object' &&
typeof amount.currency === 'string' &&
typeof amount.issuer === 'string' &&
typeof amount.value === 'string');
}
/**
* Get the associated XRP Currency details from token name. Throws an error if token is unsupported
* @param {string} tokenName - The token name
*/
getXrpCurrencyFromTokenName(tokenName) {
if (!statics_1.coins.has(tokenName)) {
throw new sdk_core_1.UnsupportedTokenError(`${tokenName} is not supported`);
}
const token = statics_1.coins.get(tokenName);
if (!token.isToken || !(token instanceof statics_1.XrpCoin)) {
throw new sdk_core_1.UnsupportedTokenError(`${tokenName} is not an XRP token`);
}
return {
currency: token.currencyCode,
issuer: token.issuerAddress,
};
}
/**
* Decodes a serialized XRPL transaction.
*
* @param {string} txHex - The serialized transaction in hex.
* @returns {Object} - Decoded transaction object.
* @throws {Error} - If decoding fails or input is invalid.
*/
decodeTransaction(txHex) {
if (typeof txHex !== 'string' || txHex.trim() === '') {
throw new Error('Invalid transaction hex. Expected a non-empty string.');
}
try {
return xrpl.decode(txHex);
}
catch (error) {
throw new Error(`Failed to decode transaction: ${error.message}`);
}
}
/**
* Get the statics coin object matching a given Xrp token issuer address and currency code if it exists
*
* @param issuerAddress The token issuer address to match against
* @param currencyCode The token currency code to match against
* @returns statics BaseCoin object for the matching token
*/
getXrpToken(issuerAddress, currencyCode) {
const tokens = statics_1.coins.filter((coin) => {
if (coin instanceof statics_1.XrpCoin) {
return coin.issuerAddress === issuerAddress && coin.currencyCode === currencyCode;
}
return false;
});
const tokensArray = tokens.map((token) => token);
if (tokensArray.length >= 1) {
// there should never be two tokens with the same issuer address and currency code, so we assert that here
(0, assert_1.default)(tokensArray.length === 1);
return tokensArray[0];
}
return undefined;
}
}
const utils = new Utils();
exports.default = utils;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsOENBTXlCO0FBQ3pCLDRDQUEwRDtBQUMxRCx5REFBMkM7QUFDM0MsZ0VBQWtEO0FBQ2xELHlDQUEyQjtBQUMzQiwyQ0FBNkI7QUFFN0IsMkNBQXNEO0FBRXRELHVDQUFrRDtBQUNsRCxvREFBNEI7QUFFNUIsTUFBTSxLQUFLO0lBQ1QsY0FBYyxDQUFDLE9BQWU7UUFDNUIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3ZELE9BQU8sT0FBTyxLQUFLLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUMzRCxDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNYLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztJQUNILENBQUM7SUFFRCxvQkFBb0IsQ0FBQyxJQUFZO1FBQy9CLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBRUQsZ0JBQWdCLENBQUMsR0FBVztRQUMxQixJQUFJLENBQUM7WUFDSCxJQUFJLGlCQUFVLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztZQUM3QixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7SUFDSCxDQUFDO0lBRUQsaUJBQWlCLENBQUMsR0FBVztRQUMzQixJQUFJLENBQUM7WUFDSCxJQUFJLGlCQUFVLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztZQUM3QixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFBQyxNQUFN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QztZQUNwRixDQUFDO1lBQ0QsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDLENBQUMsQ0FBQztRQUNILE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pELElBQUksV0FBVyxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUM1QiwwR0FBMEc7WUFDMUcsSUFBQSxnQkFBTSxFQUFDLFdBQVcsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDakMsT0FBTyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEIsQ0FBQztRQUNELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7Q0FDRjtBQUVELE1BQU0sS0FBSyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7QUFFMUIsa0JBQWUsS0FBSyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQmFzZVV0aWxzLFxuICBJbnZhbGlkQWRkcmVzc0Vycm9yLFxuICBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcixcbiAgVW5zdXBwb3J0ZWRUb2tlbkVycm9yLFxuICBVdGlsc0Vycm9yLFxufSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuaW1wb3J0IHsgQmFzZUNvaW4sIGNvaW5zLCBYcnBDb2luIH0gZnJvbSAnQGJpdGdvL3N0YXRpY3MnO1xuaW1wb3J0ICogYXMgcXVlcnlzdHJpbmcgZnJvbSAncXVlcnlzdHJpbmcnO1xuaW1wb3J0ICogYXMgcmlwcGxlS2V5cGFpcnMgZnJvbSAncmlwcGxlLWtleXBhaXJzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuaW1wb3J0ICogYXMgeHJwbCBmcm9tICd4cnBsJztcbmltcG9ydCB7IEFtb3VudCwgSXNzdWVkQ3VycmVuY3lBbW91bnQgfSBmcm9tICd4cnBsJztcbmltcG9ydCB7IFZBTElEX0FDQ09VTlRfU0VUX0ZMQUdTIH0gZnJvbSAnLi9jb25zdGFudHMnO1xuaW1wb3J0IHsgQWRkcmVzcywgU2lnbmVyRGV0YWlscyB9IGZyb20gJy4vaWZhY2UnO1xuaW1wb3J0IHsgS2V5UGFpciBhcyBYcnBLZXlQYWlyIH0gZnJvbSAnLi9rZXlQYWlyJztcbmltcG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcblxuY2xhc3MgVXRpbHMgaW1wbGVtZW50cyBCYXNlVXRpbHMge1xuICBpc1ZhbGlkQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYWRkcmVzc0RldGFpbHMgPSB0aGlzLmdldEFkZHJlc3NEZXRhaWxzKGFkZHJlc3MpO1xuICAgICAgcmV0dXJuIGFkZHJlc3MgPT09IHRoaXMubm9ybWFsaXplQWRkcmVzcyhhZGRyZXNzRGV0YWlscyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIGlzVmFsaWRUcmFuc2FjdGlvbklkKHR4SWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWRIZXgodHhJZCk7XG4gIH1cblxuICBpc1ZhbGlkUHVibGljS2V5KGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIG5ldyBYcnBLZXlQYWlyKHsgcHViOiBrZXkgfSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBpc1ZhbGlkUHJpdmF0ZUtleShrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICBuZXcgWHJwS2V5UGFpcih7IHBydjoga2V5IH0pO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgaXNWYWxpZFNpZ25hdHVyZShzaWduYXR1cmU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWRIZXgoc2lnbmF0dXJlKTtcbiAgfVxuXG4gIGlzVmFsaWRCbG9ja0lkKGhhc2g6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWRIZXgoaGFzaCk7XG4gIH1cblxuICBpc1ZhbGlkSGV4KGhleDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIC9eKFthLWZBLUYwLTldKSskLy50ZXN0KGhleCk7XG4gIH1cblxuICAvKipcbiAgICogUGFyc2UgYW4gYWRkcmVzcyBzdHJpbmcgaW50byBhZGRyZXNzIGFuZCBkZXN0aW5hdGlvbiB0YWdcbiAgICovXG4gIHB1YmxpYyBnZXRBZGRyZXNzRGV0YWlscyhhZGRyZXNzOiBzdHJpbmcpOiBBZGRyZXNzIHtcbiAgICBjb25zdCBkZXN0aW5hdGlvbkRldGFpbHMgPSB1cmwucGFyc2UoYWRkcmVzcyk7XG4gICAgY29uc3QgZGVzdGluYXRpb25BZGRyZXNzID0gZGVzdGluYXRpb25EZXRhaWxzLnBhdGhuYW1lO1xuICAgIGlmICghZGVzdGluYXRpb25BZGRyZXNzIHx8ICF4cnBsLmlzVmFsaWRDbGFzc2ljQWRkcmVzcyhkZXN0aW5hdGlvbkFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFkZHJlc3NFcnJvcihgZGVzdGluYXRpb24gYWRkcmVzcyBcIiR7ZGVzdGluYXRpb25BZGRyZXNzfVwiIGlzIG5vdCB2YWxpZGApO1xuICAgIH1cbiAgICAvLyB0aGVyZSBhcmUgbm8gb3RoZXIgcHJvcGVydGllcyBsaWtlIGRlc3RpbmF0aW9uIHRhZ3NcbiAgICBpZiAoZGVzdGluYXRpb25EZXRhaWxzLnBhdGhuYW1lID09PSBhZGRyZXNzKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBhZGRyZXNzOiBhZGRyZXNzLFxuICAgICAgICBkZXN0aW5hdGlvblRhZzogdW5kZWZpbmVkLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoIWRlc3RpbmF0aW9uRGV0YWlscy5xdWVyeSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRBZGRyZXNzRXJyb3IoJ25vIHF1ZXJ5IHBhcmFtcyBwcmVzZW50Jyk7XG4gICAgfVxuXG4gICAgY29uc3QgcXVlcnlEZXRhaWxzID0gcXVlcnlzdHJpbmcucGFyc2UoZGVzdGluYXRpb25EZXRhaWxzLnF1ZXJ5KTtcbiAgICBpZiAoIXF1ZXJ5RGV0YWlscy5kdCkge1xuICAgICAgLy8gaWYgdGhlcmUgYXJlIG1vcmUgcHJvcGVydGllcywgdGhlIHF1ZXJ5IGRldGFpbHMgbmVlZCB0byBjb250YWluIHRoZSBkZXN0aW5hdGlvbiB0YWcgcHJvcGVydHkuXG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFkZHJlc3NFcnJvcignZGVzdGluYXRpb24gdGFnIG1pc3NpbmcnKTtcbiAgICB9XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShxdWVyeURldGFpbHMuZHQpKSB7XG4gICAgICAvLyBpZiBxdWVyeURldGFpbHMuZHQgaXMgYW4gYXJyYXksIHRoYXQgbWVhbnMgZHQgd2FzIGdpdmVuIG11bHRpcGxlIHRpbWVzLCB3aGljaCBpcyBub3QgdmFsaWRcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQWRkcmVzc0Vycm9yKFxuICAgICAgICBgZGVzdGluYXRpb24gdGFnIGNhbiBhcHBlYXIgYXQgbW9zdCBvbmNlLCBidXQgJHtxdWVyeURldGFpbHMuZHQubGVuZ3RofSBkZXN0aW5hdGlvbiB0YWdzIHdlcmUgZm91bmRgXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcnNlZFRhZyA9IHBhcnNlSW50KHF1ZXJ5RGV0YWlscy5kdCwgMTApO1xuICAgIGlmICghTnVtYmVyLmlzU2FmZUludGVnZXIocGFyc2VkVGFnKSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRBZGRyZXNzRXJyb3IoJ2ludmFsaWQgZGVzdGluYXRpb24gdGFnJyk7XG4gICAgfVxuXG4gICAgaWYgKHBhcnNlZFRhZyA+IDB4ZmZmZmZmZmYgfHwgcGFyc2VkVGFnIDwgMCkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRBZGRyZXNzRXJyb3IoJ2Rlc3RpbmF0aW9uIHRhZyBvdXQgb2YgcmFuZ2UnKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgYWRkcmVzczogZGVzdGluYXRpb25BZGRyZXNzLFxuICAgICAgZGVzdGluYXRpb25UYWc6IHBhcnNlZFRhZyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIGZ1bGwsIG5vcm1hbGl6ZWQgYWRkcmVzcyBmcm9tIGFuIGFkZHJlc3MgYW5kIGRlc3RpbmF0aW9uIHRhZ1xuICAgKi9cbiAgcHVibGljIG5vcm1hbGl6ZUFkZHJlc3MoeyBhZGRyZXNzLCBkZXN0aW5hdGlvblRhZyB9OiBBZGRyZXNzKTogc3RyaW5nIHtcbiAgICBpZiAodHlwZW9mIGFkZHJlc3MgIT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFkZHJlc3NFcnJvcignaW52YWxpZCBhZGRyZXNzLCBleHBlY3RlZCBzdHJpbmcnKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBkZXN0aW5hdGlvblRhZyA9PT0gJ3VuZGVmaW5lZCcgfHwgZGVzdGluYXRpb25UYWcgPT09IG51bGwpIHtcbiAgICAgIHJldHVybiBhZGRyZXNzO1xuICAgIH1cbiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoZGVzdGluYXRpb25UYWcpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFkZHJlc3NFcnJvcignaW52YWxpZCBkZXN0aW5hdGlvbiB0YWcsIGV4cGVjdGVkIGludGVnZXInKTtcbiAgICB9XG4gICAgaWYgKGRlc3RpbmF0aW9uVGFnID4gMHhmZmZmZmZmZiB8fCBkZXN0aW5hdGlvblRhZyA8IDApIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQWRkcmVzc0Vycm9yKCdkZXN0aW5hdGlvbiB0YWcgb3V0IG9mIHJhbmdlJyk7XG4gICAgfVxuICAgIHJldHVybiBgJHthZGRyZXNzfT9kdD0ke2Rlc3RpbmF0aW9uVGFnfWA7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIG1lc3NhZ2UgaGV4IGVuY29kZWQgc3RyaW5nXG4gICAqIEBwYXJhbSBwcml2YXRlS2V5XG4gICAqIHJldHVybiBoZXggZW5jb2RlZCBzaWduYXR1cmUgc3RyaW5nLCB0aHJvd3MgaWYgYW55IG9mIHRoZSBpbnB1dHMgYXJlIGludmFsaWRcbiAgICovXG4gIHB1YmxpYyBzaWduU3RyaW5nKG1lc3NhZ2U6IHN0cmluZywgcHJpdmF0ZUtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZEhleChtZXNzYWdlKSkge1xuICAgICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoJ21lc3NhZ2UgbXVzdCBiZSBhIGhleCBlbmNvZGVkIHN0cmluZycpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuaXNWYWxpZFByaXZhdGVLZXkocHJpdmF0ZUtleSkpIHtcbiAgICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdpbnZhbGlkIHByaXZhdGUga2V5Jyk7XG4gICAgfVxuICAgIHJldHVybiByaXBwbGVLZXlwYWlycy5zaWduKG1lc3NhZ2UsIHByaXZhdGVLZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSBtZXNzYWdlIGhleCBlbmNvZGVkIHN0cmluZ1xuICAgKiBAcGFyYW0gc2lnbmF0dXJlIGhleCBlbmNvb2RlZCBzaWduYXR1cmUgc3RyaW5nXG4gICAqIEBwYXJhbSBwdWJsaWNLZXlcbiAgICogcmV0dXJuIGJvb2xlYW4sIHRocm93cyBpZiBhbnkgb2YgdGhlIGlucHV0cyBhcmUgaW52YWxpZFxuICAgKi9cbiAgcHVibGljIHZlcmlmeVNpZ25hdHVyZShtZXNzYWdlOiBzdHJpbmcsIHNpZ25hdHVyZTogc3RyaW5nLCBwdWJsaWNLZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkSGV4KG1lc3NhZ2UpKSB7XG4gICAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignbWVzc2FnZSBtdXN0IGJlIGEgaGV4IGVuY29kZWQgc3RyaW5nJyk7XG4gICAgfVxuICAgIGlmICghdGhpcy5pc1ZhbGlkU2lnbmF0dXJlKHNpZ25hdHVyZSkpIHtcbiAgICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdpbnZhbGlkIHNpZ25hdHVyZScpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuaXNWYWxpZFB1YmxpY0tleShwdWJsaWNLZXkpKSB7XG4gICAgICB0aHJvdyBuZXcgVXRpbHNFcnJvcignaW52YWxpZCBwdWJsaWMga2V5Jyk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICByZXR1cm4gcmlwcGxlS2V5cGFpcnMudmVyaWZ5KG1lc3NhZ2UsIHNpZ25hdHVyZSwgcHVibGljS2V5KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIHRoZSByYXcgdHJhbnNhY3Rpb24gaGFzIGEgdmFsaWQgZm9ybWF0IGluIHRoZSBibG9ja2NoYWluIGNvbnRleHQsIHRocm93IG90aGVyd2lzZS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJhd1RyYW5zYWN0aW9uIC0gVHJhbnNhY3Rpb24gaW4gaGV4IHN0cmluZyBmb3JtYXRcbiAgICovXG4gIHB1YmxpYyB2YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKHJhd1RyYW5zYWN0aW9uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIXJhd1RyYW5zYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgcmF3IHRyYW5zYWN0aW9uOiBVbmRlZmluZWQnKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLmlzVmFsaWRIZXgocmF3VHJhbnNhY3Rpb24pKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgcmF3IHRyYW5zYWN0aW9uOiBIZXggc3RyaW5nIGV4cGVjdGVkJyk7XG4gICAgfVxuICAgIGlmICghdGhpcy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHJhbnNhY3Rpb24pKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgcmF3IHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiByYXcgdHJhbnNhY3Rpb24gY2FuIGJlIGRlc2VyaWFsaXplZFxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcmF3VHJhbnNhY3Rpb24gLSB0cmFuc2FjdGlvbiBpbiBiYXNlNjQgc3RyaW5nIGZvcm1hdFxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB0aGUgdmFsaWRhdGlvbiByZXN1bHRcbiAgICovXG4gIHB1YmxpYyBpc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHJhbnNhY3Rpb246IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBqc29uVHggPSB4cnBsLmRlY29kZShyYXdUcmFuc2FjdGlvbik7XG4gICAgICB4cnBsLnZhbGlkYXRlKGpzb25UeCk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHZhbGlkYXRlQWNjb3VudFNldEZsYWcoc2V0RmxhZzogbnVtYmVyKSB7XG4gICAgaWYgKHR5cGVvZiBzZXRGbGFnICE9PSAnbnVtYmVyJykge1xuICAgICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoYHNldEZsYWcgJHtzZXRGbGFnfSBpcyBub3QgdmFsaWRgKTtcbiAgICB9XG4gICAgaWYgKCFWQUxJRF9BQ0NPVU5UX1NFVF9GTEFHUy5pbmNsdWRlcyhzZXRGbGFnKSkge1xuICAgICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoYHNldEZsYWcgJHtzZXRGbGFnfSBpcyBub3QgYSB2YWxpZCBhY2NvdW50IHNldCBmbGFnYCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHZhbGlkYXRlU2lnbmVyKHNpZ25lcjogU2lnbmVyRGV0YWlscyk6IHZvaWQge1xuICAgIGlmICghc2lnbmVyLmFkZHJlc3MpIHtcbiAgICAgIHRocm93IG5ldyBVdGlsc0Vycm9yKCdzaWduZXIgbXVzdCBoYXZlIGFuIGFkZHJlc3MnKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLmlzVmFsaWRBZGRyZXNzKHNpZ25lci5hZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoYHNpZ25lciBhZGRyZXNzICR7c2lnbmVyLmFkZHJlc3N9IGlzIGludmFsaWRgKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBzaWduZXIud2VpZ2h0ICE9PSAnbnVtYmVyJyB8fCBzaWduZXIud2VpZ2h0IDwgMCkge1xuICAgICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoYHNpZ25lciB3ZWlnaHQgJHtzaWduZXIud2VpZ2h0fSBpcyBub3QgdmFsaWRgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyBpZiB0aGUgcHJvdmlkZWQgYGFtb3VudGAgaXMgZm9yIGEgdG9rZW4gcGF5bWVudFxuICAgKi9cbiAgcHVibGljIGlzSXNzdWVkQ3VycmVuY3lBbW91bnQoYW1vdW50OiBBbW91bnQpOiBhbW91bnQgaXMgSXNzdWVkQ3VycmVuY3lBbW91bnQge1xuICAgIHJldHVybiAoXG4gICAgICAhIWFtb3VudCAmJlxuICAgICAgdHlwZW9mIGFtb3VudCA9PT0gJ29iamVjdCcgJiZcbiAgICAgIHR5cGVvZiBhbW91bnQuY3VycmVuY3kgPT09ICdzdHJpbmcnICYmXG4gICAgICB0eXBlb2YgYW1vdW50Lmlzc3VlciA9PT0gJ3N0cmluZycgJiZcbiAgICAgIHR5cGVvZiBhbW91bnQudmFsdWUgPT09ICdzdHJpbmcnXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGFzc29jaWF0ZWQgWFJQIEN1cnJlbmN5IGRldGFpbHMgZnJvbSB0b2tlbiBuYW1lLiBUaHJvd3MgYW4gZXJyb3IgaWYgdG9rZW4gaXMgdW5zdXBwb3J0ZWRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRva2VuTmFtZSAtIFRoZSB0b2tlbiBuYW1lXG4gICAqL1xuICBwdWJsaWMgZ2V0WHJwQ3VycmVuY3lGcm9tVG9rZW5OYW1lKHRva2VuTmFtZTogc3RyaW5nKTogeHJwbC5Jc3N1ZWRDdXJyZW5jeSB7XG4gICAgaWYgKCFjb2lucy5oYXModG9rZW5OYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkVG9rZW5FcnJvcihgJHt0b2tlbk5hbWV9IGlzIG5vdCBzdXBwb3J0ZWRgKTtcbiAgICB9XG4gICAgY29uc3QgdG9rZW4gPSBjb2lucy5nZXQodG9rZW5OYW1lKTtcbiAgICBpZiAoIXRva2VuLmlzVG9rZW4gfHwgISh0b2tlbiBpbnN0YW5jZW9mIFhycENvaW4pKSB7XG4gICAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRUb2tlbkVycm9yKGAke3Rva2VuTmFtZX0gaXMgbm90IGFuIFhSUCB0b2tlbmApO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgY3VycmVuY3k6IHRva2VuLmN1cnJlbmN5Q29kZSxcbiAgICAgIGlzc3VlcjogdG9rZW4uaXNzdWVyQWRkcmVzcyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIERlY29kZXMgYSBzZXJpYWxpemVkIFhSUEwgdHJhbnNhY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0eEhleCAtIFRoZSBzZXJpYWxpemVkIHRyYW5zYWN0aW9uIGluIGhleC5cbiAgICogQHJldHVybnMge09iamVjdH0gLSBEZWNvZGVkIHRyYW5zYWN0aW9uIG9iamVjdC5cbiAgICogQHRocm93cyB7RXJyb3J9IC0gSWYgZGVjb2RpbmcgZmFpbHMgb3IgaW5wdXQgaXMgaW52YWxpZC5cbiAgICovXG4gIHB1YmxpYyBkZWNvZGVUcmFuc2FjdGlvbih0eEhleDogc3RyaW5nKSB7XG4gICAgaWYgKHR5cGVvZiB0eEhleCAhPT0gJ3N0cmluZycgfHwgdHhIZXgudHJpbSgpID09PSAnJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uIGhleC4gRXhwZWN0ZWQgYSBub24tZW1wdHkgc3RyaW5nLicpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHhycGwuZGVjb2RlKHR4SGV4KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gZGVjb2RlIHRyYW5zYWN0aW9uOiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgc3RhdGljcyBjb2luIG9iamVjdCBtYXRjaGluZyBhIGdpdmVuIFhycCB0b2tlbiBpc3N1ZXIgYWRkcmVzcyBhbmQgY3VycmVuY3kgY29kZSBpZiBpdCBleGlzdHNcbiAgICpcbiAgICogQHBhcmFtIGlzc3VlckFkZHJlc3MgVGhlIHRva2VuIGlzc3VlciBhZGRyZXNzIHRvIG1hdGNoIGFnYWluc3RcbiAgICogQHBhcmFtIGN1cnJlbmN5Q29kZSBUaGUgdG9rZW4gY3VycmVuY3kgY29kZSB0byBtYXRjaCBhZ2FpbnN0XG4gICAqIEByZXR1cm5zIHN0YXRpY3MgQmFzZUNvaW4gb2JqZWN0IGZvciB0aGUgbWF0Y2hpbmcgdG9rZW5cbiAgICovXG4gIHB1YmxpYyBnZXRYcnBUb2tlbihpc3N1ZXJBZGRyZXNzLCBjdXJyZW5jeUNvZGUpOiBSZWFkb25seTxCYXNlQ29pbj4gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHRva2VucyA9IGNvaW5zLmZpbHRlcigoY29pbikgPT4ge1xuICAgICAgaWYgKGNvaW4gaW5zdGFuY2VvZiBYcnBDb2luKSB7XG4gICAgICAgIHJldHVybiBjb2luLmlzc3VlckFkZHJlc3MgPT09IGlzc3VlckFkZHJlc3MgJiYgY29pbi5jdXJyZW5jeUNvZGUgPT09IGN1cnJlbmN5Q29kZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9KTtcbiAgICBjb25zdCB0b2tlbnNBcnJheSA9IHRva2Vucy5tYXAoKHRva2VuKSA9PiB0b2tlbik7XG4gICAgaWYgKHRva2Vuc0FycmF5Lmxlbmd0aCA+PSAxKSB7XG4gICAgICAvLyB0aGVyZSBzaG91bGQgbmV2ZXIgYmUgdHdvIHRva2VucyB3aXRoIHRoZSBzYW1lIGlzc3VlciBhZGRyZXNzIGFuZCBjdXJyZW5jeSBjb2RlLCBzbyB3ZSBhc3NlcnQgdGhhdCBoZXJlXG4gICAgICBhc3NlcnQodG9rZW5zQXJyYXkubGVuZ3RoID09PSAxKTtcbiAgICAgIHJldHVybiB0b2tlbnNBcnJheVswXTtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG5jb25zdCB1dGlscyA9IG5ldyBVdGlscygpO1xuXG5leHBvcnQgZGVmYXVsdCB1dGlscztcbiJdfQ==Выполнить команду
Для локальной разработки. Не используйте в интернете!