すべてのSolanaトランザクションは、ネットワーク手数料を支払うためにSOLを必要とします。しかし、決済アプリケーションを利用するユーザーは、ステーブルコインで取引することを期待しており、2つ目のトークン残高を管理することは望んでいません。手数料の抽象化は、他の誰かが手数料を支払うことで、この摩擦を取り除きます。
このガイドでは、2つのレベルをカバーします。
- 手数料スポンサーシップの仕組み — 基盤となるSolanaのプリミティブ
- Koraによる大規模な手数料の抽象化 — 本番環境対応の手数料抽象化サービス
手数料スポンサーシップの仕組み
Solanaトランザクションには、指定された手数料支払者、つまりネットワーク手数料を支払うアカウントがあります。デフォルトでは、これは最初の署名者です。しかし、別のアカウントを手数料支払者として指定することができ、第三者(「スポンサー」)が送信者に代わって手数料を負担することが可能になります。
送信者とスポンサーの両方がトランザクションに署名する必要があります。
- 送信者は、トークンの転送を承認するために署名します
- スポンサーは、ネットワーク手数料の支払いを承認するために署名します
コア決済の概念については、Solanaでの決済の仕組みを参照してください。
以下の手順は、コアフローを示しています。完全な実行可能なコードについては、デモを参照してください。
スポンサーアカウントの作成
トランザクション手数料を支払うスポンサー用に、別のkeypairを生成します。スポンサーは手数料のためにSOLが必要ですが、転送されるトークンを保有する必要はありません。
転送命令の作成
送信者を権限者として、トークン転送命令を作成します。送信者はトークンを所有しており、転送に署名する必要があります。
スポンサーを手数料支払者として送信
authority(転送に署名する送信者)とfeePayer(手数料を支払うスポンサー)の両方を使用してprepareAndSendを使用します。両方がトランザクションに署名する必要があります。
デモ
// Generate keypairs for sender, recipient, and sponsor (fee payer)const sender = (await generateKeypair()).signer;const recipient = (await generateKeypair()).signer;const sponsor = (await generateKeypair()).signer;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 = getTransferInstruction({source: senderAta,destination: recipientAta,authority: sender, // Pass signer, not just addressamount: 250_000n // 0.25 tokens});// Prepare and send transaction with sponsor as fee payer using @solana/client// The sponsor pays transaction fees, sender signs for the transferconst signature = await client.transaction.prepareAndSend({authority: sender, // Sender signs the transfer instructionfeePayer: sponsor, // Sponsor pays the transaction fees (different account)instructions: [transferInstruction],version: 0});console.log("\n=== Sponsored Token Payment Complete ===");console.log("Transaction Signature:", signature.toString());// Fetch final token account balances using @solana/client SPL token helperconst splToken = client.splToken({mint: mint.address,tokenProgram: "auto"});const senderBalance = await splToken.fetchBalance(sender.address);const recipientBalance = await splToken.fetchBalance(recipient.address);console.log("\nSender Token Account Balance:", senderBalance);console.log("Recipient Token Account Balance:", recipientBalance);// Fetch transaction detailsconst transaction = await client.runtime.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// =============================================================================
エンドユーザーのためにトークンアカウントを作成する場合、ユーザーはそれを閉じて、rentに使用されたSOLを取り戻すことができます。ステーブルコインでアカウント作成料金をユーザーに請求するか、この費用を製品の経済性に組み込むことを検討してください。
Koraによる大規模な手数料抽象化
手数料支払者プリミティブは強力ですが、本番環境のガスレスシステムを構築するには、スポンサーウォレットの管理、トークン変換の処理(ユーザーがUSDCで手数料を「支払う」ことができるように)、レート制限、セキュリティ制御など、さらに多くのことが必要です。
Koraは、この複雑さを処理します。これは、ユーザーがSOLを必要としないように手数料抽象化を提供するJSON-RPCサーバーです。手数料を完全にスポンサーするか、任意のトークンで手数料の支払いを受け入れることができます。
単一のコマンドでKoraをデプロイします:
cargo install kora-clikora --config path/to/kora.toml rpc start --signers-config path/to/signers.toml
次に、Koraクライアントを使用してトランザクションに署名して送信します:
pnpm add @solana/kora
import { KoraClient } from "@solana/kora";const kora = new KoraClient({ rpcUrl: "https://your-kora-instance" });const { signature } = await kora.signAndSendTransaction({transaction: base64EncodedTransaction});
Koraリソース
Is this page helpful?