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