NAV Navbar
shell python javascript

Loop gRPC API Reference

Welcome to the gRPC API reference documentation for Lightning Loop.

Lightning Loop is a non-custodial service offered by Lightning Labs to bridge on-chain and off-chain Bitcoin using submarine swaps. This repository is home to the Loop client and depends on the Lightning Network daemon lnd. All of lnd’s supported chain backends are fully supported when using the Loop client: Neutrino, Bitcoin Core, and btcd.

The service can be used in various situations:

This site features the documentation for loop (CLI), and the API documentation for Python and JavaScript clients in order to communicate with a local loopd instance through gRPC. Currently, this communication is unauthenticated, so exposing this service to the internet is not recommended.

The original *.proto files from which the gRPC documentation was generated can be found here:

This is the reference for the gRPC API. Alternatively, there is also a REST API which is documented here.

This documentation was generated automatically against commit 10c7c34d5949114ac10e473a7405ffd4ebafa150.

Service SwapClient

SwapClient.GetLoopInQuote

Unary RPC

GetQuote returns a quote for a swap with the provided parameters.


# get a quote for the cost of a swap

$ out  get a quote for the cost of a loop out swap

# --help, -h  show help
>>> import codecs, grpc, os
>>> # Generate the following 2 modules by compiling the looprpc/client.proto with the grpcio-tools.
>>> # See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
>>> import client_pb2 as looprpc, client_pb2_grpc as clientstub
>>> channel = grpc.insecure_channel('localhost:11010')
>>> stub = clientstub.SwapClientStub(channel)
>>> request = looprpc.QuoteRequest(
        amt=<int64>,
        conf_target=<int32>,
        external_htlc=<bool>,
        swap_publication_deadline=<uint64>,
    )
>>> response = stub.GetLoopInQuote(request, metadata=[('macaroon', macaroon)])
>>> print(response)
{ 
    "swap_fee_sat": <int64>,
    "htlc_publish_fee_sat": <int64>,
    "cltv_delta": <int32>,
}
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('client.proto', loaderOptions);
const looprpc = grpc.loadPackageDefinition(packageDefinition).looprpc;
const swapClient = new looprpc.SwapClient('localhost:11010', grpc.credentials.createInsecure());
let request = { 
  amt: <int64>, 
  conf_target: <int32>, 
  external_htlc: <bool>, 
  swap_publication_deadline: <uint64>, 
};
swapClient.getLoopInQuote(request, function(err, response) {
  console.log(response);
});
// Console output:
//  { 
//      "swap_fee_sat": <int64>,
//      "htlc_publish_fee_sat": <int64>,
//      "cltv_delta": <int32>,
//  }

gRPC Request: looprpc.QuoteRequest

Parameter Type Description
amt int64 The amount to swap in satoshis.
conf_target int32 The confirmation target that should be used either for the sweep of the on-chain HTLC broadcast by the swap server in the case of a Loop Out, or for the confirmation of the on-chain HTLC broadcast by the swap client in the case of a Loop In.
external_htlc bool If external_htlc is true, we expect the htlc to be published by an external actor.
swap_publication_deadline uint64 The latest time (in unix seconds) we allow the server to wait before publishing the HTLC on chain. Setting this to a larger value will give the server the opportunity to batch multiple swaps together, and wait for low-fee periods before publishing the HTLC, potentially resulting in a lower total swap fee. This only has an effect on loop out quotes.

gRPC Response: looprpc.InQuoteResponse

Parameter Type Description
swap_fee_sat int64 The fee that the swap server is charging for the swap.
htlc_publish_fee_sat int64 An estimate of the on-chain fee that needs to be paid to publish the HTLC If a miner fee of 0 is returned, it means the external_htlc flag was set for a loop in and the fee estimation was skipped. If a miner fee of -1 is returned, it means lnd's wallet tried to estimate the fee but was unable to create a sample estimation transaction because not enough funds are available. An information message should be shown to the user in this case.
cltv_delta int32 On-chain cltv expiry delta

SwapClient.GetLoopInTerms

Unary RPC

GetTerms returns the terms that the server enforces for swaps.


# Display the current swap terms imposed by the server.

$ loop terms [arguments...]

>>> import codecs, grpc, os
>>> # Generate the following 2 modules by compiling the looprpc/client.proto with the grpcio-tools.
>>> # See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
>>> import client_pb2 as looprpc, client_pb2_grpc as clientstub
>>> channel = grpc.insecure_channel('localhost:11010')
>>> stub = clientstub.SwapClientStub(channel)
>>> request = looprpc.TermsRequest()
>>> response = stub.GetLoopInTerms(request, metadata=[('macaroon', macaroon)])
>>> print(response)
{ 
    "min_swap_amount": <int64>,
    "max_swap_amount": <int64>,
}
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('client.proto', loaderOptions);
const looprpc = grpc.loadPackageDefinition(packageDefinition).looprpc;
const swapClient = new looprpc.SwapClient('localhost:11010', grpc.credentials.createInsecure());
let request = {}
swapClient.getLoopInTerms(request, function(err, response) {
  console.log(response);
});
// Console output:
//  { 
//      "min_swap_amount": <int64>,
//      "max_swap_amount": <int64>,
//  }

gRPC Request: looprpc.TermsRequest

This request has no parameters.

gRPC Response: looprpc.InTermsResponse

Parameter Type Description
min_swap_amount int64 Minimum swap amount (sat)
max_swap_amount int64 Maximum swap amount (sat)

SwapClient.GetLsatTokens

Unary RPC

GetLsatTokens returns all LSAT tokens the daemon ever paid for.


# Shows a list of all LSAT tokens that loopd has paid for

$ loop listauth [arguments...]

>>> import codecs, grpc, os
>>> # Generate the following 2 modules by compiling the looprpc/client.proto with the grpcio-tools.
>>> # See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
>>> import client_pb2 as looprpc, client_pb2_grpc as clientstub
>>> channel = grpc.insecure_channel('localhost:11010')
>>> stub = clientstub.SwapClientStub(channel)
>>> request = looprpc.TokensRequest()
>>> response = stub.GetLsatTokens(request, metadata=[('macaroon', macaroon)])
>>> print(response)
{ 
    "tokens": <array LsatToken>,
}
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('client.proto', loaderOptions);
const looprpc = grpc.loadPackageDefinition(packageDefinition).looprpc;
const swapClient = new looprpc.SwapClient('localhost:11010', grpc.credentials.createInsecure());
let request = {}
swapClient.getLsatTokens(request, function(err, response) {
  console.log(response);
});
// Console output:
//  { 
//      "tokens": <array LsatToken>,
//  }

gRPC Request: looprpc.TokensRequest

This request has no parameters.

gRPC Response: looprpc.TokensResponse

Parameter Type Description
tokens array LsatToken List of all tokens the daemon knows of, including old/expired tokens.

SwapClient.ListSwaps

Unary RPC

ListSwaps returns a list of all currently known swaps and their current status.


# Allows the user to get a list of all swaps that are currently stored in the database

$ loop listswaps [arguments...]

>>> import codecs, grpc, os
>>> # Generate the following 2 modules by compiling the looprpc/client.proto with the grpcio-tools.
>>> # See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
>>> import client_pb2 as looprpc, client_pb2_grpc as clientstub
>>> channel = grpc.insecure_channel('localhost:11010')
>>> stub = clientstub.SwapClientStub(channel)
>>> request = looprpc.ListSwapsRequest()
>>> response = stub.ListSwaps(request, metadata=[('macaroon', macaroon)])
>>> print(response)
{ 
    "swaps": <array SwapStatus>,
}
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('client.proto', loaderOptions);
const looprpc = grpc.loadPackageDefinition(packageDefinition).looprpc;
const swapClient = new looprpc.SwapClient('localhost:11010', grpc.credentials.createInsecure());
let request = {}
swapClient.listSwaps(request, function(err, response) {
  console.log(response);
});
// Console output:
//  { 
//      "swaps": <array SwapStatus>,
//  }

gRPC Request: looprpc.ListSwapsRequest

This request has no parameters.

gRPC Response: looprpc.ListSwapsResponse

Parameter Type Description
swaps array SwapStatus The list of all currently known swaps and their status.

SwapClient.LoopIn

Unary RPC

LoopIn initiates a loop in swap with the given parameters. The call returns after the swap has been set up with the swap server. From that point onwards, progress can be tracked via the SwapStatus stream that is returned from Monitor().


# Send the amount in satoshis specified by the amt argument
# off-chain.
# By default the swap client will create and broadcast the
# on-chain htlc. The fee priority of this transaction can
# optionally be set using the conf_target flag.
# The external flag can be set to publish the on chain htlc
# independently. Note that this flag cannot be set with the
# conf_target flag.

$ loop in [command options] amt

# --amt value          the amount in satoshis to loop in (default: 0)
# --external           expect htlc to be published externally
# --conf_target value  the target number of blocks the on-chain htlc broadcast by the swap client should confirm within (default: 0)
# --last_hop value     the pubkey of the last hop to use for this swap
# --label value        an optional label for this swap,limited to 500 characters. The label may not start with our reserved prefix: [reserved].
>>> import codecs, grpc, os
>>> # Generate the following 2 modules by compiling the looprpc/client.proto with the grpcio-tools.
>>> # See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
>>> import client_pb2 as looprpc, client_pb2_grpc as clientstub
>>> channel = grpc.insecure_channel('localhost:11010')
>>> stub = clientstub.SwapClientStub(channel)
>>> request = looprpc.LoopInRequest(
        amt=<int64>,
        max_swap_fee=<int64>,
        max_miner_fee=<int64>,
        last_hop=<bytes>,
        external_htlc=<bool>,
        htlc_conf_target=<int32>,
        label=<string>,
    )
>>> response = stub.LoopIn(request, metadata=[('macaroon', macaroon)])
>>> print(response)
{ 
    "id": <string>,
    "id_bytes": <bytes>,
    "htlc_address": <string>,
    "htlc_address_np2wsh": <string>,
    "htlc_address_p2wsh": <string>,
    "server_message": <string>,
}
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('client.proto', loaderOptions);
const looprpc = grpc.loadPackageDefinition(packageDefinition).looprpc;
const swapClient = new looprpc.SwapClient('localhost:11010', grpc.credentials.createInsecure());
let request = { 
  amt: <int64>, 
  max_swap_fee: <int64>, 
  max_miner_fee: <int64>, 
  last_hop: <bytes>, 
  external_htlc: <bool>, 
  htlc_conf_target: <int32>, 
  label: <string>, 
};
swapClient.loopIn(request, function(err, response) {
  console.log(response);
});
// Console output:
//  { 
//      "id": <string>,
//      "id_bytes": <bytes>,
//      "htlc_address": <string>,
//      "htlc_address_np2wsh": <string>,
//      "htlc_address_p2wsh": <string>,
//      "server_message": <string>,
//  }

gRPC Request: looprpc.LoopInRequest

Parameter Type Description
amt int64 Requested swap amount in sat. This does not include the swap and miner fee.
max_swap_fee int64 Maximum we are willing to pay the server for the swap. This value is not disclosed in the swap initiation call, but if the server asks for a higher fee, we abort the swap. Typically this value is taken from the response of the GetQuote call.
max_miner_fee int64 Maximum in on-chain fees that we are willing to spend. If we want to publish the on-chain htlc and the fee estimate turns out higher than this value, we cancel the swap. max_miner_fee is typically taken from the response of the GetQuote call.
last_hop bytes The last hop to use for the loop in swap. If empty, the last hop is selected based on the lowest routing fee for the swap payment from the server.
external_htlc bool If external_htlc is true, we expect the htlc to be published by an external actor.
htlc_conf_target int32 The number of blocks that the on chain htlc should confirm within.
label string An optional label for this swap. This field is limited to 500 characters and may not be one of the reserved values in loop/labels Reserved list.

gRPC Response: looprpc.SwapResponse

Parameter Type Description
id string Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs. DEPRECATED: To make the API more consistent, this field is deprecated in favor of id_bytes and will be removed in a future release.
id_bytes bytes Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs.
htlc_address string DEPRECATED. This field stores the address of the onchain htlc, but depending on the request, the semantics are different. - For internal loop-in htlc_address contains the address of the native segwit (P2WSH) htlc. - For external loop-in htlc_address contains the address of the nested segwit (NP2WSH) htlc. - For loop-out htlc_address always contains the native segwit (P2WSH) htlc address.
htlc_address_np2wsh string The nested segwit address of the on-chain htlc. This field remains empty for loop-out.
htlc_address_p2wsh string The native segwit address of the on-chain htlc. Used for both loop-in and loop-out.
server_message string A human-readable message received from the loop server.

SwapClient.LoopOut

Unary RPC

LoopOut initiates an loop out swap with the given parameters. The call returns after the swap has been set up with the swap server. From that point onwards, progress can be tracked via the SwapStatus stream that is returned from Monitor().


# Attempts to loop out the target amount into either the backing lnd's
# wallet, or a targeted address.
# The amount is to be specified in satoshis.
# Optionally a BASE58/bech32 encoded bitcoin destination address may be
# specified. If not specified, a new wallet address will be generated.

$ loop out [command options] amt [addr]

# --channel value               the comma-separated list of short channel IDs of the channels to loop out
# --addr value                  the optional address that the looped out funds should be sent to, if let blank the funds will go to lnd's wallet
# --amt value                   the amount in satoshis to loop out (default: 0)
# --htlc_confs value            the number of of confirmations, in blocks that we require for the htlc extended by the server before we reveal the preimage. (default: 1)
# --conf_target value           the number of blocks from the swap initiation height that the on-chain HTLC should be swept within (default: 9)
# --max_swap_routing_fee value  the max off-chain swap routing fee in satoshis, if not specified, a default max fee will be used (default: 0)
# --fast                        Indicate you want to swap immediately, paying potentially a higher fee. If not set the swap server might choose to wait up to 30 minutes before publishing the swap HTLC on-chain, to save on its chain fees. Not setting this flag therefore might result in a lower swap fee.
# --label value                 an optional label for this swap,limited to 500 characters. The label may not start with our reserved prefix: [reserved].
>>> import codecs, grpc, os
>>> # Generate the following 2 modules by compiling the looprpc/client.proto with the grpcio-tools.
>>> # See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
>>> import client_pb2 as looprpc, client_pb2_grpc as clientstub
>>> channel = grpc.insecure_channel('localhost:11010')
>>> stub = clientstub.SwapClientStub(channel)
>>> request = looprpc.LoopOutRequest(
        amt=<int64>,
        dest=<string>,
        max_swap_routing_fee=<int64>,
        max_prepay_routing_fee=<int64>,
        max_swap_fee=<int64>,
        max_prepay_amt=<int64>,
        max_miner_fee=<int64>,
        loop_out_channel=<uint64>,
        outgoing_chan_set=<array uint64>,
        sweep_conf_target=<int32>,
        htlc_confirmations=<int32>,
        swap_publication_deadline=<uint64>,
        label=<string>,
    )
>>> response = stub.LoopOut(request, metadata=[('macaroon', macaroon)])
>>> print(response)
{ 
    "id": <string>,
    "id_bytes": <bytes>,
    "htlc_address": <string>,
    "htlc_address_np2wsh": <string>,
    "htlc_address_p2wsh": <string>,
    "server_message": <string>,
}
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('client.proto', loaderOptions);
const looprpc = grpc.loadPackageDefinition(packageDefinition).looprpc;
const swapClient = new looprpc.SwapClient('localhost:11010', grpc.credentials.createInsecure());
let request = { 
  amt: <int64>, 
  dest: <string>, 
  max_swap_routing_fee: <int64>, 
  max_prepay_routing_fee: <int64>, 
  max_swap_fee: <int64>, 
  max_prepay_amt: <int64>, 
  max_miner_fee: <int64>, 
  loop_out_channel: <uint64>, 
  outgoing_chan_set: <array uint64>, 
  sweep_conf_target: <int32>, 
  htlc_confirmations: <int32>, 
  swap_publication_deadline: <uint64>, 
  label: <string>, 
};
swapClient.loopOut(request, function(err, response) {
  console.log(response);
});
// Console output:
//  { 
//      "id": <string>,
//      "id_bytes": <bytes>,
//      "htlc_address": <string>,
//      "htlc_address_np2wsh": <string>,
//      "htlc_address_p2wsh": <string>,
//      "server_message": <string>,
//  }

gRPC Request: looprpc.LoopOutRequest

Parameter Type Description
amt int64 Requested swap amount in sat. This does not include the swap and miner fee.
dest string Base58 encoded destination address for the swap.
max_swap_routing_fee int64 Maximum off-chain fee in sat that may be paid for swap payment to the server. This limit is applied during path finding. Typically this value is taken from the response of the GetQuote call.
max_prepay_routing_fee int64 Maximum off-chain fee in sat that may be paid for the prepay to the server. This limit is applied during path finding. Typically this value is taken from the response of the GetQuote call.
max_swap_fee int64 Maximum we are willing to pay the server for the swap. This value is not disclosed in the swap initiation call, but if the server asks for a higher fee, we abort the swap. Typically this value is taken from the response of the GetQuote call. It includes the prepay amount.
max_prepay_amt int64 Maximum amount of the swap fee that may be charged as a prepayment.
max_miner_fee int64 Maximum in on-chain fees that we are willing to spend. If we want to sweep the on-chain htlc and the fee estimate turns out higher than this value, we cancel the swap. If the fee estimate is lower, we publish the sweep tx. If the sweep tx is not confirmed, we are forced to ratchet up fees until it is swept. Possibly even exceeding max_miner_fee if we get close to the htlc timeout. Because the initial publication revealed the preimage, we have no other choice. The server may already have pulled the off-chain htlc. Only when the fee becomes higher than the swap amount, we can only wait for fees to come down and hope - if we are past the timeout - that the server is not publishing the revocation. max_miner_fee is typically taken from the response of the GetQuote call.
loop_out_channel uint64 Deprecated, use outgoing_chan_set. The channel to loop out, the channel to loop out is selected based on the lowest routing fee for the swap payment to the server.
outgoing_chan_set array uint64 A restriction on the channel set that may be used to loop out. The actual channel(s) that will be used are selected based on the lowest routing fee for the swap payment to the server.
sweep_conf_target int32 The number of blocks from the on-chain HTLC's confirmation height that it should be swept within.
htlc_confirmations int32 The number of confirmations that we require for the on chain htlc that will be published by the server before we reveal the preimage.
swap_publication_deadline uint64 The latest time (in unix seconds) we allow the server to wait before publishing the HTLC on chain. Setting this to a larger value will give the server the opportunity to batch multiple swaps together, and wait for low-fee periods before publishing the HTLC, potentially resulting in a lower total swap fee.
label string An optional label for this swap. This field is limited to 500 characters and may not start with the prefix [reserved], which is used to tag labels produced by the daemon.

gRPC Response: looprpc.SwapResponse

Parameter Type Description
id string Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs. DEPRECATED: To make the API more consistent, this field is deprecated in favor of id_bytes and will be removed in a future release.
id_bytes bytes Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs.
htlc_address string DEPRECATED. This field stores the address of the onchain htlc, but depending on the request, the semantics are different. - For internal loop-in htlc_address contains the address of the native segwit (P2WSH) htlc. - For external loop-in htlc_address contains the address of the nested segwit (NP2WSH) htlc. - For loop-out htlc_address always contains the native segwit (P2WSH) htlc address.
htlc_address_np2wsh string The nested segwit address of the on-chain htlc. This field remains empty for loop-out.
htlc_address_p2wsh string The native segwit address of the on-chain htlc. Used for both loop-in and loop-out.
server_message string A human-readable message received from the loop server.

SwapClient.LoopOutQuote

Unary RPC

LoopOutQuote returns a quote for a loop out swap with the provided parameters.


# get a quote for the cost of a swap

$ out  get a quote for the cost of a loop out swap

# --help, -h  show help
>>> import codecs, grpc, os
>>> # Generate the following 2 modules by compiling the looprpc/client.proto with the grpcio-tools.
>>> # See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
>>> import client_pb2 as looprpc, client_pb2_grpc as clientstub
>>> channel = grpc.insecure_channel('localhost:11010')
>>> stub = clientstub.SwapClientStub(channel)
>>> request = looprpc.QuoteRequest(
        amt=<int64>,
        conf_target=<int32>,
        external_htlc=<bool>,
        swap_publication_deadline=<uint64>,
    )
>>> response = stub.LoopOutQuote(request, metadata=[('macaroon', macaroon)])
>>> print(response)
{ 
    "swap_fee_sat": <int64>,
    "prepay_amt_sat": <int64>,
    "htlc_sweep_fee_sat": <int64>,
    "swap_payment_dest": <bytes>,
    "cltv_delta": <int32>,
}
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('client.proto', loaderOptions);
const looprpc = grpc.loadPackageDefinition(packageDefinition).looprpc;
const swapClient = new looprpc.SwapClient('localhost:11010', grpc.credentials.createInsecure());
let request = { 
  amt: <int64>, 
  conf_target: <int32>, 
  external_htlc: <bool>, 
  swap_publication_deadline: <uint64>, 
};
swapClient.loopOutQuote(request, function(err, response) {
  console.log(response);
});
// Console output:
//  { 
//      "swap_fee_sat": <int64>,
//      "prepay_amt_sat": <int64>,
//      "htlc_sweep_fee_sat": <int64>,
//      "swap_payment_dest": <bytes>,
//      "cltv_delta": <int32>,
//  }

gRPC Request: looprpc.QuoteRequest

Parameter Type Description
amt int64 The amount to swap in satoshis.
conf_target int32 The confirmation target that should be used either for the sweep of the on-chain HTLC broadcast by the swap server in the case of a Loop Out, or for the confirmation of the on-chain HTLC broadcast by the swap client in the case of a Loop In.
external_htlc bool If external_htlc is true, we expect the htlc to be published by an external actor.
swap_publication_deadline uint64 The latest time (in unix seconds) we allow the server to wait before publishing the HTLC on chain. Setting this to a larger value will give the server the opportunity to batch multiple swaps together, and wait for low-fee periods before publishing the HTLC, potentially resulting in a lower total swap fee. This only has an effect on loop out quotes.

gRPC Response: looprpc.OutQuoteResponse

Parameter Type Description
swap_fee_sat int64 The fee that the swap server is charging for the swap.
prepay_amt_sat int64 The part of the swap fee that is requested as a prepayment.
htlc_sweep_fee_sat int64 An estimate of the on-chain fee that needs to be paid to sweep the HTLC for a loop out.
swap_payment_dest bytes The node pubkey where the swap payment needs to be paid to. This can be used to test connectivity before initiating the swap.
cltv_delta int32 On-chain cltv expiry delta

SwapClient.LoopOutTerms

Unary RPC

LoopOutTerms returns the terms that the server enforces for a loop out swap.


# Display the current swap terms imposed by the server.

$ loop terms [arguments...]

>>> import codecs, grpc, os
>>> # Generate the following 2 modules by compiling the looprpc/client.proto with the grpcio-tools.
>>> # See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
>>> import client_pb2 as looprpc, client_pb2_grpc as clientstub
>>> channel = grpc.insecure_channel('localhost:11010')
>>> stub = clientstub.SwapClientStub(channel)
>>> request = looprpc.TermsRequest()
>>> response = stub.LoopOutTerms(request, metadata=[('macaroon', macaroon)])
>>> print(response)
{ 
    "min_swap_amount": <int64>,
    "max_swap_amount": <int64>,
    "min_cltv_delta": <int32>,
    "max_cltv_delta": <int32>,
}
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('client.proto', loaderOptions);
const looprpc = grpc.loadPackageDefinition(packageDefinition).looprpc;
const swapClient = new looprpc.SwapClient('localhost:11010', grpc.credentials.createInsecure());
let request = {}
swapClient.loopOutTerms(request, function(err, response) {
  console.log(response);
});
// Console output:
//  { 
//      "min_swap_amount": <int64>,
//      "max_swap_amount": <int64>,
//      "min_cltv_delta": <int32>,
//      "max_cltv_delta": <int32>,
//  }

gRPC Request: looprpc.TermsRequest

This request has no parameters.

gRPC Response: looprpc.OutTermsResponse

Parameter Type Description
min_swap_amount int64 Minimum swap amount (sat)
max_swap_amount int64 Maximum swap amount (sat)
min_cltv_delta int32 The minimally accepted cltv delta of the on-chain htlc.
max_cltv_delta int32 The maximally accepted cltv delta of the on-chain htlc.

SwapClient.Monitor

Server-streaming RPC

Monitor will return a stream of swap updates for currently active swaps.


# Allows the user to monitor progress of any active swaps

$ loop monitor [arguments...]

>>> import codecs, grpc, os
>>> # Generate the following 2 modules by compiling the looprpc/client.proto with the grpcio-tools.
>>> # See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
>>> import client_pb2 as looprpc, client_pb2_grpc as clientstub
>>> channel = grpc.insecure_channel('localhost:11010')
>>> stub = clientstub.SwapClientStub(channel)
>>> request = looprpc.MonitorRequest()
>>> for response in stub.Monitor(request, metadata=[('macaroon', macaroon)]):
        print(response)
{ 
    "amt": <int64>,
    "id": <string>,
    "id_bytes": <bytes>,
    "type": <SwapType>,
    "state": <SwapState>,
    "failure_reason": <FailureReason>,
    "initiation_time": <int64>,
    "last_update_time": <int64>,
    "htlc_address": <string>,
    "htlc_address_p2wsh": <string>,
    "htlc_address_np2wsh": <string>,
    "cost_server": <int64>,
    "cost_onchain": <int64>,
    "cost_offchain": <int64>,
    "label": <string>,
}
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('client.proto', loaderOptions);
const looprpc = grpc.loadPackageDefinition(packageDefinition).looprpc;
const swapClient = new looprpc.SwapClient('localhost:11010', grpc.credentials.createInsecure());
let request = {}
let call = swapClient.monitor(request);
call.on('data', function(response) {
  // A response was received from the server.
  console.log(response);
});
call.on('status', function(status) {
  // The current status of the stream.
});
call.on('end', function() {
  // The server has closed the stream.
});
// Console output:
//  { 
//      "amt": <int64>,
//      "id": <string>,
//      "id_bytes": <bytes>,
//      "type": <SwapType>,
//      "state": <SwapState>,
//      "failure_reason": <FailureReason>,
//      "initiation_time": <int64>,
//      "last_update_time": <int64>,
//      "htlc_address": <string>,
//      "htlc_address_p2wsh": <string>,
//      "htlc_address_np2wsh": <string>,
//      "cost_server": <int64>,
//      "cost_onchain": <int64>,
//      "cost_offchain": <int64>,
//      "label": <string>,
//  }

gRPC Request: looprpc.MonitorRequest

This request has no parameters.

gRPC Response: looprpc.SwapStatus (Streaming)

Parameter Type Description
amt int64 Requested swap amount in sat. This does not include the swap and miner fee.
id string Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs. DEPRECATED: To make the API more consistent, this field is deprecated in favor of id_bytes and will be removed in a future release.
id_bytes bytes Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs.
type SwapType Swap type
state SwapState State the swap is currently in, see State enum.
failure_reason FailureReason A failure reason for the swap, only set if the swap has failed.
initiation_time int64 Initiation time of the swap.
last_update_time int64 Initiation time of the swap.
htlc_address string DEPRECATED: This field stores the address of the onchain htlc. - For internal loop-in htlc_address contains the address of the native segwit (P2WSH) htlc. - For external loop-in htlc_address contains the nested segwit (NP2WSH) address. - For loop-out htlc_address always contains the native segwit (P2WSH) htlc address.
htlc_address_p2wsh string HTLC address (native segwit), used in loop-in and loop-out swaps.
htlc_address_np2wsh string HTLC address (nested segwit), used in loop-in swaps only.
cost_server int64 Swap server cost
cost_onchain int64 On-chain transaction cost
cost_offchain int64 Off-chain routing fees
label string An optional label given to the swap on creation.

SwapClient.SwapInfo

Unary RPC

SwapInfo returns all known details about a single swap.


# Allows the user to get the status of a single swap currently stored in the database

$ loop swapinfo [command options] id

# --id value  the ID of the swap (default: 0)
>>> import codecs, grpc, os
>>> # Generate the following 2 modules by compiling the looprpc/client.proto with the grpcio-tools.
>>> # See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
>>> import client_pb2 as looprpc, client_pb2_grpc as clientstub
>>> channel = grpc.insecure_channel('localhost:11010')
>>> stub = clientstub.SwapClientStub(channel)
>>> request = looprpc.SwapInfoRequest(
        id=<bytes>,
    )
>>> response = stub.SwapInfo(request, metadata=[('macaroon', macaroon)])
>>> print(response)
{ 
    "amt": <int64>,
    "id": <string>,
    "id_bytes": <bytes>,
    "type": <SwapType>,
    "state": <SwapState>,
    "failure_reason": <FailureReason>,
    "initiation_time": <int64>,
    "last_update_time": <int64>,
    "htlc_address": <string>,
    "htlc_address_p2wsh": <string>,
    "htlc_address_np2wsh": <string>,
    "cost_server": <int64>,
    "cost_onchain": <int64>,
    "cost_offchain": <int64>,
    "label": <string>,
}
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('client.proto', loaderOptions);
const looprpc = grpc.loadPackageDefinition(packageDefinition).looprpc;
const swapClient = new looprpc.SwapClient('localhost:11010', grpc.credentials.createInsecure());
let request = { 
  id: <bytes>, 
};
swapClient.swapInfo(request, function(err, response) {
  console.log(response);
});
// Console output:
//  { 
//      "amt": <int64>,
//      "id": <string>,
//      "id_bytes": <bytes>,
//      "type": <SwapType>,
//      "state": <SwapState>,
//      "failure_reason": <FailureReason>,
//      "initiation_time": <int64>,
//      "last_update_time": <int64>,
//      "htlc_address": <string>,
//      "htlc_address_p2wsh": <string>,
//      "htlc_address_np2wsh": <string>,
//      "cost_server": <int64>,
//      "cost_onchain": <int64>,
//      "cost_offchain": <int64>,
//      "label": <string>,
//  }

gRPC Request: looprpc.SwapInfoRequest

Parameter Type Description
id bytes The swap identifier which currently is the hash that locks the HTLCs. When using REST, this field must be encoded as URL safe base64.

gRPC Response: looprpc.SwapStatus

Parameter Type Description
amt int64 Requested swap amount in sat. This does not include the swap and miner fee.
id string Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs. DEPRECATED: To make the API more consistent, this field is deprecated in favor of id_bytes and will be removed in a future release.
id_bytes bytes Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs.
type SwapType Swap type
state SwapState State the swap is currently in, see State enum.
failure_reason FailureReason A failure reason for the swap, only set if the swap has failed.
initiation_time int64 Initiation time of the swap.
last_update_time int64 Initiation time of the swap.
htlc_address string DEPRECATED: This field stores the address of the onchain htlc. - For internal loop-in htlc_address contains the address of the native segwit (P2WSH) htlc. - For external loop-in htlc_address contains the nested segwit (NP2WSH) address. - For loop-out htlc_address always contains the native segwit (P2WSH) htlc address.
htlc_address_p2wsh string HTLC address (native segwit), used in loop-in and loop-out swaps.
htlc_address_np2wsh string HTLC address (nested segwit), used in loop-in swaps only.
cost_server int64 Swap server cost
cost_onchain int64 On-chain transaction cost
cost_offchain int64 Off-chain routing fees
label string An optional label given to the swap on creation.

gRPC Messages

looprpc.InQuoteResponse

Parameter Type Description
swap_fee_sat int64 The fee that the swap server is charging for the swap.
htlc_publish_fee_sat int64 An estimate of the on-chain fee that needs to be paid to publish the HTLC If a miner fee of 0 is returned, it means the external_htlc flag was set for a loop in and the fee estimation was skipped. If a miner fee of -1 is returned, it means lnd's wallet tried to estimate the fee but was unable to create a sample estimation transaction because not enough funds are available. An information message should be shown to the user in this case.
cltv_delta int32 On-chain cltv expiry delta

looprpc.InTermsResponse

Parameter Type Description
min_swap_amount int64 Minimum swap amount (sat)
max_swap_amount int64 Maximum swap amount (sat)

looprpc.ListSwapsRequest

This message has no parameters.

looprpc.ListSwapsResponse

Parameter Type Description
swaps array SwapStatus The list of all currently known swaps and their status.

looprpc.LoopInRequest

Parameter Type Description
amt int64 Requested swap amount in sat. This does not include the swap and miner fee.
max_swap_fee int64 Maximum we are willing to pay the server for the swap. This value is not disclosed in the swap initiation call, but if the server asks for a higher fee, we abort the swap. Typically this value is taken from the response of the GetQuote call.
max_miner_fee int64 Maximum in on-chain fees that we are willing to spend. If we want to publish the on-chain htlc and the fee estimate turns out higher than this value, we cancel the swap. max_miner_fee is typically taken from the response of the GetQuote call.
last_hop bytes The last hop to use for the loop in swap. If empty, the last hop is selected based on the lowest routing fee for the swap payment from the server.
external_htlc bool If external_htlc is true, we expect the htlc to be published by an external actor.
htlc_conf_target int32 The number of blocks that the on chain htlc should confirm within.
label string An optional label for this swap. This field is limited to 500 characters and may not be one of the reserved values in loop/labels Reserved list.

looprpc.LoopOutRequest

Parameter Type Description
amt int64 Requested swap amount in sat. This does not include the swap and miner fee.
dest string Base58 encoded destination address for the swap.
max_swap_routing_fee int64 Maximum off-chain fee in sat that may be paid for swap payment to the server. This limit is applied during path finding. Typically this value is taken from the response of the GetQuote call.
max_prepay_routing_fee int64 Maximum off-chain fee in sat that may be paid for the prepay to the server. This limit is applied during path finding. Typically this value is taken from the response of the GetQuote call.
max_swap_fee int64 Maximum we are willing to pay the server for the swap. This value is not disclosed in the swap initiation call, but if the server asks for a higher fee, we abort the swap. Typically this value is taken from the response of the GetQuote call. It includes the prepay amount.
max_prepay_amt int64 Maximum amount of the swap fee that may be charged as a prepayment.
max_miner_fee int64 Maximum in on-chain fees that we are willing to spend. If we want to sweep the on-chain htlc and the fee estimate turns out higher than this value, we cancel the swap. If the fee estimate is lower, we publish the sweep tx. If the sweep tx is not confirmed, we are forced to ratchet up fees until it is swept. Possibly even exceeding max_miner_fee if we get close to the htlc timeout. Because the initial publication revealed the preimage, we have no other choice. The server may already have pulled the off-chain htlc. Only when the fee becomes higher than the swap amount, we can only wait for fees to come down and hope - if we are past the timeout - that the server is not publishing the revocation. max_miner_fee is typically taken from the response of the GetQuote call.
loop_out_channel uint64 Deprecated, use outgoing_chan_set. The channel to loop out, the channel to loop out is selected based on the lowest routing fee for the swap payment to the server.
outgoing_chan_set array uint64 A restriction on the channel set that may be used to loop out. The actual channel(s) that will be used are selected based on the lowest routing fee for the swap payment to the server.
sweep_conf_target int32 The number of blocks from the on-chain HTLC's confirmation height that it should be swept within.
htlc_confirmations int32 The number of confirmations that we require for the on chain htlc that will be published by the server before we reveal the preimage.
swap_publication_deadline uint64 The latest time (in unix seconds) we allow the server to wait before publishing the HTLC on chain. Setting this to a larger value will give the server the opportunity to batch multiple swaps together, and wait for low-fee periods before publishing the HTLC, potentially resulting in a lower total swap fee.
label string An optional label for this swap. This field is limited to 500 characters and may not start with the prefix [reserved], which is used to tag labels produced by the daemon.

looprpc.LsatToken

Parameter Type Description
base_macaroon bytes The base macaroon that was baked by the auth server.
payment_hash bytes The payment hash of the payment that was paid to obtain the token.
payment_preimage bytes The preimage of the payment hash, knowledge of this is proof that the payment has been paid. If the preimage is set to all zeros, this means the payment is still pending and the token is not yet fully valid.
amount_paid_msat int64 The amount of millisatoshis that was paid to get the token.
routing_fee_paid_msat int64 The amount of millisatoshis paid in routing fee to pay for the token.
time_created int64 The creation time of the token as UNIX timestamp in seconds.
expired bool Indicates whether the token is expired or still valid.
storage_name string Identifying attribute of this token in the store. Currently represents the file name of the token where it's stored on the file system.

looprpc.MonitorRequest

This message has no parameters.

looprpc.OutQuoteResponse

Parameter Type Description
swap_fee_sat int64 The fee that the swap server is charging for the swap.
prepay_amt_sat int64 The part of the swap fee that is requested as a prepayment.
htlc_sweep_fee_sat int64 An estimate of the on-chain fee that needs to be paid to sweep the HTLC for a loop out.
swap_payment_dest bytes The node pubkey where the swap payment needs to be paid to. This can be used to test connectivity before initiating the swap.
cltv_delta int32 On-chain cltv expiry delta

looprpc.OutTermsResponse

Parameter Type Description
min_swap_amount int64 Minimum swap amount (sat)
max_swap_amount int64 Maximum swap amount (sat)
min_cltv_delta int32 The minimally accepted cltv delta of the on-chain htlc.
max_cltv_delta int32 The maximally accepted cltv delta of the on-chain htlc.

looprpc.QuoteRequest

Parameter Type Description
amt int64 The amount to swap in satoshis.
conf_target int32 The confirmation target that should be used either for the sweep of the on-chain HTLC broadcast by the swap server in the case of a Loop Out, or for the confirmation of the on-chain HTLC broadcast by the swap client in the case of a Loop In.
external_htlc bool If external_htlc is true, we expect the htlc to be published by an external actor.
swap_publication_deadline uint64 The latest time (in unix seconds) we allow the server to wait before publishing the HTLC on chain. Setting this to a larger value will give the server the opportunity to batch multiple swaps together, and wait for low-fee periods before publishing the HTLC, potentially resulting in a lower total swap fee. This only has an effect on loop out quotes.

looprpc.SwapInfoRequest

Parameter Type Description
id bytes The swap identifier which currently is the hash that locks the HTLCs. When using REST, this field must be encoded as URL safe base64.

looprpc.SwapResponse

Parameter Type Description
id string Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs. DEPRECATED: To make the API more consistent, this field is deprecated in favor of id_bytes and will be removed in a future release.
id_bytes bytes Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs.
htlc_address string DEPRECATED. This field stores the address of the onchain htlc, but depending on the request, the semantics are different. - For internal loop-in htlc_address contains the address of the native segwit (P2WSH) htlc. - For external loop-in htlc_address contains the address of the nested segwit (NP2WSH) htlc. - For loop-out htlc_address always contains the native segwit (P2WSH) htlc address.
htlc_address_np2wsh string The nested segwit address of the on-chain htlc. This field remains empty for loop-out.
htlc_address_p2wsh string The native segwit address of the on-chain htlc. Used for both loop-in and loop-out.
server_message string A human-readable message received from the loop server.

looprpc.SwapStatus

Parameter Type Description
amt int64 Requested swap amount in sat. This does not include the swap and miner fee.
id string Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs. DEPRECATED: To make the API more consistent, this field is deprecated in favor of id_bytes and will be removed in a future release.
id_bytes bytes Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs.
type SwapType Swap type
state SwapState State the swap is currently in, see State enum.
failure_reason FailureReason A failure reason for the swap, only set if the swap has failed.
initiation_time int64 Initiation time of the swap.
last_update_time int64 Initiation time of the swap.
htlc_address string DEPRECATED: This field stores the address of the onchain htlc. - For internal loop-in htlc_address contains the address of the native segwit (P2WSH) htlc. - For external loop-in htlc_address contains the nested segwit (NP2WSH) address. - For loop-out htlc_address always contains the native segwit (P2WSH) htlc address.
htlc_address_p2wsh string HTLC address (native segwit), used in loop-in and loop-out swaps.
htlc_address_np2wsh string HTLC address (nested segwit), used in loop-in swaps only.
cost_server int64 Swap server cost
cost_onchain int64 On-chain transaction cost
cost_offchain int64 Off-chain routing fees
label string An optional label given to the swap on creation.

looprpc.TermsRequest

This message has no parameters.

looprpc.TokensRequest

This message has no parameters.

looprpc.TokensResponse

Parameter Type Description
tokens array LsatToken List of all tokens the daemon knows of, including old/expired tokens.

gRPC Enums

FailureReason

Name Value Description
FAILURE_REASON_NONE 0 FAILURE_REASON_NONE is set when the swap did not fail, it is either in progress or succeeded.
FAILURE_REASON_OFFCHAIN 1 FAILURE_REASON_OFFCHAIN indicates that a loop out failed because it wasn't possible to find a route for one or both off chain payments that met the fee and timelock limits required.
FAILURE_REASON_TIMEOUT 2 FAILURE_REASON_TIMEOUT indicates that the swap failed because on chain htlc did not confirm before its expiry, or it confirmed too late for us to reveal our preimage and claim.
FAILURE_REASON_SWEEP_TIMEOUT 3 FAILURE_REASON_SWEEP_TIMEOUT indicates that a loop out permanently failed because the on chain htlc wasn't swept before the server revoked the htlc.
FAILURE_REASON_INSUFFICIENT_VALUE 4 FAILURE_REASON_INSUFFICIENT_VALUE indicates that a loop out has failed because the on chain htlc had a lower value than requested.
FAILURE_REASON_TEMPORARY 5 FAILURE_REASON_TEMPORARY indicates that a swap cannot continue due to an internal error. Manual intervention such as a restart is required.
FAILURE_REASON_INCORRECT_AMOUNT 6 FAILURE_REASON_INCORRECT_AMOUNT indicates that a loop in permanently failed because the amount extended by an external loop in htlc is insufficient.

SwapState

Name Value Description
INITIATED 0 INITIATED is the initial state of a swap. At that point, the initiation call to the server has been made and the payment process has been started for the swap and prepayment invoices.
PREIMAGE_REVEALED 1 PREIMAGE_REVEALED is reached when the sweep tx publication is first attempted. From that point on, we should consider the preimage to no longer be secret and we need to do all we can to get the sweep confirmed. This state will mostly coalesce with StateHtlcConfirmed, except in the case where we wait for fees to come down before we sweep.
HTLC_PUBLISHED 2 HTLC_PUBLISHED is reached when the htlc tx has been published in a loop in swap.
SUCCESS 3 SUCCESS is the final swap state that is reached when the sweep tx has the required confirmation depth.
FAILED 4 FAILED is the final swap state for a failed swap with or without loss of the swap amount.
INVOICE_SETTLED 5 INVOICE_SETTLED is reached when the swap invoice in a loop in swap has been paid, but we are still waiting for the htlc spend to confirm.

SwapType

Name Value Description
LOOP_OUT 0 LOOP_OUT indicates an loop out swap (off-chain to on-chain)
LOOP_IN 1 LOOP_IN indicates a loop in swap (on-chain to off-chain)

Loop REST API Reference

Welcome to the REST API reference documentation for Lightning Loop.

Lightning Loop is a non-custodial service offered by Lightning Labs to bridge on-chain and off-chain Bitcoin using submarine swaps. This repository is home to the Loop client and depends on the Lightning Network daemon lnd. All of lnd’s supported chain backends are fully supported when using the Loop client: Neutrino, Bitcoin Core, and btcd.

The service can be used in various situations:

This site features the API documentation for shell script (CLI), Python and JavaScript clients in order to communicate with a local loopd instance through gRPC. Currently, this communication is unauthenticated, so exposing this service to the internet is not recommended.

The original *.swagger.js files from which the gRPC documentation was generated can be found here:

NOTE: The byte field type must be set as the base64 encoded string representation of a raw byte array.

This is the reference for the REST API. Alternatively, there is also a gRPC API which is documented here.

This documentation was generated automatically against commit 10c7c34d5949114ac10e473a7405ffd4ebafa150.

/v1/loop/in

$ curl -X POST http://localhost:8081/v1/loop/in -d '{ \
    "amt":<string>, \
    "max_swap_fee":<string>, \
    "max_miner_fee":<string>, \
    "last_hop":<byte>, \
    "external_htlc":<boolean>, \
    "htlc_conf_target":<int32>, \
    "label":<string>, \
}'
{ 
    "id": <string>, 
    "id_bytes": <byte>, 
    "htlc_address": <string>, 
    "htlc_address_np2wsh": <string>, 
    "htlc_address_p2wsh": <string>, 
    "server_message": <string>, 
}
>>> import base64, json, requests
>>> url = 'http://localhost:8081/v1/loop/in'
>>> data = { 
        'amt': <string>, 
        'max_swap_fee': <string>, 
        'max_miner_fee': <string>, 
        'last_hop': base64.b64encode(<byte>).decode(), 
        'external_htlc': <boolean>, 
        'htlc_conf_target': <int32>, 
        'label': <string>, 
    }
>>> r = requests.post(url, verify=cert_path, data=json.dumps(data))
>>> print(r.json())
{ 
    "id": <string>, 
    "id_bytes": <byte>, 
    "htlc_address": <string>, 
    "htlc_address_np2wsh": <string>, 
    "htlc_address_p2wsh": <string>, 
    "server_message": <string>, 
}
const request = require('request');
let requestBody = { 
  amt: <string>,
  max_swap_fee: <string>,
  max_miner_fee: <string>,
  last_hop: <byte>,
  external_htlc: <boolean>,
  htlc_conf_target: <int32>,
  label: <string>,
};
let options = {
  url: 'http://localhost:8081/v1/loop/in',
  json: true,
  form: JSON.stringify(requestBody)
};
request.post(options, function(error, response, body) {
  console.log(body);
});
// Console output:
//  { 
//      "id": <string>, 
//      "id_bytes": <byte>, 
//      "htlc_address": <string>, 
//      "htlc_address_np2wsh": <string>, 
//      "htlc_address_p2wsh": <string>, 
//      "server_message": <string>, 
//  }

POST /v1/loop/in

loop: in LoopIn initiates a loop in swap with the given parameters. The call returns after the swap has been set up with the swap server. From that point onwards, progress can be tracked via the SwapStatus stream that is returned from Monitor().

Field Type Placement Description
amt string body Requested swap amount in sat. This does not include the swap and miner fee.
max_swap_fee string body Maximum we are willing to pay the server for the swap. This value is not disclosed in the swap initiation call, but if the server asks for a higher fee, we abort the swap. Typically this value is taken from the response of the GetQuote call.
max_miner_fee string body Maximum in on-chain fees that we are willing to spend. If we want to publish the on-chain htlc and the fee estimate turns out higher than this value, we cancel the swap. max_miner_fee is typically taken from the response of the GetQuote call.
last_hop byte body The last hop to use for the loop in swap. If empty, the last hop is selected based on the lowest routing fee for the swap payment from the server.
external_htlc boolean body If external_htlc is true, we expect the htlc to be published by an external actor.
htlc_conf_target int32 body The number of blocks that the on chain htlc should confirm within.
label string body An optional label for this swap. This field is limited to 500 characters and may not be one of the reserved values in loop/labels Reserved list.

Response

Field Type Description
id string Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs. DEPRECATED: To make the API more consistent, this field is deprecated in favor of id_bytes and will be removed in a future release.
id_bytes byte Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs.
htlc_address string DEPRECATED. This field stores the address of the onchain htlc, but depending on the request, the semantics are different. - For internal loop-in htlc_address contains the address of the native segwit (P2WSH) htlc. - For external loop-in htlc_address contains the address of the nested segwit (NP2WSH) htlc. - For loop-out htlc_address always contains the native segwit (P2WSH) htlc address.
htlc_address_np2wsh string The nested segwit address of the on-chain htlc. This field remains empty for loop-out.
htlc_address_p2wsh string The native segwit address of the on-chain htlc. Used for both loop-in and loop-out.
server_message string A human-readable message received from the loop server.

/v1/loop/in/quote

$ curl -X GET http://localhost:8081/v1/loop/in/quote/{amt}
{ 
    "swap_fee_sat": <string>, 
    "htlc_publish_fee_sat": <string>, 
    "cltv_delta": <int32>, 
}
>>> import base64, json, requests
>>> url = 'http://localhost:8081/v1/loop/in/quote/{amt}'
>>> r = requests.get(url, verify=cert_path)
>>> print(r.json())
{ 
    "swap_fee_sat": <string>, 
    "htlc_publish_fee_sat": <string>, 
    "cltv_delta": <int32>, 
}
const request = require('request');
let options = {
  url: 'http://localhost:8081/v1/loop/in/quote/{amt}',
  json: true
};
request.get(options, function(error, response, body) {
  console.log(body);
});
// Console output:
//  { 
//      "swap_fee_sat": <string>, 
//      "htlc_publish_fee_sat": <string>, 
//      "cltv_delta": <int32>, 
//  }

GET /v1/loop/in/quote/{amt}

loop: quote GetQuote returns a quote for a swap with the provided parameters.

Field Type Placement Description
amt string path The amount to swap in satoshis.
conf_target int32 query The confirmation target that should be used either for the sweep of the on-chain HTLC broadcast by the swap server in the case of a Loop Out, or for the confirmation of the on-chain HTLC broadcast by the swap client in the case of a Loop In.
external_htlc boolean query If external_htlc is true, we expect the htlc to be published by an external actor.
swap_publication_deadline string query The latest time (in unix seconds) we allow the server to wait before publishing the HTLC on chain. Setting this to a larger value will give the server the opportunity to batch multiple swaps together, and wait for low-fee periods before publishing the HTLC, potentially resulting in a lower total swap fee. This only has an effect on loop out quotes.

Response

Field Type Description
swap_fee_sat string The fee that the swap server is charging for the swap.
htlc_publish_fee_sat string An estimate of the on-chain fee that needs to be paid to publish the HTLC If a miner fee of 0 is returned, it means the external_htlc flag was set for a loop in and the fee estimation was skipped. If a miner fee of -1 is returned, it means lnd's wallet tried to estimate the fee but was unable to create a sample estimation transaction because not enough funds are available. An information message should be shown to the user in this case.
cltv_delta int32 On-chain cltv expiry delta

/v1/loop/in/terms

$ curl -X GET http://localhost:8081/v1/loop/in/terms
{ 
    "min_swap_amount": <string>, 
    "max_swap_amount": <string>, 
}
>>> import base64, json, requests
>>> url = 'http://localhost:8081/v1/loop/in/terms'
>>> r = requests.get(url, verify=cert_path)
>>> print(r.json())
{ 
    "min_swap_amount": <string>, 
    "max_swap_amount": <string>, 
}
const request = require('request');
let options = {
  url: 'http://localhost:8081/v1/loop/in/terms',
  json: true
};
request.get(options, function(error, response, body) {
  console.log(body);
});
// Console output:
//  { 
//      "min_swap_amount": <string>, 
//      "max_swap_amount": <string>, 
//  }

GET /v1/loop/in/terms

loop: terms GetTerms returns the terms that the server enforces for swaps.

This request has no parameters.

Response

Field Type Description
min_swap_amount string Minimum swap amount (sat)
max_swap_amount string Maximum swap amount (sat)

/v1/loop/out

$ curl -X POST http://localhost:8081/v1/loop/out -d '{ \
    "amt":<string>, \
    "dest":<string>, \
    "max_swap_routing_fee":<string>, \
    "max_prepay_routing_fee":<string>, \
    "max_swap_fee":<string>, \
    "max_prepay_amt":<string>, \
    "max_miner_fee":<string>, \
    "loop_out_channel":<string>, \
    "outgoing_chan_set":<array string>, \
    "sweep_conf_target":<int32>, \
    "htlc_confirmations":<int32>, \
    "swap_publication_deadline":<string>, \
    "label":<string>, \
}'
{ 
    "id": <string>, 
    "id_bytes": <byte>, 
    "htlc_address": <string>, 
    "htlc_address_np2wsh": <string>, 
    "htlc_address_p2wsh": <string>, 
    "server_message": <string>, 
}
>>> import base64, json, requests
>>> url = 'http://localhost:8081/v1/loop/out'
>>> data = { 
        'amt': <string>, 
        'dest': <string>, 
        'max_swap_routing_fee': <string>, 
        'max_prepay_routing_fee': <string>, 
        'max_swap_fee': <string>, 
        'max_prepay_amt': <string>, 
        'max_miner_fee': <string>, 
        'loop_out_channel': <string>, 
        'outgoing_chan_set': <array string>, 
        'sweep_conf_target': <int32>, 
        'htlc_confirmations': <int32>, 
        'swap_publication_deadline': <string>, 
        'label': <string>, 
    }
>>> r = requests.post(url, verify=cert_path, data=json.dumps(data))
>>> print(r.json())
{ 
    "id": <string>, 
    "id_bytes": <byte>, 
    "htlc_address": <string>, 
    "htlc_address_np2wsh": <string>, 
    "htlc_address_p2wsh": <string>, 
    "server_message": <string>, 
}
const request = require('request');
let requestBody = { 
  amt: <string>,
  dest: <string>,
  max_swap_routing_fee: <string>,
  max_prepay_routing_fee: <string>,
  max_swap_fee: <string>,
  max_prepay_amt: <string>,
  max_miner_fee: <string>,
  loop_out_channel: <string>,
  outgoing_chan_set: <array string>,
  sweep_conf_target: <int32>,
  htlc_confirmations: <int32>,
  swap_publication_deadline: <string>,
  label: <string>,
};
let options = {
  url: 'http://localhost:8081/v1/loop/out',
  json: true,
  form: JSON.stringify(requestBody)
};
request.post(options, function(error, response, body) {
  console.log(body);
});
// Console output:
//  { 
//      "id": <string>, 
//      "id_bytes": <byte>, 
//      "htlc_address": <string>, 
//      "htlc_address_np2wsh": <string>, 
//      "htlc_address_p2wsh": <string>, 
//      "server_message": <string>, 
//  }

POST /v1/loop/out

loop: out LoopOut initiates an loop out swap with the given parameters. The call returns after the swap has been set up with the swap server. From that point onwards, progress can be tracked via the SwapStatus stream that is returned from Monitor().

Field Type Placement Description
amt string body Requested swap amount in sat. This does not include the swap and miner fee.
dest string body Base58 encoded destination address for the swap.
max_swap_routing_fee string body Maximum off-chain fee in sat that may be paid for swap payment to the server. This limit is applied during path finding. Typically this value is taken from the response of the GetQuote call.
max_prepay_routing_fee string body Maximum off-chain fee in sat that may be paid for the prepay to the server. This limit is applied during path finding. Typically this value is taken from the response of the GetQuote call.
max_swap_fee string body Maximum we are willing to pay the server for the swap. This value is not disclosed in the swap initiation call, but if the server asks for a higher fee, we abort the swap. Typically this value is taken from the response of the GetQuote call. It includes the prepay amount.
max_prepay_amt string body Maximum amount of the swap fee that may be charged as a prepayment.
max_miner_fee string body Maximum in on-chain fees that we are willing to spend. If we want to sweep the on-chain htlc and the fee estimate turns out higher than this value, we cancel the swap. If the fee estimate is lower, we publish the sweep tx. If the sweep tx is not confirmed, we are forced to ratchet up fees until it is swept. Possibly even exceeding max_miner_fee if we get close to the htlc timeout. Because the initial publication revealed the preimage, we have no other choice. The server may already have pulled the off-chain htlc. Only when the fee becomes higher than the swap amount, we can only wait for fees to come down and hope - if we are past the timeout - that the server is not publishing the revocation. max_miner_fee is typically taken from the response of the GetQuote call.
loop_out_channel string body Deprecated, use outgoing_chan_set. The channel to loop out, the channel to loop out is selected based on the lowest routing fee for the swap payment to the server.
outgoing_chan_set array string body A restriction on the channel set that may be used to loop out. The actual channel(s) that will be used are selected based on the lowest routing fee for the swap payment to the server.
sweep_conf_target int32 body The number of blocks from the on-chain HTLC's confirmation height that it should be swept within.
htlc_confirmations int32 body The number of confirmations that we require for the on chain htlc that will be published by the server before we reveal the preimage.
swap_publication_deadline string body The latest time (in unix seconds) we allow the server to wait before publishing the HTLC on chain. Setting this to a larger value will give the server the opportunity to batch multiple swaps together, and wait for low-fee periods before publishing the HTLC, potentially resulting in a lower total swap fee.
label string body An optional label for this swap. This field is limited to 500 characters and may not start with the prefix [reserved], which is used to tag labels produced by the daemon.

Response

Field Type Description
id string Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs. DEPRECATED: To make the API more consistent, this field is deprecated in favor of id_bytes and will be removed in a future release.
id_bytes byte Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs.
htlc_address string DEPRECATED. This field stores the address of the onchain htlc, but depending on the request, the semantics are different. - For internal loop-in htlc_address contains the address of the native segwit (P2WSH) htlc. - For external loop-in htlc_address contains the address of the nested segwit (NP2WSH) htlc. - For loop-out htlc_address always contains the native segwit (P2WSH) htlc address.
htlc_address_np2wsh string The nested segwit address of the on-chain htlc. This field remains empty for loop-out.
htlc_address_p2wsh string The native segwit address of the on-chain htlc. Used for both loop-in and loop-out.
server_message string A human-readable message received from the loop server.

/v1/loop/out/quote

$ curl -X GET http://localhost:8081/v1/loop/out/quote/{amt}
{ 
    "swap_fee_sat": <string>, 
    "prepay_amt_sat": <string>, 
    "htlc_sweep_fee_sat": <string>, 
    "swap_payment_dest": <byte>, 
    "cltv_delta": <int32>, 
}
>>> import base64, json, requests
>>> url = 'http://localhost:8081/v1/loop/out/quote/{amt}'
>>> r = requests.get(url, verify=cert_path)
>>> print(r.json())
{ 
    "swap_fee_sat": <string>, 
    "prepay_amt_sat": <string>, 
    "htlc_sweep_fee_sat": <string>, 
    "swap_payment_dest": <byte>, 
    "cltv_delta": <int32>, 
}
const request = require('request');
let options = {
  url: 'http://localhost:8081/v1/loop/out/quote/{amt}',
  json: true
};
request.get(options, function(error, response, body) {
  console.log(body);
});
// Console output:
//  { 
//      "swap_fee_sat": <string>, 
//      "prepay_amt_sat": <string>, 
//      "htlc_sweep_fee_sat": <string>, 
//      "swap_payment_dest": <byte>, 
//      "cltv_delta": <int32>, 
//  }

GET /v1/loop/out/quote/{amt}

loop: quote LoopOutQuote returns a quote for a loop out swap with the provided parameters.

Field Type Placement Description
amt string path The amount to swap in satoshis.
conf_target int32 query The confirmation target that should be used either for the sweep of the on-chain HTLC broadcast by the swap server in the case of a Loop Out, or for the confirmation of the on-chain HTLC broadcast by the swap client in the case of a Loop In.
external_htlc boolean query If external_htlc is true, we expect the htlc to be published by an external actor.
swap_publication_deadline string query The latest time (in unix seconds) we allow the server to wait before publishing the HTLC on chain. Setting this to a larger value will give the server the opportunity to batch multiple swaps together, and wait for low-fee periods before publishing the HTLC, potentially resulting in a lower total swap fee. This only has an effect on loop out quotes.

Response

Field Type Description
swap_fee_sat string The fee that the swap server is charging for the swap.
prepay_amt_sat string The part of the swap fee that is requested as a prepayment.
htlc_sweep_fee_sat string An estimate of the on-chain fee that needs to be paid to sweep the HTLC for a loop out.
swap_payment_dest byte The node pubkey where the swap payment needs to be paid to. This can be used to test connectivity before initiating the swap.
cltv_delta int32 On-chain cltv expiry delta

/v1/loop/out/terms

$ curl -X GET http://localhost:8081/v1/loop/out/terms
{ 
    "min_swap_amount": <string>, 
    "max_swap_amount": <string>, 
    "min_cltv_delta": <int32>, 
    "max_cltv_delta": <int32>, 
}
>>> import base64, json, requests
>>> url = 'http://localhost:8081/v1/loop/out/terms'
>>> r = requests.get(url, verify=cert_path)
>>> print(r.json())
{ 
    "min_swap_amount": <string>, 
    "max_swap_amount": <string>, 
    "min_cltv_delta": <int32>, 
    "max_cltv_delta": <int32>, 
}
const request = require('request');
let options = {
  url: 'http://localhost:8081/v1/loop/out/terms',
  json: true
};
request.get(options, function(error, response, body) {
  console.log(body);
});
// Console output:
//  { 
//      "min_swap_amount": <string>, 
//      "max_swap_amount": <string>, 
//      "min_cltv_delta": <int32>, 
//      "max_cltv_delta": <int32>, 
//  }

GET /v1/loop/out/terms

loop: terms LoopOutTerms returns the terms that the server enforces for a loop out swap.

This request has no parameters.

Response

Field Type Description
min_swap_amount string Minimum swap amount (sat)
max_swap_amount string Maximum swap amount (sat)
min_cltv_delta int32 The minimally accepted cltv delta of the on-chain htlc.
max_cltv_delta int32 The maximally accepted cltv delta of the on-chain htlc.

/v1/loop/swap

$ curl -X GET http://localhost:8081/v1/loop/swap/{id}
{ 
    "amt": <string>, 
    "id": <string>, 
    "id_bytes": <byte>, 
    "type": <looprpcSwapType>, 
    "state": <looprpcSwapState>, 
    "failure_reason": <looprpcFailureReason>, 
    "initiation_time": <string>, 
    "last_update_time": <string>, 
    "htlc_address": <string>, 
    "htlc_address_p2wsh": <string>, 
    "htlc_address_np2wsh": <string>, 
    "cost_server": <string>, 
    "cost_onchain": <string>, 
    "cost_offchain": <string>, 
    "label": <string>, 
}
>>> import base64, json, requests
>>> url = 'http://localhost:8081/v1/loop/swap/{id}'
>>> r = requests.get(url, verify=cert_path)
>>> print(r.json())
{ 
    "amt": <string>, 
    "id": <string>, 
    "id_bytes": <byte>, 
    "type": <looprpcSwapType>, 
    "state": <looprpcSwapState>, 
    "failure_reason": <looprpcFailureReason>, 
    "initiation_time": <string>, 
    "last_update_time": <string>, 
    "htlc_address": <string>, 
    "htlc_address_p2wsh": <string>, 
    "htlc_address_np2wsh": <string>, 
    "cost_server": <string>, 
    "cost_onchain": <string>, 
    "cost_offchain": <string>, 
    "label": <string>, 
}
const request = require('request');
let options = {
  url: 'http://localhost:8081/v1/loop/swap/{id}',
  json: true
};
request.get(options, function(error, response, body) {
  console.log(body);
});
// Console output:
//  { 
//      "amt": <string>, 
//      "id": <string>, 
//      "id_bytes": <byte>, 
//      "type": <looprpcSwapType>, 
//      "state": <looprpcSwapState>, 
//      "failure_reason": <looprpcFailureReason>, 
//      "initiation_time": <string>, 
//      "last_update_time": <string>, 
//      "htlc_address": <string>, 
//      "htlc_address_p2wsh": <string>, 
//      "htlc_address_np2wsh": <string>, 
//      "cost_server": <string>, 
//      "cost_onchain": <string>, 
//      "cost_offchain": <string>, 
//      "label": <string>, 
//  }

GET /v1/loop/swap/{id}

loop: swapinfo SwapInfo returns all known details about a single swap.

Field Type Placement Description
id string path The swap identifier which currently is the hash that locks the HTLCs. When using REST, this field must be encoded as URL safe base64.

Response

Field Type Description
amt string Requested swap amount in sat. This does not include the swap and miner fee.
id string Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs. DEPRECATED: To make the API more consistent, this field is deprecated in favor of id_bytes and will be removed in a future release.
id_bytes byte Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs.
type looprpcSwapType Swap type
state looprpcSwapState State the swap is currently in, see State enum.
failure_reason looprpcFailureReason A failure reason for the swap, only set if the swap has failed.
initiation_time string Initiation time of the swap.
last_update_time string Initiation time of the swap.
htlc_address string DEPRECATED: This field stores the address of the onchain htlc. - For internal loop-in htlc_address contains the address of the native segwit (P2WSH) htlc. - For external loop-in htlc_address contains the nested segwit (NP2WSH) address. - For loop-out htlc_address always contains the native segwit (P2WSH) htlc address.
htlc_address_p2wsh string HTLC address (native segwit), used in loop-in and loop-out swaps.
htlc_address_np2wsh string HTLC address (nested segwit), used in loop-in swaps only.
cost_server string Swap server cost
cost_onchain string On-chain transaction cost
cost_offchain string Off-chain routing fees
label string An optional label given to the swap on creation.

/v1/loop/swaps

$ curl -X GET http://localhost:8081/v1/loop/swaps
{ 
    "swaps": <array looprpcSwapStatus>, 
}
>>> import base64, json, requests
>>> url = 'http://localhost:8081/v1/loop/swaps'
>>> r = requests.get(url, verify=cert_path)
>>> print(r.json())
{ 
    "swaps": <array looprpcSwapStatus>, 
}
const request = require('request');
let options = {
  url: 'http://localhost:8081/v1/loop/swaps',
  json: true
};
request.get(options, function(error, response, body) {
  console.log(body);
});
// Console output:
//  { 
//      "swaps": <array looprpcSwapStatus>, 
//  }

GET /v1/loop/swaps

loop: listswaps ListSwaps returns a list of all currently known swaps and their current status.

This request has no parameters.

Response

Field Type Description
swaps array looprpcSwapStatus The list of all currently known swaps and their status.

/v1/lsat/tokens

$ curl -X GET http://localhost:8081/v1/lsat/tokens
{ 
    "tokens": <array looprpcLsatToken>, 
}
>>> import base64, json, requests
>>> url = 'http://localhost:8081/v1/lsat/tokens'
>>> r = requests.get(url, verify=cert_path)
>>> print(r.json())
{ 
    "tokens": <array looprpcLsatToken>, 
}
const request = require('request');
let options = {
  url: 'http://localhost:8081/v1/lsat/tokens',
  json: true
};
request.get(options, function(error, response, body) {
  console.log(body);
});
// Console output:
//  { 
//      "tokens": <array looprpcLsatToken>, 
//  }

GET /v1/lsat/tokens

loop: listauth GetLsatTokens returns all LSAT tokens the daemon ever paid for.

This request has no parameters.

Response

Field Type Description
tokens array looprpcLsatToken List of all tokens the daemon knows of, including old/expired tokens.

REST messages

looprpcInQuoteResponse

Field Type Description
swap_fee_sat string The fee that the swap server is charging for the swap.
htlc_publish_fee_sat string An estimate of the on-chain fee that needs to be paid to publish the HTLC If a miner fee of 0 is returned, it means the external_htlc flag was set for a loop in and the fee estimation was skipped. If a miner fee of -1 is returned, it means lnd's wallet tried to estimate the fee but was unable to create a sample estimation transaction because not enough funds are available. An information message should be shown to the user in this case.
cltv_delta int32 On-chain cltv expiry delta

looprpcInTermsResponse

Field Type Description
min_swap_amount string Minimum swap amount (sat)
max_swap_amount string Maximum swap amount (sat)

looprpcListSwapsResponse

Field Type Description
swaps array looprpcSwapStatus The list of all currently known swaps and their status.

looprpcLoopInRequest

Field Type Description
amt string Requested swap amount in sat. This does not include the swap and miner fee.
max_swap_fee string Maximum we are willing to pay the server for the swap. This value is not disclosed in the swap initiation call, but if the server asks for a higher fee, we abort the swap. Typically this value is taken from the response of the GetQuote call.
max_miner_fee string Maximum in on-chain fees that we are willing to spend. If we want to publish the on-chain htlc and the fee estimate turns out higher than this value, we cancel the swap. max_miner_fee is typically taken from the response of the GetQuote call.
last_hop byte The last hop to use for the loop in swap. If empty, the last hop is selected based on the lowest routing fee for the swap payment from the server.
external_htlc boolean If external_htlc is true, we expect the htlc to be published by an external actor.
htlc_conf_target int32 The number of blocks that the on chain htlc should confirm within.
label string An optional label for this swap. This field is limited to 500 characters and may not be one of the reserved values in loop/labels Reserved list.

looprpcLoopOutRequest

Field Type Description
amt string Requested swap amount in sat. This does not include the swap and miner fee.
dest string Base58 encoded destination address for the swap.
max_swap_routing_fee string Maximum off-chain fee in sat that may be paid for swap payment to the server. This limit is applied during path finding. Typically this value is taken from the response of the GetQuote call.
max_prepay_routing_fee string Maximum off-chain fee in sat that may be paid for the prepay to the server. This limit is applied during path finding. Typically this value is taken from the response of the GetQuote call.
max_swap_fee string Maximum we are willing to pay the server for the swap. This value is not disclosed in the swap initiation call, but if the server asks for a higher fee, we abort the swap. Typically this value is taken from the response of the GetQuote call. It includes the prepay amount.
max_prepay_amt string Maximum amount of the swap fee that may be charged as a prepayment.
max_miner_fee string Maximum in on-chain fees that we are willing to spend. If we want to sweep the on-chain htlc and the fee estimate turns out higher than this value, we cancel the swap. If the fee estimate is lower, we publish the sweep tx. If the sweep tx is not confirmed, we are forced to ratchet up fees until it is swept. Possibly even exceeding max_miner_fee if we get close to the htlc timeout. Because the initial publication revealed the preimage, we have no other choice. The server may already have pulled the off-chain htlc. Only when the fee becomes higher than the swap amount, we can only wait for fees to come down and hope - if we are past the timeout - that the server is not publishing the revocation. max_miner_fee is typically taken from the response of the GetQuote call.
loop_out_channel string Deprecated, use outgoing_chan_set. The channel to loop out, the channel to loop out is selected based on the lowest routing fee for the swap payment to the server.
outgoing_chan_set array string A restriction on the channel set that may be used to loop out. The actual channel(s) that will be used are selected based on the lowest routing fee for the swap payment to the server.
sweep_conf_target int32 The number of blocks from the on-chain HTLC's confirmation height that it should be swept within.
htlc_confirmations int32 The number of confirmations that we require for the on chain htlc that will be published by the server before we reveal the preimage.
swap_publication_deadline string The latest time (in unix seconds) we allow the server to wait before publishing the HTLC on chain. Setting this to a larger value will give the server the opportunity to batch multiple swaps together, and wait for low-fee periods before publishing the HTLC, potentially resulting in a lower total swap fee.
label string An optional label for this swap. This field is limited to 500 characters and may not start with the prefix [reserved], which is used to tag labels produced by the daemon.

looprpcLsatToken

Field Type Description
base_macaroon byte The base macaroon that was baked by the auth server.
payment_hash byte The payment hash of the payment that was paid to obtain the token.
payment_preimage byte The preimage of the payment hash, knowledge of this is proof that the payment has been paid. If the preimage is set to all zeros, this means the payment is still pending and the token is not yet fully valid.
amount_paid_msat string The amount of millisatoshis that was paid to get the token.
routing_fee_paid_msat string The amount of millisatoshis paid in routing fee to pay for the token.
time_created string The creation time of the token as UNIX timestamp in seconds.
expired boolean Indicates whether the token is expired or still valid.
storage_name string Identifying attribute of this token in the store. Currently represents the file name of the token where it's stored on the file system.

looprpcOutQuoteResponse

Field Type Description
swap_fee_sat string The fee that the swap server is charging for the swap.
prepay_amt_sat string The part of the swap fee that is requested as a prepayment.
htlc_sweep_fee_sat string An estimate of the on-chain fee that needs to be paid to sweep the HTLC for a loop out.
swap_payment_dest byte The node pubkey where the swap payment needs to be paid to. This can be used to test connectivity before initiating the swap.
cltv_delta int32 On-chain cltv expiry delta

looprpcOutTermsResponse

Field Type Description
min_swap_amount string Minimum swap amount (sat)
max_swap_amount string Maximum swap amount (sat)
min_cltv_delta int32 The minimally accepted cltv delta of the on-chain htlc.
max_cltv_delta int32 The maximally accepted cltv delta of the on-chain htlc.

looprpcSwapResponse

Field Type Description
id string Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs. DEPRECATED: To make the API more consistent, this field is deprecated in favor of id_bytes and will be removed in a future release.
id_bytes byte Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs.
htlc_address string DEPRECATED. This field stores the address of the onchain htlc, but depending on the request, the semantics are different. - For internal loop-in htlc_address contains the address of the native segwit (P2WSH) htlc. - For external loop-in htlc_address contains the address of the nested segwit (NP2WSH) htlc. - For loop-out htlc_address always contains the native segwit (P2WSH) htlc address.
htlc_address_np2wsh string The nested segwit address of the on-chain htlc. This field remains empty for loop-out.
htlc_address_p2wsh string The native segwit address of the on-chain htlc. Used for both loop-in and loop-out.
server_message string A human-readable message received from the loop server.

looprpcSwapStatus

Field Type Description
amt string Requested swap amount in sat. This does not include the swap and miner fee.
id string Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs. DEPRECATED: To make the API more consistent, this field is deprecated in favor of id_bytes and will be removed in a future release.
id_bytes byte Swap identifier to track status in the update stream that is returned from the Start() call. Currently this is the hash that locks the htlcs.
type looprpcSwapType Swap type
state looprpcSwapState State the swap is currently in, see State enum.
failure_reason looprpcFailureReason A failure reason for the swap, only set if the swap has failed.
initiation_time string Initiation time of the swap.
last_update_time string Initiation time of the swap.
htlc_address string DEPRECATED: This field stores the address of the onchain htlc. - For internal loop-in htlc_address contains the address of the native segwit (P2WSH) htlc. - For external loop-in htlc_address contains the nested segwit (NP2WSH) address. - For loop-out htlc_address always contains the native segwit (P2WSH) htlc address.
htlc_address_p2wsh string HTLC address (native segwit), used in loop-in and loop-out swaps.
htlc_address_np2wsh string HTLC address (nested segwit), used in loop-in swaps only.
cost_server string Swap server cost
cost_onchain string On-chain transaction cost
cost_offchain string Off-chain routing fees
label string An optional label given to the swap on creation.

looprpcTokensResponse

Field Type Description
tokens array looprpcLsatToken List of all tokens the daemon knows of, including old/expired tokens.

protobufAny

Field Type Description
type_url string
value byte

runtimeError

Field Type Description
error string
code int32
message string
details array protobufAny

runtimeStreamError

Field Type Description
grpc_code int32
http_code int32
message string
http_status string
details array protobufAny

REST Enums

looprpcFailureReason

Name Value Description
FAILURE_REASON_NONE 0
FAILURE_REASON_OFFCHAIN 1
FAILURE_REASON_TIMEOUT 2
FAILURE_REASON_SWEEP_TIMEOUT 3
FAILURE_REASON_INSUFFICIENT_VALUE 4
FAILURE_REASON_TEMPORARY 5
FAILURE_REASON_INCORRECT_AMOUNT 6

looprpcSwapState

Name Value Description
INITIATED 0 INITIATED is the initial state of a swap. At that point, the initiation call to the server has been made and the payment process has been started for the swap and prepayment invoices.
PREIMAGE_REVEALED 1 PREIMAGE_REVEALED is reached when the sweep tx publication is first attempted. From that point on, we should consider the preimage to no longer be secret and we need to do all we can to get the sweep confirmed. This state will mostly coalesce with StateHtlcConfirmed, except in the case where we wait for fees to come down before we sweep.
HTLC_PUBLISHED 2 HTLC_PUBLISHED is reached when the htlc tx has been published in a loop in swap.
SUCCESS 3 SUCCESS is the final swap state that is reached when the sweep tx has the required confirmation depth.
FAILED 4 FAILED is the final swap state for a failed swap with or without loss of the swap amount.
INVOICE_SETTLED 5 INVOICE_SETTLED is reached when the swap invoice in a loop in swap has been paid, but we are still waiting for the htlc spend to confirm.

looprpcSwapType

Name Value Description
LOOP_OUT 0
LOOP_IN 1

Other API References

This is the gRPC and REST API reference for the loopd daemon. There are separate API reference documents for the following daemons: