lncli: move openChannel command to new file
This is a pure code move!
This commit is contained in:
parent
376a747bb2
commit
8b05d1b61f
277
cmd/lncli/cmd_open_channel.go
Normal file
277
cmd/lncli/cmd_open_channel.go
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(roasbeef): change default number of confirmations
|
||||||
|
var openChannelCommand = cli.Command{
|
||||||
|
Name: "openchannel",
|
||||||
|
Category: "Channels",
|
||||||
|
Usage: "Open a channel to a node or an existing peer.",
|
||||||
|
Description: `
|
||||||
|
Attempt to open a new channel to an existing peer with the key node-key
|
||||||
|
optionally blocking until the channel is 'open'.
|
||||||
|
|
||||||
|
One can also connect to a node before opening a new channel to it by
|
||||||
|
setting its host:port via the --connect argument. For this to work,
|
||||||
|
the node_key must be provided, rather than the peer_id. This is optional.
|
||||||
|
|
||||||
|
The channel will be initialized with local-amt satoshis local and push-amt
|
||||||
|
satoshis for the remote node. Note that specifying push-amt means you give that
|
||||||
|
amount to the remote node as part of the channel opening. Once the channel is open,
|
||||||
|
a channelPoint (txid:vout) of the funding output is returned.
|
||||||
|
|
||||||
|
If the remote peer supports the option upfront shutdown feature bit (query
|
||||||
|
listpeers to see their supported feature bits), an address to enforce
|
||||||
|
payout of funds on cooperative close can optionally be provided. Note that
|
||||||
|
if you set this value, you will not be able to cooperatively close out to
|
||||||
|
another address.
|
||||||
|
|
||||||
|
One can manually set the fee to be used for the funding transaction via either
|
||||||
|
the --conf_target or --sat_per_byte arguments. This is optional.`,
|
||||||
|
ArgsUsage: "node-key local-amt push-amt",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "node_key",
|
||||||
|
Usage: "the identity public key of the target node/peer " +
|
||||||
|
"serialized in compressed format",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "connect",
|
||||||
|
Usage: "(optional) the host:port of the target node",
|
||||||
|
},
|
||||||
|
cli.IntFlag{
|
||||||
|
Name: "local_amt",
|
||||||
|
Usage: "the number of satoshis the wallet should commit to the channel",
|
||||||
|
},
|
||||||
|
cli.IntFlag{
|
||||||
|
Name: "push_amt",
|
||||||
|
Usage: "the number of satoshis to give the remote side " +
|
||||||
|
"as part of the initial commitment state, " +
|
||||||
|
"this is equivalent to first opening a " +
|
||||||
|
"channel and sending the remote party funds, " +
|
||||||
|
"but done all in one step",
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "block",
|
||||||
|
Usage: "block and wait until the channel is fully open",
|
||||||
|
},
|
||||||
|
cli.Int64Flag{
|
||||||
|
Name: "conf_target",
|
||||||
|
Usage: "(optional) the number of blocks that the " +
|
||||||
|
"transaction *should* confirm in, will be " +
|
||||||
|
"used for fee estimation",
|
||||||
|
},
|
||||||
|
cli.Int64Flag{
|
||||||
|
Name: "sat_per_byte",
|
||||||
|
Usage: "(optional) a manual fee expressed in " +
|
||||||
|
"sat/byte that should be used when crafting " +
|
||||||
|
"the transaction",
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "private",
|
||||||
|
Usage: "make the channel private, such that it won't " +
|
||||||
|
"be announced to the greater network, and " +
|
||||||
|
"nodes other than the two channel endpoints " +
|
||||||
|
"must be explicitly told about it to be able " +
|
||||||
|
"to route through it",
|
||||||
|
},
|
||||||
|
cli.Int64Flag{
|
||||||
|
Name: "min_htlc_msat",
|
||||||
|
Usage: "(optional) the minimum value we will require " +
|
||||||
|
"for incoming HTLCs on the channel",
|
||||||
|
},
|
||||||
|
cli.Uint64Flag{
|
||||||
|
Name: "remote_csv_delay",
|
||||||
|
Usage: "(optional) the number of blocks we will require " +
|
||||||
|
"our channel counterparty to wait before accessing " +
|
||||||
|
"its funds in case of unilateral close. If this is " +
|
||||||
|
"not set, we will scale the value according to the " +
|
||||||
|
"channel size",
|
||||||
|
},
|
||||||
|
cli.Uint64Flag{
|
||||||
|
Name: "min_confs",
|
||||||
|
Usage: "(optional) the minimum number of confirmations " +
|
||||||
|
"each one of your outputs used for the funding " +
|
||||||
|
"transaction must satisfy",
|
||||||
|
Value: 1,
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "close_address",
|
||||||
|
Usage: "(optional) an address to enforce payout of our " +
|
||||||
|
"funds to on cooperative close. Note that if this " +
|
||||||
|
"value is set on channel open, you will *not* be " +
|
||||||
|
"able to cooperatively close to a different address.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: actionDecorator(openChannel),
|
||||||
|
}
|
||||||
|
|
||||||
|
func openChannel(ctx *cli.Context) error {
|
||||||
|
// TODO(roasbeef): add deadline to context
|
||||||
|
ctxb := context.Background()
|
||||||
|
client, cleanUp := getClient(ctx)
|
||||||
|
defer cleanUp()
|
||||||
|
|
||||||
|
args := ctx.Args()
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Show command help if no arguments provided
|
||||||
|
if ctx.NArg() == 0 && ctx.NumFlags() == 0 {
|
||||||
|
cli.ShowCommandHelp(ctx, "openchannel")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
minConfs := int32(ctx.Uint64("min_confs"))
|
||||||
|
req := &lnrpc.OpenChannelRequest{
|
||||||
|
TargetConf: int32(ctx.Int64("conf_target")),
|
||||||
|
SatPerByte: ctx.Int64("sat_per_byte"),
|
||||||
|
MinHtlcMsat: ctx.Int64("min_htlc_msat"),
|
||||||
|
RemoteCsvDelay: uint32(ctx.Uint64("remote_csv_delay")),
|
||||||
|
MinConfs: minConfs,
|
||||||
|
SpendUnconfirmed: minConfs == 0,
|
||||||
|
CloseAddress: ctx.String("close_address"),
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case ctx.IsSet("node_key"):
|
||||||
|
nodePubHex, err := hex.DecodeString(ctx.String("node_key"))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to decode node public key: %v", err)
|
||||||
|
}
|
||||||
|
req.NodePubkey = nodePubHex
|
||||||
|
|
||||||
|
case args.Present():
|
||||||
|
nodePubHex, err := hex.DecodeString(args.First())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to decode node public key: %v", err)
|
||||||
|
}
|
||||||
|
args = args.Tail()
|
||||||
|
req.NodePubkey = nodePubHex
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("node id argument missing")
|
||||||
|
}
|
||||||
|
|
||||||
|
// As soon as we can confirm that the node's node_key was set, rather
|
||||||
|
// than the peer_id, we can check if the host:port was also set to
|
||||||
|
// connect to it before opening the channel.
|
||||||
|
if req.NodePubkey != nil && ctx.IsSet("connect") {
|
||||||
|
addr := &lnrpc.LightningAddress{
|
||||||
|
Pubkey: hex.EncodeToString(req.NodePubkey),
|
||||||
|
Host: ctx.String("connect"),
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &lnrpc.ConnectPeerRequest{
|
||||||
|
Addr: addr,
|
||||||
|
Perm: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if connecting to the node was successful.
|
||||||
|
// We discard the peer id returned as it is not needed.
|
||||||
|
_, err := client.ConnectPeer(ctxb, req)
|
||||||
|
if err != nil &&
|
||||||
|
!strings.Contains(err.Error(), "already connected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case ctx.IsSet("local_amt"):
|
||||||
|
req.LocalFundingAmount = int64(ctx.Int("local_amt"))
|
||||||
|
case args.Present():
|
||||||
|
req.LocalFundingAmount, err = strconv.ParseInt(args.First(), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to decode local amt: %v", err)
|
||||||
|
}
|
||||||
|
args = args.Tail()
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("local amt argument missing")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.IsSet("push_amt") {
|
||||||
|
req.PushSat = int64(ctx.Int("push_amt"))
|
||||||
|
} else if args.Present() {
|
||||||
|
req.PushSat, err = strconv.ParseInt(args.First(), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to decode push amt: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Private = ctx.Bool("private")
|
||||||
|
|
||||||
|
stream, err := client.OpenChannel(ctxb, req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
resp, err := stream.Recv()
|
||||||
|
if err == io.EOF {
|
||||||
|
return nil
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch update := resp.Update.(type) {
|
||||||
|
case *lnrpc.OpenStatusUpdate_ChanPending:
|
||||||
|
txid, err := chainhash.NewHash(update.ChanPending.Txid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
printJSON(struct {
|
||||||
|
FundingTxid string `json:"funding_txid"`
|
||||||
|
}{
|
||||||
|
FundingTxid: txid.String(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if !ctx.Bool("block") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case *lnrpc.OpenStatusUpdate_ChanOpen:
|
||||||
|
channelPoint := update.ChanOpen.ChannelPoint
|
||||||
|
|
||||||
|
// A channel point's funding txid can be get/set as a
|
||||||
|
// byte slice or a string. In the case it is a string,
|
||||||
|
// decode it.
|
||||||
|
var txidHash []byte
|
||||||
|
switch channelPoint.GetFundingTxid().(type) {
|
||||||
|
case *lnrpc.ChannelPoint_FundingTxidBytes:
|
||||||
|
txidHash = channelPoint.GetFundingTxidBytes()
|
||||||
|
case *lnrpc.ChannelPoint_FundingTxidStr:
|
||||||
|
s := channelPoint.GetFundingTxidStr()
|
||||||
|
h, err := chainhash.NewHashFromStr(s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
txidHash = h[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
txid, err := chainhash.NewHash(txidHash)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
index := channelPoint.OutputIndex
|
||||||
|
printJSON(struct {
|
||||||
|
ChannelPoint string `json:"channel_point"`
|
||||||
|
}{
|
||||||
|
ChannelPoint: fmt.Sprintf("%v:%v", txid, index),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -577,269 +577,6 @@ func disconnectPeer(ctx *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(roasbeef): change default number of confirmations
|
|
||||||
var openChannelCommand = cli.Command{
|
|
||||||
Name: "openchannel",
|
|
||||||
Category: "Channels",
|
|
||||||
Usage: "Open a channel to a node or an existing peer.",
|
|
||||||
Description: `
|
|
||||||
Attempt to open a new channel to an existing peer with the key node-key
|
|
||||||
optionally blocking until the channel is 'open'.
|
|
||||||
|
|
||||||
One can also connect to a node before opening a new channel to it by
|
|
||||||
setting its host:port via the --connect argument. For this to work,
|
|
||||||
the node_key must be provided, rather than the peer_id. This is optional.
|
|
||||||
|
|
||||||
The channel will be initialized with local-amt satoshis local and push-amt
|
|
||||||
satoshis for the remote node. Note that specifying push-amt means you give that
|
|
||||||
amount to the remote node as part of the channel opening. Once the channel is open,
|
|
||||||
a channelPoint (txid:vout) of the funding output is returned.
|
|
||||||
|
|
||||||
If the remote peer supports the option upfront shutdown feature bit (query
|
|
||||||
listpeers to see their supported feature bits), an address to enforce
|
|
||||||
payout of funds on cooperative close can optionally be provided. Note that
|
|
||||||
if you set this value, you will not be able to cooperatively close out to
|
|
||||||
another address.
|
|
||||||
|
|
||||||
One can manually set the fee to be used for the funding transaction via either
|
|
||||||
the --conf_target or --sat_per_byte arguments. This is optional.`,
|
|
||||||
ArgsUsage: "node-key local-amt push-amt",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "node_key",
|
|
||||||
Usage: "the identity public key of the target node/peer " +
|
|
||||||
"serialized in compressed format",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "connect",
|
|
||||||
Usage: "(optional) the host:port of the target node",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "local_amt",
|
|
||||||
Usage: "the number of satoshis the wallet should commit to the channel",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "push_amt",
|
|
||||||
Usage: "the number of satoshis to give the remote side " +
|
|
||||||
"as part of the initial commitment state, " +
|
|
||||||
"this is equivalent to first opening a " +
|
|
||||||
"channel and sending the remote party funds, " +
|
|
||||||
"but done all in one step",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "block",
|
|
||||||
Usage: "block and wait until the channel is fully open",
|
|
||||||
},
|
|
||||||
cli.Int64Flag{
|
|
||||||
Name: "conf_target",
|
|
||||||
Usage: "(optional) the number of blocks that the " +
|
|
||||||
"transaction *should* confirm in, will be " +
|
|
||||||
"used for fee estimation",
|
|
||||||
},
|
|
||||||
cli.Int64Flag{
|
|
||||||
Name: "sat_per_byte",
|
|
||||||
Usage: "(optional) a manual fee expressed in " +
|
|
||||||
"sat/byte that should be used when crafting " +
|
|
||||||
"the transaction",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "private",
|
|
||||||
Usage: "make the channel private, such that it won't " +
|
|
||||||
"be announced to the greater network, and " +
|
|
||||||
"nodes other than the two channel endpoints " +
|
|
||||||
"must be explicitly told about it to be able " +
|
|
||||||
"to route through it",
|
|
||||||
},
|
|
||||||
cli.Int64Flag{
|
|
||||||
Name: "min_htlc_msat",
|
|
||||||
Usage: "(optional) the minimum value we will require " +
|
|
||||||
"for incoming HTLCs on the channel",
|
|
||||||
},
|
|
||||||
cli.Uint64Flag{
|
|
||||||
Name: "remote_csv_delay",
|
|
||||||
Usage: "(optional) the number of blocks we will require " +
|
|
||||||
"our channel counterparty to wait before accessing " +
|
|
||||||
"its funds in case of unilateral close. If this is " +
|
|
||||||
"not set, we will scale the value according to the " +
|
|
||||||
"channel size",
|
|
||||||
},
|
|
||||||
cli.Uint64Flag{
|
|
||||||
Name: "min_confs",
|
|
||||||
Usage: "(optional) the minimum number of confirmations " +
|
|
||||||
"each one of your outputs used for the funding " +
|
|
||||||
"transaction must satisfy",
|
|
||||||
Value: 1,
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "close_address",
|
|
||||||
Usage: "(optional) an address to enforce payout of our " +
|
|
||||||
"funds to on cooperative close. Note that if this " +
|
|
||||||
"value is set on channel open, you will *not* be " +
|
|
||||||
"able to cooperatively close to a different address.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: actionDecorator(openChannel),
|
|
||||||
}
|
|
||||||
|
|
||||||
func openChannel(ctx *cli.Context) error {
|
|
||||||
// TODO(roasbeef): add deadline to context
|
|
||||||
ctxb := context.Background()
|
|
||||||
client, cleanUp := getClient(ctx)
|
|
||||||
defer cleanUp()
|
|
||||||
|
|
||||||
args := ctx.Args()
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// Show command help if no arguments provided
|
|
||||||
if ctx.NArg() == 0 && ctx.NumFlags() == 0 {
|
|
||||||
cli.ShowCommandHelp(ctx, "openchannel")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
minConfs := int32(ctx.Uint64("min_confs"))
|
|
||||||
req := &lnrpc.OpenChannelRequest{
|
|
||||||
TargetConf: int32(ctx.Int64("conf_target")),
|
|
||||||
SatPerByte: ctx.Int64("sat_per_byte"),
|
|
||||||
MinHtlcMsat: ctx.Int64("min_htlc_msat"),
|
|
||||||
RemoteCsvDelay: uint32(ctx.Uint64("remote_csv_delay")),
|
|
||||||
MinConfs: minConfs,
|
|
||||||
SpendUnconfirmed: minConfs == 0,
|
|
||||||
CloseAddress: ctx.String("close_address"),
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case ctx.IsSet("node_key"):
|
|
||||||
nodePubHex, err := hex.DecodeString(ctx.String("node_key"))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to decode node public key: %v", err)
|
|
||||||
}
|
|
||||||
req.NodePubkey = nodePubHex
|
|
||||||
|
|
||||||
case args.Present():
|
|
||||||
nodePubHex, err := hex.DecodeString(args.First())
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to decode node public key: %v", err)
|
|
||||||
}
|
|
||||||
args = args.Tail()
|
|
||||||
req.NodePubkey = nodePubHex
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("node id argument missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
// As soon as we can confirm that the node's node_key was set, rather
|
|
||||||
// than the peer_id, we can check if the host:port was also set to
|
|
||||||
// connect to it before opening the channel.
|
|
||||||
if req.NodePubkey != nil && ctx.IsSet("connect") {
|
|
||||||
addr := &lnrpc.LightningAddress{
|
|
||||||
Pubkey: hex.EncodeToString(req.NodePubkey),
|
|
||||||
Host: ctx.String("connect"),
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &lnrpc.ConnectPeerRequest{
|
|
||||||
Addr: addr,
|
|
||||||
Perm: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if connecting to the node was successful.
|
|
||||||
// We discard the peer id returned as it is not needed.
|
|
||||||
_, err := client.ConnectPeer(ctxb, req)
|
|
||||||
if err != nil &&
|
|
||||||
!strings.Contains(err.Error(), "already connected") {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case ctx.IsSet("local_amt"):
|
|
||||||
req.LocalFundingAmount = int64(ctx.Int("local_amt"))
|
|
||||||
case args.Present():
|
|
||||||
req.LocalFundingAmount, err = strconv.ParseInt(args.First(), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to decode local amt: %v", err)
|
|
||||||
}
|
|
||||||
args = args.Tail()
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("local amt argument missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.IsSet("push_amt") {
|
|
||||||
req.PushSat = int64(ctx.Int("push_amt"))
|
|
||||||
} else if args.Present() {
|
|
||||||
req.PushSat, err = strconv.ParseInt(args.First(), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to decode push amt: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Private = ctx.Bool("private")
|
|
||||||
|
|
||||||
stream, err := client.OpenChannel(ctxb, req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
resp, err := stream.Recv()
|
|
||||||
if err == io.EOF {
|
|
||||||
return nil
|
|
||||||
} else if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch update := resp.Update.(type) {
|
|
||||||
case *lnrpc.OpenStatusUpdate_ChanPending:
|
|
||||||
txid, err := chainhash.NewHash(update.ChanPending.Txid)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
printJSON(struct {
|
|
||||||
FundingTxid string `json:"funding_txid"`
|
|
||||||
}{
|
|
||||||
FundingTxid: txid.String(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
if !ctx.Bool("block") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
case *lnrpc.OpenStatusUpdate_ChanOpen:
|
|
||||||
channelPoint := update.ChanOpen.ChannelPoint
|
|
||||||
|
|
||||||
// A channel point's funding txid can be get/set as a
|
|
||||||
// byte slice or a string. In the case it is a string,
|
|
||||||
// decode it.
|
|
||||||
var txidHash []byte
|
|
||||||
switch channelPoint.GetFundingTxid().(type) {
|
|
||||||
case *lnrpc.ChannelPoint_FundingTxidBytes:
|
|
||||||
txidHash = channelPoint.GetFundingTxidBytes()
|
|
||||||
case *lnrpc.ChannelPoint_FundingTxidStr:
|
|
||||||
s := channelPoint.GetFundingTxidStr()
|
|
||||||
h, err := chainhash.NewHashFromStr(s)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
txidHash = h[:]
|
|
||||||
}
|
|
||||||
|
|
||||||
txid, err := chainhash.NewHash(txidHash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
index := channelPoint.OutputIndex
|
|
||||||
printJSON(struct {
|
|
||||||
ChannelPoint string `json:"channel_point"`
|
|
||||||
}{
|
|
||||||
ChannelPoint: fmt.Sprintf("%v:%v", txid, index),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(roasbeef): also allow short relative channel ID.
|
// TODO(roasbeef): also allow short relative channel ID.
|
||||||
|
|
||||||
var closeChannelCommand = cli.Command{
|
var closeChannelCommand = cli.Command{
|
||||||
|
Loading…
Reference in New Issue
Block a user