Skip to main content

TrackOnion

TrackOnion allows callers to query whether or not a payment dispatched via SendOnion succeeded or failed.

This RPC is designed to be called after a successful dispatch has been explicitly confirmed via the SendOnion RPC. It should not be used to determine whether an HTLC dispatch was received in an ambiguous network scenario. That ambiguity must be resolved by retrying the idempotent SendOnion RPC until a definitive acknowledgement is received from the Switch RPC server.

Once dispatch is confirmed, TrackOnion provides the mechanism to wait for the result of the in-flight HTLC. A client must handle three distinct categories of outcomes:

  1. PAYMENT SUCCESS (gRPC code OK, preimage set): The payment settled successfully. The response contains the payment preimage.

  2. PAYMENT FAILURE (gRPC code OK, failure_details set): The payment failed at the application level. The failure_details oneof describes the specific failure type: a ForwardingFailure from a remote hop, a LocalFailure from the local node, an UnreadableFailure if the error could not be decoded, or a SwitchError for other switch-level failures. When encrypted_error_data is populated, the client may perform its own decryption.

  3. QUERY FAILURE (gRPC error status): The query itself could not be completed. NotFound indicates the payment ID is unknown. Unavailable signals the switch is shutting down. Canceled or DeadlineExceeded reflects client-side timeouts. These are safe to retry.

Source: switchrpc/switch.proto

gRPC​

rpc TrackOnion (TrackOnionRequest) returns (TrackOnionResponse);

REST​

HTTP MethodPath
POST /v2/switch/track

Code Samples​

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', 'switchrpc/switch.proto'], loaderOptions);
const switchrpc = grpc.loadPackageDefinition(packageDefinition).switchrpc;
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 switchrpc.Switch(GRPC_HOST, creds);
let request = {
payment_hash: <bytes>,
attempt_id: <uint64>,
session_key: <bytes>,
hop_pubkeys: <bytes>,
};
client.trackOnion(request, function(err, response) {
console.log(response);
});
// Console output:
// {
// "preimage": <bytes>,
// "failure_details": <FailureDetails>,
// }

Messages​

switchrpc.TrackOnionRequest​

Source: switchrpc/switch.proto

FieldgRPC TypeREST TypeREST Placement
payment_hash
bytesstringbody
attempt_id
uint64stringbody
session_key
bytesstringbody
hop_pubkeys
bytes[]arraybody

switchrpc.TrackOnionResponse​

Source: switchrpc/switch.proto

FieldgRPC TypeREST Type
preimage
bytesstring
failure_details
FailureDetailsobject

Nested Messages​

switchrpc.FailureDetails​

FieldgRPC TypeREST Type
error_message
stringstring
local_failure
LocalFailureobject
forwarding_failure
ForwardingFailureobject
encrypted_error_data
bytesstring
unreadable_failure
UnreadableFailureobject
switch_error
SwitchErrorobject

switchrpc.ForwardingFailure​

FieldgRPC TypeREST Type
failure_source_index
uint32integer
wire_message
bytesstring

switchrpc.LocalFailure​

FieldgRPC TypeREST Type
wire_message
bytesstring

switchrpc.SwitchError​

note

This response has no parameters.

switchrpc.UnreadableFailure​

note

This response has no parameters.