6+
Провайдеров
6+
VASP-операторов
11
Статусов FSM
≥1
Доставка событий
REST
Протокол
SHA-256
Хэш-цепочка
2
Направления
PROVIDER On/Off-Ramp PROVIDER Crypto Exchange PROVIDER Payment App PROVIDER Wallet Provider PROVIDER Neobank PROVIDER Fintech API VASP VASP · Бишкек VASP VASP · Алматы VASP VASP · Ташкент VASP VASP · Бишкек VASP VASP · Астана VASP VASP · Душанбе TB Twin Bridge API · ROUTING · COMPLIANCE ПРОВАЙДЕРЫ VASP-ОПЕРАТОРЫ 6 провайдеров · ON-RAMP + OFF-RAMP · 6 VASP-операторов
Smart Routing
Rate Engine опрашивает всех VASP в реальном времени — курс, ликвидность, аптайм. Лучший маршрут выбирается автоматически за миллисекунды.
🔐
HMAC-SHA256
Каждый запрос криптографически подписан. Replay-атаки, подделка и man-in-the-middle исключены на уровне протокола.
📦
Outbox Guarantee
Паттерн Outbox + exponential backoff. Ни один webhook не потеряется даже при сбое сети — гарантированная доставка at-least-once.
🔗
Audit Chain
SHA-256 хэш-цепочка каждого перехода статуса. Полная история транзакции неизменна, верифицируема и доступна в любой момент.
Запрос провайдера
Внутренняя обработка TB
Вызов VASP
Подтверждение / Webhook
Пакет данных

Как проходит транзакция

Twin Bridge поддерживает оба направления обмена — выберите сценарий ниже

ON-RAMP
KGS → USDT
Обменник выставляет счёт → клиент платит QR → провайдер зачисляет USDT
OFF-RAMP
USDT → KGS
Провайдер автоматически дебетует USDT → обменник выплачивает KGS
ON_RAMP
OFF_RAMP
CANCELLED
FAILED

Обменник выставляет счёт через ELQR → клиент оплачивает QR в виджете провайдера → провайдер зачисляет USDT клиенту

1

Провайдер запрашивает курс

Провайдер обращается к TB. Rate Engine параллельно опрашивает всех доступных VASP-операторов — курс, ликвидность, аптайм. Scoring выбирает лучший маршрут. Курс кэшируется в Redis на 30 сек.

GET /v1/rates
2

Провайдер создаёт транзакцию

Клиент подтверждает. Провайдер отправляет: сумму KGS, пару KGS/USDT, крипто-адрес клиента (куда слать USDT) и KYC-токен. TB передаёт запрос выбранному VASP. VASP генерирует QR через ELQR и возвращает ссылку в TB.

POST /v1/transactions
3

Клиент получает QR и платит

TB передаёт QR-ссылку от обменника провайдеру. Провайдер отображает QR в своём виджете. Клиент сканирует код и оплачивает KGS на счёт обменника через ELQR.

status: PENDING_PAYMENT
4

ELQR подтверждает оплату KGS

ELQR фиксирует получение KGS на счёт VASP. VASP (получив ответ от ELQR) отправляет подписанный webhook в TB. TB верифицирует HMAC-подпись, атомарно обновляет статус и пишет событие в Outbox.

PENDING_PAYMENT → PAID → PROCESSING
5

Провайдер зачисляет USDT клиенту

TB получает подтверждение оплаты KGS от VASP и атомарно переходит PROCESSING → COMPLETED. Провайдер в своём внутреннем ledger'е пополняет баланс USDT клиента. USDT settlement между VASP и провайдером происходит off-chain периодически (weekly/daily) — TB это не оркестрирует.

PROCESSING → COMPLETED
6

TB уведомляет провайдера

Outbox Worker доставляет событие payment.completed на webhook-URL провайдера. Каждый переход статуса — в event_log с SHA-256 хэш-цепочкой.

payment.completed · SHA-256 chain

Провайдер дебетует USDT клиента внутри своей системы → обменник выплачивает KGS клиенту через ELQR

1

Провайдер запрашивает курс

Провайдер обращается к TB. Rate Engine параллельно опрашивает всех VASP-операторов и выбирает лучший курс выкупа USDT. Scoring: курс 50%, надёжность 30%, ликвидность 15%, скорость 5%.

GET /v1/rates
2

Провайдер создаёт транзакцию

Провайдер отправляет: сумму USDT, направление OFF_RAMP, реквизиты клиента (телефон или банк для получения KGS) и KYC-токен. TB фиксирует rate_locked и маршрутизирует к лучшему VASP.

POST /v1/transactions (OFF_RAMP)
3

Провайдер дебетует USDT клиента

Провайдер автоматически списывает USDT с внутреннего баланса клиента — это моментальный update в его ledger'е, никаких on-chain операций не требуется. Клиент не подписывает транзакцию, ничего не сканирует.

status: PENDING_PAYMENT
4

TB инструктирует VASP на выплату

Outbox Worker передаёт команду ExecuteKGSPayout() выбранному VASP. В payload — сумма KGS, реквизиты получателя (телефон/банк), idempotency key. VASP подтверждает приём запроса.

PAID → PROCESSING
5

Обменник выплачивает KGS клиенту

VASP переводит KGS клиенту через ELQR на его банковский счёт или телефон. VASP фиксирует подтверждение платежа и шлёт подписанный webhook в TB. TB атомарно переходит в COMPLETED.

PROCESSING → COMPLETED
6

TB уведомляет провайдера + settlement

Outbox Worker доставляет payment.completed на webhook-URL провайдера. USDT, которые провайдер списал у клиента, будут переведены VASP'у off-chain в следующем settlement-цикле (weekly/daily) — TB это не оркестрирует, только предоставляет audit trail.

payment.completed · settlement offline

Клиент не оплатил в течение TTL — транзакция отменяется

1

Транзакция создана

Провайдер создал транзакцию. TB вернул провайдеру: ON_RAMP — QR-ссылку для оплаты счёта обменника через ELQR. OFF_RAMP — провайдер автоматически дебетует USDT с кошелька клиента.

status: PENDING_PAYMENT
2

TTL истёк — оплаты нет

TB's QRExpiryScheduler отслеживает время жизни каждой транзакции. Если ELQR или блокчейн не прислали подтверждение до истечения TTL — TB сам инициирует отмену. Либо провайдер явно вызывает cancel API.

POST /v1/transactions/:id/cancel
3

TB переводит в CANCELLED

TB обновляет статус транзакции. В рамках одной pg-транзакции: UPDATE статуса + INSERT в Outbox + INSERT в event_log. Либо всё, либо ничего.

PENDING_PAYMENT → CANCELLED
4

VASP освобождает ресурсы

TB передаёт команду отмены на VASP-оператор. VASP разблокирует зарезервированный адрес или QR-слот. Ресурсы возвращаются в пул.

VASP: release reservation
5

Провайдер уведомлён

Outbox Worker доставляет событие payment.cancelled на webhook-URL провайдера. Провайдер показывает клиенту сообщение об отмене.

payment.cancelled
6

Всё зафиксировано

Переход в CANCELLED записан в event_log с SHA-256 хэшом. Причина отмены (TTL, ручная отмена, ошибка провайдера) — в аудит-поле записи.

Event Log: CANCELLED chain

Оплата поступила, но обработка у VASP завершилась ошибкой

1

Оплата зафиксирована

ELQR или блокчейн подтвердили поступление средств. TB получил webhook от VASP с подтверждением оплаты и обновил статус.

PENDING_PAYMENT → PAID
2

Execute() возвращает ошибку

Outbox Worker вызывает Execute() у VASP. VASP возвращает явную ошибку: технический сбой, превышение лимита ликвидности, недоступность платёжной системы. TB получает ответ с кодом ошибки и переводит транзакцию в FAILED.

PAID → PROCESSING → FAILED
3

TB получает UNKNOWN (если нет ответа)

Если VASP не отвечает в течение таймаута — TB переходит в UNKNOWN, а не FAILED. TB не знает что произошло: polling до получения чёткого ответа, повторный вызов ЗАПРЕЩЁН.

PROCESSING → UNKNOWN → polling
4

Статус FAILED подтверждён

Получив явный ответ об ошибке от VASP — TB фиксирует FAILED. В рамках одной pg-транзакции: статус + Outbox + event_log. Деньги клиента требуют решения.

UNKNOWN / PROCESSING → FAILED
5

Провайдер уведомлён

Outbox Worker доставляет событие payment.failed с кодом ошибки на webhook провайдера. Провайдер информирует клиента и инициирует возврат.

payment.failed
6

Что значит FAILED

FAILED означает: Execute() вернул ошибку или ReconciliationEngine получил NOT_FOUND — деньги у VASP не оказались.

FAILED — финальный статус