আমি আগে ভাবতাম যে Solana-তে একটি NFT তৈরি করার মানে হলো Metaplex-এর সাথে লড়াই করা। প্রতিটি টিউটোরিয়ালেই সেই পথটিই দেখানো হতো: একটি Candy Machine চালু করা, metadata অ্যাকাউন্টগুলো পরিচালনা করা, এবং একটি টোকেনের সাথে নাম ও ছবি যুক্ত করার জন্য আলাদা আলাদা প্রোগ্রাম সামলানো। দেখা যাচ্ছে যে সেই ধারণাটি পুরনো হয়ে গেছে। Token Extensions প্রোগ্রাম, যা Token-2022 নামেও পরিচিত, সেই জটিলতাকে সরাসরি mint-এর মধ্যেই নিয়ে এসেছে। এখন আপনি কোনো metadata প্রোগ্রাম স্পর্শ না করেই বা অতিরিক্ত অ্যাকাউন্টে ফান্ড না দিয়েই একটি সম্পূর্ণ কার্যকর NFT তৈরি করতে পারেন। আপনি শুধু কয়েকটি flag পরিবর্তন করবেন, সরাসরি mint অ্যাকাউন্টে ডেটা লিখবেন, আর আপনার কাজ শেষ।
এটি Solana-তে ডিজিটাল অ্যাসেট সম্পর্কে ডেভেলপারদের চিন্তাভাবনার ধরন বদলে দিচ্ছে। প্রথাগত ওয়েব ডেভেলপমেন্টে, একটি NFT একটি স্বতন্ত্র ডেটা স্ট্রাকচার বলে মনে হয়, যার জন্য নিজস্ব টেবিল এবং স্কিমা প্রয়োজন। Solana-তে বাস্তবতা আরও সহজ এবং মার্জিত। একটি NFT কোনো এক্সটার্নাল প্রোটোকল দ্বারা পরিচালিত বিশেষ কোনো অবজেক্ট নয়। এটি কেবল একটি mint অ্যাকাউন্ট যা ঠিক একটি সাপ্লাই (supply) এবং শূন্য ডেসিমেল (zero decimals) দিয়ে কনফিগার করা হয়েছে। একটি স্ট্যান্ডার্ড টোকেন আপনাকে ইউনিটগুলো ভাগ করতে দেয় কারণ এতে বড় সাপ্লাই এবং একাধিক ডেসিমেল থাকে। একটি NFT সাপ্লাইকে একটি মাত্র অবিভাজ্য ইউনিটে লক করে দেয়। যা কিছু এটিকে অনন্য করে তোলে, তা সেই কোর mint অ্যাকাউন্টের সাথে থাকা extensions-এর মধ্যে থাকে।
পুরোনো পদ্ধতি এবং নতুন পদ্ধতি
Token Extensions আসার আগে, প্রথাগত স্ট্যাকে mint-এর জন্য SPL Token প্রোগ্রাম এবং metadata, collections এবং কখনও কখনও off-chain indexing-এর জন্য Metaplex ব্যবহার করা হতো। Metadata আলাদা অ্যাকাউন্টে থাকত, যা আপনাকে ট্র্যাক করতে হতো এমন অ্যাড্রেস দ্বারা লিঙ্ক করা ছিল। এটি কাজ করত, কিন্তু এটি জটিলতা বাড়িয়ে দিত। বেশি অ্যাকাউন্টের মানে হলো বেশি rent, বেশি signing paths এবং একটি টোকেনের সম্পূর্ণ চিত্র বোঝার জন্য আরও বেশি client-side logic।
Token Extensions সরাসরি mint-এর মধ্যেই সক্ষমতাগুলো যুক্ত করে সেই বিশৃঙ্খলা দূর করে। নাম, সিম্বল এবং off-chain মিডিয়ার জন্য একটি পয়েন্টার প্রয়োজন? metadata extension চালু করুন। টোকেনগুলোকে একটি collection-এ গ্রুপ করতে চান? Group এবং Member extension ব্যবহার করুন। Mint নিজেই হয়ে ওঠে 'single source of truth'। রিলেশনাল ডেটাবেস ব্যবহারে অভ্যস্ত ডেভেলপারদের কাছে এই পরিবর্তনটি একটি distributed microservices architecture থেকে পুনরায় সুপরিকল্পিত foreign keys সহ একটি normalized table-এ ফিরে আসার মতো মনে হবে।
Extension-ভিত্তিক NFT-এর গঠন
Token Extensions দিয়ে একটি NFT তৈরি করতে হলে এই চেইনে ঠিক কী কারণে একটি টোকেন non-fungible হয় তা বোঝা প্রয়োজন। Supply অবশ্যই এক হতে হবে। Decimals অবশ্যই শূন্য হতে হবে। এই দুটি সীমাবদ্ধতা fractionalization রোধ করে। একবার এই প্যারামিটারগুলো সেট হয়ে গেলে, আপনি এমন extension চালু করতে পারেন যা সরাসরি mint অ্যাকাউন্টে অতিরিক্ত ফিল্ড সংরক্ষণ করে।
Metadata extension-এ নাম, সিম্বল এবং URI থাকে। সেই URI একটি JSON ফাইলের দিকে নির্দেশ করে, যা সাধারণত decentralized storage বা একটি স্ট্যান্ডার্ড ওয়েব সার্ভারে হোস্ট করা থাকে এবং যা ইমেজ, attributes এবং traits বর্ণনা করে। এখানে খুঁজে বের করার বা deserialize করার জন্য কোনো আলাদা metadata অ্যাকাউন্ট নেই। ডেটা সরাসরি mint-এর মধ্যেই থাকে, যার মানে হলো explorers, wallets এবং client software শুধুমাত্র একটি অ্যাকাউন্ট পরীক্ষা করেই টোকেনের মূল পরিচয় পড়তে পারে।
আমি এটি সরাসরি devnet-এ পরীক্ষা করেছি। আমি metadata extension চালু করে একটি নতুন mint তৈরি করেছি, তারপর সরাসরি mint state-এ নাম এবং সিম্বল লিখেছি। ট্রানজ্যাকশনটি সফল হয়েছে এবং ফলাফলটি সাথে সাথে Solana Explorer-এ দেখা গেছে। ফান্ড করার বা খুঁজে বের করার জন্য কোনো দ্বিতীয় অ্যাকাউন্ট ছিল না। কয়েক সপ্তাহ ধরে multi-account Metaplex metadata নিয়ে কাজ করার পর এই সরলতা দেখে আমি প্রায় অবাক হয়ে গিয়েছিলাম।
ডেটাবেস রো (Row)-এর মতো কালেকশন তৈরি করা
কালেকশন ছিল পরবর্তী যৌক্তিক ধাপ। লিগ্যাসি মডেলে, NFT-গুলোকে গ্রুপ করার মানে ছিল সাধারণত Metaplex Certified Collections বা off-chain registries-এর ওপর নির্ভর করা। Token Extensions দুটি নির্দিষ্ট primitive প্রবর্তন করেছে: Group extension এবং Member extension।
লজিকটি যেভাবে কাজ করে তা নিচে দেওয়া হলো। আপনি একটি মাত্র mint তৈরি করবেন যা কালেকশন হেডার হিসেবে কাজ করবে এবং এতে Group extension চালু করবেন। তারপর, কালেকশনের প্রতিটি স্বতন্ত্র NFT-এর জন্য আপনি Member extension চালু করে একটি mint তৈরি করবেন। প্রতিটি member mint কালেকশন mint অ্যাড্রেসের দিকে একটি পয়েন্টার সংরক্ষণ করে। এই সম্পর্কটি একটি রিলেশনাল ডেটাবেসের foreign key-এর মতোই কাজ করে। কালেকশন রো (row) একবারই থাকে এবং প্রতিটি মেম্বার রো কালেকশনের পরিচয় ডুপ্লিকেট না করেই এটিকে রেফারেন্স করে।
আমি এভাবে devnet-এ একটি ছোট টেস্ট কালেকশন তৈরি করেছি। মূল কালেকশন mint-এ group flag ছিল। প্রতিটি স্বতন্ত্র টোকেনে member flag ছিল এবং সেগুলো parent অ্যাড্রেসকে রেফারেন্স করছিল। চেইনটি কুয়েরি (query) করে আমি একটি পরিষ্কার এবং সহজে নেভিগেটযোগ্য স্ট্রাকচার পেয়েছি। টোকেনগুলো একে অপরের সাথে সম্পর্কিত কি না তা অনুমান করার জন্য কোনো থার্ড-পার্টি ইনডেক্সারের প্রয়োজন ছিল না। সম্পর্কটি স্পষ্ট এবং অন-চেইন (on-chain)।
ওপেন স্কিমা এবং অন-চেইন পরীক্ষা-নিরীক্ষা
একটি উল্লেখযোগ্য বিষয় হলো মেটাডেটা এক্সটেনশনের ওপেন স্কিমা। পুরনো স্ট্যান্ডার্ডগুলো প্রায়ই একটি নির্দিষ্ট ফিল্ড লিস্ট বা তালিকার বাধ্যবাধকতা আরোপ করে। আপনি যদি অন-চেইনে কোনো নন-স্ট্যান্ডার্ড কিছু সংরক্ষণ করতে চাইতেন, তবে আপনাকে সেটি অফ-চেইন JSON-এ রাখতে হতো অথবা কঠোর অ্যাকাউন্ট লেআউটগুলোর সাথে সামঞ্জস্য রেখে কোনো বিকল্প উপায় খুঁজতে হতো।
Token Extensions একটি ভিন্ন পদ্ধতি গ্রহণ করে। যেহেতু মেটাডেটা এক্সটেনশন কাস্টম ফিল্ড গ্রহণ করে, আমি সরাসরি মিন্ট অ্যাকাউন্টে একটি রারিটি (rarity) অ্যাট্রিবিউট যোগ করতে পেরেছিলাম। আমি ফিল্ডটি লিখলাম, ট্রানজ্যাকশনটি পাঠালাম এবং Solana Explorer রিফ্রেশ করলাম। নাম এবং সিম্বলের পাশাপাশি রারিটি ভ্যালুটি তাৎক্ষণিকভাবে দেখা গেল। গেম ডেভেলপার বা ডাইনামিক অ্যাসেট তৈরি করছেন এমন যে কারো জন্য এই নমনীয়তা অত্যন্ত গুরুত্বপূর্ণ। JSON পার্স করার জন্য কোনো এক্সটার্নাল ভেরিফায়ারের প্রয়োজন ছাড়াই আপনি অন-চেইনে গুরুত্বপূর্ণ বৈশিষ্ট্যগুলো প্রকাশ করতে পারেন।
অফ-চেইন গ্যাপ: URIs এবং ক্যাশিং
অন-চেইন স্টোরেজের সমস্ত চমৎকারিত্ব সত্ত্বেও, একটি শিক্ষা স্পষ্টভাবে সামনে এসেছে: আইডেন্টিটি বা পরিচয় এখনও অফ-চেইনেই থাকে। মিন্ট আপনার ছবি সংরক্ষণ করে না। এটি একটি URI সংরক্ষণ করে। যখন আমি সেই URI আপডেট করলাম এবং devnet-এ পরিবর্তনটি কমিট করলাম, চেইনটি তাৎক্ষণিকভাবে নতুন পয়েন্টারটি প্রতিফলিত করল। ব্লক এক্সপ্লোরারগুলো কোনো বিলম্ব ছাড়াই আপডেট করা লিঙ্কটি দেখিয়েছিল।
কিন্তু আমার ওয়ালেটটি কিছুটা ধীরগতিতে কাজ করছিল (lagged)। অন-চেইনের মূল ডেটা ইতিমধ্যে পরিবর্তিত হয়ে গেলেও, এটি কয়েক মিনিট ধরে জেদিভাবে একটি ক্যাশ করা (cached) ভার্সন দেখাচ্ছিল। এটি একটি বাস্তব পরিস্থিতি যার জন্য ডেভেলপারদের পরিকল্পনা করতে হবে। Solana লেজার দ্রুত। কনফার্মেশন টাইম খুব কম। তবুও ব্যবহারকারীরা যে ভিজ্যুয়াল লেয়ারের সাথে ইন্টারঅ্যাক্ট করেন তা HTTP ক্যাশ, CDN প্রোপাগেশন এবং ওয়ালেট-নির্দিষ্ট রিফ্রেশ ইন্টারভালের ওপর নির্ভর করে। আপনি যদি বাস্তব জগতের ঘটনার ওপর ভিত্তি করে পরিবর্তনশীল কোনো ডাইনামিক NFT তৈরি করেন, তবে আপনি ধরে নিতে পারেন না যে ট্রানজ্যাকশন সম্পন্ন হওয়ার সাথে সাথেই ব্যবহারকারী সেই পরিবর্তন দেখতে পাবেন। আপনার ক্যাশ-বাস্টিং (cache-busting) কৌশল, URI পাথে ভার্সনিং, অথবা ফ্রন্টএন্ডে স্পষ্ট রিফ্রেশ ট্রিগার প্রয়োজন হবে।
এরপর কী আসছে
আমার devnet পরীক্ষাগুলো একটি আরও ডাইনামিক প্রজেক্টের ভিত্তি স্থাপন করেছে। পরবর্তী ধাপ হলো একটি কালেকশন
