Κάθε συναλλαγή στο Solana απαιτεί SOL για την πληρωμή των προμηθειών δικτύου. Αλλά οι χρήστες που έρχονται στην εφαρμογή πληρωμών σας αναμένουν να συναλλάσσονται σε stablecoins—όχι να διαχειρίζονται ένα δεύτερο υπόλοιπο token. Η αφαίρεση προμηθειών εξαλείφει αυτή την τριβή επιτρέποντας σε κάποιον άλλον να πληρώσει τις προμήθειες.
Αυτός ο οδηγός καλύπτει δύο επίπεδα:
- Πώς λειτουργεί η χορηγία προμηθειών — το υποκείμενο πρωτόκολλο του Solana
- Αφαίρεση προμηθειών σε κλίμακα με το Kora — μια υπηρεσία αφαίρεσης προμηθειών έτοιμη για παραγωγή
Πώς λειτουργεί η χορηγία προμηθειών
Οι συναλλαγές στο Solana έχουν έναν καθορισμένο πληρωτή προμηθειών—τον λογαριασμό που πληρώνει την προμήθεια δικτύου. Από προεπιλογή, αυτός είναι ο πρώτος υπογράφων. Αλλά μπορείτε να ορίσετε έναν διαφορετικό λογαριασμό ως πληρωτή προμηθειών, επιτρέποντας σε ένα τρίτο μέρος (τον "χορηγό") να καλύψει τις προμήθειες εκ μέρους του αποστολέα.
Τόσο ο αποστολέας όσο και ο χορηγός πρέπει να υπογράψουν τη συναλλαγή:
- Ο αποστολέας υπογράφει για να εξουσιοδοτήσει τη μεταφορά των tokens του
- Ο χορηγός υπογράφει για να εξουσιοδοτήσει την πληρωμή της προμήθειας δικτύου
Δείτε το Πώς λειτουργούν οι πληρωμές στο Solana για βασικές έννοιες πληρωμών.
Τα παρακάτω βήματα δείχνουν τη βασική ροή. Δείτε το Demo για πλήρη εκτελέσιμο κώδικα.
Δημιουργία λογαριασμού χορηγού
Δημιουργήστε ένα ξεχωριστό ζεύγος κλειδιών για τον χορηγό που θα πληρώνει τις προμήθειες συναλλαγών. Ο χορηγός χρειάζεται SOL για τις προμήθειες αλλά δεν χρειάζεται να κατέχει τα tokens που μεταφέρονται.
Δημιουργία εντολής μεταφοράς
Δημιουργήστε την εντολή μεταφοράς token με τον αποστολέα ως εξουσιοδοτημένο. Ο αποστολέας κατέχει τα tokens και πρέπει να υπογράψει τη μεταφορά.
Αποστολή με χορηγό ως πληρωτή χρέωσης
Χρησιμοποιήστε prepareAndSend με τόσο τον authority (τον αποστολέα που
υπογράφει τη μεταφορά) όσο και τον feePayer (τον χορηγό που πληρώνει τις
χρεώσεις). Και οι δύο πρέπει να υπογράψουν τη συναλλαγή.
Demo
// 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// =============================================================================
Όταν δημιουργείτε ένα token account για έναν τελικό χρήστη, μπορεί να το κλείσει και να ανακτήσει το SOL που χρησιμοποιήθηκε για rent. Σκεφτείτε να χρεώνετε τους χρήστες για τη δημιουργία λογαριασμού σε stablecoins, ή να συνυπολογίζετε αυτό το κόστος στα οικονομικά του προϊόντος σας.
Αφαίρεση χρεώσεων σε κλίμακα με το Kora
Το primitive του πληρωτή χρέωσης είναι ισχυρό, αλλά η κατασκευή ενός production συστήματος χωρίς χρεώσεις απαιτεί περισσότερα: διαχείριση πορτοφολιών χορηγών, χειρισμό μετατροπών tokens (ώστε οι χρήστες να μπορούν να "πληρώνουν" χρεώσεις σε USDC), περιορισμό ρυθμού και ελέγχους ασφαλείας.
Το Kora χειρίζεται αυτήν την πολυπλοκότητα. Είναι ένας JSON-RPC server που παρέχει αφαίρεση χρεώσεων ώστε οι χρήστες να μην χρειάζονται ποτέ SOL. Μπορείτε να χορηγήσετε πλήρως τις χρεώσεις ή να δεχτείτε πληρωμή χρεώσεων σε οποιοδήποτε token.
Αναπτύξτε το Kora με μία μόνο εντολή:
cargo install kora-clikora --config path/to/kora.toml rpc start --signers-config path/to/signers.toml
Στη συνέχεια χρησιμοποιήστε το Kora client για να υπογράψετε και να στείλετε συναλλαγές:
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?