@@ -6576,8 +6576,9 @@ func (r *rpcServer) checkPeerChannel(ctx context.Context, peer route.Vertex,
65766576 }
65776577
65786578 // If we don't get an error here, it means we do have an asset
6579- // channel with the peer.
6580- _ , err = r .rfqChannel (ctx , assetID , & peer )
6579+ // channel with the peer. The intention doesn't matter as we're
6580+ // just checking whether a channel exists.
6581+ _ , err = r .rfqChannel (ctx , assetID , & peer , NoIntention )
65816582 if err != nil {
65826583 return fmt .Errorf ("error checking asset channel: %w" ,
65836584 err )
@@ -7217,7 +7218,9 @@ func (r *rpcServer) SendPayment(req *tchrpc.SendPaymentRequest,
72177218 }
72187219
72197220 // We can now query the asset channels we have.
7220- assetChan , err := r .rfqChannel (ctx , assetID , peerPubKey )
7221+ assetChan , err := r .rfqChannel (
7222+ ctx , assetID , peerPubKey , SendIntention ,
7223+ )
72217224 if err != nil {
72227225 return fmt .Errorf ("error finding asset channel to " +
72237226 "use: %w" , err )
@@ -7508,7 +7511,9 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
75087511 }
75097512
75107513 // We can now query the asset channels we have.
7511- assetChan , err := r .rfqChannel (ctx , assetID , peerPubKey )
7514+ assetChan , err := r .rfqChannel (
7515+ ctx , assetID , peerPubKey , ReceiveIntention ,
7516+ )
75127517 if err != nil {
75137518 return nil , fmt .Errorf ("error finding asset channel to use: %w" ,
75147519 err )
@@ -7775,12 +7780,30 @@ func (r *rpcServer) DecDisplayForAssetID(ctx context.Context,
77757780 return meta .DecDisplayOption ()
77767781}
77777782
7783+ // chanIntention defines the intention of calling rfqChannel. This helps with
7784+ // returning the channel that is most suitable for what we want to do.
7785+ type chanIntention uint8
7786+
7787+ const (
7788+ // NoIntention defines the absence of any intention, signalling that we
7789+ // don't really care which channel is returned.
7790+ NoIntention chanIntention = iota
7791+
7792+ // SendIntention defines the intention to send over an asset channel.
7793+ SendIntention
7794+
7795+ // ReceiveIntention defines the intention to receive over an asset
7796+ // channel.
7797+ ReceiveIntention
7798+ )
7799+
77787800// rfqChannel returns the channel to use for RFQ operations. If a peer public
77797801// key is specified, the channels are filtered by that peer. If there are
77807802// multiple channels for the same asset, the user must specify the peer public
77817803// key.
77827804func (r * rpcServer ) rfqChannel (ctx context.Context , id asset.ID ,
7783- peerPubKey * route.Vertex ) (* channelWithAsset , error ) {
7805+ peerPubKey * route.Vertex ,
7806+ intention chanIntention ) (* channelWithAsset , error ) {
77847807
77857808 balances , err := r .computeChannelAssetBalance (ctx )
77867809 if err != nil {
@@ -7812,18 +7835,48 @@ func (r *rpcServer) rfqChannel(ctx context.Context, id asset.ID,
78127835 return nil , fmt .Errorf ("multiple asset channels found for " +
78137836 "asset %s, please specify the peer pubkey" , id .String ())
78147837
7838+ // We don't have any channels with that asset ID and peer.
7839+ case len (assetBalances ) == 0 :
7840+ return nil , fmt .Errorf ("no asset channel found for asset %s " +
7841+ "and peer %s" , id .String (), peerPubKey .String ())
7842+ }
7843+
78157844 // If the user specified a peer public key, and we still have multiple
78167845 // channels, it means we have multiple channels with the same asset and
7817- // the same peer. So we just return the first channel.
7818- case len (assetBalances ) >= 1 :
7819- return & assetBalances [0 ], nil
7846+ // the same peer, as we ruled out the rest of the cases above.
78207847
7821- // The default case is: We don't have any channels with that asset ID
7822- // and peer.
7823- default :
7824- return nil , fmt .Errorf ("no asset channel found for asset %s " +
7825- "and peer %s" , id .String (), peerPubKey .String ())
7848+ // Initialize best balance to first channel of the list.
7849+ bestBalance := assetBalances [0 ]
7850+
7851+ switch intention {
7852+ case ReceiveIntention :
7853+ // If the intention is to receive, return the channel
7854+ // with the best remote balance.
7855+ fn .ForEach (assetBalances , func (b channelWithAsset ) {
7856+ if b .assetInfo .RemoteBalance >
7857+ bestBalance .assetInfo .RemoteBalance {
7858+
7859+ bestBalance = b
7860+ }
7861+ })
7862+
7863+ case SendIntention :
7864+ // If the intention is to send, return the channel with
7865+ // the best local balance.
7866+ fn .ForEach (assetBalances , func (b channelWithAsset ) {
7867+ if b .assetInfo .LocalBalance >
7868+ bestBalance .assetInfo .LocalBalance {
7869+
7870+ bestBalance = b
7871+ }
7872+ })
7873+
7874+ case NoIntention :
7875+ // Do nothing. Just return the first element that was
7876+ // assigned above.
78267877 }
7878+
7879+ return & bestBalance , nil
78277880}
78287881
78297882// channelWithAsset is a helper struct that combines the information of a single
0 commit comments