From 4aceaba1be3f00fa799d328737b625b879613561 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 6 Apr 2020 14:21:38 -0700 Subject: [PATCH] cmd/lncli: move invoice commands to cmd_invoice.go --- cmd/lncli/cmd_invoice.go | 288 +++++++++++++++++++++++++++++++++++++++ cmd/lncli/commands.go | 277 ------------------------------------- 2 files changed, 288 insertions(+), 277 deletions(-) create mode 100644 cmd/lncli/cmd_invoice.go diff --git a/cmd/lncli/cmd_invoice.go b/cmd/lncli/cmd_invoice.go new file mode 100644 index 000000000..d2d118edd --- /dev/null +++ b/cmd/lncli/cmd_invoice.go @@ -0,0 +1,288 @@ +package main + +import ( + "context" + "encoding/hex" + "fmt" + "strconv" + + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/urfave/cli" +) + +var addInvoiceCommand = cli.Command{ + Name: "addinvoice", + Category: "Payments", + Usage: "Add a new invoice.", + Description: ` + Add a new invoice, expressing intent for a future payment. + + Invoices without an amount can be created by not supplying any + parameters or providing an amount of 0. These invoices allow the payee + to specify the amount of satoshis they wish to send.`, + ArgsUsage: "value preimage", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "memo", + Usage: "a description of the payment to attach along " + + "with the invoice (default=\"\")", + }, + cli.StringFlag{ + Name: "preimage", + Usage: "the hex-encoded preimage (32 byte) which will " + + "allow settling an incoming HTLC payable to this " + + "preimage. If not set, a random preimage will be " + + "created.", + }, + cli.Int64Flag{ + Name: "amt", + Usage: "the amt of satoshis in this invoice", + }, + cli.StringFlag{ + Name: "description_hash", + Usage: "SHA-256 hash of the description of the payment. " + + "Used if the purpose of payment cannot naturally " + + "fit within the memo. If provided this will be " + + "used instead of the description(memo) field in " + + "the encoded invoice.", + }, + cli.StringFlag{ + Name: "fallback_addr", + Usage: "fallback on-chain address that can be used in " + + "case the lightning payment fails", + }, + cli.Int64Flag{ + Name: "expiry", + Usage: "the invoice's expiry time in seconds. If not " + + "specified an expiry of 3600 seconds (1 hour) " + + "is implied.", + }, + cli.BoolTFlag{ + Name: "private", + Usage: "encode routing hints in the invoice with " + + "private channels in order to assist the " + + "payer in reaching you", + }, + }, + Action: actionDecorator(addInvoice), +} + +func addInvoice(ctx *cli.Context) error { + var ( + preimage []byte + descHash []byte + amt int64 + err error + ) + + client, cleanUp := getClient(ctx) + defer cleanUp() + + args := ctx.Args() + + switch { + case ctx.IsSet("amt"): + amt = ctx.Int64("amt") + case args.Present(): + amt, err = strconv.ParseInt(args.First(), 10, 64) + args = args.Tail() + if err != nil { + return fmt.Errorf("unable to decode amt argument: %v", err) + } + } + + switch { + case ctx.IsSet("preimage"): + preimage, err = hex.DecodeString(ctx.String("preimage")) + case args.Present(): + preimage, err = hex.DecodeString(args.First()) + } + + if err != nil { + return fmt.Errorf("unable to parse preimage: %v", err) + } + + descHash, err = hex.DecodeString(ctx.String("description_hash")) + if err != nil { + return fmt.Errorf("unable to parse description_hash: %v", err) + } + + invoice := &lnrpc.Invoice{ + Memo: ctx.String("memo"), + RPreimage: preimage, + Value: amt, + DescriptionHash: descHash, + FallbackAddr: ctx.String("fallback_addr"), + Expiry: ctx.Int64("expiry"), + Private: ctx.Bool("private"), + } + + resp, err := client.AddInvoice(context.Background(), invoice) + if err != nil { + return err + } + + printRespJSON(resp) + + return nil +} + +var lookupInvoiceCommand = cli.Command{ + Name: "lookupinvoice", + Category: "Payments", + Usage: "Lookup an existing invoice by its payment hash.", + ArgsUsage: "rhash", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "rhash", + Usage: "the 32 byte payment hash of the invoice to query for, the hash " + + "should be a hex-encoded string", + }, + }, + Action: actionDecorator(lookupInvoice), +} + +func lookupInvoice(ctx *cli.Context) error { + client, cleanUp := getClient(ctx) + defer cleanUp() + + var ( + rHash []byte + err error + ) + + switch { + case ctx.IsSet("rhash"): + rHash, err = hex.DecodeString(ctx.String("rhash")) + case ctx.Args().Present(): + rHash, err = hex.DecodeString(ctx.Args().First()) + default: + return fmt.Errorf("rhash argument missing") + } + + if err != nil { + return fmt.Errorf("unable to decode rhash argument: %v", err) + } + + req := &lnrpc.PaymentHash{ + RHash: rHash, + } + + invoice, err := client.LookupInvoice(context.Background(), req) + if err != nil { + return err + } + + printRespJSON(invoice) + + return nil +} + +var listInvoicesCommand = cli.Command{ + Name: "listinvoices", + Category: "Payments", + Usage: "List all invoices currently stored within the database. Any " + + "active debug invoices are ignored.", + Description: ` + This command enables the retrieval of all invoices currently stored + within the database. It has full support for paginationed responses, + allowing users to query for specific invoices through their add_index. + This can be done by using either the first_index_offset or + last_index_offset fields included in the response as the index_offset of + the next request. Backward pagination is enabled by default to receive + current invoices first. If you wish to paginate forwards, set the + paginate-forwards flag. If none of the parameters are specified, then + the last 100 invoices will be returned. + + For example: if you have 200 invoices, "lncli listinvoices" will return + the last 100 created. If you wish to retrieve the previous 100, the + first_offset_index of the response can be used as the index_offset of + the next listinvoices request.`, + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "pending_only", + Usage: "toggles if all invoices should be returned, " + + "or only those that are currently unsettled", + }, + cli.Uint64Flag{ + Name: "index_offset", + Usage: "the index of an invoice that will be used as " + + "either the start or end of a query to " + + "determine which invoices should be returned " + + "in the response", + }, + cli.Uint64Flag{ + Name: "max_invoices", + Usage: "the max number of invoices to return", + }, + cli.BoolFlag{ + Name: "paginate-forwards", + Usage: "if set, invoices succeeding the " + + "index_offset will be returned", + }, + }, + Action: actionDecorator(listInvoices), +} + +func listInvoices(ctx *cli.Context) error { + client, cleanUp := getClient(ctx) + defer cleanUp() + + req := &lnrpc.ListInvoiceRequest{ + PendingOnly: ctx.Bool("pending_only"), + IndexOffset: ctx.Uint64("index_offset"), + NumMaxInvoices: ctx.Uint64("max_invoices"), + Reversed: !ctx.Bool("paginate-forwards"), + } + + invoices, err := client.ListInvoices(context.Background(), req) + if err != nil { + return err + } + + printRespJSON(invoices) + + return nil +} + +var decodePayReqCommand = cli.Command{ + Name: "decodepayreq", + Category: "Payments", + Usage: "Decode a payment request.", + Description: "Decode the passed payment request revealing the destination, payment hash and value of the payment request", + ArgsUsage: "pay_req", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "pay_req", + Usage: "the bech32 encoded payment request", + }, + }, + Action: actionDecorator(decodePayReq), +} + +func decodePayReq(ctx *cli.Context) error { + ctxb := context.Background() + client, cleanUp := getClient(ctx) + defer cleanUp() + + var payreq string + + switch { + case ctx.IsSet("pay_req"): + payreq = ctx.String("pay_req") + case ctx.Args().Present(): + payreq = ctx.Args().First() + default: + return fmt.Errorf("pay_req argument missing") + } + + resp, err := client.DecodePayReq(ctxb, &lnrpc.PayReqString{ + PayReq: payreq, + }) + if err != nil { + return err + } + + printRespJSON(resp) + return nil +} diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 79313d252..46599902b 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -1873,241 +1873,6 @@ func closedChannels(ctx *cli.Context) error { return nil } -var addInvoiceCommand = cli.Command{ - Name: "addinvoice", - Category: "Payments", - Usage: "Add a new invoice.", - Description: ` - Add a new invoice, expressing intent for a future payment. - - Invoices without an amount can be created by not supplying any - parameters or providing an amount of 0. These invoices allow the payee - to specify the amount of satoshis they wish to send.`, - ArgsUsage: "value preimage", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "memo", - Usage: "a description of the payment to attach along " + - "with the invoice (default=\"\")", - }, - cli.StringFlag{ - Name: "preimage", - Usage: "the hex-encoded preimage (32 byte) which will " + - "allow settling an incoming HTLC payable to this " + - "preimage. If not set, a random preimage will be " + - "created.", - }, - cli.Int64Flag{ - Name: "amt", - Usage: "the amt of satoshis in this invoice", - }, - cli.StringFlag{ - Name: "description_hash", - Usage: "SHA-256 hash of the description of the payment. " + - "Used if the purpose of payment cannot naturally " + - "fit within the memo. If provided this will be " + - "used instead of the description(memo) field in " + - "the encoded invoice.", - }, - cli.StringFlag{ - Name: "fallback_addr", - Usage: "fallback on-chain address that can be used in " + - "case the lightning payment fails", - }, - cli.Int64Flag{ - Name: "expiry", - Usage: "the invoice's expiry time in seconds. If not " + - "specified an expiry of 3600 seconds (1 hour) " + - "is implied.", - }, - cli.BoolTFlag{ - Name: "private", - Usage: "encode routing hints in the invoice with " + - "private channels in order to assist the " + - "payer in reaching you", - }, - }, - Action: actionDecorator(addInvoice), -} - -func addInvoice(ctx *cli.Context) error { - var ( - preimage []byte - descHash []byte - amt int64 - err error - ) - - client, cleanUp := getClient(ctx) - defer cleanUp() - - args := ctx.Args() - - switch { - case ctx.IsSet("amt"): - amt = ctx.Int64("amt") - case args.Present(): - amt, err = strconv.ParseInt(args.First(), 10, 64) - args = args.Tail() - if err != nil { - return fmt.Errorf("unable to decode amt argument: %v", err) - } - } - - switch { - case ctx.IsSet("preimage"): - preimage, err = hex.DecodeString(ctx.String("preimage")) - case args.Present(): - preimage, err = hex.DecodeString(args.First()) - } - - if err != nil { - return fmt.Errorf("unable to parse preimage: %v", err) - } - - descHash, err = hex.DecodeString(ctx.String("description_hash")) - if err != nil { - return fmt.Errorf("unable to parse description_hash: %v", err) - } - - invoice := &lnrpc.Invoice{ - Memo: ctx.String("memo"), - RPreimage: preimage, - Value: amt, - DescriptionHash: descHash, - FallbackAddr: ctx.String("fallback_addr"), - Expiry: ctx.Int64("expiry"), - Private: ctx.Bool("private"), - } - - resp, err := client.AddInvoice(context.Background(), invoice) - if err != nil { - return err - } - - printRespJSON(resp) - - return nil -} - -var lookupInvoiceCommand = cli.Command{ - Name: "lookupinvoice", - Category: "Payments", - Usage: "Lookup an existing invoice by its payment hash.", - ArgsUsage: "rhash", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "rhash", - Usage: "the 32 byte payment hash of the invoice to query for, the hash " + - "should be a hex-encoded string", - }, - }, - Action: actionDecorator(lookupInvoice), -} - -func lookupInvoice(ctx *cli.Context) error { - client, cleanUp := getClient(ctx) - defer cleanUp() - - var ( - rHash []byte - err error - ) - - switch { - case ctx.IsSet("rhash"): - rHash, err = hex.DecodeString(ctx.String("rhash")) - case ctx.Args().Present(): - rHash, err = hex.DecodeString(ctx.Args().First()) - default: - return fmt.Errorf("rhash argument missing") - } - - if err != nil { - return fmt.Errorf("unable to decode rhash argument: %v", err) - } - - req := &lnrpc.PaymentHash{ - RHash: rHash, - } - - invoice, err := client.LookupInvoice(context.Background(), req) - if err != nil { - return err - } - - printRespJSON(invoice) - - return nil -} - -var listInvoicesCommand = cli.Command{ - Name: "listinvoices", - Category: "Payments", - Usage: "List all invoices currently stored within the database. Any " + - "active debug invoices are ignored.", - Description: ` - This command enables the retrieval of all invoices currently stored - within the database. It has full support for paginationed responses, - allowing users to query for specific invoices through their add_index. - This can be done by using either the first_index_offset or - last_index_offset fields included in the response as the index_offset of - the next request. Backward pagination is enabled by default to receive - current invoices first. If you wish to paginate forwards, set the - paginate-forwards flag. If none of the parameters are specified, then - the last 100 invoices will be returned. - - For example: if you have 200 invoices, "lncli listinvoices" will return - the last 100 created. If you wish to retrieve the previous 100, the - first_offset_index of the response can be used as the index_offset of - the next listinvoices request.`, - Flags: []cli.Flag{ - cli.BoolFlag{ - Name: "pending_only", - Usage: "toggles if all invoices should be returned, " + - "or only those that are currently unsettled", - }, - cli.Uint64Flag{ - Name: "index_offset", - Usage: "the index of an invoice that will be used as " + - "either the start or end of a query to " + - "determine which invoices should be returned " + - "in the response", - }, - cli.Uint64Flag{ - Name: "max_invoices", - Usage: "the max number of invoices to return", - }, - cli.BoolFlag{ - Name: "paginate-forwards", - Usage: "if set, invoices succeeding the " + - "index_offset will be returned", - }, - }, - Action: actionDecorator(listInvoices), -} - -func listInvoices(ctx *cli.Context) error { - client, cleanUp := getClient(ctx) - defer cleanUp() - - req := &lnrpc.ListInvoiceRequest{ - PendingOnly: ctx.Bool("pending_only"), - IndexOffset: ctx.Uint64("index_offset"), - NumMaxInvoices: ctx.Uint64("max_invoices"), - Reversed: !ctx.Bool("paginate-forwards"), - } - - invoices, err := client.ListInvoices(context.Background(), req) - if err != nil { - return err - } - - printRespJSON(invoices) - - return nil -} - var describeGraphCommand = cli.Command{ Name: "describegraph", Category: "Graph", @@ -2494,48 +2259,6 @@ func debugLevel(ctx *cli.Context) error { return nil } -var decodePayReqCommand = cli.Command{ - Name: "decodepayreq", - Category: "Payments", - Usage: "Decode a payment request.", - Description: "Decode the passed payment request revealing the destination, payment hash and value of the payment request", - ArgsUsage: "pay_req", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "pay_req", - Usage: "the bech32 encoded payment request", - }, - }, - Action: actionDecorator(decodePayReq), -} - -func decodePayReq(ctx *cli.Context) error { - ctxb := context.Background() - client, cleanUp := getClient(ctx) - defer cleanUp() - - var payreq string - - switch { - case ctx.IsSet("pay_req"): - payreq = ctx.String("pay_req") - case ctx.Args().Present(): - payreq = ctx.Args().First() - default: - return fmt.Errorf("pay_req argument missing") - } - - resp, err := client.DecodePayReq(ctxb, &lnrpc.PayReqString{ - PayReq: payreq, - }) - if err != nil { - return err - } - - printRespJSON(resp) - return nil -} - var listChainTxnsCommand = cli.Command{ Name: "listchaintxns", Category: "On-chain",