Solana Web3.js 速通指南:Connection、Transaction 与质押全流程

·

如果你正用 JavaScript 对接 Solana,这份 Web3.js 实战手册 能帮你少走弯路。示例覆盖连接集群、转账、创建密钥对、编写交易、质押 SOL、管理 Nonce 账户等高频场景,全部由 @solana/web3.js 官方 API 驱动,可直接复制到本地 Devnet 演练。


1. 建立 Connection:三行代码跑通 RPC

Connection 是一切交互的起点,设置集群端点与确认级别即可。

import { Connection, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection(clusterApiUrl("devnet"), "confirmed");

const slot = await connection.getSlot();
console.log("当前 Slot:", slot);

核心关键词:Connection、Solana Devnet、RPC 节点


2. 密钥对 Keypair:随机、种子、私钥三种方法一把抓

生成或恢复密钥对只需:

import { Keypair } from "@solana/web3.js";

// 随机
const account = Keypair.generate();

// 从种子(32字节)
const seed = new Uint8Array(32).fill(42);
const fromSeed = Keypair.fromSeed(seed);

// 从私钥
const fromSecret = Keypair.fromSecretKey(account.secretKey);
安全提示:种子与私钥等同,请离线保存,切勿上传至代码仓库。

3. PublicKey:地址派生与程序地址一次讲透

地址可以来自 Base58 字符串,也可官方派生程序地址:

import { PublicKey } from "@solana/web3.js";

const base58Key = new PublicKey("5xot9PVkphiX2adznghwrAuxGs2zeWisNSxMW6hU6Hkj");

const [programAddr] = await PublicKey.findProgramAddress(
  [Buffer.from("anchor")],
  base58Key
);

4. 构建 Transaction:转账 + 签名全流程演示

import {
  Transaction,
  SystemProgram,
  sendAndConfirmTransaction,
} from "@solana/web3.js";

const payer = Keypair.generate();
await connection.requestAirdrop(payer.publicKey, 1e9); // 1 SOL

const receiver = Keypair.generate().publicKey;

const ix = SystemProgram.transfer({
  fromPubkey: payer.publicKey,
  toPubkey: receiver,
  lamports: 1000,
});

const tx = new Transaction().add(ix);
await sendAndConfirmTransaction(connection, tx, [payer]);

5. 系统程序 SystemProgram:创建、分配、指派账户

除了转账,SystemProgram 还能分派账号给任意程序、初始化空白账号:

const newAccount = Keypair.generate();
const createAccIx = SystemProgram.createAccount({
  fromPubkey: payer.publicKey,
  newAccountPubkey: newAccount.publicKey,
  lamports: await connection.getMinimumBalanceForRentExemption(100),
  space: 100,
  programId: SystemProgram.programId,
});

6. Nonce 账户:离线构造交易的保险锁

Nonce 账户把当前区块 hash 缓存成固定值,避免交易过期。

const nonceKey = Keypair.generate();
await connection.requestAirdrop(payer.publicKey, 2e9);

const minLamports = await connection.getMinimumBalanceForRentExemption(
  80 // Nonce 账户占用
);

const createNonceTx = new Transaction().add(
  SystemProgram.createNonceAccount({
    fromPubkey: payer.publicKey,
    noncePubkey: nonceKey.publicKey,
    authorizedPubkey: payer.publicKey,
    lamports: minLamports,
  })
);
await sendAndConfirmTransaction(connection, createNonceTx, [payer, nonceKey]);

const nonceData = await connection.getNonce(nonceKey.publicKey, "confirmed");
console.log("Nonce 值:", nonceData.nonce);

7. 质押 SOL:StakeProgram 全攻略

创建质押账户委托、停用、提款,五步搞定:

import { StakeProgram, Authorized, Lockup } from "@solana/web3.js";

const stakeAccount = Keypair.generate();
const stakeAmount = 1 * 1e9 + // 质押的 SOL
  (await connection.getMinimumBalanceForRentExemption(StakeProgram.space));

const createStakeIx = StakeProgram.createAccount({
  fromPubkey: payer.publicKey,
  authorized: new Authorized(payer.publicKey, payer.publicKey),
  lockup: new Lockup(0, 0, payer.publicKey),
  lamports: stakeAmount,
  stakePubkey: stakeAccount.publicKey,
});

await sendAndConfirmTransaction(connection, new Transaction().add(createStakeIx), [
  payer,
  stakeAccount,
]);

// 选验证节点
const { current } = await connection.getVoteAccounts();
const votePubkey = new PublicKey(current[0].votePubkey);

const delegateIx = StakeProgram.delegate({
  stakePubkey: stakeAccount.publicKey,
  authorizedPubkey: payer.publicKey,
  votePubkey,
});
await sendAndConfirmTransaction(connection, new Transaction().add(delegateIx), [payer]);

8. Secp256k1 程序:把以太坊签名校验搬进 Solana

链上验证比特币 / 以太坊签名:

import { Secp256k1Program } from "@solana/web3.js";

const ethAddress = Buffer.alloc(20); // 实际来自 keccak
const sig = new Uint8Array(64);
const tx = new Transaction().add(
  Secp256k1Program.createInstructionWithEthAddress({
    ethAddress: ethAddress.toString("hex"),
    plaintext: Buffer.from("Hello Solana"),
    signature: sig,
    recoveryId: 0,
  })
);

9. Message & Struct:低层玩法,构建离线交易

Message 用于构造可在浏览器以外签名的交易:

const msg = new Message({
  accountKeys: [payer.publicKey.toString(), receiver.toString(), SystemProgram.programId.toString()],
  header: {
    numRequiredSignatures: 1,
    numReadonlySignedAccounts: 0,
    numReadonlyUnsignedAccounts: 1,
  },
  instructions: [
    {
      accounts: [0, 1],
      data: Buffer.from([2, ...]), // transfer 指令二进制
      programIdIndex: 2,
    },
  ],
  recentBlockhash: (await connection.getLatestBlockhash()).blockhash,
});

const txFromMsg = Transaction.populate(msg, [payer.publicKey.toString()]);

10. Rust ↔ JS 边界:Struct & Enum 互相映射

Solidity 碰到结构体和枚举会头大,但在 Solana 只要用 Borsh

// Rust
pub struct Price { price: u64 }

// JS
import { Struct } from "@solana/web3.js";
export class Price extends Struct<{ price: BN }> {}

常见问题 FAQ

Q1:用 Mainnet 会不会被反撸手续费?
A:先在 Devnet 跑示例,确认无误再切 Mainnet,还可以申请 devnet SOL 无限复用体验 👉 点击领取最新空投水龙头

Q2:getRecentBlockhash 已被弃用怎么办?
A:改调用 getLatestBlockhash;两者结构相同,切换一行即可。

Q3:Nonce 账号必须租用吗?
A:必须。Nonce 数据占用约 80 字节,需满足租金豁免门槛;停用后可赎回。

Q4:如何把一个地址标记为“只读”?
A:Transaction Header 里的 numReadonlySignedAccountsnumReadonlyUnsignedAccounts 控制。

Q5:Keypair.generate 可重复吗?
A:随机种子熵源自操作系统,理论碰撞概率极低。如需可复现,使用 fromSeed

Q6:质押年化收益是多少?
A:取决于验证节点绩效和网络通胀参数,Solana explorer 实时可查。也可 👉 在线计算器速查


结语

通读 10 步示例,你已掌握 Web3.js 操作 Solana 的核心链路:连接 → 密钥 → 转账 → 高级账户 → 质押。把代码复制到本地 npm init && npm i @solana/web3.js,马上开启高性能链上开发之旅。