# XamiLib .NET — Referencia de clases

Namespace: `XamiSdk`. El punto de entrada es la clase `XamiSDK`, que da acceso a los
distintos servicios. Todos los métodos son `async`/`Task` y siguen la convención
PascalCase de .NET (`SignAsync`, `ResultAsync`...).

---

## `XamiSDK`

Punto de entrada de la librería. Implementa `IDisposable`.

### Constructor

```csharp
new XamiSDK(XamiConfig config)
```

`XamiConfig` acepta:

| Propiedad | Descripción |
|---|---|
| `Endpoint` | URL del servicio local (por defecto `http://127.0.0.1:8300`). |
| `WrapperKey` | Credencial de aplicación (`wrp_...`). |
| `WrapperSecret` | Secret de la credencial (`wsec_...`). |
| `TimeoutSeconds` | 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)* |
| `SyncAsync(): Task<JsonObject>` | resumen | Recarga credenciales y diseños desde Xami sin reiniciar. *(xamiSDK ≥ 0.2.0)* |

---

## `Pades`

Firma de documentos PDF (PAdES).

### Métodos

#### `SignAsync(byte[] pdfBytes, PadesSignOptions opts): Task<string>`
Envía un PDF a firmar. Devuelve el `request_id`. `PadesSignOptions`: `CredentialKey`
(requerido), `DesignKey`, `Variables`, `Reason`, `Location`, `SignerName`.

#### `ResultAsync(string requestId): Task<JsonObject>`
Consulta el estado. Cuando está `DONE`, incluye el PDF firmado en `pdf_base64`.

#### `WaitAsync(string requestId, int timeoutSeconds = 60, double pollSeconds = 1.0): Task<byte[]>`
Bloquea hasta que la firma esté lista y devuelve el PDF firmado.

#### `SignAndWaitAsync(byte[] pdfBytes, PadesSignOptions opts, int timeoutSeconds = 60): Task<byte[]>`
Atajo: `SignAsync()` + `WaitAsync()`. Devuelve el PDF firmado.

### Ejemplo

```csharp
var pdfFirmado = await xami.Pades().SignAndWaitAsync(
    await File.ReadAllBytesAsync("documento.pdf"),
    new PadesSignOptions
    {
        CredentialKey = "TU_CREDENCIAL",
        SignerName    = "Tu Nombre",
        Reason        = "Aprobación",
        Variables     = new Dictionary<string, object?> { ["name"] = "Tu Nombre" },
    });
await File.WriteAllBytesAsync("documento_firmado.pdf", pdfFirmado);
```

---

## `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

#### `SignAsync(string txHash, BlockchainSignOptions opts): Task<string>`
Envía el hash a firmar. Devuelve el `request_id`. `BlockchainSignOptions`:
`CredentialKey` (requerido, credencial EVM), `ChainId`.

#### `ResultAsync(string requestId): Task<JsonObject>`
Consulta el estado.

#### `WaitAsync(string requestId, int timeoutSeconds = 60, double pollSeconds = 1.0): Task<JsonObject>`
Bloquea hasta tener la firma. Devuelve el objeto con `r`/`s`/`v`/`signature`.

#### `SignAndWaitAsync(string txHash, BlockchainSignOptions opts, int timeoutSeconds = 60): Task<JsonObject>`
Atajo: `SignAsync()` + `WaitAsync()`.

### Ejemplo

```csharp
var firma = await xami.Blockchain().SignAndWaitAsync("0xHASH_DE_LA_TX", new BlockchainSignOptions
{
    CredentialKey = "TU_CREDENCIAL_EVM",
    ChainId       = 648541,
});
// firma["r"], firma["s"], firma["v"]
```

---

## `Credentials`

Consulta de credenciales en la caché local.

| Método | Devuelve | Descripción |
|---|---|---|
| `AllAsync(): Task<List<JsonObject>>` | lista | Todas las credenciales disponibles. |
| `GetAsync(string key): Task<JsonObject?>` | 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 |
|---|---|---|
| `AllAsync(): Task<List<JsonObject>>` | lista | Todos los diseños disponibles. |
| `GetAsync(string key): Task<JsonObject?>` | diseño o `null` | Un diseño por su `design_key`. |

---

## `Health`

| Método | Devuelve | Descripción |
|---|---|---|
| `SelfAsync(): Task<JsonObject>` | estado | Estado del servicio local (pareado, tenant, versión, etc.). |
| `VersionAsync(): Task<string?>` | versión | Versión del xamiSDK local. `null` si es anterior a 0.2.0. |
| `ApiVersionAsync(): Task<int>` | entero | Versión del contrato local. `1` = sin `Sync`, `Results` ni `Errors`. |

---

## `Results`

*Requiere xamiSDK ≥ 0.2.0.*

`Pades.ResultAsync()` 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 |
|---|---|---|
| `RecentAsync(int limit = 50): Task<List<JsonObject>>` | lista | Últimos resultados (`PENDING` / `DONE` / `ERROR`). |
| `PendingAsync(int limit = 50): Task<List<JsonObject>>` | lista | Solo los que siguen esperando la firma del chip. |

```csharp
foreach (var r in await xami.Results().PendingAsync())
    Console.WriteLine($"{r["request_id"]} lleva esperando desde {r["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 |
|---|---|---|
| `RecentAsync(int limit = 20): Task<List<JsonObject>>` | lista | Últimos errores registrados. |
| `ForRequestAsync(string requestId): Task<List<JsonObject>>` | lista | Errores de un request concreto. |

```csharp
var fallos = await xami.Errors().ForRequestAsync(requestId);
if (fallos.Count > 0)
{
    Console.WriteLine($"No se pudo firmar: {fallos[0]["short"]}");
    Console.WriteLine($"Menciona {fallos[0]["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:

```csharp
if (await xami.Health().ApiVersionAsync() >= 2)
{
    await xami.SyncAsync();
}
```

---

## Manejo de errores

Todos los métodos lanzan `XamiSdk.XamiException` ante un fallo (credencial inválida,
servicio caído, timeout). Expone `Message` y `Code` (código HTTP, `null` en errores de
red).

```csharp
try
{
    var pdf = await xami.Pades().SignAndWaitAsync(bytes, new PadesSignOptions { CredentialKey = "..." });
}
catch (XamiException e)
{
    Console.WriteLine($"Error al firmar: {e.Message} ({e.Code})");
}
```
