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