@@ -2,8 +2,13 @@ package main
2
2
3
3
import (
4
4
"context"
5
+ "encoding/hex"
6
+ "errors"
5
7
"fmt"
8
+ "strconv"
9
+ "strings"
6
10
11
+ "github.com/btcsuite/btcd/chaincfg/chainhash"
7
12
"github.com/lightninglabs/loop/looprpc"
8
13
"github.com/urfave/cli"
9
14
)
@@ -16,6 +21,7 @@ var staticAddressCommands = cli.Command{
16
21
Subcommands : []cli.Command {
17
22
newStaticAddressCommand ,
18
23
listUnspentCommand ,
24
+ withdrawalCommand ,
19
25
},
20
26
}
21
27
@@ -104,3 +110,113 @@ func listUnspent(ctx *cli.Context) error {
104
110
105
111
return nil
106
112
}
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