Перейти к основному содержанию
Виджет подтверждения владения кошельком - это размещённая страница, которая подтверждает, что ваш клиент контролирует конкретный адрес криптокошелька. По правилам EU TFR VASP должен проверить владение некастодиальным кошельком до того, как перевести средства на него или с него сверх порога sunrise. Виджет позволяет Didit собрать это подтверждение без того, чтобы вы сами создавали процессы подписания. Проверенное подтверждение помечает соответствующую запись в адресной книге кошельков как is_ownership_verified: true, что позволяет связанному переводу по Travel Rule перейти из UNCONFIRMED_OWNERSHIP.

Когда Didit создаёт её для вас

Обычно вам не нужно создавать сессию самостоятельно. Если в ваших настройках Travel Rule включён параметр auto_wallet_verification (по умолчанию он включён), Didit автоматически создаёт сессию виджета при создании транзакции, когда для перевода нужно подтверждение контроля кошелька со стороны конечного пользователя:
  • Перевод находится в статусе UNCONFIRMED_OWNERSHIP - кошелёк контрагента был заявлен как некастодиальный при отправке.
  • Перевод исходящий и находится в статусе COUNTERPARTY_VASP_NOT_FOUND - VASP контрагента не удалось определить, поэтому подтверждение владения является единственным оставшимся путём к завершению.
Автоматически созданная сессия возвращается в блоке action_required транзакции (type: "wallet_ownership", с url для открытия), а SDK запускают её автоматически при отправке на стороне клиента. Входящие переводы, которые Didit создаёт для вас (регистрация sunrise, входящий запрос TRP или входящий этап по каналу INTERNAL), никогда не получают автоматически созданную сессию, даже если они попадают в UNCONFIRMED_OWNERSHIP. Создавайте сессию вручную с помощью POST /v3/travel-rule/widget-session/, если хотите заранее подтвердить кошелёк до появления какого-либо перевода, если параметр auto_wallet_verification у вас выключен или для одного из таких входящих переводов.

Что это подтверждает

Виджет предлагает до четырёх способов подтверждения. Какие из них появятся, зависит от того, как была создана сессия, и от ваших настроек Travel Rule:

Контракт проверки подписи сообщения

После отправки подписи возвращается 200 со status: "VERIFIED", когда подпись доказывает владение кошельком. Если подпись не подтверждена, возвращается 400, доказательство остаётся открытым, и клиент может подписать сообщение снова. Возможные значения code:

Контракт проверки тестового депозита Satoshi

Проверка тестового депозита Satoshi выполняется асинхронно, потому что транзакция должна появиться в сети и затем получить подтверждение. После отправки txid депозита возвращается 200 со status: "PENDING", пока депозит не подтверждён в сети. txid сохраняется, а не отбрасывается. Когда депозит подтверждён, возвращается 200 со status: "VERIFIED". Для действительно неверного депозита возвращается 400 со status: "REJECTED": отправлен с другого кошелька, сумма на адрес депозита не совпадает с ожидаемой, транзакция старше челленджа или уже подтвердила другой кошелёк. Доказательство закрывается, и клиент может начать новое, пока в сессии остались попытки. Если депозит ещё не проиндексирован, также возвращается 200 со status: "PENDING". Если поиск завершился ошибкой на стороне Didit, возвращается 400 с кодом DEPOSIT_LOOKUP_FAILED. В обоих случаях доказательство остаётся открытым, и Didit продолжает проверку. Возвращается 410, если тестовое окно истекло раньше, чем был обнаружен действительный депозит. После отправки txid фоновое задание каждые пять минут перепроверяет депозит, ожидающий подтверждения, и завершает доказательство после подтверждения транзакции. Клиенту не нужно повторно отправлять txid. Если вы передаёте satoshi_deposit_address, срок действия самой сессии, указанный в expires_at, продлевается как минимум до окончания 24-часового окна тестового депозита Satoshi. Это даёт депозиту время подтвердиться до истечения самой сессии.

Процесс

1

Создайте сессию виджета

Вызовите POST /v3/travel-rule/widget-session/ с кошельком, который нужно верифицировать. По желанию привяжите сессию к переводу, чтобы перевод автоматически переходил к следующему статусу после подтверждения владения.
2

Откройте возвращённый URL

Отправьте клиента по url из ответа. Он проходит подтверждение там, и ему не нужны аккаунт Didit или API-ключ: token в URL и есть аутентификация.
3

Определите завершение

Когда подтверждение проверено, виджет помечает запись в адресной книге как верифицированную и, если сессия привязана к переводу, продвигает перевод. Следите за событием travel_rule.status.updated (для привязанных переводов) или опрашивайте контекст виджета.

Создание сессии виджета

В этом примере сессия привязывается к объявленному переводу на некастодиальный кошелёк из руководства по Travel Rule, поэтому wallet_address указывает на кошелёк назначения этого перевода. Сессия, привязанная к переводу, принимает подтверждения только для кошелька контрагента этого перевода.
Всегда открывайте url из ответа как есть, не формируйте его самостоятельно.

Откройте возвращённый URL

Виджет в этом релизе работает только в вебе. Открывайте url в системном браузере или в пользовательской вкладке, но никогда внутри webview мобильного SDK Didit.Подписание сообщений работает с кошельками, установленными в браузере клиента; виджет находит их по протоколам EIP-6963 и Wallet Standard. Подключение отдельного мобильного приложения-кошелька, например по QR-коду, сейчас недоступно, поэтому виджет не передаёт управление другому приложению. Webview внутри приложения, например webview SDK Didit для Web, Flutter, React Native, iOS или Android, не может обратиться к кошелькам в браузере клиента, поэтому виджет, открытый там, не даёт клиенту возможности подписать сообщение.На мобильных устройствах открывайте url в системном браузере (SFSafariViewController / Chrome Custom Tabs или браузер по умолчанию), а не отображайте его в webview. В вебе подходит обычная вкладка или всплывающее окно.

Определите завершение

Виджет предоставляет публичный endpoint чтения, доступный по token. Опрашивайте его, чтобы видеть прогресс, или полагайтесь на webhook, если сессия привязана к переводу:
  • completed_at становится ненулевым, как только подтверждение проверено.
  • Каждая запись в proofs содержит поля, нужные её методу: SATOSHI_TEST добавляет deposit_address, expected_amount и собственный expires_at; MESSAGE_SIGNING добавляет challenge, строку, которую подписывает клиент.
  • Подтверждение SATOSHI_TEST может оставаться в status: "PENDING", пока депозит виден ончейн, но ещё не подтверждён; от вас и клиента действий не требуется. См. контракт проверки Satoshi test выше.
  • Если сессия создана с transaction_id, проверка подтверждения продвигает привязанный перевод, а в продакшн-приложении срабатывает webhook travel_rule.status.updated. Предпочитайте webhook опросу. Для входящего запроса TRP одобрение отправляется обратно отправителю, и запрос переходит в COMPLETED, когда это одобрение доставлено. Любой другой перевод в UNCONFIRMED_OWNERSHIP (или входящий перевод в ON_HOLD) переходит в COMPLETED, либо в COUNTERPARTY_MISMATCHED_DATA, если имя бенефициара не совпадает с владельцем кошелька, а завершившийся урегулированный sunrise-депозит продолжает переход в FINISHED. Исходящий перевод в COUNTERPARTY_VASP_NOT_FOUND переходит в COMPLETED.
  • Подтверждение SCREENSHOT в этом контексте остаётся в status: "PENDING", даже после того как вы подтвердили владение. Одобряете его через POST .../travel-rule/ownership/, который принимает только перевод, ожидающий подтверждения владения. Поэтому скриншот невозможно одобрить в сессии без привязанного перевода или в сессии, привязанной к исходящему переводу в COUNTERPARTY_VASP_NOT_FOUND: отключите allow_screenshot_proof, если такие сессии не должны его предлагать.
  • После отклонённого подтверждения сессия даёт новую попытку, пока попытки остаются. max_attempts, attempts_used и attempts_remaining показывают счётчик, отклонённое подтверждение содержит rejection_reason, а когда attempts_remaining равно 0, при запуске новой попытки возвращается 409, и тогда нужно создать новую сессию.
  • Endpoint контекста возвращает 404 для неизвестного token и 410, если сессия истекла, не завершившись.
Здесь нет разовых зависимостей: виджет и ваш бэкенд сходятся к одному и тому же устойчивому состоянию (верифицированная запись в адресной книге и статус перевода), поэтому потерянный webhook или закрытая вкладка всегда восстанавливаются повторным чтением перевода или контекста виджета.

Локализация и брендинг

Виджет поддерживает 54 языка. Язык выбирается по пути в ссылке или по языку браузера по умолчанию. Если для вашего приложения включён White label, виджет автоматически наследует брендинг вашего потока верификации: логотип, фирменные цвета, стиль кнопок и панелей, пользовательский шрифт, фавикон и публичное название приложения в заголовке страницы. Отдельная настройка не нужна: применяется та же кастомизация, которую вы задали для KYC-сессий. Пользователь, который возвращается по уже завершённой ссылке, снова увидит экран завершения. Если вы передали callback_url, виджет перенаправит его туда. Истёкшие ссылки показывают брендированный экран истечения срока действия с предложением запросить новую ссылку. Создайте для него новую сессию через POST /v3/travel-rule/widget-session/: повторная отправка перевода с action: "resend" новую сессию не создаёт.

Следующие шаги

Travel Rule

Полный жизненный цикл обмена, каналы, настройки и потоки получения.

Адресная книга кошельков

Зарегистрируйте кошельки, которыми вы управляете, чтобы входящие переводы сопоставлялись с ними.

Webhooks

Подпишитесь на travel_rule.status.updated, чтобы реагировать, когда подтверждение продвигает перевод на следующий этап.

Нативные SDK

Открывайте URL виджета в системном браузере, а не в WebView SDK.
Последнее изменение 7 ноября 2026 г.