PHP WebShell

Текущая директория: /opt/BitGoJS/modules/express/dist/test/unit/lightning

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

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const sinon = require("sinon");
const should = require("should");
const lightningWalletRoutes_1 = require("../../../src/lightning/lightningWalletRoutes");
const bitgo_1 = require("bitgo");
const errors_1 = require("../../../src/errors");
describe('Lightning Wallet 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;
    };
    beforeEach(() => {
        const walletStub = {};
        const coinStub = {
            wallets: () => ({ get: sinon.stub().resolves(walletStub) }),
        };
        bitgo = sinon.createStubInstance(bitgo_1.BitGo, { coin: coinStub });
    });
    afterEach(() => {
        sinon.restore();
    });
    describe('Update Wallet Coin Specific', () => {
        it('should successfully update wallet coin specific data', async () => {
            const inputParams = {
                signerMacaroon: 'encrypted-macaroon-data',
                signerHost: 'signer.example.com',
                passphrase: 'wallet-password-123',
            };
            const expectedResponse = {
                coinSpecific: {
                    updated: true,
                },
            };
            const updateStub = sinon.stub().resolves(expectedResponse);
            const proxyquire = require('proxyquire');
            const lightningRoutes = proxyquire('../../../src/lightning/lightningWalletRoutes', {
                '@bitgo/abstract-lightning': {
                    updateWalletCoinSpecific: updateStub,
                },
            });
            const req = mockRequestObject({
                params: { id: 'testWalletId', coin },
                body: inputParams,
                bitgo,
            });
            const result = await lightningRoutes.handleUpdateLightningWalletCoinSpecific(req);
            should(result).deepEqual(expectedResponse);
            should(updateStub).be.calledOnce();
            const args = updateStub.getCall(0).args;
            should(args?.length).greaterThanOrEqual(2);
            const secondArg = args[1];
            should(secondArg).have.property('signerMacaroon', 'encrypted-macaroon-data');
            should(secondArg).have.property('signerHost', 'signer.example.com');
            should(secondArg).have.property('passphrase', 'wallet-password-123');
        });
        it('should throw error when passphrase is missing', async () => {
            const invalidParams = {
                signerMacaroon: 'encrypted-data',
                signerHost: 'signer.example.com',
            };
            const req = mockRequestObject({
                params: { id: 'testWalletId', coin },
                body: invalidParams,
                bitgo,
            });
            await should((0, lightningWalletRoutes_1.handleUpdateLightningWalletCoinSpecific)(req))
                .be.rejectedWith(errors_1.ApiResponseError)
                .then((error) => {
                should(error.status).equal(400);
                should(error.message).equal('Invalid request body to update lightning wallet coin specific');
            });
        });
        it('should handle invalid request body', async () => {
            const invalidParams = {
                signerHost: 12345,
                passphrase: 'valid-pass',
            };
            const req = mockRequestObject({
                params: { id: 'testWalletId', coin },
                body: invalidParams,
                bitgo,
            });
            await should((0, lightningWalletRoutes_1.handleUpdateLightningWalletCoinSpecific)(req))
                .be.rejectedWith(errors_1.ApiResponseError)
                .then((error) => {
                should(error.status).equal(400);
                should(error.message).equal('Invalid request body to update lightning wallet coin specific');
            });
        });
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRuaW5nV2FsbGV0Um91dGVzLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90ZXN0L3VuaXQvbGlnaHRuaW5nL2xpZ2h0bmluZ1dhbGxldFJvdXRlcy50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsK0JBQStCO0FBQy9CLGlDQUFpQztBQUVqQyx3RkFBdUc7QUFDdkcsaUNBQThCO0FBQzlCLGdEQUF1RDtBQUV2RCxRQUFRLENBQUMseUJBQXlCLEVBQUUsR0FBRyxFQUFFO0lBQ3ZDLElBQUksS0FBSyxDQUFDO0lBQ1YsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDO0lBRXRCLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxNQUE4RCxFQUFFLEVBQUU7UUFDM0YsTUFBTSxHQUFHLEdBQTZCLEVBQUUsQ0FBQztRQUN6QyxHQUFHLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQzdCLEdBQUcsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUM7UUFDakMsR0FBRyxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUMvQixHQUFHLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUM7UUFDekIsT0FBTyxHQUFzQixDQUFDO0lBQ2hDLENBQUMsQ0FBQztJQUVGLFVBQVUsQ0FBQyxHQUFHLEVBQUU7UUFDZCxNQUFNLFVBQVUsR0FBRyxFQUFFLENBQUM7UUFDdEIsTUFBTSxRQUFRLEdBQUc7WUFDZixPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7U0FDNUQsQ0FBQztRQUNGLEtBQUssR0FBRyxLQUFLLENBQUMsa0JBQWtCLENBQUMsYUFBWSxFQUFFLEVBQUUsSUFBSSxF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QztnQkFDaEMsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsK0RBQStELENBQUMsQ0FBQztZQUMvRixDQUFDLENBQUMsQ0FBQztRQUNQLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLG9DQUFvQyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ2xELE1BQU0sYUFBYSxHQUFHO2dCQUNwQixVQUFVLEVBQUUsS0FBSztnQkFDakIsVUFBVSxFQUFFLFlBQVk7YUFDekIsQ0FBQztZQUVGLE1BQU0sR0FBRyxHQUFHLGlCQUFpQixDQUFDO2dCQUM1QixNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsY0FBYyxFQUFFLElBQUksRUFBRTtnQkFDcEMsSUFBSSxFQUFFLGFBQWE7Z0JBQ25CLEtBQUs7YUFDTixDQUFDLENBQUM7WUFFSCxNQUFNLE1BQU0sQ0FBQyxJQUFBLCtEQUF1QyxFQUFDLEdBQUcsQ0FBQyxDQUFDO2lCQUN2RCxFQUFFLENBQUMsWUFBWSxDQUFDLHlCQUFnQixDQUFDO2lCQUNqQyxJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtnQkFDZCxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDaEMsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsK0RBQStELENBQUMsQ0FBQztZQUMvRixDQUFDLENBQUMsQ0FBQztRQUNQLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHNpbm9uIGZyb20gJ3Npbm9uJztcbmltcG9ydCAqIGFzIHNob3VsZCBmcm9tICdzaG91bGQnO1xuaW1wb3J0ICogYXMgZXhwcmVzcyBmcm9tICdleHByZXNzJztcbmltcG9ydCB7IGhhbmRsZVVwZGF0ZUxpZ2h0bmluZ1dhbGxldENvaW5TcGVjaWZpYyB9IGZyb20gJy4uLy4uLy4uL3NyYy9saWdodG5pbmcvbGlnaHRuaW5nV2FsbGV0Um91dGVzJztcbmltcG9ydCB7IEJpdEdvIH0gZnJvbSAnYml0Z28nO1xuaW1wb3J0IHsgQXBpUmVzcG9uc2VFcnJvciB9IGZyb20gJy4uLy4uLy4uL3NyYy9lcnJvcnMnO1xuXG5kZXNjcmliZSgnTGlnaHRuaW5nIFdhbGxldCBSb3V0ZXMnLCAoKSA9PiB7XG4gIGxldCBiaXRnbztcbiAgY29uc3QgY29pbiA9ICd0bG5idGMnO1xuXG4gIGNvbnN0IG1vY2tSZXF1ZXN0T2JqZWN0ID0gKHBhcmFtczogeyBib2R5PzogYW55OyBwYXJhbXM/OiBhbnk7IHF1ZXJ5PzogYW55OyBiaXRnbz86IGFueSB9KSA9PiB7XG4gICAgY29uc3QgcmVxOiBQYXJ0aWFsPGV4cHJlc3MuUmVxdWVzdD4gPSB7fTtcbiAgICByZXEuYm9keSA9IHBhcmFtcy5ib2R5IHx8IHt9O1xuICAgIHJlcS5wYXJhbXMgPSBwYXJhbXMucGFyYW1zIHx8IHt9O1xuICAgIHJlcS5xdWVyeSA9IHBhcmFtcy5xdWVyeSB8fCB7fTtcbiAgICByZXEuYml0Z28gPSBwYXJhbXMuYml0Z287XG4gICAgcmV0dXJuIHJlcSBhcyBleHByZXNzLlJlcXVlc3Q7XG4gIH07XG5cbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgY29uc3Qgd2FsbGV0U3R1YiA9IHt9O1xuICAgIGNvbnN0IGNvaW5TdHViID0ge1xuICAgICAgd2FsbGV0czogKCkgPT4gKHsgZ2V0OiBzaW5vbi5zdHViKCkucmVzb2x2ZXMod2FsbGV0U3R1YikgfSksXG4gICAgfTtcbiAgICBiaXRnbyA9IHNpbm9uLmNyZWF0ZVN0dWJJbnN0YW5jZShCaXRHbyBhcyBhbnksIHsgY29pbjogY29pblN0dWIgfSk7XG4gIH0pO1xuXG4gIGFmdGVyRWFjaCgoKSA9PiB7XG4gICAgc2lub24ucmVzdG9yZSgpO1xuICB9KTtcblxuICBkZXNjcmliZSgnVXBkYXRlIFdhbGxldCBDb2luIFNwZWNpZmljJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgc3VjY2Vzc2Z1bGx5IHVwZGF0ZSB3YWxsZXQgY29pbiBzcGVjaWZpYyBkYXRhJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgaW5wdXRQYXJhbXMgPSB7XG4gICAgICAgIHNpZ25lck1hY2Fyb29uOiAnZW5jcnlwdGVkLW1hY2Fyb29uLWRhdGEnLFxuICAgICAgICBzaWduZXJIb3N0OiAnc2lnbmVyLmV4YW1wbGUuY29tJyxcbiAgICAgICAgcGFzc3BocmFzZTogJ3dhbGxldC1wYXNzd29yZC0xMjMnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgZXhwZWN0ZWRSZXNwb25zZSA9IHtcbiAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgdXBkYXRlZDogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHVwZGF0ZVN0dWIgPSBzaW5vbi5zdHViKCkucmVzb2x2ZXMoZXhwZWN0ZWRSZXNwb25zZSk7XG5cbiAgICAgIGNvbnN0IHByb3h5cXVpcmUgPSByZXF1aXJlKCdwcm94eXF1aXJlJyk7XG4gICAgICBjb25zdCBsaWdodG5pbmdSb3V0ZXMgPSBwcm94eXF1aXJlKCcuLi8uLi8uLi9zcmMvbGlnaHRuaW5nL2xpZ2h0bmluZ1dhbGxldFJvdXRlcycsIHtcbiAgICAgICAgJ0BiaXRnby9hYnN0cmFjdC1saWdodG5pbmcnOiB7XG4gICAgICAgICAgdXBkYXRlV2FsbGV0Q29pblNwZWNpZmljOiB1cGRhdGVTdHViLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHJlcSA9IG1vY2tSZXF1ZXN0T2JqZWN0KHtcbiAgICAgICAgcGFyYW1zOiB7IGlkOiAndGVzdFdhbGxldElkJywgY29pbiB9LFxuICAgICAgICBib2R5OiBpbnB1dFBhcmFtcyxcbiAgICAgICAgYml0Z28sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgbGlnaHRuaW5nUm91dGVzLmhhbmRsZVVwZGF0ZUxpZ2h0bmluZ1dhbGxldENvaW5TcGVjaWZpYyhyZXEpO1xuXG4gICAgICBzaG91bGQocmVzdWx0KS5kZWVwRXF1YWwoZXhwZWN0ZWRSZXNwb25zZSk7XG4gICAgICBzaG91bGQodXBkYXRlU3R1YikuYmUuY2FsbGVkT25jZSgpO1xuICAgICAgY29uc3QgYXJncyA9IHVwZGF0ZVN0dWIuZ2V0Q2FsbCgwKS5hcmdzO1xuICAgICAgc2hvdWxkKGFyZ3M/Lmxlbmd0aCkuZ3JlYXRlclRoYW5PckVxdWFsKDIpO1xuICAgICAgY29uc3Qgc2Vjb25kQXJnID0gYXJnc1sxXTtcbiAgICAgIHNob3VsZChzZWNvbmRBcmcpLmhhdmUucHJvcGVydHkoJ3NpZ25lck1hY2Fyb29uJywgJ2VuY3J5cHRlZC1tYWNhcm9vbi1kYXRhJyk7XG4gICAgICBzaG91bGQoc2Vjb25kQXJnKS5oYXZlLnByb3BlcnR5KCdzaWduZXJIb3N0JywgJ3NpZ25lci5leGFtcGxlLmNvbScpO1xuICAgICAgc2hvdWxkKHNlY29uZEFyZykuaGF2ZS5wcm9wZXJ0eSgncGFzc3BocmFzZScsICd3YWxsZXQtcGFzc3dvcmQtMTIzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIHdoZW4gcGFzc3BocmFzZSBpcyBtaXNzaW5nJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgaW52YWxpZFBhcmFtcyA9IHtcbiAgICAgICAgc2lnbmVyTWFjYXJvb246ICdlbmNyeXB0ZWQtZGF0YScsXG4gICAgICAgIHNpZ25lckhvc3Q6ICdzaWduZXIuZXhhbXBsZS5jb20nLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgcmVxID0gbW9ja1JlcXVlc3RPYmplY3Qoe1xuICAgICAgICBwYXJhbXM6IHsgaWQ6ICd0ZXN0V2FsbGV0SWQnLCBjb2luIH0sXG4gICAgICAgIGJvZHk6IGludmFsaWRQYXJhbXMsXG4gICAgICAgIGJpdGdvLFxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHNob3VsZChoYW5kbGVVcGRhdGVMaWdodG5pbmdXYWxsZXRDb2luU3BlY2lmaWMocmVxKSlcbiAgICAgICAgLmJlLnJlamVjdGVkV2l0aChBcGlSZXNwb25zZUVycm9yKVxuICAgICAgICAudGhlbigoZXJyb3IpID0+IHtcbiAgICAgICAgICBzaG91bGQoZXJyb3Iuc3RhdHVzKS5lcXVhbCg0MDApO1xuICAgICAgICAgIHNob3VsZChlcnJvci5tZXNzYWdlKS5lcXVhbCgnSW52YWxpZCByZXF1ZXN0IGJvZHkgdG8gdXBkYXRlIGxpZ2h0bmluZyB3YWxsZXQgY29pbiBzcGVjaWZpYycpO1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgaGFuZGxlIGludmFsaWQgcmVxdWVzdCBib2R5JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgaW52YWxpZFBhcmFtcyA9IHtcbiAgICAgICAgc2lnbmVySG9zdDogMTIzNDUsIC8vIGludmFsaWQgdHlwZVxuICAgICAgICBwYXNzcGhyYXNlOiAndmFsaWQtcGFzcycsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCByZXEgPSBtb2NrUmVxdWVzdE9iamVjdCh7XG4gICAgICAgIHBhcmFtczogeyBpZDogJ3Rlc3RXYWxsZXRJZCcsIGNvaW4gfSxcbiAgICAgICAgYm9keTogaW52YWxpZFBhcmFtcyxcbiAgICAgICAgYml0Z28sXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgc2hvdWxkKGhhbmRsZVVwZGF0ZUxpZ2h0bmluZ1dhbGxldENvaW5TcGVjaWZpYyhyZXEpKVxuICAgICAgICAuYmUucmVqZWN0ZWRXaXRoKEFwaVJlc3BvbnNlRXJyb3IpXG4gICAgICAgIC50aGVuKChlcnJvcikgPT4ge1xuICAgICAgICAgIHNob3VsZChlcnJvci5zdGF0dXMpLmVxdWFsKDQwMCk7XG4gICAgICAgICAgc2hvdWxkKGVycm9yLm1lc3NhZ2UpLmVxdWFsKCdJbnZhbGlkIHJlcXVlc3QgYm9keSB0byB1cGRhdGUgbGlnaHRuaW5nIHdhbGxldCBjb2luIHNwZWNpZmljJyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19

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


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