Skip to content

Commit 64dd989

Browse files
committed
loop: static address withdrawals support
1 parent a665af4 commit 64dd989

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

cmd/loop/staticaddr.go

+114
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,111 @@ 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 withdrawn.",
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+
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+
default:
168+
return fmt.Errorf("unknown withdrawal request")
169+
}
170+
171+
resp, err := client.WithdrawDeposits(ctxb, &looprpc.WithdrawDepositsRequest{
172+
Outpoints: outpoints,
173+
All: isAllSelected,
174+
})
175+
if err != nil {
176+
return err
177+
}
178+
179+
printRespJSON(resp)
180+
181+
return nil
182+
}
183+
184+
func utxosToOutpoints(utxos []string) ([]*looprpc.OutPoint, error) {
185+
outpoints := make([]*looprpc.OutPoint, 0, len(utxos))
186+
if len(utxos) == 0 {
187+
return nil, fmt.Errorf("no utxos specified")
188+
}
189+
for _, utxo := range utxos {
190+
outpoint, err := NewProtoOutPoint(utxo)
191+
if err != nil {
192+
return nil, err
193+
}
194+
outpoints = append(outpoints, outpoint)
195+
}
196+
197+
return outpoints, nil
198+
}
199+
200+
// NewProtoOutPoint parses an OutPoint into its corresponding lnrpc.OutPoint
201+
// type.
202+
func NewProtoOutPoint(op string) (*looprpc.OutPoint, error) {
203+
parts := strings.Split(op, ":")
204+
if len(parts) != 2 {
205+
return nil, errors.New("outpoint should be of the form " +
206+
"txid:index")
207+
}
208+
txid := parts[0]
209+
if hex.DecodedLen(len(txid)) != chainhash.HashSize {
210+
return nil, fmt.Errorf("invalid hex-encoded txid %v", txid)
211+
}
212+
outputIndex, err := strconv.Atoi(parts[1])
213+
if err != nil {
214+
return nil, fmt.Errorf("invalid output index: %v", err)
215+
}
216+
217+
return &looprpc.OutPoint{
218+
TxidStr: txid,
219+
OutputIndex: uint32(outputIndex),
220+
}, nil
221+
}

0 commit comments

Comments
 (0)