Skip to content

Commit 82401ff

Browse files
committed
cmd: prettify loop quote in/out responses
1 parent c4d46a2 commit 82401ff

File tree

5 files changed

+126
-74
lines changed

5 files changed

+126
-74
lines changed

cmd/loop/loopin.go

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"fmt"
66

7-
"github.com/btcsuite/btcutil"
87
"github.com/lightninglabs/loop"
98
"github.com/lightninglabs/loop/labels"
109
"github.com/lightninglabs/loop/looprpc"
@@ -61,6 +60,7 @@ var (
6160
confTargetFlag,
6261
lastHopFlag,
6362
labelFlag,
63+
verboseFlag,
6464
},
6565
Action: loopIn,
6666
}
@@ -109,14 +109,12 @@ func loopIn(ctx *cli.Context) error {
109109
return err
110110
}
111111

112-
quote, err := client.GetLoopInQuote(
113-
context.Background(),
114-
&looprpc.QuoteRequest{
115-
Amt: int64(amt),
116-
ConfTarget: htlcConfTarget,
117-
ExternalHtlc: external,
118-
},
119-
)
112+
quoteReq := &looprpc.QuoteRequest{
113+
Amt: int64(amt),
114+
ConfTarget: htlcConfTarget,
115+
ExternalHtlc: external,
116+
}
117+
quote, err := client.GetLoopInQuote(context.Background(), quoteReq)
120118
if err != nil {
121119
return err
122120
}
@@ -136,9 +134,7 @@ func loopIn(ctx *cli.Context) error {
136134
}
137135

138136
limits := getInLimits(quote)
139-
err = displayInLimits(
140-
amt, btcutil.Amount(quote.HtlcPublishFeeSat), limits, external,
141-
)
137+
err = displayInDetails(quoteReq, quote, ctx.Bool("verbose"))
142138
if err != nil {
143139
return err
144140
}

cmd/loop/loopout.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ var loopOutCommand = cli.Command{
7474
"result in a lower swap fee.",
7575
},
7676
labelFlag,
77+
verboseFlag,
7778
},
7879
Action: loopOut,
7980
}
@@ -175,8 +176,8 @@ func loopOut(ctx *cli.Context) error {
175176
ctx.Int64("max_swap_routing_fee"),
176177
)
177178
}
178-
err = displayOutLimits(
179-
amt, btcutil.Amount(quote.HtlcSweepFeeSat), limits, warning,
179+
err = displayOutDetails(
180+
limits, warning, quoteReq, quote, ctx.Bool("verbose"),
180181
)
181182
if err != nil {
182183
return err

cmd/loop/main.go

Lines changed: 44 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,27 @@ var (
7474
Usage: "path to macaroon file",
7575
Value: loopd.DefaultMacaroonPath,
7676
}
77+
verboseFlag = cli.BoolFlag{
78+
Name: "verbose, v",
79+
Usage: "show expanded details",
80+
}
81+
)
82+
83+
const (
84+
85+
// satAmtFmt formats a satoshi value into a one line string, intended to
86+
// prettify the terminal output. For Instance,
87+
// fmt.Printf(f, "Estimated on-chain fee:", fee)
88+
// prints out as,
89+
// Estimated on-chain fee: 7262 sat
90+
satAmtFmt = "%-36s %12d sat\n"
91+
92+
// blkFmt formats the number of blocks into a one line string, intended
93+
// to prettify the terminal output. For Instance,
94+
// fmt.Printf(f, "Conf target", target)
95+
// prints out as,
96+
// Conf target: 9 block
97+
blkFmt = "%-36s %12d block\n"
7798
)
7899

79100
func printJSON(resp interface{}) {
@@ -246,89 +267,56 @@ func getOutLimits(amt btcutil.Amount,
246267
}
247268
}
248269

249-
func displayInLimits(amt, minerFees btcutil.Amount, l *inLimits,
250-
externalHtlc bool) error {
270+
func displayInDetails(req *looprpc.QuoteRequest,
271+
resp *looprpc.InQuoteResponse, verbose bool) error {
251272

252-
totalSuccessMax := l.maxMinerFee + l.maxSwapFee
253-
254-
if externalHtlc {
273+
if req.ExternalHtlc {
255274
fmt.Printf("On-chain fee for external loop in is not " +
256275
"included.\nSufficient fees will need to be paid " +
257276
"when constructing the transaction in the external " +
258277
"wallet.\n\n")
259278
}
260279

261-
fmt.Printf("Max swap fees for %d sat Loop %v: %d sat\n", amt, swap.TypeIn,
262-
totalSuccessMax)
280+
printQuoteInResp(req, resp, verbose)
263281

264-
fmt.Printf("CONTINUE SWAP? (y/n), expand fee detail (x): ")
282+
fmt.Printf("\nCONTINUE SWAP? (y/n): ")
265283

266284
var answer string
267285
fmt.Scanln(&answer)
268-
269-
switch answer {
270-
case "y":
286+
if answer == "y" {
271287
return nil
272-
case "x":
273-
fmt.Println()
274-
f := "%-36s %d sat\n"
275-
276-
if !externalHtlc {
277-
fmt.Printf(f, "Estimated on-chain HTLC fee:",
278-
minerFees)
279-
}
280-
281-
fmt.Printf(f, "Max swap fee:", l.maxSwapFee)
282-
283-
fmt.Printf("CONTINUE SWAP? (y/n): ")
284-
fmt.Scanln(&answer)
285-
if answer == "y" {
286-
return nil
287-
}
288288
}
289289

290290
return errors.New("swap canceled")
291291
}
292292

293-
func displayOutLimits(amt, minerFees btcutil.Amount, l *outLimits,
294-
warning string) error {
293+
func displayOutDetails(l *outLimits, warning string, req *looprpc.QuoteRequest,
294+
resp *looprpc.OutQuoteResponse, verbose bool) error {
295295

296-
totalSuccessMax := l.maxMinerFee + l.maxSwapFee + l.maxSwapRoutingFee +
297-
l.maxPrepayRoutingFee
296+
printQuoteOutResp(req, resp, verbose)
298297

299-
fmt.Printf("Max swap fees for %d sat Loop %v: %d sat\n", amt, swap.TypeOut,
300-
totalSuccessMax)
298+
// Display fee limits.
299+
if verbose {
300+
fmt.Println()
301+
fmt.Printf(satAmtFmt, "Max on-chain fee:", l.maxMinerFee)
302+
fmt.Printf(satAmtFmt,
303+
"Max off-chain swap routing fee:", l.maxSwapRoutingFee,
304+
)
305+
fmt.Printf(satAmtFmt, "Max off-chain prepay routing fee:",
306+
l.maxPrepayRoutingFee)
307+
}
301308

309+
// show warning
302310
if warning != "" {
303-
fmt.Println(warning)
311+
fmt.Printf("\n%s\n\n", warning)
304312
}
305313

306-
fmt.Printf("CONTINUE SWAP? (y/n), expand fee detail (x): ")
314+
fmt.Printf("CONTINUE SWAP? (y/n): ")
307315

308316
var answer string
309317
fmt.Scanln(&answer)
310-
311-
switch answer {
312-
case "y":
318+
if answer == "y" {
313319
return nil
314-
case "x":
315-
fmt.Println()
316-
f := "%-36s %d sat\n"
317-
318-
fmt.Printf(f, "Estimated on-chain sweep fee:", minerFees)
319-
fmt.Printf(f, "Max on-chain sweep fee:", l.maxMinerFee)
320-
fmt.Printf(f, "Max off-chain swap routing fee:",
321-
l.maxSwapRoutingFee)
322-
fmt.Printf(f, "Max no show penalty (prepay):", l.maxPrepayAmt)
323-
fmt.Printf(f, "Max off-chain prepay routing fee:",
324-
l.maxPrepayRoutingFee)
325-
fmt.Printf(f, "Max swap fee:", l.maxSwapFee)
326-
327-
fmt.Printf("CONTINUE SWAP? (y/n): ")
328-
fmt.Scanln(&answer)
329-
if answer == "y" {
330-
return nil
331-
}
332320
}
333321

334322
return errors.New("swap canceled")

cmd/loop/quote.go

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ var quoteInCommand = cli.Command{
2222
Usage: "get a quote for the cost of a loop in swap",
2323
ArgsUsage: "amt",
2424
Description: "Allows to determine the cost of a swap up front",
25-
Flags: []cli.Flag{confTargetFlag},
25+
Flags: []cli.Flag{confTargetFlag, verboseFlag},
2626
Action: quoteIn,
2727
}
2828

@@ -66,7 +66,7 @@ func quoteIn(ctx *cli.Context) error {
6666
"amount.\n")
6767
}
6868

69-
printRespJSON(quoteResp)
69+
printQuoteInResp(quoteReq, quoteResp, ctx.Bool("verbose"))
7070
return nil
7171
}
7272

@@ -93,6 +93,7 @@ var quoteOutCommand = cli.Command{
9393
"setting this flag might result in a lower " +
9494
"swap fee.",
9595
},
96+
verboseFlag,
9697
},
9798
Action: quoteOut,
9899
}
@@ -132,6 +133,68 @@ func quoteOut(ctx *cli.Context) error {
132133
return err
133134
}
134135

135-
printRespJSON(quoteResp)
136+
printQuoteOutResp(quoteReq, quoteResp, ctx.Bool("verbose"))
136137
return nil
137138
}
139+
140+
func printQuoteInResp(req *looprpc.QuoteRequest,
141+
resp *looprpc.InQuoteResponse, verbose bool) {
142+
143+
totalFee := resp.HtlcPublishFeeSat + resp.SwapFeeSat
144+
145+
fmt.Printf(satAmtFmt, "Send on-chain:", req.Amt)
146+
fmt.Printf(satAmtFmt, "Receive off-chain:", req.Amt-totalFee)
147+
148+
switch {
149+
case req.ExternalHtlc && !verbose:
150+
// If it's external then we don't know the miner fee hence the
151+
// total cost.
152+
fmt.Printf(satAmtFmt, "Loop service fee:", resp.SwapFeeSat)
153+
154+
case req.ExternalHtlc && verbose:
155+
fmt.Printf(satAmtFmt, "Loop service fee:", resp.SwapFeeSat)
156+
fmt.Println()
157+
fmt.Printf(blkFmt, "CLTV expiry delta:", resp.CltvDelta)
158+
159+
case verbose:
160+
fmt.Println()
161+
fmt.Printf(
162+
satAmtFmt, "Estimated on-chain fee:",
163+
resp.HtlcPublishFeeSat,
164+
)
165+
fmt.Printf(satAmtFmt, "Loop service fee:", resp.SwapFeeSat)
166+
fmt.Printf(satAmtFmt, "Estimated total fee:", totalFee)
167+
fmt.Println()
168+
fmt.Printf(blkFmt, "Conf target:", resp.ConfTarget)
169+
fmt.Printf(blkFmt, "CLTV expiry delta:", resp.CltvDelta)
170+
default:
171+
fmt.Printf(satAmtFmt, "Estimated total fee:", totalFee)
172+
}
173+
}
174+
175+
func printQuoteOutResp(req *looprpc.QuoteRequest,
176+
resp *looprpc.OutQuoteResponse, verbose bool) {
177+
178+
totalFee := resp.HtlcSweepFeeSat + resp.SwapFeeSat
179+
180+
fmt.Printf(satAmtFmt, "Send off-chain:", req.Amt)
181+
fmt.Printf(satAmtFmt, "Receive on-chain:", req.Amt-totalFee)
182+
183+
if !verbose {
184+
fmt.Printf(satAmtFmt, "Estimated total fee:", totalFee)
185+
return
186+
}
187+
188+
fmt.Println()
189+
fmt.Printf(satAmtFmt, "Estimated on-chain fee:", resp.HtlcSweepFeeSat)
190+
fmt.Printf(satAmtFmt, "Loop service fee:", resp.SwapFeeSat)
191+
fmt.Printf(satAmtFmt, "Estimated total fee:", totalFee)
192+
fmt.Println()
193+
fmt.Printf(satAmtFmt, "No show penalty (prepay):", resp.PrepayAmtSat)
194+
fmt.Printf(blkFmt, "Conf target:", resp.ConfTarget)
195+
fmt.Printf(blkFmt, "CLTV expiry delta:", resp.CltvDelta)
196+
fmt.Printf("%-38s %s\n",
197+
"Publication deadline:",
198+
time.Unix(int64(req.SwapPublicationDeadline), 0),
199+
)
200+
}

release_notes.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ This file tracks release notes for the loop client.
1515
## Next release
1616

1717
#### New Features
18-
18+
* A new flag, `--verbose`, or `-v`, is added to `loop in`, `loop out` and
19+
`loop quote`. Responses from these commands are also updated to provide more
20+
verbose info, giving users a more intuitive view about money paid
21+
on/off-chain and fees incurred. Use `loop in -v`, `loop out -v`,
22+
`loop quote in -v` or `loop quote out -v` to view the details.
1923

2024
#### Breaking Changes
2125

0 commit comments

Comments
 (0)