Abstraction des frais

Chaque transaction Solana nécessite du SOL pour payer les frais de réseau. Mais les utilisateurs qui viennent sur votre application de paiement s'attendent à effectuer des transactions en stablecoins, et non à gérer un solde de second jeton. L'abstraction des frais élimine cette friction en permettant à quelqu'un d'autre de payer les frais.

Ce guide couvre deux niveaux :

  1. Comment fonctionne le parrainage des frais — la primitive Solana sous-jacente
  2. Abstraction des frais à grande échelle avec Kora — un service d'abstraction des frais prêt pour la production

Comment fonctionne le parrainage des frais

Les transactions Solana ont un payeur de frais désigné, c'est-à-dire le compte qui paie les frais de réseau. Par défaut, il s'agit du premier signataire. Mais vous pouvez spécifier un compte différent comme payeur de frais, permettant à un tiers (le « parrain ») de couvrir les frais au nom de l'expéditeur.

L'expéditeur et le parrain doivent tous deux signer la transaction :

  • L'expéditeur signe pour autoriser le transfert de ses jetons
  • Le parrain signe pour autoriser le paiement des frais de réseau

Consultez Comment fonctionnent les paiements sur Solana pour les concepts de paiement de base.

Les étapes ci-dessous montrent le flux principal. Consultez la Démo pour le code complet exécutable.

Créer un compte parrain

Générez une paire de clés distincte pour le parrain qui paiera les frais de transaction. Le parrain a besoin de SOL pour les frais mais n'a pas besoin de détenir les jetons transférés.

Créer l'instruction de transfert

Créez l'instruction de transfert de jetons avec l'expéditeur comme autorité. L'expéditeur possède les jetons et doit signer le transfert.

Envoyer avec un sponsor comme payeur de frais

Créez le client avec le sponsor défini comme payeur de frais via payer(sponsor), puis appelez client.sendTransaction. Le sponsor signe pour régler les frais réseau tandis que l'expéditeur signe pour autoriser le transfert—sendTransaction collecte automatiquement chaque signataire référencé.

Créer un compte parrain

Générez une paire de clés distincte pour le parrain qui paiera les frais de transaction. Le parrain a besoin de SOL pour les frais mais n'a pas besoin de détenir les jetons transférés.

Créer l'instruction de transfert

Créez l'instruction de transfert de jetons avec l'expéditeur comme autorité. L'expéditeur possède les jetons et doit signer le transfert.

Envoyer avec un sponsor comme payeur de frais

Créez le client avec le sponsor défini comme payeur de frais via payer(sponsor), puis appelez client.sendTransaction. Le sponsor signe pour régler les frais réseau tandis que l'expéditeur signe pour autoriser le transfert—sendTransaction collecte automatiquement chaque signataire référencé.

Sponsor Transaction Fee
const sponsor = await generateKeyPairSigner();

Démo

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 tokens
const { client, mint } = await demoSetup(sender, recipient, sponsor);
console.log("\nMint Address:", mint.address);
// Derive the Associated Token Accounts addresses (ATAs) for sender and recipient
const [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 transfer
amount: 250_000n, // 0.25 tokens
decimals: 6
});
// Send transaction with sponsor as fee payer using @solana/kit
// The sponsor (client.payer) pays fees; the sender signs for the transfer
const { 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 RPC
const 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 details
const 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
// =============================================================================
Console
Click to execute the code.

Lorsque vous créez un token account pour un utilisateur final, il peut le fermer et récupérer les SOL utilisés pour le rent. Envisagez de facturer les utilisateurs pour la création de compte en stablecoins, ou intégrez ce coût dans l'économie de votre produit.

Abstraction des frais à grande échelle avec Kora

La primitive du payeur de frais est puissante, mais construire un système sans frais en production nécessite davantage : gérer les portefeuilles sponsors, gérer les conversions de tokens (pour que les utilisateurs puissent « payer » les frais en USDC), limiter le débit et mettre en place des contrôles de sécurité.

Kora gère cette complexité. C'est un serveur JSON-RPC qui fournit une abstraction des frais afin que les utilisateurs n'aient jamais besoin de SOL. Vous pouvez entièrement prendre en charge les frais ou accepter leur paiement dans n'importe quel jeton.

Déployez Kora avec une seule commande :

cargo install kora-cli
kora --config path/to/kora.toml rpc start --signers-config path/to/signers.toml

Ensuite, pointez un client Kit vers votre serveur Kora et envoyez des transactions avec la même API utilisée ci-dessus :

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 SOL
const kora = await createKitKoraClient({
endpoint: "https://your-kora-instance",
rpcUrl: "https://api.mainnet-beta.solana.com",
feeToken: address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"), // USDC
feePayerWallet: sender // Signs to authorize the token fee payment
});
// Same instruction, same call—Kora sponsors the network fee
const { context } = await kora.sendTransaction([transferInstruction]);
console.log("Signature:", context.signature);

Ressources Kora

Is this page helpful?

Table des matières

Modifier la page
© 2026 Fondation Solana. Tous droits réservés.