Merge pull request #4236 from guggero/grpc-docs
docs: update instructions for JavaScript and Python on how to use gRPC
This commit is contained in:
commit
2190bc7af9
@ -1,15 +1,16 @@
|
|||||||
# How to write a simple `lnd` client in Javascript using `node.js`
|
# How to write a simple `lnd` client in Javascript using `node.js`
|
||||||
|
|
||||||
### Setup and Installation
|
## Setup and Installation
|
||||||
|
|
||||||
First, you'll need to initialize a simple nodejs project:
|
First, you'll need to initialize a simple nodejs project:
|
||||||
```
|
```
|
||||||
npm init (or npm init -f if you want to use the default values without prompt)
|
npm init (or npm init -f if you want to use the default values without prompt)
|
||||||
```
|
```
|
||||||
|
|
||||||
Then you need to install the Javascript grpc library dependency:
|
Then you need to install the Javascript grpc and proto loader library
|
||||||
|
dependencies:
|
||||||
```
|
```
|
||||||
npm install grpc --save
|
npm install grpc @grpc/proto-loader --save
|
||||||
```
|
```
|
||||||
|
|
||||||
You also need to copy the `lnd` `rpc.proto` file in your project directory (or
|
You also need to copy the `lnd` `rpc.proto` file in your project directory (or
|
||||||
@ -18,49 +19,57 @@ at least somewhere reachable by your Javascript code).
|
|||||||
The `rpc.proto` file is [located in the `lnrpc` directory of the `lnd`
|
The `rpc.proto` file is [located in the `lnrpc` directory of the `lnd`
|
||||||
sources](https://github.com/lightningnetwork/lnd/blob/master/lnrpc/rpc.proto).
|
sources](https://github.com/lightningnetwork/lnd/blob/master/lnrpc/rpc.proto).
|
||||||
|
|
||||||
In order for the auto-generated code to compile successfully, you'll need to
|
### Imports and Client
|
||||||
comment out the following line:
|
|
||||||
|
|
||||||
```
|
|
||||||
//import "google/api/annotations.proto";
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Imports and Client
|
|
||||||
|
|
||||||
Every time you work with Javascript gRPC, you will have to import `grpc`, load
|
Every time you work with Javascript gRPC, you will have to import `grpc`, load
|
||||||
`rpc.proto`, and create a connection to your client like so:
|
`rpc.proto`, and create a connection to your client like so:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var grpc = require('grpc');
|
const grpc = require('grpc');
|
||||||
var fs = require("fs");
|
const protoLoader = require('@grpc/proto-loader');
|
||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
// Due to updated ECDSA generated tls.cert we need to let gprc know that
|
// Due to updated ECDSA generated tls.cert we need to let gprc know that
|
||||||
// we need to use that cipher suite otherwise there will be a handhsake
|
// we need to use that cipher suite otherwise there will be a handhsake
|
||||||
// error when we communicate with the lnd rpc server.
|
// error when we communicate with the lnd rpc server.
|
||||||
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA'
|
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA'
|
||||||
|
|
||||||
|
// We need to give the proto loader some extra options, otherwise the code won't
|
||||||
|
// fully work with lnd.
|
||||||
|
const loaderOptions = {
|
||||||
|
keepCase: true,
|
||||||
|
longs: String,
|
||||||
|
enums: String,
|
||||||
|
defaults: true,
|
||||||
|
oneofs: true
|
||||||
|
};
|
||||||
|
const packageDefinition = protoLoader.loadSync('rpc.proto', loaderOptions);
|
||||||
|
|
||||||
// Lnd cert is at ~/.lnd/tls.cert on Linux and
|
// Lnd cert is at ~/.lnd/tls.cert on Linux and
|
||||||
// ~/Library/Application Support/Lnd/tls.cert on Mac
|
// ~/Library/Application Support/Lnd/tls.cert on Mac
|
||||||
var lndCert = fs.readFileSync("~/.lnd/tls.cert");
|
let lndCert = fs.readFileSync("~/.lnd/tls.cert");
|
||||||
var credentials = grpc.credentials.createSsl(lndCert);
|
let credentials = grpc.credentials.createSsl(lndCert);
|
||||||
var lnrpcDescriptor = grpc.load("rpc.proto");
|
let lnrpcDescriptor = grpc.loadPackageDefinition(packageDefinition);
|
||||||
var lnrpc = lnrpcDescriptor.lnrpc;
|
let lnrpc = lnrpcDescriptor.lnrpc;
|
||||||
var lightning = new lnrpc.Lightning('localhost:10009', credentials);
|
let lightning = new lnrpc.Lightning('localhost:10009', credentials);
|
||||||
```
|
```
|
||||||
|
|
||||||
### Examples
|
## Examples
|
||||||
|
|
||||||
Let's walk through some examples of Javascript gRPC clients. These examples
|
Let's walk through some examples of Javascript gRPC clients. These examples
|
||||||
assume that you have at least two `lnd` nodes running, the RPC location of one
|
assume that you have at least two `lnd` nodes running, the RPC location of one
|
||||||
of which is at the default `localhost:10009`, with an open channel between the
|
of which is at the default `localhost:10009`, with an open channel between the
|
||||||
two nodes.
|
two nodes.
|
||||||
|
|
||||||
#### Simple RPC
|
### Simple RPC
|
||||||
|
|
||||||
```js
|
```js
|
||||||
> lightning.getInfo({}, function(err, response) {
|
lightning.getInfo({}, function(err, response) {
|
||||||
console.log('GetInfo:', response);
|
if (err) {
|
||||||
});
|
console.log('Error: ' + err);
|
||||||
|
}
|
||||||
|
console.log('GetInfo:', response);
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
You should get something like this in your console:
|
You should get something like this in your console:
|
||||||
@ -79,10 +88,10 @@ GetInfo: { identity_pubkey: '03c892e3f3f077ea1e381c081abb36491a2502bc43ed37ffb82
|
|||||||
chains: [ 'bitcoin' ] }
|
chains: [ 'bitcoin' ] }
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Response-streaming RPC
|
### Response-streaming RPC
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var call = lightning.subscribeInvoices({});
|
let call = lightning.subscribeInvoices({});
|
||||||
call.on('data', function(invoice) {
|
call.on('data', function(invoice) {
|
||||||
console.log(invoice);
|
console.log(invoice);
|
||||||
})
|
})
|
||||||
@ -108,7 +117,7 @@ $ lncli sendpayment --pay_req=<PAYMENT_REQUEST>
|
|||||||
Your Javascript console should now display the details of the recently satisfied
|
Your Javascript console should now display the details of the recently satisfied
|
||||||
invoice.
|
invoice.
|
||||||
|
|
||||||
#### Bidirectional-streaming RPC
|
### Bidirectional-streaming RPC
|
||||||
|
|
||||||
This example has a few dependencies:
|
This example has a few dependencies:
|
||||||
```shell
|
```shell
|
||||||
@ -120,15 +129,15 @@ You can run the following in your shell or put it in a program and run it like
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
// Load some libraries specific to this example
|
// Load some libraries specific to this example
|
||||||
var async = require('async');
|
const async = require('async');
|
||||||
var _ = require('lodash');
|
const _ = require('lodash');
|
||||||
var ByteBuffer = require('bytebuffer');
|
const ByteBuffer = require('bytebuffer');
|
||||||
|
|
||||||
var dest_pubkey = <RECEIVER_ID_PUBKEY>;
|
let dest_pubkey = <RECEIVER_ID_PUBKEY>;
|
||||||
var dest_pubkey_bytes = ByteBuffer.fromHex(dest_pubkey);
|
let dest_pubkey_bytes = ByteBuffer.fromHex(dest_pubkey);
|
||||||
|
|
||||||
// Set a listener on the bidirectional stream
|
// Set a listener on the bidirectional stream
|
||||||
var call = lightning.sendPayment();
|
let call = lightning.sendPayment();
|
||||||
call.on('data', function(payment) {
|
call.on('data', function(payment) {
|
||||||
console.log("Payment sent:");
|
console.log("Payment sent:");
|
||||||
console.log(payment);
|
console.log(payment);
|
||||||
@ -153,8 +162,8 @@ function paymentSender(destination, amount) {
|
|||||||
_.delay(callback, 2000);
|
_.delay(callback, 2000);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
var payment_senders = [];
|
let payment_senders = [];
|
||||||
for (var i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
payment_senders[i] = paymentSender(dest_pubkey_bytes, 100);
|
payment_senders[i] = paymentSender(dest_pubkey_bytes, 100);
|
||||||
}
|
}
|
||||||
async.series(payment_senders, function() {
|
async.series(payment_senders, function() {
|
||||||
@ -165,67 +174,62 @@ async.series(payment_senders, function() {
|
|||||||
This example will send a payment of 100 satoshis every 2 seconds.
|
This example will send a payment of 100 satoshis every 2 seconds.
|
||||||
|
|
||||||
|
|
||||||
#### Using Macaroons
|
### Using Macaroons
|
||||||
|
|
||||||
To authenticate using macaroons you need to include the macaroon in the metadata of the request.
|
To authenticate using macaroons you need to include the macaroon in the metadata
|
||||||
|
of each request.
|
||||||
|
|
||||||
|
The following snippet will add the macaroon to every request automatically:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var fs = require('fs');
|
const fs = require('fs');
|
||||||
var grpc = require('grpc');
|
const grpc = require('grpc');
|
||||||
|
const protoLoader = require('@grpc/proto-loader');
|
||||||
|
const loaderOptions = {
|
||||||
|
keepCase: true,
|
||||||
|
longs: String,
|
||||||
|
enums: String,
|
||||||
|
defaults: true,
|
||||||
|
oneofs: true
|
||||||
|
};
|
||||||
|
const packageDefinition = protoLoader.loadSync('rpc.proto', loaderOptions);
|
||||||
|
|
||||||
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA'
|
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA'
|
||||||
|
|
||||||
// Lnd admin macaroon is at ~/.lnd/data/chain/bitcoin/simnet/admin.macaroon on Linux and
|
// Lnd admin macaroon is at ~/.lnd/data/chain/bitcoin/simnet/admin.macaroon on Linux and
|
||||||
// ~/Library/Application Support/Lnd/data/chain/bitcoin/simnet/admin.macaroon on Mac
|
// ~/Library/Application Support/Lnd/data/chain/bitcoin/simnet/admin.macaroon on Mac
|
||||||
var m = fs.readFileSync('~/.lnd/data/chain/bitcoin/simnet/admin.macaroon');
|
let m = fs.readFileSync('~/.lnd/data/chain/bitcoin/simnet/admin.macaroon');
|
||||||
var macaroon = m.toString('hex');
|
let macaroon = m.toString('hex');
|
||||||
var meta = new grpc.Metadata().add('macaroon', macaroon);
|
|
||||||
|
|
||||||
var lnrpcDescriptor = grpc.load("rpc.proto");
|
|
||||||
var lnrpc = lnrpcDescriptor.lnrpc;
|
|
||||||
var client = new lnrpc.Lightning('some.address:10009', grpc.credentials.createInsecure());
|
|
||||||
|
|
||||||
client.getInfo({}, meta);
|
|
||||||
```
|
|
||||||
|
|
||||||
However, this can get tiresome to do for each request, so to avoid explicitly including the macaroon we can update the credentials to include it automatically.
|
|
||||||
|
|
||||||
```js
|
|
||||||
var fs = require('fs');
|
|
||||||
var grpc = require('grpc');
|
|
||||||
|
|
||||||
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA'
|
|
||||||
|
|
||||||
// Lnd admin macaroon is at ~/.lnd/data/chain/bitcoin/simnet/admin.macaroon on Linux and
|
|
||||||
// ~/Library/Application Support/Lnd/data/chain/bitcoin/simnet/admin.macaroon on Mac
|
|
||||||
var m = fs.readFileSync('~/.lnd/data/chain/bitcoin/simnet/admin.macaroon');
|
|
||||||
var macaroon = m.toString('hex');
|
|
||||||
|
|
||||||
// build meta data credentials
|
// build meta data credentials
|
||||||
var metadata = new grpc.Metadata()
|
let metadata = new grpc.Metadata()
|
||||||
metadata.add('macaroon', macaroon)
|
metadata.add('macaroon', macaroon)
|
||||||
var macaroonCreds = grpc.credentials.createFromMetadataGenerator((_args, callback) => {
|
let macaroonCreds = grpc.credentials.createFromMetadataGenerator((_args, callback) => {
|
||||||
callback(null, metadata);
|
callback(null, metadata);
|
||||||
});
|
});
|
||||||
|
|
||||||
// build ssl credentials using the cert the same as before
|
// build ssl credentials using the cert the same as before
|
||||||
var lndCert = fs.readFileSync("~/.lnd/tls.cert");
|
let lndCert = fs.readFileSync("~/.lnd/tls.cert");
|
||||||
var sslCreds = grpc.credentials.createSsl(lndCert);
|
let sslCreds = grpc.credentials.createSsl(lndCert);
|
||||||
|
|
||||||
// combine the cert credentials and the macaroon auth credentials
|
// combine the cert credentials and the macaroon auth credentials
|
||||||
// such that every call is properly encrypted and authenticated
|
// such that every call is properly encrypted and authenticated
|
||||||
var credentials = grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds);
|
let credentials = grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds);
|
||||||
|
|
||||||
// Pass the crendentials when creating a channel
|
// Pass the crendentials when creating a channel
|
||||||
var lnrpcDescriptor = grpc.load("rpc.proto");
|
let lnrpcDescriptor = grpc.loadPackageDefinition(packageDefinition);
|
||||||
var lnrpc = lnrpcDescriptor.lnrpc;
|
let lnrpc = lnrpcDescriptor.lnrpc;
|
||||||
var client = new lnrpc.Lightning('some.address:10009', credentials);
|
let client = new lnrpc.Lightning('some.address:10009', credentials);
|
||||||
|
|
||||||
client.getInfo({}, (err, res) => { ... });
|
client.getInfo({}, (err, response) => {
|
||||||
|
if (err) {
|
||||||
|
console.log('Error: ' + err);
|
||||||
|
}
|
||||||
|
console.log('GetInfo:', response);
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
### Conclusion
|
|
||||||
|
|
||||||
With the above, you should have all the `lnd` related `gRPC` dependencies
|
With the above, you should have all the `lnd` related `gRPC` dependencies
|
||||||
installed locally in your project. In order to get up to speed with `protofbuf`
|
installed locally in your project. In order to get up to speed with `protofbuf`
|
||||||
@ -234,3 +238,9 @@ Javascript](https://developers.google.com/protocol-buffers/docs/reference/javasc
|
|||||||
Additionally, [this official gRPC
|
Additionally, [this official gRPC
|
||||||
resource](http://www.grpc.io/docs/tutorials/basic/node.html) provides more
|
resource](http://www.grpc.io/docs/tutorials/basic/node.html) provides more
|
||||||
details around how to drive `gRPC` from `node.js`.
|
details around how to drive `gRPC` from `node.js`.
|
||||||
|
|
||||||
|
## API documentation
|
||||||
|
|
||||||
|
There is an [online API documentation](https://api.lightning.community?javascript)
|
||||||
|
available that shows all currently existing RPC methods, including code snippets
|
||||||
|
on how to use them.
|
||||||
|
@ -3,46 +3,61 @@
|
|||||||
This section enumerates what you need to do to write a client that communicates
|
This section enumerates what you need to do to write a client that communicates
|
||||||
with `lnd` in Python.
|
with `lnd` in Python.
|
||||||
|
|
||||||
### Setup and Installation
|
## Setup and Installation
|
||||||
|
|
||||||
Lnd uses the gRPC protocol for communication with clients like lncli. gRPC is
|
Lnd uses the gRPC protocol for communication with clients like lncli. gRPC is
|
||||||
based on protocol buffers and as such, you will need to compile the lnd proto
|
based on protocol buffers and as such, you will need to compile the lnd proto
|
||||||
file in Python before you can use it to communicate with lnd.
|
file in Python before you can use it to communicate with lnd.
|
||||||
|
|
||||||
* Create a virtual environment for your project
|
1. Create a virtual environment for your project
|
||||||
```
|
```
|
||||||
$ virtualenv lnd
|
$ virtualenv lnd
|
||||||
```
|
```
|
||||||
* Activate the virtual environment
|
2. Activate the virtual environment
|
||||||
```
|
```
|
||||||
$ source lnd/bin/activate
|
$ source lnd/bin/activate
|
||||||
```
|
```
|
||||||
* Install dependencies (googleapis-common-protos is required due to the use of
|
3. Install dependencies (googleapis-common-protos is required due to the use of
|
||||||
google/api/annotations.proto)
|
google/api/annotations.proto)
|
||||||
```
|
```
|
||||||
(lnd)$ pip install grpcio grpcio-tools googleapis-common-protos
|
(lnd)$ pip install grpcio grpcio-tools googleapis-common-protos
|
||||||
```
|
```
|
||||||
* Clone the google api's repository (required due to the use of
|
4. Clone the google api's repository (required due to the use of
|
||||||
google/api/annotations.proto)
|
google/api/annotations.proto)
|
||||||
```
|
```
|
||||||
(lnd)$ git clone https://github.com/googleapis/googleapis.git
|
(lnd)$ git clone https://github.com/googleapis/googleapis.git
|
||||||
```
|
```
|
||||||
* Copy the lnd rpc.proto file (you'll find this at
|
5. Copy the lnd rpc.proto file (you'll find this at
|
||||||
[lnrpc/rpc.proto](https://github.com/lightningnetwork/lnd/blob/master/lnrpc/rpc.proto))
|
[lnrpc/rpc.proto](https://github.com/lightningnetwork/lnd/blob/master/lnrpc/rpc.proto))
|
||||||
or just download it
|
or just download it
|
||||||
```
|
```
|
||||||
(lnd)$ curl -o rpc.proto -s https://raw.githubusercontent.com/lightningnetwork/lnd/master/lnrpc/rpc.proto
|
(lnd)$ curl -o rpc.proto -s https://raw.githubusercontent.com/lightningnetwork/lnd/master/lnrpc/rpc.proto
|
||||||
```
|
```
|
||||||
* Compile the proto file
|
6. Compile the proto file
|
||||||
```
|
```
|
||||||
(lnd)$ python -m grpc_tools.protoc --proto_path=googleapis:. --python_out=. --grpc_python_out=. rpc.proto
|
(lnd)$ python -m grpc_tools.protoc --proto_path=googleapis:. --python_out=. --grpc_python_out=. rpc.proto
|
||||||
```
|
```
|
||||||
|
|
||||||
After following these steps, two files `rpc_pb2.py` and `rpc_pb2_grpc.py` will
|
After following these steps, two files `rpc_pb2.py` and `rpc_pb2_grpc.py` will
|
||||||
be generated. These files will be imported in your project anytime you use
|
be generated. These files will be imported in your project anytime you use
|
||||||
Python gRPC.
|
Python gRPC.
|
||||||
|
|
||||||
#### Imports and Client
|
### Generating RPC modules for subservers
|
||||||
|
|
||||||
|
If you want to use any of the subservers' functionality, you also need to
|
||||||
|
generate the python modules for them.
|
||||||
|
|
||||||
|
For example, if you want to generate the RPC modules for the `Router` subserver
|
||||||
|
(located/defined in `routerrpc/router.proto`), you need to run the following two
|
||||||
|
extra steps (after completing all 6 step described above) to get the
|
||||||
|
`router_pb2.py` and `router_pb2_grpc.py`:
|
||||||
|
|
||||||
|
```
|
||||||
|
(lnd)$ curl -o router.proto -s https://raw.githubusercontent.com/lightningnetwork/lnd/master/lnrpc/routerrpc/router.proto
|
||||||
|
(lnd)$ python -m grpc_tools.protoc --proto_path=googleapis:. --python_out=. --grpc_python_out=. router.proto
|
||||||
|
```
|
||||||
|
|
||||||
|
### Imports and Client
|
||||||
|
|
||||||
Every time you use Python gRPC, you will have to import the generated rpc modules
|
Every time you use Python gRPC, you will have to import the generated rpc modules
|
||||||
and set up a channel and stub to your connect to your `lnd` node:
|
and set up a channel and stub to your connect to your `lnd` node:
|
||||||
@ -66,13 +81,13 @@ channel = grpc.secure_channel('localhost:10009', creds)
|
|||||||
stub = lnrpc.LightningStub(channel)
|
stub = lnrpc.LightningStub(channel)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Examples
|
## Examples
|
||||||
|
|
||||||
Let's walk through some examples of Python gRPC clients. These examples assume
|
Let's walk through some examples of Python gRPC clients. These examples assume
|
||||||
that you have at least two `lnd` nodes running, the RPC location of one of which
|
that you have at least two `lnd` nodes running, the RPC location of one of which
|
||||||
is at the default `localhost:10009`, with an open channel between the two nodes.
|
is at the default `localhost:10009`, with an open channel between the two nodes.
|
||||||
|
|
||||||
#### Simple RPC
|
### Simple RPC
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# Retrieve and display the wallet balance
|
# Retrieve and display the wallet balance
|
||||||
@ -80,7 +95,7 @@ response = stub.WalletBalance(ln.WalletBalanceRequest())
|
|||||||
print(response.total_balance)
|
print(response.total_balance)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Response-streaming RPC
|
### Response-streaming RPC
|
||||||
|
|
||||||
```python
|
```python
|
||||||
request = ln.InvoiceSubscription()
|
request = ln.InvoiceSubscription()
|
||||||
@ -102,7 +117,7 @@ $ lncli sendpayment --pay_req=<PAY_REQ>
|
|||||||
Your Python console should now display the details of the recently satisfied
|
Your Python console should now display the details of the recently satisfied
|
||||||
invoice.
|
invoice.
|
||||||
|
|
||||||
#### Bidirectional-streaming RPC
|
### Bidirectional-streaming RPC
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from time import sleep
|
from time import sleep
|
||||||
@ -133,7 +148,7 @@ for payment in stub.SendPayment(request_iterable):
|
|||||||
```
|
```
|
||||||
This example will send a payment of 100 satoshis every 2 seconds.
|
This example will send a payment of 100 satoshis every 2 seconds.
|
||||||
|
|
||||||
#### Using Macaroons
|
### Using Macaroons
|
||||||
|
|
||||||
To authenticate using macaroons you need to include the macaroon in the metadata of the request.
|
To authenticate using macaroons you need to include the macaroon in the metadata of the request.
|
||||||
|
|
||||||
@ -180,7 +195,7 @@ stub.GetInfo(ln.GetInfoRequest())
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Conclusion
|
## Conclusion
|
||||||
|
|
||||||
With the above, you should have all the `lnd` related `gRPC` dependencies
|
With the above, you should have all the `lnd` related `gRPC` dependencies
|
||||||
installed locally into your virtual environment. In order to get up to speed
|
installed locally into your virtual environment. In order to get up to speed
|
||||||
@ -189,3 +204,9 @@ Python](https://developers.google.com/protocol-buffers/docs/pythontutorial).
|
|||||||
Additionally, [this official gRPC
|
Additionally, [this official gRPC
|
||||||
resource](http://www.grpc.io/docs/tutorials/basic/python.html) provides more
|
resource](http://www.grpc.io/docs/tutorials/basic/python.html) provides more
|
||||||
details around how to drive `gRPC` from Python.
|
details around how to drive `gRPC` from Python.
|
||||||
|
|
||||||
|
## API documentation
|
||||||
|
|
||||||
|
There is an [online API documentation](https://api.lightning.community?python)
|
||||||
|
available that shows all currently existing RPC methods, including code snippets
|
||||||
|
on how to use them.
|
||||||
|
Loading…
Reference in New Issue
Block a user