قبلاً تصور میکردم ساخت یک NFT روی Solana به معنای کلنجار رفتن با Metaplex است. این همان مسیری بود که هر آموزش دیگری پیشنهاد میداد: راهاندازی یک Candy Machine، مدیریت حسابهای metadata، و سر و کله زدن با برنامههای مجزا فقط برای پیوست کردن یک نام و تصویر به یک توکن. اما مشخص شد که این تصور قدیمی شده است. برنامه Token Extensions که با نام Token-2022 نیز شناخته میشود، تمام آن پیچیدگیها را در خودِ حساب mint ادغام کرده است. اکنون میتوانید یک NFT کاملاً کاربردی را بدون دست زدن به یک برنامه metadata یا تامین بودجه برای حسابهای اضافی ایجاد کنید. کافی است چند پرچم (flag) را تغییر دهید، دادهها را مستقیماً در حساب mint بنویسید و کار تمام است.
این موضوع طرز فکر توسعهدهندگان را در مورد داراییهای دیجیتال در Solana تغییر میدهد. در توسعه وب سنتی، یک NFT مانند یک ساختار دادهای متمایز به نظر میرسد؛ چیزی که به جدول و شمای (schema) مخصوص به خود نیاز دارد. اما در Solana، واقعیت تختتر و ظریفتر است. یک NFT یک شیء خاص نیست که توسط یک پروتکل خارجی مدیریت شود؛ بلکه صرفاً یک حساب mint است که با موجودی دقیقاً یک واحد و صفر رقم اعشار پیکربندی شده است. یک توکن استاندارد به شما اجازه میدهد واحدها را تقسیم کنید، زیرا موجودی زیاد و اعشار متعددی دارد. اما یک NFT موجودی را روی یک واحد واحد و غیرقابل تقسیم قفل میکند. هر آنچه آن را منحصربهفرد میکند، در افزونههایی (extensions) قرار دارد که در کنار همان حساب اصلی mint قرار میگیرند.
روش قدیمی و روش جدید
قبل از Token Extensions، پشته (stack) استاندارد شامل برنامه SPL Token برای خودِ mint، به همراه Metaplex برای metadata، مجموعهها (collections) و گاهی اوقات ایندکسگذاری آفچین (off-chain indexing) بود. متادیتا در حسابهای جداگانه قرار داشت که با آدرسهایی که باید ردیابی میکردید، به هم متصل میشدند. این روش کار میکرد، اما سطح پیچیدگی و تعامل (surface area) را افزایش میداد. حسابهای بیشتر به معنای اجاره (rent) بیشتر، مسیرهای امضای بیشتر و منطق سمت کلاینت بیشتر برای درک تصویر کامل یک توکن بود.
Token Extensions با گنجاندن مستقیم قابلیتها در حساب mint، این پراکندگی را از بین میبرد. به نام، نماد (symbol) و یک اشارهگر به رسانههای آفچین نیاز دارید؟ افزونه metadata را فعال کنید. میخواهید توکنها را در یک مجموعه گروهبندی کنید؟ از افزونههای Group و Member استفاده کنید. در اینجا، حساب mint به تنها منبع حقیقت (single source of truth) تبدیل میشود. برای توسعهدهندگانی که با پایگاههای داده رابطهای کار کردهاند، این تغییر مانند حرکت از یک معماری میکروسرویس توزیعشده به یک جدول نرمالشده با کلیدهای خارجی (foreign keys) خوشساخت است.
کالبدشکافی یک NFT مبتنی بر افزونه (Extension)
ایجاد یک NFT با استفاده از Token Extensions مستلزم درک دقیق این نکته است که چه چیزی یک توکن را در این زنجیره به حالت غیرقابل تعویض (non-fungible) تبدیل میکند. موجودی (supply) باید برابر با یک باشد و اعشار (decimals) باید برابر با صفر باشد. این دو محدودیت از خردشدگی (fractionalization) جلوگیری میکنند. پس از تنظیم این پارامترها، افزونههایی را فعال میکنید که فیلدهای اضافی را مستقیماً در حساب mint ذخیره میکنند.
افزونه metadata شامل نام، نماد و URI است. آن URI به یک فایل JSON اشاره میکند که معمولاً در یک ذخیرهسازی غیرمتمرکز یا یک سرور وب استاندارد میزبانی میشود و تصویر، ویژگیها (attributes) و صفات (traits) را توصیف میکند. دیگر نیازی به کشف و سریالسازی معکوس (deserialize) یک حساب metadata جداگانه نیست. دادهها روی خودِ حساب mint قرار دارند، به این معنی که اکسپلوررها، کیفپولها و نرمافزارهای کلاینت میتوانند هویت اصلی توکن را تنها با بررسی یک حساب بخوانند.
من این موضوع را مستقیماً روی devnet آزمایش کردم. یک mint جدید با افزونه metadata فعال ایجاد کردم، سپس نام و نماد را مستقیماً در وضعیت (state) حساب mint نوشتم. تراکنش با موفقیت انجام شد و نتیجه بلافاصله در Solana Explorer ظاهر شد. هیچ حساب دومی برای تامین بودجه یا یافتن وجود نداشت. این سادگی پس از هفتهها کار با متادیتای چند-حسابی Metaplex، واقعاً مبهوتکننده بود.
ساخت مجموعهها مانند ردیفهای پایگاه داده
ساخت مجموعهها (collections) قدم منطقی بعدی بود. در مدل قدیمی، گروهبندی NFTها معمولاً به Metaplex Certified Collections یا رجیسترهای آفچین متکی بود. Token Extensions دو اصل اولیه (primitive) خاص را معرفی میکند: افزونه Group و افزونه Member.
منطق کار به این صورت است: شما یک mint واحد ایجاد میکنید که به عنوان سربرگ مجموعه (collection header) عمل میکند و افزونه Group را روی آن فعال میکنید. سپس، برای هر NFT انفرادی در آن مجموعه، یک mint با افزونه Member فعال ایجاد میکنید. هر حساب mintِ عضو، یک اشارهگر به آدرس حساب mintِ مجموعه ذخیره میکند. این رابطه دقیقاً مانند یک کلید خارجی (foreign key) در یک پایگاه داده رابطهای عمل میکند. ردیف مجموعه فقط یک بار وجود دارد و هر ردیف عضو بدون تکرار هویت مجموعه، به آن ارجاع میدهد.
من یک مجموعه آزمایشی کوچک را به این روش روی devnet ساختم. حساب mint اصلی مجموعه، پرچم group را داشت. توکنهای انفرادی پرچم member را داشتند و به آدرس والد ارجاع میدادند. پرسوجو (query) از زنجیره، ساختاری تمیز و قابل پیمایش (traversable) به من داد. نیازی به یک ایندکسگر شخص ثالث نبود تا حدس بزند آیا توکنها متعلق به یک گروه هستند یا خیر. این رابطه صریح و روی زنجیره (on-chain) است.
طرحواره باز و آزمایشهای درونزنجیرهای
یکی از جزئیات برجسته، طرحواره بازِ (open schema) افزونه متادیتا است. استانداردهای قدیمیتر اغلب فهرستی از فیلدهای ثابت را تحمیل میکنند. اگر میخواستید چیزی غیر استاندارد را درونزنجیرهای ذخیره کنید، مجبور بودید آن را در یک فایل JSON خارج از زنجیره ذخیره کنید یا با ساختارهای صلب حسابها دستوپنجه نرم کنید.
Token Extensions رویکرد متفاوتی را در پیش میگیرد. از آنجایی که افزونه متادیتا فیلدهای سفارشی را میپذیرد، من توانستم یک ویژگی کمیابی (rarity attribute) را مستقیماً به حساب mint اضافه کنم. فیلد را نوشتم، تراکنش را فرستادم و Solana Explorer را بازنشانی کردم. مقدار کمیابی بلافاصله در کنار نام و نماد ظاهر شد. برای توسعهدهندگان بازی یا هر کسی که داراییهای پویا (dynamic assets) میسازد، این انعطافپذیری اهمیت دارد. شما میتوانید ویژگیهای حیاتی را بدون نیاز به یک تأییدکننده خارجی برای تجزیه (parse) JSON، درونزنجیرهای نمایش دهید.
شکاف خارج از زنجیره: URIها و کشینگ
با وجود تمام ظرافتهای ذخیرهسازی درونزنجیرهای، یک درس به وضوح آشکار شد: هویت همچنان خارج از زنجیره قرار دارد. حساب mint تصویر شما را ذخیره نمیکند، بلکه یک URI را ذخیره میکند. وقتی آن URI را بهروزرسانی کردم و تغییر را در devnet ثبت کردم، زنجیره بلافاصله نشانگر (pointer) جدید را منعکس کرد. بلاکاکسپلوررها لینک بهروزرسانیشده را بدون تأخیر نشان دادند.
اما کیف پول من با تأخیر مواجه شد. تا چندین دقیقه همچنان تصویر قدیمی را نمایش میداد و با لجاجت نسخه کششده را ارائه میکرد، در حالی که دادههای زیربنایی در درونزنجیره تغییر کرده بودند. این یک واقعیت عملی است که توسعهدهندگان باید برای آن برنامهریزی کنند. دفتر کل Solana سریع است. زمانهای تأیید کوتاه هستند. با این حال، لایه بصری که کاربران با آن تعامل دارند، به کشهای HTTP، انتشار CDN و فواصل زمانی بازنشانی (refresh) مخصوص هر کیف پول بستگی دارد. اگر یک NFT پویا میسازید که بر اساس رویدادهای دنیای واقعی تغییر میکند، نمیتوانید فرض کنید کاربر درست در لحظه نهایی شدن تراکنش، تغییر را میبیند. شما به استراتژیهای مقابله با کش (cache-busting)، نسخهبندی در مسیرهای URI یا محرکهای بازنشانی صریح در فرانتاند خود نیاز دارید.
گام بعدی چیست
آزمایشهای من در devnet زمینهساز پروژهای پویاتر شده است. گام بعدی، یک مجموعه است
