5252			AllTypes : true ,
5353		},
5454	}
55+ 
56+ 	groupBalancesByAssetID  =  & taprpc.ListBalancesRequest_AssetId {
57+ 		AssetId : true ,
58+ 	}
59+ 
60+ 	groupBalancesByGroupKey  =  & taprpc.ListBalancesRequest_GroupKey {
61+ 		GroupKey : true ,
62+ 	}
5563)
5664
5765// tapClient is an interface that covers all currently available RPC interfaces 
@@ -2010,7 +2018,7 @@ func AssertGenesisOutput(t *testing.T, output *taprpc.ManagedUtxo,
20102018	require .Equal (t , expectedMerkleRoot [:], output .MerkleRoot )
20112019}
20122020
2013- func  AssertAssetBalances (t  * testing.T , client  taprpc.TaprootAssetsClient ,
2021+ func  AssertMintedAssetBalances (t  * testing.T , client  taprpc.TaprootAssetsClient ,
20142022	simpleAssets , issuableAssets  []* taprpc.Asset , includeLeased  bool ) {
20152023
20162024	t .Helper ()
@@ -2021,12 +2029,9 @@ func AssertAssetBalances(t *testing.T, client taprpc.TaprootAssetsClient,
20212029
20222030	// First, we'll ensure that we're able to get the balances of all the 
20232031	// assets grouped by their asset IDs. 
2024- 	balanceReq  :=  & taprpc.ListBalancesRequest_AssetId {
2025- 		AssetId : true ,
2026- 	}
20272032	assetIDBalances , err  :=  client .ListBalances (
20282033		ctxt , & taprpc.ListBalancesRequest {
2029- 			GroupBy :       balanceReq ,
2034+ 			GroupBy :       groupBalancesByAssetID ,
20302035			IncludeLeased : includeLeased ,
20312036		},
20322037	)
@@ -2067,20 +2072,17 @@ func AssertAssetBalances(t *testing.T, client taprpc.TaprootAssetsClient,
20672072	require .NoError (t , err )
20682073
20692074	var  totalAssetListBalance  uint64 
2070- 	for  _ , asset  :=  range  assetList .Assets  {
2071- 		totalAssetListBalance  +=  asset .Amount 
2075+ 	for  _ , a  :=  range  assetList .Assets  {
2076+ 		totalAssetListBalance  +=  a .Amount 
20722077	}
20732078
20742079	require .Equal (t , totalBalance , totalAssetListBalance )
20752080
20762081	// We'll also ensure that we're able to get the balance by key group 
20772082	// for all the assets that have one specified. 
2078- 	groupBalanceReq  :=  & taprpc.ListBalancesRequest_GroupKey {
2079- 		GroupKey : true ,
2080- 	}
20812083	assetGroupBalances , err  :=  client .ListBalances (
20822084		ctxt , & taprpc.ListBalancesRequest {
2083- 			GroupBy : groupBalanceReq ,
2085+ 			GroupBy : groupBalancesByGroupKey ,
20842086		},
20852087	)
20862088	require .NoError (t , err )
@@ -2089,19 +2091,274 @@ func AssertAssetBalances(t *testing.T, client taprpc.TaprootAssetsClient,
20892091		t , len (issuableAssets ),
20902092		len (assetGroupBalances .AssetGroupBalances ),
20912093	)
2094+ }
20922095
2093- 	for  _ , balance  :=  range  assetGroupBalances .AssetBalances  {
2094- 		for  _ , rpcAsset  :=  range  issuableAssets  {
2095- 			if  balance .AssetGenesis .Name  ==  rpcAsset .AssetGenesis .Name  {
2096- 				require .Equal (
2097- 					t , balance .Balance , rpcAsset .Amount ,
2098- 				)
2099- 				require .Equal (
2100- 					t , balance .AssetGenesis ,
2101- 					rpcAsset .AssetGenesis ,
2102- 				)
2096+ type  balanceConfig  struct  {
2097+ 	assetID              []byte 
2098+ 	groupKey             []byte 
2099+ 	groupedAssetBalance  uint64 
2100+ 	numAssetUtxos        uint32 
2101+ 	numAnchorUtxos       uint32 
2102+ 	includeLeased        bool 
2103+ 	allScriptKeyTypes    bool 
2104+ 	scriptKeyType        * asset.ScriptKeyType 
2105+ }
2106+ 
2107+ type  BalanceOption  func (* balanceConfig )
2108+ 
2109+ func  WithAssetID (assetID  []byte ) BalanceOption  {
2110+ 	return  func (c  * balanceConfig ) {
2111+ 		c .assetID  =  assetID 
2112+ 	}
2113+ }
2114+ 
2115+ func  WithGroupKey (groupKey  []byte ) BalanceOption  {
2116+ 	return  func (c  * balanceConfig ) {
2117+ 		c .groupKey  =  groupKey 
2118+ 	}
2119+ }
2120+ 
2121+ func  WithGroupedAssetBalance (groupedAssetBalance  uint64 ) BalanceOption  {
2122+ 	return  func (c  * balanceConfig ) {
2123+ 		c .groupedAssetBalance  =  groupedAssetBalance 
2124+ 	}
2125+ }
2126+ 
2127+ func  WithNumUtxos (numAssetUtxos  uint32 ) BalanceOption  {
2128+ 	return  func (c  * balanceConfig ) {
2129+ 		c .numAssetUtxos  =  numAssetUtxos 
2130+ 	}
2131+ }
2132+ 
2133+ func  WithNumAnchorUtxos (numAnchorUtxos  uint32 ) BalanceOption  {
2134+ 	return  func (c  * balanceConfig ) {
2135+ 		c .numAnchorUtxos  =  numAnchorUtxos 
2136+ 	}
2137+ }
2138+ 
2139+ func  WithIncludeLeased () BalanceOption  {
2140+ 	return  func (c  * balanceConfig ) {
2141+ 		c .includeLeased  =  true 
2142+ 	}
2143+ }
2144+ 
2145+ func  WithAllScriptKeyTypes () BalanceOption  {
2146+ 	return  func (c  * balanceConfig ) {
2147+ 		c .allScriptKeyTypes  =  true 
2148+ 	}
2149+ }
2150+ 
2151+ func  WithScriptKeyType (scriptKeyType  asset.ScriptKeyType ) BalanceOption  {
2152+ 	return  func (c  * balanceConfig ) {
2153+ 		c .scriptKeyType  =  & scriptKeyType 
2154+ 	}
2155+ }
2156+ 
2157+ func  AssertBalances (t  * testing.T , client  taprpc.TaprootAssetsClient ,
2158+ 	balance  uint64 , opts  ... BalanceOption ) {
2159+ 
2160+ 	t .Helper ()
2161+ 
2162+ 	config  :=  & balanceConfig {}
2163+ 	for  _ , opt  :=  range  opts  {
2164+ 		opt (config )
2165+ 	}
2166+ 
2167+ 	var  rpcTypeQuery  * taprpc.ScriptKeyTypeQuery 
2168+ 	switch  {
2169+ 	case  config .allScriptKeyTypes :
2170+ 		rpcTypeQuery  =  & taprpc.ScriptKeyTypeQuery {
2171+ 			Type : & taprpc.ScriptKeyTypeQuery_AllTypes {
2172+ 				AllTypes : true ,
2173+ 			},
2174+ 		}
2175+ 
2176+ 	case  config .scriptKeyType  !=  nil :
2177+ 		rpcTypeQuery  =  & taprpc.ScriptKeyTypeQuery {
2178+ 			Type : & taprpc.ScriptKeyTypeQuery_ExplicitType {
2179+ 				ExplicitType : taprpc .MarshalScriptKeyType (
2180+ 					* config .scriptKeyType ,
2181+ 				),
2182+ 			},
2183+ 		}
2184+ 	}
2185+ 
2186+ 	balanceSum  :=  func (resp  * taprpc.ListBalancesResponse ,
2187+ 		group  bool ) uint64  {
2188+ 
2189+ 		var  totalBalance  uint64 
2190+ 
2191+ 		if  group  {
2192+ 			for  _ , currentBalance  :=  range  resp .AssetGroupBalances  {
2193+ 				totalBalance  +=  currentBalance .Balance 
2194+ 			}
2195+ 		} else  {
2196+ 			for  _ , currentBalance  :=  range  resp .AssetBalances  {
2197+ 				totalBalance  +=  currentBalance .Balance 
2198+ 			}
2199+ 		}
2200+ 
2201+ 		return  totalBalance 
2202+ 	}
2203+ 
2204+ 	ctxb  :=  context .Background ()
2205+ 	ctxt , cancel  :=  context .WithTimeout (ctxb , defaultWaitTimeout )
2206+ 	defer  cancel ()
2207+ 
2208+ 	// First, we'll ensure that we're able to get the balances of all the 
2209+ 	// assets grouped by their asset IDs. 
2210+ 	assetIDBalances , err  :=  client .ListBalances (
2211+ 		ctxt , & taprpc.ListBalancesRequest {
2212+ 			GroupBy :        groupBalancesByAssetID ,
2213+ 			IncludeLeased :  config .includeLeased ,
2214+ 			ScriptKeyType :  rpcTypeQuery ,
2215+ 			AssetFilter :    config .assetID ,
2216+ 			GroupKeyFilter : config .groupKey ,
2217+ 		},
2218+ 	)
2219+ 	require .NoError (t , err )
2220+ 
2221+ 	// Spent assets (burns/tombstones) are never included in the balance, 
2222+ 	// even if we specifically query for their type. So we skip the balance 
2223+ 	// check in that case. 
2224+ 	checkBalance  :=  config .scriptKeyType  ==  nil  || 
2225+ 		(* config .scriptKeyType  !=  asset .ScriptKeyBurn  && 
2226+ 			* config .scriptKeyType  !=  asset .ScriptKeyTombstone )
2227+ 	if  checkBalance  {
2228+ 		require .Equal (
2229+ 			t , balance , balanceSum (assetIDBalances , false ),
2230+ 			"asset balance, wanted %d, got: %v" , balance ,
2231+ 			toJSON (t , assetIDBalances ),
2232+ 		)
2233+ 	}
2234+ 
2235+ 	// Next, we do the same but grouped by group keys (if requested, since 
2236+ 	// this only returns the balances for actually grouped assets). 
2237+ 	if  config .groupedAssetBalance  >  0  {
2238+ 		assetGroupBalances , err  :=  client .ListBalances (
2239+ 			ctxt , & taprpc.ListBalancesRequest {
2240+ 				GroupBy :        groupBalancesByGroupKey ,
2241+ 				IncludeLeased :  config .includeLeased ,
2242+ 				ScriptKeyType :  rpcTypeQuery ,
2243+ 				AssetFilter :    config .assetID ,
2244+ 				GroupKeyFilter : config .groupKey ,
2245+ 			},
2246+ 		)
2247+ 		require .NoError (t , err )
2248+ 
2249+ 		// Spent assets (burns/tombstones) are never included in the 
2250+ 		// balance, even if we specifically query for their type. So we 
2251+ 		// skip the balance check in that case. 
2252+ 		if  checkBalance  {
2253+ 			require .Equalf (
2254+ 				t , config .groupedAssetBalance ,
2255+ 				balanceSum (assetGroupBalances , true ),
2256+ 				"grouped balance, wanted %d, got: %v" , balance ,
2257+ 				toJSON (t , assetGroupBalances ),
2258+ 			)
2259+ 		}
2260+ 	}
2261+ 
2262+ 	// Finally, we assert that the sum of all assets queried with the given 
2263+ 	// query parameters matches the expected balance. 
2264+ 	assetList , err  :=  client .ListAssets (ctxt , & taprpc.ListAssetRequest {
2265+ 		IncludeLeased : config .includeLeased ,
2266+ 		ScriptKeyType : rpcTypeQuery ,
2267+ 	})
2268+ 	require .NoError (t , err )
2269+ 
2270+ 	var  (
2271+ 		totalBalance  uint64 
2272+ 		numUtxos      uint32 
2273+ 	)
2274+ 	for  _ , a  :=  range  assetList .Assets  {
2275+ 		if  len (config .assetID ) >  0  {
2276+ 			if  ! bytes .Equal (
2277+ 				a .AssetGenesis .AssetId , config .assetID ,
2278+ 			) {
2279+ 
2280+ 				continue 
2281+ 			}
2282+ 		}
2283+ 
2284+ 		if  len (config .groupKey ) >  0  {
2285+ 			if  ! bytes .Equal (
2286+ 				a .AssetGroup .TweakedGroupKey , config .groupKey ,
2287+ 			) {
2288+ 
2289+ 				continue 
21032290			}
21042291		}
2292+ 
2293+ 		totalBalance  +=  a .Amount 
2294+ 		numUtxos ++ 
2295+ 	}
2296+ 	require .Equalf (
2297+ 		t , balance , totalBalance , "ListAssets balance, wanted %d, " + 
2298+ 			"got: %v" , balance , toJSON (t , assetList ),
2299+ 	)
2300+ 
2301+ 	// The number of UTXOs means asset outputs in this case. We check the 
2302+ 	// BTC-level UTXOs below as well, but that's just to make sure the 
2303+ 	// output of that RPC lists the same assets. 
2304+ 	if  config .numAssetUtxos  >  0  {
2305+ 		require .Equal (
2306+ 			t , config .numAssetUtxos , numUtxos , "ListAssets num " + 
2307+ 				"asset utxos" ,
2308+ 		)
2309+ 	}
2310+ 
2311+ 	utxoList , err  :=  client .ListUtxos (ctxt , & taprpc.ListUtxosRequest {
2312+ 		IncludeLeased : config .includeLeased ,
2313+ 		ScriptKeyType : rpcTypeQuery ,
2314+ 	})
2315+ 	require .NoError (t , err )
2316+ 
2317+ 	// Make sure the ListUtxos call returns the same number of (asset) UTXOs 
2318+ 	// as the ListAssets call. 
2319+ 	var  numAnchorUtxos  uint32 
2320+ 	totalBalance  =  0 
2321+ 	numUtxos  =  0 
2322+ 	for  _ , btcUtxo  :=  range  utxoList .ManagedUtxos  {
2323+ 		numAnchorUtxos ++ 
2324+ 		for  _ , assetUtxo  :=  range  btcUtxo .Assets  {
2325+ 			if  len (config .assetID ) >  0  {
2326+ 				if  ! bytes .Equal (
2327+ 					assetUtxo .AssetGenesis .AssetId ,
2328+ 					config .assetID ,
2329+ 				) {
2330+ 
2331+ 					continue 
2332+ 				}
2333+ 			}
2334+ 
2335+ 			if  len (config .groupKey ) >  0  {
2336+ 				if  ! bytes .Equal (
2337+ 					btcUtxo .TaprootAssetRoot ,
2338+ 					config .groupKey ,
2339+ 				) {
2340+ 
2341+ 					continue 
2342+ 				}
2343+ 			}
2344+ 
2345+ 			totalBalance  +=  assetUtxo .Amount 
2346+ 			numUtxos ++ 
2347+ 		}
2348+ 	}
2349+ 	require .Equal (t , balance , totalBalance , "ListUtxos balance" )
2350+ 
2351+ 	if  config .numAnchorUtxos  >  0  {
2352+ 		require .Equal (
2353+ 			t , config .numAnchorUtxos , numAnchorUtxos , "num anchor " + 
2354+ 				"utxos" ,
2355+ 		)
2356+ 	}
2357+ 	if  config .numAssetUtxos  >  0  {
2358+ 		require .Equal (
2359+ 			t , config .numAssetUtxos , numUtxos , "ListUtxos num " + 
2360+ 				"asset utxos" ,
2361+ 		)
21052362	}
21062363}
21072364
0 commit comments