Her Solana işlemi, ağ ücretlerini ödemek için SOL gerektirir. Ancak ödeme uygulamanıza gelen kullanıcılar stablecoin'lerle işlem yapmayı bekler—ikinci bir token bakiyesi yönetmeyi değil. Ücret soyutlama, ücretleri başka birinin ödemesini sağlayarak bu sürtünmeyi ortadan kaldırır.
Bu kılavuz iki seviyeyi kapsar:
- Ücret sponsorluğu nasıl çalışır — altta yatan Solana ilkeli
- Kora ile ölçekte ücret soyutlama — üretime hazır bir ücret soyutlama hizmeti
Ücret sponsorluğu nasıl çalışır
Solana işlemlerinin belirlenmiş bir ücret ödeyicisi vardır—ağ ücretini ödeyen hesap. Varsayılan olarak bu, ilk imzalayandır. Ancak ücret ödeyici olarak farklı bir hesap belirleyebilirsiniz, bu da üçüncü bir tarafın ("sponsor") gönderen adına ücretleri karşılamasına olanak tanır.
Hem gönderen hem de sponsor işlemi imzalamalıdır:
- Gönderen, token'larının transferini yetkilendirmek için imzalar
- Sponsor, ağ ücretinin ödenmesini yetkilendirmek için imzalar
Temel ödeme kavramları için Solana'da ödemeler nasıl çalışır bölümüne bakın.
Aşağıdaki adımlar temel akışı gösterir. Tam çalıştırılabilir kod için Demo bölümüne bakın.
Sponsor hesabı oluştur
İşlem ücretlerini ödeyecek sponsor için ayrı bir keypair oluşturun. Sponsor'un ücretler için SOL'a ihtiyacı vardır ancak transfer edilen token'ları tutmasına gerek yoktur.
Transfer talimatı oluştur
Gönderen yetkili olarak token transfer talimatını oluşturun. Gönderen token'lara sahiptir ve transferi imzalamalıdır.
Sponsor'u ücret ödeyici olarak kullanarak gönder
Sponsoru ücret ödeyen olarak ayarlayarak payer(sponsor) aracılığıyla istemciyi
oluşturun, ardından client.sendTransaction işlevini çağırın. Sponsor, ağ
ücretini ödemek için imzalarken gönderen, transferi yetkilendirmek için
imzalar—sendTransaction, başvurulan tüm imzacıları otomatik olarak toplar.
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// =============================================================================
Son kullanıcı için bir token account oluşturduğunuzda, kullanıcı bunu kapatabilir ve rent için kullanılan SOL'u geri alabilir. Hesap oluşturma için kullanıcılardan stablecoin cinsinden ücret almayı düşünün veya bu maliyeti ürün ekonominize dahil edin.
Kora ile ölçekte ücret soyutlama
Ücret ödeyici primitive güçlüdür, ancak production seviyesinde gassız bir sistem oluşturmak daha fazlasını gerektirir: sponsor cüzdanlarını yönetmek, token dönüşümlerini işlemek (kullanıcıların USDC ile ücret "ödemesi" için), hız sınırlama ve güvenlik kontrolleri.
Kora bu karmaşıklığı yönetir. Kullanıcıların asla SOL'e ihtiyaç duymayacağı şekilde ücret soyutlaması sağlayan bir JSON-RPC sunucusudur. Ücretleri tamamen sponsor edebilir veya herhangi bir token ile ücret ödemesini kabul edebilirsiniz.
Kora'yı tek bir komutla deploy edin:
cargo install kora-clikora --config path/to/kora.toml rpc start --signers-config path/to/signers.toml
Ardından bir Kit istemcisini Kora sunucunuza yönlendirin ve yukarıda kullanılan aynı API ile işlem gönderin:
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 kaynakları
Is this page helpful?