Initialize repo for lightning experiments.

This commit is contained in:
Brian Lee 2024-06-15 12:37:15 -07:00
commit dab33740d0
9 changed files with 304 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
.vscode
.venv
archive
node_modules
assets
*-test.ts

1
README.md Normal file
View File

@ -0,0 +1 @@
# lightning payment experiments

90
docs/lightningd.md Normal file
View File

@ -0,0 +1,90 @@
# lightning payments
Simple payments app for core-lightning node (lightningd).
## Usage
* Start lightningd with the new rest api `--clnrest-port=3010` or configure it in `.lightning/config`
* Note that the clnrest plugin is bundled within lightningd, but its dependencies are not. You might need to `pip install -r requirements.txt` before it'll work.
* When the plugin is working, the lightningd log will show a message like `plugin-clnrest.py: REST server running at https://127.0.0.1:3010`
* Create a run with `lightning-cli commando-rune`
```shell
lightning-cli commando-rune restrictions='[["method^list", "method^get", "method=summary", "method~invoice", "method~offers"],["method/listdatastore"]]'
export RUNE=<node-rune>
curl -X GET 'http://localhost:3010/v1/list-methods' -H "Rune: ${RUNE}"
curl -k -X POST 'http://localhost:3010/v1/getinfo' -H "Rune: ${RUNE}"
curl -X POST 'http://localhost:3010/v1/listoffers' -H "Rune: ${RUNE}"
curl -X POST 'http://localhost:3010/v1/listinvoices' -H "Rune: ${RUNE}"
deno run --allow-net --unsafely-ignore-certificate-errors test.ts
```
* TODO: env var
## Resources
Swagger for lightningd will be on `https://192.168.0.42:3010`
* c-lightning-REST [API Docs](https://squirtle.satstack.net:4446/api-docs/)
* CLNRest [API Reference](https://docs.corelightning.org/reference/get_list_methods_resource)
* [CLNRest](https://docs.corelightning.org/docs/rest) has examples
## Copypasta
To run node.js in repl:
```sh
npm init -y
npm install fs socket.io-client
node
```
Paste code.
To run code in Deno:
```shell
deno repl --allow-net --unsafely-ignore-certificate-errors
```
## Decisions
### SQLite
Pros
* postgres typically wants a lot more memory, which motivates running it on a separate server
* some of our custom strfry-policies read from the same database, and strfry needs to reload the policies to import updates to the pubkey lists
* avoids introducing more failure methods, such as failing to connect to an external postgresql database
* reduces barrier to entry for other relay ops who might attempt to run the code themselves
Cons
* downsides to this choice includes increasing overhead memory requirements for the server, but the whole purpose of this code is to fund a better server anyway
* another downside is that the Deno sqlite integrations don't seem to be very mature
## Discovery Notes
Relevant methods
* Command: waitanyinvoice [lastpay_index] [timeout]
* Description: Wait for the next invoice to be paid, after {lastpay_index} (if supplied). If {timeout} seconds is reached while waiting, fail with an error.
* Command: waitinvoice label
* Description: Wait for an incoming payment matching the invoice with {label}, or if the invoice expires
* Command: listinvoices [label] [invstring] [payment_hash] [offer_id] [index] [start] [limit]
* Description: Show invoice matching {label}, {invstring}, {payment_hash} or {offerid} (or all, if no query parameter specified)
* Command: invoice amount_msat label description [expiry] [fallbacks] [preimage] [exposeprivatechannels] [cltv] [deschashonly] [dev-routes]
* Description: Create an invoice for {msatoshi} with {label} and {description} with optional {expiry} seconds (default 1 week), optional {fallbacks} address list(default empty list) and optional {preimage} (default autogenerated)
### Invoices
Generate one
```shell
lightning-cli invoice amount_msat=$((2 *1000)) label=$(openssl rand -hex 4) description="test 2" expiry=3600
curl -X POST 'http://localhost:3010/v1/listinvoices' -H "Rune: ${RUNE}"
```

11
docs/lnd.md Normal file
View File

@ -0,0 +1,11 @@
# lnd invoices
Use `--private` to fetch an invoice with route hints for a node that only has unannounced channels:
```sh
lncli addinvoice --private --expiry 3600 --memo npub1dxs2pygtfxsah77yuncsmu3ttqr274qr5g5zva3c7t5s3jtgy2xszsn4st 10
```
## Resources
* [REST API Documentation](https://lightning.engineering/api-docs/api/lnd/lightning/get-info)

14
lnd-get-info.py Normal file
View File

@ -0,0 +1,14 @@
from codecs import encode
import json
import requests
REST_HOST = '192.168.0.42:10010'
MACAROON_PATH = 'assets/readonly.macaroon'
TLS_PATH = 'assets/tls.cert'
url = f'https://{REST_HOST}/v1/getinfo'
macaroon = encode(open(MACAROON_PATH, 'rb').read(), 'hex')
headers = {'Grpc-Metadata-macaroon': macaroon}
r = requests.get(url, headers=headers, verify=TLS_PATH)
lnd_info = json.loads(r.text)
print(lnd_info)

3
lnd-get-info.sh Normal file
View File

@ -0,0 +1,3 @@
curl --cacert assets/tls.cert \
-H "Grpc-Metadata-macaroon: $(xxd -ps -u -c 10000 assets/readonly.macaroon)" \
https://192.168.0.42:10010/v1/getinfo | jq

41
lnd-get-info.ts Normal file
View File

@ -0,0 +1,41 @@
import { encodeHex } from "https://deno.land/std@0.224.0/encoding/hex.ts";
// Constants
const REST_HOST = '192.168.0.42:10010';
const MACAROON_PATH = 'assets/readonly.macaroon';
const TLS_PATH = 'assets/tls.cert';
const url = `https://${REST_HOST}/v1/getinfo`;
//const macaroonBytes = Deno.readTextFileSync(MACAROON_PATH);
//const macaroon = encodeHex(macaroonBytes).toString();
//console.log(macaroon);
using file = Deno.openSync(MACAROON_PATH, { read: true, write: false });
// Configure headers
const headers = new Headers({
'Grpc-Metadata-macaroon': macaroon,
});
// Function to make the GET request
async function getLndInfo() {
const response = await fetch(url, {
method: "GET",
headers: headers,
});
// Check if the response is OK
if (!response.ok) {
console.error("Failed to fetch:", response.status);
return;
}
// Parse the JSON response
const lndInfo = await response.json();
console.log(lndInfo);
}
// Execute the function
getLndInfo();
file.close();

122
package-lock.json generated Normal file
View File

@ -0,0 +1,122 @@
{
"name": "npub-pay-clnrest",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "npub-pay-clnrest",
"version": "0.0.1",
"license": "ISC",
"dependencies": {
"fs": "^0.0.1-security",
"socket.io-client": "^4.7.5"
}
},
"node_modules/@socket.io/component-emitter": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.1.tgz",
"integrity": "sha512-dzJtaDAAoXx4GCOJpbB2eG/Qj8VDpdwkLsWGzGm+0L7E8/434RyMbAHmk9ubXWVAb9nXmc44jUf8GKqVDiKezg=="
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/engine.io-client": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz",
"integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0",
"xmlhttprequest-ssl": "~2.0.0"
}
},
"node_modules/engine.io-parser": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz",
"integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/fs": {
"version": "0.0.1-security",
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
"integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w=="
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/socket.io-client": {
"version": "4.7.5",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz",
"integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.5.2",
"socket.io-parser": "~4.2.4"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/socket.io-parser": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/ws": {
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/xmlhttprequest-ssl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==",
"engines": {
"node": ">=0.4.0"
}
}
}
}

16
package.json Normal file
View File

@ -0,0 +1,16 @@
{
"name": "npub-pay-clnrest",
"version": "0.0.1",
"description": "Simple payments app for core-lightning node.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"fs": "^0.0.1-security",
"socket.io-client": "^4.7.5"
}
}