ทดลองสร้าง Token บน Solana ด้วย SPL Token CLI
สวัสดีครับ วันนี้มาแนะนำบทความสร้าง Token (SPL Token) บน Solana ผ่านการใช้งาน SPL Token CLI กันครับ
ทั้งหมดเป็น Devnet นะครับ และไม่ควรใช้ Wallet จริง ควรเป็น Wallet (Keypair) ที่ถูก generate มาใหม่ หรือใช้ develop เท่านั้น
สิ่งที่ต้องมี
- Solana CLI
- Rust & Cargo
- Solana Program Library CLI (spl-token)
ติดตั้ง Solana CLI
sh -c "$(curl -sSfL https://release.solana.com/stable/install)"
สามารถดูวิธีการติดตั้ง Solana หรือ เขียน Solana Program จากบล็อกก่อนหน้านี้ของผมได้ครับ
ติดตั้ง Rust ผ่าน Rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
ติดตั้ง spl-token
$ cargo install spl-token-cli
เช็ค version ของแต่ละตัว ว่าติดตั้งเรียบร้อยแล้ว
rustup --version
cargo --version
solana version
spl-token --version
Create Wallet
เริ่มต้นสร้าง wallet ของเราขึ้นมาก่อน
solana-keygen new
จะมีข้อความขึ้น เพื่อให้เราใส่ BIP39 Passphrase เพื่อเพิ่ม security อีกชั้น ซึ่งเรากด enter เฉยๆ เพื่อไม่ต้องใส่ก็ได้ เพราะเป็นแค่ dev (แต่ถ้าเป็นกระเป๋าที่ใช้งานจริงๆ แนะนำให้ใส่นะครับ ซึ่ง BIP39 มีคำอะไรบ้างดูทีนี่)
Generating a new keypair
For added security, enter a BIP39 passphrase
NOTE! This passphrase improves security of the recovery seed phrase NOT the
keypair file itself, which is stored as insecure plain text
BIP39 Passphrase (empty for none):
ตัว Solana จะทำการ generate Wallet ให้เรา โดยเราจะได้ pubkey ที่เป็น wallet address และ seed phrase 12 คำ
แต่ถ้าหากเราอยากกำหนดไฟล์ output เราสามารถระบุ option ให้มันได้ครับ แบบนี้
solana-keygen new -o ~/Desktop/test-account.json
ตัวอย่าง สมมติเราเสร็จได้ pubkey มา ถ้าเราลืมว่า pubkey เราคืออะไร สามารถเช็คได้ด้วยคำสั่ง
solana address -k <path/to/keypair.json>
เช่น
solana address -k ~/.config/solana/id.json
สุดท้าย เราสามารถ grind หรือสร้าง pubkey ให้เป็นแบบที่เราต้องการได้ เช่น ให้ pubkey ขึ้นต้นด้วยคำที่เราต้อง หรือลงท้ายด้วยคำที่เราต้องการ
solana-keygen grind --starts-with hi:1
มันก็จะ generate pubkey ที่ขึ้นต้นด้วย hi ให้เรา ยิ่งคำที่ต้องการค้นหาเยอะเท่าไหร่ ก็ใช้เวลาหานานขึ้น และโอกาสที่จะเจอก็น้อยครับ
# ถ้าอยากให้ output 12 คำ ด้วย ก็ใช้ --use-mnemonic
solana-keygen grind --use-mnemonic --starts-with hi:1
# output file ได้เหมือนปกติ
solana-keygen grind --starts-with hi:1 -o my-wallet.json
Config devnet
ในบทความนี้เราจะใช้ devnet ในการทดสอบ ข้อดีคือเราจะเห็น result ทั้งผ่าน Command Line และ Explorer
โดยในตัวอย่าง ผมจะสร้าง account ขึ้นมาใหม่ และจะใช้ address นี้อ้างอิง จะได้เห็นภาพไปด้วยกันนะครับ
solana-keygen grind --starts-with Hi:1
Wrote keypair to HiHhPVf9hLNuLADjXyZQNtG5rgWuqG1AxQt7iqWNpjps.json
pubkey ผมคือ HiHhPVf9hLNuLADjXyZQNtG5rgWuqG1AxQt7iqWNpjps
ต่อมา config network เป็น devnet
solana config set --url https://api.devnet.solana.com
และ set keypair path เป็นที่อยู่ของกระเป๋า dev ที่ผมเพิ่งสร้าง (ผมสร้างไว้ Desktop)
solana config set --keypair ~/Desktop/HiHhPVf9hLNuLADjXyZQNtG5rgWuqG1AxQt7iqWNpjps.json
เมื่อเรา set url และ keypair เสร็จ จะได้ผลลัพธ์ของ solana config
ประมาณด้านล่างนี้ (ต่างกันที่ตำแหน่งที่เก็บไฟล์น และชื่อไฟล์ นะครับ)
Config File: /Users/chai/.config/solana/cli/config.yml
RPC URL: https://api.devnet.solana.com
WebSocket URL: wss://api.devnet.solana.com/ (computed)
Keypair Path: /Users/chai/Desktop/HiHhPVf9hLNuLADjXyZQNtG5rgWuqG1AxQt7iqWNpjps.json
Commitment: confirmed
ต่อมาทำการ airdrop ให้ account ที่เราเพิ่งสร้าง
solana airdrop 2 <wallet_address>
ก็จะได้เป็น
solana airdrop 2 HiHhPVf9hLNuLADjXyZQNtG5rgWuqG1AxQt7iqWNpjps
เป็นการส่งเงิน 2 SOL ไปให้ Account ที่เราระบุไว้
- เมื่อลองไปเช็คใน Explorer ก็จะเห็น Transaction History หรือใช้ Solscan
จะเห็น airdrop transaction (ผมส่งไป 2 ครั้ง) และ Balance (SOL) คือ 4 SOL
Create Token
เมื่อมีเงินใน Balance ต่อมาคือสร้าง Token ด้วยคำสั่ง
spl-token create-token
จะได้ผลลัพธ์เป็นแบบนี้
Creating token 8CPVtuC9fh3RGztd4ugZsTgDPb57449BpfU1Qucks4iB
Signature: 4ytyJ8GRhWPBLiqtiteai4qCZ7ZSBtwVpyNCLo8vYgk6zsVApkoiza6eHUoF6dMoGsaQWezGVQFiSc7xbWLMyhB2
โดยที่ 8CPVtuC9fh3RGztd4ugZsTgDPb57449BpfU1Qucks4iB คือ Token Address ของเราครับ
ลองเข้าไปค้นหาใน Solana Explorer จะเห็นว่า Supply เราเป็น 0 หรือใช้ Cli ด้วยคำสั่ง
spl-token supply 8CPVtuC9fh3RGztd4ugZsTgDPb57449BpfU1Qucks4iB
จะเห็น supply เป็น 0 และลองเช็ค balance ดู
spl-token balance 8CPVtuC9fh3RGztd4ugZsTgDPb57449BpfU1Qucks4iB
ไม่สามารถทำได้ เพราะไม่มี token account ที่เก็บข้อมูล balance นั่นเอง (ตัวที่ spl-token สร้างเป็นแค่ token ธรรมดา มี metadata)
สิ่งที่เราต้องทำคือทำการ mint เพื่อให้มี supply แต่ว่าเราจะ mint ได้ เราต้องสร้าง account ขึ้นมาเพื่อเก็บ balance ของ token เรา ใช้คำสั่ง
spl-token create-account 8CPVtuC9fh3RGztd4ugZsTgDPb57449BpfU1Qucks4iB
จะได้ผลลัพธ์เป็น:
Creating account Fj8Ptsjjp6x1AK75BKV9mfediGMvk3BFWGGqnTQ4XSPF
Signature: 3XG8WgS44pUrkQSN8ZrnL3R1LPpRbBamdGHe8586LYDvWgKzSCpVRawxG9pka3btE6ycQHrvVaZ3gNqh2TrkbyoR
ตัว Fj8Ptsjjp6x1AK75BKV9mfediGMvk3BFWGGqnTQ4XSPF คือ Account ที่เอาไว้เก็บ state balance ของ token ครับ (ตรงนี้อาจจะสับสน แนะนำดูเรื่อง Solana Accounts เพิ่มเติมนะครับ)
ทีนี้เราสามารถเช็ค balance ของ Token เราได้แล้ว
spl-token balance 8CPVtuC9fh3RGztd4ugZsTgDPb57449BpfU1Qucks4iB
ณ ตอนนี้ เรามี 3 Addresses ละนะครับ เผื่อหลายคนสับสน
- Wallet Address (กระเป๋าเรา): HiHhPVf9hLNuLADjXyZQNtG5rgWuqG1AxQt7iqWNpjps
- Token Address (Token ของเรา): 8CPVtuC9fh3RGztd4ugZsTgDPb57449BpfU1Qucks4iB
- Token Account Address: Fj8Ptsjjp6x1AK75BKV9mfediGMvk3BFWGGqnTQ4XSPF
ทำการ Mint token ออกมาซัก 100,000
spl-token mint 8CPVtuC9fh3RGztd4ugZsTgDPb57449BpfU1Qucks4iB 100000
ลองเช็ค supply ผ่าน Explorer หรือ Cli:
spl-token supply 8CPVtuC9fh3RGztd4ugZsTgDPb57449BpfU1Qucks4iB
เช็คว่าเรามี token ใน account (wallet เรา) นี้เท่าไหร่
spl-token accounts
ได้ผลลัพธ์เป็น
Token Balance
---------------------------------------------------------------
8CPVtuC9fh3RGztd4ugZsTgDPb57449BpfU1Qucks4iB 100000
หรือถ้า Explorer จะเป็น link นี้
ต่อมาลองส่ง token ไปให้คนอื่นดู โดยมันมีรูปแบบแบบนี้
spl-token transfer <TOKEN_ADDRESS> <TOKEN_AMOUNT> <RECIPIENT_ADDRESS>
ผมส่ง 888 token ไปให้ account ใหม่ ฉะนั้นก็จะได้เป็นแบบนี้
spl-token transfer --fund-recipient 8CPVtuC9fh3RGztd4ugZsTgDPb57449BpfU1Qucks4iB 888 EjPKhV2bww3NLs9isZQQBia4f6JMFxewfnygaMe7cMBs
- EjPKhV2bww3NLs9isZQQBia4f6JMFxewfnygaMe7cMBs คือ account ที่ผมส่งเงินไปให้ (ผม
solana-keygen new
ขึ้นมาใหม่อีก wallet) --fund-recipient
ที่ต้องใส่ เพราะปกติ แต่ละ wallet account ต้องมี Associate account สำหรับ token นั้นๆ ก่อน (เหมือนกับที่สร้าง empty account เพื่อเก็บ balance ครับ) สิ่งที่--fund-recipient
ทำคือ มัน สร้าง AssociatedAccount ให้เราอัตโนมัติ นั่นเอง
จริงๆ เราสามารถสร้าง NFT ด้วยนะครับ ก็เหมือนการสร้าง Token ทุกอย่าง
spl-token create-token --decimals 0
เพียงแต่ ปกติตอนเรา create-token ถ้าเราไม่ได้กำหนด option ค่า default ของมันคือ decimals เท่ากับ 9 พอเรากำหนด decimals = 0 นั่นหมายความว่า 1 token ก็คือ 1 NFT นั่นเอง
Phantom Wallet
เราสามารถนำ Wallet ของเราไป import ใช้กับ Phantom Wallet ได้เหมือนปกติเลย จะใช้ 12 คำ หรือ private key ก็ได้
ตัวอย่างการ import private key คือ ในไฟล์ *.json
ของเรา ปกติ มันก็เก็บ public + private key อยู่แล้ว เป็น Buffer แบบด้านล่าง
[154,246,53,155,1,2,2,2,3,3,34,43,3,5,23,5,34,5,34, ... ,61,190]
ฉะนั้นไฟล์ Keypair สำคัญมากๆ เพราะมันเก็บ public + private key ใครเข้าถึง ใครอ่านได้ ก็เข้าถึงกระเป๋าได้ครับ
นำไปเพิ่มใน Phantom
เปลี่ยน Network เป็น Devnet
เพียงแค่นี้เราก็เห็น Token เราใน Phantom แล้ว ลอง transfer token ดูครับ และลองดู transaction ใน Solscan / Explorer เปรียบเทียบดูครับ
SPL Token Registry
หลายคนอาจจะสงสัย ว่าเรากำหนด ชื่อ Name, Symbol ของ Token เรายังไง? คำตอบคือมันไม่ได้ถูกเก็บใน Blockchain แบบ EVM-Based ครับ
สิ่งที่เราต้องทำคือ ไปเพิ่ม JSON shema เช่น กำหนด token, chainId, address, ชื่อ, symbol, logo เป็นต้น ที่ Repo นี้ครับ
ส่วนตัวผมก็ยังไม่เคยเพิ่มไปนะครับ เพราะใช้แค่ Devnet ยังไม่เคยทำ Product ที่เป็น Production จริงๆครับ ซึ่ง devnet ผมก็ไม่อยากเพิ่มให้เปลือง list เปล่าๆ คือมันแค่เทส เลยไม่จำเป็น
สรุป
ตัวอย่างนี้ก็เป็นตัวอย่างง่ายๆ ในการ สร้าง Token (SPL Token) บน Solana นะครับ แม้จะเป็น CLI แต่ก็ทำให้เห็นภาพมากขึ้น จะเห็นว่าทุกๆ Token และทุกๆ account การที่เราจะมี token นั้นๆ ได้ สิ่งที่ต้องทำคือ มี AssociatedAccount
และแต่ละขั้นตอน ถ้าไม่เข้าใจ แนะนำว่าลองเล่น ลองพิมพ์ และดู Solscan หรือ Solana Explorer เปรียบเทียบดูนะครับ เช่นส่วน Instructions จะบอกว่า transaction ทำอะไร เป็นต้น
หวังว่าบทความนี้เป็นประโยชน์นะครับ Happy Coding ❤️
References
- Authors
- Name
- Chai Phonbopit
- Website
- @Phonbopit