@@ -2009,6 +2009,136 @@ func assetExists(t *testing.T, client *tapClient, assetID []byte,
20092009 "found in list, got: %v" , amount , toProtoJSON (t , resp ))
20102010}
20112011
2012+ func getAssetFromAssetList (assets []rfqmsg.JsonAssetChanInfo ,
2013+ assetID []byte ) rfqmsg.JsonAssetChanInfo {
2014+ for _ , asset := range assets {
2015+ if asset .AssetInfo .AssetGenesis .AssetID == hex .EncodeToString (assetID ) {
2016+ return asset
2017+ }
2018+ }
2019+ return rfqmsg.JsonAssetChanInfo {}
2020+ }
2021+
2022+ // use printChannels to print balances along a specified route.
2023+ // This function is better than logBalance because it shows only the channels
2024+ // that participate in the route so that you can distinguish between balances
2025+ // in channels that are with nodes that aren't participating in the route.
2026+ func printExpectedRoute (t * testing.T , route []* HarnessNode , satsToSend uint64 ,
2027+ assetsToSend uint64 , assetID []byte , title string ) {
2028+ expectedRouteNames := make ([]string , 0 )
2029+ for _ , node := range route {
2030+ expectedRouteNames = append (expectedRouteNames , node .Cfg .Name )
2031+ }
2032+ t .Logf ("actual channel capacities (" + title + "):" )
2033+ t .Logf ("expected route: %v" , expectedRouteNames )
2034+ for i := 0 ; i < len (route )- 1 ; i ++ {
2035+ printChannels (t , route [i ], route [i + 1 ], satsToSend , assetsToSend ,
2036+ assetID )
2037+ }
2038+ }
2039+
2040+ // Print channel sat and asset (if defined) balances between two nodes taking
2041+ // into account the channel reserve.
2042+ // Check (shows (✔) or (x) )to see if satsToSend and assetsToSend are available
2043+ // to send/forward in the channel (if non-zero).
2044+ // Check to see if the channel is active (A) or inactive (I).
2045+ func printChannels (t * testing.T , node * HarnessNode , peer * HarnessNode ,
2046+ satsToSend uint64 , assetsToSend uint64 , assetID []byte ) {
2047+ ctxb := context .Background ()
2048+ ctxt , cancel := context .WithTimeout (ctxb , defaultTimeout )
2049+ defer cancel ()
2050+
2051+ channelResp , err := node .ListChannels (ctxt , & lnrpc.ListChannelsRequest {
2052+ Peer : peer .PubKey [:],
2053+ })
2054+ require .NoError (t , err )
2055+
2056+ // var targetChan *lnrpc.Channel
2057+ // note: the only field of the response is `channels`
2058+ for _ , channel := range channelResp .Channels {
2059+
2060+ LocalSpendable := uint64 (channel .LocalBalance ) -
2061+ channel .LocalConstraints .ChanReserveSat
2062+ RemoteSpendable := uint64 (channel .RemoteBalance ) -
2063+ channel .RemoteConstraints .ChanReserveSat
2064+
2065+ var state string
2066+ var satsBalanceStatus string
2067+
2068+ // check to see if the channel should have the ability to actually
2069+ // make the sats payment
2070+ if satsToSend == 0 {
2071+ satsBalanceStatus = ""
2072+ } else if LocalSpendable >= satsToSend {
2073+ satsBalanceStatus = "(✔) "
2074+ } else {
2075+ satsBalanceStatus = "(x) "
2076+ }
2077+
2078+ // check if the channel is active or inactive
2079+ // this helps troubleshooting channels that have gone inactive
2080+ // due to mission control putting them in an inactive state due
2081+ // to some previous error.
2082+ if channel .Active {
2083+ state = "A"
2084+ } else {
2085+ state = "I"
2086+ }
2087+
2088+ // now actually print the sats channel details
2089+ t .Logf (satsBalanceStatus + "(" + state + ") cap: %v sat, " +
2090+ node .Cfg .Name + "->[bal: %v sat|res: %v sat|spend: %v sat], " +
2091+ peer .Cfg .Name + "->[bal: %v sat|res: %v sat|spend: %v sat], " +
2092+ "commit_fee: %v" ,
2093+ channel .Capacity ,
2094+ channel .LocalBalance ,
2095+ channel .LocalConstraints .ChanReserveSat ,
2096+ LocalSpendable ,
2097+ channel .RemoteBalance ,
2098+ channel .RemoteConstraints .ChanReserveSat ,
2099+ RemoteSpendable ,
2100+ channel .CommitFee ,
2101+ )
2102+
2103+ // if this channel has data defining an asset in it, read it too
2104+ if len (channel .CustomChannelData ) > 0 {
2105+
2106+ var custom_channel_data rfqmsg.JsonAssetChannel
2107+ err = json .Unmarshal (channel .CustomChannelData ,
2108+ & custom_channel_data )
2109+ require .NoError (t , err )
2110+
2111+ asset := getAssetFromAssetList (custom_channel_data .Assets , assetID )
2112+
2113+ var assetsBalanceStatus string
2114+
2115+ // check to see if the channel should have the ability to actually
2116+ // send the asset payment
2117+ if assetsToSend == 0 {
2118+ assetsBalanceStatus = ""
2119+ } else if asset .LocalBalance >= assetsToSend {
2120+ assetsBalanceStatus = "(✔) "
2121+ } else {
2122+ assetsBalanceStatus = "(x) "
2123+ }
2124+
2125+ // note: taproot assets channels don't currently have a concept of
2126+ // reserve like normal sats channels, so this printout is simpler
2127+ // than the sats channel printed above
2128+ t .Logf (assetsBalanceStatus + "(" + state + ") cap: %v " +
2129+ asset .AssetInfo .AssetGenesis .Name +
2130+ ", " + node .Cfg .Name + "->[bal: %v " +
2131+ asset .AssetInfo .AssetGenesis .Name + "], " +
2132+ peer .Cfg .Name + "->[bal: %v " +
2133+ asset .AssetInfo .AssetGenesis .Name + "]" ,
2134+ asset .Capacity ,
2135+ asset .LocalBalance ,
2136+ asset .RemoteBalance ,
2137+ )
2138+ }
2139+ }
2140+ }
2141+
20122142func logBalance (t * testing.T , nodes []* HarnessNode , assetID []byte ,
20132143 occasion string ) {
20142144
0 commit comments