Разработка NFT-коллекции на TON
TON — архитектурно другой блокчейн. Разработчик с опытом только на EVM подойдёт к TON NFT и обнаружит, что концепции «контракт-адрес», «transfer», «approve» работают принципиально иначе. Каждый NFT токен на TON — это отдельный смарт-контракт. Не запись в маппинге, а полноценный задеплоенный контракт с собственным адресом и хранилищем. Это меняет всю логику деплоя, mint и transfer. TEP-62 стандарт описывает интерфейс, но понимание шардинговой архитектуры TON — предпосылка для корректной реализации.
Как работают NFT на TON: TEP-62
Архитектура: Collection + Item contracts
Коллекция на TON состоит из двух типов контрактов:
NFT Collection contract — главный контракт коллекции. Хранит: owner_address, next_item_index, content (metadata коллекции), nft_item_code (код для деплоя item контрактов). При минте деплоит новый NFT Item контракт через deploy_nft_item internal message.
NFT Item contract — каждый токен. Хранит: index (порядковый номер), collection_address, owner_address, individual_content. Адрес item-контракта вычисляется детерминированно из collection_address и index через stateInit.
;; Получить адрес NFT item по индексу (FunC)
cell calculate_nft_item_state_init(int item_index, cell nft_item_code) {
cell data = begin_cell()
.store_uint(item_index, 64)
.store_slice(my_address())
.end_cell();
return begin_cell()
.store_uint(0, 2)
.store_dict(nft_item_code)
.store_dict(data)
.store_uint(0, 1)
.end_cell();
}
Это означает: адрес любого NFT в коллекции можно вычислить off-chain, не делая запрос к блокчейну. Важно для индексаторов и маркетплейсов.
TEP-62 transfer механика
Transfer NFT на TON — это отправка internal message от текущего владельца к NFT Item контракту с operation code transfer. Item контракт меняет owner_address и опционально отправляет ownership_assigned notification новому владельцу.
;; NFT Item: обработка transfer
if (op == op::transfer()) {
slice new_owner = in_msg_body~load_msg_addr();
slice response_destination = in_msg_body~load_msg_addr();
throw_unless(401, equal_slices(sender_address, owner));
owner = new_owner;
save_data();
;; Уведомление нового владельца (опционально)
send_msg(new_owner, 0, op::ownership_assigned(), ...);
}
В отличие от EVM, где transferFrom — синхронная операция, в TON transfer — это async message. Новый владелец получит уведомление через следующий блок. Это важно для marketplace логики: листинг и delisting требуют обработки async confirmation.
Metadata стандарт (TEP-64)
TON NFT metadata хранится в двух форматах: on-chain (TL-B encoded прямо в контракте) и off-chain (URL на JSON файл). Для коллекций с generative metadata типичен snake encoding URL:
Cell content = begin_cell()
.store_uint(0x01, 8) // off-chain flag
.store_slice("https://example.com/nft/")
.end_cell()
Individual content хранит суффикс (например, 123.json), коллекция хранит base URL. get_nft_data() getter объединяет их для полного URI.
Формат JSON идентичен EVM: name, description, image, attributes. Хранение на IPFS работает так же — разница только в том, как URI передаётся в контракт.
Интеграция с маркетплейсами TON
GetGems — основной NFT маркетплейс TON. Использует TEP-62 стандарт напрямую. Для листинга на GetGems контракт должен корректно возвращать get_nft_data(): (init?, index, collection_address, owner_address, individual_content).
TON Diamonds, Fragment — дополнительные маркетплейсы. Fragment специализируется на Telegram usernames как NFT (также TEP-62).
Проверяем совместимость через toncenter.com API: вызываем get_nft_data() через RunGetMethod и сравниваем с ожидаемым форматом маркетплейса.
Royalty: TEP-66
TEP-66 — стандарт royalty для TON, аналог EIP-2981. Collection контракт добавляет getter royalty_params(), возвращающий (numerator, denominator, destination). Royalty 5% = numerator 50, denominator 1000.
GetGems поддерживает TEP-66 с 2023 года. Без имплементации royalty не будет выплачиваться на основных маркетплейсах.
Mint механика и Tact vs FunC
Выбор языка: FunC или Tact
FunC — нативный язык TON смарт-контрактов. Низкоуровневый, требует явного управления памятью и TL-B сериализацией. Все продакшн-контракты TON написаны на FunC, он хорошо покрыт документацией и аудитами.
Tact — язык высокого уровня для TON, синтаксически ближе к TypeScript. Компилируется в FunC. Упрощает разработку, но экосистема и инструментарий аудита пока менее зрелые. Для продакшн-коллекций в 2024 году мы используем FunC с проверенными шаблонами из ton-blockchain/token-contract репозитория.
Batch mint в шардинговой архитектуре
Каждый mint — это деплой нового контракта, что стоит дороже чем EVM SLOAD. На Ethereum mainnet mint ~50K gas; на TON — от 0.05 TON за NFT Item деплой. При batch mint 10 000 токенов сразу — 500 TON только на storage fees.
Оптимизация: lazy mint (NFT Item деплоится при первом transfer или явном claim), или предварительный деплой на стороне владельца коллекции с распределением по батчам с задержкой между блоками.
Процесс работы
Аналитика (0.5-1 день). Тип коллекции (стандартная, soulbound, fractional), количество токенов, metadata формат, royalty, целевые маркетплейсы.
Разработка (3-4 дня). Collection + Item контракты на FunC с TEP-62/TEP-64/TEP-66 имплементацией, тесты через ton-jest/sandbox, скрипты деплоя через ton/core и @ton/ton SDK.
Mint сайт (1-2 дня). Frontend через TonConnect 2.0, интеграция с TON Wallet, Tonkeeper.
Деплой (0.5-1 день). Testnet (TON Testnet), затем mainnet. Верификация на GetGems.
Базовая коллекция без mint сайта — 3-4 дня. С mint сайтом, whitelist и интеграцией с GetGems — 5-7 дней. Стоимость рассчитывается индивидуально.







