diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 9c55881f..7951391f 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -12,6 +12,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcutil" + "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwire" @@ -779,3 +780,48 @@ func UnmarshalMPP(reqMPP *lnrpc.MPPRecord) (*record.MPP, error) { return record.NewMPP(total, addr), nil } + +// MarshalHTLCAttempt constructs an RPC HTLCAttempt from the db representation. +func (r *RouterBackend) MarshalHTLCAttempt( + htlc channeldb.HTLCAttempt) (*lnrpc.HTLCAttempt, error) { + + var ( + status lnrpc.HTLCAttempt_HTLCStatus + resolveTime int64 + ) + + switch { + case htlc.Settle != nil: + status = lnrpc.HTLCAttempt_SUCCEEDED + resolveTime = MarshalTimeNano(htlc.Settle.SettleTime) + + case htlc.Failure != nil: + status = lnrpc.HTLCAttempt_FAILED + resolveTime = MarshalTimeNano(htlc.Failure.FailTime) + + default: + status = lnrpc.HTLCAttempt_IN_FLIGHT + } + + route, err := r.MarshallRoute(&htlc.Route) + if err != nil { + return nil, err + } + + return &lnrpc.HTLCAttempt{ + Status: status, + Route: route, + AttemptTimeNs: MarshalTimeNano(htlc.AttemptTime), + ResolveTimeNs: resolveTime, + }, nil +} + +// MarshalTimeNano converts a time.Time into its nanosecond representation. If +// the time is zero, this method simply returns 0, since calling UnixNano() on a +// zero-valued time is undefined. +func MarshalTimeNano(t time.Time) int64 { + if t.IsZero() { + return 0 + } + return t.UnixNano() +} diff --git a/rpcserver.go b/rpcserver.go index 6c770b78..32c3d7c0 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -4379,13 +4379,25 @@ func (r *rpcServer) ListPayments(ctx context.Context, return nil, err } + htlcs := make([]*lnrpc.HTLCAttempt, 0, len(payment.HTLCs)) + for _, dbHTLC := range payment.HTLCs { + htlc, err := r.routerBackend.MarshalHTLCAttempt(dbHTLC) + if err != nil { + return nil, err + } + + htlcs = append(htlcs, htlc) + } + paymentHash := payment.Info.PaymentHash + creationTimeNS := routerrpc.MarshalTimeNano(payment.Info.CreationTime) paymentsResp.Payments = append(paymentsResp.Payments, &lnrpc.Payment{ PaymentHash: hex.EncodeToString(paymentHash[:]), Value: satValue, ValueMsat: msatValue, ValueSat: satValue, CreationDate: payment.Info.CreationTime.Unix(), + CreationTimeNs: creationTimeNS, Path: path, Fee: int64(route.TotalFees().ToSatoshis()), FeeSat: int64(route.TotalFees().ToSatoshis()), @@ -4393,6 +4405,7 @@ func (r *rpcServer) ListPayments(ctx context.Context, PaymentPreimage: hex.EncodeToString(preimage[:]), PaymentRequest: string(payment.Info.PaymentRequest), Status: status, + Htlcs: htlcs, }) }