@@ -6,19 +6,17 @@ import (
6
6
"fmt"
7
7
"time"
8
8
9
- "github.com/lightningnetwork/lnd/lnrpc"
10
- "github.com/lightningnetwork/lnd/routing/route"
11
-
9
+ "github.com/btcsuite/btcutil"
12
10
"github.com/lightningnetwork/lnd/channeldb"
13
- "google.golang.org/grpc/codes"
14
-
11
+ "github.com/lightningnetwork/lnd/lnrpc"
15
12
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
13
+ "github.com/lightningnetwork/lnd/lntypes"
16
14
"github.com/lightningnetwork/lnd/lnwire"
15
+ "github.com/lightningnetwork/lnd/routing/route"
16
+ "github.com/lightningnetwork/lnd/zpay32"
17
17
"google.golang.org/grpc"
18
+ "google.golang.org/grpc/codes"
18
19
"google.golang.org/grpc/status"
19
-
20
- "github.com/btcsuite/btcutil"
21
- "github.com/lightningnetwork/lnd/lntypes"
22
20
)
23
21
24
22
// RouterClient exposes payment functionality.
@@ -44,11 +42,41 @@ type PaymentStatus struct {
44
42
45
43
// SendPaymentRequest defines the payment parameters for a new payment.
46
44
type 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
+
48
50
MaxFee btcutil.Amount
49
51
MaxCltv * int32
50
52
OutgoingChannel * uint64
51
53
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
52
80
}
53
81
54
82
// routerClient is a wrapper around the generated routerrpc proxy.
@@ -84,6 +112,21 @@ func (r *routerClient) SendPayment(ctx context.Context,
84
112
rpcReq .OutgoingChanId = * request .OutgoingChannel
85
113
}
86
114
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
+
87
130
stream , err := r .client .SendPayment (rpcCtx , rpcReq )
88
131
if err != nil {
89
132
return nil , nil , err
@@ -237,3 +280,46 @@ func unmarshallHop(hop *lnrpc.Hop) (*route.Hop, error) {
237
280
ChannelID : hop .ChanId ,
238
281
}, nil
239
282
}
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