diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index a9fde0a1..15d86c49 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -531,6 +531,8 @@ func listChannels(ctx *cli.Context) error { return err } + // TODO(roasbeef): defer close the client for the all + printRespJson(resp) return nil @@ -955,3 +957,33 @@ func debugLevel(ctx *cli.Context) error { printRespJson(resp) return nil } + +var DecodePayReq = cli.Command{ + Name: "decodepayreq", + Usage: "decodepayreq --pay_req=[encoded_pay_req]", + Description: "Decode the passed payment request revealing the destination, payment hash and value of the payment request", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "pay_req", + Usage: "the zpay32 encoded payment request", + }, + }, + Action: decodePayReq, +} + +func decodePayReq(ctx *cli.Context) error { + ctxb := context.Background() + client := getClient(ctx) + + req := &lnrpc.PayReqString{ + PayReq: ctx.String("pay_req"), + } + + resp, err := client.DecodePayReq(ctxb, req) + if err != nil { + return err + } + + printRespJson(resp) + return nil +} diff --git a/cmd/lncli/main.go b/cmd/lncli/main.go index 21b61f94..c414155d 100644 --- a/cmd/lncli/main.go +++ b/cmd/lncli/main.go @@ -71,6 +71,7 @@ func main() { QueryRouteCommand, GetNetworkInfoCommand, DebugLevel, + DecodePayReq, } if err := app.Run(os.Args); err != nil { diff --git a/lnd_test.go b/lnd_test.go index 0a5a12b5..d428b7be 100644 --- a/lnd_test.go +++ b/lnd_test.go @@ -1020,6 +1020,7 @@ func testInvoiceSubscriptions(net *networkHarness, t *harnessTest) { // With the assertion above set up, send a payment from Alice to Bob // which should finalize and settle the invoice. + time.Sleep(time.Millisecond * 500) sendStream, err := net.Alice.SendPayment(ctxb) if err != nil { t.Fatalf("unable to create alice payment stream: %v", err) diff --git a/rpcserver.go b/rpcserver.go index 89a63056..b6ad8745 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1792,3 +1792,25 @@ func (r *rpcServer) DebugLevel(ctx context.Context, return &lnrpc.DebugLevelResponse{}, nil } + +// DecodePayReq takes an encoded payment request string and attempts to decode +// it, returning a full description of the conditions encoded within the +// payment request. +func (r *rpcServer) DecodePayReq(ctx context.Context, + req *lnrpc.PayReqString) (*lnrpc.PayReq, error) { + + // Fist we'll attempt to decode the payment request string, if the + // request is invalid or the checksum doesn't match, then we'll exit + // here with an error. + payReq, err := zpay32.Decode(req.PayReq) + if err != nil { + return nil, err + } + + dest := payReq.Destination.SerializeCompressed() + return &lnrpc.PayReq{ + Destination: hex.EncodeToString(dest), + PaymentHash: hex.EncodeToString(payReq.PaymentHash[:]), + NumSatoshis: int64(payReq.Amount), + }, nil +}