Обработка NFT
Эта страница переведена сообществом на русский язык, но нуждается в улучшениях. Если вы хотите принять участие в переводе свяжитесь с @alexgton.
Обзор
В этом разделе нашей документации мы предоставим читателям более полное представление о NFT. Это научит читателя взаимодействовать с NFT и как принимать их через транзакции, отправленные в блокчейн TON.
Информация, представленная ниже, предполагает, что читатель уже глубоко изучил наш предыдущий [раздел, подробно описывающий обработку платежей в Toncoin] (/v3/guidelines/dapps/asset-processing/payments-processing), и что он также обладает базовым пониманием того, как программно взаимодействовать с смарт-контрактами кошелька.
Понимание основ NFT
NFT, работающие на блокчейне TON, представлены стандартами TEP-62 и TEP-64.
Блокчейн The Open Network (TON) разработан с учетом высокой производительности и включает в себя функцию автоматического сегментирование на основе адресов контрактов на TON (которые используются для предоставления конкретных проектов NFT). Чтобы достичь оптимальной производительности, отдельные NFT должны использовать свой собственный смарт-контракт. Это позволяет создавать коллекции NFT любого размера (как большие, так и маленькие), а также снижает затраты на разработку и проблемы с производительностью. Однако такой подход также вносит новые соображения в разработку коллекций NFT.
Поскольку каждый NFT использует собственный смарт-контракт, невозможно получить информацию об отдельных NFT в коллекции, используя один контракт. Чтобы извлечь информацию о всей коллекции в целом, а также о каждом индивидуальном NFT внутри коллекции, необходимо запросить как контракт коллекции, так и контракт каждого отдельного NFT в отдельности. По той же причине для отслеживания переводов NFT необходимо отслеживать все транзакции для каждого отдельного NFT в рамках конкретной коллекции.
NFT Collections
NFT Collection - это контракт, который служит для индексирования и хранения содержимого NFT и должен содержать следующие интерфейсы:
Get method get_collection_data
(int next_item_index, cell collection_content, slice owner_address) get_collection_data()
Получает общую информацию о коллекции, которая представлена следующим образом:
next_item_index
- если коллекция упорядочена, эта классификация указывает на общее количество NFT в коллекции, а также на следующий индекс, используемый для выпуска. Для неупорядоченных коллекций значениеnext_item_index
равно -1, что означает, что коллекция использует уникальные механизмы для отслеживания NFT (например, хэш или домены TON DNS).collection_content
- ячейка, представляющая содержимое коллекции в формате, совместимом с TEP-64.owner_address
- фрагмент, содержащий адрес владельца коллекции (это значение также может быть пустым).
Get method get_nft_address_by_index
(slice nft_address) get_nft_address_by_index(int index)
Этот метод можно использовать для проверки достоверности NFT и подтверждения, действительно ли он принадлежит определенной коллекции. Он также позволяет пользователям извлекать адрес NFT, указав его индекс в коллекции. Метод должен вернуть фрагмент, содержащий адрес NFT, соответствующий указанному индексу.
Get method get_nft_content
(cell full_content) get_nft_content(int index, cell individual_content)
Поскольку коллекция служит общим хранилищем данных для NFT, этот метод необходим для заполнения содержимого NFT. Чтобы использовать этот метод, сначала необходимо получить individual_content
NFT, вызвав соответствующий метод get_nft_data()
. После получения individual_content
можно вызвать метод get_nft_content()
с индексом NFT и ячейкой individual_content
. Метод должен вернуть ячейку TEP-64, содержащую полное содержимое NFT.
NFT Items
Основные NFT должны быть реализованы:
Get method get_nft_data()
(int init?, int index, slice collection_address, slice owner_address, cell individual_content) get_nft_data()
Обработчик встроенных сообщений для transfer
transfer#5fcc3d14 query_id:uint64 new_owner:MsgAddress response_destination:MsgAddress custom_payload:(Maybe ^Cell) forward_amount:(VarUInteger 16) forward_payload:(Either Cell ^Cell) = InternalMsgBody
Давайте посмотрим на каждый параметр, который нужно заполнить в вашем сообщении:
OP
-0x5fcc3d14
- константа, определенная стандартом TEP-62 в рамках сообщения о передаче.queryId
-uint64
- число uint64, используемое для отслеживания сообщения.newOwnerAddress
-MsgAddress
- адрес контракта, на который переводится NFT.responseAddress
-MsgAddress
- адрес, на который будут переведены лишние средства. Как правило, в контракт NFT отправляется дополнительная сумма в TON (например, 1 TON), чтобы обеспечить наличие достаточного количества средств для оплаты комиссии за транзакцию и создания нового перевода в случае необходимости. Все неиспользованные средства в рамках транзакции отправляются наresponseAddress
.forwardAmount
-Coins
- количество TON, используемое вместе с сообщением о пересылке (обычно устанавливается 0,01 TON). Поскольку TON использует асинхронную архитектуру, новый владелец NFT не будет уведомлен сразу после успешного получения транзакции. Чтобы уведомить нового владельца, смарт-контракт NFT отправляет внутреннее сообщение на адресnewOwnerAddress
со значением, указанным с помощьюforwardAmount
. Сообщение о пересылке начнется с операцииownership_assigned
OP (0x05138d91
), за которым следует адрес предыдущего владельцаforwardPayload
(если он присутствует).forwardPayload
-Slice | Cell
- отправляется как часть сообщения уведомленияownership_assigned
.
Это сообщение (как было объяснено выше) является основным способом взаимодействия с NFT, который изменяет свой владелец после получения уведомления в результате указанного ранее сообщения.
Например, этот тип сообщения часто используется для отправки смарт-контракта NFT Item из смарт-контракта Wallet. Когда смарт-контракт NFT получает это сообщение и выполняет его, хранилище (внутренние данные контракта) NFT-контракта обновляется вместе с ID владельца. Таким образом, NFT Item (контракт) правильно меняет своего владельца. Этот процесс описывает стандартную передачу NFT
В этом случае сумма пересылки должна быть установлена в подходящее значение (0,01 TON для обычного кошелька или больше, если вы хотите выполнить контракт, передавая NFT), чтобы обеспечить новому владельцу уведомление о передаче собственности. Это важно, поскольку без этого уведомления новый владелец не получит уведомления о том, что он получил NFT.
Получение данных NFT
Большинство SDK используют готовые обработчики для извлечения данных NFT, включая: tonweb(js), tonutils-go, pytonlib и другие.
Чтобы получить данные NFT, необходимо использовать механизм извлечения get_nft_data()
. Например, мы должны проверить следующий адрес NFT Item EQB43-VCmf17O7YMd51fAvOjcMkCw46N_3JMCoegH_ZDo40e
(также известный как домен foundation.ton).
Сначала необходимо выполнить get метод извлечения, используя API toncenter.com следующим образом:.
curl -X 'POST' \
'https://toncenter.com/api/v2/runGetMethod' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"address": "EQB43-VCmf17O7YMd51fAvOjcMkCw46N_3JMCoegH_ZDo40e",
"method": "get_nft_data",
"stack": []
}'
Ответ обычно что-то вроде следующего:
{
"ok": true,
"result": {
"@type": "smc.runResult",
"gas_used": 1581,
"stack": [
// init
[ "num", "-0x1" ],
// index
[ "num", "0x9c7d56cc115e7cf6c25e126bea77cbc3cb15d55106f2e397562591059963faa3" ],
// collection_address
[ "cell", { "bytes": "te6cckEBAQEAJAAAQ4AW7psr1kCofjDYDWbjVxFa4J78SsJhlfLDEm0U+hltmfDtDcL7" } ],
// owner_address
[ "cell", { "bytes": "te6cckEBAQEAJAAAQ4ATtS415xpeB1e+YRq/IsbVL8tFYPTNhzrjr5dcdgZdu5BlgvLe" } ],
// content
[ "cell", { "bytes": "te6cckEBCQEA7AABAwDAAQIBIAIDAUO/5NEvz/d9f/ZWh+aYYobkmY5/xar2cp73sULgTwvzeuvABAIBbgUGAER0c3/qevIyXwpbaQiTnJ1y+S20wMpSzKjOLEi7Jwi/GIVBAUG/I1EBQhz26hlqnwXCrTM5k2Qg5o03P1s9x0U4CBUQ7G4HAUG/LrgQbAsQe0P2KTvsDm8eA3Wr0ofDEIPQlYa5wXdpD/oIAEmf04AQe/qqXMblNo5fl5kYi9eYzSLgSrFtHY6k/DdIB0HmNQAQAEatAVFmGM9svpAE9og+dCyaLjylPtAuPjb0zvYqmO4eRJF0AIDBvlU=" } ]
],
"exit_code": 0,
"@extra": "1679535187.3836682:8:0.06118075068995321"
}
}
Возвращаемые параметры:
init
-boolean
— значение -1 означает, что NFT инициализирован и может быть использованindex
-uint256
- индекс NFT в коллекции. Может быть последовательным или полученным каким-либо другим способом. Например, он может обозначать хэш домена NFT, используемый с контрактами TON DNS, тогда как коллекции должны иметь только один уникальный NFT для данного индекса.collection_address
-Cell
- ячейка, содержащая адрес коллекции NFT (может быть пустой).owner_address
-Cell
- ячейка, содержащая адрес текущего владельца NFT (может быть пустой).content
-Cell
- ячейка, содержащая содержимое элемента NFT (если требуется синтаксический разбор, необходимо обратиться к стандарту TEP-64).
Получение всех NFT в коллекции
Процесс извлечения всех NFT в коллекции зависит от того, упорядочена ли коллекция или нет. Давайте рассмотрим оба процесса ниже.
Упорядоченные коллекции
Извлечь все NFT из упорядоченной коллекции относительно просто, поскольку количество NFT, необходимых для извлечения, уже известно, и их адреса можно легко получить. Чтобы завершить этот процесс, необходимо выполнить следующие шаги по порядку:
- Вызовите метод
get_collection_data
используя TonCenter API в контракте коллекции, и извлеките значениеnext_item_index
из ответа. - Используйте метод
get_nft_address_by_index
, передав в него значение индексаi
(изначально установив его на 0), чтобы получить адрес первого NFT в коллекции. - Используйте полученный в предыдущем шаге адрес для извлечения данных NFT Item. Далее проверьте, что начальный адрес умного контракта NFT Collection совпадает со адресом контракта NFT Collection, о котором сообщил NFT Item(чтобы убедиться, что Collection не присвоил адрес умного контракта NFT другого пользователя).
- Вызовите метод
get_nft_content
, передав в него значениеi
иindividual_content
из предыдущего шага. - Увеличьте значение
i
на 1 и повторите шаги 2-5, покаi
не станет равнымnext_item_index
. - На этом этапе у вас будет доступна необходимая информация о коллекции и ее отдельных элементах.
Неупорядоченные коллекции
Получение списка NFT в неупорядоченной коллекции сложнее, так как нет встроенного способа получить адреса NFT, принадлежащих коллекции. Поэтому необходимо разобрать все транзакции в контракте коллекции и проверить все исходящие сообщения, чтобы определить те, которые соответствуют NFT, принадлежащим коллекции.
Для этого необходимо извлечь данные NFT и вызвать метод get_nft_address_by_index
в коллекции с ID, возвращенным NFT контрактом. Если адрес NFT контракта и адрес, возвращенный методом get_nft_address_by_index
, совпадают, это указывает на то, что NFT принадлежит текущей коллекции. Однако разбор всех сообщений для коллекции может быть длительным процессом и может потребовать доступа к архивному узлу.
Работа с NFT вне сети TON
Отправка NFT
Чтобы передать право собственности на NFT, необходимо отправить внутреннее сообщение из кошелька владельца NFT в контракт NFT, создавая ячейку, содержащую сообщение об передаче. Это можно сделать с помощью библиотек (например, tonweb(js), ton(js), tonutils-go(go)) для конкретного языка.
После создания сообщения об передаче его необходимо отправить на адрес контракта NFT item из кошелька владельца, с достаточным количеством TON, чтобы покрыть соответствующую комиссию за транзакцию.
Чтобы передать NFT от другого пользователя себе, необходимо использовать TON Connect 2.0 или простой QR-код, содержащий ссылку ton://. Например:
ton://transfer/{nft_address}?amount={message_value}&bin={base_64_url(transfer_message)}
.
Получение NFT
Процесс отслеживания отправленных на определенный адрес умного контракта NFT (то есть кошелек пользователя) аналогичен механизму, используемому для отслеживания платежей. Это выполняется путем прослушивания всех новых транзакций в вашем кошельке и их анализа.
Следующие шаги могут отличаться в зависимости от конкретного случая использования. Давайте рассмотрим несколько различных сценариев ниже.
Сервис ожидает передачи известных адресов NFT:
- Проверьте новые транзакции, отправленные с адреса умного контракта NFT item.
- Прочитайте первые 32 бита тела сообщения как тип
uint
, и убедитесь, что они равныop::ownership_assigned()
(0x05138d91
) - Посчитайте следующие 64 бита из тела сообщения как
query_id
. - Прочитайте адрес из тела сообщения как
prev_owner_address
. - Теперь вы можете управлять своим новым NFT.