@@ -16,6 +16,7 @@ import (
1616 "github.com/lightningnetwork/lnd/lnrpc"
1717 "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
1818 "github.com/lightningnetwork/lnd/lntypes"
19+ "github.com/lightningnetwork/lnd/lnwire"
1920 "github.com/lightningnetwork/lnd/zpay32"
2021 "google.golang.org/grpc"
2122 "google.golang.org/grpc/codes"
@@ -38,6 +39,9 @@ type LightningClient interface {
3839 AddInvoice (ctx context.Context , in * invoicesrpc.AddInvoiceData ) (
3940 lntypes.Hash , string , error )
4041
42+ // LookupInvoice looks up an invoice by hash.
43+ LookupInvoice (ctx context.Context , hash lntypes.Hash ) (* Invoice , error )
44+
4145 // ListTransactions returns all known transactions of the backing lnd
4246 // node.
4347 ListTransactions (ctx context.Context ) ([]* wire.MsgTx , error )
@@ -365,6 +369,103 @@ func (s *lightningClient) AddInvoice(ctx context.Context,
365369 return hash , resp .PaymentRequest , nil
366370}
367371
372+ // Invoice represents an invoice in lnd.
373+ type Invoice struct {
374+ // Preimage is the invoice's preimage, which is set if the invoice
375+ // is settled.
376+ Preimage * lntypes.Preimage
377+
378+ // Hash is the invoice hash.
379+ Hash lntypes.Hash
380+
381+ // Memo is an optional memo field for hte invoice.
382+ Memo string
383+
384+ // PaymentRequest is the invoice's payment request.
385+ PaymentRequest string
386+
387+ // Amount is the amount of the invoice in millisatoshis.
388+ Amount lnwire.MilliSatoshi
389+
390+ // AmountPaid is the amount that was paid for the invoice. This field
391+ // will only be set if the invoice is settled.
392+ AmountPaid lnwire.MilliSatoshi
393+
394+ // CreationDate is the time the invoice was created.
395+ CreationDate time.Time
396+
397+ // SettleDate is the time the invoice was settled.
398+ SettleDate time.Time
399+
400+ // State is the invoice's current state.
401+ State channeldb.ContractState
402+
403+ // IsKeysend indicates whether the invoice was a spontaneous payment.
404+ IsKeysend bool
405+ }
406+
407+ // LookupInvoice looks up an invoice in lnd, it will error if the invoice is
408+ // not known to lnd.
409+ func (s * lightningClient ) LookupInvoice (ctx context.Context ,
410+ hash lntypes.Hash ) (* Invoice , error ) {
411+
412+ rpcCtx , cancel := context .WithTimeout (ctx , rpcTimeout )
413+ defer cancel ()
414+
415+ rpcIn := & lnrpc.PaymentHash {
416+ RHash : hash [:],
417+ }
418+
419+ rpcCtx = s .adminMac .WithMacaroonAuth (rpcCtx )
420+ resp , err := s .client .LookupInvoice (rpcCtx , rpcIn )
421+ if err != nil {
422+ return nil , err
423+ }
424+
425+ invoice := & Invoice {
426+ Preimage : nil ,
427+ Hash : hash ,
428+ Memo : resp .Memo ,
429+ PaymentRequest : resp .PaymentRequest ,
430+ Amount : lnwire .MilliSatoshi (resp .ValueMsat ),
431+ AmountPaid : lnwire .MilliSatoshi (resp .AmtPaidMsat ),
432+ CreationDate : time .Unix (resp .CreationDate , 0 ),
433+ IsKeysend : resp .IsKeysend ,
434+ }
435+
436+ switch resp .State {
437+ case lnrpc .Invoice_OPEN :
438+ invoice .State = channeldb .ContractOpen
439+
440+ case lnrpc .Invoice_ACCEPTED :
441+ invoice .State = channeldb .ContractAccepted
442+
443+ // If the invoice is settled, it also has a non-nil preimage, which we
444+ // can set on our invoice.
445+ case lnrpc .Invoice_SETTLED :
446+ invoice .State = channeldb .ContractSettled
447+ preimage , err := lntypes .MakePreimage (resp .RPreimage )
448+ if err != nil {
449+ return nil , err
450+ }
451+ invoice .Preimage = & preimage
452+
453+ case lnrpc .Invoice_CANCELED :
454+ invoice .State = channeldb .ContractCanceled
455+
456+ default :
457+ return nil , fmt .Errorf ("unknown invoice state: %v" , resp .State )
458+ }
459+
460+ // Only set settle date if it is non-zero, because 0 unix time is
461+ // not the same as a zero time struct.
462+ if resp .SettleDate != 0 {
463+ invoice .SettleDate = time .Unix (resp .SettleDate , 0 )
464+ }
465+
466+ return invoice , nil
467+ }
468+
368469// ListTransactions returns all known transactions of the backing lnd node.
369470func (s * lightningClient ) ListTransactions (ctx context.Context ) ([]* wire.MsgTx , error ) {
370471 rpcCtx , cancel := context .WithTimeout (ctx , rpcTimeout )
0 commit comments