PHP WebShell
Текущая директория: /opt/BitGoJS/modules/utxo-ord/dist/src
Просмотр файла: inscriptions.js
"use strict";
/*
Functions for dealing with inscriptions.
See https://docs.ordinals.com/inscriptions.html
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.createInscriptionRevealData = createInscriptionRevealData;
exports.createOutputScriptForInscription = createOutputScriptForInscription;
exports.signRevealTransaction = signRevealTransaction;
const assert = require("assert");
const utxo_lib_1 = require("@bitgo/utxo-lib");
const utxolib = require("@bitgo/utxo-lib");
const OPS = utxo_lib_1.script.OPS;
const MAX_LENGTH_TAP_DATA_PUSH = 520;
/**
* The max size of an individual OP_PUSH in a Taproot script is 520 bytes. This
* function splits inscriptionData into an array buffer of 520 bytes length.
* https://docs.ordinals.com/inscriptions.html
* @param inscriptionData
* @param chunkSize
*/
function splitBuffer(inscriptionData, chunkSize) {
const pushDataBuffers = [];
for (let i = 0; i < inscriptionData.length; i += chunkSize) {
pushDataBuffers.push(inscriptionData.slice(i, i + chunkSize));
}
return pushDataBuffers;
}
/**
*
* @returns inscription payment object
* @param pubkey
* @param contentType
* @param inscriptionData
*/
function createPaymentForInscription(pubkey, contentType, inscriptionData) {
const dataPushBuffers = splitBuffer(inscriptionData, MAX_LENGTH_TAP_DATA_PUSH);
const uncompiledScript = [
pubkey,
OPS.OP_CHECKSIG,
OPS.OP_FALSE,
OPS.OP_IF,
Buffer.from('ord', 'ascii'),
1, // these two lines should be combined as a single OPS.OP_1,
1, // but `ord`'s decoder has a bug so it has to be like this
Buffer.from(contentType, 'ascii'),
OPS.OP_0,
...dataPushBuffers,
OPS.OP_ENDIF,
];
const compiledScript = utxo_lib_1.script.compile(uncompiledScript);
const redeem = {
output: compiledScript,
depth: 0,
};
return utxo_lib_1.p2trPayments.p2tr({ redeems: [redeem], redeemIndex: 0 }, { eccLib: utxo_lib_1.ecc });
}
/**
* @param payment
* @param controlBlock
* @param commitOutput
* @param network
* @return virtual size of a transaction with a single inscription reveal input and a single commitOutput
*/
function getInscriptionRevealSize(payment, controlBlock, commitOutput, network) {
const psbt = utxo_lib_1.bitgo.createPsbtForNetwork({ network });
const parsedControlBlock = utxo_lib_1.taproot.parseControlBlock(utxo_lib_1.ecc, controlBlock);
const leafHash = utxo_lib_1.taproot.getTapleafHash(utxo_lib_1.ecc, parsedControlBlock, payment.redeem?.output);
psbt.addInput({
hash: Buffer.alloc(32),
index: 0,
witnessUtxo: { script: commitOutput, value: BigInt(100000) },
tapLeafScript: [
{
controlBlock,
script: payment.redeem?.output,
leafVersion: utxo_lib_1.taproot.INITIAL_TAPSCRIPT_VERSION,
},
],
});
psbt.addOutput({ script: commitOutput, value: BigInt(10000) });
psbt.signTaprootInput(0, {
publicKey: Buffer.alloc(32),
signSchnorr(hash) {
// dummy schnorr-sized signature
return Buffer.alloc(64);
},
}, [leafHash]);
psbt.finalizeTapInputWithSingleLeafScriptAndSignature(0);
return psbt.extractTransaction(/* disableFeeCheck */ true).virtualSize();
}
/**
* @param pubkey
* @param contentType
* @param inscriptionData
* @param network
* @returns PreparedInscriptionRevealData
*/
function createInscriptionRevealData(pubkey, contentType, inscriptionData, network) {
const payment = createPaymentForInscription(pubkey, contentType, inscriptionData);
const { output: commitOutput, controlBlock } = payment;
assert(commitOutput);
assert(controlBlock);
assert(payment.redeem?.output);
const commitAddress = utxo_lib_1.address.fromOutputScript(commitOutput, network);
const tapLeafScript = [
{
controlBlock,
script: payment.redeem?.output,
leafVersion: utxo_lib_1.taproot.INITIAL_TAPSCRIPT_VERSION,
},
];
const revealTransactionVSize = getInscriptionRevealSize(payment, controlBlock, commitOutput, network);
return {
address: commitAddress,
revealTransactionVSize,
tapLeafScript: tapLeafScript[0],
};
}
/**
* @param pubkey
* @param contentType
* @param inscriptionData
* @returns inscription address
*/
function createOutputScriptForInscription(pubkey, contentType, inscriptionData) {
const payment = createPaymentForInscription(pubkey, contentType, inscriptionData);
assert(payment.output, 'Failed to create inscription output script');
return payment.output;
}
/**
*
* @param privateKey
* @param tapLeafScript
* @param commitAddress
* @param recipientAddress
* @param unsignedCommitTx
* @param network
*
* @return a fully signed reveal transaction
*/
function signRevealTransaction(privateKey, tapLeafScript, commitAddress, recipientAddress, unsignedCommitTx, network) {
const unserCommitTxn = utxolib.bitgo.createTransactionFromBuffer(unsignedCommitTx, network);
const hash = unserCommitTxn.getHash();
const commitOutput = utxolib.address.toOutputScript(commitAddress, network);
const vout = unserCommitTxn.outs.findIndex((out) => out.script.equals(commitOutput));
if (vout === -1) {
throw new Error('Invalid commit transaction');
}
const psbt = utxo_lib_1.bitgo.createPsbtForNetwork({ network });
psbt.addInput({
hash,
index: vout,
witnessUtxo: { script: commitOutput, value: BigInt(unserCommitTxn.outs[vout].value) },
tapLeafScript: [tapLeafScript],
});
const recipientOutput = utxo_lib_1.address.toOutputScript(recipientAddress, network);
psbt.addOutput({ script: recipientOutput, value: BigInt(10000) });
const signer = utxo_lib_1.ECPair.fromPrivateKey(privateKey);
const parsedControlBlock = utxo_lib_1.taproot.parseControlBlock(utxo_lib_1.ecc, tapLeafScript.controlBlock);
const leafHash = utxo_lib_1.taproot.getTapleafHash(utxo_lib_1.ecc, parsedControlBlock, tapLeafScript.script);
psbt.signTaprootInput(0, signer, [leafHash]);
return psbt;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zY3JpcHRpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2luc2NyaXB0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7RUFJRTs7QUEySEYsa0VBNEJDO0FBUUQsNEVBS0M7QUFhRCxzREFrQ0M7QUFqTkQsaUNBQWlDO0FBQ2pDLDhDQVV5QjtBQUN6QiwyQ0FBMkM7QUFHM0MsTUFBTSxHQUFHLEdBQUcsaUJBQU8sQ0FBQyxHQUFHLENBQUM7QUFDeEIsTUFBTSx3QkFBd0IsR0FBRyxHQUFHLENBQUM7QUFFckM7Ozs7OztHQU1HO0FBQ0gsU0FBUyxXQUFXLENBQUMsZUFBdUIsRUFBRSxTQUFpQjtJQUM3RCxNQUFNLGVBQWUsR0FBYSxFQUFFLENBQUM7SUFDckMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLGVBQWUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLFNBQVMsRUFBRSxDQUFDO1FBQzNELGVBQWUsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUVELE9BQU8sZUFBZSxDQUFDO0FBQ3pCLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLDJCQUEyQixDQUFDLE1BQWMsRUFBRSxXQUFtQixFQUFFLGVBQXVCO0lBQy9GLE1BQU0sZUFBZSxHQUFHLFdBQVcsQ0FBQyxlQUFlLEVBQUUsd0JBQXdCLENBQUMsQ0FBQztJQUUvRSxNQUFNLGdCQUFnQixHQUFHO1FBQ3ZCLE1BQU07UUFDTixHQUFHLENBQUMsV0FBVztRQUNmLEdBQUcsQ0FBQyxRQUFRO1FBQ1osR0FBRyxDQUFDLEtBQUs7UUFDVCxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUM7UUFDM0IsQ0FBQyxFQUFFLDJEQUEyRDtRQUM5RCxDQUFDLEVBQUUsMERBQTBEO1FBQzdELE1B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QU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFFN0MsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbkZ1bmN0aW9ucyBmb3IgZGVhbGluZyB3aXRoIGluc2NyaXB0aW9ucy5cblxuU2VlIGh0dHBzOi8vZG9jcy5vcmRpbmFscy5jb20vaW5zY3JpcHRpb25zLmh0bWxcbiovXG5cbmltcG9ydCAqIGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHtcbiAgcDJ0clBheW1lbnRzIGFzIHBheW1lbnRzLFxuICBlY2MgYXMgZWNjTGliLFxuICBzY3JpcHQgYXMgYnNjcmlwdCxcbiAgUGF5bWVudCxcbiAgTmV0d29yayxcbiAgYml0Z28sXG4gIGFkZHJlc3MsXG4gIHRhcHJvb3QsXG4gIEVDUGFpcixcbn0gZnJvbSAnQGJpdGdvL3V0eG8tbGliJztcbmltcG9ydCAqIGFzIHV0eG9saWIgZnJvbSAnQGJpdGdvL3V0eG8tbGliJztcbmltcG9ydCB7IFByZXBhcmVkSW5zY3JpcHRpb25SZXZlYWxEYXRhIH0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcblxuY29uc3QgT1BTID0gYnNjcmlwdC5PUFM7XG5jb25zdCBNQVhfTEVOR1RIX1RBUF9EQVRBX1BVU0ggPSA1MjA7XG5cbi8qKlxuICogVGhlIG1heCBzaXplIG9mIGFuIGluZGl2aWR1YWwgT1BfUFVTSCBpbiBhIFRhcHJvb3Qgc2NyaXB0IGlzIDUyMCBieXRlcy4gVGhpc1xuICogZnVuY3Rpb24gc3BsaXRzIGluc2NyaXB0aW9uRGF0YSBpbnRvIGFuIGFycmF5IGJ1ZmZlciBvZiA1MjAgYnl0ZXMgbGVuZ3RoLlxuICogaHR0cHM6Ly9kb2NzLm9yZGluYWxzLmNvbS9pbnNjcmlwdGlvbnMuaHRtbFxuICogQHBhcmFtIGluc2NyaXB0aW9uRGF0YVxuICogQHBhcmFtIGNodW5rU2l6ZVxuICovXG5mdW5jdGlvbiBzcGxpdEJ1ZmZlcihpbnNjcmlwdGlvbkRhdGE6IEJ1ZmZlciwgY2h1bmtTaXplOiBudW1iZXIpIHtcbiAgY29uc3QgcHVzaERhdGFCdWZmZXJzOiBCdWZmZXJbXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGluc2NyaXB0aW9uRGF0YS5sZW5ndGg7IGkgKz0gY2h1bmtTaXplKSB7XG4gICAgcHVzaERhdGFCdWZmZXJzLnB1c2goaW5zY3JpcHRpb25EYXRhLnNsaWNlKGksIGkgKyBjaHVua1NpemUpKTtcbiAgfVxuXG4gIHJldHVybiBwdXNoRGF0YUJ1ZmZlcnM7XG59XG5cbi8qKlxuICpcbiAqIEByZXR1cm5zIGluc2NyaXB0aW9uIHBheW1lbnQgb2JqZWN0XG4gKiBAcGFyYW0gcHVia2V5XG4gKiBAcGFyYW0gY29udGVudFR5cGVcbiAqIEBwYXJhbSBpbnNjcmlwdGlvbkRhdGFcbiAqL1xuZnVuY3Rpb24gY3JlYXRlUGF5bWVudEZvckluc2NyaXB0aW9uKHB1YmtleTogQnVmZmVyLCBjb250ZW50VHlwZTogc3RyaW5nLCBpbnNjcmlwdGlvbkRhdGE6IEJ1ZmZlcik6IFBheW1lbnQge1xuICBjb25zdCBkYXRhUHVzaEJ1ZmZlcnMgPSBzcGxpdEJ1ZmZlcihpbnNjcmlwdGlvbkRhdGEsIE1BWF9MRU5HVEhfVEFQX0RBVEFfUFVTSCk7XG5cbiAgY29uc3QgdW5jb21waWxlZFNjcmlwdCA9IFtcbiAgICBwdWJrZXksXG4gICAgT1BTLk9QX0NIRUNLU0lHLFxuICAgIE9QUy5PUF9GQUxTRSxcbiAgICBPUFMuT1BfSUYsXG4gICAgQnVmZmVyLmZyb20oJ29yZCcsICdhc2NpaScpLFxuICAgIDEsIC8vIHRoZXNlIHR3byBsaW5lcyBzaG91bGQgYmUgY29tYmluZWQgYXMgYSBzaW5nbGUgT1BTLk9QXzEsXG4gICAgMSwgLy8gYnV0IGBvcmRgJ3MgZGVjb2RlciBoYXMgYSBidWcgc28gaXQgaGFzIHRvIGJlIGxpa2UgdGhpc1xuICAgIEJ1ZmZlci5mcm9tKGNvbnRlbnRUeXBlLCAnYXNjaWknKSxcbiAgICBPUFMuT1BfMCxcbiAgICAuLi5kYXRhUHVzaEJ1ZmZlcnMsXG4gICAgT1BTLk9QX0VORElGLFxuICBdO1xuXG4gIGNvbnN0IGNvbXBpbGVkU2NyaXB0ID0gYnNjcmlwdC5jb21waWxlKHVuY29tcGlsZWRTY3JpcHQpO1xuICBjb25zdCByZWRlZW06IFBheW1lbnQgPSB7XG4gICAgb3V0cHV0OiBjb21waWxlZFNjcmlwdCxcbiAgICBkZXB0aDogMCxcbiAgfTtcblxuICByZXR1cm4gcGF5bWVudHMucDJ0cih7IHJlZGVlbXM6IFtyZWRlZW1dLCByZWRlZW1JbmRleDogMCB9LCB7IGVjY0xpYiB9KTtcbn1cblxuLyoqXG4gKiBAcGFyYW0gcGF5bWVudFxuICogQHBhcmFtIGNvbnRyb2xCbG9ja1xuICogQHBhcmFtIGNvbW1pdE91dHB1dFxuICogQHBhcmFtIG5ldHdvcmtcbiAqIEByZXR1cm4gdmlydHVhbCBzaXplIG9mIGEgdHJhbnNhY3Rpb24gd2l0aCBhIHNpbmdsZSBpbnNjcmlwdGlvbiByZXZlYWwgaW5wdXQgYW5kIGEgc2luZ2xlIGNvbW1pdE91dHB1dFxuICovXG5mdW5jdGlvbiBnZXRJbnNjcmlwdGlvblJldmVhbFNpemUoXG4gIHBheW1lbnQ6IFBheW1lbnQsXG4gIGNvbnRyb2xCbG9jazogQnVmZmVyLFxuICBjb21taXRPdXRwdXQ6IEJ1ZmZlcixcbiAgbmV0d29yazogTmV0d29ya1xuKTogbnVtYmVyIHtcbiAgY29uc3QgcHNidCA9IGJpdGdvLmNyZWF0ZVBzYnRGb3JOZXR3b3JrKHsgbmV0d29yayB9KTtcbiAgY29uc3QgcGFyc2VkQ29udHJvbEJsb2NrID0gdGFwcm9vdC5wYXJzZUNvbnRyb2xCbG9jayhlY2NMaWIsIGNvbnRyb2xCbG9jayk7XG4gIGNvbnN0IGxlYWZIYXNoID0gdGFwcm9vdC5nZXRUYXBsZWFmSGFzaChlY2NMaWIsIHBhcnNlZENvbnRyb2xCbG9jaywgcGF5bWVudC5yZWRlZW0/Lm91dHB1dCBhcyBCdWZmZXIpO1xuXG4gIHBzYnQuYWRkSW5wdXQoe1xuICAgIGhhc2g6IEJ1ZmZlci5hbGxvYygzMiksXG4gICAgaW5kZXg6IDAsXG4gICAgd2l0bmVzc1V0eG86IHsgc2NyaXB0OiBjb21taXRPdXRwdXQsIHZhbHVlOiBCaWdJbnQoMTAwXzAwMCkgfSxcbiAgICB0YXBMZWFmU2NyaXB0OiBbXG4gICAgICB7XG4gICAgICAgIGNvbnRyb2xCbG9jayxcbiAgICAgICAgc2NyaXB0OiBwYXltZW50LnJlZGVlbT8ub3V0cHV0IGFzIEJ1ZmZlcixcbiAgICAgICAgbGVhZlZlcnNpb246IHRhcHJvb3QuSU5JVElBTF9UQVBTQ1JJUFRfVkVSU0lPTixcbiAgICAgIH0sXG4gICAgXSxcbiAgfSk7XG4gIHBzYnQuYWRkT3V0cHV0KHsgc2NyaXB0OiBjb21taXRPdXRwdXQsIHZhbHVlOiBCaWdJbnQoMTBfMDAwKSB9KTtcblxuICBwc2J0LnNpZ25UYXByb290SW5wdXQoXG4gICAgMCxcbiAgICB7XG4gICAgICBwdWJsaWNLZXk6IEJ1ZmZlci5hbGxvYygzMiksXG4gICAgICBzaWduU2Nobm9ycihoYXNoOiBCdWZmZXIpOiBCdWZmZXIge1xuICAgICAgICAvLyBkdW1teSBzY2hub3JyLXNpemVkIHNpZ25hdHVyZVxuICAgICAgICByZXR1cm4gQnVmZmVyLmFsbG9jKDY0KTtcbiAgICAgIH0sXG4gICAgfSxcbiAgICBbbGVhZkhhc2hdXG4gICk7XG5cbiAgcHNidC5maW5hbGl6ZVRhcElucHV0V2l0aFNpbmdsZUxlYWZTY3JpcHRBbmRTaWduYXR1cmUoMCk7XG4gIHJldHVybiBwc2J0LmV4dHJhY3RUcmFuc2FjdGlvbigvKiBkaXNhYmxlRmVlQ2hlY2sgKi8gdHJ1ZSkudmlydHVhbFNpemUoKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0gcHVia2V5XG4gKiBAcGFyYW0gY29udGVudFR5cGVcbiAqIEBwYXJhbSBpbnNjcmlwdGlvbkRhdGFcbiAqIEBwYXJhbSBuZXR3b3JrXG4gKiBAcmV0dXJucyBQcmVwYXJlZEluc2NyaXB0aW9uUmV2ZWFsRGF0YVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlSW5zY3JpcHRpb25SZXZlYWxEYXRhKFxuICBwdWJrZXk6IEJ1ZmZlcixcbiAgY29udGVudFR5cGU6IHN0cmluZyxcbiAgaW5zY3JpcHRpb25EYXRhOiBCdWZmZXIsXG4gIG5ldHdvcms6IE5ldHdvcmtcbik6IFByZXBhcmVkSW5zY3JpcHRpb25SZXZlYWxEYXRhIHtcbiAgY29uc3QgcGF5bWVudCA9IGNyZWF0ZVBheW1lbnRGb3JJbnNjcmlwdGlvbihwdWJrZXksIGNvbnRlbnRUeXBlLCBpbnNjcmlwdGlvbkRhdGEpO1xuXG4gIGNvbnN0IHsgb3V0cHV0OiBjb21taXRPdXRwdXQsIGNvbnRyb2xCbG9jayB9ID0gcGF5bWVudDtcbiAgYXNzZXJ0KGNvbW1pdE91dHB1dCk7XG4gIGFzc2VydChjb250cm9sQmxvY2spO1xuICBhc3NlcnQocGF5bWVudC5yZWRlZW0/Lm91dHB1dCk7XG4gIGNvbnN0IGNvbW1pdEFkZHJlc3MgPSBhZGRyZXNzLmZyb21PdXRwdXRTY3JpcHQoY29tbWl0T3V0cHV0LCBuZXR3b3JrKTtcblxuICBjb25zdCB0YXBMZWFmU2NyaXB0OiB1dHhvbGliLmJpdGdvLlRhcExlYWZTY3JpcHRbXSA9IFtcbiAgICB7XG4gICAgICBjb250cm9sQmxvY2ssXG4gICAgICBzY3JpcHQ6IHBheW1lbnQucmVkZWVtPy5vdXRwdXQsXG4gICAgICBsZWFmVmVyc2lvbjogdGFwcm9vdC5JTklUSUFMX1RBUFNDUklQVF9WRVJTSU9OLFxuICAgIH0sXG4gIF07XG4gIGNvbnN0IHJldmVhbFRyYW5zYWN0aW9uVlNpemUgPSBnZXRJbnNjcmlwdGlvblJldmVhbFNpemUocGF5bWVudCwgY29udHJvbEJsb2NrLCBjb21taXRPdXRwdXQsIG5ldHdvcmspO1xuXG4gIHJldHVybiB7XG4gICAgYWRkcmVzczogY29tbWl0QWRkcmVzcyxcbiAgICByZXZlYWxUcmFuc2FjdGlvblZTaXplLFxuICAgIHRhcExlYWZTY3JpcHQ6IHRhcExlYWZTY3JpcHRbMF0sXG4gIH07XG59XG5cbi8qKlxuICogQHBhcmFtIHB1YmtleVxuICogQHBhcmFtIGNvbnRlbnRUeXBlXG4gKiBAcGFyYW0gaW5zY3JpcHRpb25EYXRhXG4gKiBAcmV0dXJucyBpbnNjcmlwdGlvbiBhZGRyZXNzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVPdXRwdXRTY3JpcHRGb3JJbnNjcmlwdGlvbihwdWJrZXk6IEJ1ZmZlciwgY29udGVudFR5cGU6IHN0cmluZywgaW5zY3JpcHRpb25EYXRhOiBCdWZmZXIpOiBCdWZmZXIge1xuICBjb25zdCBwYXltZW50ID0gY3JlYXRlUGF5bWVudEZvckluc2NyaXB0aW9uKHB1YmtleSwgY29udGVudFR5cGUsIGluc2NyaXB0aW9uRGF0YSk7XG5cbiAgYXNzZXJ0KHBheW1lbnQub3V0cHV0LCAnRmFpbGVkIHRvIGNyZWF0ZSBpbnNjcmlwdGlvbiBvdXRwdXQgc2NyaXB0Jyk7XG4gIHJldHVybiBwYXltZW50Lm91dHB1dDtcbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIHByaXZhdGVLZXlcbiAqIEBwYXJhbSB0YXBMZWFmU2NyaXB0XG4gKiBAcGFyYW0gY29tbWl0QWRkcmVzc1xuICogQHBhcmFtIHJlY2lwaWVudEFkZHJlc3NcbiAqIEBwYXJhbSB1bnNpZ25lZENvbW1pdFR4XG4gKiBAcGFyYW0gbmV0d29ya1xuICpcbiAqIEByZXR1cm4gYSBmdWxseSBzaWduZWQgcmV2ZWFsIHRyYW5zYWN0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaWduUmV2ZWFsVHJhbnNhY3Rpb24oXG4gIHByaXZhdGVLZXk6IEJ1ZmZlcixcbiAgdGFwTGVhZlNjcmlwdDogdXR4b2xpYi5iaXRnby5UYXBMZWFmU2NyaXB0LFxuICBjb21taXRBZGRyZXNzOiBzdHJpbmcsXG4gIHJlY2lwaWVudEFkZHJlc3M6IHN0cmluZyxcbiAgdW5zaWduZWRDb21taXRUeDogQnVmZmVyLFxuICBuZXR3b3JrOiBOZXR3b3JrXG4pOiB1dHhvbGliLmJpdGdvLlV0eG9Qc2J0IHtcbiAgY29uc3QgdW5zZXJDb21taXRUeG4gPSB1dHhvbGliLmJpdGdvLmNyZWF0ZVRyYW5zYWN0aW9uRnJvbUJ1ZmZlcih1bnNpZ25lZENvbW1pdFR4LCBuZXR3b3JrKTtcbiAgY29uc3QgaGFzaCA9IHVuc2VyQ29tbWl0VHhuLmdldEhhc2goKTtcbiAgY29uc3QgY29tbWl0T3V0cHV0ID0gdXR4b2xpYi5hZGRyZXNzLnRvT3V0cHV0U2NyaXB0KGNvbW1pdEFkZHJlc3MsIG5ldHdvcmspO1xuICBjb25zdCB2b3V0ID0gdW5zZXJDb21taXRUeG4ub3V0cy5maW5kSW5kZXgoKG91dCkgPT4gb3V0LnNjcmlwdC5lcXVhbHMoY29tbWl0T3V0cHV0KSk7XG5cbiAgaWYgKHZvdXQgPT09IC0xKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvbW1pdCB0cmFuc2FjdGlvbicpO1xuICB9XG5cbiAgY29uc3QgcHNidCA9IGJpdGdvLmNyZWF0ZVBzYnRGb3JOZXR3b3JrKHsgbmV0d29yayB9KTtcbiAgcHNidC5hZGRJbnB1dCh7XG4gICAgaGFzaCxcbiAgICBpbmRleDogdm91dCxcbiAgICB3aXRuZXNzVXR4bzogeyBzY3JpcHQ6IGNvbW1pdE91dHB1dCwgdmFsdWU6IEJpZ0ludCh1bnNlckNvbW1pdFR4bi5vdXRzW3ZvdXRdLnZhbHVlKSB9LFxuICAgIHRhcExlYWZTY3JpcHQ6IFt0YXBMZWFmU2NyaXB0XSxcbiAgfSk7XG5cbiAgY29uc3QgcmVjaXBpZW50T3V0cHV0ID0gYWRkcmVzcy50b091dHB1dFNjcmlwdChyZWNpcGllbnRBZGRyZXNzLCBuZXR3b3JrKTtcbiAgcHNidC5hZGRPdXRwdXQoeyBzY3JpcHQ6IHJlY2lwaWVudE91dHB1dCwgdmFsdWU6IEJpZ0ludCgxMF8wMDApIH0pO1xuXG4gIGNvbnN0IHNpZ25lciA9IEVDUGFpci5mcm9tUHJpdmF0ZUtleShwcml2YXRlS2V5KTtcbiAgY29uc3QgcGFyc2VkQ29udHJvbEJsb2NrID0gdGFwcm9vdC5wYXJzZUNvbnRyb2xCbG9jayhlY2NMaWIsIHRhcExlYWZTY3JpcHQuY29udHJvbEJsb2NrKTtcbiAgY29uc3QgbGVhZkhhc2ggPSB0YXByb290LmdldFRhcGxlYWZIYXNoKGVjY0xpYiwgcGFyc2VkQ29udHJvbEJsb2NrLCB0YXBMZWFmU2NyaXB0LnNjcmlwdCBhcyBCdWZmZXIpO1xuICBwc2J0LnNpZ25UYXByb290SW5wdXQoMCwgc2lnbmVyLCBbbGVhZkhhc2hdKTtcblxuICByZXR1cm4gcHNidDtcbn1cbiJdfQ==Выполнить команду
Для локальной разработки. Не используйте в интернете!