# XamiLib Ruby — Referencia de clases

Módulo: `XamiSDKClient`. El punto de entrada es la clase `XamiSDK`. Los métodos siguen
la convención snake_case de Ruby. `Health#self` está expuesto como `self_status`, con
el alias `self` (por compatibilidad con el resto de SDKs de esta suite).

---

## `XamiSDK`

Punto de entrada de la librería.

### Constructor

```ruby
XamiSDKClient::XamiSDK.new(config = {})
```

`config` acepta:

| Clave | Descripción |
|---|---|
| `:endpoint` | URL del servicio local (por defecto `http://127.0.0.1:8300`). |
| `:wrapper_key` | Credencial de aplicación (`wrp_...`). |
| `:wrapper_secret` | Secret de la credencial (`wsec_...`). |
| `:timeout` | Timeout HTTP en segundos (opcional, 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` | `Hash` | Recarga credenciales y diseños desde Xami sin reiniciar. *(xamiSDK ≥ 0.2.0)* |

---

## `Pades`

Firma de documentos PDF (PAdES).

### Métodos

#### `sign(pdf_bytes, opts = {})`
Envía un PDF a firmar. Devuelve el `request_id`. `opts`: `credential_key` (requerido),
`design_key`, `variables`, `reason`, `location`, `signer_name`.

#### `result(request_id)`
Consulta el estado. Cuando está `DONE`, incluye el PDF firmado (`pdf_base64`).

#### `wait(request_id, timeout_seconds: 60, poll_seconds: 1.0)`
Bloquea hasta que la firma esté lista y devuelve el PDF firmado (bytes).

#### `sign_and_wait(pdf_bytes, opts = {}, timeout_seconds: 60)`
Atajo: `sign()` + `wait()`. Devuelve el PDF firmado.

### Ejemplo

```ruby
pdf_firmado = xami.pades.sign_and_wait(
  File.binread('documento.pdf'),
  {
    credential_key: 'TU_CREDENCIAL',
    signer_name: 'Tu Nombre',
    reason: 'Aprobación',
    variables: { name: 'Tu Nombre' }
  }
)
File.binwrite('documento_firmado.pdf', 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(tx_hash, opts = {})`
Envía el hash a firmar. Devuelve el `request_id`. `opts`: `credential_key` (requerido,
credencial EVM), `chain_id`.

#### `result(request_id)`
Consulta el estado.

#### `wait(request_id, timeout_seconds: 60, poll_seconds: 1.0)`
Bloquea hasta tener la firma. Devuelve `{"r"=>..., "s"=>..., "v"=>..., "signature"=>...}`.

#### `sign_and_wait(tx_hash, opts = {}, timeout_seconds: 60)`
Atajo: `sign()` + `wait()`.

### Ejemplo

```ruby
firma = xami.blockchain.sign_and_wait('0xHASH_DE_LA_TX', {
  credential_key: 'TU_CREDENCIAL_EVM',
  chain_id: 648541
})
# firma['r'], firma['s'], firma['v']
```

---

## `Credentials`

Consulta de credenciales en la caché local.

| Método | Devuelve | Descripción |
|---|---|---|
| `all` | `Array` | Todas las credenciales disponibles. |
| `get(key)` | credencial o `nil` | Una credencial por su `credential_key`. |

---

## `Designs`

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

| Método | Devuelve | Descripción |
|---|---|---|
| `all` | `Array` | Todos los diseños disponibles. |
| `get(key)` | diseño o `nil` | Un diseño por su `design_key`. |

---

## `Health`

| Método | Devuelve | Descripción |
|---|---|---|
| `self` (alias de `self_status`) | `Hash` | Estado del servicio local (pareado, tenant, versión, etc.). |
| `version` | versión | Versión del xamiSDK local. `nil` si es anterior a 0.2.0. |
| `api_version` | entero | Versión del contrato local. `1` = sin `sync`, `results` ni `errors`. |

---

## `Results`

*Requiere xamiSDK ≥ 0.2.0.*

`Pades#result` necesita que conserves el `request_id`. 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(limit = 50)` | `Array` | Últimos resultados (`PENDING` / `DONE` / `ERROR`). |
| `pending(limit = 50)` | `Array` | Solo los que siguen esperando la firma del chip. |

```ruby
xami.results.pending.each do |r|
  puts "#{r['request_id']} lleva esperando desde #{r['created_at']}"
end
```

---

## `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(limit = 20)` | `Array` | Últimos errores registrados. |
| `for_request(request_id)` | `Array` | Errores de un request concreto. |

```ruby
fallos = xami.errors.for_request(request_id)
if fallos.any?
  puts "No se pudo firmar: #{fallos.first['short']}"
  puts "Menciona #{fallos.first['error_id']} al pedir soporte."
end
```

---

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

```ruby
xami.sync if xami.health.api_version >= 2
```

---

## Manejo de errores

Todos los métodos lanzan `XamiSDKClient::XamiException` ante un fallo (credencial
inválida, servicio caído, timeout). Expone `message` y `code`.

```ruby
begin
  pdf = xami.pades.sign_and_wait(bytes, { credential_key: '...' })
rescue XamiSDKClient::XamiException => e
  puts "Error al firmar: #{e.message} (#{e.code})"
end
```
