从零开始学习 Solana 交易:创建、理解、调试全流程

Posted by JZW 加密货币资讯站 on September 5, 2025

Solana 链上的每一次数据变更,背后都有一次「交易」在默默运行。本篇文章用浅显中文把“创建交易”这件事拆解成可复现的代码范例,同时融入原子性交易费用Solana Explorer 等核心关键词,帮助你真正“读”得懂、“写”得会、“测”得稳。若想亲手跑一遍,👉 点击直达高并发网络无阻塞节点,开启 0 等待测试体验。


什么是交易?为什么一定要懂它

在 Solana 世界中,交易(transaction) 就是“打包好的指令集合”:

  • 只能整体成功或整体失败(原子性
  • 必须由至少一个签名人支付交易费用
  • 任何智能合约状态更新、NFT 铸造、代币转移,最终都靠交易驱动

交易的“四件套”

  1. Instructions(指令):要做什么
  2. Accounts(账户):对谁做
  3. Program ID(程序地址):谁去执行
  4. Data(字节数组):传哪些参数

借助 @solana/web3.js,一行代码就能生成转账指令:

const instruction = SystemProgram.transfer({
  fromPubkey: sender,
  toPubkey: recipient,
  lamports: 5_000,
});

创建一个转账交易:一步一步来

第 1 步:环境准备

确保已安装 Node 16+,并准备好:

npm install @solana/web3.js @solana-developers/helpers esrun dotenv

.env 写入本地密钥:

SECRET_KEY=[170,231, ... 你的私钥字节数组]

第 2 步:骨架代码

新建文件 transfer.ts

import {
  Connection,
  Transaction,
  SystemProgram,
  sendAndConfirmTransaction,
  PublicKey,
} from "@solana/web3.js";
import "dotenv/config";
import { getKeypairFromEnvironment } from "@solana-developers/helpers";

const suppliedToPubkey = process.argv[2] || null;
if (!suppliedToPubkey) {
  console.log("请提供接收方地址: npx esrun transfer.ts <recipient_pubkey>");
  process.exit(1);
}

const senderKeypair = getKeypairFromEnvironment("SECRET_KEY");
const toPubkey = new PublicKey(suppliedToPubkey);
const connection = new Connection("https://api.devnet.solana.com", "confirmed");

console.log("✅ 已加载本地密钥并连接至 devnet");

第 3 步:添加转账逻辑

继续补上转账 5000 lamports(≈ 0.000005 SOL):

const transaction = new Transaction();
const instruction = SystemProgram.transfer({
  fromPubkey: senderKeypair.publicKey,
  toPubkey,
  lamports: 5_000,
});
transaction.add(instruction);

const signature = await sendAndConfirmTransaction(connection, transaction, [
  senderKeypair,
]);
console.log(`💸 转账完成!签名:${signature}`);

运行效果:

npx esrun transfer.ts 7J4...recipient
# 输出:💸 转账完成!签名:4wxotDPU...

为什么我的交易失败?——常见报错速查

多数新手卡在第一关:余额不足支付交易费用。你会看到:

Transaction simulation failed: Attempt to debit an account but found no record of a prior credit.

在 Devnet 免费领水即可解决:

import { airdropIfRequired } from "@solana-developers/helpers";

await airdropIfRequired(
  connection,
  senderKeypair.publicKey,
  1 * LAMPORTS_PER_SOL,
  0.5 * LAMPORTS_PER_SOL,
);

主网无空投,请务必用官方水龙头或交易所充值的小额 SOL 充当 Gas。


在 Solana Explorer 追踪交易

signature 粘到 Solana Explorer 查询框:

  • 区块高度:交易被打包在第 N 块
  • 交易费:本次花费 0.000005 SOL 锁定确定性收费
  • Confirmations:只要 RPC 返回 confirmed,通常 1–3 秒即可“终局”

想要实时看网络状态?👉 直达可视化高吞吐 Solana 区块链浏览器


动手实验:把课堂变成小生态

每人公开自己的公钥,互相转账 5000 lamports,谁能最快完成下述任务?

考核项 目标值 记录方式
耗时 < 10 秒 console.time()
验证次数 3 笔 signature.length === 3
失败率 0 catch 错误并打印原因

完成后,把代码签入 GitHub,附上 playground 链接,分享你发现的三件事:

  1. 交易费用与转账金额无关的大小对比
  2. Devnet 上的 交易确认时间 均值
  3. 你能用 CLI solana confirm -v <tx> 追踪到的事件顺序

常见问题 FAQ

Q1:交易费到底是怎么算的?
A:Solana 用 固定基础费 + 交易指令计算单元 (CUs) 双重模型。当前 Devnet 基础费 0.000005 SOL;主网随网络负载动态调整,与转账金额无关。

Q2:为什么广播后还会“Dropped”?
A:大概率是 RPC 拥挤或学费不足。可尝试换高可用节点或重放交易。

Q3:Transaction 的 confirmedfinalized 有何区别?
A:

  • confirmed = 已由集群投票确认,但理论上可被分叉反冲。
  • finalized = 超过 31 个区块深度,结点达成共识极难回滚,适合 DeFi 结算。

Q4:能把一次转账拆成多条指令吗?
A:完全可以。把多条 SystemProgram.transfer 塞进同一笔 Transaction,只用付一次总费用,节省开销。

Q5:如何离线签名?
A:用 @solana/web3.jsTransaction.populate() + Keypair.signTransaction() 完成本地计算,再广播即可。

Q6:主网最低转账数量是多少?
A:技术上 1 lamport(0.000000001 SOL),但需额外支付交易费,因此最佳实践是 ≥ 0.00001 SOL 以保证不欠费。


小结 & 下一步

到这里,你已掌握:

  • 交易的三大特征:原子性费用确定异步并行
  • 用 8 行代码在 Devnet 完成 SOL 转账
  • 用 Solana Explorer 观测链上细节

下一步,不妨深入 自定义链上程序(PDA、Anchor 框架),把你的交易逻辑无限扩展!