您的位置:首页 > 娱乐 > 八卦 > 小试牛刀-SOL链创建Token代币

小试牛刀-SOL链创建Token代币

2024/12/24 2:16:10 来源:https://blog.csdn.net/2202_75618418/article/details/141808394  浏览:    关键词:小试牛刀-SOL链创建Token代币

目录

1.编写目的

2.账户结构

3.环境及使用依赖

4.步骤分解

4.1.导入相关依赖

4.2. 初始化变量

4.3.  创建并初始化Mint Account

4.4. 创建并初始化Metadata Account

4.5. 发送创建和初始化mint Account

4.6 铸造代币

5.源码分享


Welcome to Code Block's blog

本篇文章主要介绍了

[小试牛刀-SOL链创建Token代币]
❤博主广交技术好友,喜欢文章的可以关注一下❤

1.编写目的

        最近需要编写SOL合约进行SPL代币的转账,因为在测试网上需要自己部署测试代币,同时为了更加美观,代币需携带metadata数据(对代币名称、代币头像等)进行定义.在此对创建过程进行记录,希望帮助到有需要实现相关功能的朋友.

2.账户结构

        SOL链内的所有数据都存储在账户中,创建代币需要使用不同的程序(合约)创建三个账户,结构图如下:

 Mint Account:使用TOKEN_PROGRAM(代币相关操作)程序,创建一个Mint Account,这个账户的作用是用来铸造代币.

MetaData Account:使用METADATA_PROGRAM(metadata数据相关操作)程序,创建一个MetaData账户,用来存储代币基础信息(名称、图标/头像).

ACT Account: 铸造出的代币需要ACT Account进行接收,这需要使用用户和mint Account进行计算然后进行创建,用于接收铸造完成的代币.

3.环境及使用依赖

{"scripts": {"test": "ts-node ./test/createmint.test.ts"},"dependencies": {"@metaplex-foundation/mpl-token-metadata": "^2.1.1","@solana/spl-token": "^0.4.8","@solana/web3.js": "^1.95.3",},"devDependencies": {"@types/node": "^22.5.0","ts-node": "^10.9.2","typescript": "^5.5.4"}
}

        这里使用TypeScript和node环境进行代码编写,主要需要用到@metaplex-foundation/mpl-token-metadata(用于metadata Account初始化),@solana/spl-token(mint Account初始化和ACT Account创建),@solana/web3.js(用于基础Account创建和一些工具类).

注:这里尽量保持引入版本一致,因为不同版本的方法名称可能不同.

4.步骤分解

4.1.导入相关依赖

import { Keypair, PublicKey, SystemProgram,Connection,sendAndConfirmTransaction, Transaction } from "@solana/web3.js";
import { MINT_SIZE, TOKEN_PROGRAM_ID, createInitializeMint2Instruction, getOrCreateAssociatedTokenAccount,mintTo } from "@solana/spl-token";import {PROGRAM_ID as METADATA_PROGRAM_ID,createCreateMetadataAccountV3Instruction,
} from "@metaplex-foundation/mpl-token-metadata";
import * as fs from 'fs'

这里的fs用于读取本地密钥文件,用于生成payer.

4.2. 初始化变量

const connection = new Connection('https://api.devnet.solana.com', 'confirmed');const secretKeyPath='./wallet/id.json';
const secretKeyJSON = fs.readFileSync(secretKeyPath, 'utf-8');
// 创建测试账户
const secretKeyArray = JSON.parse(secretKeyJSON);
const secretKey = new Uint8Array(secretKeyArray);
const payer = Keypair.fromSecretKey(secretKey);
// 打印payer地址
console.log("Payer address:", payer.publicKey.toBase58());// 定义token名称等
const tokenConfig = {//小数位数decimals: 2,//代币名称name: "BOGGY",//代币符号symbol: "Boggy Coin",//metadata json地址uri: "https://bafkreibyxbbl2jba2ry6ds2wgc6phdlhm2u6sox3neltfrdth7ocgkbqfm.ipfs.nftstorage.link",};

这里connection定义了使用SOL测试网进行连接,同时通过读取本地的id.json文件创建一个交易费用支付者并进行打印。

4.3.  创建并初始化Mint Account

  //创建一个密钥对,将其公钥作为Mint地址const mintKeypair = Keypair.generate();//输出Mint Account地址console.log("Mint address:", mintKeypair.publicKey.toBase58());

这里创建一个密钥对,并打印,其公钥作为Mint Account地址在后面进行初始化.

 //创建基础Account const createMintAccountInstruction = SystemProgram.createAccount({fromPubkey: payer.publicKey,newAccountPubkey: mintKeypair.publicKey,space: MINT_SIZE,lamports: await connection.getMinimumBalanceForRentExemption(MINT_SIZE),programId: TOKEN_PROGRAM_ID,});//将Account初始化为一个mint Accountconst initializeMintInstruction = createInitializeMint2Instruction(mintKeypair.publicKey,tokenConfig.decimals,payer.publicKey,payer.publicKey,);

这里进行了mint Account的创建和初始化两条命令:

>SystemProgram.createAccount

fromPubkey:将作为该账户的拥有者和交易费用支付者.
newAccountPubkey:即为创建mint地址,
space:为组件内提供的MINT_SIZE(MINT Account必须使用的空间大小),
lamports:作为免租费用.使用提供的方法根据空间进行计算.
TOKEN_PROGRAM_ID: TOKEN_PROGRAM(代币相关操作)程序

>createInitializeMint2Instruction

mintKeypair.publicKey:指定作为mint Account的账户.
tokenConfig.decimals:设置小数位数为2位,
payer.publicKey:分别指定铸造权限拥有者和冻结权限拥有者,当设置为null时代币将不能继续被铸造.
注:这两个命令其实就可以创建代币,但代币没有名称和头像.

4.4. 创建并初始化Metadata Account

  const metadataAccount = PublicKey.findProgramAddressSync([Buffer.from("metadata"), METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()],METADATA_PROGRAM_ID,)[0];console.log("Metadata address:", metadataAccount.toBase58());

这里先创建了一个PDA账户(即METADATA_PROGRAM作为操作执行者),并进行打印.

注:根据官方要求必须使用派生(PDA)账户初始化MetaData Account.

  const createMetadataInstruction = createCreateMetadataAccountV3Instruction({metadata: metadataAccount,mint: mintKeypair.publicKey,mintAuthority: payer.publicKey,payer: payer.publicKey,updateAuthority: payer.publicKey,},{createMetadataAccountArgsV3: {data: {creators: null,name: tokenConfig.name,symbol: tokenConfig.symbol,uri: tokenConfig.uri,//费用sellerFeeBasisPoints: 0,collection: null,uses: null,},collectionDetails: null,isMutable: true,},},);

 使用createCreateMetadataAccountV3Instruction进行metadata Account的创建和初始化:

metadata:metadata Account(即PDA账户)
mint:关联MINT账户,
mintAuthority: mint的权限用户,
payer: 费用支付者和拥有者,
updateAuthority: metadata的更新操作权限拥有者,

在createMetadataAccountArgsV3中分别设置了代币名称、图像、简称地址等参数。
 

4.5. 发送创建和初始化mint Account

  const transaction=new Transaction().add(createMintAccountInstruction,initializeMintInstruction,createMetadataInstruction);const tx=await sendAndConfirmTransaction(connection,transaction,[payer,mintKeypair]);console.log("创建代币mint地址,交易tx:"+tx);

        这里将上面的 createMintAccountInstructioninitializeMintInstructioncreateMetadataInstruction添加到一个transaction中并使用sendAndConfirmTransaction发送到链上,即可完成带有metadata的SPL代币创建.

测试截图:

 

4.6 铸造代币

  const actAccount=await getOrCreateAssociatedTokenAccount(connection,payer,mintKeypair.publicKey,payer.publicKey);const mintSig=await mintTo(connection,payer,mintKeypair.publicKey,actAccount.address,payer,1000_000_000_000);console.log("向我的账户mint代币:"+mintSig);

这里使用 getOrCreateAssociatedTokenAccount方法创建一个actAccount,同时通过mintTo方法向actAccount铸造代币.

测试截图:

因为小数位数设置为两位所以铸造了 1000_000_000_000将会铸造10_000_000_000个代币.

5.源码分享

import { Keypair, PublicKey, SystemProgram,Connection,sendAndConfirmTransaction, Transaction } from "@solana/web3.js";
import { MINT_SIZE, TOKEN_PROGRAM_ID, createInitializeMint2Instruction, getOrCreateAssociatedTokenAccount,mintTo } from "@solana/spl-token";import {PROGRAM_ID as METADATA_PROGRAM_ID,createCreateMetadataAccountV3Instruction,
} from "@metaplex-foundation/mpl-token-metadata";
import * as fs from 'fs'
const connection = new Connection('https://api.devnet.solana.com', 'confirmed');const secretKeyPath='./wallet/id.json';
const secretKeyJSON = fs.readFileSync(secretKeyPath, 'utf-8');
// 创建测试账户
const secretKeyArray = JSON.parse(secretKeyJSON);
const secretKey = new Uint8Array(secretKeyArray);
const payer = Keypair.fromSecretKey(secretKey);
(async () => {console.log("Payer address:", payer.publicKey.toBase58());const mintKeypair = Keypair.generate();console.log("Mint address:", mintKeypair.publicKey.toBase58());const tokenConfig = {decimals: 2,name: "BOGGY",symbol: "Boggy Coin",uri: "https://bafkreibyxbbl2jba2ry6ds2wgc6phdlhm2u6sox3neltfrdth7ocgkbqfm.ipfs.nftstorage.link",};const createMintAccountInstruction = SystemProgram.createAccount({fromPubkey: payer.publicKey,newAccountPubkey: mintKeypair.publicKey,space: MINT_SIZE,lamports: await connection.getMinimumBalanceForRentExemption(MINT_SIZE),programId: TOKEN_PROGRAM_ID,});const initializeMintInstruction = createInitializeMint2Instruction(mintKeypair.publicKey,tokenConfig.decimals,payer.publicKey,payer.publicKey,);const metadataAccount = PublicKey.findProgramAddressSync([Buffer.from("metadata"), METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()],METADATA_PROGRAM_ID,)[0];console.log("Metadata address:", metadataAccount.toBase58());const createMetadataInstruction = createCreateMetadataAccountV3Instruction({metadata: metadataAccount,mint: mintKeypair.publicKey,mintAuthority: payer.publicKey,payer: payer.publicKey,updateAuthority: payer.publicKey,},{createMetadataAccountArgsV3: {data: {creators: null,name: tokenConfig.name,symbol: tokenConfig.symbol,uri: tokenConfig.uri,sellerFeeBasisPoints: 0,collection: null,uses: null,},collectionDetails: null,isMutable: true,},},);const transaction=new Transaction().add(createMintAccountInstruction,initializeMintInstruction,createMetadataInstruction);const tx=await sendAndConfirmTransaction(connection,transaction,[payer,mintKeypair]);console.log("创建代币mint地址,交易tx:"+tx);const actAccount=await getOrCreateAssociatedTokenAccount(connection,payer,mintKeypair.publicKey,payer.publicKey);const mintSig=await mintTo(connection,payer,mintKeypair.publicKey,actAccount.address,payer,1000_000_000_000);console.log("向我的账户mint代币:"+mintSig);
})();

感谢您的关注和收藏!!!!!!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com