@@ -2,8 +2,13 @@ package main
22
33import (
44 "context"
5+ "encoding/hex"
6+ "errors"
57 "fmt"
8+ "strconv"
9+ "strings"
610
11+ "github.com/btcsuite/btcd/chaincfg/chainhash"
712 "github.com/lightninglabs/loop/looprpc"
813 "github.com/urfave/cli"
914)
@@ -16,6 +21,7 @@ var staticAddressCommands = cli.Command{
1621 Subcommands : []cli.Command {
1722 newStaticAddressCommand ,
1823 listUnspentCommand ,
24+ withdrawalCommand ,
1925 },
2026}
2127
@@ -104,3 +110,113 @@ func listUnspent(ctx *cli.Context) error {
104110
105111 return nil
106112}
113+
114+ var withdrawalCommand = cli.Command {
115+ Name : "withdraw" ,
116+ ShortName : "w" ,
117+ Usage : "Withdraw from static address deposits." ,
118+ Description : `
119+ Withdraws from all or selected static address deposits by sweeping them
120+ back to our lnd wallet.
121+ ` ,
122+ Flags : []cli.Flag {
123+ cli.StringSliceFlag {
124+ Name : "utxo" ,
125+ Usage : "specify utxos as outpoints(tx:idx) which will" +
126+ "be closed." ,
127+ },
128+ cli.BoolFlag {
129+ Name : "all" ,
130+ Usage : "withdraws all static address deposits." ,
131+ },
132+ },
133+ Action : withdraw ,
134+ }
135+
136+ func withdraw (ctx * cli.Context ) error {
137+ if ctx .NArg () > 0 {
138+ return cli .ShowCommandHelp (ctx , "withdraw" )
139+ }
140+
141+ client , cleanup , err := getClient (ctx )
142+ if err != nil {
143+ return err
144+ }
145+ defer cleanup ()
146+
147+ var (
148+ req = & looprpc.WithdrawDepositsRequest {}
149+ isAllSelected = ctx .IsSet ("all" )
150+ isUtxoSelected = ctx .IsSet ("utxo" )
151+ outpoints []* looprpc.OutPoint
152+ ctxb = context .Background ()
153+ )
154+
155+ switch {
156+ case isAllSelected == isUtxoSelected :
157+ return errors .New ("must select either all or some utxos" )
158+
159+ case isAllSelected :
160+ case isUtxoSelected :
161+ utxos := ctx .StringSlice ("utxo" )
162+ outpoints , err = utxosToOutpoints (utxos )
163+ if err != nil {
164+ return err
165+ }
166+
167+ req .Outpoints = outpoints
168+
169+ default :
170+ return fmt .Errorf ("unknown withdrawal request" )
171+ }
172+
173+ resp , err := client .WithdrawDeposits (ctxb , & looprpc.WithdrawDepositsRequest {
174+ Outpoints : outpoints ,
175+ All : isAllSelected ,
176+ })
177+ if err != nil {
178+ return err
179+ }
180+
181+ printRespJSON (resp )
182+
183+ return nil
184+ }
185+
186+ func utxosToOutpoints (utxos []string ) ([]* looprpc.OutPoint , error ) {
187+ var outpoints []* looprpc.OutPoint
188+ if len (utxos ) == 0 {
189+ return nil , fmt .Errorf ("no utxos specified" )
190+ }
191+ for _ , utxo := range utxos {
192+ outpoint , err := NewProtoOutPoint (utxo )
193+ if err != nil {
194+ return nil , err
195+ }
196+ outpoints = append (outpoints , outpoint )
197+ }
198+
199+ return outpoints , nil
200+ }
201+
202+ // NewProtoOutPoint parses an OutPoint into its corresponding lnrpc.OutPoint
203+ // type.
204+ func NewProtoOutPoint (op string ) (* looprpc.OutPoint , error ) {
205+ parts := strings .Split (op , ":" )
206+ if len (parts ) != 2 {
207+ return nil , errors .New ("outpoint should be of the form " +
208+ "txid:index" )
209+ }
210+ txid := parts [0 ]
211+ if hex .DecodedLen (len (txid )) != chainhash .HashSize {
212+ return nil , fmt .Errorf ("invalid hex-encoded txid %v" , txid )
213+ }
214+ outputIndex , err := strconv .Atoi (parts [1 ])
215+ if err != nil {
216+ return nil , fmt .Errorf ("invalid output index: %v" , err )
217+ }
218+ return & looprpc.OutPoint {
219+ TxidStr : txid ,
220+ OutputIndex : uint32 (outputIndex ),
221+ }, nil
222+ }
0 commit comments