Конвейер
Правильный автоматический поток состоит из четырёх стадий, и пропуск любой из них рождает сбой, который проявляется только в бою.
- Симулировать. Вызовите triggerconstantcontract к контракту USDT с реальными отправителем и получателем. Он вернёт energy_used без отправки в сеть, и это число — истина для конкретно этой пары адресов.
- Запросить котировку. Спросите у поставщика цену на это количество энергии на нужный срок. Котировка — зафиксированная цена с коротким сроком действия.
- Оформить заказ. Подтвердите котировку со своим ключом идемпотентности. Поставщик делегирует ресурс на ваш адрес.
- Проверить и отправить. Убедитесь, что делегирование действительно активно на вашем адресе, и только потом подписывайте и отправляйте перевод.
Порядок важен. Симуляция после аренды означает, что вы могли арендовать не то количество; отправка до проверки — что вы тратите энергию, которая не пришла.
Зачем симулировать каждый раз
Соблазн — зашить 65 000 и не думать. Это работает, пока не перестаёт, а перестаёт молча и дорого.
- Получателю, никогда не державшему USDT, нужно примерно вдвое больше. Любая система, платящая новым контрагентам, будет попадать на это регулярно.
- Состояние контракта со временем меняется, и эмпирические правила расходятся с реальностью.
- Симуляция ничего не стоит и в сеть не отправляется, так что экономить на ней незачем.
Считайте energy_used переменной затратой на транзакцию, вычисляемой заново, — так же, как любую другую плавающую цену в платёжном потоке.
Идемпотентность
Любая автоматическая система рано или поздно повторит запрос, ответа на который не увидела. Без идемпотентности это означает двойную оплату одной аренды.
Передавайте заголовок Idempotency-Key с идентификатором из своей системы — внутренний id заказа подходит отлично. Повтор с тем же ключом вернёт исходный заказ, а не создаст второй, и повторы становятся безопасными по построению.
- Генерируйте ключ до первой попытки, а не на каждую попытку.
- Выводите его из чего-то устойчивого в вашей предметной области, чтобы повтор после перезапуска процесса дал тот же ключ.
- Никогда не переиспользуйте ключ для действительно другого заказа.
Тайминг — вот где автоматика реально ломается
Аренда действует фиксированный срок, отсчитываемый от момента делегирования. В интерактивной работе это незаметно. В очереди это главный источник инцидентов.
| Схема | Что идёт не так | Как правильно |
|---|---|---|
| Арендовать сразу под всю пачку | Делегирование истекает, пока пачка ещё обрабатывается | Арендовать под перевод либо небольшими группами по вашей пропускной способности |
| Арендовать при постановке в очередь | Задача выполняется через час против истёкшего делегирования | Арендовать в момент исполнения, непосредственно перед отправкой |
| Считать оплату доставкой | Перевод подписывается против энергии, которая не пришла | Считывать ресурс из блокчейна до подписи |
| Повторять упавший перевод без изменений | Он падает так же и сжигает комиссию ещё раз | Пересимулировать, переарендовать, затем повторять |
Проверка доставки в коде
Не полагайтесь только на статус заказа. Авторитетный ответ лежит в блокчейне, и читается он одним вызовом.
- Вызовите getaccountresource для адреса-отправителя.
- Посчитайте доступную энергию как EnergyLimit минус EnergyUsed.
- Проверьте, что её хватает на energy_used из вашей симуляции, с запасом.
- И только затем подписывайте и отправляйте. Если проверка не прошла — не отправляйте: вы заплатите по курсу сжигания, сами того не желая.
Эта последняя проверка — самая ценная защита во всём конвейере. Она превращает молчаливую переплату в пойманную ошибку, а молчаливая переплата со временем обходится дороже всего именно потому, что на неё ничто не срабатывает.
Bandwidth, о котором автоматика забывает
600 бесплатных единиц Bandwidth в сутки покрывают один перевод. Система, отправляющая десятки с одного адреса, израсходует их в первую минуту и дальше платит TRX за всё.
- Держите запас TRX на каждом отправляющем адресе и следите за ним: примерно 0,35 TRX на перевод сверх бесплатного лимита.
- Настройте алерт на запас, а не узнавайте о нём из упавших отправок.
- Если распределить отправку по нескольким адресам, каждый получит свои 600 единиц в сутки — экономия скромная, но на объёме реальная.
Что мониторить
- Фактически израсходованную энергию против предсказанного energy_used. Расходящийся разрыв означает, что шаг симуляции поплыл или пропускается.
- Переводы, сжёгшие TRX за энергию. Любое ненулевое значение означает, что аренда не успевает прийти до отправки.
- Задержку между арендой и отправкой. Если она подползает к сроку аренды, инциденты уже на подходе.
- Запас TRX на каждом отправляющем адресе, с алертом задолго до нуля.