Orders

Overview

Now that we have our account set up and funded, it's time to trade some channels!
There are two types of orders in the current version of Pool: asks, and bids. You submit an ask when you have some coins that you want to lease out as inbound liquidity for a certain period of time (expressed in blocks), at a fixed rate compounded per block. You submit a bid when you need to acquire inbound liquidity (ability to receive), for a given amount of time (again expressed in blocks), paying out a fixed rate that compounds per-block.
In the alpha version of Lightning Pool, a single lump sum premium is paid after order execution. In future versions, we plan on introducing "coupon channels" which allow for streaming interest to be paid out.
One important aspect of the market is that rather than buy/sell satoshis, we use units. A unit is simply 100,000 satoshis and represents the smallest channel that can be bought or sold on the auction platform.
With that said, let's place some orders to try to earn some yield from this 0.5 BTC that's been burning a hole in our SD card for the past year. We'll place a single order for 10 million satoshis, wanting to receive 0.3% (30 bps) over a 2016 block period (approximately 2 weeks):
1
$ pool orders submit ask 10000000 0288096be9917f8ebdfc6eb2701635fe658f4eae1e0274dcce41418b3fb5145732 --interest_rate_percent=0.3 --lease_duration_blocks=2016
2
3
-- Order Details --
4
Ask Amount: 0.1 BTC
5
Ask Duration: 2016
6
Total Premium (yield from taker): 0.00029998 BTC
7
Rate Fixed: 1488
8
Rate Per Block: 0.000001488 (0.0001488%)
9
Execution Fee: 0.00010001 BTC
10
Max batch fee rate: 100 sat/vByte
11
Max chain fee: 0.0016325 BTC
12
Confirm order (yes/no): yes
13
{
14
"accepted_order_nonce": "e3dbd57e8c22e895cbe705a4ec5ce65bdd766de4fc6d90c8bed404da8e7cbebc"
15
}
Copied!
By leaving off the --force flag, we request the final break down to confirm the details of our order before we put it through.
In this case, if this order is executed, then I'll gain 29k satoshis:
1
premium = (rate_fixed / billion) * amount * blocks
2
29,998 = (1,488/1,000,000,000)*10,000,000*2,016
Copied!
It's important to note that although internally we use a fixed rate per block to compute the final premium, on the command line, we accept the final acceptable premium as a percentage. Therefore, when submitting orders, one should place the value that they wish to receive or accept at the end of the lease period. Internally, we'll then compute the per block lease rate and submit the order using that.
The duration and fixed rate (the percentage) are two important values to pay attention to when placing orders. Given the same amount, and fixed rate, you earn more by leasing out the funds for a longer period of time. Conversely, a taker will pay more if they need the funds for a longer period of time.
Also notice the max batch fee rate break down, that regulates the highest chain fee you're willing to pay to get into a batch. When traders are included in a batch, they split the channel open fee with the party they're matched with, then pay for their account to be spent and re-created. The auctioneer then uses this value during match making to ensure that traders don't pay more chain fees than they intend to. If your desired chain fee is below the current proposed batch chain fee, then your order won't be eligible for execution until chain fees come down somewhat.
Users can use the --max_batch_fee_rate value to regulate chain fees.
Take note of the order_nonce, it's used through the auction to identify orders, and also for authentication purposes.
We can then check out the order we just placed with the following command:
1
$ pool orders list
2
3
{
4
...
5
"details": {
6
"trader_key": "024010a572c9f89b78b9d024f2be6cd4d42f4b9a80bfee4a5855e85da128c78473",
7
"rate_fixed": 1488,
8
"amt": "10000000",
9
"max_batch_fee_rate_sat_per_kw": "25000",
10
"order_nonce": "e3dbd57e8c22e895cbe705a4ec5ce65bdd766de4fc6d90c8bed404da8e7cbebc",
11
"state": "ORDER_SUBMITTED",
12
"units": 100,
13
"units_unfulfilled": 100,
14
"reserved_value_sat": "10143270",
15
"creation_timestamp_ns": "1602679458771936428",
16
"events": [
17
],
18
"min_units_match": 10
19
},
20
"lease_duration_blocks": 2016,
21
"version": 1
22
...
23
}
Copied!
The order hasn't been cleared yet (state ORDER_SUBMITTED), and it shows up as 100 units, or 10 million satoshis.
If we instead wanted to buy inbound bandwidth, we could submit a bid instead. A trader can have multiple unfilled bids and asks. Partial matching is possible as well, so someone could only purchase 10 of the 100 units we have for sale. Over time the orders will gain additional constraints such as fill-or-kill, or min partial match size.

Detailed field breakdown

Let's now take a look at all the order specific command line flags that are available.

Ask orders

Command for submitting an ask order:
1
$ pool orders submit ask
Copied!
Help output:
1
$ pool orders submit ask --help
2
3
NAME:
4
pool orders submit ask - offer channel liquidity
5
6
USAGE:
7
pool orders submit ask [command options] amt acct_key [--rate_fixed=R] [--max_batch_fee_rate=F] [--lease_duration_blocks=M]
8
9
DESCRIPTION:
10
11
Create an offer to provide inbound liquidity to an auction participant
12
by opening a channel to them for a certain time.
13
14
OPTIONS:
15
--interest_rate_percent value the total percent one is willing to pay or accept as yield for the specified interval (default: 0)
16
--amt value the amount to offer for channel creation in satoshis (default: 0)
17
--acct_key value the account key to use to offer liquidity from
18
--lease_duration_blocks value the number of blocks that the liquidity should be offered for (default: 2016)
19
--min_chan_amt value the minimum amount of satoshis that a resulting channel from this order must have (default: 0)
20
--force skip order placement confirmation
21
--max_batch_fee_rate value the maximum fee rate (sat/vByte) to use to for the batch transaction (default: 100)
Copied!
NOTE: The default values shown in the command line help are different from the actual default values that are used. A value of 0 on the command line indicates: No actual value set, use the internal default value. See the table below for more information.
Flag
Required
Default Value
Description
interest_rate_percent
Yes
n/a
The interest rate that should be earned over the total lease duration.
amt
Yes
n/a
The amount of liquidity to offer in satoshis. Must be a multiple of the base unit (100k sat).
acct_key
Yes
n/a
The account's trader key to use to pay for the offered liquidity, the order submission fee and chain fees.
lease_duration_blocks
No
2016
The minimum number of blocks the offered channels need to stay open for in order to satisfy the contract. Distinct markets are available for the different durations. See lease duration section for more information.
min_chan_amt
No
10% of amt
The minimum size/capacity of any offered channel. Higher values reduce the match potential but decrease the potential total in chain fees that must be paid. Must be a multiple of the base unit (100k sat). See chain fees section for more information.
max_batch_fee_rate
No
100 sat/vByte
The maximum on-chain fee rate at which this order should be eligible to be included in a batch. If the auctioneer estimates a higher fee rate, orders below will be skipped. See chain fees section for more information.
force
No
false
When set to true, no order details will be shown and no confirmation is required.

Bid orders

Command for submitting a bid order:
1
$ pool orders submit bid
Copied!
Help output:
1
NAME:
2
pool orders submit bid - obtain channel liquidity
3
4
USAGE:
5
pool orders submit bid [command options] amt acct_key [--rate_fixed=R] [--max_batch_fee_rate=F] [--lease_duration_blocks=M]
6
7
DESCRIPTION:
8
9
Place an offer for acquiring inbound liquidity by lending
10
funding capacity from another participant in the order book.
11
12
OPTIONS:
13
--interest_rate_percent value the total percent one is willing to pay or accept as yield for the specified interval (default: 0)
14
--amt value the amount of inbound liquidity in satoshis to request (default: 0)
15
--acct_key value the account key to use to pay the order fees with
16
--lease_duration_blocks value the number of blocks that the liquidity should be provided for (default: 2016)
17
--min_node_tier value the min node tier this bid should be matched with, tier 1 nodes are considered 'good', if set to tier 0, then all nodes will be considered regardless of 'quality' (default: 0)
18
--min_chan_amt value the minimum amount of satoshis that a resulting channel from this order must have (default: 0)
19
--force skip order placement confirmation
20
--max_batch_fee_rate value the maximum fee rate (sat/vByte) to use to for the batch transaction (default: 100)
Copied!
NOTE: The default values shown in the command line help are different from the actual default values that are used. A value of 0 on the command line indicates: No actual value set, use the internal default value. See the table below for more information.
Flag
Required
Default Value
Description
interest_rate_percent
Yes
n/a
The maximum interest rate that should be paid for leasing a channel, calculated over the total lease duration.
amt
Yes
n/a
The amount of liquidity to lease in satoshis. Must be a multiple of the base unit (100k sat).
acct_key
Yes
n/a
The account's trader key to use to pay for the lease premium, order submission fee and chain fees.
lease_duration_blocks
No
2016
The minimum number of blocks the leased channels must stay open for in order to satisfy the contract. Distinct markets are available for the different durations. See lease duration section for more information.
min_chan_amt
No
10% of amt
The minimum size/capacity of any leased channel. Higher values reduce the match potential but decrease the potential total in chain fees that must be paid. Must be a multiple of the base unit (100k sat). See chain fees section for more information.
min_node_tier
No
1
The minimum quality of node this bid should be matched with. The default (if no command line flag is set) is "Tier 1" which means the bid is only matched with asks from nodes that are considered "good". When manually setting this to --min_node_tier=0 then asks from all nodes should be considered, regardless of their "quality".
max_batch_fee_rate
No
100 sat/vByte
The maximum on-chain fee rate at which this order should be eligible to be included in a batch. If the auctioneer estimates a higher fee rate, orders below will be skipped. See chain fees section for more information.
force
No
false
When set to true, no order details will be shown and no confirmation is required.

Lease duration

The lease duration dictates the duration of the contract that the maker (submitter of the ask order) and the taker (submitter of the bid order) enter when being matched by the auctioneer. That means that the maker must provide the offered liquidity at least for the selected number of blocks. The maker is not allowed to close the channel before the agreed upon lease duration has elapsed. The maker may close the channel after the duration is over but is not obligated to do so. If a channel is economically viable, further routing fees might be collected when keeping the channel open.
In contrast, the taker of the channel is always allowed to close the channel. They pay the premium for the whole duration upfront, and it is therefore to their own disadvantage to close the channel prematurely.
To allow the formation of distinct premium rates over different durations, the possible lease durations are fixed and defined by the auctioneer. The current list of possible lease durations can be queried by running the following command:
1
$ pool auction leasedurations
2
3
{
4
"lease_durations": {
5
"2016": true,
6
"4032": false,
7
}
8
}
Copied!
The integer value is the lease duration in blocks. The boolean value indicates whether matchmaking in the given duration market is currently enabled or not. When adding a new lease duration the auctioneer might not enable matchmaking right away to wait for the order book to be populated sufficiently first.

Order execution fees

To compensate the auctioneer server for the service it is providing, an order execution fee has to be paid for every successfully executed (partial) match.
That execution fee is split into a static part (the base fee in satoshis) that is always the same independent of the matched size, and the dynamic part (the fee rate in parts per million) that is calculated based on the number of matched units.
The fee is set by the server and can change depending on demand, chain fee climate or other operational costs. The current fee can be queried by running the following command:
1
$ pool auction fee
2
3
{
4
"execution_fee": {
5
"base_fee": "123",
6
"fee_rate": "1234"
7
}
8
}
Copied!
Based on these example values, a matched order of 7 units (700k satoshis) would be charged an execution fee of 986 satoshis:
1
execution_fee = base_fee + (fee_rate / million) * match_amount
2
986.8 = 123 + (1,234 / 1,000,000) * 700,000
Copied!

Chain fees

Each successfully executed order will result in at least one channel output being created in the batch transaction that is published to the Bitcoin network. Additionally, because an account must be spent for an order to be executed, an input per involved account is also added to the transaction, and, if there is a remaining balance, the change goes back to a newly created output for that account.
In an example worst-case-scenario, a bid order for buying one channel can result in one input and two outputs being created on-chain. Each trader is charged fully for the transaction weight they produce with their account inputs and outputs. The cost for the new channel output is split in half between the maker and the taker.
Assuming we have a bid order over 5 units (500k satoshis) and an account that is 10 times that size, we'd occupy 162 virtual bytes of chain space:
1
size_vBytes = acct_input_size + 0.5 * chan_output_size + acct_output_size
2
162 ~= ~98 + 0.5 * 43 + 43
Copied!
Assuming the auctioneer estimates a current network fee rate of 34 sat/vByte, that order would cost 162 * 34 = 5,508 satoshi in chain fees to execute.
The auctioneer always tries to be economical with its fee estimation, but fee estimation is hard, and the fee market remains unpredictable. To give traders some protection against excessive fees, the --max_batch_fee_rate can be set for any order submitted that communicates to the auctioneer that the order shouldn't be considered for matching if the current estimation is higher than that rate.

Max chain fee estimation

When submitting an order, the command line shows a summary of the expected fees, as shown in our initial example:
1
Execution Fee: 0.00010001 BTC
2
Max batch fee rate: 100 sat/vByte
3
Max chain fee: 0.0016325 BTC
Copied!
The value shown as Max chain fee can look pretty scary. But it is important to note that the value is considered to be the absolute worst-case fee.
The maximum chain fee is calculated based on how many potential partial matches an order could go through (assuming it would always only match the minimum match size or minimum channel size). And for each of those partial matches the chain fee calculation as shown in the previous section would be performed with the given Max batch fee rate. It is quite unlikely however that the maximum fee is ever required to be paid for an order to be executed.
To reduce the value of this worst-case estimation, there are two possible flags that can be used to influence it:
  • --min_chan_amt: The minimum match size or minimum channel size. Instructs
    the auctioneer to only match the order with a counterpart that can at least
    fill the given amount in one match. By default, this values is set to 10% of
    the full order amount. Increasing the value makes it less likely to find a
    match candidate but reduces the number of times chain fees have to be paid.
    Increasing the value to 100% of the order amount is equivalent to a
    "kill-or-fill" order that is either executed in one part or not at all.
  • --max_batch_fee_rate: The maximum network fee rate the order should be
    considered for. Orders with a value higher than what the auctioneer estimates
    at the time of matchmaking will be excluded for that batch. Setting this
    value too low might result in orders not being executed at all or only when
    the mempools are almost empty.

Cancelling orders

To cancel an order. First get the order_nonce of the to be canceled order by using the list command and then cancel it:
1
$ pool orders cancel order_nonce
Copied!

Extensibility

At the moment there are only two restrictions that users can set on who their orders will be matched against. There is the global --newnodesonly flag which will cause the trader daemon to reject any matches with nodes that its connected lnd node already has channels with.
Takers can additionally influence the "quality" of the nodes they want their bid orders to be matched against by setting the --min_node_tier when creating the order.
In the future, more matching restrictions will likely be implemented, for example:
  • Specifying a concrete list of lnd node public keys that an order should
    be matched with.
  • Instant order: Either be matched successfully in the next batch or be
    canceled.
  • Buying channels for someone else (a.k.a. "Sidecar Channels"): When creating
    a bid order, a third party's lnd node pubkey can be specified that will
    receive the leased channel instead of the node of the bidder.
To allow these future upgrades to work seamlessly, a version field was added to the order submission protocol from the beginning. With this version field, the trader and auctioneer always know what fields an order is supposed to have set and therefore what fields are covered by the trader's order signature.
Last modified 4mo ago