Metadata-Version: 2.4
Name: daiedge-middleware-client
Version: 1.1.1
Summary: Python client library for the dAIEDGE Middleware API
Author-email: BISITE Research group <bisite@usal.es>
Project-URL: Homepage, https://bisite.github.io/dAIEdge-middleware/
Project-URL: Documentation, https://bisite.github.io/dAIEdge-middleware/docs/
Project-URL: Repository, https://github.com/bisite/dAIEDGE-Middleware-client
Project-URL: Issues, https://github.com/bisite/dAIEDGE-Middleware-client/issues
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: daiedge-middleware-client-api-v1==1.0.1
Requires-Dist: daiedge-middleware-client-api-v2==1.0.0
Requires-Dist: python-dateutil>=2.8.2
Requires-Dist: httpx>=0.28.1
Requires-Dist: pydantic>=2
Requires-Dist: typing-extensions>=4.7.1
Requires-Dist: sqlalchemy[asyncio]>=2.0
Requires-Dist: aiosqlite>=0.22.1
Requires-Dist: eth-account>=0.13
Requires-Dist: cryptography>=43.0
Provides-Extra: postgres
Requires-Dist: asyncpg>=0.31.0; extra == "postgres"

# dAIEDGE Middleware Client

[![Python](https://img.shields.io/pypi/pyversions/daiedge-middleware-client)](https://pypi.org/project/daiedge-middleware-client/)
[![License](https://img.shields.io/pypi/l/daiedge-middleware-client)](https://pypi.org/project/daiedge-middleware-client/)

Python client library for the dAIEDGE Middleware API.

## About

The dAIEDGE Middleware is a core component of the [dAIEDGE Network of Excellence](https://daiedge.eu/about), designed to be a versatile bridge layer that provides communication, integration, and orchestration capabilities in complex, distributed edge AI environments.

This package provides a Python client for interacting with the dAIEDGE Middleware API, which offers functionalities for:

- **Authentication & User Management** — Secure login, logout, and user registration
- **Identity & DID Management** — Decentralized Identifiers (DID) management
- **Verifiable Credentials** — VC issuance, verification, and presentations
- **Role-Based Access Control** — Fine-grained access control policies
- **Resource Registration** — Hardware, AI models, datasets, and benchmarks
- **Marketplace** — Resource trading and listing
- **Token Management** — Token minting and balance queries
- **Licensing** — License request and validation
- **Reward System** — Manual and automatic reward distribution

---

## Requirements

- Python 3.10+

## Installation

```sh
pip install daiedge-middleware-client
```

For PostgreSQL storage support (v2 mode only):

```sh
pip install "daiedge-middleware-client[postgres]"
```

---

## Backwards Compatibility

**Existing code requires no changes.**

`Configuration()` defaults to **v1 custodial mode**. All existing imports, method names, and response models remain supported. The v2 non-custodial mode is opt-in via `api_version="v2"`.

---

## Quick Start — v1 Custodial Mode (default)

The default API host is already configured to `https://middleware-daiedge.bisite.usal.es/api/v1`.

```python
import asyncio
from daiedge_middleware_client import ApiClient, AuthApi
from daiedge_middleware_client.models import LoginRequest
from daiedge_middleware_client.exceptions import ApiException

async def main():
    async with ApiClient() as api_client:
        auth_api = AuthApi(api_client)
        try:
            response = await auth_api.auth_login_post(
                LoginRequest(username="your_username", password="your_password")
            )
            print(f"Login successful! Session ID: {response.session_id}")
            api_client.default_headers["x-session-id"] = response.session_id
        except ApiException as e:
            print(f"Login failed: {e}")

asyncio.run(main())
```

In v1 mode the server manages wallets and private keys on behalf of the user (custodial). Every API call is forwarded directly to the backend.

---

## v2 Non-custodial Mode

In v2 mode the client manages private keys locally. The server never receives private keys or passwords. Auth challenges and blockchain transactions are signed on the client and the signed result is forwarded to the backend.

### SQLite setup (recommended for local development)

```python
import asyncio
from daiedge_middleware_client import Configuration, ApiClient, AuthApi
from daiedge_middleware_client.models import SignupRequest, LoginRequest

config = Configuration(
    api_version="v2",
    host="https://middleware.example.com/api/v1",
    storage_url="sqlite+aiosqlite:///daiedge-client.db",
    rpc_url="http://localhost:8545",
)

async def main():
    async with ApiClient(config) as api_client:
        auth = AuthApi(api_client)

        # Sign up — creates a local user and an encrypted default wallet
        await auth.auth_signup_post(
            SignupRequest(username="alice", email="alice@example.com", password="s3cr3t")
        )

        # Log in — signs a DID challenge, stores session, injects Bearer header automatically
        login = await auth.auth_login_post(
            LoginRequest(username="alice", password="s3cr3t")
        )
        api_client.default_headers["x-session-id"] = login.session_id

        # All subsequent API calls are now authenticated
        ...

asyncio.run(main())
```

> **Data backup warning:** `daiedge-client.db` contains your encrypted private keys. Back it up regularly. There is no cloud recovery — if the file is lost, access to the associated wallets is permanently lost.

> **Password warning:** Passwords are sovereign and unrecoverable. If you forget your wallet password, the encrypted private key cannot be decrypted. There is no reset mechanism.

### PostgreSQL setup (production)

Install the extra dependency:

```sh
# development
uv sync --extra postgres --dev

# installed package
pip install "daiedge-middleware-client[postgres]"
```

```python
config = Configuration(
    api_version="v2",
    host="https://middleware.example.com/api/v1",
    storage_url="postgresql+asyncpg://user:password@localhost:5432/daiedge",
    rpc_url="http://localhost:8545",
)
```

> **Security note:** Use a dedicated database user with least-privilege access. Restrict network access to the database host. Use TLS for the connection string in production environments.

### Environment variables

Instead of hard-coding credentials, configure v2 settings via environment variables:

| Variable | Description |
|---|---|
| `DAIEDGE_STORAGE_URL` | SQLAlchemy async database URL |
| `DAIEDGE_RPC_URL` | Blockchain JSON-RPC endpoint |

```python
# Reads DAIEDGE_STORAGE_URL and DAIEDGE_RPC_URL from the environment
config = Configuration(api_version="v2", host="https://middleware.example.com/api/v1")
```

---

## Security Model

- **Private keys are encrypted locally** using a password-derived key (PBKDF2, 600 000 iterations by default). The encrypted ciphertext is stored in the local database.
- **Passwords are sovereign and unrecoverable.** The server never stores or receives them.
- **The server never receives private keys.** All signing happens on the client before any data is sent.
- **Auth challenges are signed locally.** On login, the backend issues a DID challenge; the client signs it with the wallet's private key and returns only the signature.
- **Transactions are signed locally.** The backend prepares unsigned transactions and returns `{ tx }` or `{ txs }`. The client signs them and relays only the signed raw transaction.

---

## Transaction Flow (v2 mode)

You do not need to interact with a Web3 library directly for normal usage. The client handles the full flow transparently:

1. Your code calls an API method that triggers a blockchain write (e.g. `access_grant_access_post`).
2. The backend validates the request and returns a prepared unsigned transaction: `{ "tx": { "to": "0x...", "data": "0x..." } }`.
3. The client intercepts the response, signs the transaction locally using the session's private key, and relays the signed raw transaction to the backend relay endpoint.
4. The backend broadcasts the transaction to the network and returns the transaction hash.

For batch operations the backend may return `{ "txs": [...] }` — the client signs and relays each transaction in order.

---

## Using Session Authentication

The `session_id` returned by `auth_login_post` must be set in `default_headers` to authenticate subsequent requests. This works the same way in both v1 and v2 modes:

```python
from daiedge_middleware_client import ApiClient, AuthApi, IdentityApi
from daiedge_middleware_client.models import LoginRequest

async with ApiClient(config) as api_client:
    auth = AuthApi(api_client)
    login = await auth.auth_login_post(LoginRequest(username="alice", password="s3cr3t"))

    # Set session header — required for authenticated endpoints
    api_client.default_headers["x-session-id"] = login.session_id

    identity_api = IdentityApi(api_client)
    identity = await identity_api.identities_get()
```

In v2 mode the `Authorization: Bearer <jwt>` header is injected automatically by `auth_login_post` — no extra step required.

---

## Custom API Host

```python
from daiedge_middleware_client import Configuration, ApiClient

config = Configuration(host="https://your-custom-api.example.com/api/v1")
async with ApiClient(config) as api_client:
    ...
```

---

## Migration from v1-only usage to v2

If you are currently using the package in v1 mode and want to adopt v2 non-custodial mode:

1. **Install** (no package change required — v2 is included in the same wheel):
   ```sh
   pip install --upgrade daiedge-middleware-client
   ```

2. **Add** `api_version="v2"`, `storage_url`, and `rpc_url` to your `Configuration`.

3. **Sign up** existing users through `AuthApi.auth_signup_post` — this creates a local user record and an encrypted wallet. Existing backend accounts are not migrated automatically; the local user record is separate from the backend account.

4. **Replace** any direct `walletId` / `password` fields in write request bodies — v2 mode strips these automatically and signs transactions locally. You do not need to pass them.

5. **Remove** any `wallet_id` / `password` kwargs from `benchmark_id_get` calls — these parameters were removed in the v2 API and are silently ignored by the facade.

6. **Wrap** all API usage in `async with ApiClient(config) as client:` — this ensures the local database connection and HTTP client are properly closed.

> Existing v1 callers continue to work without any changes. The migration is opt-in.

---

## Available API Modules

| Module | Description |
|---|---|
| `AccessControlApi` | Access control and permissions |
| `AuthApi` | Authentication (login, logout, signup) |
| `IdentityApi` | DID and identity management |
| `LicenseApi` | License management |
| `MarketplaceApi` | Resource marketplace |
| `PolicyApi` | Policy management |
| `RegisterAiModelApi` | AI model registration |
| `RegisterBenchmarkApi` | Benchmark registration |
| `RegisterDatasetApi` | Dataset registration |
| `RegisterHardwareApi` | Hardware registration |
| `RewardManagerApi` | Reward system |
| `RoleManagementApi` | Role management |
| `SystemPauseApi` | System pause/control |
| `TokensApi` | Token operations |
| `UsersApi` | User management |
| `VcApi` | Verifiable Credentials |
| `WalletApi` | Wallet operations |

All modules are imported directly from the root package. Do not import from `daiedge_middleware_client_api_v1` or `daiedge_middleware_client_api_v2` — those are internal implementation packages.

---

## Documentation

- [Official Documentation](https://bisite.github.io/dAIEdge-middleware/)
- [Getting Started Guide](https://bisite.github.io/dAIEdge-middleware/docs/getting-started/)
- [Tutorials](https://bisite.github.io/dAIEdge-middleware/docs/tutorials/)
- [API Reference](https://middleware-daiedge.bisite.usal.es/api-docs)
- [About dAIEDGE](https://daiedge.eu/about)

---

## Development

This repository is a [uv workspace](https://docs.astral.sh/uv/concepts/workspaces/) with three packages:

| Package | Path | Description |
|---|---|---|
| `daiedge-middleware-client` | `.` | Root facade package (this package) |
| `daiedge-middleware-client-api-v1` | `v1/` | Generated raw v1 client |
| `daiedge-middleware-client-api-v2` | `v2/` | Generated raw v2 client |

The `v1/` and `v2/` packages are generated from OpenAPI specs using the OpenAPI Generator and then normalised for uv workspace metadata. They are first-party workspace dependencies — do not edit them manually.

### Setup

```sh
uv sync --locked --all-extras --dev
```

### Running tests

```sh
uv run pytest
```

### Linting and formatting

```sh
uv run ruff check .
uv run ruff format --check .
```

### Verifying workspace members

```sh
uv run --package daiedge-middleware-client-api-v1 python -c "import daiedge_middleware_client_api_v1"
uv run --package daiedge-middleware-client-api-v2 python -c "import daiedge_middleware_client_api_v2"
```

### Building all packages

```sh
uv build --all-packages
```

### Release strategy

All three packages are versioned and published independently to PyPI. The root package declares `daiedge-middleware-client-api-v1` and `daiedge-middleware-client-api-v2` as runtime dependencies, so installing the root package is sufficient for end users.

---

## License

Proprietary - All rights reserved.

## Author

BISITE Research group <bisite@usal.es>

## Resources

- [GitHub Repository](https://github.com/bisite/dAIEDGE-Middleware-client)
- [dAIEDGE Project Website](https://daiedge.eu)
- [dAIEDGE Middleware Docs](https://bisite.github.io/dAIEdge-middleware/)
