diff --git a/docs/source/interface.rst b/docs/source/interface.rst index 81435b1f0c9267cb42561ffcf1844afd9d1eb197..d3223d6fe60e9a9af9a009050a8a2b181816fe9d 100644 --- a/docs/source/interface.rst +++ b/docs/source/interface.rst @@ -154,12 +154,14 @@ This endpoint accepts no request body. The response is **OK** with ``application/json`` content-type response body like:: { "total": <integer> + , "spendable": <integer> , "unblinded-tokens": [<unblinded token string>, ...] , "lease-maintenance-spending": <spending object> } The value associated with ``total`` gives the total number of unblinded tokens in the node's database (independent of any limit placed on this query). +The value associated with ``spendable`` gives the number of unblinded tokens in the node's database which can actually be spent. The value associated with ``unblinded-tokens`` gives the requested list of unblinded tokens. The ``<spending object>`` may be ``null`` if the lease maintenance process has never run. diff --git a/src/_zkapauthorizer/resource.py b/src/_zkapauthorizer/resource.py index e675ed204ad829444b6ad9d0818e2a1b09073e32..1663b0c291d030e16614f894e54104f0a4dc73fe 100644 --- a/src/_zkapauthorizer/resource.py +++ b/src/_zkapauthorizer/resource.py @@ -370,6 +370,7 @@ class _UnblindedTokenCollection(Resource): return dumps({ u"total": len(unblinded_tokens), + u"spendable": self._store.count_unblinded_tokens(), u"unblinded-tokens": list(islice(( token for token diff --git a/src/_zkapauthorizer/tests/test_client_resource.py b/src/_zkapauthorizer/tests/test_client_resource.py index 5bee598c5c935b48ce61c1ce09669ee39daf2d44..09e1bf0f527bc7b80ebda5143f8097c8e48334b3 100644 --- a/src/_zkapauthorizer/tests/test_client_resource.py +++ b/src/_zkapauthorizer/tests/test_client_resource.py @@ -762,6 +762,7 @@ class UnblindedTokenTests(TestCase): requesting, succeeded_with_unblinded_tokens_with_matcher( num_tokens, + Equals(num_tokens), AllMatch( MatchesAll( GreaterThan(position), @@ -896,6 +897,7 @@ class UnblindedTokenTests(TestCase): def succeeded_with_unblinded_tokens_with_matcher( all_token_count, + match_spendable_token_count, match_unblinded_tokens, match_lease_maint_spending, ): @@ -920,6 +922,7 @@ def succeeded_with_unblinded_tokens_with_matcher( succeeded( ContainsDict({ u"total": Equals(all_token_count), + u"spendable": match_spendable_token_count, u"unblinded-tokens": match_unblinded_tokens, u"lease-maintenance-spending": match_lease_maint_spending, }), @@ -941,11 +944,12 @@ def succeeded_with_unblinded_tokens(all_token_count, returned_token_count): """ return succeeded_with_unblinded_tokens_with_matcher( all_token_count, - MatchesAll( + match_spendable_token_count=Equals(all_token_count), + match_unblinded_tokens=MatchesAll( HasLength(returned_token_count), AllMatch(IsInstance(unicode)), ), - matches_lease_maintenance_spending(), + match_lease_maint_spending=matches_lease_maintenance_spending(), ) def matches_lease_maintenance_spending():