Initialize repo for lightning experiments.
This commit is contained in:
commit
dab33740d0
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
.vscode
|
||||
.venv
|
||||
archive
|
||||
node_modules
|
||||
assets
|
||||
*-test.ts
|
90
docs/lightningd.md
Normal file
90
docs/lightningd.md
Normal 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
11
docs/lnd.md
Normal 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
14
lnd-get-info.py
Normal 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
3
lnd-get-info.sh
Normal 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
41
lnd-get-info.ts
Normal 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
122
package-lock.json
generated
Normal 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
16
package.json
Normal 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"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user