@@ -6,19 +6,17 @@ import (
66 "fmt"
77 "time"
88
9- "github.com/lightningnetwork/lnd/lnrpc"
10- "github.com/lightningnetwork/lnd/routing/route"
11-
9+ "github.com/btcsuite/btcutil"
1210 "github.com/lightningnetwork/lnd/channeldb"
13- "google.golang.org/grpc/codes"
14-
11+ "github.com/lightningnetwork/lnd/lnrpc"
1512 "github.com/lightningnetwork/lnd/lnrpc/routerrpc"
13+ "github.com/lightningnetwork/lnd/lntypes"
1614 "github.com/lightningnetwork/lnd/lnwire"
15+ "github.com/lightningnetwork/lnd/routing/route"
16+ "github.com/lightningnetwork/lnd/zpay32"
1717 "google.golang.org/grpc"
18+ "google.golang.org/grpc/codes"
1819 "google.golang.org/grpc/status"
19-
20- "github.com/btcsuite/btcutil"
21- "github.com/lightningnetwork/lnd/lntypes"
2220)
2321
2422// RouterClient exposes payment functionality.
@@ -44,11 +42,41 @@ type PaymentStatus struct {
4442
4543// SendPaymentRequest defines the payment parameters for a new payment.
4644type SendPaymentRequest struct {
47- Invoice string
45+ // Invoice is an encoded payment request. The individual payment
46+ // parameters Target, Amount, PaymentHash, FinalCLTVDelta and RouteHints
47+ // are only processed when the Invoice field is empty.
48+ Invoice string
49+
4850 MaxFee btcutil.Amount
4951 MaxCltv * int32
5052 OutgoingChannel * uint64
5153 Timeout time.Duration
54+
55+ // Target is the node in which the payment should be routed towards.
56+ Target route.Vertex
57+
58+ // Amount is the value of the payment to send through the network in
59+ // satoshis.
60+ Amount btcutil.Amount
61+
62+ // PaymentHash is the r-hash value to use within the HTLC extended to
63+ // the first hop.
64+ PaymentHash [32 ]byte
65+
66+ // FinalCLTVDelta is the CTLV expiry delta to use for the _final_ hop
67+ // in the route. This means that the final hop will have a CLTV delta
68+ // of at least: currentHeight + FinalCLTVDelta.
69+ FinalCLTVDelta uint16
70+
71+ // RouteHints represents the different routing hints that can be used to
72+ // assist a payment in reaching its destination successfully. These
73+ // hints will act as intermediate hops along the route.
74+ //
75+ // NOTE: This is optional unless required by the payment. When providing
76+ // multiple routes, ensure the hop hints within each route are chained
77+ // together and sorted in forward order in order to reach the
78+ // destination successfully.
79+ RouteHints [][]zpay32.HopHint
5280}
5381
5482// routerClient is a wrapper around the generated routerrpc proxy.
@@ -84,6 +112,21 @@ func (r *routerClient) SendPayment(ctx context.Context,
84112 rpcReq .OutgoingChanId = * request .OutgoingChannel
85113 }
86114
115+ // Only if there is no payment request set, we will parse the individual
116+ // payment parameters.
117+ if request .Invoice == "" {
118+ rpcReq .Dest = request .Target [:]
119+ rpcReq .Amt = int64 (request .Amount )
120+ rpcReq .PaymentHash = request .PaymentHash [:]
121+ rpcReq .FinalCltvDelta = int32 (request .FinalCLTVDelta )
122+
123+ routeHints , err := marshallRouteHints (request .RouteHints )
124+ if err != nil {
125+ return nil , nil , err
126+ }
127+ rpcReq .RouteHints = routeHints
128+ }
129+
87130 stream , err := r .client .SendPayment (rpcCtx , rpcReq )
88131 if err != nil {
89132 return nil , nil , err
@@ -237,3 +280,46 @@ func unmarshallHop(hop *lnrpc.Hop) (*route.Hop, error) {
237280 ChannelID : hop .ChanId ,
238281 }, nil
239282}
283+
284+ // marshallRouteHints marshalls a list of route hints.
285+ func marshallRouteHints (routeHints [][]zpay32.HopHint ) (
286+ []* lnrpc.RouteHint , error ) {
287+
288+ rpcRouteHints := make ([]* lnrpc.RouteHint , 0 , len (routeHints ))
289+ for _ , routeHint := range routeHints {
290+ rpcRouteHint := make (
291+ []* lnrpc.HopHint , 0 , len (routeHint ),
292+ )
293+ for _ , hint := range routeHint {
294+ rpcHint , err := marshallHopHint (hint )
295+ if err != nil {
296+ return nil , err
297+ }
298+
299+ rpcRouteHint = append (rpcRouteHint , rpcHint )
300+ }
301+ rpcRouteHints = append (rpcRouteHints , & lnrpc.RouteHint {
302+ HopHints : rpcRouteHint ,
303+ })
304+ }
305+
306+ return rpcRouteHints , nil
307+ }
308+
309+ // marshallHopHint marshalls a single hop hint.
310+ func marshallHopHint (hint zpay32.HopHint ) (* lnrpc.HopHint , error ) {
311+ nodeID , err := route .NewVertexFromBytes (
312+ hint .NodeID .SerializeCompressed (),
313+ )
314+ if err != nil {
315+ return nil , err
316+ }
317+
318+ return & lnrpc.HopHint {
319+ ChanId : hint .ChannelID ,
320+ CltvExpiryDelta : uint32 (hint .CLTVExpiryDelta ),
321+ FeeBaseMsat : hint .FeeBaseMSat ,
322+ FeeProportionalMillionths : hint .FeeProportionalMillionths ,
323+ NodeId : nodeID .String (),
324+ }, nil
325+ }
0 commit comments