diff --git a/castor/src/main/scala/org/hyperledger/identus/castor/core/model/ProtoModelHelper.scala b/castor/src/main/scala/org/hyperledger/identus/castor/core/model/ProtoModelHelper.scala
index cd12aeeb4b..2e66913279 100644
--- a/castor/src/main/scala/org/hyperledger/identus/castor/core/model/ProtoModelHelper.scala
+++ b/castor/src/main/scala/org/hyperledger/identus/castor/core/model/ProtoModelHelper.scala
@@ -24,10 +24,8 @@ import org.hyperledger.identus.castor.core.model.did.{
UpdateDIDAction,
VerificationRelationship
}
-import org.hyperledger.identus.castor.core.model.did.ServiceEndpoint.value
-import org.hyperledger.identus.castor.core.model.did.ServiceEndpoint.UriOrJsonEndpoint
-import org.hyperledger.identus.shared.models.Base64UrlString
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.castor.core.model.did.ServiceEndpoint.{value, UriOrJsonEndpoint}
+import org.hyperledger.identus.shared.models.{Base64UrlString, KeyId}
import org.hyperledger.identus.shared.utils.Traverse.*
import zio.*
diff --git a/castor/src/main/scala/org/hyperledger/identus/castor/core/model/did/PublicKey.scala b/castor/src/main/scala/org/hyperledger/identus/castor/core/model/did/PublicKey.scala
index da27a541c2..ec79f7fd2b 100644
--- a/castor/src/main/scala/org/hyperledger/identus/castor/core/model/did/PublicKey.scala
+++ b/castor/src/main/scala/org/hyperledger/identus/castor/core/model/did/PublicKey.scala
@@ -1,7 +1,6 @@
package org.hyperledger.identus.castor.core.model.did
-import org.hyperledger.identus.shared.models.Base64UrlString
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{Base64UrlString, KeyId}
final case class PublicKey(
id: KeyId,
diff --git a/castor/src/test/scala/org/hyperledger/identus/castor/core/service/MockDIDService.scala b/castor/src/test/scala/org/hyperledger/identus/castor/core/service/MockDIDService.scala
index ae128f47ed..b911ff9a92 100644
--- a/castor/src/test/scala/org/hyperledger/identus/castor/core/service/MockDIDService.scala
+++ b/castor/src/test/scala/org/hyperledger/identus/castor/core/service/MockDIDService.scala
@@ -3,8 +3,7 @@ package org.hyperledger.identus.castor.core.service
import org.hyperledger.identus.castor.core.model.did.*
import org.hyperledger.identus.castor.core.model.error
import org.hyperledger.identus.shared.crypto.{Apollo, Secp256k1KeyPair}
-import org.hyperledger.identus.shared.models.Base64UrlString
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{Base64UrlString, KeyId}
import zio.{mock, IO, URLayer, ZIO, ZLayer}
import zio.mock.{Expectation, Mock, Proxy}
import zio.test.Assertion
diff --git a/castor/src/test/scala/org/hyperledger/identus/castor/core/util/DIDOperationValidatorSpec.scala b/castor/src/test/scala/org/hyperledger/identus/castor/core/util/DIDOperationValidatorSpec.scala
index 72957513b0..7e2e8fee99 100644
--- a/castor/src/test/scala/org/hyperledger/identus/castor/core/util/DIDOperationValidatorSpec.scala
+++ b/castor/src/test/scala/org/hyperledger/identus/castor/core/util/DIDOperationValidatorSpec.scala
@@ -3,8 +3,7 @@ package org.hyperledger.identus.castor.core.util
import org.hyperledger.identus.castor.core.model.did.*
import org.hyperledger.identus.castor.core.model.error.OperationValidationError
import org.hyperledger.identus.castor.core.util.DIDOperationValidator.Config
-import org.hyperledger.identus.shared.models.Base64UrlString
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{Base64UrlString, KeyId}
import zio.*
import zio.test.*
import zio.test.Assertion.*
diff --git a/castor/src/test/scala/org/hyperledger/identus/castor/core/util/GenUtils.scala b/castor/src/test/scala/org/hyperledger/identus/castor/core/util/GenUtils.scala
index 29622b3b70..e25519ebc2 100644
--- a/castor/src/test/scala/org/hyperledger/identus/castor/core/util/GenUtils.scala
+++ b/castor/src/test/scala/org/hyperledger/identus/castor/core/util/GenUtils.scala
@@ -4,8 +4,7 @@ import io.circe.Json
import org.hyperledger.identus.castor.core.model.did.*
import org.hyperledger.identus.castor.core.model.did.ServiceEndpoint.{UriOrJsonEndpoint, UriValue}
import org.hyperledger.identus.shared.crypto.Apollo
-import org.hyperledger.identus.shared.models.Base64UrlString
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{Base64UrlString, KeyId}
import zio.*
import zio.test.Gen
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/CloudAgentApp.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/CloudAgentApp.scala
index 5503393c1a..ced294305e 100644
--- a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/CloudAgentApp.scala
+++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/CloudAgentApp.scala
@@ -26,6 +26,7 @@ import org.hyperledger.identus.pollux.credentialschema.{
SchemaRegistryServerEndpoints,
VerificationPolicyServerEndpoints
}
+import org.hyperledger.identus.pollux.prex.PresentationExchangeServerEndpoints
import org.hyperledger.identus.pollux.vc.jwt.DidResolver as JwtDidResolver
import org.hyperledger.identus.presentproof.controller.PresentProofServerEndpoints
import org.hyperledger.identus.resolvers.DIDResolver
@@ -47,7 +48,7 @@ object CloudAgentApp {
_ <- syncRevocationStatusListsJob.debug.fork
_ <- AgentHttpServer.run.tapDefect(e => ZIO.logErrorCause("Agent HTTP Server failure", e)).fork
fiber <- DidCommHttpServer.run.tapDefect(e => ZIO.logErrorCause("DIDComm HTTP Server failure", e)).fork
- _ <- WebhookPublisher.layer.build.map(_.get[WebhookPublisher]).flatMap(_.run.debug.fork)
+ _ <- WebhookPublisher.layer.build.map(_.get[WebhookPublisher]).flatMap(_.run.fork)
_ <- fiber.join *> ZIO.log(s"Server End")
_ <- ZIO.never
} yield ()
@@ -137,6 +138,7 @@ object AgentHttpServer {
allWalletManagementEndpoints <- WalletManagementServerEndpoints.all
allEventEndpoints <- EventServerEndpoints.all
allOIDCEndpoints <- CredentialIssuerServerEndpoints.all
+ allPresentationExchangeEndpoints <- PresentationExchangeServerEndpoints.all
} yield allCredentialDefinitionRegistryEndpoints ++
allSchemaRegistryEndpoints ++
allVerificationPolicyEndpoints ++
@@ -147,11 +149,13 @@ object AgentHttpServer {
allStatusListEndpoints ++
allPresentProofEndpoints ++
allVcVerificationEndpoints ++
+ allPresentationExchangeEndpoints ++
allSystemEndpoints ++
allEntityEndpoints ++
allWalletManagementEndpoints ++
allEventEndpoints ++
allOIDCEndpoints
+
def run =
for {
allEndpoints <- agentRESTServiceEndpoints
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/MainApp.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/MainApp.scala
index a2a69e8d9e..10b4928d25 100644
--- a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/MainApp.scala
+++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/MainApp.scala
@@ -46,12 +46,15 @@ import org.hyperledger.identus.pollux.credentialschema.controller.{
CredentialSchemaControllerImpl,
VerificationPolicyControllerImpl
}
+import org.hyperledger.identus.pollux.prex.controller.PresentationExchangeControllerImpl
+import org.hyperledger.identus.pollux.prex.PresentationDefinitionValidatorImpl
import org.hyperledger.identus.pollux.sql.repository.{
JdbcCredentialDefinitionRepository,
JdbcCredentialRepository,
JdbcCredentialSchemaRepository,
JdbcCredentialStatusListRepository,
JdbcOID4VCIIssuerMetadataRepository,
+ JdbcPresentationExchangeRepository,
JdbcPresentationRepository,
JdbcVerificationPolicyRepository,
Migrations as PolluxMigrations
@@ -169,12 +172,14 @@ object MainApp extends ZIOAppDefault {
WalletManagementControllerImpl.layer,
EventControllerImpl.layer,
DIDCommControllerImpl.layer,
+ PresentationExchangeControllerImpl.layer,
// domain
AppModule.apolloLayer,
AppModule.didJwtResolverLayer,
DIDOperationValidator.layer(),
DIDResolver.layer,
HttpURIDereferencerImpl.layer,
+ PresentationDefinitionValidatorImpl.layer,
// service
ConnectionServiceImpl.layer >>> ConnectionServiceNotifier.layer,
CredentialSchemaServiceImpl.layer,
@@ -188,6 +193,7 @@ object MainApp extends ZIOAppDefault {
VerificationPolicyServiceImpl.layer,
WalletManagementServiceImpl.layer,
VcVerificationServiceImpl.layer,
+ PresentationExchangeServiceImpl.layer,
// authentication
AppModule.builtInAuthenticatorLayer,
AppModule.keycloakAuthenticatorLayer,
@@ -211,6 +217,7 @@ object MainApp extends ZIOAppDefault {
RepoModule.polluxContextAwareTransactorLayer ++ RepoModule.polluxTransactorLayer >>> JdbcCredentialDefinitionRepository.layer,
RepoModule.polluxContextAwareTransactorLayer ++ RepoModule.polluxTransactorLayer >>> JdbcPresentationRepository.layer,
RepoModule.polluxContextAwareTransactorLayer ++ RepoModule.polluxTransactorLayer >>> JdbcOID4VCIIssuerMetadataRepository.layer,
+ RepoModule.polluxContextAwareTransactorLayer ++ RepoModule.polluxTransactorLayer >>> JdbcPresentationExchangeRepository.layer,
RepoModule.polluxContextAwareTransactorLayer >>> JdbcVerificationPolicyRepository.layer,
// oidc
CredentialIssuerControllerImpl.layer,
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/http/DocModels.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/http/DocModels.scala
index 0faceda3cf..e13321a552 100644
--- a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/http/DocModels.scala
+++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/http/DocModels.scala
@@ -8,6 +8,7 @@ import org.hyperledger.identus.iam.wallet.http.WalletManagementEndpoints
import org.hyperledger.identus.issue.controller.IssueEndpoints
import org.hyperledger.identus.pollux.credentialdefinition.CredentialDefinitionRegistryEndpoints
import org.hyperledger.identus.pollux.credentialschema.{SchemaRegistryEndpoints, VerificationPolicyEndpoints}
+import org.hyperledger.identus.pollux.prex.PresentationExchangeEndpoints
import org.hyperledger.identus.system.controller.SystemEndpoints
import sttp.apispec.{SecurityScheme, Tag}
import sttp.apispec.openapi.*
@@ -122,7 +123,8 @@ object DocModels {
WalletManagementEndpoints.tag,
SystemEndpoints.tag,
EventEndpoints.tag,
- EntityEndpoints.tag
+ EntityEndpoints.tag,
+ PresentationExchangeEndpoints.tag
)
)
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/jobs/StatusListJobs.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/jobs/StatusListJobs.scala
index d57cccb079..71d02db3e2 100644
--- a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/jobs/StatusListJobs.scala
+++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/jobs/StatusListJobs.scala
@@ -7,7 +7,6 @@ import org.hyperledger.identus.mercury.protocol.revocationnotificaiton.Revocatio
import org.hyperledger.identus.pollux.core.service.{CredentialService, CredentialStatusListService}
import org.hyperledger.identus.pollux.vc.jwt.revocation.{VCStatusList2021, VCStatusList2021Error}
import org.hyperledger.identus.shared.models.*
-import org.hyperledger.identus.shared.models.WalletAccessContext
import org.hyperledger.identus.shared.utils.DurationOps.toMetricsSeconds
import zio.*
import zio.metrics.Metric
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/DIDController.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/DIDController.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/DIDController.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/DIDController.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/DIDEndpoints.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/DIDEndpoints.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/DIDEndpoints.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/DIDEndpoints.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/DIDRegistrarController.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/DIDRegistrarController.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/DIDRegistrarController.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/DIDRegistrarController.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/DIDRegistrarEndpoints.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/DIDRegistrarEndpoints.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/DIDRegistrarEndpoints.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/DIDRegistrarEndpoints.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/DIDRegistrarServerEndpoints.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/DIDRegistrarServerEndpoints.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/DIDRegistrarServerEndpoints.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/DIDRegistrarServerEndpoints.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/DIDServerEndpoints.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/DIDServerEndpoints.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/DIDServerEndpoints.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/DIDServerEndpoints.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/DIDDocument.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/DIDDocument.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/DIDDocument.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/DIDDocument.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/DIDDocumentMetadata.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/DIDDocumentMetadata.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/DIDDocumentMetadata.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/DIDDocumentMetadata.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/DIDInput.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/DIDInput.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/DIDInput.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/DIDInput.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/DIDResolutionMetadata.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/DIDResolutionMetadata.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/DIDResolutionMetadata.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/DIDResolutionMetadata.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/DIDResolutionResult.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/DIDResolutionResult.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/DIDResolutionResult.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/DIDResolutionResult.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/ManagedDID.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/ManagedDID.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/ManagedDID.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/ManagedDID.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/PublicKeyJwk.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/PublicKeyJwk.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/PublicKeyJwk.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/PublicKeyJwk.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/ScheduledOperation.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/ScheduledOperation.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/ScheduledOperation.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/ScheduledOperation.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/Service.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/Service.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/Service.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/Service.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/UpdateManagedDID.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/UpdateManagedDID.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/UpdateManagedDID.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/UpdateManagedDID.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/VerificationMethod.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/VerificationMethod.scala
similarity index 100%
rename from cloud-agent/service/server/src/main/scala/org/hyperledger/identus/controller/http/VerificationMethod.scala
rename to cloud-agent/service/server/src/main/scala/org/hyperledger/identus/castor/controller/http/VerificationMethod.scala
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/didcomm/controller/DIDCommControllerError.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/didcomm/controller/DIDCommControllerError.scala
index 1bc1a644d4..5a27032b75 100644
--- a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/didcomm/controller/DIDCommControllerError.scala
+++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/didcomm/controller/DIDCommControllerError.scala
@@ -1,8 +1,7 @@
package org.hyperledger.identus.didcomm.controller
import org.hyperledger.identus.mercury.model.DidId
-import org.hyperledger.identus.shared.models.{Failure, StatusCode}
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{Failure, KeyId, StatusCode}
sealed trait DIDCommControllerError extends Failure {
override def namespace = "DIDCommControllerError"
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationExchangeEndpoints.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationExchangeEndpoints.scala
new file mode 100644
index 0000000000..435042b052
--- /dev/null
+++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationExchangeEndpoints.scala
@@ -0,0 +1,97 @@
+package org.hyperledger.identus.pollux.prex
+
+import org.hyperledger.identus.api.http.{EndpointOutputs, ErrorResponse, RequestContext}
+import org.hyperledger.identus.api.http.model.PaginationInput
+import org.hyperledger.identus.iam.authentication.apikey.ApiKeyCredentials
+import org.hyperledger.identus.iam.authentication.apikey.ApiKeyEndpointSecurityLogic.apiKeyHeader
+import org.hyperledger.identus.iam.authentication.oidc.JwtCredentials
+import org.hyperledger.identus.iam.authentication.oidc.JwtSecurityLogic.jwtAuthHeader
+import org.hyperledger.identus.pollux.prex.http.{CreatePresentationDefinition, PresentationDefinitionPage}
+import org.hyperledger.identus.pollux.prex.http.PresentationExchangeTapirSchemas.given
+import sttp.apispec.Tag
+import sttp.model.StatusCode
+import sttp.tapir.*
+import sttp.tapir.json.zio.jsonBody
+
+import java.util.UUID
+
+object PresentationExchangeEndpoints {
+
+ private val tagName = "Presentation Exchange"
+ private val tagDescription =
+ s"""
+ |The __${tagName}__ endpoints offers a way to manage resources related to [presentation exchange protocol](https://identity.foundation/presentation-exchange/spec/v2.1.1/).
+ |
+ |The verifier can create the resources such as `presentation-definition` that can be publicly referenced
+ |in various protocols such as [OpenID for Verificable Presentation](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html).
+ |""".stripMargin
+
+ val tag = Tag(tagName, Some(tagDescription))
+
+ private val paginationInput: EndpointInput[PaginationInput] = EndpointInput.derived[PaginationInput]
+
+ private val baseEndpoint = endpoint
+ .tag(tagName)
+ .in("presentation-exchange")
+ .in(extractFromRequest[RequestContext](RequestContext.apply))
+
+ private val basePrivateEndpoint = baseEndpoint
+ .securityIn(apiKeyHeader)
+ .securityIn(jwtAuthHeader)
+
+ val getPresentationDefinition: Endpoint[
+ Unit,
+ (RequestContext, UUID),
+ ErrorResponse,
+ PresentationDefinition,
+ Any
+ ] =
+ baseEndpoint.get
+ .in("presentation-definitions" / path[UUID]("id"))
+ .out(statusCode(StatusCode.Ok).description("Presentation Definition retrieved successfully"))
+ .out(jsonBody[PresentationDefinition])
+ .errorOut(EndpointOutputs.basicFailuresAndNotFound)
+ .name("getPresentationDefinition")
+ .summary("Get a presentation-definition")
+
+ val listPresentationDefinition: Endpoint[
+ (ApiKeyCredentials, JwtCredentials),
+ (RequestContext, PaginationInput),
+ ErrorResponse,
+ PresentationDefinitionPage,
+ Any,
+ ] =
+ basePrivateEndpoint.get
+ .in("presentation-definitions")
+ .in(paginationInput)
+ .out(statusCode(StatusCode.Ok).description("Presentation Definitions retrieved successfully"))
+ .out(jsonBody[PresentationDefinitionPage])
+ .errorOut(EndpointOutputs.basicFailuresAndForbidden)
+ .name("listPresentationDefinition")
+ .summary("List all presentation-definitions")
+ .description(
+ """List all `presentation-definitions` in the wallet.
+ |Return a paginated items ordered by created timestamp.""".stripMargin
+ )
+
+ val createPresentationDefinition: Endpoint[
+ (ApiKeyCredentials, JwtCredentials),
+ (RequestContext, CreatePresentationDefinition),
+ ErrorResponse,
+ PresentationDefinition,
+ Any
+ ] =
+ basePrivateEndpoint.post
+ .in("presentation-definitions")
+ .in(jsonBody[CreatePresentationDefinition])
+ .out(statusCode(StatusCode.Created).description("Presentation Definition created successfully"))
+ .out(jsonBody[PresentationDefinition])
+ .errorOut(EndpointOutputs.basicFailureAndNotFoundAndForbidden)
+ .name("createPresentationDefinition")
+ .summary("Create a new presentation-definition")
+ .description(
+ """Create a `presentation-definition` object according to the [presentation exchange protocol](https://identity.foundation/presentation-exchange/spec/v2.1.1/).
+ |The `POST` endpoint is restricted to the owner of the wallet. The `presentation-definition` object, however can be referenced by publicly by `id` returned in the response.""".stripMargin
+ )
+
+}
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationExchangeServerEndpoints.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationExchangeServerEndpoints.scala
new file mode 100644
index 0000000000..e5daa287d1
--- /dev/null
+++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationExchangeServerEndpoints.scala
@@ -0,0 +1,61 @@
+package org.hyperledger.identus.pollux.prex
+
+import org.hyperledger.identus.agent.walletapi.model.BaseEntity
+import org.hyperledger.identus.iam.authentication.{Authenticator, Authorizer, DefaultAuthenticator, SecurityLogic}
+import org.hyperledger.identus.pollux.prex.controller.PresentationExchangeController
+import org.hyperledger.identus.LogUtils.*
+import sttp.tapir.ztapir.*
+import zio.*
+
+class PresentationExchangeServerEndpoints(
+ controller: PresentationExchangeController,
+ authenticator: Authenticator[BaseEntity],
+ authorizer: Authorizer[BaseEntity]
+) {
+
+ private val getPresentationDefinitionServerEndpoint: ZServerEndpoint[Any, Any] =
+ PresentationExchangeEndpoints.getPresentationDefinition
+ .zServerLogic { case (rc, id) =>
+ controller.getPresentationDefinition(id).logTrace(rc)
+ }
+
+ private val listPresentationDefinitionServerEndpoint: ZServerEndpoint[Any, Any] =
+ PresentationExchangeEndpoints.listPresentationDefinition
+ .zServerSecurityLogic(SecurityLogic.authorizeWalletAccessWith(_)(authenticator, authorizer))
+ .serverLogic { wac =>
+ { case (rc, pagination) =>
+ controller
+ .listPresentationDefinition(pagination)(rc)
+ .provideSomeLayer(ZLayer.succeed(wac))
+ .logTrace(rc)
+ }
+ }
+
+ private val createPresentationDefinitionServerEndpoint: ZServerEndpoint[Any, Any] =
+ PresentationExchangeEndpoints.createPresentationDefinition
+ .zServerSecurityLogic(SecurityLogic.authorizeWalletAccessWith(_)(authenticator, authorizer))
+ .serverLogic { wac =>
+ { case (rc, pd) =>
+ controller
+ .createPresentationDefinition(pd)
+ .provideSomeLayer(ZLayer.succeed(wac))
+ .logTrace(rc)
+ }
+ }
+
+ val all: List[ZServerEndpoint[Any, Any]] = List(
+ getPresentationDefinitionServerEndpoint,
+ listPresentationDefinitionServerEndpoint,
+ createPresentationDefinitionServerEndpoint
+ )
+}
+
+object PresentationExchangeServerEndpoints {
+ def all: URIO[DefaultAuthenticator & PresentationExchangeController, List[ZServerEndpoint[Any, Any]]] = {
+ for {
+ controller <- ZIO.service[PresentationExchangeController]
+ authenticator <- ZIO.service[DefaultAuthenticator]
+ endpoints = PresentationExchangeServerEndpoints(controller, authenticator, authenticator)
+ } yield endpoints.all
+ }
+}
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/controller/PresentationExchangeController.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/controller/PresentationExchangeController.scala
new file mode 100644
index 0000000000..0376544d9b
--- /dev/null
+++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/controller/PresentationExchangeController.scala
@@ -0,0 +1,62 @@
+package org.hyperledger.identus.pollux.prex.controller
+
+import org.hyperledger.identus.api.http.{ErrorResponse, RequestContext}
+import org.hyperledger.identus.api.http.model.{CollectionStats, PaginationInput}
+import org.hyperledger.identus.api.util.PaginationUtils
+import org.hyperledger.identus.pollux.core.service.PresentationExchangeService
+import org.hyperledger.identus.pollux.prex.http.{CreatePresentationDefinition, PresentationDefinitionPage}
+import org.hyperledger.identus.pollux.prex.PresentationDefinition
+import org.hyperledger.identus.shared.models.WalletAccessContext
+import zio.*
+
+import java.util.UUID
+import scala.language.implicitConversions
+
+trait PresentationExchangeController {
+ def createPresentationDefinition(
+ cpd: CreatePresentationDefinition
+ ): ZIO[WalletAccessContext, ErrorResponse, PresentationDefinition]
+
+ def getPresentationDefinition(id: UUID): IO[ErrorResponse, PresentationDefinition]
+
+ def listPresentationDefinition(paginationInput: PaginationInput)(implicit
+ rc: RequestContext
+ ): ZIO[WalletAccessContext, ErrorResponse, PresentationDefinitionPage]
+}
+
+class PresentationExchangeControllerImpl(service: PresentationExchangeService) extends PresentationExchangeController {
+
+ override def createPresentationDefinition(
+ cpd: CreatePresentationDefinition
+ ): ZIO[WalletAccessContext, ErrorResponse, PresentationDefinition] = {
+ val pd: PresentationDefinition = cpd
+ service.createPresentationDefinititon(pd).as(pd)
+ }
+
+ override def getPresentationDefinition(id: UUID): IO[ErrorResponse, PresentationDefinition] =
+ service.getPresentationDefinition(id)
+
+ override def listPresentationDefinition(
+ paginationInput: PaginationInput
+ )(implicit rc: RequestContext): ZIO[WalletAccessContext, ErrorResponse, PresentationDefinitionPage] = {
+ val uri = rc.request.uri
+ val pagination = paginationInput.toPagination
+ for {
+ pageResult <- service.listPresentationDefinition(offset = paginationInput.offset, limit = paginationInput.limit)
+ (items, totalCount) = pageResult
+ stats = CollectionStats(totalCount = totalCount, filteredCount = totalCount)
+ } yield PresentationDefinitionPage(
+ self = uri.toString(),
+ pageOf = PaginationUtils.composePageOfUri(uri).toString,
+ next = PaginationUtils.composeNextUri(uri, items, pagination, stats).map(_.toString),
+ previous = PaginationUtils.composePreviousUri(uri, items, pagination, stats).map(_.toString),
+ contents = items,
+ )
+ }
+
+}
+
+object PresentationExchangeControllerImpl {
+ def layer: URLayer[PresentationExchangeService, PresentationExchangeController] =
+ ZLayer.fromFunction(PresentationExchangeControllerImpl(_))
+}
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/http/PresentationDefinition.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/http/PresentationDefinition.scala
new file mode 100644
index 0000000000..fb3c3066b2
--- /dev/null
+++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/http/PresentationDefinition.scala
@@ -0,0 +1,42 @@
+package org.hyperledger.identus.pollux.prex.http
+
+import org.hyperledger.identus.pollux.prex.{ClaimFormat, InputDescriptor, PresentationDefinition}
+import org.hyperledger.identus.pollux.prex.http.PresentationExchangeTapirSchemas.given
+import sttp.tapir.Schema
+import zio.json.{JsonDecoder, JsonEncoder}
+
+case class CreatePresentationDefinition(
+ input_descriptors: Seq[InputDescriptor] = Seq.empty,
+ name: Option[String] = None,
+ purpose: Option[String] = None,
+ format: Option[ClaimFormat] = None
+)
+
+object CreatePresentationDefinition {
+ given Schema[CreatePresentationDefinition] = Schema.derived
+ given JsonEncoder[CreatePresentationDefinition] = JsonEncoder.derived
+ given JsonDecoder[CreatePresentationDefinition] = JsonDecoder.derived
+
+ given Conversion[CreatePresentationDefinition, PresentationDefinition] = cpd =>
+ PresentationDefinition(
+ input_descriptors = cpd.input_descriptors,
+ name = cpd.name,
+ purpose = cpd.purpose,
+ format = cpd.format
+ )
+}
+
+case class PresentationDefinitionPage(
+ self: String,
+ kind: String = "PresentationDefinitionPage",
+ pageOf: String,
+ next: Option[String] = None,
+ previous: Option[String] = None,
+ contents: Seq[PresentationDefinition]
+)
+
+object PresentationDefinitionPage {
+ given Schema[PresentationDefinitionPage] = Schema.derived
+ given JsonEncoder[PresentationDefinitionPage] = JsonEncoder.derived
+ given JsonDecoder[PresentationDefinitionPage] = JsonDecoder.derived
+}
diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/http/PresentationExchangeTapirSchemas.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/http/PresentationExchangeTapirSchemas.scala
new file mode 100644
index 0000000000..91b129f5f2
--- /dev/null
+++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/prex/http/PresentationExchangeTapirSchemas.scala
@@ -0,0 +1,24 @@
+package org.hyperledger.identus.pollux.prex.http
+
+import org.hyperledger.identus.pollux.prex.*
+import sttp.tapir.json.zio.*
+import sttp.tapir.Schema
+import zio.json.ast.Json
+
+import scala.language.implicitConversions
+
+object PresentationExchangeTapirSchemas {
+ given Schema[PresentationDefinition] = Schema
+ .derived[PresentationDefinition]
+ .description(
+ "*Presentation Definition* object according to the [PresentationExchange spec](https://identity.foundation/presentation-exchange/spec/v2.1.1/#presentation-definition)"
+ )
+ given Schema[InputDescriptor] = Schema.derived
+ given Schema[ClaimFormat] = Schema.derived
+ given Schema[Constraints] = Schema.derived
+ given Schema[Jwt] = Schema.derived
+ given Schema[Ldp] = Schema.derived
+ given Schema[Field] = Schema.derived
+ given Schema[JsonPathValue] = Schema.schemaForString.map[JsonPathValue](Some(_))(_.value)
+ given Schema[FieldFilter] = Schema.derived[Json].map[FieldFilter](Some(_))(_.asJsonZio)
+}
diff --git a/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/api/util/Tapir2StaticOAS.scala b/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/api/util/Tapir2StaticOAS.scala
index 42f55edbc5..05b217c71e 100644
--- a/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/api/util/Tapir2StaticOAS.scala
+++ b/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/api/util/Tapir2StaticOAS.scala
@@ -16,6 +16,7 @@ import org.hyperledger.identus.pollux.credentialschema.controller.{
CredentialSchemaController,
VerificationPolicyController
}
+import org.hyperledger.identus.pollux.prex.controller.PresentationExchangeController
import org.hyperledger.identus.presentproof.controller.PresentProofController
import org.hyperledger.identus.system.controller.SystemController
import org.hyperledger.identus.verification.controller.VcVerificationController
@@ -58,6 +59,7 @@ object Tapir2StaticOAS extends ZIOAppDefault {
ZLayer.succeed(mock[DefaultAuthenticator]) ++
ZLayer.succeed(mock[EventController]) ++
ZLayer.succeed(mock[CredentialIssuerController]) ++
+ ZLayer.succeed(mock[PresentationExchangeController]) ++
ZLayer.succeed(mock[Oid4vciAuthenticatorFactory])
)
}
diff --git a/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/issue/controller/IssueControllerImplSpec.scala b/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/issue/controller/IssueControllerImplSpec.scala
index edcb5f1411..422928756c 100644
--- a/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/issue/controller/IssueControllerImplSpec.scala
+++ b/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/issue/controller/IssueControllerImplSpec.scala
@@ -22,8 +22,7 @@ import org.hyperledger.identus.mercury.protocol.invitation.v2.Invitation
import org.hyperledger.identus.pollux.core.model.{CredentialFormat, DidCommID, IssueCredentialRecord}
import org.hyperledger.identus.pollux.core.model.IssueCredentialRecord.{ProtocolState, Role}
import org.hyperledger.identus.pollux.core.service.MockCredentialService
-import org.hyperledger.identus.shared.models.KeyId
-import org.hyperledger.identus.shared.models.WalletId
+import org.hyperledger.identus.shared.models.{KeyId, WalletId}
import sttp.client3.{basicRequest, DeserializationException, UriContext}
import sttp.client3.ziojson.*
import sttp.model.StatusCode
diff --git a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/ManagedDIDService.scala b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/ManagedDIDService.scala
index c233844df1..935a38244f 100644
--- a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/ManagedDIDService.scala
+++ b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/ManagedDIDService.scala
@@ -7,8 +7,7 @@ import org.hyperledger.identus.castor.core.model.did.*
import org.hyperledger.identus.mercury.model.*
import org.hyperledger.identus.mercury.PeerDID
import org.hyperledger.identus.shared.crypto.{Ed25519KeyPair, Secp256k1KeyPair, X25519KeyPair}
-import org.hyperledger.identus.shared.models.KeyId
-import org.hyperledger.identus.shared.models.WalletAccessContext
+import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext}
import zio.*
/** A wrapper around Castor's DIDService providing key-management capability. Analogous to the secretAPI in
diff --git a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/ManagedDIDServiceImpl.scala b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/ManagedDIDServiceImpl.scala
index c93806c040..4e8763bdad 100644
--- a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/ManagedDIDServiceImpl.scala
+++ b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/ManagedDIDServiceImpl.scala
@@ -14,8 +14,7 @@ import org.hyperledger.identus.castor.core.util.DIDOperationValidator
import org.hyperledger.identus.mercury.model.DidId
import org.hyperledger.identus.mercury.PeerDID
import org.hyperledger.identus.shared.crypto.{Apollo, Ed25519KeyPair, Secp256k1KeyPair, X25519KeyPair}
-import org.hyperledger.identus.shared.models.KeyId
-import org.hyperledger.identus.shared.models.WalletAccessContext
+import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext}
import zio.*
import scala.collection.immutable.ArraySeq
diff --git a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/handler/DIDCreateHandler.scala b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/handler/DIDCreateHandler.scala
index 479b34ed2b..66fec256bb 100644
--- a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/handler/DIDCreateHandler.scala
+++ b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/handler/DIDCreateHandler.scala
@@ -12,8 +12,7 @@ import org.hyperledger.identus.agent.walletapi.storage.{DIDNonSecretStorage, DID
import org.hyperledger.identus.agent.walletapi.util.OperationFactory
import org.hyperledger.identus.castor.core.model.did.PrismDIDOperation
import org.hyperledger.identus.shared.crypto.{Apollo, Ed25519KeyPair, X25519KeyPair}
-import org.hyperledger.identus.shared.models.KeyId
-import org.hyperledger.identus.shared.models.WalletAccessContext
+import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext}
import zio.*
private[walletapi] class DIDCreateHandler(
diff --git a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/handler/DIDUpdateHandler.scala b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/handler/DIDUpdateHandler.scala
index b93510bc69..dd0af4256a 100644
--- a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/handler/DIDUpdateHandler.scala
+++ b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/handler/DIDUpdateHandler.scala
@@ -19,8 +19,7 @@ import org.hyperledger.identus.castor.core.model.did.{
}
import org.hyperledger.identus.castor.core.model.did.PrismDIDOperation.Update
import org.hyperledger.identus.shared.crypto.{Apollo, Ed25519KeyPair, X25519KeyPair}
-import org.hyperledger.identus.shared.models.KeyId
-import org.hyperledger.identus.shared.models.WalletAccessContext
+import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext}
import zio.*
import scala.collection.immutable.ArraySeq
diff --git a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/handler/PublicationHandler.scala b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/handler/PublicationHandler.scala
index 1807e9efd9..b1656f0679 100644
--- a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/handler/PublicationHandler.scala
+++ b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/service/handler/PublicationHandler.scala
@@ -11,8 +11,7 @@ import org.hyperledger.identus.castor.core.model.did.{
import org.hyperledger.identus.castor.core.model.error.DIDOperationError
import org.hyperledger.identus.castor.core.service.DIDService
import org.hyperledger.identus.shared.crypto.Secp256k1KeyPair
-import org.hyperledger.identus.shared.models.KeyId
-import org.hyperledger.identus.shared.models.WalletAccessContext
+import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext}
import zio.*
import scala.collection.immutable.ArraySeq
diff --git a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/sql/JdbcDIDNonSecretStorage.scala b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/sql/JdbcDIDNonSecretStorage.scala
index 85cada9985..bfdca44f73 100644
--- a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/sql/JdbcDIDNonSecretStorage.scala
+++ b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/sql/JdbcDIDNonSecretStorage.scala
@@ -16,8 +16,7 @@ import org.hyperledger.identus.mercury.model.DidId
import org.hyperledger.identus.shared.db.ContextAwareTask
import org.hyperledger.identus.shared.db.Implicits.*
import org.hyperledger.identus.shared.db.Implicits.given
-import org.hyperledger.identus.shared.models.{WalletAccessContext, WalletId}
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext, WalletId}
import zio.*
import zio.interop.catz.*
diff --git a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/sql/JdbcDIDSecretStorage.scala b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/sql/JdbcDIDSecretStorage.scala
index 76f9e2650f..7ff1e935b7 100644
--- a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/sql/JdbcDIDSecretStorage.scala
+++ b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/sql/JdbcDIDSecretStorage.scala
@@ -10,8 +10,7 @@ import org.hyperledger.identus.mercury.model.DidId
import org.hyperledger.identus.shared.crypto.jwk.{FromJWK, JWK}
import org.hyperledger.identus.shared.db.ContextAwareTask
import org.hyperledger.identus.shared.db.Implicits.*
-import org.hyperledger.identus.shared.models.KeyId
-import org.hyperledger.identus.shared.models.WalletAccessContext
+import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext}
import zio.*
import java.time.Instant
diff --git a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/storage/DIDNonSecretStorage.scala b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/storage/DIDNonSecretStorage.scala
index e1f84efb4b..1830dc1600 100644
--- a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/storage/DIDNonSecretStorage.scala
+++ b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/storage/DIDNonSecretStorage.scala
@@ -3,8 +3,7 @@ package org.hyperledger.identus.agent.walletapi.storage
import org.hyperledger.identus.agent.walletapi.model.*
import org.hyperledger.identus.castor.core.model.did.{PrismDID, ScheduledDIDOperationStatus}
import org.hyperledger.identus.mercury.model.DidId
-import org.hyperledger.identus.shared.models.{WalletAccessContext, WalletId}
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext, WalletId}
import zio.*
trait DIDNonSecretStorage {
diff --git a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/storage/DIDSecretStorage.scala b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/storage/DIDSecretStorage.scala
index 4726e5a015..0056e0d0e6 100644
--- a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/storage/DIDSecretStorage.scala
+++ b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/storage/DIDSecretStorage.scala
@@ -4,8 +4,7 @@ import com.nimbusds.jose.jwk.OctetKeyPair
import org.hyperledger.identus.castor.core.model.did.PrismDID
import org.hyperledger.identus.mercury.model.DidId
import org.hyperledger.identus.shared.crypto.jwk.{FromJWK, JWK}
-import org.hyperledger.identus.shared.models.KeyId
-import org.hyperledger.identus.shared.models.WalletAccessContext
+import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext}
import zio.*
/** A simple single-user DID key storage */
diff --git a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/util/KeyResolver.scala b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/util/KeyResolver.scala
index 6460af34f5..76a28a853f 100644
--- a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/util/KeyResolver.scala
+++ b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/util/KeyResolver.scala
@@ -9,8 +9,7 @@ import org.hyperledger.identus.agent.walletapi.model.{
import org.hyperledger.identus.agent.walletapi.storage.{DIDNonSecretStorage, DIDSecretStorage, WalletSecretStorage}
import org.hyperledger.identus.castor.core.model.did.{EllipticCurve, PrismDID}
import org.hyperledger.identus.shared.crypto.{Apollo, Ed25519KeyPair, Secp256k1KeyPair, X25519KeyPair}
-import org.hyperledger.identus.shared.models.KeyId
-import org.hyperledger.identus.shared.models.WalletAccessContext
+import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext}
import zio.*
class KeyResolver(
diff --git a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/util/OperationFactory.scala b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/util/OperationFactory.scala
index acabbb413d..9cf16b6a42 100644
--- a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/util/OperationFactory.scala
+++ b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/util/OperationFactory.scala
@@ -10,8 +10,7 @@ import org.hyperledger.identus.shared.crypto.{
Secp256k1PublicKey,
X25519PublicKey
}
-import org.hyperledger.identus.shared.models.Base64UrlString
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{Base64UrlString, KeyId}
import zio.*
import scala.collection.immutable.ArraySeq
diff --git a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/vault/VaultDIDSecretStorage.scala b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/vault/VaultDIDSecretStorage.scala
index 1cf98aa9a1..2ca1faf466 100644
--- a/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/vault/VaultDIDSecretStorage.scala
+++ b/cloud-agent/service/wallet-api/src/main/scala/org/hyperledger/identus/agent/walletapi/vault/VaultDIDSecretStorage.scala
@@ -6,8 +6,7 @@ import org.hyperledger.identus.castor.core.model.did.PrismDID
import org.hyperledger.identus.mercury.model.DidId
import org.hyperledger.identus.shared.crypto.jwk.{FromJWK, JWK}
import org.hyperledger.identus.shared.crypto.Sha256Hash
-import org.hyperledger.identus.shared.models.{HexString, WalletAccessContext, WalletId}
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{HexString, KeyId, WalletAccessContext, WalletId}
import zio.*
import java.nio.charset.StandardCharsets
diff --git a/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/service/ManagedDIDServiceSpec.scala b/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/service/ManagedDIDServiceSpec.scala
index 8448ae4131..7950a38265 100644
--- a/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/service/ManagedDIDServiceSpec.scala
+++ b/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/service/ManagedDIDServiceSpec.scala
@@ -15,8 +15,7 @@ import org.hyperledger.identus.castor.core.model.error
import org.hyperledger.identus.castor.core.service.DIDService
import org.hyperledger.identus.castor.core.util.DIDOperationValidator
import org.hyperledger.identus.shared.crypto.{ApolloSpecHelper, Ed25519KeyPair, Secp256k1KeyPair, X25519KeyPair}
-import org.hyperledger.identus.shared.models.{WalletAccessContext, WalletAdministrationContext}
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext, WalletAdministrationContext}
import org.hyperledger.identus.sharedtest.containers.PostgresTestContainerSupport
import org.hyperledger.identus.test.container.{DBTestUtils, VaultTestContainerSupport}
import zio.*
diff --git a/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/storage/DIDSecretStorageSpec.scala b/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/storage/DIDSecretStorageSpec.scala
index 0ff4217449..9288c39cd9 100644
--- a/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/storage/DIDSecretStorageSpec.scala
+++ b/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/storage/DIDSecretStorageSpec.scala
@@ -12,8 +12,7 @@ import org.hyperledger.identus.agent.walletapi.vault.{VaultDIDSecretStorage, Vau
import org.hyperledger.identus.castor.core.model.did.PrismDIDOperation
import org.hyperledger.identus.mercury.PeerDID
import org.hyperledger.identus.shared.crypto.{Apollo, ApolloSpecHelper, Ed25519KeyPair, X25519KeyPair}
-import org.hyperledger.identus.shared.models.{WalletAccessContext, WalletAdministrationContext}
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext, WalletAdministrationContext}
import org.hyperledger.identus.sharedtest.containers.PostgresTestContainerSupport
import org.hyperledger.identus.test.container.{DBTestUtils, VaultTestContainerSupport}
import zio.*
diff --git a/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/storage/MockDIDNonSecretStorage.scala b/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/storage/MockDIDNonSecretStorage.scala
index e20c1a245a..f14df4d00d 100644
--- a/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/storage/MockDIDNonSecretStorage.scala
+++ b/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/storage/MockDIDNonSecretStorage.scala
@@ -3,8 +3,7 @@ package org.hyperledger.identus.agent.walletapi.storage
import org.hyperledger.identus.agent.walletapi.model.*
import org.hyperledger.identus.castor.core.model.did.{PrismDID, ScheduledDIDOperationStatus}
import org.hyperledger.identus.mercury.model.DidId
-import org.hyperledger.identus.shared.models.{WalletAccessContext, WalletId}
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext, WalletId}
import zio.*
import zio.mock.{Expectation, Mock, Proxy}
import zio.test.Assertion.equalTo
diff --git a/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/storage/StorageSpecHelper.scala b/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/storage/StorageSpecHelper.scala
index ef6a3b05e4..15f348ca1d 100644
--- a/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/storage/StorageSpecHelper.scala
+++ b/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/storage/StorageSpecHelper.scala
@@ -18,8 +18,7 @@ import org.hyperledger.identus.castor.core.model.did.{
VerificationRelationship
}
import org.hyperledger.identus.shared.crypto.ApolloSpecHelper
-import org.hyperledger.identus.shared.models.{WalletAccessContext, WalletAdministrationContext}
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext, WalletAdministrationContext}
import zio.*
import zio.test.*
diff --git a/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/util/OperationFactorySpec.scala b/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/util/OperationFactorySpec.scala
index 8131d80f18..6d24a9c403 100644
--- a/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/util/OperationFactorySpec.scala
+++ b/cloud-agent/service/wallet-api/src/test/scala/org/hyperledger/identus/agent/walletapi/util/OperationFactorySpec.scala
@@ -3,8 +3,7 @@ package org.hyperledger.identus.agent.walletapi.util
import org.hyperledger.identus.agent.walletapi.model.*
import org.hyperledger.identus.castor.core.model.did.*
import org.hyperledger.identus.shared.crypto.{ApolloSpecHelper, Ed25519KeyPair, X25519KeyPair}
-import org.hyperledger.identus.shared.models.HexString
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{HexString, KeyId}
import zio.*
import zio.test.*
import zio.test.Assertion.*
diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/error/CredentialServiceError.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/error/CredentialServiceError.scala
index 09d221ed25..a0ffdbe944 100644
--- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/error/CredentialServiceError.scala
+++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/error/CredentialServiceError.scala
@@ -4,8 +4,7 @@ import org.hyperledger.identus.agent.walletapi.model.PublicationState
import org.hyperledger.identus.castor.core.model.did.{PrismDID, VerificationRelationship}
import org.hyperledger.identus.pollux.core.model.DidCommID
import org.hyperledger.identus.pollux.core.model.IssueCredentialRecord.ProtocolState
-import org.hyperledger.identus.shared.models.{Failure, StatusCode}
-import org.hyperledger.identus.shared.models.KeyId
+import org.hyperledger.identus.shared.models.{Failure, KeyId, StatusCode}
import java.util.UUID
diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/PresentationExchangeRepository.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/PresentationExchangeRepository.scala
new file mode 100644
index 0000000000..b94026af86
--- /dev/null
+++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/PresentationExchangeRepository.scala
@@ -0,0 +1,16 @@
+package org.hyperledger.identus.pollux.core.repository
+
+import org.hyperledger.identus.pollux.prex.PresentationDefinition
+import org.hyperledger.identus.shared.models.WalletAccessContext
+import zio.*
+
+import java.util.UUID
+
+trait PresentationExchangeRepository {
+ def createPresentationDefinition(pd: PresentationDefinition): URIO[WalletAccessContext, Unit]
+ def findPresentationDefinition(id: UUID): UIO[Option[PresentationDefinition]]
+ def listPresentationDefinition(
+ offset: Option[Int] = None,
+ limit: Option[Int] = None
+ ): URIO[WalletAccessContext, (Seq[PresentationDefinition], Int)]
+}
diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/PresentationExchangeService.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/PresentationExchangeService.scala
new file mode 100644
index 0000000000..9096c2510e
--- /dev/null
+++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/PresentationExchangeService.scala
@@ -0,0 +1,44 @@
+package org.hyperledger.identus.pollux.core.service
+
+import org.hyperledger.identus.pollux.core.service.PresentationExchangeServiceError.{
+ PresentationDefinitionNotFound,
+ PresentationDefinitionValidationError
+}
+import org.hyperledger.identus.pollux.prex.{PresentationDefinition, PresentationDefinitionError}
+import org.hyperledger.identus.shared.models.{Failure, StatusCode, WalletAccessContext}
+import zio.*
+
+import java.util.UUID
+
+sealed trait PresentationExchangeServiceError(
+ val statusCode: StatusCode,
+ val userFacingMessage: String
+) extends Failure {
+ override val namespace = "PresentationExchangeServiceError"
+}
+
+object PresentationExchangeServiceError {
+ case class PresentationDefinitionNotFound(id: UUID)
+ extends PresentationExchangeServiceError(StatusCode.NotFound, s"PresentationDefinition not found with id: $id")
+
+ case class PresentationDefinitionValidationError(error: PresentationDefinitionError)
+ extends PresentationExchangeServiceError(
+ StatusCode.BadRequest,
+ s"PresentationDefinition validation failed: ${error.userFacingMessage}"
+ )
+}
+
+trait PresentationExchangeService {
+ def createPresentationDefinititon(
+ pd: PresentationDefinition
+ ): ZIO[WalletAccessContext, PresentationDefinitionValidationError, Unit]
+
+ def getPresentationDefinition(
+ id: UUID
+ ): IO[PresentationDefinitionNotFound, PresentationDefinition]
+
+ def listPresentationDefinition(
+ limit: Option[Int],
+ offset: Option[Int]
+ ): URIO[WalletAccessContext, (Seq[PresentationDefinition], Int)]
+}
diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/PresentationExchangeServiceImpl.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/PresentationExchangeServiceImpl.scala
new file mode 100644
index 0000000000..4af0203c07
--- /dev/null
+++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/PresentationExchangeServiceImpl.scala
@@ -0,0 +1,41 @@
+package org.hyperledger.identus.pollux.core.service
+
+import org.hyperledger.identus.pollux.core.repository.PresentationExchangeRepository
+import org.hyperledger.identus.pollux.core.service.PresentationExchangeServiceError.{
+ PresentationDefinitionNotFound,
+ PresentationDefinitionValidationError
+}
+import org.hyperledger.identus.pollux.prex.{PresentationDefinition, PresentationDefinitionValidator}
+import org.hyperledger.identus.shared.models.WalletAccessContext
+import zio.*
+
+import java.util.UUID
+
+class PresentationExchangeServiceImpl(validator: PresentationDefinitionValidator, repo: PresentationExchangeRepository)
+ extends PresentationExchangeService {
+
+ override def createPresentationDefinititon(
+ pd: PresentationDefinition
+ ): ZIO[WalletAccessContext, PresentationDefinitionValidationError, Unit] =
+ for {
+ _ <- validator.validate(pd).mapError(PresentationDefinitionValidationError(_))
+ _ <- repo.createPresentationDefinition(pd)
+ } yield ()
+
+ override def getPresentationDefinition(
+ id: UUID
+ ): IO[PresentationDefinitionNotFound, PresentationDefinition] =
+ repo.findPresentationDefinition(id).someOrFail(PresentationDefinitionNotFound(id))
+
+ override def listPresentationDefinition(
+ limit: Option[Int],
+ offset: Option[Int]
+ ): URIO[WalletAccessContext, (Seq[PresentationDefinition], Int)] =
+ repo.listPresentationDefinition(offset = offset, limit = limit)
+
+}
+
+object PresentationExchangeServiceImpl {
+ def layer: URLayer[PresentationDefinitionValidator & PresentationExchangeRepository, PresentationExchangeService] =
+ ZLayer.fromFunction(PresentationExchangeServiceImpl(_, _))
+}
diff --git a/pollux/prex/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationDefinition.scala b/pollux/prex/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationDefinition.scala
index 21ded1e947..ea16960cc9 100644
--- a/pollux/prex/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationDefinition.scala
+++ b/pollux/prex/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationDefinition.scala
@@ -6,6 +6,7 @@ import io.circe.generic.semiauto.*
import io.circe.Json as CirceJson
import org.hyperledger.identus.shared.json.{JsonInterop, JsonPath, JsonPathError, JsonSchemaError, JsonSchemaUtils}
import zio.*
+import zio.json.{JsonDecoder, JsonEncoder}
import zio.json.ast.Json as ZioJson
opaque type JsonPathValue = String
@@ -15,6 +16,9 @@ object JsonPathValue {
given Decoder[JsonPathValue] = Decoder.decodeString
given Conversion[String, JsonPathValue] = identity
+ given JsonEncoder[JsonPathValue] = JsonEncoder.string
+ given JsonDecoder[JsonPathValue] = JsonDecoder.string
+
extension (jpv: JsonPathValue) {
def toJsonPath: Either[JsonPathError, JsonPath] = JsonPath.compile(jpv)
def value: String = jpv
@@ -26,6 +30,10 @@ opaque type FieldFilter = ZioJson
object FieldFilter {
given Encoder[FieldFilter] = Encoder.encodeJson.contramap(JsonInterop.toCirceJsonAst)
given Decoder[FieldFilter] = Decoder.decodeJson.map(JsonInterop.toZioJsonAst)
+ given Conversion[ZioJson, FieldFilter] = identity
+
+ given JsonEncoder[FieldFilter] = ZioJson.encoder
+ given JsonDecoder[FieldFilter] = ZioJson.decoder
extension (f: FieldFilter)
def asJsonZio: ZioJson = f
@@ -49,6 +57,9 @@ case class Field(
object Field {
given Encoder[Field] = deriveEncoder[Field]
given Decoder[Field] = deriveDecoder[Field]
+
+ given JsonEncoder[Field] = JsonEncoder.derived
+ given JsonDecoder[Field] = JsonDecoder.derived
}
case class Jwt(alg: Seq[String])
@@ -56,6 +67,9 @@ case class Jwt(alg: Seq[String])
object Jwt {
given Encoder[Jwt] = deriveEncoder[Jwt]
given Decoder[Jwt] = deriveDecoder[Jwt]
+
+ given JsonEncoder[Jwt] = JsonEncoder.derived
+ given JsonDecoder[Jwt] = JsonDecoder.derived
}
case class Ldp(proof_type: Seq[String])
@@ -63,6 +77,9 @@ case class Ldp(proof_type: Seq[String])
object Ldp {
given Encoder[Ldp] = deriveEncoder[Ldp]
given Decoder[Ldp] = deriveDecoder[Ldp]
+
+ given JsonEncoder[Ldp] = JsonEncoder.derived
+ given JsonDecoder[Ldp] = JsonDecoder.derived
}
enum ClaimFormatValue(val value: String) {
@@ -89,6 +106,9 @@ case class ClaimFormat(
object ClaimFormat {
given Encoder[ClaimFormat] = deriveEncoder[ClaimFormat]
given Decoder[ClaimFormat] = deriveDecoder[ClaimFormat]
+
+ given JsonEncoder[ClaimFormat] = JsonEncoder.derived
+ given JsonDecoder[ClaimFormat] = JsonDecoder.derived
}
case class Constraints(fields: Option[Seq[Field]])
@@ -96,6 +116,9 @@ case class Constraints(fields: Option[Seq[Field]])
object Constraints {
given Encoder[Constraints] = deriveEncoder[Constraints]
given Decoder[Constraints] = deriveDecoder[Constraints]
+
+ given JsonEncoder[Constraints] = JsonEncoder.derived
+ given JsonDecoder[Constraints] = JsonDecoder.derived
}
/** Refer to Input Descriptors
@@ -111,6 +134,9 @@ case class InputDescriptor(
object InputDescriptor {
given Encoder[InputDescriptor] = deriveEncoder[InputDescriptor]
given Decoder[InputDescriptor] = deriveDecoder[InputDescriptor]
+
+ given JsonEncoder[InputDescriptor] = JsonEncoder.derived
+ given JsonDecoder[InputDescriptor] = JsonDecoder.derived
}
/** Refer to Presentation
@@ -127,4 +153,7 @@ case class PresentationDefinition(
object PresentationDefinition {
given Encoder[PresentationDefinition] = deriveEncoder[PresentationDefinition]
given Decoder[PresentationDefinition] = deriveDecoder[PresentationDefinition]
+
+ given JsonEncoder[PresentationDefinition] = JsonEncoder.derived
+ given JsonDecoder[PresentationDefinition] = JsonDecoder.derived
}
diff --git a/pollux/prex/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationDefinitionValidator.scala b/pollux/prex/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationDefinitionValidator.scala
index 9b21a17d94..d0fba75b67 100644
--- a/pollux/prex/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationDefinitionValidator.scala
+++ b/pollux/prex/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationDefinitionValidator.scala
@@ -56,10 +56,11 @@ trait PresentationDefinitionValidator {
}
object PresentationDefinitionValidatorImpl {
- def layer: Layer[JsonSchemaError, PresentationDefinitionValidator] =
+ def layer: ULayer[PresentationDefinitionValidator] =
ZLayer.scoped {
JsonSchemaValidatorImpl.draft7Meta
.map(PresentationDefinitionValidatorImpl(_))
+ .orDieWith(e => Exception(s"Failed to load JSON schema draft-7 meta schema: $e"))
}
}
diff --git a/pollux/sql-doobie/src/main/resources/sql/pollux/V27__presentation_definition_table.sql b/pollux/sql-doobie/src/main/resources/sql/pollux/V27__presentation_definition_table.sql
new file mode 100644
index 0000000000..5faf02007a
--- /dev/null
+++ b/pollux/sql-doobie/src/main/resources/sql/pollux/V27__presentation_definition_table.sql
@@ -0,0 +1,16 @@
+CREATE TABLE public.presentation_definition (
+ id UUID PRIMARY KEY,
+ input_descriptors json NOT NULL,
+ name VARCHAR(300),
+ purpose VARCHAR(100),
+ format json,
+ wallet_id UUID NOT NULL,
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL
+);
+
+ALTER TABLE public.presentation_definition
+ ENABLE ROW LEVEL SECURITY;
+
+CREATE POLICY presentation_definition_wallet_isolation
+ ON public.presentation_definition
+ USING (wallet_id = current_setting('app.current_wallet_id')::UUID);
diff --git a/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/model/db/PresentationDefinition.scala b/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/model/db/PresentationDefinition.scala
new file mode 100644
index 0000000000..5b6d436a89
--- /dev/null
+++ b/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/model/db/PresentationDefinition.scala
@@ -0,0 +1,69 @@
+package org.hyperledger.identus.pollux.sql.model.db
+
+import io.getquill.*
+import io.getquill.context.json.PostgresJsonExtensions
+import io.getquill.doobie.DoobieContext
+import io.getquill.idiom.*
+import org.hyperledger.identus.pollux.prex
+import org.hyperledger.identus.shared.models.WalletId
+
+import java.time.Instant
+import java.util.UUID
+
+case class PresentationDefinition(
+ id: UUID,
+ input_descriptors: JsonValue[Seq[prex.InputDescriptor]],
+ name: Option[String],
+ purpose: Option[String],
+ format: Option[JsonValue[prex.ClaimFormat]],
+ createdAt: Instant,
+ walletId: WalletId
+)
+
+object PresentationDefinition {
+ def fromModel(pd: prex.PresentationDefinition, walletId: WalletId, createdAt: Instant): PresentationDefinition = {
+ PresentationDefinition(
+ id = UUID.fromString(pd.id),
+ input_descriptors = JsonValue(pd.input_descriptors),
+ name = pd.name,
+ purpose = pd.purpose,
+ format = pd.format.map(JsonValue(_)),
+ createdAt = createdAt,
+ walletId = walletId
+ )
+ }
+
+ extension (pd: PresentationDefinition) {
+ def toModel: prex.PresentationDefinition = {
+ prex.PresentationDefinition(
+ id = pd.id.toString(),
+ input_descriptors = pd.input_descriptors.value,
+ name = pd.name,
+ purpose = pd.purpose,
+ format = pd.format.map(_.value)
+ )
+ }
+ }
+}
+
+object PresentationDefinitionSql extends DoobieContext.Postgres(SnakeCase) with PostgresJsonExtensions {
+ def insert(pd: PresentationDefinition) = run {
+ quote {
+ query[PresentationDefinition].insertValue(lift(pd))
+ }
+ }
+
+ def findById(id: UUID) = run {
+ quote {
+ query[PresentationDefinition].filter(_.id == lift(id))
+ }
+ }
+
+ def lookupCount() = run { quote(query[PresentationDefinition].size) }
+
+ def lookup(offset: Int, limit: Int) = run {
+ quote {
+ query[PresentationDefinition].sortBy(_.createdAt).drop(lift(offset)).take(lift(limit))
+ }
+ }
+}
diff --git a/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcPresentationExchangeRepository.scala b/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcPresentationExchangeRepository.scala
new file mode 100644
index 0000000000..2c58dd6245
--- /dev/null
+++ b/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcPresentationExchangeRepository.scala
@@ -0,0 +1,67 @@
+package org.hyperledger.identus.pollux.sql.repository
+
+import doobie.*
+import doobie.implicits.*
+import doobie.util.transactor.Transactor
+import org.hyperledger.identus.pollux.core.repository.PresentationExchangeRepository
+import org.hyperledger.identus.pollux.prex.PresentationDefinition
+import org.hyperledger.identus.pollux.sql.model.db
+import org.hyperledger.identus.pollux.sql.model.db.PresentationDefinitionSql
+import org.hyperledger.identus.shared.db.ContextAwareTask
+import org.hyperledger.identus.shared.db.Implicits.*
+import org.hyperledger.identus.shared.models.WalletAccessContext
+import zio.*
+import zio.interop.catz.*
+
+import java.util.UUID
+
+class JdbcPresentationExchangeRepository(xa: Transactor[ContextAwareTask], xb: Transactor[Task])
+ extends PresentationExchangeRepository {
+
+ override def createPresentationDefinition(pd: PresentationDefinition): URIO[WalletAccessContext, Unit] = {
+ for {
+ now <- Clock.instant
+ walletId <- ZIO.serviceWith[WalletAccessContext](_.walletId)
+ row = db.PresentationDefinition.fromModel(pd, walletId, now)
+ _ <- PresentationDefinitionSql
+ .insert(row)
+ .transactWallet(xa)
+ .orDie
+ } yield ()
+ }
+
+ override def findPresentationDefinition(id: UUID): UIO[Option[PresentationDefinition]] = {
+ PresentationDefinitionSql
+ .findById(id)
+ .transact(xb)
+ .orDie
+ .map(_.headOption.map(_.toModel))
+ }
+
+ override def listPresentationDefinition(
+ offset: Option[Int],
+ limit: Option[Int]
+ ): URIO[WalletAccessContext, (Seq[PresentationDefinition], Int)] = {
+ val countCxnIO = PresentationDefinitionSql.lookupCount()
+ val pdCxnIO = PresentationDefinitionSql.lookup(
+ offset = offset.getOrElse(0),
+ limit = limit.getOrElse(100)
+ )
+
+ val effect =
+ for {
+ totalCount <- countCxnIO
+ rows <- pdCxnIO.map(_.map(_.toModel))
+ } yield (rows, totalCount.toInt)
+
+ effect
+ .transactWallet(xa)
+ .orDie
+ }
+
+}
+
+object JdbcPresentationExchangeRepository {
+ def layer: URLayer[Transactor[ContextAwareTask] & Transactor[Task], PresentationExchangeRepository] =
+ ZLayer.fromFunction(JdbcPresentationExchangeRepository(_, _))
+}
diff --git a/shared/core/src/main/scala/org/hyperledger/identus/shared/models/KeyId.scala b/shared/core/src/main/scala/org/hyperledger/identus/shared/models/KeyId.scala
index f6cbc60efe..185cd59732 100644
--- a/shared/core/src/main/scala/org/hyperledger/identus/shared/models/KeyId.scala
+++ b/shared/core/src/main/scala/org/hyperledger/identus/shared/models/KeyId.scala
@@ -1,6 +1,6 @@
package org.hyperledger.identus.shared.models
-import zio.json._
+import zio.json.*
opaque type KeyId = String
object KeyId: