github.com/decred/dcrlnd@v0.7.6/cmd/dcrlncli/invoicesrpc_active.go (about)

     1  //go:build !no_invoicesrpc
     2  // +build !no_invoicesrpc
     3  
     4  package main
     5  
     6  import (
     7  	"encoding/hex"
     8  	"fmt"
     9  	"strconv"
    10  
    11  	"github.com/decred/dcrlnd/lnrpc/invoicesrpc"
    12  
    13  	"github.com/urfave/cli"
    14  )
    15  
    16  // invoicesCommands will return nil for non-invoicesrpc builds.
    17  func invoicesCommands() []cli.Command {
    18  	return []cli.Command{
    19  		cancelInvoiceCommand,
    20  		addHoldInvoiceCommand,
    21  		settleInvoiceCommand,
    22  	}
    23  }
    24  
    25  func getInvoicesClient(ctx *cli.Context) (invoicesrpc.InvoicesClient, func()) {
    26  	conn := getClientConn(ctx, false)
    27  
    28  	cleanUp := func() {
    29  		conn.Close()
    30  	}
    31  
    32  	return invoicesrpc.NewInvoicesClient(conn), cleanUp
    33  }
    34  
    35  var settleInvoiceCommand = cli.Command{
    36  	Name:     "settleinvoice",
    37  	Category: "Invoices",
    38  	Usage:    "Reveal a preimage and use it to settle the corresponding invoice.",
    39  	Description: `
    40  	Todo.`,
    41  	ArgsUsage: "preimage",
    42  	Flags: []cli.Flag{
    43  		cli.StringFlag{
    44  			Name: "preimage",
    45  			Usage: "The hex-encoded preimage (32 byte) which will " +
    46  				"allow settling an incoming HTLC payable to this " +
    47  				"preimage.",
    48  		},
    49  	},
    50  	Action: actionDecorator(settleInvoice),
    51  }
    52  
    53  func settleInvoice(ctx *cli.Context) error {
    54  	var (
    55  		preimage []byte
    56  		err      error
    57  	)
    58  
    59  	ctxc := getContext()
    60  	client, cleanUp := getInvoicesClient(ctx)
    61  	defer cleanUp()
    62  
    63  	args := ctx.Args()
    64  
    65  	switch {
    66  	case ctx.IsSet("preimage"):
    67  		preimage, err = hex.DecodeString(ctx.String("preimage"))
    68  	case args.Present():
    69  		preimage, err = hex.DecodeString(args.First())
    70  	}
    71  
    72  	if err != nil {
    73  		return fmt.Errorf("unable to parse preimage: %v", err)
    74  	}
    75  
    76  	invoice := &invoicesrpc.SettleInvoiceMsg{
    77  		Preimage: preimage,
    78  	}
    79  
    80  	resp, err := client.SettleInvoice(ctxc, invoice)
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	printRespJSON(resp)
    86  
    87  	return nil
    88  }
    89  
    90  var cancelInvoiceCommand = cli.Command{
    91  	Name:     "cancelinvoice",
    92  	Category: "Invoices",
    93  	Usage:    "Cancels a (hold) invoice.",
    94  	Description: `
    95  	Todo.`,
    96  	ArgsUsage: "paymenthash",
    97  	Flags: []cli.Flag{
    98  		cli.StringFlag{
    99  			Name: "paymenthash",
   100  			Usage: "The hex-encoded payment hash (32 byte) for which the " +
   101  				"corresponding invoice will be canceled.",
   102  		},
   103  	},
   104  	Action: actionDecorator(cancelInvoice),
   105  }
   106  
   107  func cancelInvoice(ctx *cli.Context) error {
   108  	var (
   109  		paymentHash []byte
   110  		err         error
   111  	)
   112  
   113  	ctxc := getContext()
   114  	client, cleanUp := getInvoicesClient(ctx)
   115  	defer cleanUp()
   116  
   117  	args := ctx.Args()
   118  
   119  	switch {
   120  	case ctx.IsSet("paymenthash"):
   121  		paymentHash, err = hex.DecodeString(ctx.String("paymenthash"))
   122  	case args.Present():
   123  		paymentHash, err = hex.DecodeString(args.First())
   124  	}
   125  
   126  	if err != nil {
   127  		return fmt.Errorf("unable to parse preimage: %v", err)
   128  	}
   129  
   130  	invoice := &invoicesrpc.CancelInvoiceMsg{
   131  		PaymentHash: paymentHash,
   132  	}
   133  
   134  	resp, err := client.CancelInvoice(ctxc, invoice)
   135  	if err != nil {
   136  		return err
   137  	}
   138  
   139  	printRespJSON(resp)
   140  
   141  	return nil
   142  }
   143  
   144  var addHoldInvoiceCommand = cli.Command{
   145  	Name:     "addholdinvoice",
   146  	Category: "Invoices",
   147  	Usage:    "Add a new hold invoice.",
   148  	Description: `
   149  	Add a new invoice, expressing intent for a future payment.
   150  
   151  	Invoices without an amount can be created by not supplying any
   152  	parameters or providing an amount of 0. These invoices allow the payee
   153  	to specify the amount of atoms they wish to send.`,
   154  	ArgsUsage: "hash [amt]",
   155  	Flags: []cli.Flag{
   156  		cli.StringFlag{
   157  			Name: "memo",
   158  			Usage: "A description of the payment to attach along " +
   159  				"with the invoice (default=\"\")",
   160  		},
   161  		cli.Int64Flag{
   162  			Name:  "amt",
   163  			Usage: "The amt of atoms in this invoice",
   164  		},
   165  		cli.Int64Flag{
   166  			Name:  "amt_m_atoms",
   167  			Usage: "The amt of milliatoms in this invoice",
   168  		},
   169  		cli.StringFlag{
   170  			Name: "description_hash",
   171  			Usage: "SHA-256 hash of the description of the payment. " +
   172  				"Used if the purpose of payment cannot naturally " +
   173  				"fit within the memo. If provided this will be " +
   174  				"used instead of the description(memo) field in " +
   175  				"the encoded invoice.",
   176  		},
   177  		cli.StringFlag{
   178  			Name: "fallback_addr",
   179  			Usage: "Fallback on-chain address that can be used in " +
   180  				"case the lightning payment fails",
   181  		},
   182  		cli.Int64Flag{
   183  			Name: "expiry",
   184  			Usage: "The invoice's expiry time in seconds. If not " +
   185  				"specified, an expiry of 3600 seconds (1 hour) " +
   186  				"is implied.",
   187  		},
   188  		cli.BoolTFlag{
   189  			Name: "private",
   190  			Usage: "Encode routing hints in the invoice with " +
   191  				"private channels in order to assist the " +
   192  				"payer in reaching you",
   193  		},
   194  	},
   195  	Action: actionDecorator(addHoldInvoice),
   196  }
   197  
   198  func addHoldInvoice(ctx *cli.Context) error {
   199  	var (
   200  		descHash []byte
   201  		err      error
   202  	)
   203  
   204  	ctxc := getContext()
   205  	client, cleanUp := getInvoicesClient(ctx)
   206  	defer cleanUp()
   207  
   208  	args := ctx.Args()
   209  	if ctx.NArg() == 0 {
   210  		cli.ShowCommandHelp(ctx, "addholdinvoice")
   211  		return nil
   212  	}
   213  
   214  	hash, err := hex.DecodeString(args.First())
   215  	if err != nil {
   216  		return fmt.Errorf("unable to parse hash: %v", err)
   217  	}
   218  
   219  	args = args.Tail()
   220  
   221  	amt := ctx.Int64("amt")
   222  	amtMAtoms := ctx.Int64("amt_m_atoms")
   223  
   224  	if !ctx.IsSet("amt") && !ctx.IsSet("amt_m_atoms") && args.Present() {
   225  		amt, err = strconv.ParseInt(args.First(), 10, 64)
   226  		if err != nil {
   227  			return fmt.Errorf("unable to decode amt argument: %v", err)
   228  		}
   229  	}
   230  
   231  	descHash, err = hex.DecodeString(ctx.String("description_hash"))
   232  	if err != nil {
   233  		return fmt.Errorf("unable to parse description_hash: %v", err)
   234  	}
   235  
   236  	invoice := &invoicesrpc.AddHoldInvoiceRequest{
   237  		Memo:            ctx.String("memo"),
   238  		Hash:            hash,
   239  		Value:           amt,
   240  		ValueMAtoms:     amtMAtoms,
   241  		DescriptionHash: descHash,
   242  		FallbackAddr:    ctx.String("fallback_addr"),
   243  		Expiry:          ctx.Int64("expiry"),
   244  		Private:         ctx.Bool("private"),
   245  	}
   246  
   247  	resp, err := client.AddHoldInvoice(ctxc, invoice)
   248  	if err != nil {
   249  		return err
   250  	}
   251  
   252  	printRespJSON(resp)
   253  
   254  	return nil
   255  }