تتطلب كل معاملة على سولانا عملة SOL لدفع رسوم الشبكة. لكن المستخدمين القادمين إلى تطبيق الدفع الخاص بك يتوقعون التعامل بالعملات المستقرة - وليس إدارة رصيد رمز ثانٍ. يزيل تجريد الرسوم هذا الاحتكاك من خلال قيام شخص آخر بدفع الرسوم.
يغطي هذا الدليل مستويين:
- كيفية عمل رعاية الرسوم — البنية الأساسية لسولانا
- تجريد الرسوم على نطاق واسع باستخدام Kora — خدمة تجريد رسوم جاهزة للإنتاج
كيفية عمل رعاية الرسوم
تحتوي معاملات سولانا على دافع رسوم محدد - الحساب الذي يدفع رسوم الشبكة. افتراضيًا، هذا هو الموقّع الأول. لكن يمكنك تحديد حساب مختلف كدافع للرسوم، مما يسمح لطرف ثالث ("الراعي") بتغطية الرسوم نيابة عن المرسل.
يجب على كل من المرسل والراعي التوقيع على المعاملة:
- يوقع المرسل للترخيص بنقل رموزه
- يوقع الراعي للترخيص بدفع رسوم الشبكة
راجع كيفية عمل المدفوعات على سولانا لمفاهيم الدفع الأساسية.
توضح الخطوات أدناه التدفق الأساسي. راجع العرض التوضيحي للحصول على كود كامل قابل للتشغيل.
إنشاء حساب راعٍ
قم بإنشاء زوج مفاتيح منفصل للراعي الذي سيدفع رسوم المعاملات. يحتاج الراعي إلى SOL للرسوم لكنه لا يحتاج إلى الاحتفاظ بالرموز التي يتم نقلها.
إنشاء تعليمات النقل
قم بإنشاء تعليمات نقل الرمز مع المرسل كسلطة. يمتلك المرسل الرموز ويجب عليه التوقيع على النقل.
الإرسال مع الممول كدافع للرسوم
أنشئ العميل مع تعيين الجهة الراعية كمدفوع الرسوم عبر payer(sponsor)، ثم استدعِ
client.sendTransaction. يقوم الراعي بالتوقيع لدفع رسوم الشبكة بينما يوقّع
المُرسِل للموافقة على التحويل—يجمع sendTransaction جميع الموقّعين المشار إليهم
تلقائيًا.
عرض توضيحي
// Generate keypairs for sender, recipient, and sponsor (fee payer)const sender = await generateKeyPairSigner();const recipient = await generateKeyPairSigner();const sponsor = await generateKeyPairSigner();console.log("Sender Address:", sender.address);console.log("Recipient Address:", recipient.address);console.log("Sponsor Address (Fee Payer):", sponsor.address);// Demo Setup: Create client, mint account, token accounts, and fund with initial tokensconst { client, mint } = await demoSetup(sender, recipient, sponsor);console.log("\nMint Address:", mint.address);// Derive the Associated Token Accounts addresses (ATAs) for sender and recipientconst [senderAta] = await findAssociatedTokenPda({mint: mint.address,owner: sender.address,tokenProgram: TOKEN_2022_PROGRAM_ADDRESS});const [recipientAta] = await findAssociatedTokenPda({mint: mint.address,owner: recipient.address,tokenProgram: TOKEN_2022_PROGRAM_ADDRESS});console.log("Sender Token Account:", senderAta.toString());console.log("Recipient Token Account:", recipientAta.toString());// =============================================================================// Sponsored Token Payment Demo// =============================================================================// Create instruction to transfer tokens from sender to recipient// Transferring 250,000 base units = 0.25 tokens (with 6 decimals)const transferInstruction = getTransferCheckedInstruction({source: senderAta,mint: mint.address,destination: recipientAta,authority: sender, // Sender signs to authorize the transferamount: 250_000n, // 0.25 tokensdecimals: 6});// Send transaction with sponsor as fee payer using @solana/kit// The sponsor (client.payer) pays fees; the sender signs for the transferconst { context } = await client.sendTransaction([transferInstruction]);const signature = context.signature;console.log("\n=== Sponsored Token Payment Complete ===");console.log("Transaction Signature:", signature.toString());// Fetch final token account balances from the RPCconst senderBalance = await client.rpc.getTokenAccountBalance(senderAta).send();const recipientBalance = await client.rpc.getTokenAccountBalance(recipientAta).send();console.log("\nSender Token Account Balance:", senderBalance.value.uiAmount);console.log("Recipient Token Account Balance:",recipientBalance.value.uiAmount);// Fetch transaction detailsconst transaction = await client.rpc.getTransaction(signature, {encoding: "jsonParsed",maxSupportedTransactionVersion: 0}).send();const feePayer = transaction?.transaction.message.accountKeys?.[0];console.log("\nNote: The first account in accountKeys is always the fee payer");console.log("Fee Payer Address:", feePayer);// =============================================================================// Demo Setup Helper Function// =============================================================================
عندما تنشئ حساب رمز لمستخدم نهائي، يمكنه إغلاقه واستعادة SOL المستخدم للإيجار. فكر في فرض رسوم على المستخدمين مقابل إنشاء الحساب بالعملات المستقرة، أو ضع هذه التكلفة في الاعتبار ضمن اقتصاديات منتجك.
تجريد الرسوم على نطاق واسع مع Kora
بدائية دافع الرسوم قوية، لكن بناء نظام بدون رسوم للإنتاج يتطلب المزيد: إدارة محافظ الممولين، والتعامل مع تحويلات الرموز (حتى يتمكن المستخدمون من "دفع" الرسوم بـ USDC)، وتحديد المعدل، وضوابط الأمان.
Kora تتعامل مع هذا التعقيد. إنه خادم JSON-RPC يوفر تجريد الرسوم بحيث لا يحتاج المستخدمون أبدًا إلى SOL. يمكنك رعاية الرسوم بالكامل أو قبول دفع الرسوم بأي رمز مميز.
انشر Kora بأمر واحد:
cargo install kora-clikora --config path/to/kora.toml rpc start --signers-config path/to/signers.toml
ثم وجِّه عميل Kit إلى خادم Kora الخاص بك وأرسل المعاملات باستخدام نفس واجهة برمجة التطبيقات المستخدمة أعلاه:
pnpm add @solana/kora
import { address } from "@solana/kit";import { createKitKoraClient } from "@solana/kora";// A Kora-backed Kit client: Kora is the fee payer, and users pay// fees in the SPL token of your choice instead of SOLconst kora = await createKitKoraClient({endpoint: "https://your-kora-instance",rpcUrl: "https://api.mainnet-beta.solana.com",feeToken: address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"), // USDCfeePayerWallet: sender // Signs to authorize the token fee payment});// Same instruction, same call—Kora sponsors the network feeconst { context } = await kora.sendTransaction([transferInstruction]);console.log("Signature:", context.signature);
موارد Kora
Is this page helpful?