# XamiLib Go — Referencia de clases

Paquete: `xamisdk`. El punto de entrada es `XamiSDK`, creado con `xamisdk.New(cfg)`.
Todos los métodos devuelven `error` como último valor; el error concreto es
`*xamisdk.XamiException`.

---

## `XamiSDK`

Punto de entrada de la librería.

### Constructor

```go
xamisdk.New(cfg xamisdk.Config) *XamiSDK
```

`Config` acepta:

| Campo | 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)* |
| `Sync() (map[string]interface{}, error)` | resumen | Recarga credenciales y diseños desde Xami sin reiniciar. *(xamiSDK ≥ 0.2.0)* |

---

## `Pades`

Firma de documentos PDF (PAdES).

### Métodos

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

#### `Result(requestID string) (map[string]interface{}, error)`
Consulta el estado. Cuando está `DONE`, incluye el PDF firmado en `pdf_base64`.

#### `Wait(requestID string, timeoutSeconds int, pollSeconds float64) ([]byte, error)`
Bloquea hasta que la firma esté lista y devuelve el PDF firmado.

#### `SignAndWait(pdfBytes []byte, opts PadesSignOptions, timeoutSeconds int) ([]byte, error)`
Atajo: `Sign()` + `Wait()`. Devuelve el PDF firmado.

### Ejemplo

```go
pdfBytes, _ := os.ReadFile("documento.pdf")

firmado, err := xami.Pades().SignAndWait(pdfBytes, xamisdk.PadesSignOptions{
    CredentialKey: "TU_CREDENCIAL",
    SignerName:    "Tu Nombre",
    Reason:        "Aprobación",
    Variables:     map[string]interface{}{"name": "Tu Nombre"},
}, 60)
if err != nil {
    var xe *xamisdk.XamiException
    if errors.As(err, &xe) {
        fmt.Println("Error al firmar:", xe.Message, xe.Code)
    }
    return
}
os.WriteFile("documento_firmado.pdf", firmado, 0o644)
```

---

## `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(txHash string, opts BlockchainSignOptions) (string, error)`
Envía el hash a firmar. Devuelve el `request_id`. `BlockchainSignOptions`:
`CredentialKey` (requerido, credencial EVM), `ChainID`.

#### `Result(requestID string) (map[string]interface{}, error)`
Consulta el estado.

#### `Wait(requestID string, timeoutSeconds int, pollSeconds float64) (map[string]interface{}, error)`
Bloquea hasta tener la firma. Devuelve el mapa con `r`/`s`/`v`/`signature`.

#### `SignAndWait(txHash string, opts BlockchainSignOptions, timeoutSeconds int) (map[string]interface{}, error)`
Atajo: `Sign()` + `Wait()`.

### Ejemplo

```go
firma, err := xami.Blockchain().SignAndWait("0xHASH_DE_LA_TX", xamisdk.BlockchainSignOptions{
    CredentialKey: "TU_CREDENCIAL_EVM",
    ChainID:       648541,
}, 60)
// firma["r"], firma["s"], firma["v"]
```

---

## `Credentials`

Consulta de credenciales en la caché local.

| Método | Devuelve | Descripción |
|---|---|---|
| `All() ([]interface{}, error)` | lista | Todas las credenciales disponibles. |
| `Get(key string) (map[string]interface{}, error)` | 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() ([]interface{}, error)` | lista | Todos los diseños disponibles. |
| `Get(key string) (map[string]interface{}, error)` | diseño o `nil` | Un diseño por su `design_key`. |

---

## `Health`

| Método | Devuelve | Descripción |
|---|---|---|
| `Self() (map[string]interface{}, error)` | estado | Estado del servicio local (pareado, tenant, versión, etc.). |
| `Version() (string, error)` | versión | Versión del xamiSDK local. `""` si es anterior a 0.2.0. |
| `APIVersion() (int, error)` | 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(limit int) ([]interface{}, error)` | lista | Últimos resultados (`PENDING` / `DONE` / `ERROR`). |
| `Pending(limit int) ([]interface{}, error)` | lista | Solo los que siguen esperando la firma del chip. |

```go
pendientes, _ := xami.Results().Pending(50)
for _, it := range pendientes {
    r := it.(map[string]interface{})
    fmt.Println(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 |
|---|---|---|
| `Recent(limit int) ([]interface{}, error)` | lista | Últimos errores registrados. |
| `ForRequest(requestID string) ([]interface{}, error)` | lista | Errores de un request concreto. |

```go
fallos, _ := xami.Errors().ForRequest(requestID)
if len(fallos) > 0 {
    f := fallos[0].(map[string]interface{})
    fmt.Println("No se pudo firmar:", f["short"])
    fmt.Println("Menciona", f["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:

```go
v, _ := xami.Health().APIVersion()
if v >= 2 {
    xami.Sync()
}
```

---

## Manejo de errores

Todos los métodos devuelven `error`; el error concreto es `*xamisdk.XamiException`
(campos `Message`, `Code`, `Code == 0` cuando no aplica, p. ej. error de red).

```go
firmado, err := xami.Pades().SignAndWait(pdfBytes, opts, 60)
if err != nil {
    var xe *xamisdk.XamiException
    if errors.As(err, &xe) {
        log.Printf("Error al firmar: %s (%d)", xe.Message, xe.Code)
    }
    return
}
```
