Elke Solana-transactie vereist SOL om netwerkkosten te betalen. Maar gebruikers die naar jouw betalingsapplicatie komen, verwachten te transacteren in stablecoins—niet een tweede tokensaldo te beheren. Fee abstraction verwijdert deze wrijving doordat iemand anders de kosten betaalt.
Deze gids behandelt twee niveaus:
- Hoe fee sponsorship werkt — de onderliggende Solana-primitief
- Fee abstraction op schaal met Kora — een productierijpe fee abstraction-service
Hoe fee sponsorship werkt
Solana-transacties hebben een aangewezen fee payer—het account dat de netwerkkosten betaalt. Standaard is dit de eerste ondertekenaar. Maar je kunt een ander account als fee payer specificeren, waardoor een derde partij (de "sponsor") kosten kan dekken namens de verzender.
Zowel de verzender als de sponsor moeten de transactie ondertekenen:
- De verzender ondertekent om de overdracht van hun tokens te autoriseren
- De sponsor ondertekent om betaling van de netwerkkosten te autoriseren
Zie How Payments Work on Solana voor kernconcepten van betalingen.
De onderstaande stappen tonen de kernflow. Zie de Demo voor complete uitvoerbare code.
Maak een sponsor-account aan
Genereer een apart keypair voor de sponsor die transactiekosten zal betalen. De sponsor heeft SOL nodig voor kosten maar hoeft de tokens die worden overgedragen niet te bezitten.
Maak transfer-instructie aan
Maak de token transfer-instructie aan met de verzender als authority. De verzender bezit de tokens en moet de overdracht ondertekenen.
Verzenden met sponsor als betaler van kosten
Maak de client aan met de sponsor ingesteld als betaler van de transactiekosten
via payer(sponsor), roep vervolgens client.sendTransaction aan. De sponsor
ondertekent om de netwerkkosten te betalen terwijl de afzender ondertekent om de
overdracht te autoriseren—sendTransaction verzamelt alle betrokken
ondertekenaars 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// =============================================================================
Wanneer je een token account aanmaakt voor een eindgebruiker, kunnen ze deze sluiten en de SOL die gebruikt is voor rent terugvorderen. Overweeg om gebruikers te laten betalen voor het aanmaken van accounts in stablecoins, of verwerk deze kosten in je producteconomie.
Fee-abstractie op schaal met Kora
De fee payer primitive is krachtig, maar het bouwen van een productie-gasless systeem vereist meer: het beheren van sponsor wallets, het afhandelen van tokenconversies (zodat gebruikers kosten kunnen "betalen" in USDC), rate limiting en beveiligingscontroles.
Kora handelt deze complexiteit af. Het is een JSON-RPC-server die fee-abstractie biedt, zodat gebruikers nooit SOL nodig hebben. Je kunt kosten volledig sponsoren of betalingen in elke token accepteren.
Deploy Kora met een enkel commando:
cargo install kora-clikora --config path/to/kora.toml rpc start --signers-config path/to/signers.toml
Wijs vervolgens een Kit-client toe aan uw Kora-server en verstuur transacties met dezelfde API als hierboven gebruikt:
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-bronnen
Is this page helpful?