Passer au contenu principal
Le widget de propriété du portefeuille est une page hébergée qui prouve qu’un de vos clients contrôle une adresse de portefeuille crypto spécifique. Selon le règlement européen TFR, un VASP doit vérifier la propriété d’un portefeuille auto-hébergé (non hébergé) avant d’envoyer des fonds vers ce portefeuille ou depuis celui-ci, au-delà du seuil sunrise. Le widget permet à Didit de recueillir cette preuve sans que vous ayez à développer vous-même les flux de signature. Une preuve vérifiée marque l’entrée du carnet d’adresses de portefeuilles correspondante avec is_ownership_verified: true, ce qui permet à un transfert Travel Rule lié de sortir de l’état UNCONFIRMED_OWNERSHIP.

Quand Didit le crée pour vous

Vous avez rarement besoin de créer une session vous-même. Lorsque auto_wallet_verification est activé dans vos paramètres Travel Rule (valeur par défaut), Didit crée automatiquement une session de widget à la création de la transaction, chaque fois qu’un transfert nécessite une preuve de contrôle du portefeuille par l’utilisateur final :
  • Le transfert est en UNCONFIRMED_OWNERSHIP : le portefeuille de la contrepartie a été déclaré auto-hébergé lors de la soumission.
  • Le transfert est sortant et en COUNTERPARTY_VASP_NOT_FOUND : aucun VASP de contrepartie n’a pu être identifié, la preuve de propriété est donc la seule voie restante pour mener le transfert à terme.
La session créée automatiquement est renvoyée dans le bloc action_required de la transaction (type: "wallet_ownership", avec l’url à ouvrir), et les SDK la lancent automatiquement lors de la soumission côté client. Les transferts entrants que Didit crée pour vous (un enregistrement sunrise, une requête TRP entrante ou la portion entrante du rail INTERNAL) ne reçoivent jamais de session générée automatiquement, même lorsqu’ils passent en UNCONFIRMED_OWNERSHIP. Créez une session manuellement avec POST /v3/travel-rule/widget-session/ lorsque vous souhaitez pré-vérifier un portefeuille avant qu’un transfert n’existe, lorsque auto_wallet_verification est désactivé, ou pour l’un de ces transferts entrants.

Ce que cela prouve

Le widget propose jusqu’à quatre méthodes de preuve. Les méthodes qui apparaissent dépendent de la façon dont vous avez créé la session et de vos paramètres Travel Rule :

Contrat de vérification de la signature de message

La soumission de la signature renvoie 200 avec status: "VERIFIED" dès qu’elle prouve le contrôle du portefeuille. Elle renvoie 400 et laisse la preuve ouverte, afin que le client puisse signer à nouveau, avec l’une de ces valeurs de code :

Contrat de vérification du test Satoshi

La vérification d’un dépôt de test Satoshi est asynchrone, car la transaction doit être visible on-chain, puis confirmée. La soumission du txid du dépôt renvoie 200 avec status: "PENDING" tant que le dépôt n’est pas encore confirmé on-chain. Le txid est conservé, et non abandonné. Elle renvoie 200 avec status: "VERIFIED" dès que le dépôt est confirmé. Elle renvoie 400 avec status: "REJECTED" pour un dépôt réellement incorrect : envoyé depuis un autre portefeuille, montant différent de celui attendu vers l’adresse de dépôt, antérieur au défi, ou transaction ayant déjà prouvé un autre portefeuille. La preuve est close, et le client peut en démarrer une nouvelle tant que la session dispose encore de tentatives. Un dépôt qui n’est pas encore indexé renvoie également 200 avec status: "PENDING", et un échec de recherche côté Didit renvoie 400 avec le code DEPOSIT_LOOKUP_FAILED. Dans les deux cas, la preuve reste ouverte et Didit continue de vérifier. Elle renvoie 410 si la fenêtre de test expire avant qu’un dépôt valide ne soit constaté. Une fois un txid soumis, une tâche en arrière-plan revérifie le dépôt en attente toutes les cinq minutes et complète la preuve après la confirmation de la transaction. Le client n’a donc pas besoin de soumettre à nouveau le txid. Lorsque vous transmettez un satoshi_deposit_address, le expires_at de la session du widget est prolongé à au moins la fenêtre de test Satoshi de 24 heures, afin que le dépôt ait le temps de se confirmer avant l’expiration de la session elle-même.

Déroulement

1

Générer une session de widget

Appelez POST /v3/travel-rule/widget-session/ avec le portefeuille que vous devez faire vérifier. Vous pouvez éventuellement le lier à un transfert afin que celui-ci avance automatiquement une fois la propriété du portefeuille prouvée.
2

Ouvrir l'URL renvoyée

Envoyez votre client à l’url de la réponse. Il y réalise une preuve sans compte Didit ni clé API : le token présent dans l’URL sert d’authentification.
3

Détecter la fin du processus

Lorsqu’une preuve est vérifiée, le widget marque l’entrée du carnet d’adresses comme vérifiée et, si la session est liée à un transfert, fait avancer celui-ci. Surveillez travel_rule.status.updated (pour les transferts liés) ou interrogez le contexte du widget.

Générer une session de widget

Cet exemple lie la session au transfert déclaré vers un portefeuille auto-hébergé du guide Travel Rule, de sorte que wallet_address correspond à l’adresse de destination de ce transfert. Une session liée à un transfert n’accepte que les preuves portant sur l’adresse de la contrepartie de ce transfert.
Ouvrez toujours l’url renvoyée dans la réponse telle quelle : ne la construisez pas vous-même.

Ouvrir l’URL renvoyée

Le widget n’est disponible que sur le web dans cette version. Ouvrez l’url dans le navigateur du système ou dans un onglet personnalisé - jamais dans une webview du SDK mobile Didit.La signature de message fonctionne avec les portefeuilles installés dans le navigateur du client, que le widget détecte grâce aux protocoles EIP-6963 et Wallet Standard. L’appairage d’une application de portefeuille mobile distincte, par exemple par QR code, n’est pas disponible actuellement : le widget ne transmet donc pas le processus à une autre application. Une webview intégrée à l’application, telle que la webview des SDK Didit Web, Flutter, React Native, iOS et Android, ne peut pas accéder aux portefeuilles du navigateur du client. Un widget ouvert dans une telle webview empêche le client de signer.Sur mobile, ouvrez l’url avec le navigateur du système (SFSafariViewController / Chrome Custom Tabs, ou le navigateur par défaut) au lieu de l’afficher dans une webview. Sur le web, un onglet ou une fenêtre popup classique convient.

Détecter la fin du processus

Le widget expose un endpoint de lecture public, identifié par le token. Interrogez-le pour suivre la progression, ou appuyez-vous sur les webhooks lorsque la session est liée à un transfert :
  • completed_at prend une valeur non nulle dès qu’une preuve est vérifiée.
  • Chaque entrée de proofs contient les champs nécessaires à sa méthode : une preuve SATOSHI_TEST ajoute deposit_address, expected_amount et son propre expires_at ; une preuve MESSAGE_SIGNING ajoute challenge, la chaîne que le client signe.
  • Une preuve SATOSHI_TEST peut rester à status: "PENDING" tant que son dépôt est visible on-chain mais non confirmé, sans aucune action requise de votre part ni de celle du client : voir contrat de vérification du test Satoshi ci-dessus.
  • Lorsque la session a été générée avec un transaction_id, la vérification de la preuve fait avancer le transfert lié, et, sur une application en production, le webhook travel_rule.status.updated est déclenché. Privilégiez le webhook plutôt que l’interrogation. Une demande TRP entrante est approuvée et renvoyée à l’expéditeur, et passe à COMPLETED une fois cette approbation transmise. Tout autre transfert en UNCONFIRMED_OWNERSHIP (ou un transfert entrant ON_HOLD) passe à COMPLETED, ou à COUNTERPARTY_MISMATCHED_DATA lorsque le nom du bénéficiaire ne correspond pas à celui du titulaire du portefeuille, et un dépôt sunrise réglé qui aboutit passe à FINISHED. Un transfert sortant en COUNTERPARTY_VASP_NOT_FOUND passe à COMPLETED.
  • Une preuve SCREENSHOT reste à status: "PENDING" dans ce contexte, même après que vous avez confirmé la propriété. Vous l’approuvez avec POST .../travel-rule/ownership/, qui n’accepte que les transferts en attente de confirmation de propriété. Une capture d’écran n’a donc aucun chemin d’approbation sur une session sans transfert lié, ou sur une session liée à un transfert sortant en COUNTERPARTY_VASP_NOT_FOUND : désactivez allow_screenshot_proof si ces sessions ne doivent pas proposer cette option.
  • Après une preuve rejetée, la session offre une nouvelle tentative tant qu’il en reste. max_attempts, attempts_used et attempts_remaining indiquent le nombre de tentatives, une preuve rejetée contient rejection_reason, et lorsque attempts_remaining vaut 0, toute nouvelle preuve renvoie 409 : vous devez alors générer une nouvelle session.
  • L’endpoint de contexte renvoie 404 pour un token inconnu et 410 lorsque la session a expiré sans être terminée.
Il n’existe aucune dépendance à usage unique ici : le widget et votre backend convergent vers le même état durable (l’entrée vérifiée du carnet d’adresses et le statut du transfert). La situation reste donc toujours récupérable en cas de webhook perdu ou d’onglet fermé, en relisant le transfert ou le contexte du widget.

Localisation et personnalisation

Le widget s’affiche en 54 langues, selon le chemin de langue du lien (ou la langue par défaut du navigateur). Lorsque la marque blanche est activée pour votre application, le widget reprend automatiquement la personnalisation de votre parcours de vérification : logo, couleurs de marque, style des boutons et du panneau, police personnalisée, favicon et nom public de votre application dans le titre. Aucune configuration distincte : la même personnalisation que celle définie pour les sessions KYC s’applique ici. Un utilisateur qui revient sur un lien déjà terminé revoit l’écran de fin ; si vous avez transmis un callback_url, le widget le renvoie vers cette URL. Les liens expirés affichent un écran d’expiration personnalisé qui invite l’utilisateur à demander un nouveau lien. Générez une nouvelle session avec POST /v3/travel-rule/widget-session/ pour cet utilisateur : renvoyer un transfert avec action: "resend" n’en crée pas une.

Prochaines étapes

Travel Rule

Le cycle de vie complet des échanges, les rails, les paramètres et les flux de réception.

Carnet d'adresses des portefeuilles

Enregistrez les portefeuilles que vous contrôlez afin que les transferts entrants soient associés à ces portefeuilles.

Webhooks

Abonnez-vous à travel_rule.status.updated pour réagir lorsqu’une preuve fait progresser un transfert.

SDK natifs

Ouvrez l’URL du widget dans le navigateur système, et non dans la webview du SDK.
Dernière modification le 7 novembre 2026