在 Solana 上构建支付流程之前,你需要了解五个核心概念:钱包、稳定币、token account、手续费和交易。Solana 的支付模型与多币种支付系统高度契合:
| 传统支付模型 | Solana | 说明 |
|---|---|---|
| 客户 ID / 账号 | Wallet address | 账户持有人的唯一标识符 |
| 货币(USD、EUR) | Token Mint (USDG, USDC) | 被转移的资产类型 |
| 按币种余额 | Token Account (ATA) | 存储某一币种/资产的余额 |
就像银行客户有唯一身份但为每种货币分别持有余额一样,Solana 钱包也有一个地址,但每种资产都对应一个独立的 token account。下面我们来逐一解析这些组成部分。
钱包:发送方与接收方
每笔支付都涉及两方,每一方都由一个 wallet address
标识——一个唯一的 32 字节公钥(例如,7EcDhS...)。
- Sender:发起支付的钱包。必须拥有足够的稳定币账户余额并签署交易。
- Receiver:接收方钱包。无需签名,也不需要已有余额。
- Fee Payer:可选的手续费支付钱包。可用于补贴或实现仅限稳定币的用户间交易。
可以把钱包地址类比为银行账号:公开、安全、可分享,是收发资金的必要信息。
稳定币
在 Solana 上,稳定币被称为“token”。Token 代表网络上的一种资产类型。每个 token 都有一个唯一的“mint address”。在构建支付系统时,你需要引用这些 mint address 来标识你所操作的资产。以下是主网上常见的稳定币 mint:
| Token | Issuer | Mint Address |
|---|---|---|
| USDC | Circle | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
| USDT | Tether | Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB |
| PYUSD | PayPal | 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo |
| USDG | Paxos | 2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH |
如需了解更多关于 Solana 上稳定币的信息,请参阅 Stablecoins 解决方案页面。
接受付款时,请务必验证 mint 地址和 Token Program。 不同的 token 可能名称相同,但发行方和底层资产不同。
Token Account
钱包并不直接持有 token。相反,每个钱包对其持有的每种 token 都拥有一个 token account 的管理权限。付款时,token 会从发送方的 token account 转账到接收方同一 mint 的 token account:
Token Account
Associated Token Account(关联 token account)是与特定钱包和 mint 绑定的确定性 token account。给定钱包地址和 mint,ATA 地址始终唯一。
- 每个 mint 仅有一个 ATA。一个钱包对 USDC 有一个 ATA,对 USDT 也有一个,依此类推。
- 必须先存在才能接收。不能向不存在的 ATA 发送 token。
- 通常由发送方创建。如果接收方的 ATA 不存在,发送方可以在支付交易中创建。
import { findAssociatedTokenPda } from "@solana-program/token";const [receiverATA] = await findAssociatedTokenPda({mint: USDG_MINT_ADDRESS,owner: receiverWallet.address,tokenProgram: TOKEN_PROGRAM_ADDRESS});
Token Program
在 Solana 上,program 是用于管理账户状态的可执行逻辑。token account 由 Token Program 管理——链上的代码会原子性地验证转账并更新余额。
Solana 有两个 Token Program:
| Program | Address | 示例代币 使用此程序 |
|---|---|---|
| Token Program | TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA | USDC、USDT |
| Token-2022 | TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb | PYUSD、USDG |
Token-2022(也称为 "Token Extensions")增加了如转账钩子、转账手续费和隐私转账等功能。两种程序在基础转账操作上类似,但在派生 ATA 时必须使用正确的程序。
为什么这很重要
用于创建代币的 Token Program 决定了该代币的指令和账户状态。如果你使用了错误的程序,将无法转账该代币。
ATA 由三个输入派生而来:wallet + mint + token_program。使用错误的程序会生成完全不同的地址:
import {findAssociatedTokenPda,TOKEN_PROGRAM_ADDRESS} from "@solana-program/token";import { TOKEN_2022_PROGRAM_ADDRESS } from "@solana-program/token-2022";// USDC uses Token Programconst [usdcAta] = await findAssociatedTokenPda({mint: USDC_MINT,owner: walletAddress,tokenProgram: TOKEN_PROGRAM_ADDRESS // ✓ Correct});// ❌ This will produce a different address because it uses the wrong programconst [wrongUsdcAta] = await findAssociatedTokenPda({mint: USDC_MINT,owner: walletAddress,tokenProgram: TOKEN_2022_PROGRAM_ADDRESS // ❌ Wrong program});// PYUSD uses Token-2022const [pyusdAta] = await findAssociatedTokenPda({mint: PYUSD_MINT,owner: walletAddress,tokenProgram: TOKEN_2022_PROGRAM_ADDRESS // ✓ Correct});
用错误的程序派生 ATA 会生成无效地址。务必确保程序与代币的 mint 匹配。
转账指令同样适用此原则。每个 token program 都有自己的转账指令,必须调用正确的指令:
import { getTransferInstruction } from "@solana-program/token";import { getTransferInstruction as getTransferInstruction22 } from "@solana-program/token-2022";// For USDC (Token Program)const usdcTransferIx = getTransferInstruction({source: senderUsdcAta,destination: receiverUsdcAta,authority: senderWallet,amount: 1_000_000n // 1 USDC (6 decimals)});// For PYUSD (Token-2022)const pyusdTransferIx = getTransferInstruction22({source: senderPyusdAta,destination: receiverPyusdAta,authority: senderWallet,amount: 1_000_000n // 1 PYUSD (6 decimals)});// *Note*: Most token program JS Client functions include the ability// to specify the token program address. Generally, defining it is a// good practice to ensure you are fully aware of the program you are usingconst usdcTransferIx2 = getTransferInstruction({source: senderUsdcAta,destination: receiverUsdcAta,authority: senderWallet,amount: 1_000_000n // 1 USDC (6 decimals)},{ tokenProgram: TOKEN_PROGRAM_ADDRESS });
将转账指令发送到错误的程序会导致失败。程序会验证其是否拥有相关 token account——由 Token Program 创建的账户无法通过 Token-2022 转账,反之亦然。
要验证某个代币或 token account 使用的是哪个程序,可获取 mint 或 token
account 并检查其 owner 字段:
import { createSolanaRpc, address } from "@solana/kit";const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");const accountInfo = await rpc.getAccountInfo(address(mintAddress)).send();// The owner field tells you which program manages this tokenconst tokenProgram = accountInfo.value?.owner;// Returns: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA (Token Program)// or: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb (Token-2022)
对于支付应用,建议为每个支持的代币存储正确的程序地址:
const SUPPORTED_TOKENS = {USDC: {mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",program: TOKEN_PROGRAM_ADDRESS,decimals: 6},PYUSD: {mint: "2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo",program: TOKEN_2022_PROGRAM_ADDRESS,decimals: 6}};
Token Extensions
Token Extensions Program(Token 2022)通过额外的指令(称为 extensions)为 Token 提供了更多功能。Extensions 是可选功能,你可以为 token mint 或 token account 添加这些扩展功能。
如需了解更多 Token Extensions 相关信息,请参阅 Token Extensions 文档。
费用
Solana 支付包含最多三项费用组成部分:
| 费用类型 | SOL | 估算美元 | 发生时机 |
|---|---|---|---|
| 基础交易费 | 5,000 lamports* | ~$0.0007 | 每笔交易(可将多笔支付打包以摊销费用) |
| 优先费 | 浮动 | 浮动 | 可选;网络拥堵时可加速确认 |
| 账户创建(rent) | ~0.0029 SOL | ~$0.40 | 仅在创建新 token account 时收取 |
每笔支付总成本:大多数转账低于 $0.001。如需创建新 token account,总费用约为 $0.40。
Solana 采用本地费用市场——每个程序的交易只与目标相同状态的其他交易竞争。这意味着即使在网络其他部分高负载时,支付费用依然低且可预测。rent 成本也计划在近期降低 50%。
你可以完全抽象费用,让用户无需直接接触 SOL。实现方式请参见 Fee Abstraction。
交易与指令
在 Solana 上,交易是原子执行单元——要么全部操作成功,要么全部失败。每笔交易包含一个或多个指令,每个指令都是独立命令(如“转账 10 USDC”,“创建 token account”)。
一次典型的支付交易可能包含两个指令:如有需要,先创建收款方的 token account,然后转账 token。两步操作原子执行——不会出现部分完成的状态。正如你将在 支付处理 中看到的,你可以将多笔支付打包进一笔交易,以降低成本并提升吞吐量。
综合流程
一个典型的支付流程:
- 收集信息。获取发送方和接收方的钱包地址,以及所转账代币的 mint 地址。
- 推导 ATA。确定双方的代币账户。
- 构建并签名。构建包含必要转账指令的交易,并用发送方密钥签名。
- 发送并确认。交易将在一秒内完成结算。
下一步
* lamport 是 SOL 的最小单位,等于 0.000000001 SOL
Is this page helpful?