Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions apps/frontend/build/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"files": {
"main.css": "/static/css/main.1ce19166.css",
"main.js": "/static/js/main.4501e70f.js",
"main.js": "/static/js/main.2875dcdc.js",
"static/media/Inter-Bold.ttf": "/static/media/Inter-Bold.88fa7ae373b07b41ecce.ttf",
"static/media/Inter-SemiBold.ttf": "/static/media/Inter-SemiBold.4d56bb21f2399db8ad48.ttf",
"static/media/Inter-Medium.ttf": "/static/media/Inter-Medium.6dcbc9bed1ec438907ee.ttf",
"static/media/Inter-Thin.ttf": "/static/media/Inter-Thin.f341ca512063c66296d1.ttf",
"index.html": "/index.html",
"main.1ce19166.css.map": "/static/css/main.1ce19166.css.map",
"main.4501e70f.js.map": "/static/js/main.4501e70f.js.map"
"main.2875dcdc.js.map": "/static/js/main.2875dcdc.js.map"
},
"entrypoints": [
"static/css/main.1ce19166.css",
"static/js/main.4501e70f.js"
"static/js/main.2875dcdc.js"
]
}
2 changes: 1 addition & 1 deletion apps/frontend/build/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./images/cln-favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="color-scheme" content="light dark"><meta name="description" content="Core lightning application"/><link rel="apple-touch-icon" href="./images/cln-logo-dark.png"/><title>Core Lightning</title><script defer="defer" src="/static/js/main.4501e70f.js"></script><link href="/static/css/main.1ce19166.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./images/cln-favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="color-scheme" content="light dark"><meta name="description" content="Core lightning application"/><link rel="apple-touch-icon" href="./images/cln-logo-dark.png"/><title>Core Lightning</title><script defer="defer" src="/static/js/main.2875dcdc.js"></script><link href="/static/css/main.1ce19166.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
3 changes: 3 additions & 0 deletions apps/frontend/build/static/js/main.2875dcdc.js

Large diffs are not rendered by default.

90 changes: 90 additions & 0 deletions apps/frontend/build/static/js/main.2875dcdc.js.LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*!
Copyright (c) 2018 Jed Watson.
Licensed under the MIT License (MIT), see
http://jedwatson.github.io/classnames
*/

/*!
* perfect-scrollbar v1.5.3
* Copyright 2021 Hyunje Jun, MDBootstrap and Contributors
* Licensed under MIT
*/

/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/**
* @license qrcode.react
* Copyright (c) Paul O'Shannessy
* SPDX-License-Identifier: ISC
*/

/**
* @remix-run/router v1.15.2
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/

/**
* React Router DOM v6.22.2
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/

/**
* React Router v6.22.2
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
1 change: 1 addition & 0 deletions apps/frontend/build/static/js/main.2875dcdc.js.map

Large diffs are not rendered by default.

33 changes: 9 additions & 24 deletions apps/frontend/src/components/App/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,35 @@ import App, { rootRouteConfig } from './App';
import { RouterProvider, createMemoryRouter } from 'react-router-dom';
import { cleanup } from "@testing-library/react";

jest.mock('../../services/logger.service', () => ({
__esModule: true,
default: {
info: jest.fn(),
warn: jest.fn(),
error: jest.fn()
}
}));

afterEach(cleanup);

describe('App component ', () => {
beforeEach(() => render(<App />));

it('should be in the document', () => {
expect(screen.getByTestId('container')).not.toBeEmptyDOMElement()
expect(screen.getByTestId('container')).not.toBeEmptyDOMElement();
});
});

describe('Root routing', () => {
const setUp = (async () => {
const router = createMemoryRouter(rootRouteConfig, { initialEntries: ['/'] })

render(
<RouterProvider router={router} />
);

return { router }
const router = createMemoryRouter(rootRouteConfig, { initialEntries: ['/'] });
render(<RouterProvider router={router} />);
return router;
});

it('redirects from / to /home', async () => {
let router = setUp();
expect((await router).router.state.location.pathname).toBe("/home");
let router = await setUp();
expect(router.state?.location?.pathname).toBe("/home");
});

it('going to bookkeeper hides the cln view, preserves header', async () => {
let router = setUp();
let router = await setUp();
expect(screen.getByTestId('header')).not.toBeEmptyDOMElement();
expect(screen.queryByTestId('cln-container')).toBeInTheDocument();
expect(screen.queryByTestId('bookkeeper-container')).not.toBeInTheDocument();
await act(async () => {
(await router).router.navigate("/bookkeeper");
})
expect((await router).router.state.location.pathname).toBe("/bookkeeper");
await act(async () => { router.navigate("/bookkeeper"); });
expect(router.state?.location?.pathname).toBe("/bookkeeper");
expect(screen.getByTestId('header')).not.toBeEmptyDOMElement();
expect(screen.queryByTestId('cln-container')).not.toBeInTheDocument();
expect(screen.queryByTestId('bookkeeper-container')).toBeInTheDocument();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { render, screen } from '@testing-library/react';
import Bookkeeper from './BkprRoot';

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: jest.fn(),
}));

describe('Bookkeeper component ', () => {
beforeEach(() => render(<Bookkeeper />));

Expand Down
55 changes: 53 additions & 2 deletions apps/frontend/src/components/cln/CLNSend/CLNSend.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,62 @@
import { render, screen } from '@testing-library/react';
import { act, fireEvent, screen } from '@testing-library/react';
import CLNSend from './CLNSend';
import { getMockStoreData, renderWithMockContext } from '../../../utilities/test-utilities';

describe('CLNSend component ', () => {
beforeEach(() => render(<CLNSend />));
let providerProps;
beforeEach(() => providerProps = JSON.parse(JSON.stringify(getMockStoreData())));

it('should be in the document', () => {
renderWithMockContext(<CLNSend />, { providerProps });
expect(screen.getByTestId('cln-send')).toBeInTheDocument();
});

it('should accept lowercase invoice', async () => {
renderWithMockContext(<CLNSend />, { providerProps });

const invoiceInput = screen.getByTestId("address-input");
const testInvoice = 'lnb12345';
await act(async () => fireEvent.change(invoiceInput, { target: { value: testInvoice } }));

expect(screen.queryByText('Invalid Invoice')).not.toBeInTheDocument();
});

it('should accept UPPERCASE invoice', async () => {
renderWithMockContext(<CLNSend />, { providerProps });

const invoiceInput = screen.getByTestId("address-input");
const testInvoice = "LNB12345";
await act(async () => fireEvent.change(invoiceInput, { target: { value: testInvoice } }));

expect(screen.queryByText("Invalid Invoice")).not.toBeInTheDocument();
});

it('should accept lowercase offer', async () => {
renderWithMockContext(<CLNSend />, { providerProps });

const offerRadioButton = screen.getByLabelText("Offer");
await act(async () => fireEvent.click(offerRadioButton));

const offerInput = screen.getByTestId("address-input");
const testOffer = "lno12345";
await act(async () => fireEvent.change(offerInput, { target: { value: testOffer } }));

expect(offerRadioButton).toBeChecked();
expect(screen.queryByText("Invalid Offer")).not.toBeInTheDocument();
});

it('should accept UPPERCASE offer', async () => {
renderWithMockContext(<CLNSend />, { providerProps });

const offerRadioButton = screen.getByLabelText("Offer");
await act(async () => fireEvent.click(offerRadioButton));

const offerInput = screen.getByTestId("address-input");
const testOffer = "LNO12345";
await act(async () => fireEvent.change(offerInput, { target: { value: testOffer } }));

expect(offerRadioButton).toBeChecked();
expect(screen.queryByText("Invalid Offer")).not.toBeInTheDocument();
});

});
2 changes: 2 additions & 0 deletions apps/frontend/src/components/cln/CLNSend/CLNSend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ const CLNSend = (props) => {
<Form.Control
tabIndex={4}
id='invoice'
data-testid='address-input'
type='text'
placeholder={paymentType === PaymentType.KEYSEND ? 'Pubkey' : paymentType === PaymentType.OFFER ? 'Offer' : 'Invoice'}
aria-label='invoice'
Expand Down Expand Up @@ -266,6 +267,7 @@ const CLNSend = (props) => {
<Form.Control
tabIndex={5}
id='amount'
data-testid='amount-input'
type='number'
placeholder='Amount (Sats)'
aria-label='amount'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const ConnectWallet = () => {
const [networkTypes, setNetworkTypes] = useState<string[]>(['LN Message', 'LN Message (Tor)']);
const [selNetwork, setSelNetwork] = useState('LN Message');
const [connectUrl, setConnectUrl] = useState('');
const initialConnectValues: ConnectWalletFields = { port: { title: 'Websocket Port', field: 'WS_PORT' }, host: { title: 'CLN Host', field: 'DEVICE_DOMAIN_NAME' }, macaroon: { title: 'Rune', field: 'COMMANDO_RUNE' }, invoiceRune: { title: 'Invoice Rune', field: "INVOICE_RUNE" }, connectUrl: { title: 'Lnmessage URL', field: '' }, clientCert: { title: 'Client Cert', field: '' }, caCert: { title: 'CA Cert', field: '' } };
const initialConnectValues: ConnectWalletFields = { port: { title: 'Websocket Port', field: 'WS_PORT' }, host: { title: 'CLN Host', field: 'DEVICE_DOMAIN_NAME' }, macaroon: { title: 'Rune', field: 'COMMANDO_RUNE' }, invoiceRune: { title: 'Invoice Rune', field: 'INVOICE_RUNE' }, connectUrl: { title: 'Lnmessage URL', field: '' }, clientCert: { title: 'Client Cert', field: '' }, caCert: { title: 'CA Cert', field: '' } };
const [connectValues, setConnectValues] = useState(initialConnectValues);
const [isLoadingInvoiceRune, setIsLoadingInvoiceRune] = useState(false);

Expand Down Expand Up @@ -117,37 +117,37 @@ const ConnectWallet = () => {
setSelNetwork(event.target.id);
switch (event.target.id) {
case 'LN Message':
setConnectValues({ port: { title: 'Websocket Port', field: 'WS_PORT' }, host: { title: 'CLN Host', field: 'DEVICE_DOMAIN_NAME' }, macaroon: { title: 'Rune', field: 'COMMANDO_RUNE' }, invoiceRune: { title: 'Invoice Rune', field: "INVOICE_RUNE" }, connectUrl: { title: 'Lnmessage URL', field: '' }, clientCert: { title: 'Client Cert', field: '' }, caCert: { title: 'CA Cert', field: '' } });
setConnectValues({ port: { title: 'Websocket Port', field: 'WS_PORT' }, host: { title: 'CLN Host', field: 'DEVICE_DOMAIN_NAME' }, macaroon: { title: 'Rune', field: 'COMMANDO_RUNE' }, invoiceRune: { title: 'Invoice Rune', field: 'INVOICE_RUNE' }, connectUrl: { title: 'Lnmessage URL', field: '' }, clientCert: { title: 'Client Cert', field: '' }, caCert: { title: 'CA Cert', field: '' } });
setConnectUrl('ln-message://' + appCtx.walletConnect.DEVICE_DOMAIN_NAME + ':' + appCtx.walletConnect.WS_PORT + '?rune=' + appCtx.walletConnect.COMMANDO_RUNE);
break;

case 'LN Message (Tor)':
setConnectValues({ port: { title: 'Websocket Port', field: 'WS_PORT' }, host: { title: 'CLN Host', field: 'TOR_DOMAIN_NAME' }, macaroon: { title: 'Rune', field: 'COMMANDO_RUNE' }, invoiceRune: { title: 'Invoice Rune', field: "INVOICE_RUNE" }, connectUrl: { title: 'Lnmessage URL', field: '' }, clientCert: { title: 'Client Cert', field: '' }, caCert: { title: 'CA Cert', field: '' } });
setConnectValues({ port: { title: 'Websocket Port', field: 'WS_PORT' }, host: { title: 'CLN Host', field: 'TOR_DOMAIN_NAME' }, macaroon: { title: 'Rune', field: 'COMMANDO_RUNE' }, invoiceRune: { title: 'Invoice Rune', field: 'INVOICE_RUNE' }, connectUrl: { title: 'Lnmessage URL', field: '' }, clientCert: { title: 'Client Cert', field: '' }, caCert: { title: 'CA Cert', field: '' } });
setConnectUrl('ln-message://' + appCtx.walletConnect.TOR_DOMAIN_NAME + ':' + appCtx.walletConnect.WS_PORT + '?rune=' + appCtx.walletConnect.COMMANDO_RUNE);
break;

case 'REST':
setConnectValues({ port: { title: 'REST Port', field: 'REST_PORT' }, host: { title: 'CLN Host', field: 'LOCAL_HOST' }, macaroon: { title: 'Macaroon', field: 'REST_MACAROON' }, invoiceRune: { title: 'Invoice Rune', field: "INVOICE_RUNE" }, connectUrl: { title: 'REST URL', field: '' }, clientCert: { title: 'Client Cert', field: '' }, caCert: { title: 'CA Cert', field: '' } });
setConnectValues({ port: { title: 'REST Port', field: 'REST_PORT' }, host: { title: 'CLN Host', field: 'LOCAL_HOST' }, macaroon: { title: 'Macaroon', field: 'REST_MACAROON' }, invoiceRune: { title: 'Invoice Rune', field: 'INVOICE_RUNE' }, connectUrl: { title: 'REST URL', field: '' }, clientCert: { title: 'Client Cert', field: '' }, caCert: { title: 'CA Cert', field: '' } });
setConnectUrl('c-lightning-rest://' + appCtx.walletConnect.LOCAL_HOST + ':' + appCtx.walletConnect.REST_PORT + '?macaroon=' + appCtx.walletConnect.REST_MACAROON + '&protocol=http');
break;

case 'REST (Tor)':
setConnectValues({ port: { title: 'REST Port', field: 'REST_PORT' }, host: { title: 'CLN Host', field: 'TOR_HOST' }, macaroon: { title: 'Macaroon', field: 'REST_MACAROON' }, invoiceRune: { title: 'Invoice Rune', field: "INVOICE_RUNE" }, connectUrl: { title: 'REST URL', field: '' }, clientCert: { title: 'Client Cert', field: '' }, caCert: { title: 'CA Cert', field: '' } });
setConnectValues({ port: { title: 'REST Port', field: 'REST_PORT' }, host: { title: 'CLN Host', field: 'TOR_HOST' }, macaroon: { title: 'Macaroon', field: 'REST_MACAROON' }, invoiceRune: { title: 'Invoice Rune', field: 'INVOICE_RUNE' }, connectUrl: { title: 'REST URL', field: '' }, clientCert: { title: 'Client Cert', field: '' }, caCert: { title: 'CA Cert', field: '' } });
setConnectUrl('c-lightning-rest://' + appCtx.walletConnect.TOR_HOST + ':' + appCtx.walletConnect.REST_PORT + '?macaroon=' + appCtx.walletConnect.REST_MACAROON + '&protocol=http');
break;

case 'gRPC':
setConnectValues({ port: { title: 'gRPC Port', field: 'GRPC_PORT' }, host: { title: 'CLN Host', field: 'DEVICE_DOMAIN_NAME' }, macaroon: { title: 'Client Key', field: 'CLIENT_KEY' }, invoiceRune: { title: 'Invoice Rune', field: "INVOICE_RUNE" }, connectUrl: { title: 'gRPC URL', field: '' }, clientCert: { title: 'Client Cert', field: 'CLIENT_CERT' }, caCert: { title: 'CA Cert', field: 'CA_CERT' } });
setConnectValues({ port: { title: 'gRPC Port', field: 'GRPC_PORT' }, host: { title: 'CLN Host', field: 'DEVICE_DOMAIN_NAME' }, macaroon: { title: 'Client Key', field: 'CLIENT_KEY' }, invoiceRune: { title: 'Invoice Rune', field: 'INVOICE_RUNE' }, connectUrl: { title: 'gRPC URL', field: '' }, clientCert: { title: 'Client Cert', field: 'CLIENT_CERT' }, caCert: { title: 'CA Cert', field: 'CA_CERT' } });
setConnectUrl('cln-grpc://' + appCtx.walletConnect.DEVICE_DOMAIN_NAME + ':' + appCtx.walletConnect.GRPC_PORT + '?clientkey=' + appCtx.walletConnect.CLIENT_KEY + '&clientCert=' + appCtx.walletConnect.CLIENT_CERT + '&caCert=' + appCtx.walletConnect.CA_CERT);
break;

case 'gRPC (Tor)':
setConnectValues({ port: { title: 'gRPC Port', field: 'GRPC_PORT' }, host: { title: 'CLN Host', field: 'TOR_DOMAIN_NAME' }, macaroon: { title: 'Client Key', field: 'CLIENT_KEY' }, invoiceRune: { title: 'Invoice Rune', field: "INVOICE_RUNE" }, connectUrl: { title: 'gRPC URL', field: '' }, clientCert: { title: 'Client Cert', field: 'CLIENT_CERT' }, caCert: { title: 'CA Cert', field: 'CA_CERT' } });
setConnectValues({ port: { title: 'gRPC Port', field: 'GRPC_PORT' }, host: { title: 'CLN Host', field: 'TOR_DOMAIN_NAME' }, macaroon: { title: 'Client Key', field: 'CLIENT_KEY' }, invoiceRune: { title: 'Invoice Rune', field: 'INVOICE_RUNE' }, connectUrl: { title: 'gRPC URL', field: '' }, clientCert: { title: 'Client Cert', field: 'CLIENT_CERT' }, caCert: { title: 'CA Cert', field: 'CA_CERT' } });
setConnectUrl('cln-grpc://' + appCtx.walletConnect.TOR_DOMAIN_NAME + ':' + appCtx.walletConnect.GRPC_PORT + '?clientkey=' + appCtx.walletConnect.CLIENT_KEY + '&clientCert=' + appCtx.walletConnect.CLIENT_CERT);
break;

default:
setConnectValues({ port: { title: 'Websocket Port', field: 'WS_PORT' }, host: { title: 'CLN Host', field: 'DEVICE_DOMAIN_NAME' }, macaroon: { title: 'Rune', field: 'COMMANDO_RUNE' }, invoiceRune: { title: 'Invoice Rune', field: "INVOICE_RUNE" }, connectUrl: { title: 'Lnmessage URL', field: '' }, clientCert: { title: 'Client Cert', field: '' }, caCert: { title: 'CA Cert', field: '' } });
setConnectValues({ port: { title: 'Websocket Port', field: 'WS_PORT' }, host: { title: 'CLN Host', field: 'DEVICE_DOMAIN_NAME' }, macaroon: { title: 'Rune', field: 'COMMANDO_RUNE' }, invoiceRune: { title: 'Invoice Rune', field: 'INVOICE_RUNE' }, connectUrl: { title: 'Lnmessage URL', field: '' }, clientCert: { title: 'Client Cert', field: '' }, caCert: { title: 'CA Cert', field: '' } });
setConnectUrl('ln-message://' + appCtx.walletConnect.DEVICE_DOMAIN_NAME + ':' + appCtx.walletConnect.WS_PORT + '?rune=' + appCtx.walletConnect.COMMANDO_RUNE);
break;
}
Expand Down
7 changes: 7 additions & 0 deletions apps/frontend/src/setupTests.ts
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
import '@testing-library/jest-dom';
import '@testing-library/jest-dom';
jest.mock('./hooks/use-http.ts', () => require('./utilities/test-use-http.tsx'));

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: jest.fn(),
}));
4 changes: 2 additions & 2 deletions apps/frontend/src/svgs/Add.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export const AddSVG = props => {
overlay={(props.showTooltip ? <Tooltip>{props.tooltipText || ''}</Tooltip> : <></>)}
>
<svg width='17' height='17' viewBox='0 0 17 17' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path d='M1 8.5H16' stroke='#9F9F9F' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round' />
<path d='M8.5 1V16' stroke='#9F9F9F' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round' />
<path d='M1 8.5H16' stroke='#9F9F9F' strokeWidth='1.3' strokeLinecap='round' strokeLinejoin='round' />
<path d='M8.5 1V16' stroke='#9F9F9F' strokeWidth='1.3' strokeLinecap='round' strokeLinejoin='round' />
</svg>
</OverlayTrigger>
);
Expand Down
8 changes: 8 additions & 0 deletions apps/frontend/src/types/lightning-wallet.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ export type Offer = {
single_use?: boolean;
used?: boolean;
label?: string;
valid?: boolean;
}

export type ListOffers = {
Expand All @@ -462,3 +463,10 @@ export type Inflight = {
our_funding_msat: string;
scratch_txid?: string;
}

export type Rune = {
rune: string;
unique_id: string;
restrictions?: any[];
restrictions_as_english?: string;
}
Loading