Skip to content

Commit a9d9e6f

Browse files
committed
cmd: static address loop-in
1 parent 7768af2 commit a9d9e6f

File tree

1 file changed

+180
-4
lines changed

1 file changed

+180
-4
lines changed

cmd/loop/staticaddr.go

Lines changed: 180 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import (
99
"strings"
1010

1111
"github.com/btcsuite/btcd/chaincfg/chainhash"
12+
"github.com/lightninglabs/loop/labels"
1213
"github.com/lightninglabs/loop/looprpc"
14+
"github.com/lightninglabs/loop/swapserverrpc"
15+
"github.com/lightningnetwork/lnd/routing/route"
1316
"github.com/urfave/cli"
1417
)
1518

@@ -24,6 +27,50 @@ var staticAddressCommands = cli.Command{
2427
withdrawalCommand,
2528
summaryCommand,
2629
},
30+
Description: `
31+
Requests a loop-in swap based on static address deposits.
32+
`,
33+
Flags: []cli.Flag{
34+
cli.StringSliceFlag{
35+
Name: "utxo",
36+
Usage: "specify the utxos of deposits as " +
37+
"outpoints(tx:idx) that should be looped in.",
38+
},
39+
cli.BoolFlag{
40+
Name: "all",
41+
Usage: "loop in all static address deposits.",
42+
},
43+
cli.StringFlag{
44+
Name: "last_hop",
45+
Usage: "the pubkey of the last hop to use for this " +
46+
"swap",
47+
},
48+
cli.StringFlag{
49+
Name: "label",
50+
Usage: fmt.Sprintf("an optional label for this swap,"+
51+
"limited to %v characters. The label may not "+
52+
"start with our reserved prefix: %v.",
53+
labels.MaxLength, labels.Reserved),
54+
},
55+
cli.StringSliceFlag{
56+
Name: "route_hints",
57+
Usage: "route hints that can each be individually " +
58+
"used to assist in reaching the invoice's " +
59+
"destination",
60+
},
61+
cli.BoolFlag{
62+
Name: "private",
63+
Usage: "generates and passes route hints. Should be " +
64+
"used if the connected node is only " +
65+
"reachable via private channels",
66+
},
67+
cli.BoolFlag{
68+
Name: "force, f",
69+
Usage: "Assumes yes during confirmation. Using this " +
70+
"option will result in an immediate swap",
71+
},
72+
},
73+
Action: staticAddressLoopIn,
2774
}
2875

2976
var newStaticAddressCommand = cli.Command{
@@ -194,10 +241,14 @@ var summaryCommand = cli.Command{
194241
cli.StringFlag{
195242
Name: "filter",
196243
Usage: "specify a filter to only display deposits in " +
197-
"the specified state. The state can be one " +
198-
"of [deposited|withdrawing|withdrawn|" +
199-
"publish_expired_deposit|" +
200-
"wait_for_expiry_sweep|expired|failed].",
244+
"the specified state. Leaving out the filter " +
245+
"returns all deposits.\nThe state can be one " +
246+
"of the following: \n" +
247+
"deposited\nwithdrawing\nwithdrawn\n" +
248+
"loopingin\nloopedin\n" +
249+
"publish_expired_deposit\n" +
250+
"sweep_htlc_timeout\nhtlc_timeout_swept\n" +
251+
"wait_for_expiry_sweep\nexpired\nfailed\n.",
201252
},
202253
},
203254
Action: summary,
@@ -229,9 +280,21 @@ func summary(ctx *cli.Context) error {
229280
case "withdrawn":
230281
filterState = looprpc.DepositState_WITHDRAWN
231282

283+
case "loopingin":
284+
filterState = looprpc.DepositState_LOOPING_IN
285+
286+
case "loopedin":
287+
filterState = looprpc.DepositState_LOOPED_IN
288+
232289
case "publish_expired_deposit":
233290
filterState = looprpc.DepositState_PUBLISH_EXPIRED
234291

292+
case "sweep_htlc_timeout":
293+
filterState = looprpc.DepositState_SWEEP_HTLC_TIMEOUT
294+
295+
case "htlc_timeout_swept":
296+
filterState = looprpc.DepositState_HTLC_TIMEOUT_SWEPT
297+
235298
case "wait_for_expiry_sweep":
236299
filterState = looprpc.DepositState_WAIT_FOR_EXPIRY_SWEEP
237300

@@ -297,3 +360,116 @@ func NewProtoOutPoint(op string) (*looprpc.OutPoint, error) {
297360
OutputIndex: uint32(outputIndex),
298361
}, nil
299362
}
363+
364+
func staticAddressLoopIn(ctx *cli.Context) error {
365+
if ctx.NArg() > 0 {
366+
return cli.ShowCommandHelp(ctx, "static")
367+
}
368+
369+
client, cleanup, err := getClient(ctx)
370+
if err != nil {
371+
return err
372+
}
373+
defer cleanup()
374+
375+
var (
376+
ctxb = context.Background()
377+
isAllSelected = ctx.IsSet("all")
378+
isUtxoSelected = ctx.IsSet("utxo")
379+
label = ctx.String("static-loop-in")
380+
hints []*swapserverrpc.RouteHint
381+
lastHop []byte
382+
)
383+
384+
// Validate our label early so that we can fail before getting a quote.
385+
if err := labels.Validate(label); err != nil {
386+
return err
387+
}
388+
389+
// Private and route hints are mutually exclusive as setting private
390+
// means we retrieve our own route hints from the connected node.
391+
hints, err = validateRouteHints(ctx)
392+
if err != nil {
393+
return err
394+
}
395+
396+
if ctx.IsSet(lastHopFlag.Name) {
397+
lastHopVertex, err := route.NewVertexFromStr(
398+
ctx.String(lastHopFlag.Name),
399+
)
400+
if err != nil {
401+
return err
402+
}
403+
404+
lastHop = lastHopVertex[:]
405+
}
406+
407+
// Get the amount we need to quote for.
408+
summaryResp, err := client.GetStaticAddressSummary(
409+
ctxb, &looprpc.StaticAddressSummaryRequest{
410+
StateFilter: looprpc.DepositState_DEPOSITED,
411+
},
412+
)
413+
if err != nil {
414+
return err
415+
}
416+
417+
var depositOutpoints []string
418+
switch {
419+
case isAllSelected == isUtxoSelected:
420+
return errors.New("must select either all or some utxos")
421+
422+
case isAllSelected:
423+
depositOutpoints = depositsToOutpoints(
424+
summaryResp.FilteredDeposits,
425+
)
426+
427+
case isUtxoSelected:
428+
depositOutpoints = ctx.StringSlice("utxo")
429+
430+
default:
431+
return fmt.Errorf("unknown quote request")
432+
}
433+
434+
quote, err := client.GetLoopInQuote(
435+
ctxb, &looprpc.QuoteRequest{
436+
LoopInRouteHints: hints,
437+
LoopInLastHop: lastHop,
438+
Private: ctx.Bool(privateFlag.Name),
439+
DepositOutpoints: depositOutpoints,
440+
},
441+
)
442+
if err != nil {
443+
return err
444+
}
445+
446+
limits := getInLimits(quote)
447+
448+
req := &looprpc.StaticAddressLoopInRequest{
449+
Outpoints: depositOutpoints,
450+
MaxSwapFee: int64(limits.maxSwapFee),
451+
LastHop: lastHop,
452+
Label: ctx.String(labelFlag.Name),
453+
Initiator: defaultInitiator,
454+
RouteHints: hints,
455+
Private: ctx.Bool("private"),
456+
}
457+
458+
resp, err := client.StaticAddressLoopIn(ctxb, req)
459+
if err != nil {
460+
return err
461+
}
462+
463+
fmt.Printf("Static loop-in response from the server: %v\n", resp)
464+
465+
return nil
466+
}
467+
468+
func depositsToOutpoints(deposits []*looprpc.Deposit) []string {
469+
outpoints := make([]string, 0, len(deposits))
470+
for _, deposit := range deposits {
471+
outpoints = append(outpoints, deposit.Outpoint)
472+
}
473+
474+
return outpoints
475+
}

0 commit comments

Comments
 (0)