Минт NFT-коллекции

Заминтишь NFT через collection: поймёшь роль owner коллекции, деплой item и куда уходит владение.

Кто минтит и кто становится owner

Минт делает owner коллекции (или контракт с правом mint — зависит от реализации). Collection увеличивает next_item_index и деплоит новый item-контракт с StateInit. В init item получает index, адрес collection и owner — кошелёк получателя NFT.

Без ключа owner коллекции минт недоступен. После минта владение айтемом живёт в item, не в mapping на collection.


Минт item через collection (reference NFT)

typescript
// @ton/core ^0.59.0, @ton/ton ^15.1.0, @ton/blueprint ^0.27.0
// Layout близок к ton-blockchain/token-contract nft (FunC reference)
// Конкретный opcode mint зависит от реализации — сверь со своим контрактом
import { Address, beginCell, toNano, Cell } from "@ton/core";
import { NetworkProvider } from "@ton/blueprint";

/**
 * Типичное тело mint для reference NFT Collection:
 * op::deploy_new_nft / mint (часто uint32 = 1 в эталоне Getgems/ton-blockchain)
 * query_id, item_index, amount (Gram на деплой item), nft_content:^Cell
 */
function buildMintNft(opts: {
  itemIndex: bigint;
  itemOwner: Address;
  individualContentUri: string; // off-chain часть, TEP-64
  queryId?: bigint;
}) {
  const content = beginCell()
    .storeAddress(opts.itemOwner)
    .storeRef(
      beginCell()
        .storeUint(1, 8) // off-chain content marker (TEP-64)
        .storeStringTail(opts.individualContentUri)
        .endCell(),
    )
    .endCell();

  return beginCell()
    .storeUint(1, 32) // op mint/deploy_new_nft — сверь с исходником своей collection
    .storeUint(opts.queryId ?? 0n, 64)
    .storeUint(opts.itemIndex, 64)
    .storeCoins(toNano("0.05")) // Gram, который collection приложит к деплою item
    .storeRef(content)
    .endCell();
}

export async function run(provider: NetworkProvider) {
  const sender = provider.sender();
  if (!sender.address) throw new Error("Wallet not connected");

  // Адрес ТВОЕЙ NFT Collection после деплоя
  const collection = Address.parse(
    "EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c", // ← замени
  );

  const recipient = Address.parse(
    "EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N",
  );

  // index должен совпадать с текущим next_item_index из get_collection_data
  await sender.send({
    to: collection,
    value: toNano("0.1"), // газ owner→collection + деплой item
    body: buildMintNft({
      itemIndex: 0n,
      itemOwner: recipient,
      individualContentUri: "0.json", // collection склеит с common prefix
    }),
  });
}

Перед mainnet сверь opcode и layout с исходником своей collection (Tact-шаблон Blueprint / Getgems / ton-blockchain могут отличаться). Расхождение = failed compute phase.

После минта проверь:

typescript
const itemAddr = await client.runMethod(collection, "get_nft_address_by_index", [
  { type: "int", value: 0n },
]);
// get_nft_data(item) → owner == recipient, init != 0

Как это работает

  • Внешнее сообщение → collection, отправитель должен быть owner коллекции.
  • itemOwner — адрес кошелька получателя NFT, не «временный» контракт.
  • Collection деплоит item с детерминированным адресом (get_nft_address_by_index).
  • individual_content хранит кусок метаданных; полный URI часто собирает get_nft_content на collection.

Частые ошибки

Минтишь не с owner коллекции → collection отклоняет; item не появляется.

Неверный item_index → коллизия или gap; бери актуальный next_item_index из get_collection_data.

Мало Gram в value / amount на деплой → item не инициализируется (init? = 0) или bounce.


Что дальше

Материалы gramdocs.tech носят образовательный характер и не являются финансовой, юридической или инвестиционной рекомендацией. Работа с блокчейном TON и токеном Gram связана с рисками потери средств. Правовая информация