Zum Hauptinhalt springen

Überblick

Die Solana-Blockchain speichert Daten in einem sequenziellen Ledger, an den Daten nur angehängt werden. Das ist ideal für Datenintegrität und Transaktionsdurchsatz, hat aber einen erheblichen Nachteil: Abfragen von historischen Daten sind dadurch sehr ineffizient und unvertretbar langsam. Komplexe Vorgänge erfordern häufig das Filtern, Aggregieren oder Verknüpfen von Daten aus mehreren Quellen. In diesen Fällen sind direkte Abfragen an Solana für die meisten realen Anwendungen unpraktisch. Um dieses Problem zu lösen, erstellen die meisten Unternehmen private Indizes für die historischen Daten von Solana. Dieser Leitfaden behandelt den gesamten Lebenszyklus: historische Daten mit getTransactionsForAddress und anderen archivierenden RPC-Methoden per backfill laden, eine Datenbank auswählen und den Index durch Echtzeit-Streaming aktuell halten.

Wann du das verwenden solltest

Erstelle einen Index, wenn:
  • Dein Produkt schnelle, gefilterte Abfragen benötigt, für die direkte RPC-Aufrufe zu langsam sind (z. B. die token-Konten und Guthaben einer Wallet oder der vollständige Verlauf eines Handelspaars)
  • Du On-Chain-Daten filtern, aggregieren oder verknüpfen oder sie mit Off-Chain-Daten kombinieren musst (CEX-Preise, KYC, Labels)
  • Du Werte wie PnL, Analysen zu Inhabern oder den Verkaufsverlauf von NFTs berechnest, die vorverarbeitete, abfragbare Daten erfordern
  • Du viele Nutzer bedienst und dir die Latenz pro request gegenüber der Blockchain nicht leisten kannst
Wenn du nur standardmäßige Wallet- oder Asset-Daten benötigst, ist eine verwaltete API möglicherweise einfacher als ein eigener Index. Weitere Informationen findest du unten unter Ergänzende Optionen.

Was bedeutet die Indexierung von Solana-Daten?

Bei der Indexierung werden Daten von der Solana-Blockchain abgefragt und in einer Backend-Datenbank (z. B. PostgreSQL oder ClickHouse) gespeichert. Damit kannst du requests von Kunden schnell bearbeiten, ohne die Blockchain direkt über Solana-RPC-Aufrufe abfragen zu müssen. Ein Indexer erledigt normalerweise vier Aufgaben:
  1. Historische Daten per backfill laden: Frage mit archivierenden RPC-Methoden alle historischen Daten ab
  2. Neue Daten streamen: Verarbeite neue Blöcke, sobald das Netzwerk sie bestätigt
  3. Daten parsen und transformieren: Extrahiere relevante Daten aus den bestätigten Blöcken (z. B. Transaktionen, Zustandsänderungen usw.)
  4. Daten in einer Datenbank organisieren: Aktualisiere den Index mit den neuen Daten

Warum erstellen die meisten Unternehmen Solana-Indizes?

Unternehmen erstellen Solana-Indizes, weil ihr Geschäft vom schnellen Echtzeitzugriff auf zweckgebundene Blockchain-Daten abhängt, die native RPCs nicht bieten (z. B. den Verkaufsverlauf von NFTs). Unternehmen nutzen benutzerdefinierte Indizes außerdem, um Off-Chain-Daten (z. B. Preise zentralisierter Börsen, KYC-Informationen usw.) mit ihren On-Chain-Daten zu kombinieren.

Wallet-Beispiel

Wenn eine Solana-Wallet beispielsweise die token-Konten und Guthaben eines Nutzers schnell zurückgeben muss, sind direkte Abfragen an Solana mit getTokenAccountsByOwner und getTokenAccountBalance zu langsam und könnten das Produkt unbrauchbar machen. Stattdessen verwalten Wallets normalerweise eigene Indizes für Kundenadressen, token und Kontoguthaben.

Handelsbeispiel

Ebenso könnte ein Kryptohandelsunternehmen sämtliche Handelsaktivitäten für ein bestimmtes Handelspaar (z. B. SOL-USDC) oder einen bestimmten Markt protokollieren wollen, um seine Handelsalgorithmen rückwirkend zu testen. Eine direkte Abfrage dieser Daten von der Blockchain wäre für jede praktische Handelsanalyse viel zu langsam. Quantitative Händler können stattdessen Indizes für den SOL-USDC-Markt erstellen und sie mit den neuesten Trades über Echtzeit-Streaming-Produkte wie LaserStream aktualisieren.

Filterbeispiel

Stell dir vor, ein Nutzer möchte Transaktionen in seiner Frontend-Anwendung nach bestimmten Kriterien filtern (z. B. nach token-Typ, Übertragungsbetrag, Datum oder Wallet-Adresse). Ohne Indexer müsste deine App Millionen von Transaktionen in Hunderttausenden von Blöcken durchsuchen und jede einzelne anhand der Filterkriterien prüfen. Dieser Vorgang ist für die Nutzererfahrung moderner Produkte zu langsam.

PnL-Beispiel

Um den Gewinn und Verlust (PnL) eines Händlers zu berechnen, müsstest du:
  • Jede mit seiner Wallet verknüpfte Transaktion in einem bestimmten Zeitraum finden
  • Swap-Transaktionen herausfiltern und als Käufe oder Verkäufe kennzeichnen
  • Ermitteln, wie viele Gebühren der Nutzer bei jedem Swap bezahlt hat
  • Die historischen Preisdaten für jeden token zum Zeitpunkt des jeweiligen Trades abrufen
  • Den PnL jeder Transaktion aggregieren, um den gesamten PnL des Händlers zu berechnen
All das in Echtzeit zu berechnen, ist unpraktisch und erfordert eine schnellere, besser skalierbare Lösung. Mit einem Index sind all diese Informationen bereits verarbeitet und in einer abfragbaren Datenbank gespeichert. Der PnL eines Händlers lässt sich dann mit einem einzigen API-Aufruf berechnen, der sofort beantwortet wird. Sehen wir uns drei Ansätze an, mit denen du einen Solana-Index per backfill füllst und aktuell hältst.

Schritt 1: Historische Daten abrufen

Beim Erstellen eines Solana-Index musst du zuerst alle für dich relevanten historischen Daten abrufen. Dafür gibt es drei Hauptmethoden:
  1. getTransactionsForAddress (empfohlen)
  2. getSignaturesForAddress und getTransaction
  3. getBlock

Methode 1: getTransactionsForAddress (empfohlen)

Mit der RPC-Methode getTransactionsForAddress kannst du die vollständigen Transaktionsdetails für ein beliebiges Segment der Blockchain-Daten abrufen. Dank der leistungsfähigen Filter rufst du keine Daten ab, die dein Index nicht benötigt. Durch die Rückwärtssuche kannst du Transaktionen außerdem in chronologischer Reihenfolge abrufen.

Schritte zur Verwendung dieser Methode

  • Bestimme den Zeitraum, aus dem du Daten benötigst, und lege den Filter entsprechend fest
  • Setze transactionDetails auf full, um alle Transaktionsdetails abzurufen
  • Konfiguriere bei Bedarf den Filter tokenAccounts, um Transaktionen zugehöriger token-Konten einzuschließen
  • Paginiere die Ergebnisse mit paginationToken
  • Extrahiere bei jeder Iteration die benötigten Daten und speichere sie in deiner Datenbank

Vorteile von getTransactionsForAddress

Die wichtigsten Vorteile des gTFA endpoint sind Geschwindigkeit und Einfachheit. Mit slot- und zeitbasierten Filtern, Unterstützung für token-Konten, Rückwärtssuche und Paginierung kannst du beliebige Daten aus jedem Zeitpunkt der Solana-Historie mit einem einzigen Aufruf abrufen. Komplexe Schleifen oder Wiederholungslogik sind nicht nötig. Anders als getSignaturesForAddress kann die Methode auch Transaktionen einbeziehen, an denen zugehörige token-Konten im Besitz der Adresse beteiligt sind. Wenn sich dein Index speziell auf Bewegungen von token und nativem SOL konzentriert (Zahlungen, Ledger, Kontenabgleich), gibt getTransfersByAddress statt vollständiger Transaktionen geparste, für den Abgleich vorbereitete Übertragungszeilen zurück. So sparst du einen Parsing-Schritt.

Methode 2: getSignaturesForAddress und getTransaction

Vor der Veröffentlichung von gTFA bestand der Standardansatz für die Abfrage historischer Daten darin, Signaturen rekursiv mit getSignaturesForAddress zu durchlaufen (von der neuesten zur ältesten) und anschließend getTransaction aufzurufen, um die vollständigen Transaktionsdetails zu extrahieren.

Schritte zur Verwendung dieser Methode

So verwendest du diese Methode:
  • Rufe getSignaturesForAddress auf
  • Speichere die Signatur der letzten bei diesem Aufruf empfangenen Transaktion
  • Setze beim nächsten Aufruf von getSignaturesForAddress den Parameter before auf diese Signatur
  • Wiederhole diesen Vorgang so lange wie nötig in einer Schleife
  • Rufe für jede auf diese Weise abgerufene Transaktionssignatur getTransaction auf, um die vollständigen Transaktionsdetails abzurufen
  • Füge die relevanten Daten in deine Datenbank ein

Nachteile dieser Methode

Leider musst du für diese Methode:
  • Bei der neuesten Transaktion beginnen und rückwärts arbeiten
  • Für jede Transaktion einen zusätzlichen RPC-Aufruf ausführen
  • Eine threadsichere Warteschlange für die parallele Verarbeitung erstellen
  • Logik für Wiederholungsversuche und Backoffs implementieren, um fehlende Daten und eine Einschränkung durch das rate limit zu vermeiden
  • Beachten, dass Transaktionen mit zugehörigen token-Konten im Besitz der Adresse nicht enthalten sind
Diese Methode funktioniert zwar, ist aber komplizierter, weniger flexibel und verbraucht deutlich mehr Credits. Verwende stattdessen getTransactionsForAddress, um den vollständigen Wallet-Verlauf einschließlich der token-Konten abzurufen.

Methode 3: getBlock verwenden

Die Methode getBlock ist am effektivsten, wenn ein hoher Anteil der Transaktionen in deinen Zielblöcken für deine Analyse relevant ist. Das gilt etwa bei der Indexierung von Transaktionen häufig genutzter Solana-Programme wie DFlows Aggregator, dem Pump.fun-Programm oder dem token-Programm von Solana.

Schritte zur Verwendung dieser Methode

Der grundlegende Ablauf zum Abfragen historischer Daten mit getBlock umfasst:
  • Lege einen Zeitraum für die Abfrage fest
  • Konvertiere diesen Zeitraum in slot-Nummern
  • Rufe die entsprechenden Blöcke nacheinander ab (vorwärts oder rückwärts)
  • Filtere in jedem Block die für deinen Index relevanten Transaktionen
  • Speichere die relevanten Informationen daraus in deinem Index
Für die meisten Anwendungsfälle ist diese Methode grundsätzlich ineffizient, da du alle Transaktionen eines Blocks abrufst, obwohl normalerweise nur ein kleiner Teil davon für deine Analyse relevant ist. Verwende diese Methode nur, wenn du die Transaktionen häufig genutzter Programme untersuchst oder deine Zieldaten nicht durch adressbasierte Filter erfassen kannst.

Schritt 2: Solana-Daten mit deiner Datenbank synchronisieren

Nachdem du die historischen Daten abgerufen hast, musst du sie transformieren und effizient in einer Datenbank speichern. Passe deine Speicherlösung an deinen konkreten Anwendungsfall an — eine Universallösung gibt es nicht. Die richtige Datenbank hängt von der Größe deines Datensatzes, den Latenzanforderungen, den Abfragemustern und der Erfahrung deines Teams ab.

Option 1: SQL-Datenbanken

Für die meisten Anwendungsfälle solltest du Solana-Daten in relationalen Datenbanken wie PostgreSQL speichern. SQL ist flexibel, weitverbreitet und leicht zu erlernen. Moderne relationale Datenbanken können auf mehr als 100 Millionen Zeilen skalieren und bieten weiterhin Vorteile wie ACID-Konformität, komplexe Joins und leistungsfähige Sekundärindizes. Verwende SQLite für Prototypen, die lokale Entwicklung oder wenn du eine Datenbank in einer einzigen Datei ohne Konfigurationsaufwand benötigst. SQLite eignet sich ideal, wenn dein Datensatz nur wenige Gigabyte groß bleibt. Verwende PostgreSQL für Produktionsanwendungen, die Datenreplikation, gleichzeitigen Zugriff mehrerer Clients oder erweiterte Funktionen wie Volltextsuche und JSON-Operatoren benötigen. Für die meisten produktiven Solana-Indexer empfehlen wir PostgreSQL.

Implementierungsbeispiel:

Als Beispiel zeigen wir, wie du token-Übertragungen in einer PostgreSQL-Datenbank speicherst. Erstelle zuerst eine Tabelle:
Füge anschließend Indizes für häufig abgefragte Spalten hinzu:
Du kannst auch partielle Indizes erstellen, wenn nur ein Teil der Daten häufig abgefragt wird. So erstellst du einen Index ausschließlich für hochwertige Übertragungen:
Verwende beim backfill der Daten Bulk-INSERTs und vorbereitete Anweisungen, um eine optimale Schreibgeschwindigkeit zu erreichen.

Option 2: Spaltenorientierte Datenbanken

Spaltenorientierte Datenbanken sind für analytische Abfragen, Aggregationen und große Mengen an Zeitreihendaten optimiert. Wenn du mehrere Milliarden Transaktionen indexieren musst, sind spaltenorientierte Datenbanken wie ClickHouse oder Cassandra die beste Option. Verwende ClickHouse, wenn du analytische Echtzeitabfragen für große Datensätze benötigst. ClickHouse ist für schnelle Lesevorgänge, Aggregationen und Zeitreihenanalysen optimiert. Verwende Cassandra, wenn du einen extrem hohen Schreibdurchsatz, mühelose horizontale Skalierung und hohe Fehlertoleranz benötigst. Dadurch eignet sich Cassandra ideal für die kontinuierliche Aufnahme riesiger Mengen an Solana-Daten.

Implementierungsbeispiel:

Wir zeigen, wie du token-Übertragungen in einer ClickHouse-Datenbank speicherst. Erstelle dazu eine Tabelle, die die MergeTree-Tabellen-Engine verwendet. Sie ist für hohe Aufnahmeraten ausgelegt und eignet sich daher ideal für die Indexierung. Verwende diesen Befehl:
In dieser Konfiguration dient (token_mint, date) sowohl als Primärschlüssel als auch als Sortierschlüssel. ClickHouse ordnet die Daten auf dem Datenträger anhand deines Sortierschlüssels. Das ist optimal, um einen einzelnen token-Mint abzufragen und die response nach Datumsbereichen einzugrenzen. Hier ist eine Beispielabfrage:
Transaktionssignaturen und Adressen werden im Datenformat FixedString(N) gespeichert, das exakt N Byte speichert. ClickHouse komprimiert Daten automatisch. Das senkt die Speicherkosten um den Faktor 10 bis 20 und verbessert die Abfrageleistung. Optimiere die Abfrageleistung mit materialisierten Sichten, um häufige Aggregationen im Voraus zu berechnen. Du könntest beispielsweise das tägliche Übertragungsvolumen von token vorab berechnen und für volumenbezogene Diagramme auf einem Dashboard verwenden.

Option 3: Data Lakes

Data Lakes eignen sich ideal, um riesige Mengen an rohen und verarbeiteten Blockchain-Daten langfristig zu archivieren und analytisch abzufragen. Eine einfache Implementierung verwendet das Parquet-Datenformat mit Amazon Athena. Parquet ist ein spaltenorientiertes Dateiformat zur effizienten Speicherung und Abfrage von Daten. Amazon Athena ist ein interaktiver Abfragedienst. Damit kannst du in Amazon S3 gespeicherte Daten mit Standard-SQL analysieren, ohne Infrastruktur einzurichten oder Daten in eine separate Datenbank zu laden.
Data Lakes werden nur empfohlen, wenn du große Mengen unstrukturierter Daten abfragen musst. Für die meisten Anwendungsfälle empfehlen wir eine SQL-Datenbank (Option 1).

Implementierungsbeispiel:

Wir möchten ein Archiv mit token-Übertragungen erstellen und diese abfragen. Zuerst müssen wir sie in S3 speichern: Erstelle einen Bucket namens solana_index und partitioniere deine Daten zu token-Übertragungen anhand der Zeit mit dieser Schlüsselstruktur:
Die Übertragungen jedes Tages werden in einer separaten Parquet-Datei im entsprechenden Datumsordner gespeichert. Transformiere die Übertragungen bei der Verarbeitung aus Solana in das Parquet-Format und schreibe sie in das jeweilige S3-Objekt. Später erstellst du eine Tabelle in Athena und verbindest sie mit dem Bucket. So kannst du Abfragen wie diese direkt für die Daten im Bucket ausführen:

Indexierungs-Frameworks verwenden

Verwende Carbon und ähnliche Frameworks, um keinen Boilerplate-Code schreiben zu müssen und deinen Indexer innerhalb von Stunden statt Tagen einzurichten.

Wichtige Funktionen:

  • Vorgefertigte Decoder für beliebte Programme (token-Programm, DeFi-Protokolle, Metaplex)
  • Konfigurierbare Datenquellen (RPC, LaserStream, Enhanced WebSockets)
  • Integrierte Unterstützung für backfill und Echtzeit-Streaming
  • Ausgabe an mehrere Speicher-Backends (Postgres ist standardmäßig enthalten)
  • Vollständig anpassbar: Du kannst eigene Datenquellen, Decoder und Datensenken einrichten

Schritt 3: Halte deinen Index aktuell

Nachdem du historische Daten per backfill geladen hast, benötigst du eine Echtzeit-Streaming-Lösung, um deinen Index bei neuen Blockchain-Aktivitäten aktuell zu halten. Andernfalls veraltet dein Index.

Methode 1: LaserStream (empfohlen)

Wir empfehlen LaserStream gRPC als Standardlösung für alle produktiven Indexierungsanwendungen. Es wurde speziell für zuverlässiges, extrem latenzarmes und fehlertolerantes Daten-Streaming entwickelt. LaserStream bietet unter anderem folgende Vorteile:
  • 24-stündige historische Wiedergabe: Wenn dein Indexer die Verbindung trennt, gibt LaserStream automatisch alle verpassten Transaktionen ab der Unterbrechung wieder
  • Automatische Wiederverbindung: Unsere LaserStream SDKs (Rust, Go, JS/TS) verarbeiten Netzwerkunterbrechungen nahtlos für dich
  • Node-Failover: Deine LaserStream-Verbindung aggregiert gleichzeitig Daten von mehreren Nodes und gewährleistet so maximale Verfügbarkeit
LaserStream kombiniert Geschwindigkeit und Zuverlässigkeit und eignet sich ideal für Echtzeitanwendungen wie Live-Transaktionsfeeds, Handels-Dashboards und sofortige Guthabenaktualisierungen.

LaserStream für die Indexierung verwenden

Verwende die Methode subscribe, um Blockchain-Ereignisse zu abonnieren. Beachte dabei diese Best Practices:
  • Grenze deinen Filter so weit wie möglich ein: Abonniere nur die Daten, die du tatsächlich indexieren musst. So minimierst du den Bandbreitenverbrauch und den Verarbeitungsaufwand.
  • Verwende das commitment-Level confirmed: Es bietet ein ausgewogenes Verhältnis zwischen Latenz und Endgültigkeit. Das Level processed ist möglicherweise zu unzuverlässig, während finalized eine Latenz von ~13 Sekunden hinzufügt
  • Setze failed: false, sofern du nicht ausdrücklich fehlgeschlagene Transaktionen verfolgen musst
  • Schließe Abstimmungstransaktionen aus (vote: false), da sie für die Indexierung nicht relevant sind
Sehen wir uns ein Beispiel an. Verwende das folgende Abonnement, um alle neuen token-Übertragungen zu indexieren:

Methode 2: LaserStream WebSocket verwenden

LaserStream WebSocket — die WebSocket-Variante von LaserStream einschließlich der Helius-spezifischen Erweiterung transactionSubscribe — läuft auf demselben Backend wie LaserStream gRPC. Wenn du gRPC nicht benötigst, ist sie eine kostengünstige Alternative für Echtzeit-Streaming. Verwende LaserStream WebSocket, wenn:
  • Deine Anwendung gelegentliche Datenlücken tolerieren kann
  • Echtzeitaktualisierungen wichtig, aber nicht geschäftskritisch sind
  • Du bereits Infrastruktur hast, um fehlende Daten zu erkennen und per backfill nachzuladen
  • Dein Budget stark begrenzt ist und du die Streaming-Kosten minimieren musst
  • Du einen Prototyp entwickelst oder Tests durchführst, bevor du dich für LaserStream entscheidest
Bei der Auswahl von WebSockets musst du jedoch einige Kompromisse berücksichtigen:
  • Geschwindigkeit: LaserStream WebSocket läuft auf demselben Backend wie LaserStream gRPC. Das WebSocket-Protokoll verursacht jedoch zusätzlichen Aufwand durch JSON-Framing und einzelne Nachrichten. Verwende für die geringstmögliche Latenz bei denselben Daten LaserStream gRPC
  • Zuverlässigkeit: Es gibt keine Garantie für historische Wiedergaben. Wenn dein WebSocket die Verbindung trennt, musst du Lücken manuell erkennen und mit RPC-Methoden per backfill schließen
  • Komplexität: Erfordert zusätzliche Überwachungsinfrastruktur, um die Vollständigkeit der Daten zu gewährleisten

WebSockets für die Indexierung verwenden

Um einen Index zu aktualisieren, der alle token-Übertragungen speichert, abonnierst du transactionSubscribe wie folgt:

Erste Schritte

Um einen robusten Solana-Index zu erstellen und Daten per backfill zu laden, musst du drei zentrale Herausforderungen lösen:
  1. Historische Daten effizient abrufen
  2. Daten für schnelle Abrufe transformieren und speichern
  3. Indexierte Solana-Daten in Echtzeit aktuell halten
Mit unserem neuen hochmodernen Archivsystem, archivierenden Aufrufen wie getTransactionsForAddress und branchenführenden Daten-Streaming-Lösungen wie LaserStream ist es einfacher und praktikabler denn je, einen Solana-Index zu erstellen.

Ergänzende Optionen

Ein eigener Index gibt dir vollständige Kontrolle, ist aber nicht immer notwendig. Für häufige Anforderungen kann eine verwaltete Helius API einen benutzerdefinierten Index ersetzen oder ergänzen:
  • DAS API — Frage NFTs, fungible token und komprimierte Assets ab (Metadaten, Besitz, Guthaben, nach Eigentümer, Sammlung oder Ersteller), ohne Asset-Daten selbst zu indexieren.
  • Wallet API — Übergeordnete REST endpoints für Wallet-Guthaben, Verlauf, Übertragungen und Identität, mit USD-Werten und einer einfacheren response-Struktur.
Viele Teams verwenden diese APIs für Portfolio-, token- und Wallet-Daten und nutzen einen benutzerdefinierten Index nur für zweckgebundene Daten, die von den verwalteten APIs nicht abgedeckt werden.

Nächste Schritte