Skip to content

Commit 1b4ca0c

Browse files
committed
loop: static address withdrawals support
1 parent 07f5d18 commit 1b4ca0c

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

cmd/loop/staticaddr.go

+116
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ package main
22

33
import (
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

@@ -105,3 +111,113 @@ func listUnspent(ctx *cli.Context) error {
105111

106112
return nil
107113
}
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

Comments
 (0)