Kiedyś zakładałem, że tworzenie NFT na Solanie oznacza zmaganie się z Metaplex. Taką ścieżkę sugerował każdy poradnik: uruchomienie Candy Machine, zarządzanie kontami metadanych, żonglowanie oddzielnymi programami tylko po to, aby przypisać nazwę i obraz do tokena. Okazało się jednak, że to założenie jest już nieaktualne. Program Token Extensions, znany również jako Token-2022, skondensował tę złożoność bezpośrednio w samym koncie mint. Możesz teraz stworzyć w pełni funkcjonalne NFT bez dotykania programu metadanych ani finansowania dodatkowych kont. Wystarczy przełączyć kilka flag, zapisać dane bezpośrednio w koncie mint i gotowe.

Zmienia to sposób, w jaki programiści powinni myśleć o aktywach cyfrowych na Solanie. W tradycyjnym programowaniu webowym NFT wydaje się odrębną strukturą danych, czymś, co wymaga własnej tabeli i schematu. Na Solanie rzeczywistość jest bardziej płaska i elegancka. NFT nie jest specjalnym obiektem zarządzanym przez zewnętrzny protokół. To po prostu konto mint skonfigurowane z podażą wynoszącą dokładnie jeden i zerową liczbą miejsc po przecinku. Standardowy token pozwala na dzielenie jednostek, ponieważ posiada dużą podaż i wiele miejsc po przecinku. NFT blokuje podaż na poziomie pojedynczej, niepodzielnej jednostki. Wszystko, co czyni je unikalnym, znajduje się w rozszerzeniach (extensions), które działają obok tego podstawowego konta mint.

Stary sposób i nowy sposób

Przed Token Extensions kanoniczny stos obejmował program SPL Token dla samego mintu, plus Metaplex do obsługi metadanych, kolekcji i czasem indeksowania off-chain. Metadane znajdowały się na oddzielnych kontach, połączonych adresami, które trzeba było śledzić. To działało, ale zwiększało powierzchnię operacyjną. Więcej kont oznaczało więcej opłat za rent, więcej ścieżek podpisywania i więcej logiki po stronie klienta, aby uzyskać pełny obraz tokena.

Token Extensions zastępuje to rozproszenie, wpisując możliwości bezpośrednio w konto mint. Potrzebujesz nazwy, symbolu i wskaźnika do mediów off-chain? Włącz rozszerzenie metadanych (metadata extension). Chcesz pogrupować tokeny w kolekcję? Użyj rozszerzeń Group i Member. Konto mint staje się jedynym źródłem prawdy (single source of truth). Dla programistów przyzwyczajonych do baz danych relacyjnych ta zmiana przypomina przejście z rozproszonej architektury mikroserwisów z powrotem do znormalizowanej tabeli z dobrze zaprojektowanymi kluczami obcymi.

Anatomia NFT opartego na rozszerzeniach

Tworzenie NFT za pomocą Token Extensions wymaga zrozumienia, co dokładnie sprawia, że token jest niezamienny (non-fungible) na tym łańcuchu. Podaż musi wynosić jeden. Liczba miejsc po przecinku (decimals) musi wynosić zero. Te dwa ograniczenia zapobiegają ułamkowości (fractionalization). Gdy te parametry zostaną ustawione, włączasz rozszerzenia, które przechowują dodatkowe pola bezpośrednio na koncie mint.

Rozszerzenie metadanych przechowuje nazwę, symbol i URI. To URI wskazuje na plik JSON, zazwyczaj hostowany w zdecentralizowanej pamięci masowej lub na standardowym serwerze WWW, który opisuje obraz, atrybuty i cechy (traits). Nie ma oddzielnego konta metadanych, które trzeba by wykryć i zdeserializować. Dane znajdują się w samym koncie mint, co oznacza, że eksploratory, portfele i oprogramowanie klienckie mogą odczytać podstawową tożsamość tokena, sprawdzając tylko jedno konto.

Przetestowałem to osobiście na devnet. Utworzyłem nowy mint z włączonym rozszerzeniem metadanych, a następnie zapisałem nazwę i symbol bezpośrednio w stanie mintu (mint state). Transakcja zakończyła się sukcesem, a wynik natychmiast pojawił się w Solana Explorer. Nie było drugiego konta, które trzeba by dofinansować lub zlokalizować. Prostota była niemal uderzająca po tygodniach pracy z wielokontową metadaną Metaplex.

Budowanie kolekcji jak wierszy w bazie danych

Kolekcje były kolejnym logicznym krokiem. W starym modelu grupowanie NFT zazwyczaj oznaczało poleganie na Metaplex Certified Collections lub rejestrach off-chain. Token Extensions wprowadza dwie specyficzne prymitywy: rozszerzenie Group oraz rozszerzenie Member.

Oto jak przebiega ta logika. Tworzysz pojedynczy mint, który działa jako nagłówek kolekcji, i włączasz na nim rozszerzenie Group. Następnie, dla każdego pojedynczego NFT w kolekcji, tworzysz mint z włączonym rozszerzeniem Member. Każdy mint członka (member mint) przechowuje wskaźnik powrotny do adresu mintu kolekcji. Relacja ta zachowuje się dokładnie tak jak klucz obcy w bazie danych relacyjnej. Wiersz kolekcji istnieje tylko raz, a każdy wiersz członka odwołuje się do niego bez duplikowania tożsamości kolekcji.

Zbudowałem w ten sposób małą kolekcję testową na devnet. Główny mint kolekcji posiadał flagę group. Pojedyncze tokeny posiadały flagę member i odwoływały się do adresu nadrzędnego. Zapytanie do łańcucha dało mi czystą, łatwą do przeszukiwania strukturę. Nie było potrzeby używania zewnętrznego indeksera, aby zgadywał, czy tokeny należą do siebie. Relacja jest jawna i znajduje się on-chain.

Otwarty schemat i eksperymenty on-chain

Jednym z wyróżniających się szczegółów jest otwarty schemat rozszerzenia metadanych. Starsze standardy często narzucają stałą listę pól. Jeśli chciałeś zapisać coś niestandardowego on-chain, pozostawało Ci jedynie umieszczenie tego w pliku JSON poza łańcuchem (off-chain) lub obchodzenie sztywnych układów kont.

Token Extensions przyjmuje inne podejście. Ponieważ rozszerzenie metadanych akceptuje niestandardowe pola, mogłem dodać atrybut rzadkości (rarity) bezpośrednio do konta mint. Zapisałem pole, wysłałem transakcję i odświeżyłem Solana Explorer. Wartość rzadkości pojawiła się natychmiast obok nazwy i symbolu. Dla twórców gier lub każdego, kto buduje dynamiczne zasoby, ta elastyczność ma znaczenie. Możesz udostępniać kluczowe cechy on-chain bez konieczności używania zewnętrznego weryfikatora do analizy plików JSON.

Luka off-chain: URI i buforowanie

Mimo całej elegancji przechowywania danych on-chain, jedna lekcja wybrzmiała wyjątkowo wyraźnie: tożsamość wciąż znajduje się off-chain. Mint nie przechowuje Twojego obrazu. Przechowuje URI. Gdy zaktualizowałem to URI i zatwierdziłem zmianę w devnet, łańcuch natychmiast odzwierciedlił nowy wskaźnik. Eksploratory bloków pokazywały zaktualizowany link bez opóźnień.

Jednak mój portfel miał opóźnienie. Przez kilka minut uparcie wyświetlał stary obraz, serwując wersję z pamięci podręcznej (cache), podczas gdy dane bazowe on-chain uległy już zmianie. To praktyczna rzeczywistość, którą programiści muszą uwzględnić w planowaniu. Rejestr Solana jest szybki. Czasy potwierdzeń są krótkie. Jednak warstwa wizualna, z którą wchodzą w interakcję użytkownicy, zależy od pamięci podręcznych HTTP, propagacji CDN i interwałów odświeżania specyficznych dla danego portfela. Jeśli budujesz dynamiczny NFT, który zmienia się na podstawie zdarzeń ze świata rzeczywistego, nie możesz zakładać, że użytkownik zobaczy zmianę w momencie zatwierdzenia transakcji. Potrzebujesz strategii unikania cache'u (cache-busting), wersjonowania ścieżek URI lub jawnych wyzwalaczy odświeżania w swoim frontendzie.

Co dalej

Moje eksperymenty w devnet położyły fundament pod bardziej dynamiczny projekt. Kolejnym krokiem jest kolekcja