- Message → Was der Benutzer tun wollte (sein unterschriebener Vorschlag)
- Meta → Was tatsächlich passiert ist (das Ausführungsergebnis)
<Buffer 00 bf a0 e8...> anstatt als lesbare Adressen und Signaturen.
Diese Anleitung zeigt Ihnen, wie Sie: Diese Binärdaten in ein menschenlesbares Format dekodieren, bedeutungsvolle Informationen extrahieren und die gesamte Transaktionsgeschichte vom Vorschlag bis zur Ausführung verstehen können.
Ein Livestream, keine Dekodierung
Führen Sie den minimalen Client unten aus. Die Filteroptionen lassen Abstimmungs- und fehlgeschlagene Transaktionen weg, und dasaccountInclude Array begrenzt die Ergebnisse auf Aktivitäten, die die Jupiter-Programm-ID berühren.
filters, createdAt plus ein transaction Zweig, der zwei Kinder verbirgt:
transaction.transaction.transaction→ die unterzeichnete Nachrichttransaction.transaction.meta→ die Ausführungs-Meta
Uint8Array aussieht, bleibt momentan opak.
Wenn Sie das Skript mit der Dekodierungsfunktion ausführen, sehen Sie die tatsächliche verschachtelte Struktur mit lesbaren Adressen:
Dekodierung der Binärdaten
Warum dekodieren? Rohe Laserstream-Daten enthalten Signaturen, Kontoschlüssel und Hashes als binäreUint8Array Objekte, die unleserlich sind. Sie müssen diese in Base58-Zeichenfolgen konvertieren, um die Transaktion zu verstehen.
Die Lösung: Laserstream verwendet Yellowstone gRPC, das integrierte Dekodierungsfunktionen bietet. Anstatt separate Dekodierer für jeden Feldtyp zu schreiben, verwenden wir eine rekursive Funktion, die alle Binärdaten in ein menschenlesbares Format umwandelt.
Verständnis der Transaktionsstruktur
Jetzt, da wir die dekodierten Daten sehen können, lassen Sie uns die beiden Hauptteile jeder Laserstream-Transaktionsaktualisierung untersuchen. Erinnern Sie sich an unser anfängliches Beispiel, dass jede Transaktion zwei wichtige Objekte enthält:- Message (Proposal) →
transaction.transaction.transaction→ die signierte Nachricht (Vorschlag des Benutzers) - Meta (Execution) →
transaction.transaction.meta→ die Ausführungs-Metadaten (Antwort des Validators)
Der Vorschlag: alles innerhalb der Nachricht
Der Benutzer erstellt eine Nachricht, die was, wer und bis wann spezifiziert. So dekodieren Sie jeden Teil:Transaktionsheader
numRequiredSignatures teilt dem Validator mit, wie viele Signaturen zu überprüfen sind, während die zwei numReadonly* Werte Konten kennzeichnen, die die Laufzeit als schreibgeschützt behandeln kann, was eine parallele Ausführung ermöglicht.
Kontoschlüssel-Wörterbuch
accountKeys ist eine einfache Liste von öffentlichen Schlüsseln, die als Nachschlagetabelle dient. Jede spätere Zahl in der Transaktion - programIdIndex, jedes Element in einem Anweisungs-accounts Array - verweist nach Index auf diese Liste zurück, was mehr als ein Kilobyte pro Nachricht spart.
Schutz vor Wiedergabe
recentBlockhash läuft ab, sobald es aus den letzten 150 Block-Hashes herausgescrollt ist, ungefähr neunzig Sekunden im Mainnet.
Anweisungen: Die eigentlichen Befehle
- Program ID (
programIdIndex): Verweist auf eine Adresse imaccountKeysArray (z.B. Index 10 =ComputeBudget111111111111111111111111111111) - Accounts (
accounts): Eine Base58-codierte Zeichenfolge, die angibt, welche Konto-Indizes diese Anweisung berührt - Data (
data): Die tatsächlichen Anweisungsdaten, die als Base58 codiert sind
convertBuffers Funktion erscheinen Konten als Base58, enthalten jedoch tatsächlich Konto-Indizes (z.B. "3vtmrQMafzDoG2CBz1iqgXPTnC" dekodiert zu Indizes [21, 19, 12, 17, 2, 6, 1, 22])
Dieses Design bedeutet, dass anstatt vollständige 32-Byte-Adressen zu wiederholen, jede Anweisung nur Positionen in der Nachschlagetabelle referenziert.
Signaturen: Nachweis der Autorisierung
signatures enthält die kryptografischen Signaturen, die belegen, dass die erforderlichen Konten diese Transaktion autorisiert haben. Die Anzahl der Signaturen muss mit header.numRequiredSignatures übereinstimmen.
Adresstabellen-Nachschläge
versioned true ist, erscheint addressTableLookups mit einer On-Chain-Tabelle und zwei Indizes-Listen. Nachschlagetabellen heben die harte Grenze der Adressanzahl auf Dutzende an, während das Paket unter der MTU von 1.232 Byte bleibt.
Transaktion v1: Rechenbudget im Header
Transaktion v1 (SIMD-0385, Agave 4.2) fügt der Nachricht ein weiteres Feld hinzu:transactionConfig.
instructions Array einer v1-Transaktion niemals einen ComputeBudget111111111111111111111111111111 Eintrag enthält. priorityFee ist die gesamte Gebühr in Lamports für die gesamte Transaktion, nicht in Mikro-Lamports pro Recheneinheit. Ein null Feld bedeutet, dass der Absender ihn nicht gesetzt hat. Legacy und v0 Nachrichten haben keinen transactionConfig, so dass seine Anwesenheit eine v1-Transaktion identifiziert.
Zwei Dinge, die Sie in Ihrem Decoder überprüfen sollten:
- Prioritätsgebührenextraktion. Lesen Sie
transactionConfig.priorityFee, wenn es existiert, und durchforsten Sie ComputeBudget-Anweisungen nur für Legacy- und v0-Transaktionen. Code, der nur Anweisungen durchsucht, liest jede v1-Transaktion als zahlend keine Prioritätsgebühr. - Proto-Version.
yellowstone-grpc-proto12.6.0 ist die erste Version, die die v1-Felder enthält, undhelius-laserstream0.8.4 (JavaScript), 0.6.3 (Rust) und 0.2.0 (Go) sind die ersten SDK-Versionen, die darauf basieren. Ältere Versionen lassentransactionConfigstillschweigend fallen.
So verbindet sich alles: Der Ablauf
Hier ist, was von den Grundlagen an passiert:- Die Nachschlagetabelle erstellen:
accountKeyslistet alle Adressen auf, die diese Transaktion berühren wird - Regeln festlegen:
headerlegt fest, wie viele Signaturen erforderlich sind und welche Konten schreibgeschützt sind - Befehle erstellen: Jeder
instructionzeigt auf:- Ein Programm (über
programIdIndex→accountKeys[index]) - Die benötigten Konten (über
accounts→ mehrereaccountKeys[index]Positionen) - Die Anweisungsdaten (im
datakodiert)
- Ein Programm (über
- Autorisierung hinzufügen:
signaturesbeweist, dass die erforderlichen Konten diese Transaktion genehmigt haben - Ablauf festlegen:
recentBlockhashstellt sicher, dass diese Transaktion später nicht erneut abgespielt werden kann
Die Ausführung: alles in Meta
Während die Nachricht zeigt, was der Benutzer tun wollte, zeigt die Meta, was tatsächlich passiert ist, als Validatoren die Transaktion ausführten.Grundlegende Ausführungsinformationen
Erfolg/Misserfolgerr: null= Erfolgerr: {...}= Fehler mit Fehlerdetailsfee= Lamports, die für diese Transaktion berechnet wurden
accountKeys Array nach Index:
- Konto 0: 15000 Lamports verloren (Gebührenzahlung)
- Konto 1: 1461600 Lamports gewonnen (neues Konto erstellt)
- Konto 3: 2001231920 Lamports gewonnen (Programmkonto)
Erweiterte Ausführungsdetails
Innere AnweisungenPraktische Dekodierungsmuster
Hier sind allgemeine Muster zum Extrahieren nützlicher Informationen aus dekodierten Transaktionen:Komplettes Beispiel: Jupiter Swap Decoder
Hier ist ein komplettes Beispiel, das Jupiter Swap-Transaktionen dekodiert und bedeutungsvolle Informationen extrahiert:Wichtige Erkenntnisse
- Zweiteilige Struktur: Jede Transaktion hat eine Nachricht (was angefordert wurde) und Meta (was tatsächlich passiert ist)
- Binärdekodierung: Verwenden Sie
bs58.encode(), um Binärfelder in lesbare Base58-Zeichenfolgen umzuwandeln - Kontoschlüssel-Nachschläge: Anweisungen verweisen auf Konten nach Index im
accountKeysArray - Saldenverfolgung: Vergleichen Sie
preBalancesundpostBalances, um zu sehen, was sich geändert hat - Transaktion v1: Lesen Sie das Rechenbudget und die Prioritätsgebühr von
transactionConfig, wenn es vorhanden ist; v1 Transaktionen haben keine ComputeBudget Anweisungen