Skip to content

Commit f2b930d

Browse files
committed
litcli: update payinvoice for multirfq
1 parent 91bc1ac commit f2b930d

File tree

1 file changed

+52
-47
lines changed

1 file changed

+52
-47
lines changed

cmd/litcli/ln.go

Lines changed: 52 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import (
55
"context"
66
"crypto/rand"
77
"encoding/hex"
8-
"errors"
98
"fmt"
109
"time"
1110

1211
"github.com/lightninglabs/taproot-assets/rfq"
1312
"github.com/lightninglabs/taproot-assets/rfqmath"
1413
"github.com/lightninglabs/taproot-assets/rpcutils"
1514
"github.com/lightninglabs/taproot-assets/taprpc"
15+
"github.com/lightninglabs/taproot-assets/taprpc/rfqrpc"
1616
tchrpc "github.com/lightninglabs/taproot-assets/taprpc/tapchannelrpc"
1717
"github.com/lightningnetwork/lnd/cmd/commands"
1818
"github.com/lightningnetwork/lnd/lnrpc"
@@ -210,9 +210,8 @@ var (
210210
rfqPeerPubKeyFlag = cli.StringFlag{
211211
Name: "rfq_peer_pubkey",
212212
Usage: "(optional) the public key of the peer to ask for a " +
213-
"quote when converting from assets to sats; must be " +
214-
"set if there are multiple channels with the same " +
215-
"asset ID present",
213+
"quote when converting from assets to sats; if left " +
214+
"unset then rfq peers will be picked automatically",
216215
}
217216

218217
allowOverpayFlag = cli.BoolFlag{
@@ -237,74 +236,80 @@ type resultStreamWrapper struct {
237236
//
238237
// NOTE: This method is part of the PaymentResultStream interface.
239238
func (w *resultStreamWrapper) Recv() (*lnrpc.Payment, error) {
240-
resp, err := w.stream.Recv()
241-
if err != nil {
242-
return nil, err
243-
}
244-
245-
res := resp.Result
246-
switch r := res.(type) {
247-
// The very first response might be an accepted sell order, which we
248-
// just print out.
249-
case *tchrpc.SendPaymentResponse_AcceptedSellOrder:
250-
quote := r.AcceptedSellOrder
239+
// printQuote unmarshals and prints an accepted quote.
240+
printQuote := func(quote *rfqrpc.PeerAcceptedSellQuote) error {
251241
rpcRate := quote.BidAssetRate
252242
rate, err := rpcutils.UnmarshalRfqFixedPoint(rpcRate)
253243
if err != nil {
254-
return nil, fmt.Errorf("unable to unmarshal fixed "+
255-
"point: %w", err)
244+
return fmt.Errorf("unable to unmarshal fixed point: %w",
245+
err)
256246
}
257247

258248
amountMsat := lnwire.MilliSatoshi(w.amountMsat)
259249
milliSatsFP := rfqmath.MilliSatoshiToUnits(amountMsat, *rate)
260250
numUnits := milliSatsFP.ScaleTo(0).ToUint64()
261251

262-
// If the calculated number of units is 0 then the asset rate
263-
// was not sufficient to represent the value of this payment.
252+
// The purpose of this function is just to print, so let's avoid
253+
// dividing by zero or reporting an invalid msat/unit rate.
264254
if numUnits == 0 {
265-
// We will calculate the minimum amount that can be
266-
// effectively sent with this asset by calculating the
267-
// value of a single asset unit, based on the provided
268-
// asset rate.
269-
270-
// We create the single unit.
271-
unit := rfqmath.FixedPointFromUint64[rfqmath.BigInt](
272-
1, 0,
273-
)
274-
275-
// We derive the minimum amount.
276-
minAmt := rfqmath.UnitsToMilliSatoshi(unit, *rate)
277-
278-
// We return the error to the user.
279-
return nil, fmt.Errorf("smallest payment with asset "+
280-
"rate %v is %v, cannot send %v",
281-
rate.ToUint64(), minAmt, amountMsat)
255+
return nil
282256
}
283257

284258
msatPerUnit := uint64(w.amountMsat) / numUnits
285259

286260
fmt.Printf("Got quote for %v asset units at %v msat/unit from "+
287-
"peer %s with SCID %d\n", numUnits, msatPerUnit,
261+
" peer %s with SCID %d\n", numUnits, msatPerUnit,
288262
quote.Peer, quote.Scid)
289263

290-
resp, err = w.stream.Recv()
264+
return nil
265+
}
266+
267+
// A boolean to indicate whether the first quote was printed via the
268+
// legacy single-rfq response field.
269+
legacyFirstPrint := false
270+
271+
for {
272+
resp, err := w.stream.Recv()
291273
if err != nil {
292274
return nil, err
293275
}
294276

295-
if resp == nil || resp.Result == nil ||
296-
resp.GetPaymentResult() == nil {
277+
res := resp.Result
297278

298-
return nil, errors.New("unexpected nil result")
299-
}
279+
switch r := res.(type) {
280+
case *tchrpc.SendPaymentResponse_AcceptedSellOrder:
281+
err := printQuote(r.AcceptedSellOrder)
282+
if err != nil {
283+
return nil, err
284+
}
300285

301-
return resp.GetPaymentResult(), nil
286+
legacyFirstPrint = true
302287

303-
case *tchrpc.SendPaymentResponse_PaymentResult:
304-
return r.PaymentResult, nil
288+
case *tchrpc.SendPaymentResponse_AcceptedSellOrders:
289+
quotes := r.AcceptedSellOrders.AcceptedSellOrders
305290

306-
default:
307-
return nil, fmt.Errorf("unexpected response type: %T", r)
291+
for _, quote := range quotes {
292+
// If the first item was returned via the legacy
293+
// field then skip printing it again here. This
294+
// skip only applies to the first element.
295+
if legacyFirstPrint {
296+
legacyFirstPrint = false
297+
continue
298+
}
299+
300+
err := printQuote(quote)
301+
if err != nil {
302+
return nil, err
303+
}
304+
}
305+
306+
case *tchrpc.SendPaymentResponse_PaymentResult:
307+
return r.PaymentResult, nil
308+
309+
default:
310+
return nil, fmt.Errorf("unexpected response type: %T",
311+
r)
312+
}
308313
}
309314
}
310315

0 commit comments

Comments
 (0)