PHP WebShell
Текущая директория: /opt/BitGoJS/modules/express/dist/test/unit/lightning
Просмотр файла: lightningInvoiceRoutes.test.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const sinon = require("sinon");
const should = require("should");
const lightningInvoiceRoutes_1 = require("../../../src/lightning/lightningInvoiceRoutes");
const abstract_lightning_1 = require("@bitgo/abstract-lightning");
const bitgo_1 = require("bitgo");
const assert = require("node:assert");
describe('Lightning Invoice Routes', () => {
let bitgo;
const coin = 'tlnbtc';
const mockRequestObject = (params) => {
const req = {};
req.body = params.body || {};
req.params = params.params || {};
req.query = params.query || {};
req.bitgo = params.bitgo;
return req;
};
afterEach(() => {
sinon.restore();
});
describe('Create Lightning Invoice', () => {
it('should successfully create a lightning invoice', async () => {
const inputParams = {
valueMsat: '10000',
memo: 'test invoice',
expiry: 3600,
};
const expectedResponse = {
valueMsat: 10000n,
memo: 'test invoice',
paymentHash: 'abc123',
invoice: 'lntb100u1p3h2jk3pp5yndyvx4zmv...',
walletId: 'testWalletId',
status: 'open',
expiresAt: new Date('2025-02-21T10:00:00.000Z'),
};
const createInvoiceSpy = sinon.stub().resolves(expectedResponse);
const mockLightningWallet = {
createInvoice: createInvoiceSpy,
};
// Mock the module import
const proxyquire = require('proxyquire');
const lightningRoutes = proxyquire('../../../src/lightning/lightningInvoiceRoutes', {
'@bitgo/abstract-lightning': {
getLightningWallet: () => mockLightningWallet,
},
});
const walletStub = {};
const coinStub = {
wallets: () => ({ get: sinon.stub().resolves(walletStub) }),
};
const stubBitgo = sinon.createStubInstance(bitgo_1.BitGo, { coin: coinStub });
const req = mockRequestObject({
params: { id: 'testWalletId', coin },
body: inputParams,
bitgo: stubBitgo,
});
const result = await lightningRoutes.handleCreateLightningInvoice(req);
should(result).deepEqual(abstract_lightning_1.Invoice.encode(expectedResponse));
const decodedResult = abstract_lightning_1.Invoice.decode(result);
assert('right' in decodedResult);
should(decodedResult.right).deepEqual(expectedResponse);
should(createInvoiceSpy).be.calledOnce();
const [firstArg] = createInvoiceSpy.getCall(0).args;
should(firstArg).have.property('valueMsat', BigInt(10000));
should(firstArg).have.property('memo', 'test invoice');
should(firstArg).have.property('expiry', 3600);
});
it('should fail when valueMsat is missing from request', async () => {
const inputParams = {
memo: 'test invoice',
expiry: 3600,
};
const req = mockRequestObject({
params: { id: 'testWalletId', coin },
body: inputParams,
});
req.bitgo = bitgo;
await should((0, lightningInvoiceRoutes_1.handleCreateLightningInvoice)(req)).be.rejectedWith(/^Invalid request body to create lightning invoice/);
});
});
describe('Pay Lightning Invoice', () => {
it('should successfully pay a lightning invoice', async () => {
const inputParams = {
invoice: 'lntb100u1p3h2jk3pp5yndyvx4zmv...',
amountMsat: '10000',
passphrase: 'wallet-password-12345',
randomParamThatWontBreakDecoding: 'randomValue',
};
const expectedResponse = {
paymentStatus: {
paymentHash: 'xyz789',
status: 'settled',
},
txRequestState: 'delivered',
txRequestId: '123',
};
const payInvoiceStub = sinon.stub().resolves(expectedResponse);
const mockLightningWallet = {
payInvoice: payInvoiceStub,
};
// Mock the module import
const proxyquire = require('proxyquire');
const lightningRoutes = proxyquire('../../../src/lightning/lightningInvoiceRoutes', {
'@bitgo/abstract-lightning': {
getLightningWallet: () => mockLightningWallet,
},
});
const walletStub = {};
const coinStub = {
wallets: () => ({ get: sinon.stub().resolves(walletStub) }),
};
const stubBitgo = sinon.createStubInstance(bitgo_1.BitGo, { coin: coinStub });
const req = mockRequestObject({
params: { id: 'testWalletId', coin },
body: inputParams,
bitgo: stubBitgo,
});
const result = await lightningRoutes.handlePayLightningInvoice(req);
should(result).deepEqual(expectedResponse);
should(payInvoiceStub).be.calledOnce();
const [firstArg] = payInvoiceStub.getCall(0).args;
// we decode the amountMsat string to bigint, it should be in bigint format when passed to payInvoice
should(firstArg).have.property('amountMsat', BigInt(10000));
should(firstArg).have.property('invoice', inputParams.invoice);
should(firstArg).have.property('passphrase', 'wallet-password-12345');
});
it('should throw an error if the passphrase is missing in the request params', async () => {
const inputParams = {
invoice: 'lntb100u1p3h2jk3pp5yndyvx4zmv...',
amountMsat: '10000',
};
const req = mockRequestObject({
params: { id: 'testWalletId', coin },
body: inputParams,
});
req.bitgo = bitgo;
await should((0, lightningInvoiceRoutes_1.handlePayLightningInvoice)(req)).be.rejectedWith('Invalid request body to pay lightning invoice');
});
it('should throw an error if the invoice is missing in the request params', async () => {
const inputParams = {
amountMsat: '10000',
passphrase: 'wallet-password-12345',
};
const req = mockRequestObject({
params: { id: 'testWalletId', coin },
body: inputParams,
});
req.bitgo = bitgo;
await should((0, lightningInvoiceRoutes_1.handlePayLightningInvoice)(req)).be.rejectedWith(/^Invalid request body to pay lightning invoice/);
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRuaW5nSW52b2ljZVJvdXRlcy50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdGVzdC91bml0L2xpZ2h0bmluZy9saWdodG5pbmdJbnZvaWNlUm91dGVzLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSwrQkFBK0I7QUFDL0IsaUNBQWlDO0FBRWpDLDBGQUF3SDtBQUN4SCxrRUFBd0U7QUFDeEUsaUNBQThCO0FBQzlCLHNDQUFzQztBQUV0QyxRQUFRLENBQUMsMEJBQTBCLEVBQUUsR0FBRyxFQUFFO0lBQ3hDLElBQUksS0FBSyxDQUFDO0lBQ1YsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDO0lBRXRCLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxNQUE4RCxFQUFFLEVBQUU7UUFDM0YsTUFBTSxHQUFHLEdBQTZCLEVBQUUsQ0FBQztRQUN6QyxHQUFHLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQzdCLEdBQUcsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUM7UUFDakMsR0FBRyxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUMvQixHQUFHLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUM7UUFDekIsT0FBTyxHQUFzQixDQUFDO0lBQ2hDLENBQUMsQ0FBQztJQUVGLFNBQVMsQ0FBQyxHQUFHLEVBQUU7UUFDYixLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDbEIsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsMEJBQTBCLEVBQUUsR0FBRyxFQUFFO1FBQ3hDLEVBQUUsQ0FBQyxnREFBZ0QsRUFBRSxLQUFLLElBQUksRUFBRTtZQUM5RCxNQUFNLFdBQVcsR0FBRztnQkFDbEIsU0FBUyxFQUFFLE9BQU87Z0JBQ2xCLElBQUksRUFBRSxjQUFjO2dCQUNwQixNQUFNLEVB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cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgc2lub24gZnJvbSAnc2lub24nO1xuaW1wb3J0ICogYXMgc2hvdWxkIGZyb20gJ3Nob3VsZCc7XG5pbXBvcnQgKiBhcyBleHByZXNzIGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHsgaGFuZGxlUGF5TGlnaHRuaW5nSW52b2ljZSwgaGFuZGxlQ3JlYXRlTGlnaHRuaW5nSW52b2ljZSB9IGZyb20gJy4uLy4uLy4uL3NyYy9saWdodG5pbmcvbGlnaHRuaW5nSW52b2ljZVJvdXRlcyc7XG5pbXBvcnQgeyBJbnZvaWNlLCBQYXlJbnZvaWNlUmVzcG9uc2UgfSBmcm9tICdAYml0Z28vYWJzdHJhY3QtbGlnaHRuaW5nJztcbmltcG9ydCB7IEJpdEdvIH0gZnJvbSAnYml0Z28nO1xuaW1wb3J0ICogYXMgYXNzZXJ0IGZyb20gJ25vZGU6YXNzZXJ0JztcblxuZGVzY3JpYmUoJ0xpZ2h0bmluZyBJbnZvaWNlIFJvdXRlcycsICgpID0+IHtcbiAgbGV0IGJpdGdvO1xuICBjb25zdCBjb2luID0gJ3RsbmJ0Yyc7XG5cbiAgY29uc3QgbW9ja1JlcXVlc3RPYmplY3QgPSAocGFyYW1zOiB7IGJvZHk/OiBhbnk7IHBhcmFtcz86IGFueTsgcXVlcnk/OiBhbnk7IGJpdGdvPzogYW55IH0pID0+IHtcbiAgICBjb25zdCByZXE6IFBhcnRpYWw8ZXhwcmVzcy5SZXF1ZXN0PiA9IHt9O1xuICAgIHJlcS5ib2R5ID0gcGFyYW1zLmJvZHkgfHwge307XG4gICAgcmVxLnBhcmFtcyA9IHBhcmFtcy5wYXJhbXMgfHwge307XG4gICAgcmVxLnF1ZXJ5ID0gcGFyYW1zLnF1ZXJ5IHx8IHt9O1xuICAgIHJlcS5iaXRnbyA9IHBhcmFtcy5iaXRnbztcbiAgICByZXR1cm4gcmVxIGFzIGV4cHJlc3MuUmVxdWVzdDtcbiAgfTtcblxuICBhZnRlckVhY2goKCkgPT4ge1xuICAgIHNpbm9uLnJlc3RvcmUoKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0NyZWF0ZSBMaWdodG5pbmcgSW52b2ljZScsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHN1Y2Nlc3NmdWxseSBjcmVhdGUgYSBsaWdodG5pbmcgaW52b2ljZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGlucHV0UGFyYW1zID0ge1xuICAgICAgICB2YWx1ZU1zYXQ6ICcxMDAwMCcsXG4gICAgICAgIG1lbW86ICd0ZXN0IGludm9pY2UnLFxuICAgICAgICBleHBpcnk6IDM2MDAsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBleHBlY3RlZFJlc3BvbnNlID0ge1xuICAgICAgICB2YWx1ZU1zYXQ6IDEwMDAwbixcbiAgICAgICAgbWVtbzogJ3Rlc3QgaW52b2ljZScsXG4gICAgICAgIHBheW1lbnRIYXNoOiAnYWJjMTIzJyxcbiAgICAgICAgaW52b2ljZTogJ2xudGIxMDB1MXAzaDJqazNwcDV5bmR5dng0em12Li4uJyxcbiAgICAgICAgd2FsbGV0SWQ6ICd0ZXN0V2FsbGV0SWQnLFxuICAgICAgICBzdGF0dXM6ICdvcGVuJyBhcyBjb25zdCxcbiAgICAgICAgZXhwaXJlc0F0OiBuZXcgRGF0ZSgnMjAyNS0wMi0yMVQxMDowMDowMC4wMDBaJyksXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBjcmVhdGVJbnZvaWNlU3B5ID0gc2lub24uc3R1YigpLnJlc29sdmVzKGV4cGVjdGVkUmVzcG9uc2UpO1xuICAgICAgY29uc3QgbW9ja0xpZ2h0bmluZ1dhbGxldCA9IHtcbiAgICAgICAgY3JlYXRlSW52b2ljZTogY3JlYXRlSW52b2ljZVNweSxcbiAgICAgIH07XG5cbiAgICAgIC8vIE1vY2sgdGhlIG1vZHVsZSBpbXBvcnRcbiAgICAgIGNvbnN0IHByb3h5cXVpcmUgPSByZXF1aXJlKCdwcm94eXF1aXJlJyk7XG4gICAgICBjb25zdCBsaWdodG5pbmdSb3V0ZXMgPSBwcm94eXF1aXJlKCcuLi8uLi8uLi9zcmMvbGlnaHRuaW5nL2xpZ2h0bmluZ0ludm9pY2VSb3V0ZXMnLCB7XG4gICAgICAgICdAYml0Z28vYWJzdHJhY3QtbGlnaHRuaW5nJzoge1xuICAgICAgICAgIGdldExpZ2h0bmluZ1dhbGxldDogKCkgPT4gbW9ja0xpZ2h0bmluZ1dhbGxldCxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB3YWxsZXRTdHViID0ge307XG4gICAgICBjb25zdCBjb2luU3R1YiA9IHtcbiAgICAgICAgd2FsbGV0czogKCkgPT4gKHsgZ2V0OiBzaW5vbi5zdHViKCkucmVzb2x2ZXMod2FsbGV0U3R1YikgfSksXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBzdHViQml0Z28gPSBzaW5vbi5jcmVhdGVTdHViSW5zdGFuY2UoQml0R28gYXMgYW55LCB7IGNvaW46IGNvaW5TdHViIH0pO1xuXG4gICAgICBjb25zdCByZXEgPSBtb2NrUmVxdWVzdE9iamVjdCh7XG4gICAgICAgIHBhcmFtczogeyBpZDogJ3Rlc3RXYWxsZXRJZCcsIGNvaW4gfSxcbiAgICAgICAgYm9keTogaW5wdXRQYXJhbXMsXG4gICAgICAgIGJpdGdvOiBzdHViQml0Z28sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgbGlnaHRuaW5nUm91dGVzLmhhbmRsZUNyZWF0ZUxpZ2h0bmluZ0ludm9pY2UocmVxKTtcblxuICAgICAgc2hvdWxkKHJlc3VsdCkuZGVlcEVxdWFsKEludm9pY2UuZW5jb2RlKGV4cGVjdGVkUmVzcG9uc2UpKTtcbiAgICAgIGNvbnN0IGRlY29kZWRSZXN1bHQgPSBJbnZvaWNlLmRlY29kZShyZXN1bHQpO1xuICAgICAgYXNzZXJ0KCdyaWdodCcgaW4gZGVjb2RlZFJlc3VsdCk7XG4gICAgICBzaG91bGQoZGVjb2RlZFJlc3VsdC5yaWdodCkuZGVlcEVxdWFsKGV4cGVjdGVkUmVzcG9uc2UpO1xuICAgICAgc2hvdWxkKGNyZWF0ZUludm9pY2VTcHkpLmJlLmNhbGxlZE9uY2UoKTtcbiAgICAgIGNvbnN0IFtmaXJzdEFyZ10gPSBjcmVhdGVJbnZvaWNlU3B5LmdldENhbGwoMCkuYXJncztcblxuICAgICAgc2hvdWxkKGZpcnN0QXJnKS5oYXZlLnByb3BlcnR5KCd2YWx1ZU1zYXQnLCBCaWdJbnQoMTAwMDApKTtcbiAgICAgIHNob3VsZChmaXJzdEFyZykuaGF2ZS5wcm9wZXJ0eSgnbWVtbycsICd0ZXN0IGludm9pY2UnKTtcbiAgICAgIHNob3VsZChmaXJzdEFyZykuaGF2ZS5wcm9wZXJ0eSgnZXhwaXJ5JywgMzYwMCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgd2hlbiB2YWx1ZU1zYXQgaXMgbWlzc2luZyBmcm9tIHJlcXVlc3QnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBpbnB1dFBhcmFtcyA9IHtcbiAgICAgICAgbWVtbzogJ3Rlc3QgaW52b2ljZScsXG4gICAgICAgIGV4cGlyeTogMzYwMCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlcSA9IG1vY2tSZXF1ZXN0T2JqZWN0KHtcbiAgICAgICAgcGFyYW1zOiB7IGlkOiAndGVzdFdhbGxldElkJywgY29pbiB9LFxuICAgICAgICBib2R5OiBpbnB1dFBhcmFtcyxcbiAgICAgIH0pO1xuICAgICAgcmVxLmJpdGdvID0gYml0Z287XG5cbiAgICAgIGF3YWl0IHNob3VsZChoYW5kbGVDcmVhdGVMaWdodG5pbmdJbnZvaWNlKHJlcSkpLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgL15JbnZhbGlkIHJlcXVlc3QgYm9keSB0byBjcmVhdGUgbGlnaHRuaW5nIGludm9pY2UvXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUGF5IExpZ2h0bmluZyBJbnZvaWNlJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgc3VjY2Vzc2Z1bGx5IHBheSBhIGxpZ2h0bmluZyBpbnZvaWNlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgaW5wdXRQYXJhbXMgPSB7XG4gICAgICAgIGludm9pY2U6ICdsbnRiMTAwdTFwM2gyamszcHA1eW5keXZ4NHptdi4uLicsXG4gICAgICAgIGFtb3VudE1zYXQ6ICcxMDAwMCcsXG4gICAgICAgIHBhc3NwaHJhc2U6ICd3YWxsZXQtcGFzc3dvcmQtMTIzNDUnLFxuICAgICAgICByYW5kb21QYXJhbVRoYXRXb250QnJlYWtEZWNvZGluZzogJ3JhbmRvbVZhbHVlJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGV4cGVjdGVkUmVzcG9uc2U6IFBheUludm9pY2VSZXNwb25zZSA9IHtcbiAgICAgICAgcGF5bWVudFN0YXR1czoge1xuICAgICAgICAgIHBheW1lbnRIYXNoOiAneHl6Nzg5JyxcbiAgICAgICAgICBzdGF0dXM6ICdzZXR0bGVkJyxcbiAgICAgICAgfSxcbiAgICAgICAgdHhSZXF1ZXN0U3RhdGU6ICdkZWxpdmVyZWQnLFxuICAgICAgICB0eFJlcXVlc3RJZDogJzEyMycsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBwYXlJbnZvaWNlU3R1YiA9IHNpbm9uLnN0dWIoKS5yZXNvbHZlcyhleHBlY3RlZFJlc3BvbnNlKTtcbiAgICAgIGNvbnN0IG1vY2tMaWdodG5pbmdXYWxsZXQgPSB7XG4gICAgICAgIHBheUludm9pY2U6IHBheUludm9pY2VTdHViLFxuICAgICAgfTtcblxuICAgICAgLy8gTW9jayB0aGUgbW9kdWxlIGltcG9ydFxuICAgICAgY29uc3QgcHJveHlxdWlyZSA9IHJlcXVpcmUoJ3Byb3h5cXVpcmUnKTtcbiAgICAgIGNvbnN0IGxpZ2h0bmluZ1JvdXRlcyA9IHByb3h5cXVpcmUoJy4uLy4uLy4uL3NyYy9saWdodG5pbmcvbGlnaHRuaW5nSW52b2ljZVJvdXRlcycsIHtcbiAgICAgICAgJ0BiaXRnby9hYnN0cmFjdC1saWdodG5pbmcnOiB7XG4gICAgICAgICAgZ2V0TGlnaHRuaW5nV2FsbGV0OiAoKSA9PiBtb2NrTGlnaHRuaW5nV2FsbGV0LFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHdhbGxldFN0dWIgPSB7fTtcbiAgICAgIGNvbnN0IGNvaW5TdHViID0ge1xuICAgICAgICB3YWxsZXRzOiAoKSA9PiAoeyBnZXQ6IHNpbm9uLnN0dWIoKS5yZXNvbHZlcyh3YWxsZXRTdHViKSB9KSxcbiAgICAgIH07XG4gICAgICBjb25zdCBzdHViQml0Z28gPSBzaW5vbi5jcmVhdGVTdHViSW5zdGFuY2UoQml0R28gYXMgYW55LCB7IGNvaW46IGNvaW5TdHViIH0pO1xuXG4gICAgICBjb25zdCByZXEgPSBtb2NrUmVxdWVzdE9iamVjdCh7XG4gICAgICAgIHBhcmFtczogeyBpZDogJ3Rlc3RXYWxsZXRJZCcsIGNvaW4gfSxcbiAgICAgICAgYm9keTogaW5wdXRQYXJhbXMsXG4gICAgICAgIGJpdGdvOiBzdHViQml0Z28sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgbGlnaHRuaW5nUm91dGVzLmhhbmRsZVBheUxpZ2h0bmluZ0ludm9pY2UocmVxKTtcblxuICAgICAgc2hvdWxkKHJlc3VsdCkuZGVlcEVxdWFsKGV4cGVjdGVkUmVzcG9uc2UpO1xuICAgICAgc2hvdWxkKHBheUludm9pY2VTdHViKS5iZS5jYWxsZWRPbmNlKCk7XG4gICAgICBjb25zdCBbZmlyc3RBcmddID0gcGF5SW52b2ljZVN0dWIuZ2V0Q2FsbCgwKS5hcmdzO1xuXG4gICAgICAvLyB3ZSBkZWNvZGUgdGhlIGFtb3VudE1zYXQgc3RyaW5nIHRvIGJpZ2ludCwgaXQgc2hvdWxkIGJlIGluIGJpZ2ludCBmb3JtYXQgd2hlbiBwYXNzZWQgdG8gcGF5SW52b2ljZVxuICAgICAgc2hvdWxkKGZpcnN0QXJnKS5oYXZlLnByb3BlcnR5KCdhbW91bnRNc2F0JywgQmlnSW50KDEwMDAwKSk7XG4gICAgICBzaG91bGQoZmlyc3RBcmcpLmhhdmUucHJvcGVydHkoJ2ludm9pY2UnLCBpbnB1dFBhcmFtcy5pbnZvaWNlKTtcbiAgICAgIHNob3VsZChmaXJzdEFyZykuaGF2ZS5wcm9wZXJ0eSgncGFzc3BocmFzZScsICd3YWxsZXQtcGFzc3dvcmQtMTIzNDUnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgYW4gZXJyb3IgaWYgdGhlIHBhc3NwaHJhc2UgaXMgbWlzc2luZyBpbiB0aGUgcmVxdWVzdCBwYXJhbXMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBpbnB1dFBhcmFtcyA9IHtcbiAgICAgICAgaW52b2ljZTogJ2xudGIxMDB1MXAzaDJqazNwcDV5bmR5dng0em12Li4uJyxcbiAgICAgICAgYW1vdW50TXNhdDogJzEwMDAwJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlcSA9IG1vY2tSZXF1ZXN0T2JqZWN0KHtcbiAgICAgICAgcGFyYW1zOiB7IGlkOiAndGVzdFdhbGxldElkJywgY29pbiB9LFxuICAgICAgICBib2R5OiBpbnB1dFBhcmFtcyxcbiAgICAgIH0pO1xuICAgICAgcmVxLmJpdGdvID0gYml0Z287XG5cbiAgICAgIGF3YWl0IHNob3VsZChoYW5kbGVQYXlMaWdodG5pbmdJbnZvaWNlKHJlcSkpLmJlLnJlamVjdGVkV2l0aCgnSW52YWxpZCByZXF1ZXN0IGJvZHkgdG8gcGF5IGxpZ2h0bmluZyBpbnZvaWNlJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGFuIGVycm9yIGlmIHRoZSBpbnZvaWNlIGlzIG1pc3NpbmcgaW4gdGhlIHJlcXVlc3QgcGFyYW1zJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgaW5wdXRQYXJhbXMgPSB7XG4gICAgICAgIGFtb3VudE1zYXQ6ICcxMDAwMCcsXG4gICAgICAgIHBhc3NwaHJhc2U6ICd3YWxsZXQtcGFzc3dvcmQtMTIzNDUnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgcmVxID0gbW9ja1JlcXVlc3RPYmplY3Qoe1xuICAgICAgICBwYXJhbXM6IHsgaWQ6ICd0ZXN0V2FsbGV0SWQnLCBjb2luIH0sXG4gICAgICAgIGJvZHk6IGlucHV0UGFyYW1zLFxuICAgICAgfSk7XG4gICAgICByZXEuYml0Z28gPSBiaXRnbztcblxuICAgICAgYXdhaXQgc2hvdWxkKGhhbmRsZVBheUxpZ2h0bmluZ0ludm9pY2UocmVxKSkuYmUucmVqZWN0ZWRXaXRoKC9eSW52YWxpZCByZXF1ZXN0IGJvZHkgdG8gcGF5IGxpZ2h0bmluZyBpbnZvaWNlLyk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=Выполнить команду
Для локальной разработки. Не используйте в интернете!