المدفوعاتالاشتراكات

التفويض المتكرر

يتيح التفويض المتكرر للمستخدم الموافقة على محفظة أو خدمة أخرى لسحب مبلغ يصل إلى حد معين يتم إعادة تعيينه في كل فترة.

يُبقي هذا الدليل الأجزاء المتحركة مرئية. تقوم باشتقاق الحسابات أولاً، ثم تهيئة سلطة الاشتراك إذا لزم الأمر، وإنشاء التفويض المتكرر، ثم استخدام PDA الخاص بذلك التفويض للتحويلات.

التثبيت

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

إنشاء التفويض

يتكون الإعداد من أربعة أجزاء:

  1. إنشاء عميل مع الموقّع المستخدم وإضافة الاشتراكات.
  2. اشتقاق حساب الرمز المميز للمستخدم، و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 رمز مميز.
  • يرفض البرنامج عمليات النقل التي تتجاوز المخصص المتبقي للفترة الحالية.
  • بمجرد بدء الفترة التالية، يُعاد ضبط المبلغ المسحوب.
  • expiryTs هو حد صارم: بمجرد تجاوزه، تفشل عمليات النقل ويمكن للراعي استرداد rent. لا توجد فترة سماح للإنفاق.
  • اضبط startTs على 0 لبدء التفويض عند تسجيل المعاملة على السلسلة بدلاً من وقت محدد. يُوسّع هذا النافذة الزمنية لإتاحة الفرصة للمستخدم للتوقيع والانضمام. عند القيام بذلك، يجب أن يكون expiryTs غير صفري — لا يمكن للتفويض الذي يبدأ عند التسجيل أن يُعيَّن كذلك ليلا ينتهي أبدًا.
  • يوقّع المستخدم على معاملات الإعداد والإلغاء. يوقّع المفوَّض إليه على معاملات النقل.

Is this page helpful?

جدول المحتويات

تعديل الصفحة