# XamiLib Java — Referencia de clases

Paquete: `run.xami.sdk`. El punto de entrada es la clase `XamiSDK`. Los métodos siguen
la convención camelCase de Java. La opción `sign()` usa un builder fluido
(`new Pades.SignOptions().credentialKey(...).reason(...)`). Como `wait` es palabra
reservada en Java, ese método se llama `await`.

---

## `XamiSDK`

Punto de entrada de la librería.

### Constructor

```java
new XamiSDK(XamiConfig config)
```

`XamiConfig` acepta (vía setters fluidos):

| Setter | Descripción |
|---|---|
| `setEndpoint(String)` | URL del servicio local (por defecto `http://127.0.0.1:8300`). |
| `setWrapperKey(String)` | Credencial de aplicación (`wrp_...`). |
| `setWrapperSecret(String)` | Secret de la credencial (`wsec_...`). |
| `setTimeoutSeconds(int)` | Timeout HTTP en segundos (30 por defecto). |

### Métodos

| Método | Devuelve | Descripción |
|---|---|---|
| `pades()` | `Pades` | Servicio de firma de documentos PDF. |
| `blockchain()` | `Blockchain` | Servicio de firma de transacciones EVM. |
| `credentials()` | `Credentials` | Consulta de credenciales. |
| `designs()` | `Designs` | Consulta de diseños de sello. |
| `health()` | `Health` | Estado del servicio local. |
| `results()` | `Results` | Resultados de firma recientes. *(xamiSDK ≥ 0.2.0)* |
| `errors()` | `Errors` | Errores registrados por el servicio local. *(xamiSDK ≥ 0.2.0)* |
| `sync(): Map<String,Object>` | resumen | Recarga credenciales y diseños desde Xami sin reiniciar. *(xamiSDK ≥ 0.2.0)* |

---

## `Pades`

Firma de documentos PDF (PAdES).

### Métodos

#### `sign(byte[] pdfBytes, Pades.SignOptions opts): String`
Envía un PDF a firmar. Devuelve el `request_id`. `SignOptions`: `credentialKey`
(requerido), `designKey`, `variables`, `reason`, `location`, `signerName`.

#### `result(String requestId): Map<String,Object>`
Consulta el estado. Cuando está `DONE`, incluye el PDF firmado en `pdf_base64`.

#### `await(String requestId, int timeoutSeconds, double pollSeconds): byte[]`
Bloquea hasta que la firma esté lista y devuelve el PDF firmado. Sobrecarga
`await(requestId)` usa 60s / 1.0s por defecto.

#### `signAndWait(byte[] pdfBytes, Pades.SignOptions opts, int timeoutSeconds): byte[]`
Atajo: `sign()` + `await()`. Devuelve el PDF firmado. Sobrecarga sin `timeoutSeconds`
usa 60s.

### Ejemplo

```java
byte[] pdfBytes = Files.readAllBytes(Path.of("documento.pdf"));
byte[] firmado = xami.pades().signAndWait(pdfBytes, new Pades.SignOptions()
        .credentialKey("TU_CREDENCIAL")
        .signerName("Tu Nombre")
        .reason("Aprobación")
        .variables(Map.of("name", "Tu Nombre")));
Files.write(Path.of("documento_firmado.pdf"), firmado);
```

---

## `Blockchain`

Firma de transacciones / mensajes EVM. El chip actúa como wallet y devuelve `r`/`s`/`v`;
tú ensamblas la transacción con tu librería EVM.

### Métodos

#### `sign(String txHash, Blockchain.SignOptions opts): String`
Envía el hash a firmar. Devuelve el `request_id`. `SignOptions`: `credentialKey`
(requerido, credencial EVM), `chainId`.

#### `result(String requestId): Map<String,Object>`
Consulta el estado.

#### `await(String requestId, int timeoutSeconds, double pollSeconds): Map<String,Object>`
Bloquea hasta tener la firma. Devuelve el mapa con `r`/`s`/`v`/`signature`.

#### `signAndWait(String txHash, Blockchain.SignOptions opts, int timeoutSeconds): Map<String,Object>`
Atajo: `sign()` + `await()`.

### Ejemplo

```java
Map<String, Object> firma = xami.blockchain().signAndWait("0xHASH_DE_LA_TX",
        new Blockchain.SignOptions().credentialKey("TU_CREDENCIAL_EVM").chainId(648541));
// firma.get("r"), firma.get("s"), firma.get("v")
```

---

## `Credentials`

Consulta de credenciales en la caché local.

| Método | Devuelve | Descripción |
|---|---|---|
| `all(): List<Map<String,Object>>` | lista | Todas las credenciales disponibles. |
| `get(String key): Map<String,Object>` | credencial o `null` | Una credencial por su `credential_key`. |

---

## `Designs`

Consulta de diseños de sello en la caché local.

| Método | Devuelve | Descripción |
|---|---|---|
| `all(): List<Map<String,Object>>` | lista | Todos los diseños disponibles. |
| `get(String key): Map<String,Object>` | diseño o `null` | Un diseño por su `design_key`. |

---

## `Health`

| Método | Devuelve | Descripción |
|---|---|---|
| `self(): Map<String,Object>` | estado | Estado del servicio local (pareado, tenant, versión, etc.). |
| `version(): String` | versión | Versión del xamiSDK local. `null` si es anterior a 0.2.0. |
| `apiVersion(): int` | entero | Versión del contrato local. `1` = sin `sync()`, `results()` ni `errors()`. |

---

## `Results`

*Requiere xamiSDK ≥ 0.2.0.*

`Pades.result()` necesita que conserves el `requestId`. Si tu proceso se reinició o el
push no llegó, ese documento quedaba inalcanzable desde la librería. Con `Results`
puedes recuperar lo firmado sin depender de tu propio almacenamiento.

| Método | Devuelve | Descripción |
|---|---|---|
| `recent(int limit): List<Map<String,Object>>` | lista | Últimos resultados (`PENDING` / `DONE` / `ERROR`). Sobrecarga sin argumentos usa 50. |
| `pending(int limit): List<Map<String,Object>>` | lista | Solo los que siguen esperando la firma del chip. Sobrecarga sin argumentos usa 50. |

```java
for (Map<String, Object> r : xami.results().pending()) {
    System.out.println(r.get("request_id") + " lleva esperando desde " + r.get("created_at"));
}
```

---

## `Errors`

*Requiere xamiSDK ≥ 0.2.0.*

Devuelve el mensaje corto y el `error_id` de cada fallo. **Nunca devuelve el
traceback**: el detalle técnico solo sale del equipo del cliente cuando alguien
ejecuta `xamisdk report`. Está pensado para que tu aplicación pueda decirle al usuario
qué falló y con qué identificador pedir soporte.

| Método | Devuelve | Descripción |
|---|---|---|
| `recent(int limit): List<Map<String,Object>>` | lista | Últimos errores registrados. Sobrecarga sin argumentos usa 20. |
| `forRequest(String requestId): List<Map<String,Object>>` | lista | Errores de un request concreto. |

```java
List<Map<String, Object>> fallos = xami.errors().forRequest(requestId);
if (!fallos.isEmpty()) {
    System.out.println("No se pudo firmar: " + fallos.get(0).get("short"));
    System.out.println("Menciona " + fallos.get(0).get("error_id") + " al pedir soporte.");
}
```

---

## Compatibilidad de versiones

Los métodos marcados con *xamiSDK ≥ 0.2.0* devuelven `404` contra un servicio
anterior. Compruébalo antes si no controlas la versión instalada:

```java
if (xami.health().apiVersion() >= 2) {
    xami.sync();
}
```

---

## Manejo de errores

Todos los métodos lanzan `run.xami.sdk.XamiException` (extiende `RuntimeException`)
ante un fallo (credencial inválida, servicio caído, timeout). Expone `getMessage()` y
`getCode()` (`-1` cuando no aplica, p. ej. error de red).

```java
try {
    byte[] pdf = xami.pades().signAndWait(bytes, new Pades.SignOptions().credentialKey("..."));
} catch (XamiException e) {
    System.err.println("Error al firmar: " + e.getMessage() + " (" + e.getCode() + ")");
}
```
