Jede Solana-Transaktion erfordert SOL zur Zahlung von Netzwerk-Fees. Aber Nutzer, die zu Ihrer Zahlungsanwendung kommen, erwarten Transaktionen in Stablecoins – nicht die Verwaltung eines zweiten Token-Guthabens. Fee-Abstraktion beseitigt diese Reibung, indem jemand anderes die Fees zahlt.
Dieser Leitfaden behandelt zwei Ebenen:
- Wie Fee-Sponsoring funktioniert – die zugrunde liegende Solana-Primitive
- Fee-Abstraktion im großen Maßstab mit Kora – ein produktionsreifer Fee-Abstraktions-Service
Wie Fee-Sponsoring funktioniert
Solana-Transaktionen haben einen festgelegten Fee-Zahler – das Konto, das die Netzwerk-Fee zahlt. Standardmäßig ist dies der erste Signer. Sie können jedoch ein anderes Konto als Fee-Zahler angeben, sodass ein Dritter (der "Sponsor") Fees im Namen des Absenders übernehmen kann.
Sowohl der Absender als auch der Sponsor müssen die Transaktion signieren:
- Der Absender signiert, um die Übertragung seiner Token zu autorisieren
- Der Sponsor signiert, um die Zahlung der Netzwerk-Fee zu autorisieren
Siehe Wie Zahlungen auf Solana funktionieren für grundlegende Zahlungskonzepte.
Die folgenden Schritte zeigen den grundlegenden Ablauf. Siehe die Demo für vollständigen ausführbaren Code.
Sponsor-Konto erstellen
Generieren Sie ein separates Keypair für den Sponsor, der Transaktions-Fees zahlen wird. Der Sponsor benötigt SOL für Fees, muss aber nicht die zu übertragenden Token halten.
Transfer-Instruktion erstellen
Erstellen Sie die Token-Transfer-Instruktion mit dem Absender als Autorität. Der Absender besitzt die Token und muss die Übertragung signieren.
Senden mit Sponsor als Fee-Zahler
Erstellen Sie den Client mit dem Sponsor als Fee-Zahler über payer(sponsor),
dann rufen Sie client.sendTransaction auf. Der Sponsor unterschreibt, um die
Netzwerk-Fee zu bezahlen, während der Absender unterschreibt, um die Überweisung
zu autorisieren – sendTransaction erfasst jeden referenzierten Signer
automatisch.
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// =============================================================================
Wenn Sie ein Token-Konto für einen Endbenutzer erstellen, kann dieser es schließen und die für Rent verwendeten SOL zurückfordern. Erwägen Sie, Benutzern die Kontoerstellung in Stablecoins in Rechnung zu stellen, oder berücksichtigen Sie diese Kosten in Ihrer Produktökonomie.
Fee-Abstraktion im großen Maßstab mit Kora
Das Fee-Payer-Primitiv ist leistungsstark, aber der Aufbau eines produktionsreifen Gasless-Systems erfordert mehr: Verwaltung von Sponsor-Wallets, Handhabung von Token-Konvertierungen (damit Benutzer Fees in USDC "zahlen" können), Rate-Limiting und Sicherheitskontrollen.
Kora bewältigt diese Komplexität. Es ist ein JSON-RPC-Server, der Fee-Abstraktion bereitstellt, sodass Benutzer niemals SOL benötigen. Sie können Gebühren vollständig sponsern oder die Zahlung der Fee in einem beliebigen Token akzeptieren.
Deployen Sie Kora mit einem einzigen Befehl:
cargo install kora-clikora --config path/to/kora.toml rpc start --signers-config path/to/signers.toml
Verbinden Sie dann einen Kit-Client mit Ihrem Kora-Server und senden Sie Transaktionen mit derselben API wie oben beschrieben:
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-Ressourcen
Kora Schnellstart
Kora in wenigen Minuten lokal zum Laufen bringen.
Vollständige Transaktionsdemo
Komplette Implementierungsanleitung für Fee-Abstraktions-Transaktionen.
API-Referenz
JSON-RPC-Methoden und SDK-Dokumentation.
Leitfaden für Node-Betreiber
Deployment und Konfiguration Ihrer eigenen Kora-Instanz.
Is this page helpful?