QueryRoutes
QueryRoutes attempts to query the daemon's Channel Router for a possible route to a target destination capable of carrying a specific amount of satoshis. The returned route contains the full details required to craft and send an HTLC, also including the necessary information that should be present within the Sphinx packet encapsulated within the HTLC.
When using REST, the dest_custom_records
map type can be set by appending
&dest_custom_records[<record_number>]=<record_data_base64_url_encoded>
to the URL. Unfortunately this map type doesn't appear in the REST API
documentation because of a bug in the grpc-gateway library.
Source: lightning.proto
gRPC
rpc QueryRoutes (QueryRoutesRequest) returns (QueryRoutesResponse);
REST
HTTP Method | Path |
---|---|
GET | /v1/graph/routes/{pub_key}/{amt} |
Code Samples
- gRPC
- REST
- Shell
- Javascript
- Python
const fs = require('fs');
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const GRPC_HOST = 'localhost:10009'
const MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
const TLS_PATH = 'LND_DIR/tls.cert'
const loaderOptions = {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
};
const packageDefinition = protoLoader.loadSync('lightning.proto', loaderOptions);
const lnrpc = grpc.loadPackageDefinition(packageDefinition).lnrpc;
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA';
const tlsCert = fs.readFileSync(TLS_PATH);
const sslCreds = grpc.credentials.createSsl(tlsCert);
const macaroon = fs.readFileSync(MACAROON_PATH).toString('hex');
const macaroonCreds = grpc.credentials.createFromMetadataGenerator(function(args, callback) {
let metadata = new grpc.Metadata();
metadata.add('macaroon', macaroon);
callback(null, metadata);
});
let creds = grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds);
let client = new lnrpc.Lightning(GRPC_HOST, creds);
let request = {
pub_key: <string>,
amt: <int64>,
amt_msat: <int64>,
final_cltv_delta: <int32>,
fee_limit: <FeeLimit>,
ignored_nodes: <bytes>,
ignored_edges: <EdgeLocator>,
source_pub_key: <string>,
use_mission_control: <bool>,
ignored_pairs: <NodePair>,
cltv_limit: <uint32>,
dest_custom_records: <DestCustomRecordsEntry>,
outgoing_chan_id: <uint64>,
last_hop_pubkey: <bytes>,
route_hints: <RouteHint>,
dest_features: <FeatureBit>,
time_pref: <double>,
};
client.queryRoutes(request, function(err, response) {
console.log(response);
});
// Console output:
// {
// "routes": <Route>,
// "success_prob": <double>,
// }
import codecs, grpc, os
# Generate the following 2 modules by compiling the lightning.proto with the grpcio-tools.
# See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
import lightning_pb2 as lnrpc, lightning_pb2_grpc as lightningstub
GRPC_HOST = 'localhost:10009'
MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
TLS_PATH = 'LND_DIR/tls.cert'
# create macaroon credentials
macaroon = codecs.encode(open(MACAROON_PATH, 'rb').read(), 'hex')
def metadata_callback(context, callback):
callback([('macaroon', macaroon)], None)
auth_creds = grpc.metadata_call_credentials(metadata_callback)
# create SSL credentials
os.environ['GRPC_SSL_CIPHER_SUITES'] = 'HIGH+ECDSA'
cert = open(TLS_PATH, 'rb').read()
ssl_creds = grpc.ssl_channel_credentials(cert)
# combine macaroon and SSL credentials
combined_creds = grpc.composite_channel_credentials(ssl_creds, auth_creds)
# make the request
channel = grpc.secure_channel(GRPC_HOST, combined_creds)
stub = lightningstub.LightningStub(channel)
request = lnrpc.QueryRoutesRequest(
pub_key=<string>,
amt=<int64>,
amt_msat=<int64>,
final_cltv_delta=<int32>,
fee_limit=<FeeLimit>,
ignored_nodes=<bytes>,
ignored_edges=<EdgeLocator>,
source_pub_key=<string>,
use_mission_control=<bool>,
ignored_pairs=<NodePair>,
cltv_limit=<uint32>,
dest_custom_records=<DestCustomRecordsEntry>,
outgoing_chan_id=<uint64>,
last_hop_pubkey=<bytes>,
route_hints=<RouteHint>,
dest_features=<FeatureBit>,
time_pref=<double>,
)
response = stub.QueryRoutes(request)
print(response)
# {
# "routes": <Route>,
# "success_prob": <double>,
# }
- Javascript
- Python
const fs = require('fs');
const request = require('request');
const REST_HOST = 'localhost:8080'
const MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
let options = {
url: `https://${REST_HOST}/v1/graph/routes/{pub_key}/{amt}`,
// Work-around for self-signed certificates.
rejectUnauthorized: false,
json: true,
headers: {
'Grpc-Metadata-macaroon': fs.readFileSync(MACAROON_PATH).toString('hex'),
},
}
request.get(options, function(error, response, body) {
console.log(body);
});
// Console output:
// {
// "routes": <array>, // <Route>
// "success_prob": <number>, // <double>
// }
import base64, codecs, json, requests
REST_HOST = 'localhost:8080'
MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
TLS_PATH = 'LND_DIR/tls.cert'
url = f'https://{REST_HOST}/v1/graph/routes/{pub_key}/{amt}'
macaroon = codecs.encode(open(MACAROON_PATH, 'rb').read(), 'hex')
headers = {'Grpc-Metadata-macaroon': macaroon}
r = requests.get(url, headers=headers, verify=TLS_PATH)
print(r.json())
# {
# "routes": <Route>,
# "success_prob": <double>,
# }
$ lncli queryroutes --help
NAME:
lncli queryroutes - Query a route to a destination.
USAGE:
lncli queryroutes [command options] dest amt
CATEGORY:
Payments
DESCRIPTION:
Queries the channel router for a potential path to the destination that has sufficient flow for the amount including fees
OPTIONS:
--dest value the 33-byte hex-encoded public key for the payment destination
--amt value the amount to send expressed in satoshis (default: 0)
--fee_limit value maximum fee allowed in satoshis when sending the payment (default: 0)
--fee_limit_percent value percentage of the payment's amount used as the maximum fee allowed when sending the payment (default: 0)
--final_cltv_delta value (optional) number of blocks the last hop has to reveal the preimage (default: 0)
--use_mc use mission control probabilities
--outgoing_chanid value (optional) the channel id of the channel that must be taken to the first hop (default: 0)
--ignore_pair value ignore directional node pair <node1>:<node2>. This flag can be specified multiple times if multiple node pairs are to be ignored
--time_pref value (optional) expresses time preference (range -1 to 1) (default: 0)
--cltv_limit value the maximum time lock that may be used for this payment (default: 0)
Messages
lnrpc.QueryRoutesRequest
Source: lightning.proto
Field | gRPC Type | REST Type | REST Placement |
---|---|---|---|
pub_key | string | string | path |
amt | int64 | string | path |
amt_msat | int64 | string | query |
final_cltv_delta | int32 | integer | query |
fee_limit | FeeLimit | object | query |
ignored_nodes | bytes[] | array | query |
ignored_edges | EdgeLocator[] | object | unknown |
source_pub_key | string | string | query |
use_mission_control | bool | boolean | query |
ignored_pairs | NodePair[] | object | unknown |
cltv_limit | uint32 | integer | query |
dest_custom_records | DestCustomRecordsEntry[] | object | unknown |
outgoing_chan_id | uint64 | string | query |
last_hop_pubkey | bytes | string | query |
route_hints | RouteHint[] | object | unknown |
dest_features | FeatureBit[] | object | query |
time_pref | double | number | query |
lnrpc.QueryRoutesResponse
Source: lightning.proto
Field | gRPC Type | REST Type |
---|---|---|
routes | Route[] | array |
success_prob | double | number |
Nested Messages
lnrpc.FeeLimit
Field | gRPC Type | REST Type |
---|---|---|
fixed | int64 | string |
fixed_msat | int64 | string |
percent | int64 | string |
lnrpc.EdgeLocator
Field | gRPC Type | REST Type |
---|---|---|
channel_id | uint64 | string |
direction_reverse | bool | boolean |
lnrpc.NodePair
Field | gRPC Type | REST Type |
---|---|---|
from | bytes | string |
to | bytes | string |
lnrpc.QueryRoutesRequest.DestCustomRecordsEntry
Field | gRPC Type | REST Type |
---|---|---|
key | uint64 | unknown |
value | bytes | unknown |
lnrpc.RouteHint
Field | gRPC Type | REST Type |
---|---|---|
hop_hints | HopHint[] | array |
lnrpc.HopHint
Field | gRPC Type | REST Type |
---|---|---|
node_id | string | string |
chan_id | uint64 | string |
fee_base_msat | uint32 | integer |
fee_proportional_millionths | uint32 | integer |
cltv_expiry_delta | uint32 | integer |
lnrpc.Route
Field | gRPC Type | REST Type |
---|---|---|
total_time_lock | uint32 | integer |
total_fees | int64 | string |
total_amt | int64 | string |
hops | Hop[] | array |
total_fees_msat | int64 | string |
total_amt_msat | int64 | string |
lnrpc.Hop
Field | gRPC Type | REST Type |
---|---|---|
chan_id | uint64 | string |
chan_capacity | int64 | string |
amt_to_forward | int64 | string |
fee | int64 | string |
expiry | uint32 | integer |
amt_to_forward_msat | int64 | string |
fee_msat | int64 | string |
pub_key | string | string |
tlv_payload | bool | boolean |
mpp_record | MPPRecord | object |
amp_record | AMPRecord | object |
custom_records | CustomRecordsEntry[] | object |
metadata | bytes | string |
lnrpc.MPPRecord
Field | gRPC Type | REST Type |
---|---|---|
payment_addr | bytes | string |
total_amt_msat | int64 | string |
lnrpc.AMPRecord
Field | gRPC Type | REST Type |
---|---|---|
root_share | bytes | string |
set_id | bytes | string |
child_index | uint32 | integer |
lnrpc.Hop.CustomRecordsEntry
Field | gRPC Type | REST Type |
---|---|---|
key | uint64 | unknown |
value | bytes | unknown |
Enums
lnrpc.FeatureBit
Name | Number |
---|---|
DATALOSS_PROTECT_REQ | 0 |
DATALOSS_PROTECT_OPT | 1 |
INITIAL_ROUING_SYNC | 3 |
UPFRONT_SHUTDOWN_SCRIPT_REQ | 4 |
UPFRONT_SHUTDOWN_SCRIPT_OPT | 5 |
GOSSIP_QUERIES_REQ | 6 |
GOSSIP_QUERIES_OPT | 7 |
TLV_ONION_REQ | 8 |
TLV_ONION_OPT | 9 |
EXT_GOSSIP_QUERIES_REQ | 10 |
EXT_GOSSIP_QUERIES_OPT | 11 |
STATIC_REMOTE_KEY_REQ | 12 |
STATIC_REMOTE_KEY_OPT | 13 |
PAYMENT_ADDR_REQ | 14 |
PAYMENT_ADDR_OPT | 15 |
MPP_REQ | 16 |
MPP_OPT | 17 |
WUMBO_CHANNELS_REQ | 18 |
WUMBO_CHANNELS_OPT | 19 |
ANCHORS_REQ | 20 |
ANCHORS_OPT | 21 |
ANCHORS_ZERO_FEE_HTLC_REQ | 22 |
ANCHORS_ZERO_FEE_HTLC_OPT | 23 |
AMP_REQ | 30 |
AMP_OPT | 31 |