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
2 changes: 2 additions & 0 deletions .github/docs/Docker-Setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ docker run -d \
-e LIGHTNING_HOST="cln-node" \
-e LIGHTNING_VARS_FILE="/app/.commando" \
-e LIGHTNING_WS_PROTOCOL="ws" \
-e LIGHTNING_WS_HOST="cln-node" \
-e LIGHTNING_WS_TOR_HOST="tor.onion" \
-e LIGHTNING_WS_PORT=5018 \
ghcr.io/elementsproject/cln-application:25.07.2 npm run start
```
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@
- APP_CONNECT: Choose how to connect to CLN (valid values: COMMANDO/REST/GRPC, default: `COMMANDO`)

# Core lightning Values
- LIGHTNING_HOST: IP address of Core lightning node container (used for `COMMANDO` APP_CONNECT, default: `localhost`)
- LIGHTNING_TOR_HOST: REST hidden service url (default: ``)
- LIGHTNING_HOST: IP address of Core lightning node (default: `localhost`)
- LIGHTNING_TOR_HOST: Tor Hidden Service url (default: ``)
- LIGHTNING_VARS_FILE: Full Path including the file name for connection auth with LIGHTNING_PUBKEY & LIGHTNING_RUNE (defult: `./.commando-env`)

# CLN Commando (WS) Values
- LIGHTNING_WS_PROTOCOL: Core lightning's web socket is serving on ws or serving via WSSProxy (valid values: ws/wss, default: `ws`)
- LIGHTNING_WS_HOST: Core lightning's IP address where commando can connect (default: `localhost`)
- LIGHTNING_WS_TOR_HOST: Core lightning's Tor address where commando can connect (default: ``)
- LIGHTNING_WS_PORT: Core lightning's websocket port (used by `COMMANDO` APP_CONNECT; with `bind-addr=ws:`/`wss-bind-addr` in CLN config; default: `5001`)
- LIGHTNING_WS_CLIENT_KEY_FILE: Client key file path including file name for websocket TLS authentication (used by `COMMANDO` APP_CONNECT and `wss` LIGHTNING_WS_PROTOCOL; default: `./client-key.pem`)
- LIGHTNING_WS_CLIENT_CERT_FILE: Client certificate file path including file name for websocket TLS authentication (used by `COMMANDO` APP_CONNECT and `wss` LIGHTNING_WS_PROTOCOL; default: `./client.pem`)
Expand Down
9 changes: 7 additions & 2 deletions apps/backend/source/shared/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ export const DEFAULT_ENV_VALUES = {
LIGHTNING_TOR_HOST: '',
LIGHTNING_VARS_FILE: './.commando-env',
LIGHTNING_WS_PROTOCOL: 'ws',
LIGHTNING_WS_HOST: 'localhost',
LIGHTNING_WS_TOR_HOST: 'tor.onion',
LIGHTNING_WS_PORT: 5001,
LIGHTNING_WS_CLIENT_KEY_FILE: './client-key.pem',
LIGHTNING_WS_CLIENT_CERT_FILE: './client.pem',
Expand Down Expand Up @@ -85,6 +87,9 @@ export const APP_CONSTANTS = {
LIGHTNING_VARS_FILE: process.env.LIGHTNING_VARS_FILE || DEFAULT_ENV_VALUES.LIGHTNING_VARS_FILE,
LIGHTNING_WS_PROTOCOL:
process.env.LIGHTNING_WS_PROTOCOL || DEFAULT_ENV_VALUES.LIGHTNING_WS_PROTOCOL,
LIGHTNING_WS_HOST: process.env.LIGHTNING_WS_HOST || DEFAULT_ENV_VALUES.LIGHTNING_WS_HOST,
LIGHTNING_WS_TOR_HOST:
process.env.LIGHTNING_WS_TOR_HOST || DEFAULT_ENV_VALUES.LIGHTNING_WS_TOR_HOST,
LIGHTNING_WS_PORT: +(process.env.LIGHTNING_WS_PORT || DEFAULT_ENV_VALUES.LIGHTNING_WS_PORT),
LIGHTNING_WS_CLIENT_KEY_FILE:
process.env.LIGHTNING_WS_CLIENT_KEY_FILE || DEFAULT_ENV_VALUES.LIGHTNING_WS_CLIENT_KEY_FILE,
Expand Down Expand Up @@ -162,10 +167,10 @@ export const LN_MESSAGE_CONFIG = {
wsProxy:
APP_CONSTANTS.LIGHTNING_WS_PROTOCOL +
'://' +
APP_CONSTANTS.LIGHTNING_HOST +
APP_CONSTANTS.LIGHTNING_WS_HOST +
':' +
APP_CONSTANTS.LIGHTNING_WS_PORT,
ip: APP_CONSTANTS.LIGHTNING_HOST,
ip: APP_CONSTANTS.LIGHTNING_WS_HOST,
port: APP_CONSTANTS.LIGHTNING_WS_PORT,
privateKey: crypto.randomBytes(32).toString('hex'),
socket: (url: string) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('CommandoForm Component', () => {
it('displays correct values for Commando network', async () => {
await renderWithProviders(<ConnectWallet />, { preloadedState: customMockStore });
expect(screen.getByTestId('ws-protocol')).toHaveValue(mockConnectWallet.LIGHTNING_WS_PROTOCOL);
expect(screen.getByTestId('ws-host')).toHaveValue(mockConnectWallet.LIGHTNING_HOST);
expect(screen.getByTestId('ws-host')).toHaveValue(mockConnectWallet.LIGHTNING_WS_HOST);
expect(screen.getByTestId('ws-port')).toHaveValue(mockConnectWallet.LIGHTNING_WS_PORT.toString());
expect(screen.getByTestId('node-pubkey')).toHaveValue(mockConnectWallet.NODE_PUBKEY);
expect(screen.getByTestId('rune')).toHaveValue(mockConnectWallet.ADMIN_RUNE);
Expand All @@ -68,15 +68,15 @@ describe('CommandoForm Component', () => {
await act(async () => {
fireEvent.click(commandoTorSelect);
});
expect(screen.getByTestId('ws-host')).toHaveValue(mockConnectWallet.LIGHTNING_TOR_HOST);
expect(screen.getByTestId('ws-host')).toHaveValue(mockConnectWallet.LIGHTNING_WS_TOR_HOST);
});

it('copies field values to clipboard when clicked', async () => {
const copyTextToClipboard = jest.spyOn(dataFormatUtils, 'copyTextToClipboard');
await renderWithProviders(<ConnectWallet />, { preloadedState: customMockStore });
const fieldsToTest = [
{ id: 'WS Protocol', testId: 'ws-protocol', expected: mockConnectWallet.LIGHTNING_WS_PROTOCOL },
{ id: 'WS Host', testId: 'ws-host', expected: mockConnectWallet.LIGHTNING_HOST },
{ id: 'WS Host', testId: 'ws-host', expected: mockConnectWallet.LIGHTNING_WS_HOST },
{ id: 'WS Port', testId: 'ws-port', expected: mockConnectWallet.LIGHTNING_WS_PORT.toString() },
{ id: 'Node Public Key', testId: 'node-pubkey', expected: mockConnectWallet.NODE_PUBKEY },
{ id: 'Rune', testId: 'rune', expected: mockConnectWallet.ADMIN_RUNE },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const CommandoForm = ({ selNetwork }) => {
textToCopy = connectWallet.LIGHTNING_WS_PROTOCOL || '';
break;
case 'WS Host':
textToCopy = (selNetwork.includes('(Tor)') ? connectWallet.LIGHTNING_TOR_HOST : connectWallet.LIGHTNING_HOST) || '';
textToCopy = (selNetwork.includes('(Tor)') ? connectWallet.LIGHTNING_WS_TOR_HOST : connectWallet.LIGHTNING_WS_HOST) || '';
break;
case 'WS Port':
textToCopy = connectWallet.LIGHTNING_WS_PORT?.toString() || '';
Expand Down Expand Up @@ -108,8 +108,8 @@ const CommandoForm = ({ selNetwork }) => {
<Form.Control
onClick={copyHandler}
id='WS Host'
value={selNetwork.includes('(Tor)') ? connectWallet.LIGHTNING_TOR_HOST : connectWallet.LIGHTNING_HOST}
aria-label={selNetwork.includes('(Tor)') ? connectWallet.LIGHTNING_TOR_HOST : connectWallet.LIGHTNING_HOST}
value={selNetwork.includes('(Tor)') ? connectWallet.LIGHTNING_WS_TOR_HOST : connectWallet.LIGHTNING_WS_HOST}
aria-label={selNetwork.includes('(Tor)') ? connectWallet.LIGHTNING_WS_TOR_HOST : connectWallet.LIGHTNING_WS_HOST}
aria-describedby='copy-addon-host'
className='form-control-left'
data-testid='ws-host'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,15 @@ describe('ConnectWallet component', () => {
it('updates the connection URL when network is changed', async () => {
await renderWithProviders(<ConnectWallet />, { preloadedState: customMockStore });
const initialUrl = screen.getByTestId('connect-url');
expect(initialUrl).toHaveValue('commando+wss://'+ mockConnectWallet.LIGHTNING_HOST + ':' + mockConnectWallet.LIGHTNING_WS_PORT + '?pubkey=' + mockConnectWallet.NODE_PUBKEY + '&rune=' + mockConnectWallet.ADMIN_RUNE + '&invoiceRune=' + mockConnectWallet.INVOICE_RUNE + '&certs=' + mockConnectWallet.LIGHTNING_WS_TLS_CERTS);
expect(initialUrl).toHaveValue('commando+wss://'+ mockConnectWallet.LIGHTNING_WS_HOST + ':' + mockConnectWallet.LIGHTNING_WS_PORT + '?pubkey=' + mockConnectWallet.NODE_PUBKEY + '&rune=' + mockConnectWallet.ADMIN_RUNE + '&invoiceRune=' + mockConnectWallet.INVOICE_RUNE + '&certs=' + mockConnectWallet.LIGHTNING_WS_TLS_CERTS);
await act(async () => {
fireEvent.click(screen.getByTestId('network-toggle'));
});
const commandoTorSelect = screen.getAllByTestId('network-item')[1];
await act(async () => {
fireEvent.click(commandoTorSelect);
});
expect(initialUrl).toHaveValue('commando+wss://'+ mockConnectWallet.LIGHTNING_WS_TOR_HOST + ':' + mockConnectWallet.LIGHTNING_WS_PORT + '?pubkey=' + mockConnectWallet.NODE_PUBKEY + '&rune=' + mockConnectWallet.ADMIN_RUNE + '&invoiceRune=' + mockConnectWallet.INVOICE_RUNE + '&certs=' + mockConnectWallet.LIGHTNING_WS_TLS_CERTS);
await act(async () => {
fireEvent.click(screen.getByTestId('network-toggle'));
});
Expand All @@ -76,7 +84,7 @@ describe('ConnectWallet component', () => {
await act(async () => {
fireEvent.click(copyClick);
});
expect(copyTextToClipboard).toHaveBeenCalledWith('commando+wss://'+ mockConnectWallet.LIGHTNING_HOST + ':' + mockConnectWallet.LIGHTNING_WS_PORT + '?pubkey=' + mockConnectWallet.NODE_PUBKEY + '&rune=' + mockConnectWallet.ADMIN_RUNE + '&invoiceRune=' + mockConnectWallet.INVOICE_RUNE + '&certs=' + mockConnectWallet.LIGHTNING_WS_TLS_CERTS);
expect(copyTextToClipboard).toHaveBeenCalledWith('commando+wss://'+ mockConnectWallet.LIGHTNING_WS_HOST + ':' + mockConnectWallet.LIGHTNING_WS_PORT + '?pubkey=' + mockConnectWallet.NODE_PUBKEY + '&rune=' + mockConnectWallet.ADMIN_RUNE + '&invoiceRune=' + mockConnectWallet.INVOICE_RUNE + '&certs=' + mockConnectWallet.LIGHTNING_WS_TLS_CERTS);
});

it('displays the correct form based on selected network', async () => {
Expand Down Expand Up @@ -116,7 +124,7 @@ describe('ConnectWallet component', () => {
await renderWithProviders(<ConnectWallet />, { preloadedState: customMockStore });

const connectUrl = screen.getByTestId('connect-url');
expect(connectUrl).toHaveValue('commando+wss://'+ mockConnectWallet.LIGHTNING_HOST + ':' + mockConnectWallet.LIGHTNING_WS_PORT + '?pubkey=' + mockConnectWallet.NODE_PUBKEY + '&rune=' + mockConnectWallet.ADMIN_RUNE + '&invoiceRune=' + mockConnectWallet.INVOICE_RUNE + '&certs=' + mockConnectWallet.LIGHTNING_WS_TLS_CERTS);
expect(connectUrl).toHaveValue('commando+wss://'+ mockConnectWallet.LIGHTNING_WS_HOST + ':' + mockConnectWallet.LIGHTNING_WS_PORT + '?pubkey=' + mockConnectWallet.NODE_PUBKEY + '&rune=' + mockConnectWallet.ADMIN_RUNE + '&invoiceRune=' + mockConnectWallet.INVOICE_RUNE + '&certs=' + mockConnectWallet.LIGHTNING_WS_TLS_CERTS);
});

it('does not include invoice rune in URL when not available', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const ConnectWallet = () => {

useEffect(() => {
let newNetworkTypes: string[] = ['Commando'];
if (connectWallet.LIGHTNING_WS_PORT && connectWallet.LIGHTNING_TOR_HOST && connectWallet.LIGHTNING_TOR_HOST !== '') {
if (connectWallet.LIGHTNING_WS_PORT && connectWallet.LIGHTNING_WS_TOR_HOST && connectWallet.LIGHTNING_WS_TOR_HOST !== '') {
newNetworkTypes.push('Commando (Tor)');
}
if (connectWallet.LIGHTNING_REST_PORT) {
Expand Down Expand Up @@ -56,7 +56,7 @@ const ConnectWallet = () => {
const setConnectUrlOnChange = () => {
let newConnectUrl = '';
if (selNetwork === 'Commando' || selNetwork === 'Commando (Tor)') {
newConnectUrl = 'commando+' + connectWallet.LIGHTNING_WS_PROTOCOL + '://' + (selNetwork.includes('(Tor)') ? connectWallet.LIGHTNING_TOR_HOST : connectWallet.LIGHTNING_HOST) + ':' + connectWallet.LIGHTNING_WS_PORT + '?pubkey=' + connectWallet.NODE_PUBKEY + '&rune=' + connectWallet.ADMIN_RUNE + (connectWallet.INVOICE_RUNE != '' ? '&invoiceRune=' + connectWallet.INVOICE_RUNE : '') + (connectWallet.LIGHTNING_WS_PROTOCOL?.toLowerCase() === 'wss' ? '&certs=' + connectWallet.LIGHTNING_WS_TLS_CERTS : '');
newConnectUrl = 'commando+' + connectWallet.LIGHTNING_WS_PROTOCOL + '://' + (selNetwork.includes('(Tor)') ? connectWallet.LIGHTNING_WS_TOR_HOST : connectWallet.LIGHTNING_WS_HOST) + ':' + connectWallet.LIGHTNING_WS_PORT + '?pubkey=' + connectWallet.NODE_PUBKEY + '&rune=' + connectWallet.ADMIN_RUNE + (connectWallet.INVOICE_RUNE != '' ? '&invoiceRune=' + connectWallet.INVOICE_RUNE : '') + (connectWallet.LIGHTNING_WS_PROTOCOL?.toLowerCase() === 'wss' ? '&certs=' + connectWallet.LIGHTNING_WS_TLS_CERTS : '');
} else if (selNetwork === 'REST' || selNetwork === 'REST (Tor)') {
newConnectUrl = 'clnrest+' + connectWallet.LIGHTNING_REST_PROTOCOL + '://' + (selNetwork.includes('(Tor)') ? connectWallet.LIGHTNING_REST_TOR_HOST : connectWallet.LIGHTNING_REST_HOST) + ':' + connectWallet.LIGHTNING_REST_PORT + '?rune=' + connectWallet.ADMIN_RUNE + (connectWallet.LIGHTNING_REST_PROTOCOL?.toLowerCase() === 'https' ? '&certs=' + connectWallet.LIGHTNING_REST_TLS_CERTS : '');
} else if (selNetwork === 'gRPC' || selNetwork === 'gRPC (Tor)') {
Expand Down
2 changes: 2 additions & 0 deletions apps/frontend/src/types/root.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ export type WalletConnect = {
LIGHTNING_TOR_HOST?: string;
LIGHTNING_VARS_FILE?: string;
LIGHTNING_WS_PROTOCOL?: string;
LIGHTNING_WS_HOST?: string;
LIGHTNING_WS_TOR_HOST?: string;
LIGHTNING_WS_PORT?: number;
LIGHTNING_WS_CLIENT_KEY_FILE?: string;
LIGHTNING_WS_CLIENT_CERT_FILE?: string;
Expand Down
4 changes: 3 additions & 1 deletion apps/frontend/src/utilities/test-utilities/mockData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ export const mockConnectWallet = {
LIGHTNING_TOR_HOST: "lightning.tor.onion",
LIGHTNING_VARS_FILE: "/home/data/app/.commando",
LIGHTNING_WS_PROTOCOL: "wss",
LIGHTNING_WS_HOST: "localhost",
LIGHTNING_WS_TOR_HOST: "lightning.ws.tor.onion",
LIGHTNING_WS_PORT: 5015,
LIGHTNING_WS_CLIENT_KEY_FILE: "/home/network/regtest/client-key.pem",
LIGHTNING_WS_CLIENT_CERT_FILE: "/home/network/regtest/client.pem",
Expand Down Expand Up @@ -740,7 +742,7 @@ export const mockRootStoreData = {
showModals: mockShowModals,
showToast: mockShowToast,
connectWallet: mockConnectWallet,
connectionUrl: 'commando+' + mockConnectWallet.LIGHTNING_WS_PROTOCOL + '://' + mockConnectWallet.LIGHTNING_HOST + ':' + mockConnectWallet.LIGHTNING_WS_PORT + '?pubkey=' + mockConnectWallet.NODE_PUBKEY + '&rune=' + mockConnectWallet.ADMIN_RUNE + '&invoiceRune=' + mockConnectWallet.INVOICE_RUNE + '&certs=' + mockConnectWallet.LIGHTNING_WS_TLS_CERTS,
connectionUrl: 'commando+' + mockConnectWallet.LIGHTNING_WS_PROTOCOL + '://' + mockConnectWallet.LIGHTNING_WS_HOST + ':' + mockConnectWallet.LIGHTNING_WS_PORT + '?pubkey=' + mockConnectWallet.NODE_PUBKEY + '&rune=' + mockConnectWallet.ADMIN_RUNE + '&invoiceRune=' + mockConnectWallet.INVOICE_RUNE + '&certs=' + mockConnectWallet.LIGHTNING_WS_TLS_CERTS,
walletBalances: mockWalletBalances,
nodeInfo: mockNodeInfo,
listFunds: mockListFunds,
Expand Down
4 changes: 4 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ services:
APP_HOST: ${APP_HOST}
LIGHTNING_GRPC_PORT: ${LIGHTNING_GRPC_PORT}
LIGHTNING_REST_PORT: ${LIGHTNING_REST_PORT}
LIGHTNING_WS_HOST: ${LIGHTNING_WS_HOST}
LIGHTNING_WS_TOR_HOST: ${LIGHTNING_WS_TOR_HOST}
LIGHTNING_WS_PORT: ${LIGHTNING_WS_PORT}
LIGHTNING_TOR_HOST: ${LIGHTNING_TOR_HOST}
LIGHTNING_DATA_DIR: ${LIGHTNING_DATA_DIR}
Expand Down Expand Up @@ -115,6 +117,8 @@ services:
LIGHTNING_GRPC_PORT: 2115
LIGHTNING_REST_PORT: 2114
LIGHTNING_WS_PORT: 2116
LIGHTNING_WS_HOST: 170.21.22.13
LIGHTNING_WS_TOR_HOST: tor2.onion
LIGHTNING_TOR_HOST: tor2.onion
LIGHTNING_DATA_DIR: /data/.lightning-2
LIGHTNING_VARS_FILE: /data/.lightning-2/.commando-env
Expand Down
2 changes: 2 additions & 0 deletions env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export LIGHTNING_HOST="user.local"
export LIGHTNING_TOR_HOST="tor.onion"
export LIGHTNING_VARS_FILE="$PWD/.commando"
export LIGHTNING_WS_PROTOCOL="wss"
export LIGHTNING_WS_HOST="user.local"
export LIGHTNING_WS_TOR_HOST="tor.onion"
export LIGHTNING_WS_PORT=5001
export LIGHTNING_WS_CLIENT_KEY_FILE="/home/.lightning/regtest/client-key.pem"
export LIGHTNING_WS_CLIENT_CERT_FILE="/home/.lightning/regtest/client.pem"
Expand Down