@@ -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,46 @@ var staticAddressCommands = cli.Command{
2427 withdrawalCommand ,
2528 summaryCommand ,
2629 },
30+ Description : `
31+ TODO .
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.StringFlag {
40+ Name : "last_hop" ,
41+ Usage : "the pubkey of the last hop to use for this " +
42+ "swap" ,
43+ },
44+ cli.StringFlag {
45+ Name : "label" ,
46+ Usage : fmt .Sprintf ("an optional label for this swap," +
47+ "limited to %v characters. The label may not " +
48+ "start with our reserved prefix: %v." ,
49+ labels .MaxLength , labels .Reserved ),
50+ },
51+ cli.StringSliceFlag {
52+ Name : "route_hints" ,
53+ Usage : "route hints that can each be individually " +
54+ "used to assist in reaching the invoice's " +
55+ "destination" ,
56+ },
57+ cli.BoolFlag {
58+ Name : "private" ,
59+ Usage : "generates and passes routehints. Should be " +
60+ "used if the connected node is only " +
61+ "reachable via private channels" ,
62+ },
63+ cli.BoolFlag {
64+ Name : "force, f" ,
65+ Usage : "Assumes yes during confirmation. Using this " +
66+ "option will result in an immediate swap" ,
67+ },
68+ },
69+ Action : staticAddressLoopIn ,
2770}
2871
2972var newStaticAddressCommand = cli.Command {
@@ -196,7 +239,7 @@ var summaryCommand = cli.Command{
196239 Usage : "specify a filter to only display deposits in " +
197240 "the specified state. The state can be one " +
198241 "of [deposited|withdrawing|withdrawn|" +
199- "publish_expired_deposit|" +
242+ "loopingin|loopedin| publish_expired_deposit|" +
200243 "wait_for_expiry_sweep|expired|failed]." ,
201244 },
202245 },
@@ -229,6 +272,12 @@ func summary(ctx *cli.Context) error {
229272 case "withdrawn" :
230273 filterState = looprpc .DepositState_WITHDRAWN
231274
275+ case "loopingin" :
276+ filterState = looprpc .DepositState_LOOPING_IN
277+
278+ case "loopedin" :
279+ filterState = looprpc .DepositState_LOOPED_IN
280+
232281 case "publish_expired_deposit" :
233282 filterState = looprpc .DepositState_PUBLISH_EXPIRED
234283
@@ -297,3 +346,137 @@ func NewProtoOutPoint(op string) (*looprpc.OutPoint, error) {
297346 OutputIndex : uint32 (outputIndex ),
298347 }, nil
299348}
349+
350+ func staticAddressLoopIn (ctx * cli.Context ) error {
351+ if ctx .NArg () > 0 {
352+ return cli .ShowCommandHelp (ctx , "static" )
353+ }
354+
355+ client , cleanup , err := getClient (ctx )
356+ if err != nil {
357+ return err
358+ }
359+ defer cleanup ()
360+
361+ var (
362+ ctxb = context .Background ()
363+ isAllSelected = ctx .IsSet ("all" )
364+ isUtxoSelected = ctx .IsSet ("utxo" )
365+ label = ctx .String ("static-loop-in" )
366+ hints []* swapserverrpc.RouteHint
367+ lastHop []byte
368+ )
369+
370+ // Validate our label early so that we can fail before getting a quote.
371+ if err := labels .Validate (label ); err != nil {
372+ return err
373+ }
374+
375+ // Private and route hints are mutually exclusive as setting private
376+ // means we retrieve our own route hints from the connected node.
377+ hints , err = validateRouteHints (ctx )
378+ if err != nil {
379+ return err
380+ }
381+
382+ if ctx .IsSet (lastHopFlag .Name ) {
383+ lastHopVertex , err := route .NewVertexFromStr (
384+ ctx .String (lastHopFlag .Name ),
385+ )
386+ if err != nil {
387+ return err
388+ }
389+
390+ lastHop = lastHopVertex [:]
391+ }
392+
393+ // Get the amount we need to quote for.
394+ summaryResp , err := client .GetStaticAddressSummary (
395+ ctxb , & looprpc.StaticAddressSummaryRequest {
396+ StateFilter : looprpc .DepositState_DEPOSITED ,
397+ },
398+ )
399+ if err != nil {
400+ return err
401+ }
402+
403+ var quoteAmount int64
404+ var depositOutpoints []string
405+ switch {
406+ case isAllSelected == isUtxoSelected :
407+ return errors .New ("must select either all or some utxos" )
408+
409+ case isAllSelected :
410+ quoteAmount = summaryResp .ValueDeposited
411+ depositOutpoints = depositsToOutpoints (
412+ summaryResp .FilteredDeposits ,
413+ )
414+
415+ case isUtxoSelected :
416+ depositOutpoints = ctx .StringSlice ("utxo" )
417+ quoteAmount = sumOutpointValues (
418+ depositOutpoints , summaryResp .FilteredDeposits ,
419+ )
420+
421+ default :
422+ return fmt .Errorf ("unknown quote request" )
423+ }
424+
425+ quote , err := client .GetLoopInQuote (
426+ ctxb , & looprpc.QuoteRequest {
427+ Amt : quoteAmount ,
428+ LoopInRouteHints : hints ,
429+ LoopInLastHop : lastHop ,
430+ Private : ctx .Bool (privateFlag .Name ),
431+ DepositOutpoints : depositOutpoints ,
432+ },
433+ )
434+ if err != nil {
435+ return err
436+ }
437+
438+ limits := getInLimits (quote )
439+
440+ req := & looprpc.StaticAddressLoopInRequest {
441+ Outpoints : depositOutpoints ,
442+ MaxMinerFee : int64 (limits .maxMinerFee ),
443+ MaxSwapFee : int64 (limits .maxSwapFee ),
444+ LastHop : lastHop ,
445+ Label : label ,
446+ Initiator : defaultInitiator ,
447+ RouteHints : hints ,
448+ Private : ctx .Bool ("private" ),
449+ }
450+
451+ resp , err := client .StaticAddressLoopIn (ctxb , req )
452+ if err != nil {
453+ return err
454+ }
455+
456+ fmt .Printf ("Static loop-in response from the server: %v\n " , resp )
457+
458+ return nil
459+ }
460+
461+ func sumOutpointValues (outpoints []string , deposits []* looprpc.Deposit ) int64 {
462+ var total int64
463+ for _ , outpoint := range outpoints {
464+ for _ , deposit := range deposits {
465+ if deposit .Outpoint == outpoint {
466+ total += deposit .Value
467+ break
468+ }
469+ }
470+ }
471+
472+ return total
473+ }
474+
475+ func depositsToOutpoints (deposits []* looprpc.Deposit ) []string {
476+ outpoints := make ([]string , 0 , len (deposits ))
477+ for _ , deposit := range deposits {
478+ outpoints = append (outpoints , deposit .Outpoint )
479+ }
480+
481+ return outpoints
482+ }
0 commit comments