> For the complete documentation index, see [llms.txt](https://docs.ston.fi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ston.fi/es/seccion-para-desarrolladores/omniston/resolvers/guide.md).

# Cómo convertirse en un Resolver

Esta guía explica cómo convertirse en un resolver (Market Maker) en el protocolo Omniston e integrarse con su API gRPC.

## Resumen

Un resolver es un servicio que proporciona tipos de cambio de tokens y ejecuta operaciones. Para convertirse en un resolver, necesita:

1. Registrarse obteniendo un Soul-Bound Token (SBT)
2. Conectarse a la API gRPC
3. Gestionar solicitudes de cotización y operaciones

## Proceso de registro

### Paso 1: Generar claves

Primero, genere uno o más pares de claves Ed25519 que se usarán para la autenticación:

{% hint style="success" %}
[Implementación en JavaScript](https://github.com/3nsoft/ecma-nacl)
{% endhint %}

{% hint style="success" %}
[Implementación en Rust](https://github.com/3nsoft/rust-nacl)
{% endhint %}

{% hint style="info" %}
Para otros lenguajes, puede usar cualquier biblioteca estándar de implementación Ed25519 disponible en su lenguaje de programación preferido
{% endhint %}

### Paso 2: Preparar metadatos

Cree un documento JSON que contenga:

* El nombre de su resolver
* Su(s) clave(s) pública(s)

Ejemplo:

```json
{
  "name": "MyResolver",
  "publicKeys": [
    "b951254b184fae6906a61ab01e37296fbb28961494cacf7befac9f638fcfe40c",
    "9397ddd52a0d6033da4a32e654b4afbddcc5d832575e396c0a6f5b213faa199f"
  ]
}
```

### Paso 3: Enviar el registro

{% hint style="success" %}
[Enlace al formulario de Google](https://forms.gle/LxY2GphQdyhLu3L39)
{% endhint %}

1. Sus metadatos se almacenarán en una colección NFT SBT
2. Recibirá la dirección de participación de su SBT para la autenticación de la API

## Conectarse a la API

### Autenticación

1. Cree una carga útil de conexión:

```protobuf
message ConnectPayload {
  uint64 connect_timestamp = 1;  // Marca de tiempo actual en milisegundos
  string stake_address = 2;      // La dirección de participación de su SBT
}
```

2. Firme la carga útil:

* Serialice el `ConnectPayload` en bytes
* Firme usando su clave privada Ed25519
* Codifique la firma en Base64

3. Envíe un `ConnectRequest`:

```protobuf
message ConnectRequest {
  bytes payload = 1;    // ConnectPayload serializado
  bytes public_key = 2; // Su clave pública Ed25519
  bytes signature = 3;  // Firma de la carga útil
}
```

Ejemplo de solicitud de conexión:

```json
{
  "connect": {
    "payload": "CPKnlt2xYxIwRVFDWFNzMnhaMmRoazlUQXh6R3pYcmEyRWJHX1MyU3F5TjhUZmk2Zko4MkVZaVZq",
    "public_key": "TAPsnPvWhlOvxEK19rONv4sueMeQzOzlrrIFUOKsi34=",
    "signature": "us7nMd9wmUOkuPk0otg6dvUojZwj8VcyXU6HD13BDQhVrzV8sKgyXtKze+9+j9FC1Ghxkx7Jo5FIDeE8ljbADQjyp5bdsWMSMEVRQ1hTczJ4WjJkaGs5VEF4ekd6WHJhMkViR19TMlNxeU44VGZpNmZKODJFWWlWag=="
  },
  "seqno": 1
}
```

## Flujo de mensajes

La API del resolver usa un flujo gRPC bidireccional. Después de conectarse:

### 1. Eventos entrantes

Recibirá estos eventos del servidor:

```protobuf
message ResolverEvent {
  oneof mux {
    uint64 seqno = 1;    // ID del evento generado por el servidor
    uint64 reply_to = 2;  // Hace referencia al seqno de su solicitud
  }

  oneof event {
    QuoteRequestedEvent quote_requested = 10;
    QuoteRequestCancelledEvent quote_request_cancelled = 11;
    QuoteAcceptedEvent quote_accepted = 20;
    QuoteRejectedEvent quote_rejected = 21;
    QuoteInvalidatedEvent quote_invalidated = 22;
    KeepAlive keep_alive = 100;
  }
}
```

Eventos clave:

* `QuoteRequestedEvent`: Nueva solicitud de cotización de un trader
* `QuoteRequestCancelledEvent`: El trader canceló su solicitud
* `QuoteAcceptedEvent`: Su cotización fue aceptada
* `QuoteRejectedEvent`: Su cotización fue rechazada
* `QuoteInvalidatedEvent`: Confirmación de invalidación de la cotización

### 2. Solicitudes salientes

Puede enviar estas solicitudes al servidor:

```protobuf
message ResolverRequest {
  oneof mux {
    uint64 seqno = 1;    // ID de su solicitud
    uint64 reply_to = 2;  // Hace referencia al seqno del evento del servidor
  }

  oneof request {
    ConnectRequest connect = 10;
    UpdateQuoteRequest update_quote = 11;
    InvalidateQuoteRequest invalidate_quote = 12;
  }
}
```

Solicitudes clave:

* `UpdateQuoteRequest`: Proporcionar o actualizar una cotización
* `InvalidateQuoteRequest`: Cancelar una cotización proporcionada previamente

## Flujo de cotización

### 1. Recepción del acuse de recibo de la solicitud de cotización

Cuando un trader envía una solicitud de cotización, primero recibirá un `QuoteRequestAck` que contiene el `rfq_id` que identifica de forma única su solicitud.

### 2. Recepción de solicitudes de cotización

Como resolver, cuando reciba un `QuoteRequestedEvent`:

```protobuf
message QuoteRequestedEvent {
  string rfq_id = 1;                      // ID de la solicitud de cotización (cadena hex de SHA-256)
  QuoteRequest quote_request = 2;         // La solicitud real
  uint32 protocol_fee_bps = 3;           // Tarifa del protocolo en puntos básicos
  sint64 request_timestamp = 4;          // Cuándo se realizó la solicitud
  sint64 quote_validity_timeout = 5;     // Durante cuánto tiempo debe ser válida la cotización
  sint64 deposit_settling_delay = 6;     // Retraso mínimo antes de la liquidación
  sint64 resolve_timeout = 7;            // Tiempo máximo para completar la operación
}
```

### 3. Proporcionar cotizaciones

Responda con un `UpdateQuoteRequest`:

```protobuf
message UpdateQuoteRequest {
  string rfq_id = 1;                    // De QuoteRequestedEvent
  string bid_units = 2;               // Cantidad que paga el trader
  string ask_units = 3;                 // Cantidad que recibe el trader
  uint64 trade_start_deadline = 4;      // Hora de expiración de la cotización

  oneof params {
    ResolverSwapParams swap = 20;       // Para liquidación por swap
    ResolverEscrowParams escrow = 21;   // Para liquidación en depósito en garantía
    ResolverHtlcParams htlc = 22;       // Para liquidación HTLC
  }
}
```

Para la liquidación por swap, incluya información de la ruta:

```protobuf
message ResolverSwapParams {
  repeated SwapRoute routes = 1;  // Posibles rutas de swap
}
```

Importante: al especificar el protocolo en un SwapChunk, la API gRPC espera que sea una de las cadenas "StonFiV1", "StonFiV2", "DeDust" o "TonCo". Actualmente, solo `extra_version = 1` es compatible.

### 4. Ciclo de vida de la cotización

1. Recibe `QuoteRequestedEvent`
2. Envía `UpdateQuoteRequest`
3. El servidor valida su cotización y responde con:
   * `QuoteAcceptedEvent`: Su cotización fue validada y aceptada, incluye `quote_id`.
   * `QuoteRejectedEvent`: Su cotización fue rechazada. El evento incluye un campo `code` del `QuoteRejectedCode` enum. Las posibles razones incluyen:
     * `UNDEFINED` (0) - Error no categorizado
     * `INVALID_PARAMETERS` (1) - Valor inválido de un parámetro
     * `INVALID_AMOUNTS` (2) - Las restricciones de cantidad de activos no cumplen los requisitos del RFQ
     * `ROUTE_PROHIBITED` (3) - La ruta usa un activo intermedio prohibido
     * `POOL_PROHIBITED` (4) - La ruta usa un pool de liquidez no verificado o prohibido
     * `EMULATION_RESULT_MISMATCH` (5) - La emulación de la transacción produjo un resultado diferente al de la cotización
     * `INTERNAL_ERROR` (101) - Errores del servidor
4. En cualquier momento, puede:
   * Enviar nuevo `UpdateQuoteRequest` para actualizar la cotización
   * Enviar `InvalidateQuoteRequest` para cancelar la cotización

## Buenas prácticas

1. **Números de secuencia**
   * Use `seqno` monótonamente crecientes para sus solicitudes
   * Empareje `reply_to` con el evento `seqno` al responder
   * Realice el seguimiento de la correlación solicitud/respuesta usando `seqno`
2. **Gestión de cotizaciones**
   * Respete sus cotizaciones hasta `trade_start_deadline`
   * Invalide las cotizaciones que no pueda cumplir
   * Incluya todas las comisiones en los importes cotizados
3. **Gestión de errores**
   * Reconéctese si se pierde la conexión
   * Gestione todos los tipos de evento
   * Registre las cotizaciones rechazadas para monitoreo
4. **Rendimiento**
   * Mantenga una única conexión gRPC
   * Procese los eventos de forma asíncrona
   * Almacene en búfer las solicitudes salientes

## Puntos finales de la API

**Producción**:

* WebSocket (JSON-RPC): `wss://omni-ws.ston.fi`
* gRPC (TLS): `omni-grpc.ston.fi:443`
* Sitio de demostración: [omniston.ston.fi](https://omniston.ston.fi)

**Sandbox**:

* WebSocket (JSON-RPC): `wss://omni-ws-sandbox.ston.fi`
* gRPC (TLS): `omni-grpc-sandbox.ston.fi:443`
* Sitio de demostración: [omniston-sandbox.ston.fi](https://omniston-sandbox.ston.fi)

> ⚠️ Los endpoints gRPC son **host:puerto** destinos sobre TLS y no son URL REST HTTP. No uses `https://...` como si fuera una API REST.

## Ver también

* [Documentación del protocolo de swap](/es/seccion-para-desarrolladores/omniston/swap.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ston.fi/es/seccion-para-desarrolladores/omniston/resolvers/guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
