Setiap transaksi Solana memerlukan SOL untuk membayar biaya jaringan. Namun pengguna yang datang ke aplikasi pembayaran Anda mengharapkan untuk bertransaksi dalam stablecoin—bukan mengelola saldo token kedua. Abstraksi biaya menghilangkan hambatan ini dengan meminta orang lain membayar biayanya.
Panduan ini mencakup dua tingkat:
- Cara kerja sponsorship biaya — primitif Solana yang mendasarinya
- Abstraksi biaya dalam skala besar dengan Kora — layanan abstraksi biaya yang siap produksi
Cara kerja sponsorship biaya
Transaksi Solana memiliki pembayar biaya yang ditentukan—akun yang membayar biaya jaringan. Secara default, ini adalah penandatangan pertama. Namun Anda dapat menentukan akun yang berbeda sebagai pembayar biaya, memungkinkan pihak ketiga ("sponsor") untuk menanggung biaya atas nama pengirim.
Baik pengirim maupun sponsor harus menandatangani transaksi:
- Pengirim menandatangani untuk mengotorisasi transfer token mereka
- Sponsor menandatangani untuk mengotorisasi pembayaran biaya jaringan
Lihat Cara kerja pembayaran di Solana untuk konsep pembayaran inti.
Langkah-langkah di bawah ini menunjukkan alur inti. Lihat Demo untuk kode lengkap yang dapat dijalankan.
Buat akun sponsor
Buat keypair terpisah untuk sponsor yang akan membayar biaya transaksi. Sponsor memerlukan SOL untuk biaya tetapi tidak perlu memegang token yang sedang ditransfer.
Buat instruksi transfer
Buat instruksi transfer token dengan pengirim sebagai otoritas. Pengirim memiliki token dan harus menandatangani transfer.
Kirim dengan sponsor sebagai pembayar biaya
Gunakan prepareAndSend dengan authority (pengirim yang menandatangani
transfer) dan feePayer (sponsor yang membayar biaya). Keduanya harus
menandatangani transaksi.
Demo
// Generate keypairs for sender, recipient, and sponsor (fee payer)const sender = (await generateKeypair()).signer;const recipient = (await generateKeypair()).signer;const sponsor = (await generateKeypair()).signer;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 = getTransferInstruction({source: senderAta,destination: recipientAta,authority: sender, // Pass signer, not just addressamount: 250_000n // 0.25 tokens});// Prepare and send transaction with sponsor as fee payer using @solana/client// The sponsor pays transaction fees, sender signs for the transferconst signature = await client.transaction.prepareAndSend({authority: sender, // Sender signs the transfer instructionfeePayer: sponsor, // Sponsor pays the transaction fees (different account)instructions: [transferInstruction],version: 0});console.log("\n=== Sponsored Token Payment Complete ===");console.log("Transaction Signature:", signature.toString());// Fetch final token account balances using @solana/client SPL token helperconst splToken = client.splToken({mint: mint.address,tokenProgram: "auto"});const senderBalance = await splToken.fetchBalance(sender.address);const recipientBalance = await splToken.fetchBalance(recipient.address);console.log("\nSender Token Account Balance:", senderBalance);console.log("Recipient Token Account Balance:", recipientBalance);// Fetch transaction detailsconst transaction = await client.runtime.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// =============================================================================
Ketika Anda membuat token account untuk pengguna akhir, mereka dapat menutupnya dan mengklaim kembali SOL yang digunakan untuk rent. Pertimbangkan untuk menagih pengguna untuk pembuatan akun dalam stablecoin, atau masukkan biaya ini ke dalam ekonomi produk Anda.
Abstraksi biaya dalam skala besar dengan Kora
Primitif pembayar biaya sangat powerful, tetapi membangun sistem gasless produksi memerlukan lebih banyak: mengelola dompet sponsor, menangani konversi token (sehingga pengguna dapat "membayar" biaya dalam USDC), pembatasan rate, dan kontrol keamanan.
Kora menangani kompleksitas ini. Ini adalah server JSON-RPC yang menyediakan abstraksi biaya sehingga pengguna tidak pernah memerlukan SOL. Anda dapat sepenuhnya mensponsori biaya atau menerima pembayaran biaya dalam token apa pun.
Deploy Kora dengan satu perintah:
cargo install kora-clikora --config path/to/kora.toml rpc start --signers-config path/to/signers.toml
Kemudian gunakan klien Kora untuk menandatangani dan mengirim transaksi:
pnpm add @solana/kora
import { KoraClient } from "@solana/kora";const kora = new KoraClient({ rpcUrl: "https://your-kora-instance" });const { signature } = await kora.signAndSendTransaction({transaction: base64EncodedTransaction});
Sumber daya Kora
Is this page helpful?