From c1af6018159f7d2b6317f10136a2fa593b46068b Mon Sep 17 00:00:00 2001 From: ShahanaFarooqui Date: Tue, 18 Nov 2025 21:47:42 -0800 Subject: [PATCH] Add `LIGHTNING_WS_HOST` and `LIGHTNING_WS_TOR_HOST` Closes #134 --- .github/docs/Docker-Setup.md | 2 ++ README.md | 6 ++++-- apps/backend/source/shared/consts.ts | 9 +++++++-- .../CommandoForm/CommandoForm.test.tsx | 6 +++--- .../ConnectWallet/CommandoForm/CommandoForm.tsx | 6 +++--- .../modals/ConnectWallet/ConnectWallet.test.tsx | 14 +++++++++++--- .../modals/ConnectWallet/ConnectWallet.tsx | 4 ++-- apps/frontend/src/types/root.type.ts | 2 ++ .../src/utilities/test-utilities/mockData.tsx | 4 +++- docker-compose.yml | 4 ++++ env.sh | 2 ++ 11 files changed, 43 insertions(+), 16 deletions(-) diff --git a/.github/docs/Docker-Setup.md b/.github/docs/Docker-Setup.md index fa97bd3f..4fb2a0e2 100644 --- a/.github/docs/Docker-Setup.md +++ b/.github/docs/Docker-Setup.md @@ -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 ``` diff --git a/README.md b/README.md index e3c98b27..571d9893 100644 --- a/README.md +++ b/README.md @@ -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`) diff --git a/apps/backend/source/shared/consts.ts b/apps/backend/source/shared/consts.ts index e74c3fc3..8c4e5e0a 100755 --- a/apps/backend/source/shared/consts.ts +++ b/apps/backend/source/shared/consts.ts @@ -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', @@ -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, @@ -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) => diff --git a/apps/frontend/src/components/modals/ConnectWallet/CommandoForm/CommandoForm.test.tsx b/apps/frontend/src/components/modals/ConnectWallet/CommandoForm/CommandoForm.test.tsx index 11ef9023..4ab22391 100644 --- a/apps/frontend/src/components/modals/ConnectWallet/CommandoForm/CommandoForm.test.tsx +++ b/apps/frontend/src/components/modals/ConnectWallet/CommandoForm/CommandoForm.test.tsx @@ -51,7 +51,7 @@ describe('CommandoForm Component', () => { it('displays correct values for Commando network', async () => { await renderWithProviders(, { 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); @@ -68,7 +68,7 @@ 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 () => { @@ -76,7 +76,7 @@ describe('CommandoForm Component', () => { await renderWithProviders(, { 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 }, diff --git a/apps/frontend/src/components/modals/ConnectWallet/CommandoForm/CommandoForm.tsx b/apps/frontend/src/components/modals/ConnectWallet/CommandoForm/CommandoForm.tsx index d0faec54..3ba69c54 100755 --- a/apps/frontend/src/components/modals/ConnectWallet/CommandoForm/CommandoForm.tsx +++ b/apps/frontend/src/components/modals/ConnectWallet/CommandoForm/CommandoForm.tsx @@ -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() || ''; @@ -108,8 +108,8 @@ const CommandoForm = ({ selNetwork }) => { { it('updates the connection URL when network is changed', async () => { await renderWithProviders(, { 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')); }); @@ -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 () => { @@ -116,7 +124,7 @@ describe('ConnectWallet component', () => { await renderWithProviders(, { 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 () => { diff --git a/apps/frontend/src/components/modals/ConnectWallet/ConnectWallet.tsx b/apps/frontend/src/components/modals/ConnectWallet/ConnectWallet.tsx index 0988dfa2..874b56b2 100755 --- a/apps/frontend/src/components/modals/ConnectWallet/ConnectWallet.tsx +++ b/apps/frontend/src/components/modals/ConnectWallet/ConnectWallet.tsx @@ -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) { @@ -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)') { diff --git a/apps/frontend/src/types/root.type.ts b/apps/frontend/src/types/root.type.ts index fa019354..78838018 100755 --- a/apps/frontend/src/types/root.type.ts +++ b/apps/frontend/src/types/root.type.ts @@ -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; diff --git a/apps/frontend/src/utilities/test-utilities/mockData.tsx b/apps/frontend/src/utilities/test-utilities/mockData.tsx index 5d10e79b..1f7486d7 100644 --- a/apps/frontend/src/utilities/test-utilities/mockData.tsx +++ b/apps/frontend/src/utilities/test-utilities/mockData.tsx @@ -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", @@ -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, diff --git a/docker-compose.yml b/docker-compose.yml index 31e27de1..2e127ddb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -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} @@ -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 diff --git a/env.sh b/env.sh index 4345e10e..c514a0c9 100755 --- a/env.sh +++ b/env.sh @@ -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"