seqno
Sequence number в TON-кошельке: 32-битный счётчик-nonce, который смарт-контракт инкрементирует при каждой исходящей транзакции для защиты от replay-атак.
Синонимы: sequence number, секно
seqno (sequence number) — 32-битный счётчик в data-cell каждого TON-кошелька, увеличивающийся на 1 после каждой исходящей транзакции. Подписанные сообщения включают seqno в тело; если seqno в подписанном сообщении не равен текущему в data — контракт отклоняет транзакцию через THROWIFNOT 33.
Зачем нужен
- Защита от replay: атакующий не может «переотправить» вашу старую транзакцию — её seqno уже инкрементирован.
- Гарантия порядка: транзакции выполняются строго по возрастанию seqno.
Как использовать в SDK
@ton/ton SDK сам читает seqno у контракта перед отправкой:
const seqno = await walletContract.getSeqno();
await walletContract.sendTransfer({ seqno, secretKey, messages: [...] });
В Wallet V5 появилась расширенная семантика: extensions могут иметь собственный seqno-namespace и подписывать независимо от основного владельца.
Что делать, если транзакция «застряла»
Если sendTransfer прошёл, но в эксплорере транзакции нет 30+ секунд — возможные сценарии:
- Внешнее сообщение отклонено валидатором (низкая комиссия, неверная подпись). seqno в data не инкрементировался — можно повторять с тем же seqno.
- Сеть перегружена — сообщение в очереди, ждите ещё 15-30 секунд.
- Race condition с другой подписью — если кто-то параллельно отправил транзакцию (например, открытое второе окно кошелька) с тем же seqno, ваше отклонит throw 33.
Проверка через API:
const stored = await walletContract.getSeqno();
if (stored === seqno) {
// транзакция не прошла — можно retry
} else if (stored > seqno) {
// транзакция включена в блок (или была другая параллельная отправка)
}
Никогда не «угадывайте» seqno вручную — всегда читайте свежее значение перед каждой подписью.
Batch-отправка
Один seqno покрывает один внешний message, но внутри него можно отправить до 4 outgoing-сообщений (Wallet V4) или до 255 (Wallet V5 batch mode). Все они выполнятся атомарно в рамках одной транзакции; если хоть один fail’нет на стадии compute — откатывается весь batch.
Wallet V5 namespaces — подробнее
В Wallet V5 структура data усложнилась: помимо основного signature_auth_seqno есть отдельные счётчики для каждого подписанного extension. Это позволяет:
- Использовать multi-sig с несколькими ключами без race-конфликтов.
- Делегировать sign-полномочия dApp’у (через TON Connect 2) с ограниченным namespace.
- Запускать gasless flows: relayer оплачивает gas, юзер подписывает только тело operation.
При работе с V5 кошельком всегда используйте getSeqno({ extensionId }) если вы — extension, иначе будет 33-throw от чужого namespace’а.