Перейти к содержанию

Статические кошельки

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

Он подходит для пополнения счёта и регулярных депозитов. А когда нужна конкретная сумма за конкретный заказ — берите инвойс.

Выпуск адреса

curl -X POST https://api.pay.nullswap.com/api/v1/static-wallets \
  -H "x-api-key: sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "chainType": "EVM", "reference": "customer-42" }'
Поле Тип Обяз. Примечания
chainType перечисление да EVM, TRON, SOLANA, BITCOIN, LITECOIN, TON, MONERO
reference строка да Ваше собственное имя для клиента. Максимум 128 символов
{
  "id": "f6a7b8c9-d0e1-4234-a567-8b9c0d1e2f34",
  "merchantId": "9f1d2c3b-4a5e-4f60-8b71-2c3d4e5f6a7b",
  "chainType": "EVM",
  "address": "0x1234567890abcdef1234567890abcdef12345678",
  "reference": "customer-42",
  "createdAt": "2026-01-01T12:00:00.000Z"
}

Работать с этим эндпоинтом просто — из-за двух его свойств:

  • Он идемпотентен по reference. Повторный запрос с тем же референсом вернёт уже выданный этому референсу адрес, а не выпустит второй. Отвечает он всегда 201 — независимо от того, создал что-нибудь или нет, — так что его можно вызывать при каждом визите клиента и не хранить адрес у себя.
  • Адрес выпускается на семейство сетей, а не на отдельную сеть. Один адрес EVM обслуживает и Ethereum, и Arbitrum, и BNB Chain, и любую другую EVM-сеть. Клиенту нужен один адрес на семейство, а не по адресу на каждую сеть, — поэтому маршрут и принимает chainType, а не chainId.
Статус message Причина
400 InvalidRequestBodyError Поля нет либо chainType не входит в перечисление
403 MerchantIsBlockedError Мерчант заблокирован
422 InvalidStaticWalletReferenceError reference пуст или длиннее 128 символов
404 MerchantWalletForChainTypeNotFoundError Для этого семейства сетей у вас не настроен кошелёк

Чтение адресов

Метод Путь Назначение
GET /api/v1/static-wallets Список с фильтрами по id, chainType, reference, address
GET /api/v1/static-wallets/{staticWalletId} Прочитать один

Обычно выпущенный ранее адрес ищут именно по reference:

GET /api/v1/static-wallets?reference=customer-42&limit=10

Платежи

curl "https://api.pay.nullswap.com/api/v1/static-wallets/payments?settlement=PENDING&limit=100" \
  -H "x-api-key: sk_live_..."

Без staticWalletId эндпоинт отдаёт поступления сразу по всем вашим адресам — именно это и нужно для сверки. Фильтры: id, staticWalletId, status, settlement плюс обычная пагинация.

{
  "id": "a7b8c9d0-e1f2-4345-a678-9b0c1d2e3f45",
  "staticWalletId": "f6a7b8c9-d0e1-4234-a567-8b9c0d1e2f34",
  "chainTransactionId": "cc33dd44-ee55-4f66-8077-889900112233",
  "chainTransferId": "dd44ee55-ff66-4077-8188-990011223344",
  "chainId": "1c9a7f36-5f2b-4a83-9d51-0e6b7c8d9a10",
  "tokenId": "3b7e1a48-2c6d-4e9f-8a01-5d4c3b2a1908",
  "fromAddress": "0xfedcba0987654321fedcba0987654321fedcba09",
  "amount": "1500000",
  "status": "CONFIRMED",
  "confirmations": 12,
  "amlStatus": "PASSED",
  "amlResultId": "5c6d7e8f-9a0b-41c2-8d34-5e6f7a8b9c0d",
  "settlement": "SWEEPING",
  "sweepTransferId": "ee55ff66-0077-4188-8299-001122334455",
  "createdAt": "2026-01-01T12:00:00.000Z",
  "updatedAt": "2026-01-01T12:03:00.000Z"
}

Статические кошельки не отправляют вебхуки

Ни одно событие из каталога вебхуков статических кошельков не касается. Сверять их можно только опросом этого эндпоинта. Хватит фоновой задачи, которая раз в минуту-другую запрашивает settlement=PENDING за нужное окно с сортировкой по createdAt.

Смотрите на settlement, а не на status

Статический адрес собирает средства и передаёт их дальше, поэтому важно не то, подтвердилась ли транзакция, а то, где в итоге оказались деньги.

flowchart TD
    A["Приходит депозит"] --> B["status DETECTED<br/>settlement PENDING"]
    B --> C["Подтверждён до нужной глубины"]
    C --> D{"AML-скрининг"}
    D -- "PASSED / SKIPPED" --> E{"Настроен ли кошелёк для выплат<br/>для этого семейства сетей?"}
    D -- "FAILED" --> F["settlement WITHHELD<br/>деньги остаются на адресе"]
    E -- "да" --> G["settlement SWEEPING<br/>sweepTransferId установлен"]
    E -- "нет" --> H["settlement PENDING<br/>ничего не перемещено"]
    G --> I["Зачислено на ваш баланс"]
settlement Значение
PENDING Скрининг ещё не прошёл либо прошёл чисто, но свип создать не удалось. Деньги никуда не двигались.
SWEEPING Чисто, свип на ваш собственный кошелёк отправлен в работу. sweepTransferId заполнен
WITHHELD Помечено скринингом, деньги остаются на статическом адресе
status Значение
DETECTED Видно в сети, но ещё не подтверждено и не проверено скринингом. Это пока не ваши деньги
CONFIRMED Подтверждено и проверено скринингом
FAILED Транзакция откатилась или выпала при реорганизации цепочки

PENDING неоднозначен намеренно: под ним и «мы это ещё не проверяли», и «оно чистое, но переместить не получилось». Различить два случая помогает amlStatus: null означает, что скрининг не запускался.

Разблокировать платёж в статусе WITHHELD через API нельзя — такого маршрута нет. Если считаете вердикт ошибочным, укажите его amlResultId, когда будете обращаться с этим вопросом.

Когда платёж дошёл до SWEEPING и свип завершился, деньги появляются в балансах как CLEAN — оттуда вы их и выводите.