PHP WebShell

Текущая директория: /opt/BitGoJS/modules/sdk-coin-mantra/dist/test/unit

Просмотр файла: mantra.js

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const sdk_api_1 = require("@bitgo/sdk-api");
const sdk_test_1 = require("@bitgo/sdk-test");
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const sinon_1 = __importDefault(require("sinon"));
const src_1 = require("../../src");
const utils_1 = __importDefault(require("../../src/lib/utils"));
const mantra_1 = require("../resources/mantra");
const should = require("should");
describe('Mantra', function () {
    let bitgo;
    let basecoin;
    before(function () {
        bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
        bitgo.safeRegister('mantra', src_1.Mantra.createInstance);
        bitgo.safeRegister('tmantra', src_1.Tmantra.createInstance);
        bitgo.initializeTestVars();
        basecoin = bitgo.coin('tmantra');
    });
    it('should return the right info', function () {
        const mantra = bitgo.coin('mantra');
        const tmantra = bitgo.coin('tmantra');
        mantra.getChain().should.equal('mantra');
        mantra.getFamily().should.equal('mantra');
        mantra.getFullName().should.equal('Mantra');
        mantra.getBaseFactor().should.equal(1e6);
        tmantra.getChain().should.equal('tmantra');
        tmantra.getFamily().should.equal('mantra');
        tmantra.getFullName().should.equal('Testnet Mantra');
        tmantra.getBaseFactor().should.equal(1e6);
    });
    describe('Address Validation', () => {
        it('should get address details without memoId', function () {
            const addressDetails = basecoin.getAddressDetails(mantra_1.address.noMemoIdAddress);
            addressDetails.address.should.equal(mantra_1.address.noMemoIdAddress);
            should.not.exist(addressDetails.memoId);
        });
        it('should get address details with memoId', function () {
            const addressDetails = basecoin.getAddressDetails(mantra_1.address.validMemoIdAddress);
            addressDetails.address.should.equal(mantra_1.address.validMemoIdAddress.split('?')[0]);
            addressDetails.memoId.should.equal('2');
            const addressDetails2 = basecoin.getAddressDetails(mantra_1.address.validMemoIdAddress2);
            addressDetails2.address.should.equal(mantra_1.address.validMemoIdAddress2.split('?')[0]);
            addressDetails2.memoId.should.equal('xyz123');
        });
        it('should throw on invalid memo id address', () => {
            (() => {
                basecoin.getAddressDetails(mantra_1.address.invalidMemoIdAddress);
            }).should.throw();
            (() => {
                basecoin.getAddressDetails(mantra_1.address.invalidMemoIdAddress2);
            }).should.throw();
        });
        it('should throw on multiple memo id address', () => {
            (() => {
                basecoin.getAddressDetails(mantra_1.address.multipleMemoIdAddress);
            }).should.throw();
        });
        it('should validate wallet receive address', async function () {
            const receiveAddress = {
                address: 'mantra178596utuac8l9tkj25afvwz8l7d7684kkswjlj?memoId=7',
                coinSpecific: {
                    rootAddress: 'mantra178596utuac8l9tkj25afvwz8l7d7684kkswjlj',
                    memoID: '7',
                },
            };
            const isValid = await basecoin.isWalletAddress(receiveAddress);
            isValid.should.equal(true);
        });
        it('should validate account addresses correctly', () => {
            should.equal(utils_1.default.isValidAddress(mantra_1.address.address1), true);
            should.equal(utils_1.default.isValidAddress(mantra_1.address.address2), true);
            should.equal(utils_1.default.isValidAddress(mantra_1.address.address3), false);
            should.equal(utils_1.default.isValidAddress(mantra_1.address.address4), false);
            should.equal(utils_1.default.isValidAddress('dfjk35y'), false);
            should.equal(utils_1.default.isValidAddress(undefined), false);
            should.equal(utils_1.default.isValidAddress(''), false);
            should.equal(utils_1.default.isValidAddress(mantra_1.address.validMemoIdAddress), true);
            should.equal(utils_1.default.isValidAddress(mantra_1.address.validMemoIdAddress2), true);
            should.equal(utils_1.default.isValidAddress(mantra_1.address.multipleMemoIdAddress), false);
        });
        it('should validate validator addresses correctly', () => {
            should.equal(utils_1.default.isValidValidatorAddress(mantra_1.address.validatorAddress1), true);
            should.equal(utils_1.default.isValidValidatorAddress(mantra_1.address.validatorAddress2), true);
            should.equal(utils_1.default.isValidValidatorAddress(mantra_1.address.validatorAddress3), false);
            should.equal(utils_1.default.isValidValidatorAddress(mantra_1.address.validatorAddress4), false);
            should.equal(utils_1.default.isValidValidatorAddress('dfjk35y'), false);
            should.equal(utils_1.default.isValidValidatorAddress(undefined), false);
            should.equal(utils_1.default.isValidValidatorAddress(''), false);
        });
    });
    describe('Verify transaction: ', () => {
        it('should succeed to verify transaction', async function () {
            const txPrebuild = {
                txHex: mantra_1.TEST_SEND_TX.signedTxBase64,
                txInfo: {},
            };
            const txParams = {
                recipients: [
                    {
                        address: mantra_1.TEST_SEND_TX.recipient,
                        amount: mantra_1.TEST_SEND_TX.sendAmount,
                    },
                ],
            };
            const verification = {};
            const isTransactionVerified = await basecoin.verifyTransaction({ txParams, txPrebuild, verification });
            isTransactionVerified.should.equal(true);
        });
        it('should succeed to verify sendMany transaction', async function () {
            const txPrebuild = {
                txHex: mantra_1.TEST_SEND_MANY_TX.signedTxBase64,
                txInfo: {},
            };
            const txParams = {
                recipients: [
                    {
                        address: 'mantra18favpsj0s8hfy2j00e89pqmpp9ndfl03a6a7vj',
                        amount: '10000',
                    },
                    {
                        address: 'mantra1m493txuc2jh0zz842wjsamht6hsy7t506t40rq',
                        amount: '10000',
                    },
                ],
            };
            const verification = {};
            const isTransactionVerified = await basecoin.verifyTransaction({ txParams, txPrebuild, verification });
            isTransactionVerified.should.equal(true);
        });
        it('should fail to verify transaction with invalid param', async function () {
            const txPrebuild = {};
            const txParams = { recipients: undefined };
            await basecoin
                .verifyTransaction({
                txParams,
                txPrebuild,
            })
                .should.rejectedWith('missing required tx prebuild property txHex');
        });
    });
    describe('Explain Transaction: ', () => {
        it('should explain a transfer transaction', async function () {
            const explainedTransaction = await basecoin.explainTransaction({
                txHex: mantra_1.TEST_SEND_TX.signedTxBase64,
            });
            explainedTransaction.should.deepEqual({
                displayOrder: ['id', 'outputs', 'outputAmount', 'changeOutputs', 'changeAmount', 'fee', 'type'],
                id: mantra_1.TEST_SEND_TX.hash,
                outputs: [
                    {
                        address: mantra_1.TEST_SEND_TX.recipient,
                        amount: mantra_1.TEST_SEND_TX.sendAmount,
                    },
                ],
                outputAmount: mantra_1.TEST_SEND_TX.sendAmount,
                changeOutputs: [],
                changeAmount: '0',
                fee: { fee: mantra_1.TEST_SEND_TX.gasBudget.amount[0].amount },
                type: 0,
            });
        });
        it('should explain sendMany transfer transaction', async function () {
            const explainedTransaction = await basecoin.explainTransaction({
                txHex: mantra_1.TEST_SEND_MANY_TX.signedTxBase64,
            });
            explainedTransaction.should.deepEqual({
                displayOrder: ['id', 'outputs', 'outputAmount', 'changeOutputs', 'changeAmount', 'fee', 'type'],
                id: mantra_1.TEST_SEND_MANY_TX.hash,
                outputs: [
                    {
                        address: 'mantra18favpsj0s8hfy2j00e89pqmpp9ndfl03a6a7vj',
                        amount: '10000',
                    },
                    {
                        address: 'mantra1m493txuc2jh0zz842wjsamht6hsy7t506t40rq',
                        amount: '10000',
                    },
                ],
                outputAmount: '20000',
                changeOutputs: [],
                changeAmount: '0',
                fee: { fee: mantra_1.TEST_SEND_MANY_TX.gasBudget.amount[0].amount },
                type: 0,
            });
        });
        it('should explain a transfer transaction with memo', async function () {
            const explainedTransaction = await basecoin.explainTransaction({
                txHex: mantra_1.TEST_TX_WITH_MEMO.signedTxBase64,
            });
            explainedTransaction.should.deepEqual({
                displayOrder: ['id', 'outputs', 'outputAmount', 'changeOutputs', 'changeAmount', 'fee', 'type'],
                id: mantra_1.TEST_TX_WITH_MEMO.hash,
                outputs: [
                    {
                        address: mantra_1.TEST_TX_WITH_MEMO.to,
                        amount: mantra_1.TEST_TX_WITH_MEMO.sendAmount,
                        memo: mantra_1.TEST_TX_WITH_MEMO.memo,
                    },
                ],
                outputAmount: mantra_1.TEST_TX_WITH_MEMO.sendAmount,
                changeOutputs: [],
                changeAmount: '0',
                fee: { fee: mantra_1.TEST_TX_WITH_MEMO.gasBudget.amount[0].amount },
                type: 0,
            });
        });
        it('should fail to explain transaction with missing params', async function () {
            try {
                await basecoin.explainTransaction({});
            }
            catch (error) {
                should.equal(error.message, 'missing required txHex parameter');
            }
        });
        it('should fail to explain transaction with invalid params', async function () {
            try {
                await basecoin.explainTransaction({ txHex: 'randomString' });
            }
            catch (error) {
                should.equal(error.message.startsWith('Invalid transaction:'), true);
            }
        });
    });
    describe('Parse Transactions: ', () => {
        const transferInputsResponse = {
            address: mantra_1.TEST_SEND_TX.recipient,
            amount: new bignumber_js_1.default(mantra_1.TEST_SEND_TX.sendAmount).plus(mantra_1.TEST_SEND_TX.gasBudget.amount[0].amount).toFixed(),
        };
        const transferOutputsResponse = {
            address: mantra_1.TEST_SEND_TX.recipient,
            amount: mantra_1.TEST_SEND_TX.sendAmount,
        };
        it('should parse a transfer transaction', async function () {
            const parsedTransaction = await basecoin.parseTransaction({ txHex: mantra_1.TEST_SEND_TX.signedTxBase64 });
            parsedTransaction.should.deepEqual({
                inputs: [transferInputsResponse],
                outputs: [transferOutputsResponse],
            });
        });
        it('should fail to parse a transfer transaction when explainTransaction response is undefined', async function () {
            const stub = sinon_1.default.stub(src_1.Mantra.prototype, 'explainTransaction');
            stub.resolves(undefined);
            await basecoin
                .parseTransaction({ txHex: mantra_1.TEST_SEND_TX.signedTxBase64 })
                .should.be.rejectedWith('Invalid transaction');
            stub.restore();
        });
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFudHJhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L21hbnRyYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDRDQUEwQztBQUMxQyw4Q0FBMEQ7QUFDMUQsZ0VBQXFDO0FBQ3JDLGtEQUEwQjtBQUMxQixtQ0FBNEM7QUFDNUMsZ0VBQXdDO0FBQ3hDLGdEQUFrRztBQUNsRyxpQ0FBa0M7QUFFbEMsUUFBUSxDQUFDLFFBQVEsRUFBRTtJQUNqQixJQUFJLEtBQW1CLENBQUM7SUFDeEIsSUFBSSxRQUFRLENBQUM7SUFDYixNQUFNLENBQUM7UUFDTCxLQUFLLEdBQUcsb0JBQVMsQ0FBQyxRQUFRLENBQUMsa0JBQVEsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3RELEtBQUssQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLFlBQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNwRCxLQUFLLENBQUMsWUFBWSxDQUFDLFNBQVMsRUFBRSxhQUFPLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDdEQsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDM0IsUUFBUSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDbkMsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsOEJBQThCLEVBQUU7UUFDakMsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNwQyxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRXRDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3pDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzFDLE1BQU0sQ0FB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QkFBWSxDQUFDLGNBQWMsRUFBRSxDQUFDO2lCQUN4RCxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1lBQ2pELElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNqQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby9zZGstYXBpJztcbmltcG9ydCB7IFRlc3RCaXRHbywgVGVzdEJpdEdvQVBJIH0gZnJvbSAnQGJpdGdvL3Nkay10ZXN0JztcbmltcG9ydCBCaWdOdW1iZXIgZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCBzaW5vbiBmcm9tICdzaW5vbic7XG5pbXBvcnQgeyBNYW50cmEsIFRtYW50cmEgfSBmcm9tICcuLi8uLi9zcmMnO1xuaW1wb3J0IHV0aWxzIGZyb20gJy4uLy4uL3NyYy9saWIvdXRpbHMnO1xuaW1wb3J0IHsgVEVTVF9TRU5EX01BTllfVFgsIFRFU1RfU0VORF9UWCwgVEVTVF9UWF9XSVRIX01FTU8sIGFkZHJlc3MgfSBmcm9tICcuLi9yZXNvdXJjZXMvbWFudHJhJztcbmltcG9ydCBzaG91bGQgPSByZXF1aXJlKCdzaG91bGQnKTtcblxuZGVzY3JpYmUoJ01hbnRyYScsIGZ1bmN0aW9uICgpIHtcbiAgbGV0IGJpdGdvOiBUZXN0Qml0R29BUEk7XG4gIGxldCBiYXNlY29pbjtcbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICBiaXRnby5zYWZlUmVnaXN0ZXIoJ21hbnRyYScsIE1hbnRyYS5jcmVhdGVJbnN0YW5jZSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCd0bWFudHJhJywgVG1hbnRyYS5jcmVhdGVJbnN0YW5jZSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgYmFzZWNvaW4gPSBiaXRnby5jb2luKCd0bWFudHJhJyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIHRoZSByaWdodCBpbmZvJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IG1hbnRyYSA9IGJpdGdvLmNvaW4oJ21hbnRyYScpO1xuICAgIGNvbnN0IHRtYW50cmEgPSBiaXRnby5jb2luKCd0bWFudHJhJyk7XG5cbiAgICBtYW50cmEuZ2V0Q2hhaW4oKS5zaG91bGQuZXF1YWwoJ21hbnRyYScpO1xuICAgIG1hbnRyYS5nZXRGYW1pbHkoKS5zaG91bGQuZXF1YWwoJ21hbnRyYScpO1xuICAgIG1hbnRyYS5nZXRGdWxsTmFtZSgpLnNob3VsZC5lcXVhbCgnTWFudHJhJyk7XG4gICAgbWFudHJhLmdldEJhc2VGYWN0b3IoKS5zaG91bGQuZXF1YWwoMWU2KTtcblxuICAgIHRtYW50cmEuZ2V0Q2hhaW4oKS5zaG91bGQuZXF1YWwoJ3RtYW50cmEnKTtcbiAgICB0bWFudHJhLmdldEZhbWlseSgpLnNob3VsZC5lcXVhbCgnbWFudHJhJyk7XG4gICAgdG1hbnRyYS5nZXRGdWxsTmFtZSgpLnNob3VsZC5lcXVhbCgnVGVzdG5ldCBNYW50cmEnKTtcbiAgICB0bWFudHJhLmdldEJhc2VGYWN0b3IoKS5zaG91bGQuZXF1YWwoMWU2KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0FkZHJlc3MgVmFsaWRhdGlvbicsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGdldCBhZGRyZXNzIGRldGFpbHMgd2l0aG91dCBtZW1vSWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhZGRyZXNzRGV0YWlscyA9IGJhc2Vjb2luLmdldEFkZHJlc3NEZXRhaWxzKGFkZHJlc3Mubm9NZW1vSWRBZGRyZXNzKTtcbiAgICAgIGFkZHJlc3NEZXRhaWxzLmFkZHJlc3Muc2hvdWxkLmVxdWFsKGFkZHJlc3Mubm9NZW1vSWRBZGRyZXNzKTtcbiAgICAgIHNob3VsZC5ub3QuZXhpc3QoYWRkcmVzc0RldGFpbHMubWVtb0lkKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZ2V0IGFkZHJlc3MgZGV0YWlscyB3aXRoIG1lbW9JZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGFkZHJlc3NEZXRhaWxzID0gYmFzZWNvaW4uZ2V0QWRkcmVzc0RldGFpbHMoYWRkcmVzcy52YWxpZE1lbW9JZEFkZHJlc3MpO1xuICAgICAgYWRkcmVzc0RldGFpbHMuYWRkcmVzcy5zaG91bGQuZXF1YWwoYWRkcmVzcy52YWxpZE1lbW9JZEFkZHJlc3Muc3BsaXQoJz8nKVswXSk7XG4gICAgICBhZGRyZXNzRGV0YWlscy5tZW1vSWQuc2hvdWxkLmVxdWFsKCcyJyk7XG5cbiAgICAgIGNvbnN0IGFkZHJlc3NEZXRhaWxzMiA9IGJhc2Vjb2luLmdldEFkZHJlc3NEZXRhaWxzKGFkZHJlc3MudmFsaWRNZW1vSWRBZGRyZXNzMik7XG4gICAgICBhZGRyZXNzRGV0YWlsczIuYWRkcmVzcy5zaG91bGQuZXF1YWwoYWRkcmVzcy52YWxpZE1lbW9JZEFkZHJlc3MyLnNwbGl0KCc/JylbMF0pO1xuICAgICAgYWRkcmVzc0RldGFpbHMyLm1lbW9JZC5zaG91bGQuZXF1YWwoJ3h5ejEyMycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBvbiBpbnZhbGlkIG1lbW8gaWQgYWRkcmVzcycsICgpID0+IHtcbiAgICAgICgoKSA9PiB7XG4gICAgICAgIGJhc2Vjb2luLmdldEFkZHJlc3NEZXRhaWxzKGFkZHJlc3MuaW52YWxpZE1lbW9JZEFkZHJlc3MpO1xuICAgICAgfSkuc2hvdWxkLnRocm93KCk7XG5cbiAgICAgICgoKSA9PiB7XG4gICAgICAgIGJhc2Vjb2luLmdldEFkZHJlc3NEZXRhaWxzKGFkZHJlc3MuaW52YWxpZE1lbW9JZEFkZHJlc3MyKTtcbiAgICAgIH0pLnNob3VsZC50aHJvdygpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBvbiBtdWx0aXBsZSBtZW1vIGlkIGFkZHJlc3MnLCAoKSA9PiB7XG4gICAgICAoKCkgPT4ge1xuICAgICAgICBiYXNlY29pbi5nZXRBZGRyZXNzRGV0YWlscyhhZGRyZXNzLm11bHRpcGxlTWVtb0lkQWRkcmVzcyk7XG4gICAgICB9KS5zaG91bGQudGhyb3coKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgd2FsbGV0IHJlY2VpdmUgYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlY2VpdmVBZGRyZXNzID0ge1xuICAgICAgICBhZGRyZXNzOiAnbWFudHJhMTc4NTk2dXR1YWM4bDl0a2oyNWFmdnd6OGw3ZDc2ODRra3N3amxqP21lbW9JZD03JyxcbiAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgcm9vdEFkZHJlc3M6ICdtYW50cmExNzg1OTZ1dHVhYzhsOXRrajI1YWZ2d3o4bDdkNzY4NGtrc3dqbGonLFxuICAgICAgICAgIG1lbW9JRDogJzcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSBhd2FpdCBiYXNlY29pbi5pc1dhbGxldEFkZHJlc3MocmVjZWl2ZUFkZHJlc3MpO1xuICAgICAgaXNWYWxpZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIGFjY291bnQgYWRkcmVzc2VzIGNvcnJlY3RseScsICgpID0+IHtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkQWRkcmVzcyhhZGRyZXNzLmFkZHJlc3MxKSwgdHJ1ZSk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZEFkZHJlc3MoYWRkcmVzcy5hZGRyZXNzMiksIHRydWUpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRBZGRyZXNzKGFkZHJlc3MuYWRkcmVzczMpLCBmYWxzZSk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZEFkZHJlc3MoYWRkcmVzcy5hZGRyZXNzNCksIGZhbHNlKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkQWRkcmVzcygnZGZqazM1eScpLCBmYWxzZSk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZEFkZHJlc3ModW5kZWZpbmVkIGFzIHVua25vd24gYXMgc3RyaW5nKSwgZmFsc2UpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRBZGRyZXNzKCcnKSwgZmFsc2UpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRBZGRyZXNzKGFkZHJlc3MudmFsaWRNZW1vSWRBZGRyZXNzKSwgdHJ1ZSk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZEFkZHJlc3MoYWRkcmVzcy52YWxpZE1lbW9JZEFkZHJlc3MyKSwgdHJ1ZSk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZEFkZHJlc3MoYWRkcmVzcy5tdWx0aXBsZU1lbW9JZEFkZHJlc3MpLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIHZhbGlkYXRvciBhZGRyZXNzZXMgY29ycmVjdGx5JywgKCkgPT4ge1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRWYWxpZGF0b3JBZGRyZXNzKGFkZHJlc3MudmFsaWRhdG9yQWRkcmVzczEpLCB0cnVlKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkVmFsaWRhdG9yQWRkcmVzcyhhZGRyZXNzLnZhbGlkYXRvckFkZHJlc3MyKSwgdHJ1ZSk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFZhbGlkYXRvckFkZHJlc3MoYWRkcmVzcy52YWxpZGF0b3JBZGRyZXNzMyksIGZhbHNlKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkVmFsaWRhdG9yQWRkcmVzcyhhZGRyZXNzLnZhbGlkYXRvckFkZHJlc3M0KSwgZmFsc2UpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRWYWxpZGF0b3JBZGRyZXNzKCdkZmprMzV5JyksIGZhbHNlKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkVmFsaWRhdG9yQWRkcmVzcyh1bmRlZmluZWQgYXMgdW5rbm93biBhcyBzdHJpbmcpLCBmYWxzZSk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFZhbGlkYXRvckFkZHJlc3MoJycpLCBmYWxzZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdWZXJpZnkgdHJhbnNhY3Rpb246ICcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHN1Y2NlZWQgdG8gdmVyaWZ5IHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgdHhIZXg6IFRFU1RfU0VORF9UWC5zaWduZWRUeEJhc2U2NCxcbiAgICAgICAgdHhJbmZvOiB7fSxcbiAgICAgIH07XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6IFRFU1RfU0VORF9UWC5yZWNpcGllbnQsXG4gICAgICAgICAgICBhbW91bnQ6IFRFU1RfU0VORF9UWC5zZW5kQW1vdW50LFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG4gICAgICBjb25zdCBpc1RyYW5zYWN0aW9uVmVyaWZpZWQgPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB2ZXJpZmljYXRpb24gfSk7XG4gICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzdWNjZWVkIHRvIHZlcmlmeSBzZW5kTWFueSB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHR4SGV4OiBURVNUX1NFTkRfTUFOWV9UWC5zaWduZWRUeEJhc2U2NCxcbiAgICAgICAgdHhJbmZvOiB7fSxcbiAgICAgIH07XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICdtYW50cmExOGZhdnBzajBzOGhmeTJqMDBlODlwcW1wcDluZGZsMDNhNmE3dmonLFxuICAgICAgICAgICAgYW1vdW50OiAnMTAwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogJ21hbnRyYTFtNDkzdHh1YzJqaDB6ejg0Mndqc2FtaHQ2aHN5N3Q1MDZ0NDBycScsXG4gICAgICAgICAgICBhbW91bnQ6ICcxMDAwMCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcbiAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHZlcmlmaWNhdGlvbiB9KTtcbiAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gdmVyaWZ5IHRyYW5zYWN0aW9uIHdpdGggaW52YWxpZCBwYXJhbScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7fTtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0geyByZWNpcGllbnRzOiB1bmRlZmluZWQgfTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXMsXG4gICAgICAgICAgdHhQcmVidWlsZCxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5yZWplY3RlZFdpdGgoJ21pc3NpbmcgcmVxdWlyZWQgdHggcHJlYnVpbGQgcHJvcGVydHkgdHhIZXgnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0V4cGxhaW4gVHJhbnNhY3Rpb246ICcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGV4cGxhaW4gYSB0cmFuc2ZlciB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGxhaW5lZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhIZXg6IFRFU1RfU0VORF9UWC5zaWduZWRUeEJhc2U2NCxcbiAgICAgIH0pO1xuICAgICAgZXhwbGFpbmVkVHJhbnNhY3Rpb24uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGRpc3BsYXlPcmRlcjogWydpZCcsICdvdXRwdXRzJywgJ291dHB1dEFtb3VudCcsICdjaGFuZ2VPdXRwdXRzJywgJ2NoYW5nZUFtb3VudCcsICdmZWUnLCAndHlwZSddLFxuICAgICAgICBpZDogVEVTVF9TRU5EX1RYLmhhc2gsXG4gICAgICAgIG91dHB1dHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhZGRyZXNzOiBURVNUX1NFTkRfVFgucmVjaXBpZW50LFxuICAgICAgICAgICAgYW1vdW50OiBURVNUX1NFTkRfVFguc2VuZEFtb3VudCxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBvdXRwdXRBbW91bnQ6IFRFU1RfU0VORF9UWC5zZW5kQW1vdW50LFxuICAgICAgICBjaGFuZ2VPdXRwdXRzOiBbXSxcbiAgICAgICAgY2hhbmdlQW1vdW50OiAnMCcsXG4gICAgICAgIGZlZTogeyBmZWU6IFRFU1RfU0VORF9UWC5nYXNCdWRnZXQuYW1vdW50WzBdLmFtb3VudCB9LFxuICAgICAgICB0eXBlOiAwLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGV4cGxhaW4gc2VuZE1hbnkgdHJhbnNmZXIgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBleHBsYWluZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4SGV4OiBURVNUX1NFTkRfTUFOWV9UWC5zaWduZWRUeEJhc2U2NCxcbiAgICAgIH0pO1xuICAgICAgZXhwbGFpbmVkVHJhbnNhY3Rpb24uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGRpc3BsYXlPcmRlcjogWydpZCcsICdvdXRwdXRzJywgJ291dHB1dEFtb3VudCcsICdjaGFuZ2VPdXRwdXRzJywgJ2NoYW5nZUFtb3VudCcsICdmZWUnLCAndHlwZSddLFxuICAgICAgICBpZDogVEVTVF9TRU5EX01BTllfVFguaGFzaCxcbiAgICAgICAgb3V0cHV0czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICdtYW50cmExOGZhdnBzajBzOGhmeTJqMDBlODlwcW1wcDluZGZsMDNhNmE3dmonLFxuICAgICAgICAgICAgYW1vdW50OiAnMTAwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogJ21hbnRyYTFtNDkzdHh1YzJqaDB6ejg0Mndqc2FtaHQ2aHN5N3Q1MDZ0NDBycScsXG4gICAgICAgICAgICBhbW91bnQ6ICcxMDAwMCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgb3V0cHV0QW1vdW50OiAnMjAwMDAnLFxuICAgICAgICBjaGFuZ2VPdXRwdXRzOiBbXSxcbiAgICAgICAgY2hhbmdlQW1vdW50OiAnMCcsXG4gICAgICAgIGZlZTogeyBmZWU6IFRFU1RfU0VORF9NQU5ZX1RYLmdhc0J1ZGdldC5hbW91bnRbMF0uYW1vdW50IH0sXG4gICAgICAgIHR5cGU6IDAsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdpdGggbWVtbycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGxhaW5lZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhIZXg6IFRFU1RfVFhfV0lUSF9NRU1PLnNpZ25lZFR4QmFzZTY0LFxuICAgICAgfSk7XG4gICAgICBleHBsYWluZWRUcmFuc2FjdGlvbi5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgZGlzcGxheU9yZGVyOiBbJ2lkJywgJ291dHB1dHMnLCAnb3V0cHV0QW1vdW50JywgJ2NoYW5nZU91dHB1dHMnLCAnY2hhbmdlQW1vdW50JywgJ2ZlZScsICd0eXBlJ10sXG4gICAgICAgIGlkOiBURVNUX1RYX1dJVEhfTUVNTy5oYXNoLFxuICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogVEVTVF9UWF9XSVRIX01FTU8udG8sXG4gICAgICAgICAgICBhbW91bnQ6IFRFU1RfVFhfV0lUSF9NRU1PLnNlbmRBbW91bnQsXG4gICAgICAgICAgICBtZW1vOiBURVNUX1RYX1dJVEhfTUVNTy5tZW1vLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIG91dHB1dEFtb3VudDogVEVTVF9UWF9XSVRIX01FTU8uc2VuZEFtb3VudCxcbiAgICAgICAgY2hhbmdlT3V0cHV0czogW10sXG4gICAgICAgIGNoYW5nZUFtb3VudDogJzAnLFxuICAgICAgICBmZWU6IHsgZmVlOiBURVNUX1RYX1dJVEhfTUVNTy5nYXNCdWRnZXQuYW1vdW50WzBdLmFtb3VudCB9LFxuICAgICAgICB0eXBlOiAwLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gZXhwbGFpbiB0cmFuc2FjdGlvbiB3aXRoIG1pc3NpbmcgcGFyYW1zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHt9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHNob3VsZC5lcXVhbChlcnJvci5tZXNzYWdlLCAnbWlzc2luZyByZXF1aXJlZCB0eEhleCBwYXJhbWV0ZXInKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBleHBsYWluIHRyYW5zYWN0aW9uIHdpdGggaW52YWxpZCBwYXJhbXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oeyB0eEhleDogJ3JhbmRvbVN0cmluZycgfSk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBzaG91bGQuZXF1YWwoZXJyb3IubWVzc2FnZS5zdGFydHNXaXRoKCdJbnZhbGlkIHRyYW5zYWN0aW9uOicpLCB0cnVlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1BhcnNlIFRyYW5zYWN0aW9uczogJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZmVySW5wdXRzUmVzcG9uc2UgPSB7XG4gICAgICBhZGRyZXNzOiBURVNUX1NFTkRfVFgucmVjaXBpZW50LFxuICAgICAgYW1vdW50OiBuZXcgQmlnTnVtYmVyKFRFU1RfU0VORF9UWC5zZW5kQW1vdW50KS5wbHVzKFRFU1RfU0VORF9UWC5nYXNCdWRnZXQuYW1vdW50WzBdLmFtb3VudCkudG9GaXhlZCgpLFxuICAgIH07XG5cbiAgICBjb25zdCB0cmFuc2Zlck91dHB1dHNSZXNwb25zZSA9IHtcbiAgICAgIGFkZHJlc3M6IFRFU1RfU0VORF9UWC5yZWNpcGllbnQsXG4gICAgICBhbW91bnQ6IFRFU1RfU0VORF9UWC5zZW5kQW1vdW50LFxuICAgIH07XG5cbiAgICBpdCgnc2hvdWxkIHBhcnNlIGEgdHJhbnNmZXIgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJzZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLnBhcnNlVHJhbnNhY3Rpb24oeyB0eEhleDogVEVTVF9TRU5EX1RYLnNpZ25lZFR4QmFzZTY0IH0pO1xuXG4gICAgICBwYXJzZWRUcmFuc2FjdGlvbi5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgaW5wdXRzOiBbdHJhbnNmZXJJbnB1dHNSZXNwb25zZV0sXG4gICAgICAgIG91dHB1dHM6IFt0cmFuc2Zlck91dHB1dHNSZXNwb25zZV0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBwYXJzZSBhIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdoZW4gZXhwbGFpblRyYW5zYWN0aW9uIHJlc3BvbnNlIGlzIHVuZGVmaW5lZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHN0dWIgPSBzaW5vbi5zdHViKE1hbnRyYS5wcm90b3R5cGUsICdleHBsYWluVHJhbnNhY3Rpb24nKTtcbiAgICAgIHN0dWIucmVzb2x2ZXModW5kZWZpbmVkKTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC5wYXJzZVRyYW5zYWN0aW9uKHsgdHhIZXg6IFRFU1RfU0VORF9UWC5zaWduZWRUeEJhc2U2NCB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnSW52YWxpZCB0cmFuc2FjdGlvbicpO1xuICAgICAgc3R1Yi5yZXN0b3JlKCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=

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


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