Skip to content

Commit 4399d8c

Browse files
ShahanaFarooquievansmjafxsoftware
authored
Release 0.0.6 (#73)
* Updating version number * Display Invoice Rune (#56) * Display Invoice Rune * Cosmetic updates for Invoice Rune * Update plus/add icon svg (#70) * Resolve commando-rune deprecation and use createrune instead (#72) * Change invoice and offer to lowercase (#68) * Add tests for address casing fix (#69) * Update jsx camelCase property name * Adding mock use-http hook * Add tests for invoice and offer capital casing --------- Co-authored-by: Michael Evans <[email protected]> Co-authored-by: afxsoftware <[email protected]>
1 parent 180e141 commit 4399d8c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+627
-120
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
- ### Commando Authentication
9292
- This application utilizes [lnmessage](https://github.com/aaronbarnardsound/lnmessage) and [commando](https://docs.corelightning.org/reference/lightning-commando) for connecting with core lightning node. The connection is trustless and end-to-end encrypted. Commando manages authentication and authorization through runes, which can grant either full or fine-grained permissions.
9393
- The backend server reads `LIGHTNING_PUBKEY` & `LIGHTNING_RUNE` from the `COMMANDO_CONFIG` file for this communication.
94-
- Values can either be set manually or script `entrypoint.sh` can be used to call `getinfo` and `commando-rune` methods and save values in `COMMANDO_CONFIG`.
94+
- Values can either be set manually or script `entrypoint.sh` can be used to call `getinfo` and `createrune` methods and save values in `COMMANDO_CONFIG`.
9595
- `entrypoint.sh` can only run for the locally installed lightning. If `cln-application` is running remotely then pubkey and
9696
rune can be set manually.
9797
- Sample commando config should look like:

apps/backend/dist/controllers/shared.js

+22
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import handleError from '../shared/error-handler.js';
66
import { APIError } from '../models/errors.js';
77
import { setSharedApplicationConfig, overrideSettingsWithEnvVariables } from '../shared/utils.js';
88
import { sep } from 'path';
9+
import { LNMessage } from '../service/lightning.service.js';
910
class SharedController {
1011
getApplicationSettings(req, res, next) {
1112
try {
@@ -72,6 +73,7 @@ class SharedController {
7273
.replace('-----BEGIN CERTIFICATE-----', '')
7374
.replace('-----END CERTIFICATE-----', '');
7475
}
76+
LNMessage.refreshEnvVariables();
7577
const CONNECT_WALLET_SETTINGS = {
7678
LOCAL_HOST: process.env.LOCAL_HOST || '',
7779
DEVICE_DOMAIN_NAME: process.env.DEVICE_DOMAIN_NAME || '',
@@ -87,6 +89,7 @@ class SharedController {
8789
NODE_PUBKEY: process.env.LIGHTNING_PUBKEY || '',
8890
COMMANDO_RUNE: process.env.COMMANDO_RUNE,
8991
APP_VERSION: JSON.parse(packageData).version || '',
92+
INVOICE_RUNE: process.env.INVOICE_RUNE || '',
9093
};
9194
res.status(200).json(CONNECT_WALLET_SETTINGS);
9295
}
@@ -119,5 +122,24 @@ class SharedController {
119122
handleError(error, req, res, next);
120123
}
121124
}
125+
async saveInvoiceRune(req, res, next) {
126+
try {
127+
logger.info('Saving Invoice Rune');
128+
const showRunes = await LNMessage.call('showrunes', []);
129+
const invoiceRune = showRunes.runes.find(rune => rune.restrictions.some(restriction => restriction.alternatives.some(alternative => alternative.value === 'invoice')) &&
130+
rune.restrictions.some(restriction => restriction.alternatives.some(alternative => alternative.value === 'listinvoices')));
131+
if (invoiceRune && fs.existsSync(APP_CONSTANTS.COMMANDO_ENV_LOCATION)) {
132+
const invoiceRuneString = `INVOICE_RUNE="${invoiceRune.rune}"\n`;
133+
fs.appendFileSync(APP_CONSTANTS.COMMANDO_ENV_LOCATION, invoiceRuneString, 'utf-8');
134+
res.status(201).send();
135+
}
136+
else {
137+
throw new Error('Invoice rune not found or .commando-env does not exist.');
138+
}
139+
}
140+
catch (error) {
141+
handleError(error, req, res, next);
142+
}
143+
}
122144
}
123145
export default new SharedController();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export {};

apps/backend/dist/routes/v1/shared.js

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ export class SharedRoutes extends CommonRoutesConfig {
2525
this.app
2626
.route(API_VERSION + SHARED_ROUTE + '/rate/:fiatCurrency')
2727
.get(SharedController.getFiatRate);
28+
this.app
29+
.route(API_VERSION + SHARED_ROUTE + '/saveinvoicerune/')
30+
.post(AuthController.isUserAuthenticated, SharedController.saveInvoiceRune);
2831
return this.app;
2932
}
3033
}

apps/backend/dist/service/lightning.service.js

+29-5
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,14 @@ import Lnmessage from 'lnmessage';
44
import { LightningError } from '../models/errors.js';
55
import { HttpStatusCode, APP_CONSTANTS, LN_MESSAGE_CONFIG } from '../shared/consts.js';
66
import { logger } from '../shared/logger.js';
7+
import { readFileSync } from 'fs';
78
export class LightningService {
89
lnMessage = null;
910
constructor() {
1011
try {
1112
logger.info('Getting Commando Rune');
1213
if (fs.existsSync(APP_CONSTANTS.COMMANDO_ENV_LOCATION)) {
13-
const DATA_SPLIT = (Buffer.from(fs.readFileSync(APP_CONSTANTS.COMMANDO_ENV_LOCATION)).toString() || '\n').split('\n');
14-
process.env.LIGHTNING_PUBKEY = DATA_SPLIT[0].substring(18, DATA_SPLIT[0].length - 1);
15-
process.env.COMMANDO_RUNE = DATA_SPLIT[1].substring(16, DATA_SPLIT[1].length - 1);
16-
LN_MESSAGE_CONFIG.remoteNodePublicKey = process.env.LIGHTNING_PUBKEY;
17-
APP_CONSTANTS.COMMANDO_RUNE = process.env.COMMANDO_RUNE;
14+
this.refreshEnvVariables();
1815
logger.info('lnMessage connecting with config: ' + JSON.stringify(LN_MESSAGE_CONFIG));
1916
this.lnMessage = new Lnmessage(LN_MESSAGE_CONFIG);
2017
this.lnMessage.connect();
@@ -53,5 +50,32 @@ export class LightningService {
5350
}
5451
});
5552
};
53+
refreshEnvVariables() {
54+
const envVars = this.parseEnvFile(APP_CONSTANTS.COMMANDO_ENV_LOCATION);
55+
process.env.LIGHTNING_PUBKEY = envVars.LIGHTNING_PUBKEY;
56+
process.env.COMMANDO_RUNE = envVars.LIGHTNING_RUNE;
57+
process.env.INVOICE_RUNE = envVars.INVOICE_RUNE !== undefined ? envVars.INVOICE_RUNE : '';
58+
LN_MESSAGE_CONFIG.remoteNodePublicKey = process.env.LIGHTNING_PUBKEY;
59+
APP_CONSTANTS.COMMANDO_RUNE = process.env.COMMANDO_RUNE;
60+
}
61+
parseEnvFile(filePath) {
62+
try {
63+
const content = readFileSync(filePath, 'utf8');
64+
const lines = content.split('\n');
65+
const envVars = {};
66+
for (let line of lines) {
67+
line = line.trim();
68+
if (line && line.indexOf('=') !== -1 && !line.startsWith('#')) {
69+
const [key, ...value] = line.split('=');
70+
envVars[key] = value.join('=').replace(/(^"|"$)/g, '');
71+
}
72+
}
73+
return envVars;
74+
}
75+
catch (err) {
76+
logger.error('Error reading .commando-env file:', err);
77+
return {};
78+
}
79+
}
5680
}
5781
export const LNMessage = new LightningService();

apps/backend/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cln-application-backend",
3-
"version": "0.0.5",
3+
"version": "0.0.6",
44
"description": "Core lightning application backend",
55
"private": true,
66
"license": "MIT",

apps/backend/source/controllers/shared.ts

+29
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import handleError from '../shared/error-handler.js';
88
import { APIError } from '../models/errors.js';
99
import { setSharedApplicationConfig, overrideSettingsWithEnvVariables } from '../shared/utils.js';
1010
import { sep } from 'path';
11+
import { LNMessage } from '../service/lightning.service.js';
12+
import { ShowRunes } from '../models/showrunes.type.js';
1113

1214
class SharedController {
1315
getApplicationSettings(req: Request, res: Response, next: NextFunction) {
@@ -82,6 +84,7 @@ class SharedController {
8284
.replace('-----BEGIN CERTIFICATE-----', '')
8385
.replace('-----END CERTIFICATE-----', '');
8486
}
87+
LNMessage.refreshEnvVariables();
8588
const CONNECT_WALLET_SETTINGS = {
8689
LOCAL_HOST: process.env.LOCAL_HOST || '',
8790
DEVICE_DOMAIN_NAME: process.env.DEVICE_DOMAIN_NAME || '',
@@ -97,6 +100,7 @@ class SharedController {
97100
NODE_PUBKEY: process.env.LIGHTNING_PUBKEY || '',
98101
COMMANDO_RUNE: process.env.COMMANDO_RUNE,
99102
APP_VERSION: JSON.parse(packageData).version || '',
103+
INVOICE_RUNE: process.env.INVOICE_RUNE || '',
100104
};
101105
res.status(200).json(CONNECT_WALLET_SETTINGS);
102106
} catch (error: any) {
@@ -127,6 +131,31 @@ class SharedController {
127131
handleError(error, req, res, next);
128132
}
129133
}
134+
135+
async saveInvoiceRune(req: Request, res: Response, next: NextFunction) {
136+
try {
137+
logger.info('Saving Invoice Rune');
138+
const showRunes: ShowRunes = await LNMessage.call('showrunes', []);
139+
const invoiceRune = showRunes.runes.find(
140+
rune =>
141+
rune.restrictions.some(restriction =>
142+
restriction.alternatives.some(alternative => alternative.value === 'invoice'),
143+
) &&
144+
rune.restrictions.some(restriction =>
145+
restriction.alternatives.some(alternative => alternative.value === 'listinvoices'),
146+
),
147+
);
148+
if (invoiceRune && fs.existsSync(APP_CONSTANTS.COMMANDO_ENV_LOCATION)) {
149+
const invoiceRuneString = `INVOICE_RUNE="${invoiceRune.rune}"\n`;
150+
fs.appendFileSync(APP_CONSTANTS.COMMANDO_ENV_LOCATION, invoiceRuneString, 'utf-8');
151+
res.status(201).send();
152+
} else {
153+
throw new Error('Invoice rune not found or .commando-env does not exist.');
154+
}
155+
} catch (error: any) {
156+
handleError(error, req, res, next);
157+
}
158+
}
130159
}
131160

132161
export default new SharedController();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
export type ShowRunes = {
2+
runes: Rune[];
3+
isLoading: boolean;
4+
error?: any;
5+
};
6+
7+
export type Rune = {
8+
rune: string;
9+
unique_id: string;
10+
restrictions: Restriction[];
11+
restrictions_as_english: string;
12+
stored?: boolean;
13+
blacklisted?: boolean;
14+
last_used?: number;
15+
our_rune?: boolean;
16+
};
17+
18+
export type Restriction = {
19+
alternatives: Alternative[];
20+
english: string;
21+
};
22+
23+
export type Alternative = {
24+
fieldname: string;
25+
value: string;
26+
condition: string;
27+
english: string;
28+
};

apps/backend/source/routes/v1/shared.ts

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ export class SharedRoutes extends CommonRoutesConfig {
3030
this.app
3131
.route(API_VERSION + SHARED_ROUTE + '/rate/:fiatCurrency')
3232
.get(SharedController.getFiatRate);
33+
this.app
34+
.route(API_VERSION + SHARED_ROUTE + '/saveinvoicerune/')
35+
.post(AuthController.isUserAuthenticated, SharedController.saveInvoiceRune);
3336
return this.app;
3437
}
3538
}

apps/backend/source/service/lightning.service.ts

+33-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Lnmessage from 'lnmessage';
44
import { LightningError } from '../models/errors.js';
55
import { HttpStatusCode, APP_CONSTANTS, LN_MESSAGE_CONFIG } from '../shared/consts.js';
66
import { logger } from '../shared/logger.js';
7+
import { readFileSync } from 'fs';
78

89
export class LightningService {
910
private lnMessage: any = null;
@@ -12,13 +13,7 @@ export class LightningService {
1213
try {
1314
logger.info('Getting Commando Rune');
1415
if (fs.existsSync(APP_CONSTANTS.COMMANDO_ENV_LOCATION)) {
15-
const DATA_SPLIT = (
16-
Buffer.from(fs.readFileSync(APP_CONSTANTS.COMMANDO_ENV_LOCATION)).toString() || '\n'
17-
).split('\n');
18-
process.env.LIGHTNING_PUBKEY = DATA_SPLIT[0].substring(18, DATA_SPLIT[0].length - 1);
19-
process.env.COMMANDO_RUNE = DATA_SPLIT[1].substring(16, DATA_SPLIT[1].length - 1);
20-
LN_MESSAGE_CONFIG.remoteNodePublicKey = process.env.LIGHTNING_PUBKEY;
21-
APP_CONSTANTS.COMMANDO_RUNE = process.env.COMMANDO_RUNE;
16+
this.refreshEnvVariables();
2217
logger.info('lnMessage connecting with config: ' + JSON.stringify(LN_MESSAGE_CONFIG));
2318
this.lnMessage = new Lnmessage(LN_MESSAGE_CONFIG);
2419
this.lnMessage.connect();
@@ -67,6 +62,37 @@ export class LightningService {
6762
}
6863
});
6964
};
65+
66+
refreshEnvVariables() {
67+
const envVars = this.parseEnvFile(APP_CONSTANTS.COMMANDO_ENV_LOCATION);
68+
69+
process.env.LIGHTNING_PUBKEY = envVars.LIGHTNING_PUBKEY;
70+
process.env.COMMANDO_RUNE = envVars.LIGHTNING_RUNE;
71+
process.env.INVOICE_RUNE = envVars.INVOICE_RUNE !== undefined ? envVars.INVOICE_RUNE : '';
72+
LN_MESSAGE_CONFIG.remoteNodePublicKey = process.env.LIGHTNING_PUBKEY;
73+
APP_CONSTANTS.COMMANDO_RUNE = process.env.COMMANDO_RUNE;
74+
}
75+
76+
private parseEnvFile(filePath: string): { [key: string]: string } {
77+
try {
78+
const content = readFileSync(filePath, 'utf8');
79+
const lines = content.split('\n');
80+
const envVars: { [key: string]: string } = {};
81+
82+
for (let line of lines) {
83+
line = line.trim();
84+
if (line && line.indexOf('=') !== -1 && !line.startsWith('#')) {
85+
const [key, ...value] = line.split('=');
86+
envVars[key] = value.join('=').replace(/(^"|"$)/g, '');
87+
}
88+
}
89+
90+
return envVars;
91+
} catch (err) {
92+
logger.error('Error reading .commando-env file:', err);
93+
return {};
94+
}
95+
}
7096
}
7197

7298
export const LNMessage = new LightningService();
+6-6
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
{
22
"files": {
3-
"main.css": "/static/css/main.6598f92c.css",
4-
"main.js": "/static/js/main.7b5c5d6e.js",
3+
"main.css": "/static/css/main.1ce19166.css",
4+
"main.js": "/static/js/main.2875dcdc.js",
55
"static/media/Inter-Bold.ttf": "/static/media/Inter-Bold.88fa7ae373b07b41ecce.ttf",
66
"static/media/Inter-SemiBold.ttf": "/static/media/Inter-SemiBold.4d56bb21f2399db8ad48.ttf",
77
"static/media/Inter-Medium.ttf": "/static/media/Inter-Medium.6dcbc9bed1ec438907ee.ttf",
88
"static/media/Inter-Thin.ttf": "/static/media/Inter-Thin.f341ca512063c66296d1.ttf",
99
"index.html": "/index.html",
10-
"main.6598f92c.css.map": "/static/css/main.6598f92c.css.map",
11-
"main.7b5c5d6e.js.map": "/static/js/main.7b5c5d6e.js.map"
10+
"main.1ce19166.css.map": "/static/css/main.1ce19166.css.map",
11+
"main.2875dcdc.js.map": "/static/js/main.2875dcdc.js.map"
1212
},
1313
"entrypoints": [
14-
"static/css/main.6598f92c.css",
15-
"static/js/main.7b5c5d6e.js"
14+
"static/css/main.1ce19166.css",
15+
"static/js/main.2875dcdc.js"
1616
]
1717
}

apps/frontend/build/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +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.7b5c5d6e.js"></script><link href="/static/css/main.6598f92c.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
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.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>

apps/frontend/build/static/css/main.6598f92c.css apps/frontend/build/static/css/main.1ce19166.css

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/frontend/build/static/css/main.1ce19166.css.map

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/frontend/build/static/css/main.6598f92c.css.map

-1
This file was deleted.

apps/frontend/build/static/js/main.2875dcdc.js

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/frontend/build/static/js/main.2875dcdc.js.map

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/frontend/build/static/js/main.4501e70f.js

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)