Core ConceptsVault и деривация

Vault и деривация

Vault — это дерево адресов, которое вы проектируете сами. Сегменты деривации становятся детерминированными путями, а путь адреса — вашей моделью учёта.

Vault — это отдельное пространство вашей организации в V3 Custody: у него есть код (code, slug), имя и — главное — структура деривации, которую вы задаёте сами. Почти все маршруты API начинаются с кода Vault'а, а все адреса, балансы, политики и отчёты живут внутри него.

Введение уже описало Vault в двух словах. Здесь разберём, из чего он собран и как из ваших сегментов получаются детерминированные адреса.

Схему адресов вы проектируете сами

Обычный кошелёк выдаёт адреса «как получится». Vault идёт от обратного: вы описываете, какими осями различаются ваши адреса, а платформа превращает это в дерево путей деривации.

Каждый адрес — это лист дерева. Дорога от корня к листу состоит из сегментов, и каждый сегмент отвечает за одну ось: сеть, назначение, актив, клиент, стадия — набор выбираете вы. Порядок сегментов фиксирован: он и определяет форму пути.

Сеть — обязательный первый сегмент

В структуре есть один особый сегмент — network. Он определяет блокчейн и его coinType по стандарту BIP‑44 (например, TRON — 195, Ethereum — 60). Значения сети попадают в глобальный реестр Network, а путь всегда начинается с m/44/{coinType}/....

Один Vault может держать несколько сетей: к нему подключаются нужные coinType, и под каждую строится своя ветка.

Сегменты: статические и динамические

Остальные сегменты — это Route'ы, упорядоченные полем order (нормализуется от 0). Route бывает двух видов:

  • Статический — закрытый список вариантов, который вы задаёте заранее. Например, purpose = invoices | settlement, asset = usdt | usdc. Каждый вариант хранит свой индекс в пути; ненужные варианты можно отключить (disabled), не ломая уже выданные адреса.
  • Динамический — не список, а целочисленный индекс в диапазоне [0, 2^31−1]. Он даёт новую ветку на каждую сущность: на клиента, на заявку, на депозит. Именно так под каждого клиента заводится отдельное поддерево, а адресов в нём — сколько угодно.

Смысл разделения простой: статические сегменты — это ваши категории (их немного, они известны заранее), динамические — ваши экземпляры (их много, они появляются на ходу).

Как из сегментов рождается адрес

Адрес создаётся выбором значения для каждого сегмента. Дальше платформа собирает канонический путь и заводит адрес:

Выбираются значения сегментов

Сеть (networkCode) и значения статических сегментов (staticSegments). Для динамических сегментов индекс подбирается автоматически.

Считается следующий индекс

Для этой комбинации сегментов берётся следующий свободный pathIndex (с повтором при конкурентном конфликте) — так два параллельных запроса не займут один путь.

Собирается канонический путь

Из значений строится путь вида m/44/{coinType}/{seg0}/{seg1}/... — по одному числу на сегмент, в фиксированном порядке.

Проверяется политикой

Создание адреса проходит через Policy Engine (action=create_address): он может разрешить, отклонить или отправить на подтверждение.

Пример создания адреса:

curl -X POST "[BASE_URL]/api/v1/vaults/demo_vault/addresses" \
  -H "Authorization: Bearer $V3_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "networkCode": "tron_network",
    "staticSegments": { "purpose": "invoices", "asset": "usdt" }
  }'

Путь читается в обе стороны

Поскольку путь детерминирован, его можно собрать из сегментов и разобрать обратно:

  • POST /api/v1/vaults/{code}/derivation-path/build — собрать канонический путь из значений сегментов. Проверяет, что сеть подключена к Vault, присутствуют все Route'ы, статические варианты существуют и включены, а динамические значения — целые в допустимом диапазоне.
  • POST /api/v1/vaults/{code}/derivation-path/parse — разобрать путь обратно на сеть и значение каждого сегмента. Ошибётся, если префикс не m/44/, coinType не подключён к Vault или число сегментов не совпадает со структурой.

Разберём путь на примере:

m / 44 / 195 / 0 / 0 / 42
  • 44 — стандарт BIP‑44.
  • 195network: TRON (это и есть coinType).
  • 0purpose: invoices (статический вариант).
  • 0asset: usdt (статический вариант).
  • 42client: индекс 42 (динамический сегмент).

Почему дерево — это модель учёта

Форма пути — не техническая деталь, а способ вести учёт:

  • По адресу видно назначение. purpose=invoices, asset=usdt, client=42 — сразу понятно, что это адрес для инвойсов конкретного клиента, а не безымянная строка.
  • Политики пишутся по тем же сегментам. Policy Engine выбирает правила по сети, активу, назначению — тем же осям, что и дерево. Не нужно перечислять адреса вручную.
  • Отчёты сворачиваются по осям. Балансы и обороты агрегируются по сети, активу, назначению, клиенту — потому что это уже заложено в структуру.

Создание Vault

Vault со всей структурой деривации создаётся одним запросом POST /api/v1/vaults. В теле передаётся RouteMap — карта сегментов, обязательно со спец‑ключом network (его варианты добавляются в реестр Network по coinType); остальные ключи становятся Route'ами, а их order нормализуется от 0 в порядке следования.

Полную конфигурацию созданного Vault'а — подключённые сети (по coinType) и Route'ы (по order) со всеми вариантами — отдаёт GET /api/v1/vaults/{code}.

Точная схема тела RouteMap и всех полей — в Справочнике API на странице создания Vault'а. Здесь описан смысл структуры, а не формат запроса.

Что дальше