Сначала заморозьте точный вызов
| Поле | Что сохранить | Почему |
|---|---|---|
| caller + from_subaccount | Principal вызывающего и 32 байта subaccount либо null | Вместе определяют исходный account |
| to | owner и subaccount получателя | Другой subaccount — другой account |
| amount + fee | Целые raw units и буквально переданный fee/null | null и явная fee — разные поля TransferArgs |
| memo | Точные bytes или null | Ledger SHOULD учитывать memo при deduplication |
| created_at_time | nat64 в наносекундах UTC | Определяет временную привязку запроса |
- Поле
- caller + from_subaccount
- Что сохранить
- Principal вызывающего и 32 байта subaccount либо null
- Почему
- Вместе определяют исходный account
- Поле
- to
- Что сохранить
- owner и subaccount получателя
- Почему
- Другой subaccount — другой account
- Поле
- amount + fee
- Что сохранить
- Целые raw units и буквально переданный fee/null
- Почему
- null и явная fee — разные поля TransferArgs
- Поле
- memo
- Что сохранить
- Точные bytes или null
- Почему
- Ledger SHOULD учитывать memo при deduplication
- Поле
- created_at_time
- Что сохранить
- nat64 в наносекундах UTC
- Почему
- Определяет временную привязку запроса
Ответ `Duplicate { duplicate_of }` возвращает transaction index ранее принятой транзакции. Он не доказывает, что интерфейс правильно показал получателя или сумму, поэтому индекс нужно связать с записью именно этого ledger. Сохраняйте option-поля буквально: null и явно переданное значение — разные TransferArgs, даже если бизнес-эффект кажется одинаковым.
Дедупликация в ICRC-1 — нормативная рекомендация `SHOULD`, а не безусловная гарантия каждой реализации. Если `created_at_time` не задан, стандарт рекомендует ledger не дедуплицировать вызов вообще. При потерянном сетевом ответе такой запрос нельзя безопасно повторять, пока история и состояние получателя не исключили первый перевод.
Duplicate проверяют по исходному индексу
Диагностический проход
- 1Подтвердить ledger
Зафиксируйте canister ID, сеть и поддерживаемые стандарты. Одинаковый transaction index в другом ledger не относится к операции.
- 2Сохранить ответ
Запишите raw response, время запроса и значение duplicate_of без преобразования в хеш или строковый идентификатор.
- 3Получить исходную запись
Используйте документированный этим ledger интерфейс истории. Если canister объявляет поддержку ICRC-3, проверьте его get-blocks и archives; базовый ICRC-1 универсального endpoint не задаёт.
- 4Сверить опубликованные поля
Сопоставьте все поля, которые сохраняет схема этого ledger: тип операции, from/to, amount и fee, а memo и created_at_time — только если история их публикует. Если нужного поля нет, не объявляйте полное совпадение.
- 5Проверить эффект
Подтвердите исходную запись в надёжной истории и состояние получателя после неё. Текущий баланс используйте только как дополнительный сигнал: последующие операции могли его изменить.
Общий статус перевода помогает отделить локальную запись кошелька от данных сети. Здесь главным идентификатором ответа остаётся transaction index конкретного ledger.
TooOld не раскрывает универсальное окно
Стандарт рекомендует (`SHOULD`) отклонять слишком старый `created_at_time`, но не назначает фиксированный `TX_WINDOW`. Реализация ledger определяет границу. Поэтому число из документации одного токена нельзя переносить на другой canister.
| Ответ | Что известно | Безопасное продолжение |
|---|---|---|
| Ok(index) | Ledger принял transfer и вернул transaction index | Получить исходную запись и подтвердить эффект |
| Duplicate(duplicate_of) | Совпадающий запрос уже принят | Проверить исходный индекс; не повторять |
| TooOld | Переданное время вне принятого прошлого окна | Искать исходную операцию по локальному журналу и ledger history |
| CreatedInFuture(ledger_time) | Время клиента слишком далеко впереди | Исправить часы, но сначала исключить ранее принятый вызов |
| TemporarilyUnavailable | Ledger не дал окончательного результата | Если created_at_time задан и dedup документирован — повторить byte-for-byte внутри окна; иначе сначала проверить историю и состояние |
- Ответ
- Ok(index)
- Что известно
- Ledger принял transfer и вернул transaction index
- Безопасное продолжение
- Получить исходную запись и подтвердить эффект
- Ответ
- Duplicate(duplicate_of)
- Что известно
- Совпадающий запрос уже принят
- Безопасное продолжение
- Проверить исходный индекс; не повторять
- Ответ
- TooOld
- Что известно
- Переданное время вне принятого прошлого окна
- Безопасное продолжение
- Искать исходную операцию по локальному журналу и ledger history
- Ответ
- CreatedInFuture(ledger_time)
- Что известно
- Время клиента слишком далеко впереди
- Безопасное продолжение
- Исправить часы, но сначала исключить ранее принятый вызов
- Ответ
- TemporarilyUnavailable
- Что известно
- Ledger не дал окончательного результата
- Безопасное продолжение
- Если created_at_time задан и dedup документирован — повторить byte-for-byte внутри окна; иначе сначала проверить историю и состояние
Если исходная операция не найдена, пересборка допустима лишь после документированной проверки истории и текущего состояния. Новый created_at_time создаёт новый запрос, который ledger вправе принять как отдельный перевод; получателя, сумму, fee и memo нужно подтвердить заново.
Стоп-сигналы
- created_at_time отсутствует, но повтор считают защищённым дедупликацией;
- duplicate_of ищут в другом canister или другой сети;
- история или архив не покрывает нужный transaction index либо документированное соответствие записи, а перевод уже объявляют отсутствующим;
- memo или created_at_time меняют до проверки исходного результата.
Ошибку memo на бирже и внутренний перевод без публичного хеша разбирают иначе: биржа сопоставляет депозит вне базового ICRC-1 стандарта. Не подменяйте её внутренний идентификатор полем memo ledger.
При восстановлении кошелька сначала проверьте правильный account и subaccount. Нулевой баланс из другого пути не является доказательством отсутствия перевода.
Источники
Мы используем прямые ссылки и фиксируем дату проверки. Полный текст чужих материалов не перепечатывается.
- DFINITY ICRC-1 Token Standard DFINITY · Проверено 30 августа 2026 г. в 15:55 GMT+5
- DFINITY ICRC-3 Ledger Standard DFINITY · Проверено 30 августа 2026 г. в 15:55 GMT+5
