52
52
AllTypes : true ,
53
53
},
54
54
}
55
+
56
+ groupBalancesByAssetID = & taprpc.ListBalancesRequest_AssetId {
57
+ AssetId : true ,
58
+ }
59
+
60
+ groupBalancesByGroupKey = & taprpc.ListBalancesRequest_GroupKey {
61
+ GroupKey : true ,
62
+ }
55
63
)
56
64
57
65
// tapClient is an interface that covers all currently available RPC interfaces
@@ -1988,7 +1996,7 @@ func AssertGenesisOutput(t *testing.T, output *taprpc.ManagedUtxo,
1988
1996
require .Equal (t , expectedMerkleRoot [:], output .MerkleRoot )
1989
1997
}
1990
1998
1991
- func AssertAssetBalances (t * testing.T , client taprpc.TaprootAssetsClient ,
1999
+ func AssertMintedAssetBalances (t * testing.T , client taprpc.TaprootAssetsClient ,
1992
2000
simpleAssets , issuableAssets []* taprpc.Asset , includeLeased bool ) {
1993
2001
1994
2002
t .Helper ()
@@ -1999,12 +2007,9 @@ func AssertAssetBalances(t *testing.T, client taprpc.TaprootAssetsClient,
1999
2007
2000
2008
// First, we'll ensure that we're able to get the balances of all the
2001
2009
// assets grouped by their asset IDs.
2002
- balanceReq := & taprpc.ListBalancesRequest_AssetId {
2003
- AssetId : true ,
2004
- }
2005
2010
assetIDBalances , err := client .ListBalances (
2006
2011
ctxt , & taprpc.ListBalancesRequest {
2007
- GroupBy : balanceReq ,
2012
+ GroupBy : groupBalancesByAssetID ,
2008
2013
IncludeLeased : includeLeased ,
2009
2014
},
2010
2015
)
@@ -2045,20 +2050,17 @@ func AssertAssetBalances(t *testing.T, client taprpc.TaprootAssetsClient,
2045
2050
require .NoError (t , err )
2046
2051
2047
2052
var totalAssetListBalance uint64
2048
- for _ , asset := range assetList .Assets {
2049
- totalAssetListBalance += asset .Amount
2053
+ for _ , a := range assetList .Assets {
2054
+ totalAssetListBalance += a .Amount
2050
2055
}
2051
2056
2052
2057
require .Equal (t , totalBalance , totalAssetListBalance )
2053
2058
2054
2059
// We'll also ensure that we're able to get the balance by key group
2055
2060
// for all the assets that have one specified.
2056
- groupBalanceReq := & taprpc.ListBalancesRequest_GroupKey {
2057
- GroupKey : true ,
2058
- }
2059
2061
assetGroupBalances , err := client .ListBalances (
2060
2062
ctxt , & taprpc.ListBalancesRequest {
2061
- GroupBy : groupBalanceReq ,
2063
+ GroupBy : groupBalancesByGroupKey ,
2062
2064
},
2063
2065
)
2064
2066
require .NoError (t , err )
@@ -2067,19 +2069,274 @@ func AssertAssetBalances(t *testing.T, client taprpc.TaprootAssetsClient,
2067
2069
t , len (issuableAssets ),
2068
2070
len (assetGroupBalances .AssetGroupBalances ),
2069
2071
)
2072
+ }
2070
2073
2071
- for _ , balance := range assetGroupBalances .AssetBalances {
2072
- for _ , rpcAsset := range issuableAssets {
2073
- if balance .AssetGenesis .Name == rpcAsset .AssetGenesis .Name {
2074
- require .Equal (
2075
- t , balance .Balance , rpcAsset .Amount ,
2076
- )
2077
- require .Equal (
2078
- t , balance .AssetGenesis ,
2079
- rpcAsset .AssetGenesis ,
2080
- )
2074
+ type balanceConfig struct {
2075
+ assetID []byte
2076
+ groupKey []byte
2077
+ groupedAssetBalance uint64
2078
+ numAssetUtxos uint32
2079
+ numAnchorUtxos uint32
2080
+ includeLeased bool
2081
+ allScriptKeyTypes bool
2082
+ scriptKeyType * asset.ScriptKeyType
2083
+ }
2084
+
2085
+ type BalanceOption func (* balanceConfig )
2086
+
2087
+ func WithAssetID (assetID []byte ) BalanceOption {
2088
+ return func (c * balanceConfig ) {
2089
+ c .assetID = assetID
2090
+ }
2091
+ }
2092
+
2093
+ func WithGroupKey (groupKey []byte ) BalanceOption {
2094
+ return func (c * balanceConfig ) {
2095
+ c .groupKey = groupKey
2096
+ }
2097
+ }
2098
+
2099
+ func WithGroupedAssetBalance (groupedAssetBalance uint64 ) BalanceOption {
2100
+ return func (c * balanceConfig ) {
2101
+ c .groupedAssetBalance = groupedAssetBalance
2102
+ }
2103
+ }
2104
+
2105
+ func WithNumUtxos (numAssetUtxos uint32 ) BalanceOption {
2106
+ return func (c * balanceConfig ) {
2107
+ c .numAssetUtxos = numAssetUtxos
2108
+ }
2109
+ }
2110
+
2111
+ func WithNumAnchorUtxos (numAnchorUtxos uint32 ) BalanceOption {
2112
+ return func (c * balanceConfig ) {
2113
+ c .numAnchorUtxos = numAnchorUtxos
2114
+ }
2115
+ }
2116
+
2117
+ func WithIncludeLeased () BalanceOption {
2118
+ return func (c * balanceConfig ) {
2119
+ c .includeLeased = true
2120
+ }
2121
+ }
2122
+
2123
+ func WithAllScriptKeyTypes () BalanceOption {
2124
+ return func (c * balanceConfig ) {
2125
+ c .allScriptKeyTypes = true
2126
+ }
2127
+ }
2128
+
2129
+ func WithScriptKeyType (scriptKeyType asset.ScriptKeyType ) BalanceOption {
2130
+ return func (c * balanceConfig ) {
2131
+ c .scriptKeyType = & scriptKeyType
2132
+ }
2133
+ }
2134
+
2135
+ func AssertBalances (t * testing.T , client taprpc.TaprootAssetsClient ,
2136
+ balance uint64 , opts ... BalanceOption ) {
2137
+
2138
+ t .Helper ()
2139
+
2140
+ config := & balanceConfig {}
2141
+ for _ , opt := range opts {
2142
+ opt (config )
2143
+ }
2144
+
2145
+ var rpcTypeQuery * taprpc.ScriptKeyTypeQuery
2146
+ switch {
2147
+ case config .allScriptKeyTypes :
2148
+ rpcTypeQuery = & taprpc.ScriptKeyTypeQuery {
2149
+ Type : & taprpc.ScriptKeyTypeQuery_AllTypes {
2150
+ AllTypes : true ,
2151
+ },
2152
+ }
2153
+
2154
+ case config .scriptKeyType != nil :
2155
+ rpcTypeQuery = & taprpc.ScriptKeyTypeQuery {
2156
+ Type : & taprpc.ScriptKeyTypeQuery_ExplicitType {
2157
+ ExplicitType : taprpc .MarshalScriptKeyType (
2158
+ * config .scriptKeyType ,
2159
+ ),
2160
+ },
2161
+ }
2162
+ }
2163
+
2164
+ balanceSum := func (resp * taprpc.ListBalancesResponse ,
2165
+ group bool ) uint64 {
2166
+
2167
+ var totalBalance uint64
2168
+
2169
+ if group {
2170
+ for _ , currentBalance := range resp .AssetGroupBalances {
2171
+ totalBalance += currentBalance .Balance
2172
+ }
2173
+ } else {
2174
+ for _ , currentBalance := range resp .AssetBalances {
2175
+ totalBalance += currentBalance .Balance
2176
+ }
2177
+ }
2178
+
2179
+ return totalBalance
2180
+ }
2181
+
2182
+ ctxb := context .Background ()
2183
+ ctxt , cancel := context .WithTimeout (ctxb , defaultWaitTimeout )
2184
+ defer cancel ()
2185
+
2186
+ // First, we'll ensure that we're able to get the balances of all the
2187
+ // assets grouped by their asset IDs.
2188
+ assetIDBalances , err := client .ListBalances (
2189
+ ctxt , & taprpc.ListBalancesRequest {
2190
+ GroupBy : groupBalancesByAssetID ,
2191
+ IncludeLeased : config .includeLeased ,
2192
+ ScriptKeyType : rpcTypeQuery ,
2193
+ AssetFilter : config .assetID ,
2194
+ GroupKeyFilter : config .groupKey ,
2195
+ },
2196
+ )
2197
+ require .NoError (t , err )
2198
+
2199
+ // Spent assets (burns/tombstones) are never included in the balance,
2200
+ // even if we specifically query for their type. So we skip the balance
2201
+ // check in that case.
2202
+ checkBalance := config .scriptKeyType == nil ||
2203
+ (* config .scriptKeyType != asset .ScriptKeyBurn &&
2204
+ * config .scriptKeyType != asset .ScriptKeyTombstone )
2205
+ if checkBalance {
2206
+ require .Equal (
2207
+ t , balance , balanceSum (assetIDBalances , false ),
2208
+ "asset balance, wanted %d, got: %v" , balance ,
2209
+ toJSON (t , assetIDBalances ),
2210
+ )
2211
+ }
2212
+
2213
+ // Next, we do the same but grouped by group keys (if requested, since
2214
+ // this only returns the balances for actually grouped assets).
2215
+ if config .groupedAssetBalance > 0 {
2216
+ assetGroupBalances , err := client .ListBalances (
2217
+ ctxt , & taprpc.ListBalancesRequest {
2218
+ GroupBy : groupBalancesByGroupKey ,
2219
+ IncludeLeased : config .includeLeased ,
2220
+ ScriptKeyType : rpcTypeQuery ,
2221
+ AssetFilter : config .assetID ,
2222
+ GroupKeyFilter : config .groupKey ,
2223
+ },
2224
+ )
2225
+ require .NoError (t , err )
2226
+
2227
+ // Spent assets (burns/tombstones) are never included in the
2228
+ // balance, even if we specifically query for their type. So we
2229
+ // skip the balance check in that case.
2230
+ if checkBalance {
2231
+ require .Equalf (
2232
+ t , config .groupedAssetBalance ,
2233
+ balanceSum (assetGroupBalances , true ), "grouped " +
2234
+ "balance, wanted %d, got: %v" , balance ,
2235
+ toJSON (t , assetGroupBalances ),
2236
+ )
2237
+ }
2238
+ }
2239
+
2240
+ // Finally, we assert that the sum of all assets queried with the given
2241
+ // query parameters matches the expected balance.
2242
+ assetList , err := client .ListAssets (ctxt , & taprpc.ListAssetRequest {
2243
+ IncludeLeased : config .includeLeased ,
2244
+ ScriptKeyType : rpcTypeQuery ,
2245
+ })
2246
+ require .NoError (t , err )
2247
+
2248
+ var (
2249
+ totalBalance uint64
2250
+ numUtxos uint32
2251
+ )
2252
+ for _ , a := range assetList .Assets {
2253
+ if len (config .assetID ) > 0 {
2254
+ if ! bytes .Equal (
2255
+ a .AssetGenesis .AssetId , config .assetID ,
2256
+ ) {
2257
+
2258
+ continue
2081
2259
}
2082
2260
}
2261
+
2262
+ if len (config .groupKey ) > 0 {
2263
+ if ! bytes .Equal (
2264
+ a .AssetGroup .TweakedGroupKey , config .groupKey ,
2265
+ ) {
2266
+
2267
+ continue
2268
+ }
2269
+ }
2270
+
2271
+ totalBalance += a .Amount
2272
+ numUtxos ++
2273
+ }
2274
+ require .Equalf (
2275
+ t , balance , totalBalance , "ListAssets balance, wanted %d, " +
2276
+ "got: %v" , balance , toJSON (t , assetList ),
2277
+ )
2278
+
2279
+ // The number of UTXOs means asset outputs in this case. We check the
2280
+ // BTC-level UTXOs below as well, but that's just to make sure the
2281
+ // output of that RPC lists the same assets.
2282
+ if config .numAssetUtxos > 0 {
2283
+ require .Equal (
2284
+ t , config .numAssetUtxos , numUtxos , "ListAssets num " +
2285
+ "asset utxos" ,
2286
+ )
2287
+ }
2288
+
2289
+ utxoList , err := client .ListUtxos (ctxt , & taprpc.ListUtxosRequest {
2290
+ IncludeLeased : config .includeLeased ,
2291
+ ScriptKeyType : rpcTypeQuery ,
2292
+ })
2293
+ require .NoError (t , err )
2294
+
2295
+ // Make sure the ListUtxos call returns the same number of (asset) UTXOs
2296
+ // as the ListAssets call.
2297
+ var numAnchorUtxos uint32
2298
+ totalBalance = 0
2299
+ numUtxos = 0
2300
+ for _ , btcUtxo := range utxoList .ManagedUtxos {
2301
+ numAnchorUtxos ++
2302
+ for _ , assetUtxo := range btcUtxo .Assets {
2303
+ if len (config .assetID ) > 0 {
2304
+ if ! bytes .Equal (
2305
+ assetUtxo .AssetGenesis .AssetId ,
2306
+ config .assetID ,
2307
+ ) {
2308
+
2309
+ continue
2310
+ }
2311
+ }
2312
+
2313
+ if len (config .groupKey ) > 0 {
2314
+ if ! bytes .Equal (
2315
+ btcUtxo .TaprootAssetRoot ,
2316
+ config .groupKey ,
2317
+ ) {
2318
+
2319
+ continue
2320
+ }
2321
+ }
2322
+
2323
+ totalBalance += assetUtxo .Amount
2324
+ numUtxos ++
2325
+ }
2326
+ }
2327
+ require .Equal (t , balance , totalBalance , "ListUtxos balance" )
2328
+
2329
+ if config .numAnchorUtxos > 0 {
2330
+ require .Equal (
2331
+ t , config .numAnchorUtxos , numAnchorUtxos , "num anchor " +
2332
+ "utxos" ,
2333
+ )
2334
+ }
2335
+ if config .numAssetUtxos > 0 {
2336
+ require .Equal (
2337
+ t , config .numAssetUtxos , numUtxos , "ListUtxos num " +
2338
+ "asset utxos" ,
2339
+ )
2083
2340
}
2084
2341
}
2085
2342
0 commit comments