Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 52 additions & 20 deletions oid4vc/integration/credo_wrapper/__init__.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
"""AFJ Wrapper."""
"""Credo Wrapper."""

from jrpc_client import BaseSocketTransport, JsonRpcClient
from __future__ import annotations

import httpx


class CredoWrapper:
"""Credo Wrapper."""
"""Credo Wrapper using HTTP."""

def __init__(self, transport: BaseSocketTransport, client: JsonRpcClient):
def __init__(self, base_url: str):
"""Initialize the wrapper."""
self.transport = transport
self.client = client
self.base_url = base_url.rstrip("/")
self.client: httpx.AsyncClient | None = None

async def start(self):
"""Start the wrapper."""
await self.transport.connect()
await self.client.start()
await self.client.request("initialize")
self.client = httpx.AsyncClient()
# Check Credo agent health
response = await self.client.get(f"{self.base_url}/health", timeout=30.0)
response.raise_for_status()

async def stop(self):
"""Stop the wrapper."""
await self.client.stop()
await self.transport.close()
if self.client:
await self.client.aclose()
self.client = None

def _client(self) -> httpx.AsyncClient:
if not self.client:
raise RuntimeError(
"CredoWrapper not started; use within an async context manager"
)
return self.client

async def __aenter__(self):
"""Start the wrapper when entering the context manager."""
Expand All @@ -33,16 +44,37 @@ async def __aexit__(self, exc_type, exc, tb):

# Credo API

async def openid4vci_accept_offer(self, offer: str):
async def test(self):
"""Test basic connectivity to Credo agent."""
response = await self._client().get(f"{self.base_url}/health", timeout=30.0)
response.raise_for_status()
return response.json()

async def openid4vci_accept_offer(self, offer: str, holder_did_method: str = "key"):
"""Accept OpenID4VCI credential offer."""
return await self.client.request(
"openid4vci.acceptCredentialOffer",
offer=offer,
response = await self._client().post(
f"{self.base_url}/oid4vci/accept-offer",
json={"credential_offer": offer, "holder_did_method": holder_did_method},
timeout=120.0,
)
response.raise_for_status()
return response.json()

async def openid4vp_accept_request(self, request: str, credentials: list = None):
"""Accept OpenID4VP presentation (authorization) request.

Args:
request: The presentation request URI
credentials: List of credentials to present (can be strings for mso_mdoc or dicts)
"""
payload = {"request_uri": request}
if credentials:
payload["credentials"] = credentials

async def openid4vp_accept_request(self, request: str):
"""Accept OpenID4VP presentation (authorization) request."""
return await self.client.request(
"openid4vci.acceptAuthorizationRequest",
request=request,
response = await self._client().post(
f"{self.base_url}/oid4vp/present",
json=payload,
timeout=120.0,
)
response.raise_for_status()
return response.json()
3 changes: 2 additions & 1 deletion oid4vc/integration/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ services:
ACAPY_VERSION: 1.4.0
working_dir: /usr/src/app
environment:
- REQUIRE_MDOC=true
- REQUIRE_MDOC=false
- CREDO_AGENT_URL=http://credo-agent:3020
- SPHEREON_WRAPPER_URL=http://sphereon-wrapper:3010
- ACAPY_ISSUER_ADMIN_URL=http://acapy-issuer:8021
Expand All @@ -149,6 +149,7 @@ services:
volumes:
- ./test-results:/usr/src/app/test-results
- ./tests:/usr/src/app/tests
- ./credo_wrapper:/usr/src/app/credo_wrapper
- ./pyproject.toml:/usr/src/app/pyproject.toml
# Static cert mounts removed - certs generated dynamically in tests
depends_on:
Expand Down
Loading