Есть ли где-нибудь руководство по созданию NFT на TON?
-
Я ищу хороший учебник по созданию смарт-контракта NFT на TON.
Этот вопрос был импортирован из чата Telegram: > <***Скрыто***
click to show
-
Это хорошее предложение для специального пошагового руководства. Я полагаю, что сообщество TON сосредоточится на этом в ближайшие месяцы.
Вот несколько ресурсов, которые помогут в создании NFT:
- TON-NFT-deployer: созданный TON Diamonds, это полноценный проект, который может помочь технически грамотному разработчику развернуть NFT
- Disintar: торговая площадка NFT для TON. Возможно, вам захочется заглянуть сюда, если вы хотите работать создателем, а не быть более технически подкованным.
- Документация TON NFT: Документация TON содержит ссылки на множество ресурсов NFT.
Поскольку были упомянуты смарт-контракты, я хотел бы включить информацию о стандарте и реализации смарт-контракта.
Стандарт довольно объемный, и вы можете прочитать весь анализ на его странице в GitHub. Официально стандартом для NFT на TON является TEP-62 (в отличие от ERC-721 на Ethereum).
Что касается реализации смарт-контракта, то вот простой вариант, который предоставляется документацией TON, но существует также множество его версий:
;; ;; TON NFT Item Smart Contract ;; {- NOTE that this tokens can be transferred within the same workchain. This is suitable for most tokens, if you need tokens transferable between workchains there are two solutions: 1) use more expensive but universal function to calculate message forward fee for arbitrary destination (see `misc/forward-fee-calc.cs`) 2) use token holder proxies in target workchain (that way even 'non-universal' token can be used from any workchain) -} int min_tons_for_storage() asm "50000000 PUSHINT"; ;; 0.05 TON ;; ;; Storage ;; ;; uint64 index ;; MsgAddressInt collection_address ;; MsgAddressInt owner_address ;; cell content ;; (int, int, slice, slice, cell) load_data() { slice ds = get_data().begin_parse(); var (index, collection_address) = (ds~load_uint(64), ds~load_msg_addr()); if (ds.slice_bits() > 0) { return (-1, index, collection_address, ds~load_msg_addr(), ds~load_ref()); } else { return (0, index, collection_address, null(), null()); ;; nft not initialized yet } } () store_data(int index, slice collection_address, slice owner_address, cell content) impure { set_data( begin_cell() .store_uint(index, 64) .store_slice(collection_address) .store_slice(owner_address) .store_ref(content) .end_cell() ); } () send_msg(slice to_address, int amount, int op, int query_id, builder payload, int send_mode) impure inline { var msg = begin_cell() .store_uint(0x10, 6) ;; nobounce - int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool src:MsgAddress -> 010000 .store_slice(to_address) .store_coins(amount) .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) .store_uint(op, 32) .store_uint(query_id, 64); if (~ builder_null?(payload)) { msg = msg.store_builder(payload); } send_raw_message(msg.end_cell(), send_mode); } () transfer_ownership(int my_balance, int index, slice collection_address, slice owner_address, cell content, slice sender_address, int query_id, slice in_msg_body, int fwd_fees) impure inline { throw_unless(401, equal_slices(sender_address, owner_address)); slice new_owner_address = in_msg_body~load_msg_addr(); force_chain(new_owner_address); slice response_destination = in_msg_body~load_msg_addr(); in_msg_body~load_int(1); ;; this nft don't use custom_payload int forward_amount = in_msg_body~load_coins(); throw_unless(708, slice_bits(in_msg_body) >= 1); int rest_amount = my_balance - min_tons_for_storage(); if (forward_amount) { rest_amount -= (forward_amount + fwd_fees); } int need_response = response_destination.preload_uint(2) != 0; ;; if NOT addr_none: 00 if (need_response) { rest_amount -= fwd_fees; } throw_unless(402, rest_amount >= 0); ;; base nft spends fixed amount of gas, will not check for response if (forward_amount) { send_msg(new_owner_address, forward_amount, op::ownership_assigned(), query_id, begin_cell().store_slice(owner_address).store_slice(in_msg_body), 1); ;; paying fees, revert on errors } if (need_response) { force_chain(response_destination); send_msg(response_destination, rest_amount, op::excesses(), query_id, null(), 1); ;; paying fees, revert on errors } store_data(index, collection_address, new_owner_address, content); } () recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure { if (in_msg_body.slice_empty?()) { ;; ignore empty messages return (); } slice cs = in_msg_full.begin_parse(); int flags = cs~load_uint(4); if (flags & 1) { ;; ignore all bounced messages return (); } slice sender_address = cs~load_msg_addr(); cs~load_msg_addr(); ;; skip dst cs~load_coins(); ;; skip value cs~skip_bits(1); ;; skip extracurrency collection cs~load_coins(); ;; skip ihr_fee int fwd_fee = muldiv(cs~load_coins(), 3, 2); ;; we use message fwd_fee for estimation of forward_payload costs (int init?, int index, slice collection_address, slice owner_address, cell content) = load_data(); if (~ init?) { throw_unless(405, equal_slices(collection_address, sender_address)); store_data(index, collection_address, in_msg_body~load_msg_addr(), in_msg_body~load_ref()); return (); } int op = in_msg_body~load_uint(32); int query_id = in_msg_body~load_uint(64); if (op == op::transfer()) { transfer_ownership(my_balance, index, collection_address, owner_address, content, sender_address, query_id, in_msg_body, fwd_fee); return (); } if (op == op::get_static_data()) { send_msg(sender_address, 0, op::report_static_data(), query_id, begin_cell().store_uint(index, 256).store_slice(collection_address), 64); ;; carry all the remaining value of the inbound message return (); } throw(0xffff); } ;; ;; GET Methods ;; (int, int, slice, slice, cell) get_nft_data() method_id { (int init?, int index, slice collection_address, slice owner_address, cell content) = load_data(); return (init?, index, collection_address, owner_address, content); }
-
Привет, так что, если вам нравится, я настоятельно рекомендую вам использовать репозиторий NFT здесь, который использует язык Tact для NFT!
- Это более легко усваивается
- Существует так же просто, как просто извлечь репозиторий и запустить
yarn
, чтобы установить библиотеку и развернуть контракт.
https://github.com/howardpen9/nft-standard-template, наслаждайтесь!