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
Buat klien dengan sponsor yang ditetapkan sebagai pembayar biaya melalui
payer(sponsor), lalu panggil client.sendTransaction. Sponsor menandatangani
untuk membayar biaya jaringan sementara pengirim menandatangani untuk
mengotorisasi transfer—sendTransaction mengumpulkan setiap penanda tangan yang
direferensikan secara otomatis.
Demo
// 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// =============================================================================
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 arahkan klien Kit ke server Kora Anda dan kirim transaksi dengan API yang sama seperti yang digunakan di atas:
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);
Sumber daya Kora
Is this page helpful?