PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-coin-sui/dist/test/local_fullnode
Просмотр файла: transactions.js
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
process.env.DEBUG = 'RpcClient,SuiTransactionTypes';
const assert_1 = __importDefault(require("assert"));
const util_1 = __importDefault(require("util"));
const faucet_1 = require("./faucet");
const debug_1 = __importDefault(require("debug"));
const crypto_1 = require("crypto");
const src_1 = require("../../src");
const RpcClient_1 = require("./RpcClient");
const getBuilderFactory_1 = require("../unit/getBuilderFactory");
const iface_1 = require("../../src/lib/iface");
const constants_1 = require("../../src/lib/constants");
const debug = (0, debug_1.default)('SuiTransactionTypes');
async function getAllCoins(conn, address) {
return (await conn.getCoins(address)).data.map((v) => {
return {
digest: v.digest,
objectId: v.coinObjectId,
version: v.version,
};
});
}
/**
* @returns The stakes array with the stakedSui amount reduced by amount. If amount is undefined, the stakedSui is removed.
*/
function subtractStake(stakes, stakedSui, amount) {
return stakes.flatMap((s) => {
if (s.stakedSuiId === stakedSui.stakedSuiId) {
if (amount === undefined) {
// remove the stake
return [];
}
else {
// reduce the stake by amount
return [{ ...s, principal: Number(s.principal) - amount }];
}
}
else {
// keep the stake unchanged
return [s];
}
});
}
/**
* Asserts that the stakesAfter array is the same as the stakesBefore array with the stakedSui amount reduced by amount.
*/
function assertReducedStake(stakesBefore, stakesAfter, stakedSui, amount) {
/*
* Normalize the stake objects by converting the principal to a number and removing the estimatedReward.
*/
function normStake(s) {
return { ...s, principal: Number(s.principal), estimatedReward: undefined };
}
stakesBefore = stakesBefore.map(normStake);
stakesAfter = stakesAfter.map(normStake);
assert_1.default.deepStrictEqual(stakesAfter, subtractStake(stakesBefore, stakedSui, amount));
}
async function getStakes(conn, owner, params = {}) {
const all = await conn.getStakes(owner);
const result = await Promise.all(all.flatMap((s) => s.stakes
.filter((v) => params.filterStatus === undefined || v.status === params.filterStatus)
.filter((v) => params.filterMinValue === undefined || params.filterMinValue <= Number(v.principal))));
if (result.length) {
return result;
}
const { attempts = 60, sleepMs = 1000 } = params;
if (0 < attempts) {
await new Promise((resolve) => setTimeout(resolve, sleepMs));
return await getStakes(conn, owner, { ...params, attempts: attempts - 1, sleepMs });
}
else {
throw new Error('getAllActiveStakedSuis: no active staked suis found');
}
}
async function resolveStakedSui(conn, stake) {
return (await conn.getObject(stake.stakedSuiId)).data;
}
function getKeyPair(seed) {
const seedBuf = (0, crypto_1.createHash)('sha256').update(seed).digest();
return new src_1.KeyPair({ seed: seedBuf });
}
async function signAndSubmit(conn, keyPair, txb) {
txb.sign({ key: keyPair.getKeys().prv });
const tx = (await txb.build());
debug('tx', util_1.default.inspect(tx.suiTransaction.tx, { depth: 10 }));
const result = await conn.executeTransactionBlock(tx.toBroadcastFormat(), [
Buffer.from(tx.serializedSig).toString('base64'),
]);
if (result.effects?.status.status !== 'success') {
throw new Error(`Transaction failed: ${JSON.stringify(result.effects?.status)}`);
}
}
async function fundFromFaucet(url, v, amount = 100e9) {
if (typeof v !== 'string') {
v = v.getAddress();
}
await new faucet_1.Faucet(url).getCoins(v, 10e9);
}
describe('Sui Transaction Types', function () {
if (process.env.DRONE) {
console.log('skipping local_fullnode/transactions.ts on drone');
return;
}
const keyPair = getKeyPair('test');
const address = keyPair.getAddress();
debug('address', address);
const fullnodeUrl = process.env.SUI_FULLNODE_URL || 'http://127.0.0.1:9000';
const faucetUrl = process.env.SUI_FAUCET_URL || 'http://127.0.0.1:9123';
async function getDefaultGasData(keyPair) {
return {
owner: keyPair.getAddress(),
payment: await getAllCoins(conn, keyPair.getAddress()),
budget: 100000000,
price: constants_1.DUMMY_SUI_GAS_PRICE,
};
}
let conn;
let validator;
before('establish connection', async function () {
conn = await RpcClient_1.RpcClient.createCheckedConnection(fullnodeUrl);
const { apys } = await conn.getValidatorsApy();
validator = apys[0].address;
});
before('fund via faucet', async function () {
if (faucetUrl) {
await fundFromFaucet(faucetUrl, address);
}
});
it('has coins', async function () {
const { data } = await conn.getCoins(address);
assert_1.default.notStrictEqual(data.length, 0);
});
it('can transfer coins', async function () {
const builder = (0, getBuilderFactory_1.getBuilderFactory)('tsui').getTransferBuilder();
const txb = builder
.type(iface_1.SuiTransactionType.Transfer)
.sender(address)
.send([{ address, amount: (111111).toString() }])
.gasData(await getDefaultGasData(keyPair));
await signAndSubmit(conn, keyPair, txb);
});
async function stakeAmount(keyPair, amount) {
const builder = (0, getBuilderFactory_1.getBuilderFactory)('tsui').getStakingBuilder();
const txb = builder
.type(iface_1.SuiTransactionType.AddStake)
.sender(keyPair.getAddress())
.stake([{ amount, validatorAddress: validator }])
.gasData(await getDefaultGasData(keyPair));
await signAndSubmit(conn, keyPair, txb);
}
it('can stake coins', async function () {
await stakeAmount(keyPair, 1e9);
});
function testUnstake(amount) {
describe(`unstake (amount=${amount})`, function () {
const keyPairStakeTest = getKeyPair(`stake-test-amount-${amount !== undefined}`);
const address = keyPairStakeTest.getAddress();
before('stake coins', async function () {
await fundFromFaucet(faucetUrl, address);
await stakeAmount(keyPairStakeTest, 10e9);
});
it(`can unstake`, async function () {
const activeStakedSui = await getStakes(conn, address, {
filterStatus: 'Active',
filterMinValue: constants_1.MIN_STAKING_THRESHOLD + (amount || 0),
});
(0, assert_1.default)(activeStakedSui.length > 0, 'No staked coins found');
for (const stakedSui of activeStakedSui.slice(0, 3)) {
debug('unstaking', stakedSui);
const builder = (0, getBuilderFactory_1.getBuilderFactory)('tsui').getUnstakingBuilder();
const stakedBefore = await getStakes(conn, address);
const txb = builder
.type(iface_1.SuiTransactionType.WithdrawStake)
.sender(address)
.unstake({ stakedSui: await resolveStakedSui(conn, stakedSui), amount })
.gasData(await getDefaultGasData(keyPairStakeTest));
await signAndSubmit(conn, keyPairStakeTest, txb);
assertReducedStake(stakedBefore, await getStakes(conn, address), stakedSui, amount);
}
});
});
}
testUnstake(undefined);
testUnstake(1e9);
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC9sb2NhbF9mdWxsbm9kZS90cmFuc2FjdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFFQSxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssR0FBRywrQkFBK0IsQ0FBQztBQUVwRCxvREFBNEI7QUFDNUIsZ0RBQXdCO0FBQ3hCLHFDQUFrQztBQUNsQyxrREFBK0I7QUFDL0IsbUNBQW9DO0FBRXBDLG1DQVFtQjtBQUNuQiwyQ0FBd0M7QUFDeEMsaUVBQThEO0FBQzlELCtDQUF5RDtBQUV6RCx1REFBcUY7QUFFckYsTUFBTSxLQUFLLEdBQUcsSUFBQSxlQUFVLEVBQUMscUJBQXFCLENBQUMsQ0FBQztBQUVoRCxLQUFLLFVBQVUsV0FBVyxDQUFDLElBQWUsRUFBRSxPQUFlO0lBQ3pELE9BQU8sQ0FBQyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7UUFDbkQsT0FBTztZQUNMLE1BQU0sRUFBRSxDQUFDLENBQUMsTUFBTTtZQUNoQixRQUFRLEVBQUUsQ0FBQyxDQUFDLFlBQVk7WUFDeEIsT0FBTyxFQUFFLENBQUMsQ0FBQyxPQUFPO1NBQ25CLENBQUM7SUFDSixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsYUFBYSxDQUFDLE1BQXFCLEVBQUUsU0FBc0IsRUFBRSxNQUEwQjtJQUM5RixPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQWlCLEVBQUU7UUFDekMsSUFBSSxDQUFDLENBQUMsV0FBVyxLQUFLLFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUM1QyxJQUFJLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDekIsbUJBQW1CO2dCQUNuQixPQUFPLEVBQUUsQ0FBQztZQUNa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QUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU3Rha2VPYmplY3QgfSBmcm9tICcuLi8uLi9zcmMvbGliL215c3RlbmxhYi90eXBlcy92YWxpZGF0b3InO1xuXG5wcm9jZXNzLmVudi5ERUJVRyA9ICdScGNDbGllbnQsU3VpVHJhbnNhY3Rpb25UeXBlcyc7XG5cbmltcG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB1dGlsIGZyb20gJ3V0aWwnO1xuaW1wb3J0IHsgRmF1Y2V0IH0gZnJvbSAnLi9mYXVjZXQnO1xuaW1wb3J0IGJ1aWxkRGVidWcgZnJvbSAnZGVidWcnO1xuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ2NyeXB0byc7XG5cbmltcG9ydCB7XG4gIEtleVBhaXIsXG4gIFN0YWtpbmdCdWlsZGVyLFxuICBTdGFraW5nVHJhbnNhY3Rpb24sXG4gIFRyYW5zZmVyQnVpbGRlcixcbiAgVHJhbnNmZXJUcmFuc2FjdGlvbixcbiAgVW5zdGFraW5nQnVpbGRlcixcbiAgVW5zdGFraW5nVHJhbnNhY3Rpb24sXG59IGZyb20gJy4uLy4uL3NyYyc7XG5pbXBvcnQgeyBScGNDbGllbnQgfSBmcm9tICcuL1JwY0NsaWVudCc7XG5pbXBvcnQgeyBnZXRCdWlsZGVyRmFjdG9yeSB9IGZyb20gJy4uL3VuaXQvZ2V0QnVpbGRlckZhY3RvcnknO1xuaW1wb3J0IHsgU3VpVHJhbnNhY3Rpb25UeXBlIH0gZnJvbSAnLi4vLi4vc3JjL2xpYi9pZmFjZSc7XG5pbXBvcnQgeyBHYXNEYXRhLCBTdWlPYmplY3RSZWYgfSBmcm9tICcuLi8uLi9zcmMvbGliL215c3RlbmxhYi90eXBlcyc7XG5pbXBvcnQgeyBEVU1NWV9TVUlfR0FTX1BSSUNFLCBNSU5fU1RBS0lOR19USFJFU0hPTEQgfSBmcm9tICcuLi8uLi9zcmMvbGliL2NvbnN0YW50cyc7XG5cbmNvbnN0IGRlYnVnID0gYnVpbGREZWJ1ZygnU3VpVHJhbnNhY3Rpb25UeXBlcycpO1xuXG5hc3luYyBmdW5jdGlvbiBnZXRBbGxDb2lucyhjb25uOiBScGNDbGllbnQsIGFkZHJlc3M6IHN0cmluZyk6IFByb21pc2U8U3VpT2JqZWN0UmVmW10+IHtcbiAgcmV0dXJuIChhd2FpdCBjb25uLmdldENvaW5zKGFkZHJlc3MpKS5kYXRhLm1hcCgodikgPT4ge1xuICAgIHJldHVybiB7XG4gICAgICBkaWdlc3Q6IHYuZGlnZXN0LFxuICAgICAgb2JqZWN0SWQ6IHYuY29pbk9iamVjdElkLFxuICAgICAgdmVyc2lvbjogdi52ZXJzaW9uLFxuICAgIH07XG4gIH0pO1xufVxuXG4vKipcbiAqIEByZXR1cm5zIFRoZSBzdGFrZXMgYXJyYXkgd2l0aCB0aGUgc3Rha2VkU3VpIGFtb3VudCByZWR1Y2VkIGJ5IGFtb3VudC4gSWYgYW1vdW50IGlzIHVuZGVmaW5lZCwgdGhlIHN0YWtlZFN1aSBpcyByZW1vdmVkLlxuICovXG5mdW5jdGlvbiBzdWJ0cmFjdFN0YWtlKHN0YWtlczogU3Rha2VPYmplY3RbXSwgc3Rha2VkU3VpOiBTdGFrZU9iamVjdCwgYW1vdW50OiBudW1iZXIgfCB1bmRlZmluZWQpOiBTdGFrZU9iamVjdFtdIHtcbiAgcmV0dXJuIHN0YWtlcy5mbGF0TWFwKChzKTogU3Rha2VPYmplY3RbXSA9PiB7XG4gICAgaWYgKHMuc3Rha2VkU3VpSWQgPT09IHN0YWtlZFN1aS5zdGFrZWRTdWlJZCkge1xuICAgICAgaWYgKGFtb3VudCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIHJlbW92ZSB0aGUgc3Rha2VcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcmVkdWNlIHRoZSBzdGFrZSBieSBhbW91bnRcbiAgICAgICAgcmV0dXJuIFt7IC4uLnMsIHByaW5jaXBhbDogTnVtYmVyKHMucHJpbmNpcGFsKSAtIGFtb3VudCB9XTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8ga2VlcCB0aGUgc3Rha2UgdW5jaGFuZ2VkXG4gICAgICByZXR1cm4gW3NdO1xuICAgIH1cbiAgfSk7XG59XG5cbi8qKlxuICogQXNzZXJ0cyB0aGF0IHRoZSBzdGFrZXNBZnRlciBhcnJheSBpcyB0aGUgc2FtZSBhcyB0aGUgc3Rha2VzQmVmb3JlIGFycmF5IHdpdGggdGhlIHN0YWtlZFN1aSBhbW91bnQgcmVkdWNlZCBieSBhbW91bnQuXG4gKi9cbmZ1bmN0aW9uIGFzc2VydFJlZHVjZWRTdGFrZShcbiAgc3Rha2VzQmVmb3JlOiBTdGFrZU9iamVjdFtdLFxuICBzdGFrZXNBZnRlcjogU3Rha2VPYmplY3RbXSxcbiAgc3Rha2VkU3VpOiBTdGFrZU9iamVjdCxcbiAgYW1vdW50OiBudW1iZXIgfCB1bmRlZmluZWRcbikge1xuICAvKlxuICAgKiBOb3JtYWxpemUgdGhlIHN0YWtlIG9iamVjdHMgYnkgY29udmVydGluZyB0aGUgcHJpbmNpcGFsIHRvIGEgbnVtYmVyIGFuZCByZW1vdmluZyB0aGUgZXN0aW1hdGVkUmV3YXJkLlxuICAgKi9cbiAgZnVuY3Rpb24gbm9ybVN0YWtlKHM6IFN0YWtlT2JqZWN0KTogU3Rha2VPYmplY3Qge1xuICAgIHJldHVybiB7IC4uLnMsIHByaW5jaXBhbDogTnVtYmVyKHMucHJpbmNpcGFsKSwgZXN0aW1hdGVkUmV3YXJkOiB1bmRlZmluZWQgfTtcbiAgfVxuICBzdGFrZXNCZWZvcmUgPSBzdGFrZXNCZWZvcmUubWFwKG5vcm1TdGFrZSk7XG4gIHN0YWtlc0FmdGVyID0gc3Rha2VzQWZ0ZXIubWFwKG5vcm1TdGFrZSk7XG4gIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoc3Rha2VzQWZ0ZXIsIHN1YnRyYWN0U3Rha2Uoc3Rha2VzQmVmb3JlLCBzdGFrZWRTdWksIGFtb3VudCkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRTdGFrZXMoXG4gIGNvbm46IFJwY0NsaWVudCxcbiAgb3duZXI6IHN0cmluZyxcbiAgcGFyYW1zOiB7XG4gICAgZmlsdGVyU3RhdHVzPzogU3Rha2VPYmplY3RbJ3N0YXR1cyddO1xuICAgIGZpbHRlck1pblZhbHVlPzogbnVtYmVyO1xuICAgIGF0dGVtcHRzPzogbnVtYmVyO1xuICAgIHNsZWVwTXM/OiBudW1iZXI7XG4gIH0gPSB7fVxuKTogUHJvbWlzZTxTdGFrZU9iamVjdFtdPiB7XG4gIGNvbnN0IGFsbCA9IGF3YWl0IGNvbm4uZ2V0U3Rha2VzKG93bmVyKTtcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgYWxsLmZsYXRNYXAoKHMpID0+XG4gICAgICBzLnN0YWtlc1xuICAgICAgICAuZmlsdGVyKCh2KSA9PiBwYXJhbXMuZmlsdGVyU3RhdHVzID09PSB1bmRlZmluZWQgfHwgdi5zdGF0dXMgPT09IHBhcmFtcy5maWx0ZXJTdGF0dXMpXG4gICAgICAgIC5maWx0ZXIoKHYpID0+IHBhcmFtcy5maWx0ZXJNaW5WYWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHBhcmFtcy5maWx0ZXJNaW5WYWx1ZSA8PSBOdW1iZXIodi5wcmluY2lwYWwpKVxuICAgIClcbiAgKTtcbiAgaWYgKHJlc3VsdC5sZW5ndGgpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIGNvbnN0IHsgYXR0ZW1wdHMgPSA2MCwgc2xlZXBNcyA9IDEwMDAgfSA9IHBhcmFtcztcbiAgaWYgKDAgPCBhdHRlbXB0cykge1xuICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIHNsZWVwTXMpKTtcbiAgICByZXR1cm4gYXdhaXQgZ2V0U3Rha2VzKGNvbm4sIG93bmVyLCB7IC4uLnBhcmFtcywgYXR0ZW1wdHM6IGF0dGVtcHRzIC0gMSwgc2xlZXBNcyB9KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dldEFsbEFjdGl2ZVN0YWtlZFN1aXM6IG5vIGFjdGl2ZSBzdGFrZWQgc3VpcyBmb3VuZCcpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVTdGFrZWRTdWkoY29ubjogUnBjQ2xpZW50LCBzdGFrZTogU3Rha2VPYmplY3QpOiBQcm9taXNlPFN1aU9iamVjdFJlZj4ge1xuICByZXR1cm4gKGF3YWl0IGNvbm4uZ2V0T2JqZWN0KHN0YWtlLnN0YWtlZFN1aUlkKSkuZGF0YTtcbn1cblxuZnVuY3Rpb24gZ2V0S2V5UGFpcihzZWVkOiBzdHJpbmcpOiBLZXlQYWlyIHtcbiAgY29uc3Qgc2VlZEJ1ZiA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShzZWVkKS5kaWdlc3QoKTtcbiAgcmV0dXJuIG5ldyBLZXlQYWlyKHsgc2VlZDogc2VlZEJ1ZiB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2lnbkFuZFN1Ym1pdChcbiAgY29ubjogUnBjQ2xpZW50LFxuICBrZXlQYWlyOiBLZXlQYWlyLFxuICB0eGI6IFRyYW5zZmVyQnVpbGRlciB8IFN0YWtpbmdCdWlsZGVyIHwgVW5zdGFraW5nQnVpbGRlclxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIHR4Yi5zaWduKHsga2V5OiBrZXlQYWlyLmdldEtleXMoKS5wcnYgfSk7XG4gIGNvbnN0IHR4ID0gKGF3YWl0IHR4Yi5idWlsZCgpKSBhcyBUcmFuc2ZlclRyYW5zYWN0aW9uIHwgU3Rha2luZ1RyYW5zYWN0aW9uIHwgVW5zdGFraW5nVHJhbnNhY3Rpb247XG4gIGRlYnVnKCd0eCcsIHV0aWwuaW5zcGVjdCh0eC5zdWlUcmFuc2FjdGlvbi50eCwgeyBkZXB0aDogMTAgfSkpO1xuICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb25uLmV4ZWN1dGVUcmFuc2FjdGlvbkJsb2NrKHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCksIFtcbiAgICBCdWZmZXIuZnJvbSh0eC5zZXJpYWxpemVkU2lnKS50b1N0cmluZygnYmFzZTY0JyksXG4gIF0pO1xuICBpZiAocmVzdWx0LmVmZmVjdHM/LnN0YXR1cy5zdGF0dXMgIT09ICdzdWNjZXNzJykge1xuICAgIHRocm93IG5ldyBFcnJvcihgVHJhbnNhY3Rpb24gZmFpbGVkOiAke0pTT04uc3RyaW5naWZ5KHJlc3VsdC5lZmZlY3RzPy5zdGF0dXMpfWApO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZ1bmRGcm9tRmF1Y2V0KHVybDogc3RyaW5nLCB2OiBLZXlQYWlyIHwgc3RyaW5nLCBhbW91bnQgPSAxMDBlOSk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAodHlwZW9mIHYgIT09ICdzdHJpbmcnKSB7XG4gICAgdiA9IHYuZ2V0QWRkcmVzcygpO1xuICB9XG4gIGF3YWl0IG5ldyBGYXVjZXQodXJsKS5nZXRDb2lucyh2LCAxMGU5KTtcbn1cblxuZGVzY3JpYmUoJ1N1aSBUcmFuc2FjdGlvbiBUeXBlcycsIGZ1bmN0aW9uICgpIHtcbiAgaWYgKHByb2Nlc3MuZW52LkRST05FKSB7XG4gICAgY29uc29sZS5sb2coJ3NraXBwaW5nIGxvY2FsX2Z1bGxub2RlL3RyYW5zYWN0aW9ucy50cyBvbiBkcm9uZScpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IGtleVBhaXIgPSBnZXRLZXlQYWlyKCd0ZXN0Jyk7XG4gIGNvbnN0IGFkZHJlc3MgPSBrZXlQYWlyLmdldEFkZHJlc3MoKTtcbiAgZGVidWcoJ2FkZHJlc3MnLCBhZGRyZXNzKTtcblxuICBjb25zdCBmdWxsbm9kZVVybCA9IHByb2Nlc3MuZW52LlNVSV9GVUxMTk9ERV9VUkwgfHwgJ2h0dHA6Ly8xMjcuMC4wLjE6OTAwMCc7XG4gIGNvbnN0IGZhdWNldFVybCA9IHByb2Nlc3MuZW52LlNVSV9GQVVDRVRfVVJMIHx8ICdodHRwOi8vMTI3LjAuMC4xOjkxMjMnO1xuXG4gIGFzeW5jIGZ1bmN0aW9uIGdldERlZmF1bHRHYXNEYXRhKGtleVBhaXI6IEtleVBhaXIpOiBQcm9taXNlPEdhc0RhdGE+IHtcbiAgICByZXR1cm4ge1xuICAgICAgb3duZXI6IGtleVBhaXIuZ2V0QWRkcmVzcygpLFxuICAgICAgcGF5bWVudDogYXdhaXQgZ2V0QWxsQ29pbnMoY29ubiwga2V5UGFpci5nZXRBZGRyZXNzKCkpLFxuICAgICAgYnVkZ2V0OiAxMDBfMDAwXzAwMCxcbiAgICAgIHByaWNlOiBEVU1NWV9TVUlfR0FTX1BSSUNFLFxuICAgIH07XG4gIH1cblxuICBsZXQgY29ubjogUnBjQ2xpZW50O1xuICBsZXQgdmFsaWRhdG9yOiBzdHJpbmc7XG4gIGJlZm9yZSgnZXN0YWJsaXNoIGNvbm5lY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29ubiA9IGF3YWl0IFJwY0NsaWVudC5jcmVhdGVDaGVja2VkQ29ubmVjdGlvbihmdWxsbm9kZVVybCk7XG4gICAgY29uc3QgeyBhcHlzIH0gPSBhd2FpdCBjb25uLmdldFZhbGlkYXRvcnNBcHkoKTtcbiAgICB2YWxpZGF0b3IgPSBhcHlzWzBdLmFkZHJlc3M7XG4gIH0pO1xuXG4gIGJlZm9yZSgnZnVuZCB2aWEgZmF1Y2V0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGlmIChmYXVjZXRVcmwpIHtcbiAgICAgIGF3YWl0IGZ1bmRGcm9tRmF1Y2V0KGZhdWNldFVybCwgYWRkcmVzcyk7XG4gICAgfVxuICB9KTtcblxuICBpdCgnaGFzIGNvaW5zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHsgZGF0YSB9ID0gYXdhaXQgY29ubi5nZXRDb2lucyhhZGRyZXNzKTtcbiAgICBhc3NlcnQubm90U3RyaWN0RXF1YWwoZGF0YS5sZW5ndGgsIDApO1xuICB9KTtcblxuICBpdCgnY2FuIHRyYW5zZmVyIGNvaW5zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGJ1aWxkZXIgPSBnZXRCdWlsZGVyRmFjdG9yeSgndHN1aScpLmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgIGNvbnN0IHR4YiA9IGJ1aWxkZXJcbiAgICAgIC50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2ZlcilcbiAgICAgIC5zZW5kZXIoYWRkcmVzcylcbiAgICAgIC5zZW5kKFt7IGFkZHJlc3MsIGFtb3VudDogKDExMV8xMTEpLnRvU3RyaW5nKCkgfV0pXG4gICAgICAuZ2FzRGF0YShhd2FpdCBnZXREZWZhdWx0R2FzRGF0YShrZXlQYWlyKSk7XG5cbiAgICBhd2FpdCBzaWduQW5kU3VibWl0KGNvbm4sIGtleVBhaXIsIHR4Yik7XG4gIH0pO1xuXG4gIGFzeW5jIGZ1bmN0aW9uIHN0YWtlQW1vdW50KGtleVBhaXI6IEtleVBhaXIsIGFtb3VudDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgYnVpbGRlciA9IGdldEJ1aWxkZXJGYWN0b3J5KCd0c3VpJykuZ2V0U3Rha2luZ0J1aWxkZXIoKTtcbiAgICBjb25zdCB0eGIgPSBidWlsZGVyXG4gICAgICAudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuQWRkU3Rha2UpXG4gICAgICAuc2VuZGVyKGtleVBhaXIuZ2V0QWRkcmVzcygpKVxuICAgICAgLnN0YWtlKFt7IGFtb3VudCwgdmFsaWRhdG9yQWRkcmVzczogdmFsaWRhdG9yIH1dKVxuICAgICAgLmdhc0RhdGEoYXdhaXQgZ2V0RGVmYXVsdEdhc0RhdGEoa2V5UGFpcikpO1xuXG4gICAgYXdhaXQgc2lnbkFuZFN1Ym1pdChjb25uLCBrZXlQYWlyLCB0eGIpO1xuICB9XG5cbiAgaXQoJ2NhbiBzdGFrZSBjb2lucycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBhd2FpdCBzdGFrZUFtb3VudChrZXlQYWlyLCAxZTkpO1xuICB9KTtcblxuICBmdW5jdGlvbiB0ZXN0VW5zdGFrZShhbW91bnQ6IG51bWJlciB8IHVuZGVmaW5lZCkge1xuICAgIGRlc2NyaWJlKGB1bnN0YWtlIChhbW91bnQ9JHthbW91bnR9KWAsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGtleVBhaXJTdGFrZVRlc3QgPSBnZXRLZXlQYWlyKGBzdGFrZS10ZXN0LWFtb3VudC0ke2Ftb3VudCAhPT0gdW5kZWZpbmVkfWApO1xuICAgICAgY29uc3QgYWRkcmVzcyA9IGtleVBhaXJTdGFrZVRlc3QuZ2V0QWRkcmVzcygpO1xuXG4gICAgICBiZWZvcmUoJ3N0YWtlIGNvaW5zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBhd2FpdCBmdW5kRnJvbUZhdWNldChmYXVjZXRVcmwsIGFkZHJlc3MpO1xuICAgICAgICBhd2FpdCBzdGFrZUFtb3VudChrZXlQYWlyU3Rha2VUZXN0LCAxMGU5KTtcbiAgICAgIH0pO1xuXG4gICAgICBpdChgY2FuIHVuc3Rha2VgLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGFjdGl2ZVN0YWtlZFN1aSA9IGF3YWl0IGdldFN0YWtlcyhjb25uLCBhZGRyZXNzLCB7XG4gICAgICAgICAgZmlsdGVyU3RhdHVzOiAnQWN0aXZlJyxcbiAgICAgICAgICBmaWx0ZXJNaW5WYWx1ZTogTUlOX1NUQUtJTkdfVEhSRVNIT0xEICsgKGFtb3VudCB8fCAwKSxcbiAgICAgICAgfSk7XG4gICAgICAgIGFzc2VydChhY3RpdmVTdGFrZWRTdWkubGVuZ3RoID4gMCwgJ05vIHN0YWtlZCBjb2lucyBmb3VuZCcpO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc3Rha2VkU3VpIG9mIGFjdGl2ZVN0YWtlZFN1aS5zbGljZSgwLCAzKSkge1xuICAgICAgICAgIGRlYnVnKCd1bnN0YWtpbmcnLCBzdGFrZWRTdWkpO1xuICAgICAgICAgIGNvbnN0IGJ1aWxkZXIgPSBnZXRCdWlsZGVyRmFjdG9yeSgndHN1aScpLmdldFVuc3Rha2luZ0J1aWxkZXIoKTtcbiAgICAgICAgICBjb25zdCBzdGFrZWRCZWZvcmUgPSBhd2FpdCBnZXRTdGFrZXMoY29ubiwgYWRkcmVzcyk7XG4gICAgICAgICAgY29uc3QgdHhiID0gYnVpbGRlclxuICAgICAgICAgICAgLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLldpdGhkcmF3U3Rha2UpXG4gICAgICAgICAgICAuc2VuZGVyKGFkZHJlc3MpXG4gICAgICAgICAgICAudW5zdGFrZSh7IHN0YWtlZFN1aTogYXdhaXQgcmVzb2x2ZVN0YWtlZFN1aShjb25uLCBzdGFrZWRTdWkpLCBhbW91bnQgfSlcbiAgICAgICAgICAgIC5nYXNEYXRhKGF3YWl0IGdldERlZmF1bHRHYXNEYXRhKGtleVBhaXJTdGFrZVRlc3QpKTtcbiAgICAgICAgICBhd2FpdCBzaWduQW5kU3VibWl0KGNvbm4sIGtleVBhaXJTdGFrZVRlc3QsIHR4Yik7XG5cbiAgICAgICAgICBhc3NlcnRSZWR1Y2VkU3Rha2Uoc3Rha2VkQmVmb3JlLCBhd2FpdCBnZXRTdGFrZXMoY29ubiwgYWRkcmVzcyksIHN0YWtlZFN1aSwgYW1vdW50KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICB0ZXN0VW5zdGFrZSh1bmRlZmluZWQpO1xuICB0ZXN0VW5zdGFrZSgxZTkpO1xufSk7XG4iXX0=Выполнить команду
Для локальной разработки. Не используйте в интернете!