Εργαλεία επαλήθευσης

Τα tokens καταλήγουν στο πορτοφόλι σας τη στιγμή που επιβεβαιώνεται μια συναλλαγή. Δεν απαιτείται καμία ενέργεια από τον παραλήπτη. Το Solana αυξάνει ατομικά το υπόλοιπο του token account του παραλήπτη και μειώνει το υπόλοιπο του αποστολέα. Σε αυτόν τον οδηγό, καλύπτουμε μερικά χρήσιμα εργαλεία για την κατανόηση του υπολοίπου του token account σας και την παρακολούθηση εισερχόμενων πληρωμών.

Ερώτημα υπολοίπου token

Ελέγξτε το υπόλοιπο σας σε stablecoin χρησιμοποιώντας τη μέθοδο RPC getTokenAccountBalance:

import { createSolanaRpc, address, type Address } from "@solana/kit";
import {
findAssociatedTokenPda,
TOKEN_PROGRAM_ADDRESS
} from "@solana-program/token";
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
const USDC_MINT = address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
async function getBalance(walletAddress: Address) {
// Derive the token account address
const [ata] = await findAssociatedTokenPda({
mint: USDC_MINT,
owner: walletAddress,
tokenProgram: TOKEN_PROGRAM_ADDRESS
});
// Query balance via RPC
const { value } = await rpc.getTokenAccountBalance(ata).send();
return {
raw: BigInt(value.amount), // "1000000" -> 1000000n
formatted: value.uiAmountString, // "1.00"
decimals: value.decimals // 6
};
}

Παρακολούθηση εισερχόμενων μεταφορών

Εγγραφείτε στο token account σας για ειδοποιήσεις πληρωμών σε πραγματικό χρόνο χρησιμοποιώντας τη μέθοδο RPC accountNotifications:

const rpcSubscriptions = createSolanaRpcSubscriptions(
"wss://api.mainnet-beta.solana.com"
);
async function watchPayments(
tokenAccountAddress: Address,
onPayment: (amount: bigint) => void
) {
const abortController = new AbortController();
const subscription = await rpcSubscriptions
.accountNotifications(tokenAccountAddress, {
commitment: "confirmed",
encoding: "base64"
})
.subscribe({ abortSignal: abortController.signal });
let previousBalance = 0n;
for await (const notification of subscription) {
const [data] = notification.value.data;
const dataBytes = getBase64Codec().encode(data);
const token = getTokenCodec().decode(dataBytes);
if (token.amount > previousBalance) {
const received = token.amount - previousBalance;
onPayment(received);
}
previousBalance = token.amount;
}
abortController.abort();
}

Σημειώστε εδώ ότι χρησιμοποιούμε RPC Subscriptions και σύνδεση websocket στο δίκτυο Solana.

Κάθε ειδοποίηση περιέχει ένα κωδικοποιημένο σε base64 string των δεδομένων του token account. Επειδή γνωρίζουμε ότι ο λογαριασμός που εξετάζουμε είναι token account, μπορούμε να αποκωδικοποιήσουμε τα δεδομένα χρησιμοποιώντας τη μέθοδο getTokenCodec από το πακέτο @solana-program/token.

Σημειώστε ότι για εφαρμογές παραγωγής, θα πρέπει να εξετάσετε μια πιο ισχυρή λύση streaming. Μερικές επιλογές περιλαμβάνουν:

Ανάλυση ιστορικού συναλλαγών

Το Solana διαθέτει μεθόδους RPC που σας επιτρέπουν να ανακτήσετε το ιστορικό συναλλαγών ενός λογαριασμού (getSignaturesForAddress) και να λάβετε τις λεπτομέρειες μιας συναλλαγής (getTransaction). Για να αναλύσουμε το ιστορικό συναλλαγών, ανακτούμε πρόσφατες υπογραφές για το token account μας, στη συνέχεια ανακτούμε τα υπόλοιπα token πριν/μετά κάθε συναλλαγής. Συγκρίνοντας το υπόλοιπο του ATA μας πριν και μετά από κάθε συναλλαγή, μπορούμε να προσδιορίσουμε το ποσό πληρωμής και την κατεύθυνση (εισερχόμενη έναντι εξερχόμενης).

async function getRecentPayments(
tokenAccountAddress: Address,
limit = 100
): Promise<Payment[]> {
const signatures = await rpc
.getSignaturesForAddress(tokenAccountAddress, { limit })
.send();
const payments: ParsedPayment[] = [];
for (const sig of signatures) {
const tx = await rpc
.getTransaction(sig.signature, { maxSupportedTransactionVersion: 0 })
.send();
if (!tx?.meta?.preTokenBalances || !tx?.meta?.postTokenBalances) continue;
// Find our ATA's index in the transaction
const accountKeys = tx.transaction.message.accountKeys;
const ataIndex = accountKeys.findIndex((key) => key === ata);
if (ataIndex === -1) continue;
// Compare pre/post balances for our ATA
const pre = tx.meta.preTokenBalances.find(
(b) => b.accountIndex === ataIndex && b.mint === USDC_MINT
);
const post = tx.meta.postTokenBalances.find(
(b) => b.accountIndex === ataIndex && b.mint === USDC_MINT
);
const preAmount = BigInt(pre?.uiTokenAmount.amount ?? "0");
const postAmount = BigInt(post?.uiTokenAmount.amount ?? "0");
const diff = postAmount - preAmount;
if (diff !== 0n) {
payments.push({
signature: sig.signature,
timestamp: tx.blockTime,
amount: diff > 0n ? diff : -diff,
type: diff > 0n ? "incoming" : "outgoing"
});
}
}
return payments;
}

Για να αναγνωρίσετε το αντισυμβαλλόμενο μέρος, μπορείτε να σαρώσετε τα υπόλοιπα token της συναλλαγής για έναν άλλο λογαριασμό του οποίου το υπόλοιπο άλλαξε στην αντίθετη κατεύθυνση—αν λάβατε κεφάλαια, αναζητήστε έναν λογαριασμό του οποίου το υπόλοιπο μειώθηκε κατά το ίδιο ποσό.

Επειδή οι μεταφορές SPL token μπορούν να υπάρχουν πέρα από απλές πληρωμές μεταξύ χρηστών, αυτή η προσέγγιση ενδέχεται να αποδώσει ορισμένες συναλλαγές που δεν είναι πληρωμές. Μια καλή εναλλακτική εδώ είναι η χρήση των Memos.

Περιορισμοί της ανάλυσης υπολοίπων πριν/μετά

Η παραπάνω προσέγγιση λειτουργεί καλά για απλές ροές πληρωμών. Ωστόσο, οι εταιρείες που επεξεργάζονται πληρωμές σε μεγάλη κλίμακα συχνά χρειάζονται πιο λεπτομερή και δεδομένα σε πραγματικό χρόνο:

  • Ανάλυση ανά εντολή: Μια μεμονωμένη συναλλαγή μπορεί να περιέχει πολλαπλές μεταφορές. Τα υπόλοιπα πριν/μετά δείχνουν μόνο την καθαρή μεταβολή, όχι τις μεμονωμένες μεταφορές.
  • Συναλλαγές πολλαπλών μερών: Οι σύνθετες συναλλαγές (ανταλλαγές, ομαδικές πληρωμές) περιλαμβάνουν πολλαπλούς λογαριασμούς. Οι διαφορές υπολοίπων δεν αποκαλύπτουν την πλήρη ροή κεφαλαίων.
  • Απαιτήσεις ελέγχου: Η χρηματοοικονομική συμμόρφωση συχνά απαιτεί την ανακατασκευή ακριβών ακολουθιών μεταφοράς, όχι μόνο τελικών υπολοίπων.

Για συστήματα παραγωγής που χειρίζονται μεγάλους όγκους, εξετάστε αφιερωμένες λύσεις ευρετηρίασης που αναλύουν μεμονωμένες εντολές μεταφοράς και παρέχουν λεπτομέρειες σε επίπεδο συναλλαγής.

Συμφωνία πληρωμών με Memos

Όταν οι αποστολείς συμπεριλαμβάνουν memos (αναγνωριστικά τιμολογίου, αριθμούς παραγγελίας), μπορείτε να τα εξαγάγετε από το μήνυμα της συναλλαγής χρησιμοποιώντας τη μέθοδο RPC getTransaction και την κωδικοποίηση jsonParsed:

function extractMemos(transaction): string | null {
const { instructions } = transaction.transaction.message;
let memos = "";
for (const instruction of instructions) {
if (instruction.program !== "spl-memo") continue;
memos += instruction.parsed + "; ";
}
return memos;
}
async function getTransactionMemo(
signature: Signature
): Promise<string | null> {
const tx = await rpc
.getTransaction(signature, {
maxSupportedTransactionVersion: 0,
encoding: "jsonParsed"
})
.send();
if (!tx) return null;
return extractMemos(tx);
}

Προστασίες

Μερικές καταστάσεις αποτυχίας που πρέπει να αποφύγετε:

  • Εμπιστοσύνη στο frontend. Μια σελίδα ολοκλήρωσης αγοράς λέει "η πληρωμή ολοκληρώθηκε"—αλλά η συναλλαγή πραγματικά καταχωρήθηκε; Επαληθεύετε πάντα από την πλευρά του διακομιστή ερωτώντας το RPC. Οι επιβεβαιώσεις frontend μπορούν να παραποιηθούν.

  • Ενέργεια με βάση την κατάσταση "processed". Οι συναλλαγές Solana περνούν από τρία στάδια: processed → confirmed → finalized. Μια συναλλαγή "processed" μπορεί ακόμα να απορριφθεί κατά τη διάρκεια forks. Περιμένετε για "confirmed" (1-2 δευτερόλεπτα) πριν αποστείλετε παραγγελίες, ή "finalized" (~13 δευτερόλεπτα) για συναλλαγές υψηλής αξίας.

  • Acting on "processed" status. Solana transactions go through three stages: processed → confirmed → finalized. A "processed" transaction can still be dropped during forks. Wait for "confirmed" (1-2 seconds) before shipping orders, or "finalized" (~13 seconds) for high-value transactions.

  • Αγνοώντας το mint. Οποιοσδήποτε μπορεί να δημιουργήσει ένα token με το όνομα "USDC". Επαληθεύστε ότι η διεύθυνση mint του token account ταιριάζει με την πραγματική διεύθυνση mint του stablecoin και το token program, όχι απλώς το όνομα του token.

  • Διπλή εκπλήρωση. Το webhook σας ενεργοποιείται, αποστέλλετε την παραγγελία. Πρόβλημα δικτύου, το webhook ενεργοποιείται ξανά. Τώρα έχετε αποστείλει δύο φορές. Αποθηκεύστε τις επεξεργασμένες υπογραφές συναλλαγών και ελέγξτε πριν από την εκπλήρωση.

Is this page helpful?

Διαχειρίζεται από

© 2026 Ίδρυμα Solana.
Με επιφύλαξη παντός δικαιώματος.
Συνδεθείτε