这里主要就是通过程序发行的代币相关的交互。SPL(ERC20)代币的交互在Solana中,可以官方提供了模板进行山寨币的创建,可以通过调用系统程序进行代币的创建。JS交互可以通过JS和SPL代币进行交互,包括了:代币的创建、铸币、查看账户中代币的余额、进行SPL代币转账、销毁持有的SPL
这里主要就是通过程序发行的代币相关的交互。
在Solana
中,可以官方提供了模板进行山寨币的创建,可以通过调用系统程序进行代币的创建。
可以通过JS
和SPL
代币进行交互,包括了:代币的创建、铸币、查看账户中代币的余额、进行SPL
代币转账、销毁持有的SPL
// 通过 js 创建 spl 、查看 spl 余额、进行 spl 转账、销毁 spl
// 导入相关模块
const web3 = require("@solana/web3.js");
const spltoken = require("@solana/spl-token");
// 创建与 solana 的连接
const connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed");
// 加载钱包文件
function localwalletkey(keypairFile) {
const fs = require("fs");
const loaded = web3.Keypair.fromSecretKey(
new Uint8Array(JSON.parse(fs.readFileSync(keypairFile).toString()))
);
return loaded;
}
// 创建一个 spl token
async function createspl() {
// 加载一个钱包,作为交易费用支付者
const pairkey = localwalletkey("$key_path");
////////////////// 创建中涉及的用户地址 //////////////////
// 交易费用支付者
const payer = pairkey;
// 控制铸币的账户
const mintAuthority = pairkey.publicKey;
// 可以冻结代币的账户(可选是否存在)
const freezeAuthority = pairkey.publicKey;
// 通过solana系统程序创建一个 spl 代币
const mint = await spltoken.createMint(
// solana 连接
connection,
payer,
mintAuthority,
freezeAuthority,
// 代币的精度
9
);
console.log("创建新SPLToken", mint.toBase58());
}
// 向指定账户进行铸币
async function minttoken(account) {
// 需要铸币的 spl token 地址
const mint = new web3.PublicKey("token_address");
// 支付交易费用者
const payer = localwalletkey("$key_path");
// 拥有铸币权限的地址(因为是测试,所以地址为 payer)
const mintAuthority = payer;
// 接收 spl token 的地址
const recipient = account;
// 获取接收者对应的 token 账户(获取或创建)
const totokenaccount = await spltoken.getOrCreateAssociatedTokenAccount(
connection,
// 如果要创建账户,那么创建账户交易的支付者
payer,
// token 账户对应 token
mint,
// 账户的所有者地址
recipient
);
await spltoken.mintTo(
connection,
// 交易费用支付者
payer,
// token 地址
mint,
// 接收者 token 账户地址
totokenaccount.address,
// 拥有铸币权限的地址
mintAuthority.publicKey,
100 * 1000000000
);
}
// 查看指定账户的 spl 余额
async function catbalance(account) {
// 需要监控的地址
const destination = account;
// token 地址
const mint = new web3.PublicKey("token_address");
const mintinfo = await spltoken.getMint(connection, mint);
// 获取地址对应的 token 账户
const splaccount = await spltoken.getAssociatedTokenAddress(mint, destination, true);
const accountinfo = await spltoken.getAccount(connection, splaccount);
console.log("token supply:", mintinfo.supply);
console.log("account address:", account.toBase58());
console.log("token account Balance:", accountinfo.amount);
}
// 向指定账户转账 spl
async function transferspl() {
// token 地址
mint = new web3.PublicKey("token_address");
// 交易费用支付者
const payer = localwalletkey("$key_path");
// 发送者公钥地址
const sender = payer.publicKey;
const recipient = new web3.PublicKey("$another_publikey")
const fromtoken = await spltoken.getAssociatedTokenAddress(mint, sender, true);
const totoken = await spltoken.getOrCreateAssociatedTokenAccount(
connection,
payer,
mint,
// 账户的所有者地址
recipient
);
let tx = spltoken.createTransferInstruction(
fromtoken,
totoken.address,
sender,
1 * 1000000000,
[],
spltoken.TOKEN_PROGRAM_ID
);
let transaction = new web3.Transaction().add(tx);
let signature = await web3.sendAndConfirmTransaction(connection, transaction, [payer]);
console.log("交易哈希:", signature);
}
// 销毁持有的一定数量的 spl 代币
async function burnspl(account) {
// 交易费用支付者
const payer = account;
// token 地址
const mint = new web3.PublicKey("token_address");
// 获取地址对应的 token 账户
const splaccount = await spltoken.getAssociatedTokenAddress(mint, account.publicKey, true);
let tx = spltoken.createBurnInstruction(splaccount, mint, account.publicKey, 0.1 * 1000000000);
let transaction = new web3.Transaction().add(tx);
let signature = await web3.sendAndConfirmTransaction(connection, transaction, [payer]);
console.log("交易哈希:", signature);
}
async function main() {
// await createspl();
const accounta = localwalletkey("wallet-keypair.json");
const publicKeya = accounta.publicKey;
const publicKeyb = new web3.PublicKey("BGCmiwDbQ4BDq2vjLARuZ5ptZeXR2BLFB53wmmPpUQyA");
// 向地址 a 进行铸币
await minttoken(publicKeya);
// 查看 a 余额
await catbalance(publicKeya);
// a 向 b 转账
await transferspl();
// 查看 a 和 b 的余额
await catbalance(publicKeya);
await catbalance(publicKeyb);
await catbalance(publicKeya);
// 销毁 a 中的一定数量的 spl 代币
await burnspl(accounta);
await catbalance(publicKeya);
}
main();
python 的Seahorse
很多资料没有,目前只能进行:查看 token 余额、转账
from seahorse.prelude import *
# 在程序中查看 token 余额、转账
declare_id("")
class Program(Account):
# 进行转账的 spl token 的地址
mint_addr:Pubkey
# 存放 spl token 的账户
program_token_account:Pubkey
@instruction
def init_token_accout(token_account:Empty[TokenAccount],mint:TokenMint,signer:Signer,program:Empty[Program]):
# 初始化程序的 token account
token_account = token_account.init(payer=signer,seeds=['token_account'],mint=mint,authority=signer)
# 初始化并保存程序的账户
program = program.init(payer=signer,seeds=['program'])
program.mint_addr = mint.key()
program.program_token_account = token_account.key()
# 将自己手中的 spl token 发送给程序的 token 账户
@instruction
def spend_token(spender_token:TokenAccount,program_token_account:TokenAccount,signer:Signer,program:Program):
# 检查用户提供的 spl token 是不是我们指定的 spl token
assert str(spender_token.mint) == str(program.mint_addr),"token error"
# 保证发送到的 token 账户,为指定的 token 账户
assert program_token_account.key() == program.program_token_account,"program token account error"
spender_token.transfer(authority=signer,to=program_token_account,amount=10000000)
# 取出程序中的 spl token
@instruction
def withdrawals(to_account:TokenAccount,program_token_account:TokenAccount,program:Program,signer:Signer):
# 检查用户提供的 spl token 是不是我们指定的 spl token
assert str(to_account.mint) == str(program.mint_addr),"token error"
# 保证取出的 token 账户,为指定的 token 账户
assert program_token_account.key() == program.program_token_account,"program token account error"
# 将程序的 token 账户中的所有余额取出
program_token_account.transfer(authority=signer,to=to_account,amount=u64(program_token_account.amount))
在Solana
中铸造一个 NFT 其实就是铸造一个特殊的SPL
代币,精度为 0,数量为1,该token
带有的metadata
和普通SPL
有些不同。
在前面的SPL
的声明中,并没有输入token
的名称的信息,
因为NFT
和SPL
相差不多,主要区别在于声明参数,和必须添加metadata
部分(SPL
可以不添加,这样只是会显得这个SPL
没有特点,添加的话和NFT
几乎一样的方法,只是属性略有区别),所以只列举了NFT
的创建。
// 导入相关库
const { createMetadataAccountV3 } = require("@metaplex-foundation/mpl-token-metadata");
const { createSignerFromKeypair, none, signerIdentity } = require("@metaplex-foundation/umi");
const { createUmi } = require("@metaplex-foundation/umi-bundle-defaults");
const {
fromWeb3JsKeypair,
fromWeb3JsPublicKey,
} = require("@metaplex-foundation/umi-web3js-adapters");
const web3 = require("@solana/web3.js");
const { create } = require("domain");
// 加载钱包文件
function localwalletkey(keypairFile) {
const fs = require("fs");
const loaded = web3.Keypair.fromSecretKey(
new Uint8Array(JSON.parse(fs.readFileSync(keypairFile).toString()))
);
return loaded;
}
async function creatNft() {
/////////////////////// 环境准备 ///////////////////////
// 加载钱包
const mywallet = localwalletkey("$key_path");
// 创建的 spl token 的地址(spl 的精度为 0 ,数量为 1)
const mint = new web3.PublicKey("token addr");
// 创建与 solana 连接实例
const umi = createUmi("https://api.devnet.solana.com");
// 使用现有钱包生成一个签名对象,方便签名交易
const signer = createSignerFromKeypair(umi, fromWeb3JsKeypair(mywallet));
// 设置 umi
umi.use(signerIdentity(signer, true));
/////////////////////// 数据准备 ///////////////////////
// 创建 NFT 的数据内容
const nftMetadata = {
name: "NFT name",
symbol: "TN",
// 存储在链下,但是其他地方如 ipfs 上所得到的地址
uri: "json uri",
sellerFeeBasisPoints: 0,
creators: none(),
collection: none(),
uses: none(),
};
const accounts = {
mint: fromWeb3JsPublicKey(mint),
mintAuthority: signer,
};
const data = {
isMutable: true,
colletionDetails: null,
data: nftMetadata,
};
/////////////////////// 上链 ///////////////////////
// 将数据上链
const txid = await createMetadataAccountV3(umi, { ...accounts, ...data }).sendAndConfirm(umi);
}
creatNft();
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!