支付订阅

周期性委托

周期性委托允许用户批准另一个钱包或服务在每个周期内提取不超过限额的资金。

本指南保持各个组成部分的可见性。您首先派生账户,如有需要则初始化订阅授权,创建周期性委托,然后使用该委托 PDA 进行转账。

安装

pnpm add @solana/subscriptions @solana/kit @solana/kit-plugin-rpc @solana/kit-plugin-signer @solana-program/token

创建委托

设置包含四个部分:

  1. 使用用户签名者和订阅插件创建客户端。
  2. 派生用户的 token account、订阅授权 PDA 和周期性委托 PDA。
  3. 如果订阅授权尚不存在,则初始化它。
  4. 使用周期金额、周期长度、开始时间和到期时间创建周期性委托。
import { address, createClient } from '@solana/kit';
import { solanaLocalRpc } from '@solana/kit-plugin-rpc';
import { signer } from '@solana/kit-plugin-signer';
import { findAssociatedTokenPda, TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
import {
fetchMaybeSubscriptionAuthority,
findRecurringDelegationPda,
findSubscriptionAuthorityPda,
subscriptionsProgram,
} from '@solana/subscriptions';
const client = createClient()
.use(signer(userSigner))
.use(solanaLocalRpc({ rpcUrl: 'http://127.0.0.1:8899' }))
.use(subscriptionsProgram());
const tokenMint = address('TOKEN_MINT_ADDRESS_HERE');
const delegatee = address('DELEGATEE_WALLET_ADDRESS_HERE');
const now = BigInt(Math.floor(Date.now() / 1000));
const nonce = 0n;
const amountPerPeriod = 1_000_000n;
const periodLengthS = 86_400n;
const startTs = now;
const expiryTs = now + periodLengthS * 30n;
const [userAta] = await findAssociatedTokenPda({
mint: tokenMint,
owner: userSigner.address,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
});
const [subscriptionAuthorityPda] = await findSubscriptionAuthorityPda({
user: userSigner.address,
tokenMint,
});
const [delegationPda] = await findRecurringDelegationPda({
subscriptionAuthority: subscriptionAuthorityPda,
delegator: userSigner.address,
delegatee,
nonce,
});
const subscriptionAuthority = await fetchMaybeSubscriptionAuthority(
client.rpc,
subscriptionAuthorityPda,
);
if (!subscriptionAuthority.exists) {
await client.subscriptions.instructions
.initSubscriptionAuthority({
tokenMint,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
userAta,
})
.sendTransaction();
}
await client.subscriptions.instructions
.createRecurringDelegation({
tokenMint,
delegatee,
nonce,
amountPerPeriod,
periodLengthS,
startTs,
expiryTs,
})
.sendTransaction();

从委托进行转账

被委托方对每笔转账进行签名。程序会检查当前周期,并拒绝超出该周期剩余额度的转账。

const receiverAta = address('RECEIVER_TOKEN_ACCOUNT_ADDRESS_HERE');
await client.subscriptions.instructions
.transferRecurring({
delegatee: delegateeSigner,
delegator: userSigner.address,
delegatorAta: userAta,
tokenMint,
delegationPda,
amount: 100_000n,
receiverAta,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
})
.sendTransaction();

撤销委托

委托人可以随时撤销定期委托。撤销操作会关闭委托 PDA 并将其租金返还给签名者。

await client.subscriptions.instructions
.revokeDelegation({
authority: userSigner,
delegationAccount: delegationPda,
})
.sendTransaction();

注意事项

  • amountPerPeriod 以基本单位计算。对于 6 位小数的代币,1_000_000 表示 1 个代币。
  • 程序会拒绝超过当前周期剩余额度的转账。
  • 一旦下一个周期开始,已提取金额将重置。
  • 用户对设置和撤销交易进行签名。受委托方对转账进行签名。

Is this page helpful?

Table of Contents

Edit Page
©️ 2026 Solana 基金会版权所有