diff --git a/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/admin/http/HttpScanHandler.scala b/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/admin/http/HttpScanHandler.scala index f04b4ab196..648fc9db68 100644 --- a/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/admin/http/HttpScanHandler.scala +++ b/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/admin/http/HttpScanHandler.scala @@ -2428,16 +2428,23 @@ class HttpScanHandler( ): Future[ScanResource.GetValidatorFaucetsByValidatorResponse] = { implicit val tc = extracted withSpan(s"$workflowId.getValidatorFaucetsByValidator") { _ => _ => - store - .getValidatorLicenseByValidator(validators.map(v => PartyId.tryFromProtoPrimitive(v))) - .map(licenses => - ScanResource.GetValidatorFaucetsByValidatorResponse.OK( - definitions - .GetValidatorFaucetsByValidatorResponse( - FaucetProcessor.process(licenses) - ) - ) + if (validators.isEmpty) { + Future.successful( + ScanResource.GetValidatorFaucetsByValidatorResponse + .BadRequest(definitions.ErrorResponse("validator_ids must not be empty")) ) + } else { + store + .getValidatorLicenseByValidator(validators.map(v => PartyId.tryFromProtoPrimitive(v))) + .map(licenses => + ScanResource.GetValidatorFaucetsByValidatorResponse.OK( + definitions + .GetValidatorFaucetsByValidatorResponse( + FaucetProcessor.process(licenses) + ) + ) + ) + } } } diff --git a/apps/scan/src/test/scala/org/lfdecentralizedtrust/splice/store/db/ScanStoreTest.scala b/apps/scan/src/test/scala/org/lfdecentralizedtrust/splice/store/db/ScanStoreTest.scala index 220a8d562c..0e3ac01649 100644 --- a/apps/scan/src/test/scala/org/lfdecentralizedtrust/splice/store/db/ScanStoreTest.scala +++ b/apps/scan/src/test/scala/org/lfdecentralizedtrust/splice/store/db/ScanStoreTest.scala @@ -1949,6 +1949,22 @@ class DbScanStoreTest result should not contain charlesValidatorLicense } } + + "return an empty result when given no validators" in { + val alice = userParty(443) + val aliceValidatorLicense = validatorLicense( + alice, + dsoParty, + Some(new FaucetState(new Round(0), new Round(1000L), 0L)) + ) + for { + store <- mkStore() + _ <- dummyDomain.create(aliceValidatorLicense)(store.multiDomainAcsStore) + result <- store.getValidatorLicenseByValidator(Vector.empty) + } yield { + result shouldBe empty + } + } } "Changing the acsStoreDescriptorUserVersion" should { val alice = userParty(443) diff --git a/docs/src/release_notes_upcoming.rst b/docs/src/release_notes_upcoming.rst index c7800786d3..4f29c765d1 100644 --- a/docs/src/release_notes_upcoming.rst +++ b/docs/src/release_notes_upcoming.rst @@ -42,6 +42,9 @@ wallets can make use of the new batching functionality (see below) on all validator nodes. + - Scan + - The ``/v0/validators/validator-faucets`` endpoint now returns HTTP 400 when called with no ``validator_ids`` query parameters, instead of returning an empty result. This makes typos in the query parameter key (e.g. ``validator`` instead of ``validator_ids``) fail loudly rather than silently. + - Daml - Release the Token Standard V2 APIs (`CIP-112 `__).