Solana

2026年01月27日更新 17 人订阅
原价: ¥ 8.6 限时优惠
专栏简介 Solana 开发学习之Solana 基础知识 Solana 开发学习之通过RPC与Solana交互 Web3与Solana实操指南:如何签名与发送交易 Web3 新玩法:Solana Nonce Account 让你交易无忧 Web3 快上手:Solana 造你的链上名片 Web3 开发实战:用 Anchor 打造 Solana 猜数游戏 @solana/web3.js 2.0:Solana 转账全流程解析 玩转 Web3 Solana:从零到代币开发 Web3 开发入门:Solana CLI 配置与本地验证器实战 Web3 Eclipse 开发环境搭建与资产跨链桥接实战指南 用 Gill 库解锁 Web3:Solana 代币转账实战 Web3开发:用Rust实现Solana SOL转账教程 用 Rust 开发 Solana:解锁 Web3 交易费用计算 Web3开发入门:Solana账户创建与Rust实践全攻略 Web3 实战:用 Anchor 打造 Solana 智能合约全流程 Solana Web3 快速入门:创建并获取钱包账户的完整指南 Web3 开发实操:用 Anchor 在 Solana 创建代币 Mint Account 从零到 Web3:使用 @solana/kit 快速查询 Solana 账户余额 快速上手 Web3:用 @solana/kit 在 Solana 上创建钱包并查询余额 Web3实战:使用Anchor与Rust开发和调用Solana智能合约 Web3实战:Solana CPI全解析,从Anchor封装到PDA转账 用 Rust 在 Solana 上打造你的专属代币:从零到一的 Web3 实践 探索Solana SDK实战:Web3开发的双路径与轻量模块化 手把手教你用 Solana Token-2022 创建支持元数据的区块链代币 Solana 开发实战:Rust 客户端调用链上程序全流程 Solana 开发进阶:在 Devnet 上实现链上程序部署、调用与更新 Solana 开发进阶:链上事件到链下解析全攻略 从零打造Solana空投工具库:Rust开发实战指南 从零开始:用 Rust 开发 Solana 链上 Token 元数据查询工具 Solana 智能合约终极部署指南:从入门到主网,定制你的专属靓号 Program ID 【Solana 开发实战】轻松搞定链上 IDL:从上传到获取全解析 Solana 投票 DApp 开发实战:从合约到部署的完整指南 Surfpool:Solana 上的 Anvil,本地开发闪电般⚡️ 【Solana实操】64字节私钥文件解析难题:用三种姿势安全获取钱包地址 Solana 密钥实战:一文搞懂私钥、公钥、PDA 的底层关系与 CLI 操作 Solana 地址进阶:从 TS/JS 到 Rust SDK V3,完全掌握公钥与 PDA 的底层逻辑 Solana 开发者笔记:PDA 与账户操作的10个关键要点 拒绝“版本代差”:基于 Solana SDK V3 的「链上动态存储器」工业级实现 从零到 Devnet:Solana Anchor Vault 个人金库开发全流程实操 Anchor 中一个隐蔽但致命的坑:Accounts 顺序导致 AccountNotInitialized 从核心逻辑到上链部署:Solana Anchor 托管程序实战全记录 Solana 开发实战:使用 @solana/web3.js 与 Bun 铸造首个 SPL 代币 Solana 开发实战:使用 @solana/kit (v2) 发行 SPL 代币全流程 仅 0.6 秒编译!用 Pinocchio 打造极致轻量化 Solana Vault 合约全记录

Solana 开发实战:使用 @solana/kit (v2) 发行 SPL 代币全流程

Solana开发实战:使用@solana/kit(v2)发行SPL代币全流程Solana的开发工具正在经历一次重要的进化。随着@solana/web3.js2.x版本正式更名为@solana/kit,官方SDK迎来了更轻量、更模块化、且全面拥抱函数式编程的新时代。对于开

Solana 开发实战:使用 @solana/kit (v2) 发行 SPL 代币全流程

Solana 的开发工具正在经历一次重要的进化。

随着 @solana/web3.js 2.x 版本正式更名为 @solana/kit,官方 SDK 迎来了更轻量、更模块化、且全面拥抱函数式编程的新时代。对于开发者而言,这意味着代码将变得更具可组合性,同时能更好地利用 Tree-shaking 优化包体积。

但新技术总需要一段适应期。新版的 Rpc 怎么建?交易流水线 pipe 怎么写?如何像以前一样轻松地发币?

本文将抛开繁杂的理论,直接进入代码实操模式。我们将基于本地测试网络(Surfnet),手把手带你跑通从环境初始化、加载签名者、到完成一笔“原子化铸币”交易的全过程,最后教你如何读取并验证链上数据。

准备好了吗?让我们开始构建。

实操

使用 @solana/kit 铸造一个 SPL Token

Solana Kit 这是用于构建适用于 Node、Web 和 React Native 的 Solana 应用程序的 JavaScript SDK。@solana/web3.js 的 2.x 版本重命名为 @solana/kit。

安装依赖

pnpm install --save @solana/kit

bun add @solana-program/system \
  @solana-program/memo \
  @solana-program/token \
  @solana-program/compute-budget

初始化 Solana 交互客户端 (Context)

connect.ts 文件

import {
    createSolanaRpc,
    createSolanaRpcSubscriptions,
    sendAndConfirmTransactionFactory,
} from '@solana/kit'

// 1. 设置 RPC 连接(指向你的本地 Surfpool)
const rpc = createSolanaRpc('http://127.0.0.1:8899') //

// 2. 设置订阅服务(用于实时确认交易)
const rpcSubscriptions = createSolanaRpcSubscriptions('ws://127.0.0.1:8900') //

// 3. 创建发送并确认交易的工具函数
const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions }) //

console.log("🚀 Solana Kit 已就绪,连接至本地 Surfnet!")

// 快速测试:获取当前 Slot
const slot = await rpc.getSlot().send()
console.log(`当前本地 Slot: ${slot}`)

/**
 * Code/Solana/solana_forge via 🍞 v1.2.17
➜ bun run src/solanakit/connect.ts
🚀 Solana Kit 已就绪,连接至本地 Surfnet!
当前本地 Slot: 395783430
 */

这段代码使用 Solana Kit 初始化了与本地开发环境(如 Surfpool 或本地验证器)的通信链路:首先通过 createSolanaRpc 建立 HTTP 连接以执行基础查询,接着利用 createSolanaRpcSubscriptions 开启 WebSocket 监听以实时获取交易状态,最后通过 sendAndConfirmTransactionFactory 将两者整合为一个能够自动发送并等待网络确认的工具函数,从而实现对链上数据(如 Slot 高度)的异步交互。

执行客户端连接脚本

Code/Solana/solana_forge via 🍞 v1.2.17 
➜ bun run src/solanakit/connect.ts  
🚀 Solana Kit 已就绪,连接至本地 Surfnet!
当前本地 Slot: 395783430

这段运行结果展示了通过 Bun 运行时成功执行了连接脚本,证实了 Solana Kit 客户端 已与本地 Surfnet 节点建立双向通信:它不仅完成了 RPC 实例的初始化,还通过成功获取并打印当前的 Slot(插槽高度),验证了程序具备从链上读取实时数据以及发送指令的能力。

加载本地文件系统签名者 (Signer)

signer.ts 文件

import {
    createKeyPairFromBytes,
    createSignerFromKeyPair,
    address
} from '@solana/kit'
import { readFileSync } from 'node:fs'

export async function getLocalSigner() {
    // 1. 读取 64 字节的 id.json
    const WALLET_PATH = "/Users/qiaopengjun/.config/solana/id.json"
    const secretKeyArray = JSON.parse(readFileSync(WALLET_PATH, 'utf-8'))
    const secretKeyBytes = new Uint8Array(secretKeyArray)

    // 2. 将字节转为 CryptoKeyPair
    const keyPair = await createKeyPairFromBytes(secretKeyBytes)

    // 3. 关键一步:将 KeyPair 包装成 Signer
    const signer = createSignerFromKeyPair(keyPair)

    // 现在 signer.address 就有值了!
    return signer
}

// 执行并打印
const signer = await getLocalSigner()
console.log(`✅ Kit 签名者已就绪: ${signer.address}`)

这段代码通过 node:fs 读取本地 Solana CLI 默认生成的 id.json 私钥文件,并利用 Solana KitcreateKeyPairFromBytes 将原始字节数组转换为非对称加密密钥对,最后通过 createSignerFromKeyPair 将其封装为具备自动签名能力的 Signer 对象,从而实现将本地开发钱包安全地导入到 Web3 应用中以进行交易授权。

加载本地钱包身份验证

Code/Solana/solana_forge via 🍞 v1.2.17 
➜ bun run src/solanakit/signer.ts
✅ Kit 签名者已就绪: 6MZDRo5v8K2NfdohdD76QNpSgk3GH3Aup53BeMaRAEpd

该运行结果表明脚本已成功通过 Bun 运行时解析并加载了本地文件系统中的私钥,利用 Solana Kit 将其转换为合法的加密签名者对象,并正确派生出了对应的公共地址(6MZD...),这意味着该身份已准备就绪,可以代表该钱包在后续的流水线中对任何链上交易进行授权签名。

构建单例模式的 Solana 交互客户端 (Client Singleton)

client.ts 文件

import {
    createSolanaRpc,
    createSolanaRpcSubscriptions,
} from '@solana/kit'
import type {
    Rpc,
    RpcSubscriptions,
    SolanaRpcApi,
    SolanaRpcSubscriptionsApi,
    TransactionSigner,
    MessageSigner
} from '@solana/kit'
import { getLocalSigner } from './signer'

// 定义 Client 类型
export type Client = {
    rpc: Rpc<SolanaRpcApi>
    rpcSubscriptions: RpcSubscriptions<SolanaRpcSubscriptionsApi>
    wallet: TransactionSigner & MessageSigner
}

let client: Client | undefined

export async function getClient(): Promise<Client> {
    if (!client) {
        const rpc = createSolanaRpc('http://127.0.0.1:8899')
        const rpcSubscriptions = createSolanaRpcSubscriptions('ws://127.0.0.1:8900')

        const wallet = await getLocalSigner()

        client = { rpc, rpcSubscriptions, wallet }
    }
    return client
}

这段代码采用 单例模式 封装了 Solana 客户端的初始化逻辑,通过定义 Client 类型将远程过程调用(RPC)、WebSocket 订阅服务以及本地签名钱包(Wallet)整合在一起,并利用 getClient 异步函数确保在整个应用程序生命周期内只创建一次连接实例,从而为其他模块提供了一个高效、统一且类型安全的链上交互入口。

使用 Solana Kit 实现原子化铸造代币 (Atomic SPL Token Minting)


/** Mint an SPL Token
 *
 *
 * Goal:
 *   Mint an SPL token in a single transaction using @solana/kit library.
 *
 * Objectives:
 *   1. Create an SPL mint account.
 *   2. Initialize the mint with 6 decimals and your public key (feePayer) as the mint and freeze authorities.
 *   3. Create an associated token account for your public key (feePayer) to hold the minted tokens.
 *   4. Mint 21,000,000 tokens to your associated token account.
 *   5. Sign and send the transaction.
 */
import {
    appendTransactionMessageInstructions,
    assertIsSendableTransaction,
    assertIsTransactionWithBlockhashLifetime,
    createTransactionMessage,
    generateKeyPairSigner,
    getSignatureFromTransaction,
    pipe,
    sendAndConfirmTransactionFactory,
    setTransactionMessageFeePayerSigner,
    setTransactionMessageLifetimeUsingBlockhash,
    signTransactionMessageWithSigners
} from '@solana/kit'
import {
    findAssociatedTokenPda,
    getCreateAssociatedTokenInstruction,
    getCreateAssociatedTokenInstructionAsync,
    getInitializeMintInstruction,
    getMintSize,
    getMintToInstruction,
    TOKEN_PROGRAM_ADDRESS
} from '@solana-program/token'
import { getCreateAccountInstruction } from '@solana-program/system'
import { getClient } from "./client"

async function main() {
    try {
        const { rpc, rpcSubscriptions, wallet } = await getClient()
        const sendAndConfirm = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })

        // --- 准备阶段 ---
        const decimals = 6
        const mintAmount = 21_000_000n * (10n ** BigInt(decimals))
        const mintSize = getMintSize()

        const [mintSigner, { value: latestBlockhash }, mintRent] = await Promise.all([
            generateKeyPairSigner(),
            rpc.getLatestBlockhash().send(),
            rpc.getMinimumBalanceForRentExemption(BigInt(mintSize)).send(),
        ])

        // 计算 ATA 地址 (PDA)
        const [ataAddress] = await findAssociatedTokenPda({
            mint: mintSigner.address,
            owner: wallet.address,
            tokenProgram: TOKEN_PROGRAM_ADDRESS,
        })

        console.log(`✅ 加载钱包: ${wallet.address}`)
        console.log(`🛠️ 创建 Mint: ${mintSigner.address}`)
        console.log(`📦 ATA 地址: ${ataAddress}`)

        const createAtaIx = await getCreateAssociatedTokenInstructionAsync({
            payer: wallet,
            mint: mintSigner.address,
            owner: wallet.address,
            tokenProgram: TOKEN_PROGRAM_ADDRESS,
        })

        // --- 构建流水线交易 (Objective 1-5) ---
        const transactionMessage = pipe(
            createTransactionMessage({ version: 'legacy' }),
            (tx) => setTransactionMessageFeePayerSigner(wallet, tx),
            (tx)...

剩余50%的内容订阅专栏后可查看

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论