Solana Program Library Token (SPL Token) टोकन के लिए Solana का स्टैण्डर्ड है: टोकन कैसे बनाए जाते हैं और उन्हें कैसे व्यवहार करना चाहिए। यह Ethereum के टोकन स्टैण्डर्ड जैसे ERC-20 (फंजिबल टोकन) और ERC-721 (NFTs) के समकक्ष Solana का वर्ज़न है।
Ethereum के विपरीत, जो प्रत्येक टोकन स्टैण्डर्ड के लिए अलग-अलग स्मार्ट कॉन्ट्रैक्ट का उपयोग करता है, Solana में सभी SPL टोकन एक ही प्रोग्राम का उपयोग करते हैं। इसका मतलब यह है कि Solana पर सभी टोकन समान अंतर्निहित लॉजिक (underlying logic) साझा करते हैं, जहाँ टोकन-विशिष्ट पैरामीटर एक अलग प्रोग्राम कोड द्वारा सेट होने के बजाय निर्माण के दौरान सेट किए जाते हैं। SPL Token प्रोग्राम में केवल लॉजिक होता है, जबकि सभी टोकन डेटा अलग से स्टोर किए जाते हैं। यह इस बात के अनुरूप है कि Solana कैसे लॉजिक को स्टेट (state) से अलग-अलग अकाउंट्स में विभाजित करता है।
Ethereum की तुलना में SPL टोकन के बारे में सोचने का एक तरीका यहाँ दिया गया है: Ethereum पर, आप आमतौर पर प्रत्येक यूनिक टोकन के लिए एक नया स्मार्ट कॉन्ट्रैक्ट (जैसे ERC-20) डिप्लॉय करते हैं। Solana पर, नए कोड को डिप्लॉय करने के बजाय, आप इस सिंगल SPL प्रोग्राम के साथ इंटरैक्ट करते हैं, जिसमें टोकन को परिभाषित करने, मिंटिंग (minting), ट्रांसफर, अप्रूवल और बर्निंग (burning) के लिए आवश्यक सभी निर्देश (instructions) होते हैं।
Ethereum पर, प्रत्येक टोकन कस्टम कोड के साथ अपना स्वयं का स्मार्ट कॉन्ट्रैक्ट होता है, जिसका अर्थ है कि USDC अप्रूवल को DAI से अलग तरीके से हैंडल कर सकता है; लचीलेपन (flexibility) के संदर्भ में इसके फायदे हैं, लेकिन इससे अप्रत्याशित व्यवहार भी हो सकता है। Solana पर, प्रत्येक SPL टोकन समान ट्रांसफर फंक्शन, समान अप्रूवल सिस्टम और समान सुरक्षा जांच (security checks) का उपयोग करता है।
यह आर्टिकल SPL टोकन कॉन्सेप्ट्स की व्याख्या करता है और बताता है कि Solana टोकन लॉजिक को टोकन डेटा से कैसे अलग करता है। इसमें शामिल हैं:
- Solana का टोकन आर्किटेक्चर Ethereum से कैसे अलग है,
- तीन प्रमुख अकाउंट्स जो SPL टोकन को काम करने योग्य बनाते हैं,
- Solana सभी टोकन के लिए एक ही प्रोग्राम का उपयोग क्यों करता है, और
- Solana उपयोगकर्ता के टोकन बैलेंस को कैसे ट्रैक करता है।
अगले आर्टिकल, Creating SPL Tokens with Anchor में, हम दिखाएंगे कि SPL टोकन कैसे बनाएं और ट्रांसफर करें।
यह समझने के लिए कि व्यवहार में यह सब कैसे काम करता है, हम पहले स्वयं SPL Token प्रोग्राम को देखते हैं। हम कभी-कभी इसे केवल टोकन प्रोग्राम कहेंगे, लेकिन दोनों का अर्थ एक ही है।
Token Program
SPL Token प्रोग्राम SPL टोकन कार्यक्षमता को प्रबंधित करने के लिए जिम्मेदार मुख्य ऑन-चेन प्रोग्राम है। इसमें SPL टोकन बनाने का लॉजिक होता है और यह परिभाषित करता है कि वे कैसे व्यवहार करते हैं। SPL Token प्रोग्राम एक निश्चित पते (fixed address) पर रहता है: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA।
Token Program उन सभी अकाउंट्स का मालिक (owner) होता है जो SPL टोकन की स्टेट को स्टोर करते हैं (हम आगे बढ़ने पर इन अकाउंट्स का परिचय देंगे)। इस ओनरशिप का मतलब है कि Token Program एकमात्र प्रोग्राम है जो इन अकाउंट्स में डेटा को मॉडिफाई कर सकता है।
जिन पाठकों को Solana के अकाउंट ओनरशिप मॉडल को फिर से समझने की आवश्यकता है, वे Understanding Account Ownership in Solana देख सकते हैं।
इसके बाद, हम SPL टोकन से जुड़े विभिन्न अकाउंट्स पर चर्चा करेंगे, जो Mint Account, और Token Account तथा Associated Token Account (ATA) हैं। प्रत्येक अकाउंट टोकन के लेखांकन (accounting) और ट्रांसफर में एक विशिष्ट भूमिका निभाता है।
Mint account
प्रत्येक व्यक्तिगत SPL टोकन में एक यूनिक Mint account होता है जो उस टोकन के बारे में ग्लोबल जानकारी स्टोर करता है। यह टोकन की कुल सप्लाई (total supply), डेसीमल्स (decimals) की संख्या और किन पतों (यदि कोई हो) के पास टोकन मिंट करने और अकाउंट्स को फ्रीज करने (यानी ब्लैकलिस्टिंग) की ऑथोरिटी (authority) है, जैसे डेटा रखता है। जैसा कि ऊपर उल्लेख किया गया है, टोकन का मुख्य लॉजिक SPL Token Program में ही रहता है।
प्रत्येक mint account यूनिक होता है और एक नया SPL टोकन इनिशियलाइज़ करते समय SPL Token Program के माध्यम से बनाया जाता है। जब हम Solana में किसी टोकन एड्रेस का उल्लेख करते हैं, तो हमारा मतलब उसके mint account एड्रेस से भी होता है, क्योंकि वे समान होते हैं। उदाहरण के लिए, क्रमशः USDC और USDT के लिए टोकन पते (mint accounts) यहाँ दिए गए हैं: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v और Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB।


नीचे दिया गया आरेख (diagram) Token program और mint accounts के बीच संबंध दिखाता है।

Mint account का विवरण
सभी Solana अकाउंट्स की तरह, mint account में स्टैण्डर्ड मेटाडेटा फ़ील्ड्स होते हैं, जो इस प्रकार हैं:
- Lamports (किराये के लिए)
- Owner (जो इस मामले में Token Program का पता है)
- Executable स्थिति (एक
falseवैल्यू क्योंकि यह डेटा स्टोरेज के लिए है)
Solana अकाउंट्स के बारे में अधिक जानकारी के लिए Initializing Accounts in Solana and Anchor देखें।
इन स्टैण्डर्ड फ़ील्ड्स के अलावा, mint account में विशिष्ट डेटा फ़ील्ड्स होते हैं जो टोकन को ही परिभाषित करते हैं:
mint_authority: नए टोकन बनाने की अनुमति वाला पता।freeze_authority: इस टोकन को रखने वाले टोकन अकाउंट्स को फ्रीज करने की अनुमति वाला पता।decimals: टोकन द्वारा उपयोग किए जाने वाले दशमलव स्थानों (0-9) की संख्या।supply: बनाए गए टोकन की कुल संख्या।is_initialized: बूलियन फ्लैग जो पुन: आरंभीकरण (reinitialization) को रोकता है।
हालाँकि mint account टोकन जानकारी संग्रहीत करता है, यह व्यक्तिगत उपयोगकर्ता बैलेंस को ट्रैक नहीं करता है, इसे अलग-अलग अकाउंट्स द्वारा नियंत्रित किया जाता है जिन पर हम बाद में चर्चा करेंगे।
नीचे दिया गया आरेख mint account की प्रॉपर्टीज को दर्शाता है।

एक mint account की mint और freeze authorities (जैसा कि ऊपर दिखाया गया है) इसके निर्माण के दौरान असाइन की जाती हैं और आमतौर पर ट्रांजेक्शन हस्ताक्षरकर्ता (signer) के पते पर सेट की जाती हैं। हम “Token program instruction” अनुभाग में इसके लिए निर्देश (instruction) देखेंगे।
mint accounts का एक महत्वपूर्ण पहलू यह है कि वे टोकन की सप्लाई को कैसे नियंत्रित करते हैं। यह mint authority फ़ील्ड के माध्यम से नियंत्रित किया जाता है। हम इसे नीचे समझाते हैं।
अधिकतम टोकन सप्लाई (Maximum Token Supply) कैसे सेट करें
SPL टोकन स्पष्ट सीमाओं के बजाय अनुमति हटाने (permission removal) के माध्यम से अधिकतम सप्लाई लागू करते हैं। यह डिज़ाइन विकल्प इस बात के मूलभूत अंतरों से उपजा है कि Solana और Ethereum स्टेट को कैसे संभालते हैं।
एक mint account डेटा में कोई स्पष्ट “max supply” फ़ील्ड नहीं होता है। इसलिए, एक निश्चित सप्लाई बनाने के लिए, आप mint authority को None (शून्य वैल्यू) पर सेट करके इसे अक्षम (disable) कर देते हैं। यह स्थायी रूप से mint authority को अक्षम कर देता है, क्योंकि यह इसे किसी को भी असाइन नहीं करता है। चूंकि किसी भी अकाउंट के पास अधिक टोकन मिंट करने की ऑथोरिटी नहीं होती है, इसलिए वर्तमान कुल सप्लाई निश्चित अधिकतम बन जाती है।
Ethereum में, टोकन की कुल सप्लाई को सीमित करने का पारंपरिक तरीका स्पष्ट रूप से उस संख्या को कहीं स्टोर करना और इस संख्या से अधिक मिंटिंग को ब्लॉक करना है। SPL टोकन में “कुल सप्लाई सीमा” (total supply limit) की कोई धारणा नहीं है और इस प्रकार ऐसी कोई संख्या कहीं भी स्टोर नहीं की जाती है।
SPL के साथ, यदि हम 1 मिलियन टोकन की कुल सप्लाई चाहते हैं, तो हम धारकों के लिए सभी 1 मिलियन मिंट करते हैं और फिर mint authority को अक्षम कर देते हैं। वैकल्पिक रूप से, जैसा कि हम बाद के ट्यूटोरियल में देखेंगे, हम एक अलग प्रोग्राम को mint authority बना सकते हैं और उस प्रोग्राम से सप्लाई कैप (supply cap) तक पहुंचने के बाद टोकन मिंट करना बंद करवा सकते हैं।
Token Accounts और Associated Token Accounts (ATAs)
जैसा कि पहले उल्लेख किया गया है, mint account केवल टोकन के बारे में जानकारी स्टोर करता है। व्यक्तिगत उपयोगकर्ता बैलेंस को ट्रैक करने के लिए, Solana अलग-अलग अकाउंट्स का उपयोग करता है जिन्हें Token Accounts कहा जाता है।
Token Accounts
Token Accounts ऐसे Solana अकाउंट्स हैं जो एक उपयोगकर्ता का टोकन बैलेंस, वह mint एड्रेस जिससे अकाउंट जुड़ा है, और वह ओनर (owner) जो ट्रांसफर्स को ऑथराइज कर सकता है, साथ ही अन्य फ़ील्ड्स को स्टोर करते हैं जिन्हें हम बाद में विस्तार से कवर करेंगे।
डिज़ाइन के अनुसार, एक उपयोगकर्ता के पास एक ही टोकन के लिए कई Token Accounts हो सकते हैं, जो अलग-अलग पतों पर बनाए गए हों। यह एक चुनौती पैदा करता है जैसा कि Solana Program Library दस्तावेज़ में बताया गया है:
“एक उपयोगकर्ता के पास एक ही मिंट से संबंधित मनमाने ढंग से कई टोकन अकाउंट हो सकते हैं, जिससे अन्य उपयोगकर्ताओं के लिए यह जानना मुश्किल हो जाता है कि उन्हें किस अकाउंट में टोकन भेजने चाहिए।”
इसका मतलब यह है कि एक टोकन के लिए उपयोगकर्ता का बैलेंस एक ही स्थान पर रहने के बजाय कई अकाउंट्स में विभाजित हो सकता है।
उदाहरण के लिए:
- Alice के एक टोकन अकाउंट में 5 टोकन हैं और दूसरे टोकन अकाउंट में 15 टोकन हैं। दोनों टोकन अकाउंट्स एक ही मिंट के हैं, इसलिए मिलाकर उसके पास उस मिंट के 20 टोकन हैं।
- हालाँकि, यदि Bob, Alice को अधिक टोकन भेजना चाहता है, तो उसके पास यह जानने का कोई आसान तरीका नहीं है कि वह उन्हें किस अकाउंट में प्राप्त करना पसंद करती है।
SPL दस्तावेज़ का “मनमाने ढंग से कई टोकन अकाउंट” (“arbitrarily many token accounts”) की चुनौती से यही अर्थ है। बैलेंस रिडंडेंट कॉपियां (redundant copies) नहीं हैं, बल्कि कई अकाउंट्स में फैले कुल बैलेंस के टुकड़े हैं।
इस समस्या के समाधान के लिए, Solana ने Associated Token Accounts (ATAs) पेश किए।
Associated Token Accounts (ATAs)
नियमित Token Accounts के विपरीत, जहाँ उपयोगकर्ताओं के पास प्रति मिंट कई अकाउंट हो सकते हैं, ATAs विशेष Token Accounts होते हैं (एड्रेस खोजने के लिए एक नियतात्मक नियम (deterministic rule) के साथ) जो उपयोगकर्ता के वॉलेट पते और एक मिंट के बीच वन-टू-वन (one-to-one) संबंध लागू करते हैं। यह सुनिश्चित करता है कि:
- प्रत्येक उपयोगकर्ता के पास प्रत्येक टोकन प्रकार के लिए बिल्कुल एक प्रिडिक्टेबल (predictable) ATA होता है
- कोई भी एप्लिकेशन बिना किसी पूर्व ज्ञान के आसानी से उपयोगकर्ता का टोकन बैलेंस ढूंढ सकता है क्योंकि पता नियतात्मक (deterministic) होता है। हम नीचे समझाते हैं कि कैसे।
यह आर्टिकल मुख्य रूप से ATAs पर केंद्रित है क्योंकि ऊपर चर्चा की गई नियमित Token Addresses की चुनौतियों के कारण Solana में टोकन के प्रबंधन के लिए वे स्टैण्डर्ड दृष्टिकोण (standard approach) बन गए हैं।
ATA एड्रेस कैसे डिराइव (derive) किए जाते हैं?
एक ATA एड्रेस एक Program Derived Address (PDA) है, जो नियतात्मक रूप से दो इनपुट से डिराइव किया जाता है:
- उपयोगकर्ता/हस्ताक्षरकर्ता (signer) के वॉलेट का पता (इच्छित ऑथोरिटी)।
- टोकन के mint account का पता।
हम Associated Token Account की तुलना Ethereum के ERC20 mapping(address => uint256) public balanceOf से कर सकते हैं, क्योंकि दोनों उपयोगकर्ता के पास कितने टोकन हैं, इसे ट्रैक करने के तरीके के रूप में काम करते हैं।
चूँकि एक उपयोगकर्ता के पास कई SPL टोकन हो सकते हैं, इसलिए विभिन्न टोकन के बैलेंस के बीच अंतर करने के लिए केवल उपयोगकर्ता के पते का उपयोग करना अपर्याप्त होगा। इसलिए डेरिवेशन में mint address को भी शामिल किया गया है। उपयोगकर्ता के वॉलेट पते और टोकन के मिंट पते दोनों को मिलाकर, Solana यह सुनिश्चित करता है कि प्रत्येक (user, token) जोड़ी को एक यूनिक ATA पता मिले।
यह डिज़ाइन टकरावों (collisions) से बचाता है और एक सुसंगत संरचना लागू करता है:
user_wallet_address + token_mint_address => associated_token_account_address
इसे और अधिक स्पष्ट करने के लिए, नीचे दी गई तालिका तुलना करती है कि Ethereum और Solana टोकन बैलेंस का प्रबंधन कैसे करते हैं।
| Aspect | Ethereum (ERC-20) | Solana (ATAs) |
|---|---|---|
| Storage Model | एक केंद्रीय कॉन्ट्रैक्ट मैपिंग में बैलेंस स्टोर करता है | प्रत्येक उपयोगकर्ता के पास प्रत्येक टोकन के लिए एक अलग अकाउंट (ATA) होता है |
| Balance Location | टोकन कॉन्ट्रैक्ट के अंदर स्टोर किया जाता है | उपयोगकर्ता के ATA के अंदर स्टोर किया जाता है |
| Who Pays for Storage | कॉन्ट्रैक्ट का मालिक (डिप्लॉयमेंट लागत) | उपयोगकर्ता अपने अकाउंट के लिए भुगतान करता है |
| Lookup | balanceOf(user) कॉल करें |
ATA पता डिराइव करें → बैलेंस पढ़ें |
| Parallel Access | कॉन्ट्रैक्ट द्वारा सीमित | पूरी तरह से समानांतर |
दोनों एक ही लक्ष्य प्राप्त करते हैं—टोकन ओनरशिप को ट्रैक करना—लेकिन Solana का दृष्टिकोण पैरेलल प्रोसेसिंग (parallel processing) को सक्षम बनाता है क्योंकि प्रत्येक बैलेंस एक अलग अकाउंट में होता है।
नीचे दिया गया आरेख एक Associated Token Account के फ़ील्ड्स दिखाता है।

ATA किसी विशिष्ट टोकन/मिंट के उपयोगकर्ता के बैलेंस का विवरण रखता है। इसके प्रमुख फ़ील्ड्स हैं:
mint: उस टोकन (Mint Account) का पता जिसे यह अकाउंट होल्ड करता है। उदाहरण के लिए, यदि यह USDC बैलेंस का प्रतिनिधित्व कर रहा है, तो यह USDC मिंट अकाउंट का पता होगा।owner: हालाँकि इसे ‘owner’ के रूप में लेबल किया गया है, यह ATA की ऑथोरिटी है। प्रत्येक ATA का वास्तविक ओनर (owner) हमेशा Token Program होता है, क्योंकि यह सभी नियमों को लागू करता है। यहाँownerफ़ील्ड Token Program को बताता है कि अपडेट या ट्रांसफर को पूरा करने के लिए किस ऑथोरिटी को हस्ताक्षर करना होगा। Owner vs Authority आर्टिकल से याद रखें, अकाउंट का ओनर इसके नियम को लागू करता है, जबकि ऑथोरिटी एकमात्र वैध हस्ताक्षरकर्ता है जो अकाउंट को मॉडिफाई करने के लिए निर्देश (instructions) भेज सकता है, जब तक कि इस ऑथोरिटी द्वारा Token Program के माध्यम से हस्ताक्षर करने के अधिकार डेलिगेट (delegate) न किए गए हों।amount: इस बैलेंस में रखे गए टोकन की मात्रा।delegate: एक डेलिगेट अकाउंट का पता, जिसे टोकन ट्रांसफर करने के लिए अप्रूव किया गया है। टोकन अकाउंट के लिए एक समय में केवल एक ही डेलिगेट मौजूद हो सकता है क्योंकि यहाँ केवल एक हीdelegateफ़ील्ड है। यह ERC-20 से अलग है, जहाँ एक ओनर कई खर्च करने वालों (spenders) को अप्रूव कर सकता है।state: टोकन अकाउंट की स्थिति, उदा., यह एक enum है और यहUninitialized,InitializedयाFrozenहो सकता है।close_authority: अकाउंट को बंद करने की अनुमति वाला पता, डिफ़ॉल्ट रूप सेownerके समान पब्लिक की (public key) लेकिनownerएक औरclose_authorityनामित कर सकता है। जब किसी टोकन अकाउंट का बैलेंस शून्य हो जाता है, तो ओनर किराए के लिए उपयोग किए गए SOL को पुनः प्राप्त करने के लिए इसे बंद कर सकता है। Solflare wallet और Sol-Incinerator जैसे कई वेब टूल खाली टोकन अकाउंट्स को बंद करने के सुविधाजनक तरीके प्रदान करते हैं।
नीचे दिया गया आरेख Token Program, mint account और token account के बीच संबंध दिखाता है।

(इस बिंदु से आगे, जब हम “token account” कहते हैं, तो इसमें ATAs भी शामिल होते हैं, क्योंकि ATAs केवल एक विशेष प्रकार के टोकन अकाउंट होते हैं।)
Associated Token Account Program
Associated Token Account प्रोग्राम का फिक्स्ड एड्रेस ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL है। यह एक ऑन-चेन प्रोग्राम है जो किसी दिए गए उपयोगकर्ता-टोकन जोड़ी के लिए सही ATA ढूंढता है या बनाता है। यह नियतात्मक एड्रेस डेरिवेशन (deterministic address derivation) को संभालता है और, आवश्यकता पड़ने पर, Token Program के माध्यम से नए ATAs बनाने के लिए Cross Program Invocation (CPI) का उपयोग करता है।
विशेष रूप से, ATA Program द्वारा संचालित निर्माण प्रवाह (creation flow) है:

Ethereum के विपरीत जहाँ बैलेंस कॉन्ट्रैक्ट के स्टोरेज में अंतर्निहित रूप से मौजूद होते हैं, Solana में स्पष्ट अकाउंट निर्माण की आवश्यकता होती है। यह एक मूलभूत UX चुनौती पैदा करता है: टोकन उन उपयोगकर्ताओं को नहीं भेजे जा सकते हैं जिन्होंने स्पष्ट रूप से रिसीविंग Associated Token Accounts नहीं बनाए हैं क्योंकि टोकन बैलेंस सचमुच Associated Token Account में स्टोर किया जाता है।
इसलिए, कोई भी टोकन भेजने से पहले, हमें उपयोगकर्ता-टोकन जोड़ी के लिए ATA बनाना होगा। ATA पता वॉलेट पते और मिंट पते का उपयोग करके नियतात्मक रूप से ऑफ-चेन (off-chain) डिराइव किया जाता है। एक बार डिराइव होने के बाद, हम ATA को ऑन-चेन बनाने के लिए Associated Token Account Program का उपयोग करते हैं यदि यह पहले से मौजूद नहीं है। यह एक महत्वपूर्ण सुरक्षा प्रश्न उठाता है: यदि कोई किसी और के लिए ATA बना सकता है, तो क्या वे स्वयं को ATA ओनर और क्लोज ऑथोरिटी (close authority) के रूप में भी असाइन कर सकते हैं? सौभाग्य से, नहीं। किसी अन्य वॉलेट के लिए ATA बनाते समय, ATA Program यह लागू करता है कि owner और close_authority फ़ील्ड्स हमेशा उस वॉलेट पते पर सेट हों जिसके लिए ATA बनाया जा रहा है, न कि ट्रांजेक्शन हस्ताक्षरकर्ता पर। यह सुरक्षा गारंटी ATA Program’s code में अंतर्निहित है, यह सुनिश्चित करते हुए कि केवल सही वॉलेट ओनर ही अपने टोकन पर नियंत्रण और अपना अकाउंट बंद करने की क्षमता बनाए रखता है।
उदाहरण के लिए: जब Alice, Bob को टोकन भेजना चाहती है, तो वह Bob का ATA पता डिराइव करती है, यदि यह मौजूद नहीं है तो इसे ऑन-चेन बनाती है, फिर गंतव्य के रूप में Bob के ATA के साथ Token Program के Transfer निर्देश को कॉल करती है। (व्यवहार में, @solana/spl-token जैसी क्लाइंट लाइब्रेरी सहायक फ़ंक्शंस प्रदान करती हैं जो ATA डेरिवेशन और निर्माण चरणों को जोड़ती हैं)। उदाहरण के लिए: जब Alice, Bob को टोकन भेजना चाहती है, तो वह Bob का ATA पता डिराइव करती है, यदि यह मौजूद नहीं है तो इसे ऑन-चेन बनाती है, फिर गंतव्य के रूप में Bob के ATA के साथ Token Program के Transfer निर्देश को कॉल करती है। (व्यवहार में, @solana/spl-token जैसी क्लाइंट लाइब्रेरी सहायक फ़ंक्शंस प्रदान करती हैं जो ATA डेरिवेशन और निर्माण चरणों को जोड़ती हैं)।
यह आरेख ATA प्रोग्राम की सामग्री दिखाता है।

हमने SPL टोकन बनाने और प्रबंधित करने में शामिल अकाउंट्स पर चर्चा की है। इसके बाद, हम Token Program और ATA program के निर्देशों (instructions) को कवर करेंगे। ये निर्देश आपको नए टोकन बनाने और मिंट करने, ATAs के बीच टोकन भेजने, दूसरों को अपने टोकन खर्च करने के लिए अप्रूवल सेट करने, सप्लाई कम करने के लिए टोकन बर्न (burn) करने और किराया वापस पाने के लिए खाली अकाउंट्स को बंद करने जैसे काम करने देते हैं।
Token Program के निर्देश (Instructions)
आइए Token Program द्वारा प्रदान किए गए सार्वजनिक फ़ंक्शंस (public functions) का पता लगाएं जो आपको SPL टोकन के साथ इंटरैक्ट करने की अनुमति देते हैं।
ध्यान दें कि नीचे दिए गए निर्देश पैरामीटर्स में, जब हम टोकन अकाउंट्स का उल्लेख करते हैं, तो ये या तो नियमित टोकन अकाउंट या Associated Token Accounts (ATAs) हो सकते हैं, जैसा कि पहले Token Accounts और Associated Token Accounts अनुभाग में चर्चा की गई थी। जब कोई अंतर महत्वपूर्ण होगा, तो हम स्पष्ट रूप से निर्दिष्ट करेंगे कि हम नियमित टोकन अकाउंट्स की बात कर रहे हैं या ATAs की।
Token Program में निम्नलिखित सार्वजनिक फ़ंक्शंस हैं:
InitializeMint: यह निर्देश एक नया mint account बनाता है, जो ऑन-चेन एक नए SPL टोकन का प्रतिनिधित्व करता है।
pub fn initialize_mint(
mint_pubkey: &Pubkey, // इनिशियलाइज़ करने के लिए mint account
decimals: u8, // टोकन के लिए दशमलव स्थानों की संख्या
mint_authority: &Pubkey, // नए टोकन बनाने की अनुमति वाला अकाउंट
freeze_authority: Option<&Pubkey> // वैकल्पिक: वह अकाउंट जो टोकन अकाउंट्स को फ्रीज कर सकता है
) -> Instruction
mint_pubkey या तो एक अप्रयुक्त (unused) keypair account या एक PDA का पता हो सकता है जिसे एक मिंट अकाउंट के रूप में इनिशियलाइज़ किया जाना है। हम अगले ट्यूटोरियल में इस प्रक्रिया को व्यवहार में देखेंगे।
InitializeAccount: यह निर्देश एक विशिष्ट SPL टोकन मिंट के लिए उपयोगकर्ता का बैलेंस रखने के लिए एक नए नियमित टोकन अकाउंट (non-ATA) को इनिशियलाइज़ करता है।
pub fn initialize_account(
account_pubkey: &Pubkey, // इनिशियलाइज़ करने के लिए टोकन अकाउंट
mint_pubkey: &Pubkey, // नए टोकन अकाउंट के लिए मिंट
owner_pubkey: &Pubkey // नए टोकन अकाउंट का ओनर (owner)
) -> Instruction
ATAs को ATA Program द्वारा इनिशियलाइज़ किया जाता है, जो पर्दे के पीछे इस InitializeAccount निर्देश के लिए एक CPI निष्पादित करता है। हम देखेंगे कि यह कैसे होता है।
Transfer: इसका उपयोग SPL टोकन की इकाइयों को एक उपयोगकर्ता के टोकन अकाउंट (स्रोत) से दूसरे (गंतव्य) में ट्रांसफर करने के लिए किया जाता है। एक “बैलेंस” बस associated token account में स्टोर की गई एक संख्या है जिसे केवल SPL प्रोग्राम ही मॉडिफाई कर सकता है। ध्यान दें कि mint account और token account मौजूद होने चाहिए या अन्यथा MintTo निर्देश कॉल होने से ठीक पहले बनाए जाने चाहिए (नीचे दिए गए MintTo निर्देश के लिए भी लागू होता है)। हम अगले ट्यूटोरियल में Anchor का उपयोग करके इसे प्रदर्शित करेंगे।
pub fn transfer(
source_pubkey: &Pubkey, // टोकन भेजने वाला अकाउंट (आमतौर पर प्रेषक का ATA; मिंट अकाउंट नहीं)
destination_pubkey: &Pubkey, // गंतव्य टोकन अकाउंट (जिसमें टोकन प्राप्त होते हैं)
authority_pubkey: &Pubkey, // भेजने वाले टोकन अकाउंट से खर्च करने के लिए अधिकृत ओनर या डेलिगेट
amount: u64 // ट्रांसफर किए जाने वाले टोकन की संख्या
) -> Instruction
MintTo: यह निर्देश नई टोकन इकाइयाँ (token units) बनाता है और उन्हें एक निर्दिष्ट टोकन अकाउंट में जोड़ता है।
pub fn mint_to(
mint_pubkey: &Pubkey, // टोकन मिंट का पता
account_pubkey: &Pubkey, // जिस टोकन अकाउंट में मिंट करना है
authority_pubkey: &Pubkey, // मिंट की मिंटिंग ऑथोरिटी
amount: u64 // मिंट की जाने वाली मात्रा
) -> Instruction
Burn: यह निर्देश एक टोकन अकाउंट से निर्दिष्ट मात्रा में SPL टोकन इकाइयों को नष्ट (destroy) कर देता है, जिससे कुल टोकन सप्लाई कम हो जाती है। यह ERC20 के बर्न फंक्शन के समान काम करता है।
pub fn burn(
account_pubkey: &Pubkey, // जिस टोकन अकाउंट से बर्न करना है
mint_pubkey: &Pubkey, // टोकन मिंट
authority_pubkey: &Pubkey, // टोकन अकाउंट का ओनर/डेलिगेट
amount: u64 // बर्न की जाने वाली मात्रा
) -> Instruction
Approve: यह निर्देश अधिकतम मात्रा के लिए टोकन अकाउंट ओनर से एक निर्दिष्ट डेलिगेट (delegate) को खर्च करने की शक्ति प्रदान करता है। यह टोकन अकाउंट के delegate और उस अकाउंट पर स्वीकृत मात्रा को सेट करता है; एक समय में केवल एक ही डेलिगेट मौजूद हो सकता है। उस सीमा के भीतर, डेलिगेट ओनर की ओर से टोकन ट्रांसफर कर सकता है।
ERC-20 के विपरीत, जो एक कॉन्ट्रैक्ट मैपिंग में भत्ते (allowances) स्टोर करता है, SPL अप्रूवल को सीधे ओनर के टोकन अकाउंट (आमतौर पर ATA) पर रिकॉर्ड करता है। यह डिज़ाइन एक अप्रूवल और एक ट्रांसफर को एक ही ट्रांजेक्शन में पूरा करने की अनुमति देता है, क्योंकि केवल टोकन अकाउंट की स्टेट को मॉडिफाई किया जाता है।
pub fn approve(
source_pubkey: &Pubkey, // अप्रूवल देने वाला टोकन अकाउंट
delegate_pubkey: &Pubkey, // डेलिगेट अकाउंट
owner_pubkey: &Pubkey, // अप्रूवल देने वाले टोकन अकाउंट का ओनर
amount: u64 // डेलिगेट द्वारा ट्रांसफर किए जा सकने वाले टोकन की अधिकतम संख्या
) -> Instruction
Revoke: यह निर्देश किसी भी पहले से दिए गए डेलिगेट अप्रूवल (जो Approve निर्देश के साथ बनाया गया हो) को रद्द कर देता है। यह टोकन अकाउंट के delegate फ़ील्ड को None (कोई डेलिगेट नहीं) पर सेट करके डेलिगेट को पूरी तरह से हटा देता है।
चूँकि अप्रूवल्स को आंशिक रूप से कम नहीं किया जा सकता है, इसलिए यदि आप भत्ता (allowance) कम करना चाहते हैं तो एक कम मात्रा के साथ नया अप्रूवल सेट किया जाना चाहिए, ठीक उसी तरह जैसे ERC20 भत्ते कम करता है।
pub fn revoke(
source_pubkey: &Pubkey, // अप्रूवल रद्द करने वाला टोकन अकाउंट (वही अकाउंट जिसने पहले अप्रूवल दिया था)
owner_pubkey: &Pubkey // अप्रूवल रद्द करने वाले टोकन अकाउंट का ओनर
) -> Instruction
FreezeAccount: इस निर्देश का उपयोग किसी टोकन अकाउंट को फ्रीज करने के लिए किया जाता है, जो अस्थायी रूप से अकाउंट में रखे टोकन से जुड़े किसी भी ट्रांसफर या ट्रांजेक्शन को तब तक रोकता है जब तक कि यह अनफ्रीज न हो जाए। दूसरे शब्दों में, SPL किसी उपयोगकर्ता के टोकन अकाउंट पते को ब्लैकलिस्ट करने का समर्थन करता है।
pub fn freeze_account(
account_pubkey: &Pubkey, // फ्रीज किया जाने वाला टोकन अकाउंट
mint_pubkey: &Pubkey, // टोकन मिंट
authority_pubkey: &Pubkey // मिंट की फ्रीज ऑथोरिटी
) -> Instruction
ThawAccount: यह निर्देश उस टोकन अकाउंट को अनफ्रीज करता है जो पहले फ्रीज किया गया था, जिससे टोकन ट्रांसफर और ट्रांजेक्शन फिर से शुरू हो सकते हैं।
pub fn thaw_account(
account_pubkey: &Pubkey, // अनफ्रीज किया जाने वाला टोकन अकाउंट
mint_pubkey: &Pubkey, // टोकन मिंट
authority_pubkey: &Pubkey // मिंट की फ्रीज ऑथोरिटी
) -> Instruction
SetAuthority: यह निर्देश बदलता है कि मिंट और टोकन अकाउंट्स पर विशिष्ट ऑथोरिटी रोल्स किसके पास हैं।
याद करें कि एक मिंट अकाउंट में दो फ़ील्ड होते हैं जिनमें “authority” होती है:
mint_authorityfreeze_authority
(Associated) टोकन अकाउंट में दो फ़ील्ड होते हैं जिनमें “authority” होती है:
ownerटोकन का ओनर, PDA का “Solana रनटाइम ओनर” नहीं (यह नामकरण भ्रमित करने वाला है)।delegateएक पब्लिक की जो ओनर की ओर से टोकन खर्च कर सकती है
नीचे दिए गए set_authority में account_pubkey एक मिंट अकाउंट या एक टोकन अकाउंट को संदर्भित कर सकता है।
निर्दिष्ट authority_type उस ऑथोरिटी के प्रकार से मेल खाना चाहिए जो उस अकाउंट के पास है।
SPL के लिए Solana सोर्स कोड चार प्रकार की ऑथोरिटी में से प्रत्येक के लिए एक enum नाम देता है:
MintTokensFreezeAccountAccountOwnerCloseAccount
इस बात से अवगत रहें कि SPL प्रोग्राम टोकन अकाउंट में ऑथोरिटी रोल्स को सुसंगत (consistent) तरीके से संदर्भित नहीं करता है और भ्रमित करने वाले रूप में टोकन ओनर को “owner” के रूप में संदर्भित करता है — इसे PDA के ओनर के साथ भ्रमित नहीं किया जाना चाहिए।
pub fn set_authority(
account_pubkey: &Pubkey, // मिंट या टोकन अकाउंट
current_authority_pubkey: &Pubkey, // वर्तमान ऑथोरिटी
authority_type: AuthorityType, // बदलने के लिए ऑथोरिटी का प्रकार (उदा., MintTokens, FreezeAccount)
new_authority_pubkey: Option<&Pubkey> // नई ऑथोरिटी, या अक्षम करने के लिए None
) -> Instruction
Revoke का प्रभाव SetAuthority के समान ही है क्योंकि दोनों यह बदलते हैं कि ऑथोरिटी किसके पास है। Revoke टोकन अकाउंट के डेलिगेशन को साफ करता है (delegate को None पर सेट करता है), जबकि SetAuthority मिंट/अकाउंट ऑथोरिटीज (MintTokens, FreezeAccount, AccountOwner, CloseAccount) को बदलता है।
CloseAccount: यह निर्देश स्थायी रूप से एक associated token account को बंद कर देता है और इसके SOL लैम्पोर्ट बैलेंस (lamport balance) को पुनः प्राप्त करता है जिसका उपयोग अकाउंट को रेंट-एग्जेम्प्ट (rent-exempt) बनाने के लिए किया गया था। हालाँकि, ATA के पास अंतर्निहित मिंट टोकन का बिल्कुल शून्य बैलेंस होना चाहिए, अन्यथा एक त्रुटि (error) वापस कर दी जाती है।
pub fn close_account(
account_pubkey: &Pubkey, // बंद किया जाने वाला अकाउंट
destination_pubkey: &Pubkey, // पुनः प्राप्त SOL प्राप्त करने वाला अकाउंट
owner_pubkey: &Pubkey // बंद होने वाले अकाउंट का ओनर
) -> Instruction
अब आइए ATA प्रोग्राम के प्रमुख निर्देशों पर चर्चा करें।
Associated Token Account (ATA) Program के निर्देश
ATA प्रोग्राम Token Program के साथ काम करता है और इसमें ये मुख्य निर्देश हैं:
Create: यह निर्देश एक वॉलेट पते और टोकन मिंट पते के संयोजन से डिराइव एक नियतात्मक (deterministic) PDA पते पर एक ATA बनाता है। यदि डिराइव किए गए पते पर कोई अकाउंट पहले से मौजूद है तो निर्देश विफल हो जाता है।
pub fn create_associated_token_account(
payer: &Pubkey, // निर्माण को फंड करने वाला अकाउंट
wallet_address: &Pubkey, // ATA के लिए वॉलेट पता
token_mint: &Pubkey // टोकन मिंट
) -> Instruction
CreateIdempotent: सुनिश्चित करता है कि सही ATA डिराइव किए गए PDA पते पर मौजूद है। जरूरत पड़ने पर अकाउंट बनाता है। लेकिन Create निर्देश के विपरीत, यह बिना किसी त्रुटि के सफल होता है, भले ही सही अकाउंट पहले से मौजूद हो।
pub fn create_associated_token_account_idempotent(
payer: &Pubkey, // निर्माण को फंड करने वाला अकाउंट
wallet_address: &Pubkey, // ATA के लिए वॉलेट पता
token_mint: &Pubkey // टोकन मिंट
) -> Instruction
Create और CreateIdempotent दोनों ATA पता डिराइव करते हैं और फिर associated token account सेट करने के लिए Token Program के InitializeAccount निर्देश (जो हमने पहले देखा था) पर एक CPI करते हैं।
सारांश (Summary)
संक्षेप में कहें तो, Solana का SPL टोकन आर्किटेक्चर टोकन डेटा से प्रोग्राम लॉजिक को मौलिक रूप से अलग करने पर बना है। Ethereum की तरह हर टोकन के लिए एक नया कॉन्ट्रैक्ट डिप्लॉय करने के बजाय, Solana पर सभी टोकन उसी मुख्य Token Program द्वारा प्रबंधित किए जाते हैं।
याद रखने योग्य सबसे महत्वपूर्ण बिंदु यहाँ दिए गए हैं:
- Logic vs. State: सिंगल Token Program में सभी नियम (ट्रांसफर, मिंट, बर्न) होते हैं, लेकिन यह स्वयं कोई टोकन डेटा (बैलेंस, डेसीमल्स, सप्लाई) नहीं रखता है। यह सभी SPL टोकन के लिए एक सार्वभौमिक (universal) लॉजिक इंजन के रूप में कार्य करता है।
- The Mint Account is the Token: एक Mint Account एक यूनिक टोकन को परिभाषित करता है। यह टोकन की ग्लोबल जानकारी को स्टोर करता है, जैसे इसकी कुल सप्लाई, डेसीमल्स, और किसके पास और अधिक बनाने की ऑथोरिटी है। मिंट अकाउंट का पता ही टोकन का पता (उदा., USDC का मिंट पता) होता है।
- Balances Live in Token Accounts/ATAs: उपयोगकर्ता बैलेंस को अलग-अलग Token Accounts या Associated Token Accounts (ATAs) में रखा जाता है। पतों को बैलेंस से मैप करने वाले एक बड़े कॉन्ट्रैक्ट के बजाय, प्रत्येक उपयोगकर्ता को अपने स्वामित्व वाले प्रत्येक प्रकार के टोकन के लिए एक अलग अकाउंट मिलता है। एक ATA का पता उपयोगकर्ता के वॉलेट और टोकन के मिंट पते से प्रिडिक्टेबल (predictable) तरीके से डिराइव किया जाता है, और यह अनुशंसित समाधान है।
SPL आर्किटेक्चर के कुछ फायदे
- Parallel Processing: चूँकि प्रत्येक उपयोगकर्ता का बैलेंस एक अलग अकाउंट में होता है, नेटवर्क एक ही समय में एक-दूसरे के रास्ते में आए बिना हजारों ट्रांसफर प्रोसेस कर सकता है।
- Standardization: प्रत्येक SPL टोकन, चाहे वह एक स्टेबलकॉइन (stablecoin) हो या मीम कॉइन (meme coin), मुख्य Token Program से बिल्कुल समान सुरक्षित लॉजिक का पालन करता है। यह उन बग्स के जोखिम को कम करता है जो कस्टम टोकन कॉन्ट्रैक्ट्स के साथ हो सकते हैं।
यह आर्टिकल Solana पर ट्यूटोरियल सीरीज़ का हिस्सा है।