@@ -9,7 +9,10 @@ import (
9
9
"strings"
10
10
11
11
"github.com/btcsuite/btcd/chaincfg/chainhash"
12
+ "github.com/lightninglabs/loop/labels"
12
13
"github.com/lightninglabs/loop/looprpc"
14
+ "github.com/lightninglabs/loop/swapserverrpc"
15
+ "github.com/lightningnetwork/lnd/routing/route"
13
16
"github.com/urfave/cli"
14
17
)
15
18
@@ -24,6 +27,50 @@ var staticAddressCommands = cli.Command{
24
27
withdrawalCommand ,
25
28
summaryCommand ,
26
29
},
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 ,
27
74
}
28
75
29
76
var newStaticAddressCommand = cli.Command {
@@ -194,10 +241,14 @@ var summaryCommand = cli.Command{
194
241
cli.StringFlag {
195
242
Name : "filter" ,
196
243
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.\n The state can be one " +
246
+ "of the following: \n " +
247
+ "deposited\n withdrawing\n withdrawn\n " +
248
+ "loopingin\n loopedin\n " +
249
+ "publish_expired_deposit\n " +
250
+ "sweep_htlc_timeout\n htlc_timeout_swept\n " +
251
+ "wait_for_expiry_sweep\n expired\n failed\n ." ,
201
252
},
202
253
},
203
254
Action : summary ,
@@ -229,9 +280,21 @@ func summary(ctx *cli.Context) error {
229
280
case "withdrawn" :
230
281
filterState = looprpc .DepositState_WITHDRAWN
231
282
283
+ case "loopingin" :
284
+ filterState = looprpc .DepositState_LOOPING_IN
285
+
286
+ case "loopedin" :
287
+ filterState = looprpc .DepositState_LOOPED_IN
288
+
232
289
case "publish_expired_deposit" :
233
290
filterState = looprpc .DepositState_PUBLISH_EXPIRED
234
291
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
+
235
298
case "wait_for_expiry_sweep" :
236
299
filterState = looprpc .DepositState_WAIT_FOR_EXPIRY_SWEEP
237
300
@@ -297,3 +360,116 @@ func NewProtoOutPoint(op string) (*looprpc.OutPoint, error) {
297
360
OutputIndex : uint32 (outputIndex ),
298
361
}, nil
299
362
}
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