Skip to content

Commit 82e84d6

Browse files
ShahanaFarooquicdecker
authored andcommitted
Updated javascript example
Fixed bug due to encodeDelimited function.
1 parent 92e10b5 commit 82e84d6

File tree

2 files changed

+58
-40
lines changed

2 files changed

+58
-40
lines changed

examples/javascript/README.md

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,32 +45,24 @@ lightning-hsmtool getnodeid $HOME/greenlight/.gltestserver/gl-testserver/hsm_sec
4545
```
4646
Sample Output: 034c46b632a9ff3975fb7cd4e764a36ec476b522be2555e83a3183ab1ee3e36e93
4747

48-
### 5.3: Encode Node ID to Base64
49-
```python
50-
import binascii
51-
import base64
52-
print(base64.b64encode(binascii.unhexlify("<node id from step 5.2>")).decode('utf-8'))
53-
```
54-
Sample Output: A0xGtjKp/zl1+3zU52SjbsR2tSK+JVXoOjGDqx7j426T
55-
56-
### 5.4: Modify Default Values
48+
### 5.3: Modify Default Values
5749
- Open the file `./examples/javascript/grpc-web-proxy-client.js`.
5850

59-
- Locate the line defining `AUTH_PUBKEY` and replace its value with the Base64-encoded public key output from Step 5.3:
51+
- Locate the line defining `NODE_PUBKEY` and replace its value with your node's public key from Step 5.2:
6052

6153
```javascript
62-
const AUTH_PUBKEY = 'replace+this+with+your+base64+encoded+pubkey';
54+
const NODE_PUBKEY = 'yournodepubkeyhexvalue00000000000000000000000000000000000000000000';
6355
```
6456

65-
- Replace the default PORT value `1111` with the port number from `grpc_web_proxy_uri` obtained in Step 1:
57+
- If `getPortFromMetadata` fails to retrieve the gRPC port value, replace the default `PORT` value (`1111`) with the port number extracted from the `grpc_web_proxy_uri` obtained in Step 1.
6658
```javascript
67-
const PORT = process.argv[2] || '1111';
59+
const PORT = process.argv[2] || getPortFromMetadata() || '1111';
6860
```
6961
Alternatively, the port number can be passed as a command-line argument when running the nodejs script in the next step.
7062

7163
- Save the changes to the file.
7264

73-
### 5.5: Run the Example
65+
### 5.4: Run the Example
7466
```bash
7567
node grpc-web-proxy-client.js
7668
```

examples/javascript/grpc-web-proxy-client.js

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,36 @@
1+
const fs = require('fs');
12
const path = require('path');
23
const axios = require('axios');
34
const protobuf = require('protobufjs');
45

5-
const PORT = process.argv[2] || '1111';
6-
const AUTH_PUBKEY = 'replace+this+with+your+base64+encoded+pubkey';
6+
const PORT = process.argv[2] || getPortFromMetadata() || '1111';
7+
const NODE_PUBKEY = 'yournodepubkeyhexvalue00000000000000000000000000000000000000000000';
8+
const AUTH_PUBKEY = Buffer.from(NODE_PUBKEY, 'hex').toString('base64');
79
const AUTH_SIGNATURE = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
810
const PROTO_PATHS = [
911
path.join(process.cwd(), '../../libs/gl-client/.resources/proto/node.proto'),
1012
path.join(process.cwd(), '../../libs/gl-client/.resources/proto/primitives.proto')
1113
];
1214

15+
function getPortFromMetadata() {
16+
try {
17+
const grpcWebProxyUri = JSON.parse(fs.readFileSync('../../metadata.json')).grpc_web_proxy_uri;
18+
if (!grpcWebProxyUri) {
19+
console.error('grpc_web_proxy_uri not found in metadata.json');
20+
return null;
21+
}
22+
const grpc_port = new URL(grpcWebProxyUri).port;
23+
if (!grpc_port) {
24+
console.error('Port not found in grpc_web_proxy_uri');
25+
return null;
26+
}
27+
return grpc_port;
28+
} catch (error) {
29+
console.error('Error reading metadata.json: ', error.message);
30+
return null;
31+
}
32+
}
33+
1334
function getGrpcErrorMessage(grpcStatusCode) {
1435
const grpcStatusMessages = {
1536
0: 'OK: The operation completed successfully.',
@@ -37,11 +58,13 @@ async function encodePayload(clnNode, method, payload) {
3758
const methodRequest = clnNode.lookupType(`cln.${method}Request`);
3859
const errMsg = methodRequest.verify(payload);
3960
if (errMsg) throw new Error(errMsg);
40-
const header = Buffer.alloc(4);
41-
header.writeUInt8(0, 0);
4261
const requestPayload = methodRequest.create(payload);
43-
const encodedPayload = methodRequest.encodeDelimited(requestPayload).finish();
44-
return Buffer.concat([header, encodedPayload]);
62+
const encodedPayload = methodRequest.encode(requestPayload).finish();
63+
const flags = Buffer.alloc(1);
64+
flags.writeUInt8(0, 0);
65+
const header = Buffer.alloc(4);
66+
header.writeUInt32BE(encodedPayload.length, 0);
67+
return Buffer.concat([flags, header, encodedPayload]);
4568
}
4669

4770
async function sendRequest(methodUrl, encodedPayload) {
@@ -72,31 +95,34 @@ function transformValue(key, value) {
7295
}
7396

7497
function decodeResponse(clnNode, method, response) {
75-
const methodResponse = clnNode.lookupType(`cln.${method}Response`)
76-
const offset = 5;
77-
const responseData = new Uint8Array(response.data).slice(offset);
98+
const methodResponse = clnNode.lookupType(`cln.${method}Response`);
99+
const dataBuffer = Buffer.from(response.data);
100+
const resFlag = dataBuffer.subarray(0, 1);
101+
const resDataLength = dataBuffer.subarray(1, 5);
102+
const responseData = dataBuffer.subarray(5);
78103
const grpcStatus = +response.headers['grpc-status'];
79104
if (grpcStatus !== 0) {
80-
let errorDecoded = new TextDecoder("utf-8").decode(responseData);
81-
if (errorDecoded !== 'None') {
82-
errorDecoded = JSON.parse(errorDecoded.replace(/([a-zA-Z0-9_]+):/g, '"$1":'));
83-
} else {
84-
errorDecoded = {code: grpcStatus, message: getGrpcErrorMessage(grpcStatus)};
85-
}
86-
return { grpc_code: grpcStatus, grpc_error: getGrpcErrorMessage(grpcStatus), error: errorDecoded};
87-
} else {
88-
// FIXME: Use decodeDelimited
89-
const decodedRes = methodResponse.decode(responseData);
90-
const decodedResObject = methodResponse.toObject(decodedRes, {
105+
let errorMessage = 'None';
106+
try {
107+
errorMessage = decodeURIComponent(new TextDecoder('utf-8').decode(responseData)).trim();
108+
if (errorMessage == 'None') {
109+
errorMessage = getGrpcErrorMessage(grpcStatus);
110+
}
111+
} catch (decodeError) {
112+
errorMessage = decodeError;
113+
}
114+
throw new Error(errorMessage);
115+
}
116+
const decodedRes = methodResponse.decode(responseData);
117+
const decodedResObject = methodResponse.toObject(decodedRes, {
91118
longs: String,
92119
enums: String,
93120
bytes: Buffer,
94121
defaults: true,
95122
arrays: true,
96123
objects: true,
97-
});
98-
return JSON.parse(JSON.stringify(decodedResObject, transformValue));
99-
}
124+
});
125+
return JSON.parse(JSON.stringify(decodedResObject, transformValue));
100126
}
101127

102128
async function fetchNodeData() {
@@ -120,14 +146,14 @@ async function fetchNodeData() {
120146
console.log('\nResponse Decoded:');
121147
console.dir(responseJSON, { depth: null, color: true });
122148
} catch (error) {
123-
console.error('\nResponse Error:\n', error.response.status, ' - ', error.response.statusText);
149+
console.error('\nResponse Error:\n', error.response?.status || error.code, ' - ', error.response?.statusText || error.response?.data || error.message || '');
124150
}
125151
}
126152
} catch (error) {
127153
console.error('Error:', error.message);
128154
if (error.response) {
129-
console.error('Error status:', error.response.status);
130-
console.error('Error data:', error.response.data);
155+
console.error('Error status:', error.response?.status || error.code);
156+
console.error('Error data:', error.response?.statusText || error.response?.data || error.message || '');
131157
}
132158
}
133159
}

0 commit comments

Comments
 (0)