Skip to content

Commit 77fa6dd

Browse files
author
ffranr
authored
Merge pull request #1224 from GeorgeTsagk/sendpayment-manual-rfq
Support user-generated RFQ on `tchrpc.SendPayment`
2 parents 35552e5 + 9da1d71 commit 77fa6dd

File tree

4 files changed

+173
-70
lines changed

4 files changed

+173
-70
lines changed

rpcserver.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7034,6 +7034,87 @@ func (r *rpcServer) SendPayment(req *tchrpc.SendPaymentRequest,
70347034
case len(firstHopRecords) > 0:
70357035
// Continue below.
70367036

7037+
case req.RfqId != nil:
7038+
// Check if the provided rfq ID matches the expected length.
7039+
if len(req.RfqId) != 32 {
7040+
return fmt.Errorf("rfq must be 32 bytes in length")
7041+
}
7042+
7043+
// Now let's try to perform an internal lookup to see if there's
7044+
// an actual quote on this ID.
7045+
var rfqID rfqmsg.ID
7046+
copy(rfqID[:], req.RfqId)
7047+
7048+
var quote *rfqmsg.SellAccept
7049+
for _, q := range r.cfg.RfqManager.PeerAcceptedSellQuotes() {
7050+
if q.ID == rfqID {
7051+
qCopy := q
7052+
quote = &qCopy
7053+
break
7054+
}
7055+
}
7056+
7057+
// This quote ID did not match anything.
7058+
if quote == nil {
7059+
return fmt.Errorf("quote ID did not match an " +
7060+
"accepted quote")
7061+
}
7062+
7063+
invoice, err := zpay32.Decode(
7064+
pReq.PaymentRequest, r.cfg.Lnd.ChainParams,
7065+
)
7066+
if err != nil {
7067+
return fmt.Errorf("error decoding payment request: %w",
7068+
err)
7069+
}
7070+
7071+
rate := quote.AssetRate.Rate
7072+
7073+
// Calculate the equivalent asset units for the given invoice
7074+
// amount based on the asset-to-BTC conversion rate.
7075+
numAssetUnits := rfqmath.MilliSatoshiToUnits(
7076+
*invoice.MilliSat, rate,
7077+
)
7078+
7079+
sellOrder := &rfqrpc.PeerAcceptedSellQuote{
7080+
Peer: quote.Peer.String(),
7081+
Id: quote.ID[:],
7082+
Scid: uint64(quote.ID.Scid()),
7083+
BidAssetRate: &rfqrpc.FixedPoint{
7084+
Coefficient: rate.Coefficient.String(),
7085+
Scale: uint32(rate.Scale),
7086+
},
7087+
AssetAmount: numAssetUnits.ToUint64(),
7088+
Expiry: uint64(quote.AssetRate.Expiry.Unix()),
7089+
}
7090+
7091+
// Send out the information about the quote on the stream.
7092+
err = stream.Send(&tchrpc.SendPaymentResponse{
7093+
Result: &tchrpc.SendPaymentResponse_AcceptedSellOrder{
7094+
AcceptedSellOrder: sellOrder,
7095+
},
7096+
})
7097+
if err != nil {
7098+
return fmt.Errorf("payment failed to send accepted "+
7099+
"sell order over stream: %v", err)
7100+
}
7101+
7102+
rpcsLog.Infof("Using quote for %v asset units at %v asset/BTC "+
7103+
"from peer %x with SCID %d", numAssetUnits,
7104+
rate.String(), quote.Peer, quote.ID.Scid())
7105+
7106+
htlc := rfqmsg.NewHtlc(nil, fn.Some(quote.ID))
7107+
7108+
// We'll now map the HTLC struct into a set of TLV records,
7109+
// which we can then encode into the expected map format.
7110+
htlcMapRecords, err := tlv.RecordsToMap(htlc.Records())
7111+
if err != nil {
7112+
return fmt.Errorf("unable to encode records as map: %w",
7113+
err)
7114+
}
7115+
7116+
pReq.FirstHopCustomRecords = htlcMapRecords
7117+
70377118
// The request wants to pay a specific invoice.
70387119
case pReq.PaymentRequest != "":
70397120
invoice, err := zpay32.Decode(

taprpc/tapchannelrpc/tapchannel.pb.go

Lines changed: 82 additions & 70 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

taprpc/tapchannelrpc/tapchannel.proto

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ message SendPaymentRequest {
121121
// contain a valid keysend record (key 5482373484 and a 32-byte preimage
122122
// that corresponds to the payment hash).
123123
routerrpc.SendPaymentRequest payment_request = 4;
124+
125+
// The rfq id to use for this payment. If the user sets this value then the
126+
// payment will immediately be dispatched, skipping the rfq negotiation
127+
// phase, and using the following rfq id instead.
128+
bytes rfq_id = 5;
124129
}
125130

126131
message SendPaymentResponse {

taprpc/tapchannelrpc/tapchannel.swagger.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,6 +1455,11 @@
14551455
"payment_request": {
14561456
"$ref": "#/definitions/routerrpcSendPaymentRequest",
14571457
"description": "The full lnd payment request to send. All fields behave the same way as\nthey do for lnd's routerrpc.SendPaymentV2 RPC method (see the API docs\nat https://lightning.engineering/api-docs/api/lnd/router/send-payment-v2\nfor more details).\nTo send a keysend payment, the payment_request.dest_custom_records must\ncontain a valid keysend record (key 5482373484 and a 32-byte preimage\nthat corresponds to the payment hash)."
1458+
},
1459+
"rfq_id": {
1460+
"type": "string",
1461+
"format": "byte",
1462+
"description": "The rfq id to use for this payment. If the user sets this value then the\npayment will immediately be dispatched, skipping the rfq negotiation\nphase, and using the following rfq id instead."
14581463
}
14591464
}
14601465
},

0 commit comments

Comments
 (0)