@@ -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.
239238func (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