Solana Web3.js 2.0 快速上手指南:用 JavaScript 发送链上交易

·

本指南聚焦于 Solana Web3.js 2.0 的「函数式」用法,一次演练从空投资金到发送转账的完整流程。十分钟读完,你就能用不到百行代码把 Solana JavaScript 交互跑通。

👉 想直接在浏览器里体验交互?立即查看在线示例!


1 项目准备

1.1 环境依赖

1.2 安装依赖包

mkdir solana-transfer-demo && cd solana-transfer-demo
npm init -y
npm install @solana/web3.js@2 @solana-program/system
npm install --save-dev @types/node
npx tsc --init --resolveJsonModule true
echo > transfer.ts

2 初始化连接:掌握 RPC 和订阅

在发送任何交易前,先建立 RPCWebSocket 连接,它们是驱动 Solana 交易的两条主线。

// transfer.ts
import {
  createSolanaRpc,
  createSolanaRpcSubscriptions
} from "@solana/web3.js";

const HTTP_ENDPOINT = "http://127.0.0.1:8899";   // 本地验证器
const WS_ENDPOINT   = "ws://127.0.0.1:8900";

const rpc = createSolanaRpc(HTTP_ENDPOINT);
const rpcSubscriptions = createSolanaRpcSubscriptions(WS_ENDPOINT);
console.log("✅ RPC 已连接");

3 钱包准备:两种密钥生成方式

为了让 Solana Web3.js 2.0 尽显灵活性,这里演示“算法生成”与“字节导入”双轨并行:

import {
  generateKeyPairSigner,
  createKeyPairSignerFromBytes
} from "@solana/web3.js";

const user1 = await generateKeyPairSigner();
console.log("user1 地址:", user1.address);

// 如已有 my-keypair.json
import secret from "./my-keypair.json";
const user2 = await createKeyPairSignerFromBytes(new Uint8Array(secret));

4 领取测试代币:空投 1 SOL

Solana 开发离不开充足的 lamports。展示两种空投风格:

import { lamports, airdropFactory } from "@solana/web3.js";

const LAMPORTS_PER_SOL = BigInt(1_000_000_000);

// 方法 A:原生 RPC
const tx1 = await rpc
  .requestAirdrop(user1.address, lamports(LAMPORTS_PER_SOL))
  .send();

// 方法 B:工厂模式
const airdrop = airdropFactory({ rpc, rpcSubscriptions });
await airdrop({ recipientAddress: user2.address, lamports: lamports(LAMPORTS_PER_SOL) });

两种路径均以 commitment: 'processed' 接收后立即刷新余额,满足高频测试需求。


5 构造转账交易:函数式「管道」解析

Web3.js 2.0 的核心变化之一是用 函数式管道 取代「对象链式操作」。继续拆解:

import {
  pipe,
  createTransactionMessage,
  setTransactionMessageFeePayer,
  setTransactionMessageLifetimeUsingBlockhash,
  appendTransactionMessageInstruction,
  sendAndConfirmTransactionFactory,
  signTransactionMessageWithSigners,
  getSignatureFromTransaction
} from "@solana/web3.js";
import { getTransferSolInstruction } from "@solana-program/system";

const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();

const transferMsg = pipe(
  createTransactionMessage({ version: 0 }),
  (tx) => setTransactionMessageFeePayer(user1.address, tx),
  (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
  (tx) => appendTransactionMessageInstruction(
    getTransferSolInstruction({
      source: user1,
      destination: user2.address,
      amount: lamports(LAMPORTS_PER_SOL / 2n) // 0.5 SOL
    }),
    tx
  )
);

const signed = await signTransactionMessageWithSigners(transferMsg);

const sendAndConfirm = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
await sendAndConfirm(signed, { commitment: "confirmed" });

console.log("✅ 转账成功,签名:", getSignatureFromTransaction(signed));

6 本地验证与运行

打开新终端:

solana-test-validator -r

回放:

ts-node transfer.ts

输出示例:

✅ RPC 已连接
✅ user1 地址: 8sFgz...
✅ user2 地址: 5o3Xy...
✅ 空投完成
✅ 转账成功,签名:5k7QW...

7 扩展:多指令打包

函数式 Solana风格里,pipe 天然支持追加指令。例如再转 0.3 SOL 给第三个账户:

const thirdAddress = "<SECRET_KEY>";
const multiTx = pipe(
  // 上文已有步骤省略 ...
  (tx) => appendTransactionMessageInstruction(
    getTransferSolInstruction({
      source: user1,
      destination: thirdAddress,
      amount: lamports(LAMPORTS_PER_SOL * 3n / 10n)
    }),
    tx
  )
);

一行即可完成批量 SOL 转账的场景封装,适合 DeFi、空投脚本、NFT 批量铸造等高并发案例。


8 常见问题速览

Q1 Web3.js 2.0 与 1.x 可以同时共存吗?
A 不可以。项目须迁移到 2.x,唯一的向下兼容方案是为旧项目保留独立工作区。

Q2 lamports 为什么要改成 BigInt?
A 70% 新增 bug 来自精度溢出。使用 BigInt 可避免 2^53 限制,确保 Solana Rust 合约 对齐 u64。

Q3 管道式写法会不会太长?
A 可以把重复步骤封装为 util 函数,依旧保持可读;团队内部可共享模块,微信搜索「Solana 2.0 模板库」获取更多示例。

Q4 生产环境节点如何选?
A 推荐使用专业 RPC。👉 点此配置高可用节点,享受低延迟 + 100万次每日免费请求

Q5 本地验证器连接失败怎么办?
A 检查 8899/8900 端口被占用;或直接替换成 Devnet 端点,命令仅需改动两行。

Q6 TypeScript 报错找不到模块?
A 确认 tsconfig.json 包含 "moduleResolution": "node",并运行 npm ci 还原依赖锁。


9 小结

通过本指南,你已掌握:

坚持链上交易安全第一,精确验证 every lamport。下一步可以尝试 PDA、SPL Token 转账,或将代码抽象为 CLI 工具正式发布。加油编码,祝你和 Solana 一起飞升!