生产环境准备

在本地构建并在 devnet 上测试是开始使用 Solana 支付的好方法。然而,当你准备部署到主网时,需要注意主网的一些细节。devnet 可以容忍错误,而主网则不行。本指南将介绍关键差异,帮助你的用户获得流畅的体验。

DevnetMainnet
可以通过水龙头免费获取 SOL获取真实 SOL 用于支付手续费
区块空间竞争小优先费很重要
交易容易确认交易配置至关重要
公共 RPC 可用生产环境需使用专用 RPC
Devnet 密钥对和代币铸造主网需使用不同的密钥和代币铸造——请更新你的配置

RPC 基础设施

公共端点api.mainnet.solana.com)受速率限制且无服务级别协议。它们适合用于 开发,但无法支撑生产环境中的支付流程——就像试图通过一个没有正常运行时间保障的共享 API 来运行支付处理器一样。

切勿在生产环境中使用公共 RPC

请使用 专用 RPC 服务商 以获得可靠、低延迟的访问。

选择 RPC 服务商时,请关注:

  • 可靠性:具备高可用性 SLA(99.9% 及以上)
  • 延迟:靠近用户的地理位置
  • 功能:交易落地、索引、优先费 API 等功能

完整的 RPC 服务商列表请参见 RPC 基础设施服务商 指南。

冗余 RPC 配置

和其他网络服务商一样,RPC 服务商也可能出现宕机或性能下降。为了确保你的应用具备弹性,建议配置多个 RPC 服务商。

Solana Kit 提供了一个用于自定义 RPC 传输的库,可以让你构建自己的冗余 RPC 客户端。以下是一个使用该库构建冗余 RPC 客户端的示例:

import { RpcTransport } from "@solana/rpc-spec";
import { RpcResponse } from "@solana/rpc-spec-types";
import { createHttpTransport } from "@solana/rpc-transport-http";
// Create a transport for each RPC server
const transports = [
createHttpTransport({ url: "https://mainnet-beta.my-server-1.com" }),
createHttpTransport({ url: "https://mainnet-beta.my-server-2.com" }),
createHttpTransport({ url: "https://mainnet-beta.my-server-3.com" })
];
// Create a wrapper transport that distributes requests to them
let nextTransport = 0;
async function roundRobinTransport<TResponse>(
...args: Parameters<RpcTransport>
): Promise<RpcResponse<TResponse>> {
const transport = transports[nextTransport];
nextTransport = (nextTransport + 1) % transports.length;
return await transport(...args);
}

如果你不想自己构建路由工具,可以利用第三方服务,例如 Iron Forge,来为你处理路由。

交易落地

在 Devnet 上,交易通常可以较容易地落地。而在 Mainnet 上,你需要与他人竞争区块空间。为了提高你的交易被包含进区块的概率,你应确保正确组装交易,包括:

  • 在发送交易前包含一个新的 blockhash
  • 在交易中加入带有有竞争力优先费用的优先费用指令
  • 在交易中加入基于预估计算单元需求的计算单元限制指令

此外,你还可以考虑使用 Jito Bundles 等其他工具,以进一步提升交易被包含进区块的概率。我们接下来将更详细地介绍这些工具。

交易发送配置

在 Mainnet 上发送交易时,配置以下参数以获得最佳落地率:

Blockhash 管理:

  • 使用 confirmed commitment 获取
  • 存储 lastValidBlockHeight,该值由 getLatestBlockhash 返回——它会告诉你交易何时过期
  • blockhash 大约在 150 个区块后(约 60-90 秒)过期

发送选项:

  • maxRetries: 0 — 禁用自动 RPC 重试。请自行处理重试,以便在需要时刷新 blockhash。
  • skipPreflight: true — 发送前跳过模拟。当你已验证交易并希望获得最低延迟时使用。在开发阶段,保持 false 以便及早发现错误。
import { createSolanaRpc } from "@solana/kit";
const rpc = createSolanaRpc(process.env.RPC_URL!);
// 1. Get blockhash with confirmed commitment
const { value: latestBlockhash } = await rpc
.getLatestBlockhash({ commitment: "confirmed" })
.send();
// 2. Build and sign your transaction with the blockhash
// ... (transaction building code)
// 3. Send with production settings
const signature = await rpc
.sendTransaction(encodedTransaction, {
encoding: "base64",
maxRetries: 0n, // Handle retries yourself
skipPreflight: true, // Skip simulation for speed (use false during dev)
preflightCommitment: "confirmed"
})
.send();
// 4. Track expiration using lastValidBlockHeight
const { lastValidBlockHeight } = latestBlockhash;
// Stop retrying when current block height exceeds lastValidBlockHeight

使用优先费用

每笔 Solana 交易都需要支付交易手续费,费用以 SOL 结算。交易手续费分为两部分:基础费用和优先费用。基础费用用于补偿验证者处理交易。优先费用是可选的,支付后可以提高当前 leader 处理你交易的概率。你可以把它理解为“加急快递”:支付更多费用,获得更快、更可靠的处理。

费用运作方式:

Total fee = Base fee (5,000 lamports per signature) + Priority fee
Priority fee = Compute units x Price per unit (micro-lamports per compute unit)

实际费用示例:

  • 简单的 USDC 转账:正常情况下约 $0.001-0.005
  • 拥堵时:约 $0.01-0.05
  • 高峰拥堵:可能更高

示例实现:

@solana-program/compute-budget 包提供了一个辅助函数,可以轻松地为交易更新或添加计算单元价格(以微 lamports 计)的指令。

import { updateOrAppendSetComputeUnitPriceInstruction } from "@solana-program/compute-budget";
const tx = pipe(
createTransactionMessage({ version: 0 }),
(m) => setTransactionMessageFeePayerSigner(payer, m),
(m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
(m) => appendTransactionMessageInstructions([myInstructions], m),
(m) => updateOrAppendSetComputeUnitPriceInstruction(1000n as MicroLamports, m)
);

获取费用估算: 大多数 RPC 服务商都提供优先费用 API:

完整的费用机制请参见 Transaction Fees 以及我们的指南:如何为交易添加优先费用

优化计算单元

在 Solana 上,计算量实际上衡量的是程序执行的工作量。每笔交易都有计算单元的上限(目前为 140 万计算单元),每个账户每个区块也有计算单元的上限(目前为 1 亿计算单元)。

提交交易时,你需要预估将会用到的计算单元数量,并相应设置计算单元上限——这实际上是请求为你的交易预留多少总容量。实际操作中,准确预估交易所需的计算单元对于交易能否被打包进区块至关重要(同时也影响优先费用的管理)。

Solana JSON RPC API 提供了一个 simulatetransaction 方法,可用于估算交易所需的计算单元,其中包括对将使用的计算单元的估算。 @solana/kit 提供了辅助函数,可在一步内估算交易的资源限制并将其设置在消息中(底层使用 simulatetransaction 方法)。对于版本 1 的交易,这些辅助函数还会估算已加载账户的数据大小限制。

import {
estimateResourceLimitsFactory,
estimateAndSetResourceLimitsFactory
} from "@solana/kit";
const estimateResourceLimits = estimateResourceLimitsFactory({ rpc });
const estimateAndSetResourceLimits = estimateAndSetResourceLimitsFactory(
estimateResourceLimits
);
const txWithResourceLimits = await estimateAndSetResourceLimits(tx);

如果您使用 kit 插件客户端构建并发送交易,通常无需此步骤——客户端在发送时会自动为您添加计算预算指令(.sendTransaction())。上述手动流程适用于直接使用 @solana/kit 组装交易的场景。

在生产环境中,如果您需要多次重复执行相同类型的交易,建议缓存该交易类型的计算量估算值,以避免每次都重新估算计算单元所带来的额外开销。

Jito 捆绑包

Jito 捆绑包是一种用于管理多笔交易原子性执行的工具。其实现方式是向 Jito 网络发送多笔交易并附带小费。小费可用于激励 Jito 网络将您的交易纳入区块中。

相关资源:

重试策略

交易可能因多种原因而失败。与传统支付 API 立即返回成功或失败不同,区块链交易需要持续跟踪确认状态。

核心概念:

  • 区块哈希过期:交易有效期约为 ~150 个区块(约 60–90 秒)
  • 幂等性:相同的已签名交易始终产生相同的签名——重新提交是安全的
  • 指数退避:避免频繁重试对网络造成过大压力
import {
createSolanaRpc,
createSolanaRpcSubscriptions,
sendAndConfirmTransactionFactory,
isSolanaError,
SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED
} from "@solana/kit";
const rpc = createSolanaRpc(process.env.RPC_URL!);
const rpcSubscriptions = createSolanaRpcSubscriptions(process.env.RPC_WSS_URL!);
const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
rpc,
rpcSubscriptions
});
// Send with automatic confirmation tracking and block height monitoring
try {
await sendAndConfirmTransaction(signedTransaction, {
commitment: "confirmed",
// Optional: abort after 75 seconds
abortSignal: AbortSignal.timeout(75_000)
});
} catch (e) {
if (isSolanaError(e, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {
// Blockhash expired—rebuild transaction with fresh blockhash and retry
rebuildAndRetryTransaction(); // implement your own logic for rebuilding and retrying the transaction
}
throw e;
}

sendAndConfirmTransactionFactory 来自 @solana/kit,可自动处理确认轮询和区块高度跟踪。当交易的 blockhash 过期时,它会抛出 SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED,提示您需要使用新的 blockhash 重新构建交易。

其他资源

了解确认级别

Solana 提供三种确认级别。以传统金融术语来表述:

级别Solana 定义传统等价概念适用场景
processed已打包入块,尚未投票待授权实时 UI 更新
confirmed超级多数已投票资金已清算大多数支付场景
finalized已固化,不可逆资金已结算高价值交易、合规场景

各级别的使用时机:

  • UI 更新:显示 processed 以提供即时反馈("支付已提交")
  • 为用户账户充值:等待 confirmed(适用于大多数交易)
  • 发货实物商品:等待 finalized
  • 大额提现:等待 finalized
  • 合规/审计:始终记录 finalized 状态

有关检查交易状态的更多信息,请参阅 与 Solana 交互

错误处理

Solana Kit 通过 isSolanaError() 提供类型化错误。请使用具体的错误码而非字符串匹配:

import {
isSolanaError,
SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED,
SOLANA_ERROR__TRANSACTION_ERROR__INSUFFICIENT_FUNDS_FOR_FEE,
SOLANA_ERROR__TRANSACTION_ERROR__BLOCKHASH_NOT_FOUND,
SOLANA_ERROR__INSTRUCTION_ERROR__INSUFFICIENT_FUNDS
} from "@solana/kit";
function handlePaymentError(error: unknown): {
message: string;
retryable: boolean;
} {
// Blockhash expired—rebuild and retry
if (
isSolanaError(error, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED) ||
isSolanaError(error, SOLANA_ERROR__TRANSACTION_ERROR__BLOCKHASH_NOT_FOUND)
) {
return { message: "Transaction expired—rebuilding", retryable: true };
}
// Insufficient SOL for fees
if (
isSolanaError(
error,
SOLANA_ERROR__TRANSACTION_ERROR__INSUFFICIENT_FUNDS_FOR_FEE
)
) {
return { message: "Not enough SOL for fees", retryable: false };
}
// Insufficient token balance
if (
isSolanaError(error, SOLANA_ERROR__INSTRUCTION_ERROR__INSUFFICIENT_FUNDS)
) {
return { message: "Insufficient balance", retryable: false };
}
// Unknown error
console.error("Payment error:", error);
return { message: "Payment failed—please retry", retryable: true };
}

常见错误码:

错误码原因恢复方式
BLOCK_HEIGHT_EXCEEDEDBlockhash 已过期使用新的 blockhash 重新构建交易
BLOCKHASH_NOT_FOUNDBlockhash 未找到使用新的 blockhash 重新构建交易
INSUFFICIENT_FUNDS_FOR_FEESOL 余额不足为付费账户充值或使用费用抽象
INSUFFICIENT_FUNDS代币余额不足用户需要增加余额
ACCOUNT_NOT_FOUNDtoken account 不存在在交易中创建 ATA

无Gas交易

用户希望使用稳定币支付,而不是为网络费用购买SOL。无Gas交易解决了这一问题——类似于Venmo用户无需关心ACH手续费。完整实现方式请参阅费用抽象

安全性

密钥管理

  • 切勿在前端代码中暴露私钥。 请使用后端签名、硬件钱包、多签钱包或密钥管理服务。
  • 分离热钱包与冷钱包。 热钱包用于日常操作,冷钱包用于资金储备。
  • 备份所有生产环境密钥。 将加密备份存储在多个安全位置。丢失密钥意味着永久失去访问权限。
  • 为开发网和主网使用不同的密钥。 开发网密钥不应与主网密钥相同。使用基于环境的配置,确保每个网络加载对应的正确密钥。

签名基础设施

对于生产环境的后端签名,推荐使用 Keychain——这是一个统一的签名库,通过单一接口抽象多种密钥管理后端,支持:Memory、Vault、Privy、Turnkey、AWS KMS、Fireblocks、GCP KMS、CDP、Para、Dfns、Crossmint、Openfort 和 Utila。这使您可以在本地使用内存密钥进行开发,然后无需修改应用代码即可切换到生产级后端。

不确定哪种后端适合您?请参阅选择后端。Keychain 同时支持 RustTypeScript

RPC 安全

将 RPC 端点视为 API 密钥——不要在前端代码中暴露它们,因为它们可能被提取并滥用。使用后端代理或环境变量,确保不会被打包到客户端代码中。

监控

在生产环境中跟踪以下指标:

指标原因
交易成功率及早发现问题
确认延迟监控网络健康状况
优先费用支出成本管理
RPC 错误率提供商健康状况

为以下情况设置警报:

  • 超过阈值的资金库转账
  • 失败交易率激增
  • 异常的接收方模式
  • RPC 错误率上升

要了解大规模实时交易监控,请参阅我们的索引指南

验证地址

每个代币和程序在主网上都有唯一正确的地址。模仿 USDC 或其他稳定币的欺诈代币很常见——它们会有相同的名称和符号,但铸币地址不同。您的应用程序应该硬编码或将铸币地址加入白名单(根据您的要求),绝不要从不可信来源动态接受它们。

基于环境的配置: Devnet 和 Mainnet 通常使用完全不同的代币铸造地址。请配置您的应用程序以根据不同环境加载正确的地址——不要硬编码主网地址并在测试时忘记切换,更糟糕的是,将开发网地址发布到生产环境。

一些常见的稳定币铸造地址包括:

代币发行方铸造地址
USDCCircleEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
USDTTetherEs9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB
PYUSDPayPal2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo
USDGPaxos2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH

程序地址同样重要。向错误的程序发送指令将导致失败——或者更糟的是,造成资金不可逆转的损失。Token Program 的地址为:

程序地址
Token ProgramTokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
Token-2022 ProgramTokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb

将正确的地址加入白名单可防止伪造代币,但无法防止发送到错误类型的账户。收款地址可以是钱包、token account、铸币账户或程序,每种类型需要不同的处理方式。将原生 SOL 发送到钱包以外的任何地址都会使资金脱离发送方的控制——发送到铸币账户或程序将直接丢失,发送到 token account 则只能由账户所有者找回——且不会有交易失败的提示来警告用户。

发送前验证收款方

在签署转账之前,请对每个收款地址进行分类。请参阅验证地址,获取完整的决策树和参考代码,用于区分钱包、token account、铸币账户和程序。

上线前检查清单

  • 已获取主网 SOL 用于手续费和 rent
  • 已配置生产环境 RPC(非公共端点)
  • 已配置备用 RPC 端点
  • 已实现动态定价的优先费用
  • 重试逻辑可处理区块哈希过期问题
  • 确认级别与使用场景相匹配
  • 所有常见错误均已妥善处理
  • 已配置无 Gas 模式(如适用)
  • 已验证主网代币地址(非开发网铸币账户)
  • 发送前已验证收款地址(钱包 vs token account vs 铸币账户 vs 程序)
  • 所有密钥已安全备份
  • 已审查密钥管理方案(前端不存储密钥)
  • 交易监控与告警已启用
  • 已按预期负载完成压力测试

部署程序

如果您正在部署自定义 Solana 程序作为支付基础设施的一部分,则需要考虑一些额外的事项。

部署前准备

  • Solana CLI 版本: 确保您使用的是最新版本的 Solana CLI
  • 程序 keypair: 您的程序在主网上的地址与开发网(devnet)不同(除非您重用相同的 keypair)。请更新应用配置中的所有相关引用。将您的程序 keypair 存储在安全位置(请注意,运行 cargo clean 可能会删除您的程序 keypair)。
  • 初始化账户: 如果您的程序需要管理员账户、PDA 或其他状态账户,请确保在用户与您的应用交互之前,这些账户已在主网上创建完毕。程序所需的任何 Associated Token Accounts(ATA)同样如此。

部署流程

  • 缓冲账户: 大型程序通过缓冲账户进行部署。solana program deploy 命令会自动处理此过程,但请注意部署并非原子操作——若部署中断,您可能需要恢复或关闭缓冲账户。请参阅 部署程序
  • 升级权限: 决定您的程序在上线后是否支持升级。若要实现不可变性,请在部署后撤销升级权限;若需保留灵活性,请妥善保管升级权限密钥。
  • 租金: 确保您的部署钱包中有足够的 SOL,以覆盖所有 program account 的免租最低余额要求。
  • 验证: 验证您的程序,确保您部署到 Solana 网络上的可执行程序与代码仓库中的源代码一致。

有关程序部署的完整指南,请参阅 部署程序

Is this page helpful?

©️ 2026 Solana 基金会版权所有