Saltar al contenido principal
El widget de propiedad de wallet es una página alojada que demuestra que uno de tus clientes controla una dirección de wallet de criptomonedas concreta. Según el TFR de la UE, un VASP debe verificar la propiedad de una wallet sin custodia (no alojada) antes de liberar fondos hacia ella o desde ella por encima del umbral de sunrise; el widget es la forma en que Didit recopila esa prueba sin que tengas que crear tú mismo los flujos de firma. Una prueba verificada marca la entrada correspondiente de la libreta de direcciones de wallets como is_ownership_verified: true, lo que permite que una transferencia de Travel Rule vinculada salga del estado UNCONFIRMED_OWNERSHIP.

Cuándo la genera Didit por ti

Rara vez necesitas generar una sesión tú mismo. Cuando auto_wallet_verification está activado en tu configuración de Travel Rule (el valor predeterminado), Didit genera automáticamente una sesión del widget al crear la transacción siempre que una transferencia requiera que el usuario final demuestre el control de la wallet:
  • La transferencia está en UNCONFIRMED_OWNERSHIP: la wallet de la contraparte se declaró sin custodia en el envío.
  • La transferencia es saliente y está en COUNTERPARTY_VASP_NOT_FOUND: no se pudo identificar ningún VASP de contraparte, por lo que la prueba de propiedad es la vía que queda para completarla.
La sesión generada automáticamente se devuelve en el bloque action_required de la transacción (type: "wallet_ownership", con la url que hay que abrir), y los SDK la abren automáticamente en el envío desde el cliente. Las transferencias entrantes que Didit crea por ti (un registro de sunrise, una consulta TRP entrante o el tramo entrante por la vía INTERNAL) nunca reciben una sesión generada automáticamente, aunque terminen en UNCONFIRMED_OWNERSHIP. Genera la sesión manualmente con POST /v3/travel-rule/widget-session/ cuando quieras verificar una wallet de antemano, antes de que exista ninguna transferencia, cuando tengas auto_wallet_verification desactivado o para una de esas transferencias entrantes.

Qué demuestra

El widget ofrece hasta cuatro métodos de prueba. Los que aparecen dependen de cómo generaste la sesión y de tu configuración de Travel Rule:

Contrato de verificación de la firma de mensajes

Enviar la firma devuelve 200 con status: "VERIFIED" cuando demuestra el control de la wallet. Devuelve 400 y deja la prueba abierta, para que el cliente pueda volver a firmar, con uno de estos valores de code:

Contrato de verificación del test de satoshis

La verificación de un depósito del test de satoshis es asíncrona, porque la transacción tiene que verse on-chain y después confirmarse. Enviar el txid del depósito devuelve 200 con status: "PENDING" mientras el depósito aún no esté confirmado on-chain; el txid se conserva, no se descarta. Devuelve 200 con status: "VERIFIED" cuando el depósito se confirma. Devuelve 400 con status: "REJECTED" para un depósito realmente incorrecto: enviado desde otra wallet, que no envía el importe esperado a la dirección de depósito, anterior al desafío o que ya se utilizó para demostrar la propiedad de otra wallet. La prueba se cierra y el cliente puede iniciar una nueva mientras a la sesión le queden intentos. Un depósito que todavía no está indexado también devuelve 200 con status: "PENDING", y una consulta que falla por parte de Didit devuelve 400 con el código DEPOSIT_LOOKUP_FAILED: en ambos casos la prueba sigue abierta y Didit sigue comprobándola. Devuelve 410 si la ventana del test expira antes de que se detecte un depósito válido. Una vez enviado un txid, un proceso en segundo plano vuelve a comprobar el depósito pendiente cada cinco minutos y completa la prueba cuando la transacción se confirma, por lo que el cliente no necesita volver a enviar el txid. Cuando pasas una satoshi_deposit_address, el propio expires_at de la sesión del widget se amplía como mínimo a la ventana de 24 horas del test de satoshis, lo que da tiempo a que el depósito se confirme antes de que expire la sesión.

Flujo

1

Crea una sesión del widget

Llama a POST /v3/travel-rule/widget-session/ con la wallet que necesitas verificar. Opcionalmente, vincula la sesión a una transferencia para que esta avance automáticamente en cuanto se demuestre la propiedad.
2

Abre la URL devuelta

Envía a tu cliente a la url de la respuesta. Allí completa una prueba sin necesidad de una cuenta de Didit ni de una clave de API: el token de la URL es la autenticación.
3

Detecta la finalización

Cuando se verifica una prueba, el widget marca como verificada la entrada de la libreta de direcciones y, si la sesión está vinculada a una transferencia, la hace avanzar. Espera el evento travel_rule.status.updated (transferencias vinculadas) o consulta periódicamente el contexto del widget.

Crea una sesión del widget

Este ejemplo vincula la sesión a la transferencia declarada a una wallet sin custodia de la guía de Travel Rule, por lo que wallet_address es la wallet de destino de esa transferencia. Una sesión vinculada a una transferencia solo acepta pruebas para la wallet de la contraparte de la transferencia.
Abre siempre la url devuelta en la respuesta tal cual, sin construirla tú.

Abre la URL devuelta

En esta versión, el widget solo funciona en la web. Abre la url en el navegador del sistema o en una custom tab, nunca dentro de un webview de un SDK móvil de Didit.La firma de mensajes funciona con las wallets instaladas en el navegador del cliente, que el widget detecta mediante los protocolos EIP-6963 y Wallet Standard. Vincular una aplicación de wallet móvil independiente, por ejemplo mediante código QR, no está disponible actualmente, por lo que el widget no pasa a otra aplicación. Un webview dentro de la aplicación, como el webview de los SDK de Didit para Web, Flutter, React Native, iOS o Android, no puede acceder a las wallets del navegador del cliente, por lo que un widget abierto allí deja al cliente sin forma de firmar.En dispositivos móviles, abre la url con el navegador del sistema operativo (SFSafariViewController / Chrome Custom Tabs, o el navegador predeterminado) en lugar de mostrarla en un webview. En la web, basta con una pestaña normal o una ventana emergente.

Detecta la finalización

El widget expone un endpoint público de lectura identificado por el token: consúltalo periódicamente para ver el progreso, o confía en los webhooks cuando la sesión esté vinculada a una transferencia:
  • completed_at deja de ser nulo en cuanto se verifica una prueba.
  • Cada entrada de proofs incluye los campos que necesita su método: una prueba SATOSHI_TEST añade deposit_address, expected_amount y su propio expires_at; una prueba MESSAGE_SIGNING añade challenge, la cadena que firma el cliente.
  • Una prueba SATOSHI_TEST puede permanecer en status: "PENDING" mientras se detecta su depósito on-chain pero sin confirmar, sin que tú ni el cliente tengan que hacer nada: consulta el contrato de verificación del test de Satoshi más arriba.
  • Cuando la sesión se creó con un transaction_id, verificar la prueba hace avanzar la transferencia vinculada y, en una aplicación en producción, se dispara un webhook travel_rule.status.updated. Prefiere el webhook a la consulta periódica. Una consulta TRP entrante se responde como aprobada al remitente y pasa a COMPLETED en cuanto se entrega esa aprobación. Cualquier otra transferencia en UNCONFIRMED_OWNERSHIP (o una entrante en ON_HOLD) pasa a COMPLETED, o a COUNTERPARTY_MISMATCHED_DATA cuando el nombre del beneficiario no coincide con el titular de la wallet, y un depósito sunrise liquidado que se completa continúa hasta FINISHED. Una transferencia saliente en COUNTERPARTY_VASP_NOT_FOUND pasa a COMPLETED.
  • Una prueba SCREENSHOT mantiene status: "PENDING" en este contexto incluso después de que confirmes la propiedad. La apruebas con POST .../travel-rule/ownership/, que solo acepta una transferencia pendiente de confirmación de propiedad. Por tanto, una captura de pantalla no tiene vía de aprobación en una sesión sin transferencia vinculada, ni en una sesión vinculada a una transferencia saliente en COUNTERPARTY_VASP_NOT_FOUND: desactiva allow_screenshot_proof si esas sesiones no deben ofrecerla.
  • Tras una prueba rechazada, la sesión admite un nuevo intento mientras queden intentos. max_attempts, attempts_used y attempts_remaining indican el recuento, una prueba rechazada incluye rejection_reason y, cuando attempts_remaining es 0, iniciar otra prueba responde 409 y debes crear una nueva sesión.
  • El endpoint de contexto devuelve 404 para un token desconocido y 410 cuando la sesión ha expirado sin completarse.
Aquí no hay dependencias de ejecución única: tanto el widget como tu backend convergen en el mismo estado persistente (la entrada verificada de la libreta de direcciones y el estado de la transferencia), por lo que un webhook perdido o una pestaña cerrada siempre se pueden recuperar volviendo a leer la transferencia o el contexto del widget.

Localización y personalización de marca

El widget se muestra en 54 idiomas, según la ruta de idioma del enlace (o el idioma predeterminado del navegador). Cuando la marca blanca está activada para tu aplicación, el widget hereda automáticamente la marca de tu flujo de verificación: logotipo, colores de marca, estilo de botones y paneles, fuente personalizada, favicon y el nombre público de tu aplicación en el título. No hace falta ninguna configuración aparte: la misma personalización que configuras para las sesiones de KYC se aplica aquí. Un usuario que vuelve a un enlace ya completado ve de nuevo la pantalla de finalización; si pasaste una callback_url, el widget lo redirige allí. Los enlaces expirados muestran una pantalla de caducidad con tu marca que le pide al usuario solicitar un nuevo enlace. Crea una nueva sesión para el usuario con POST /v3/travel-rule/widget-session/: reenviar una transferencia con action: "resend" no crea ninguna.

Próximos pasos

Travel Rule

El ciclo de vida completo del intercambio, los canales, la configuración y los flujos de recepción.

Libreta de direcciones de wallets

Registra las wallets que controlas para que las transferencias entrantes se vinculen a ellas.

Webhooks

Suscríbete a travel_rule.status.updated para reaccionar cuando una prueba haga que una transferencia avance.

SDK nativos

Abre la URL del widget con el navegador del sistema, no con el webview del SDK.
Última modificación el 1 de noviembre de 2026