SAVITRI-721: Стандарт NFT
SAVITRI-721 (SNT1 — Savitri Non-Fungible Token) — стандарт NFT для Savitri Network, аналог ERC-721 в Ethereum. Каждый токен имеет уникальный идентификатор и единственного владельца.
Интерфейс
| Функция | Параметры | Возвращает | Описание |
|---|---|---|---|
balance_of | owner | u64 | Количество NFT на адресе |
owner_of | token_id | address | Владелец конкретного токена |
transfer_from | from, to, token_id | Result | Перевести NFT |
approve | to, token_id | Result | Одобрить адрес для перевода токена |
safe_transfer_from | from, to, token_id | Result | Перевод с проверкой безопасности |
token_uri | token_id | String | Получить URI метаданных токена |
mint | to, token_id, uri | Result | Выпустить новый NFT |
Схема хранилища
| Диапазон слотов | Назначение | Вычисление |
|---|---|---|
| 0–99 | BaseContract (зарезервировано) | Прямое |
| 100+ | Владельцы токенов | keccak256(100 || token_id) |
| 200+ | Балансы токенов | keccak256(200 || address) |
| 300+ | Одобрения токенов | keccak256(300 || token_id) |
| 400+ | URI токенов | keccak256(400 || token_id) |
Хеширование Keccak256 предотвращает коллизии слотов между категориями (например, token_id 100 не будет конфликтовать с базовым слотом балансов).
Выпуск NFT
use savitri_contracts::contracts::standards::savitri721::SAVITRI721;
SAVITRI721::mint(
&mut contract_storage,
&storage,
&recipient, // [u8; 32]
42, // token_id: u64
"ipfs://Qm.../meta", // token URI
&mut event_system,
Some(&mut gas_meter),
)?;
Перевод
// Direct transfer
SAVITRI721::transfer_from(
&mut contract_storage,
&storage,
&from, // current owner
&to, // new owner
42, // token_id
&mut event_system,
Some(&mut gas_meter),
)?;
Запросы
// Who owns token #42?
let owner = SAVITRI721::owner_of(&contract_storage, &storage, 42)?;
// How many NFTs does this address own?
let count = SAVITRI721::balance_of(&contract_storage, &storage, &address)?;
// Get metadata URI
let uri = SAVITRI721::token_uri(&contract_storage, &storage, 42)?;
События
| Событие | Поля | Описание |
|---|---|---|
Transfer | from, to, token_id | NFT переведён |
Approval | owner, approved, token_id | Одобрение выдано |
Mint | to, token_id | Новый NFT выпущен |
Через SDK
use savitri_sdk::{ContractClient, Wallet};
let contract = ContractClient::from_url_and_wallet("http://localhost:8545", wallet)?;
// Mint NFT via contract call
let tx = contract.call_contract(
&nft_contract_address,
b"mint",
&encode_mint_args(recipient, token_id, uri),
Some(0),
).await?;