Разработка системы рарити (редкости) NFT
Rarity score — то, что превращает однотипные токены коллекции в иерархию с разной рыночной стоимостью. Без продуманной системы рарити коллекция из 10 000 токенов торгуется как однородная масса, где цена определяется только floor price. С правильной системой — топ-1% коллекции стоит в 10-50 раз дороже floor. Это прямо влияет на ликвидность и интерес трейдеров. Технически задача состоит из двух частей: off-chain генерация и ранжирование, и on-chain верификация через Merkle tree или хранение в metadata.
Алгоритмы расчёта rarity score
Statistical rarity (метод Rarity Tools)
Классический подход: для каждого атрибута считается частота появления в коллекции. Score = сумма 1 / trait_frequency по всем атрибутам токена.
# Псевдокод расчёта
for nft in collection:
score = 0
for trait_type, trait_value in nft['attributes']:
frequency = count(trait_value) / total_supply
score += 1 / frequency
nft['rarity_score'] = score
Проблема statistical rarity: trait count bias. Токен с 10 обычными атрибутами может получить более высокий score, чем токен с 5 атрибутами, один из которых уникальный (1/10000). Это counterintuitive для пользователей и создаёт споры о «справедливости» рарити.
Information content rarity (метод Rarity Sniper)
Использует information-theoretic подход: каждый атрибут вносит вклад пропорционально его информационному содержанию -log2(probability).
IC(trait) = -log2(count(trait) / total_supply)
Атрибут с частотой 0.1% (1 из 1000) даёт IC = log2(1000) ≈ 10 bits. Атрибут с частотой 50% даёт IC = 1 bit. Итоговый score = сумма IC всех атрибутов. Это более справедливая метрика, которая не штрафует за количество атрибутов.
Нормализованный score для single-attribute rarities
Если в коллекции есть trait типа "background" с 20 вариантами и trait "special" с 2 вариантами (один из которых встречается в 1 токене), нормализация позволяет сравнивать вклад разных trait types на единой шкале:
normalized_score(trait) = rarity_score(trait) / max_rarity_score(trait_type)
Выбор алгоритма зависит от структуры коллекции и маркетинговой стратегии. Для коллекций с "Legendary" tier — статистический подход с trait type weighting работает лучше.
Технический стек реализации
Генерация и расчёт (off-chain)
Python-скрипт с тремя этапами:
- Trait analysis — парсинг всех JSON metadata, построение частотной таблицы по каждому trait_type/trait_value
- Score calculation — выбранный алгоритм, нормализация, ранжирование
-
Output — обновлённые JSON файлы с добавленными полями
rarity_score,rarity_rank
Ключевой момент: metadata обновляется до загрузки на IPFS. После pin на IPFS CID фиксирован — изменить rarity score без смены CID нельзя. Прозрачность и неизменность — обязательные условия доверия к проекту.
Merkle-based on-chain верификация
Для проектов, которые хотят on-chain верификацию rarity (например, для выдачи бонусов топ-100 холдерам):
// Merkle proof верификация rarity rank
function verifyRarityRank(
uint256 tokenId,
uint256 rank,
bytes32[] calldata proof
) external view returns (bool) {
bytes32 leaf = keccak256(abi.encodePacked(tokenId, rank));
return MerkleProof.verify(proof, rarityMerkleRoot, leaf);
}
Root генерируется из полного дерева {tokenId: rank} и фиксируется в контракте после reveal. Пользователь доказывает свой rank без хранения 10 000 значений on-chain.
API для агрегаторов
Rarity Tool, Rarity Sniper, OpenSea — все они читают metadata из tokenURI(). Важно корректно форматировать поле attributes:
{
"attributes": [
{"trait_type": "Background", "value": "Gold"},
{"trait_type": "Eyes", "value": "Laser"},
{"display_type": "number", "trait_type": "Rarity Rank", "value": 42},
{"display_type": "number", "trait_type": "Rarity Score", "value": 847.3}
]
}
display_type: "number" позволяет OpenSea и другим маркетплейсам показывать rarity rank как числовое поле с сортировкой.
Типичные ошибки при разработке rarity системы
Trait count не учтён. Токены с разным числом атрибутов (у некоторых NFT может не быть определённых trait_type) получают несправедливый score. Решение: None как отдельное значение с частотой появления.
Score рассчитан до финальной генерации. Если художник добавил новые варианты после расчёта score — вся таблица невалидна. Рarity рассчитывается единожды по финальной коллекции, до любых изменений.
Отсутствие тай-брейкера. Токены с одинаковым score получают одинаковый rank. Стандартный подход — тай-брейк по tokenId (меньший ID = более высокий rank при равных score).
Процесс работы
Аналитика trait structure (0.5-1 день). Анализируем набор атрибутов, частоты, выбираем алгоритм. Если у проекта уже есть частичная генерация — проверяем корректность trait distribution (нет ли случайных дублей, пропусков).
Разработка скрипта (1-2 дня). Python pipeline: trait analysis → score calculation → metadata update → IPFS upload. Выходные данные: JSON с rarity_score и rarity_rank для каждого токена, CSV для команды проекта, обновлённые metadata файлы.
On-chain компонент (1 день если нужен). Merkle tree генерация, деплой верификатора, тест доказательств.
Интеграция с маркетплейсами (0.5 дня). Верификация корректного отображения на OpenSea, Blur, LooksRare.
Сроки: 2-3 дня для коллекции до 10 000 токенов. Для более крупных коллекций или нестандартных алгоритмов — до 5 дней. Стоимость рассчитывается после анализа структуры коллекции.







