NEU: Helius übernimmt Light Protocol
getTransfersByAddress
Blog/Updates

getTransfersByAddress: Geparster Solana-Transferverlauf mit 1 Aufruf

Produkt @ HeliusKiryl Miranovich auf XKiryl Miranovich auf LinkedIn
5 Min. Lesezeit

getTransfersByAddress ist eine neue, exklusiv bei Helius verfügbare Solana-RPC-Methode, die geparste, menschenlesbare Token- und SOL-Transferdatensätze für eine Wallet-Adresse zurückgibt — mit nativen Filtern für Mint, Zeit, Betrag, Slot, Richtung und Gegenpartei.

Sie ist die perfekte Ergänzung zu getTransactionsForAddress (gTFA). Während gTFA vollständige Transaktionsdaten zurückgibt, liefert getTransfersByAddress kompakte Transferobjekte: Wer hat was wann, an wen und in welcher Höhe gesendet?

Warum brauchen wir eine RPC-Methode speziell für Transfers?

Die meisten Wallet-, Zahlungs- und Portfolioprodukte benötigen nicht die gesamten Transaktionsdaten. Sie benötigen Transfers.

Was tun sie also? Jedes Team schreibt eine eigene Version desselben Transfer-Parsers. Leider behandeln die meisten davon Sonderfälle falsch.

Bisher mussten Entwickler für einen übersichtlichen Solana-Transferverlauf:

  1. Signaturen mit getSignaturesForAddress abrufen
  2. Jede Signatur mit getTransaction abrufen
  3. Pre-/Post-Salden, Token-Salden und innere Anweisungen parsen
  4. Transfers rekonstruieren, die unterschiedlichen Gebührenregeln von SPL Token und Token-2022 berücksichtigen und das Rauschen durch das Wrapping und Unwrapping von WSOL auflösen
  5. Dies über mehrere Seiten hinweg wiederholen, erneute Versuche verwalten und Ergebnisse speichern

Auch wenn die getTransactionsForAddress-Methode die Schritte 1 und 2 in einem Aufruf zusammenfasst, bleiben die Schritte 3–5 weiterhin am Entwickler hängen.

Jetzt erledigt getTransfersByAddress diese Arbeit für dich und gibt das Ergebnis als strukturierte Liste zurück.

Antwort von getTransfersByAddress

Jedes Transferobjekt enthält die Signatur, den Slot, die Blockzeit, den Transfertyp, Absender, Empfänger, Mint, Betrag (roh und für die Benutzeroberfläche aufbereitet), Dezimalstellen, Bestätigungsstatus und genaue Anweisungsindizes. So kannst du jeden Transfer seiner Quelltransaktion zuordnen.

Code
{
  "signature": "<TX_SIGNATURE>",
  "slot": 315073428,
  "blockTime": 1736159420,
  "type": "transfer",
  "fromUserAccount": "<SENDER_WALLET>",
  "toUserAccount": "<RECIPIENT_WALLET>",
  "fromTokenAccount": "<SENDER_TOKEN_ACCOUNT>",
  "toTokenAccount": "<RECIPIENT_TOKEN_ACCOUNT>",
  "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "amount": "2500000",
  "decimals": 6,
  "uiAmount": "2.5",
  "confirmationStatus": "finalized",
  "transactionIdx": 35,
  "instructionIdx": 1,
  "innerInstructionIdx": 0
}

Das Typfeld zeigt dir genau, was passiert ist — transfer, transferFee, mint, burn, wrap, unwrap, changeAccountOwner oder withdrawWithheldFee. Du musst das Verhalten also nicht aus rohen Programmdaten ableiten.

Warum ist das Parsen von Solana-Transfers schwierig?

Ein Transfer in einer Solana-Transaktion ist kein einheitliches Konzept.

Es ist eine Kategorie, hinter der sich ein halbes Dutzend Sonderfälle verbergen. Wenn du nur einen davon falsch behandelst, beschädigst du deine Daten.

SOL vs. WSOL

Natives SOL und Wrapped SOL erscheinen einem Nutzer wie derselbe Vermögenswert, befinden sich aber in unterschiedlichen Teilen einer Transaktion.

Natives SOL wird über die Pre-/Post-Lamport-Salden von Systemkonten übertragen. WSOL wird über SPL-Token-Salden auf Token-Konten übertragen.

Ein Nutzer, der auf Jupiter einen Swap durchführt, kann SOL in WSOL wrappen, WSOL gegen USDC tauschen und es anschließend nie unwrappen — dadurch bleibt ein WSOL-Token-Konto zurück.

Aus Sicht des Nutzers hat er SOL ausgegeben. Aus Sicht des Netzwerks gab es drei Transfers und einen Wrap.

Schlimmer noch: Der Wrap selbst ist kein Transfer an einen anderen Eigentümer — dieselbe Wallet verschiebt Lamports in ihr eigenes Token-Konto. Wenn du ihn als Transfer zählst, erfasst du die Aktivität des Nutzers doppelt.

Transfergebühren von Token-2022

Token-2022 führte TransferCheckedWithFee ein. Dabei entspricht die Belastung des Absenders nicht der Gutschrift des Empfängers.

Die Differenz wird als Gebühr im Token-Konto des Empfängers einbehalten und kann später über withdrawWithheldFee an eine Gebühreninstanz ausgezahlt werden.

Ein einfacher Parser erkennt einen Transfer und berechnet den Betrag falsch. Ein sorgfältiger Parser erkennt die Gebührenerweiterung, teilt die Anweisung in einen Transfer und eine Rückstellung für einbehaltene Gebühren auf und verfolgt das Gebührenkonto separat.

Mints und Burns

Token, die in ein Konto gemintet werden, haben keinen Absender. Verbrannte Token haben keinen Empfänger. In den Differenzen zwischen Pre- und Post-Salden sehen beide wie „Transfers“ aus. Wenn du sie jedoch mit Transfers zwischen Wallets gleichsetzt, verfälschst du die Analyse der Gegenparteien — Wallets würden scheinbar Mittel von der Nulladresse „empfangen“ und Mittel ins Nichts „senden“.

getTransfersByAddress stellt diese als die Typen mint und burn dar, wobei fromUserAccount oder toUserAccount auf null gesetzt ist. So kannst du sie je nach Anwendungsfall ein- oder ausschließen.

Vorteile von getTransfersByAddress

Die Methode getTransfersByAddress unterstützt Filter, für die du bisher vollständige Transaktionsverläufe clientseitig abrufen und parsen musstest. 

Nach Mint suchen

Gib nur Transfers für einen bestimmten Token zurück.

Code
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "getTransfersByAddress",
  "params": [
    "<WALLET_ADDRESS>",
    { "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" }
  ]
}

Nach Betrag suchen

Filtere den Rohbetrag mit den Vergleichen gt, gte, lt und lte. Das ist nützlich, um Whales zu erkennen, Dust zu ignorieren (also Konten mit unbedeutenden Token-Beträgen) oder ungewöhnliche Aktivitäten zu markieren.

Code
{
  "params": [
    "<WALLET_ADDRESS>",
    {
      "mint": "So11111111111111111111111111111111111111112",
      "filters": {
        "amount": { "gte": 1000000000, "lt": 10000000000 }
      }
    }
  ]
}

Nach Zeit suchen

Die Blockzeit wird als Unix-Zeitstempelbereich unterstützt. Slot-Bereiche funktionieren genauso für slotgenaue Abfragen.

Code
{
  "params": [
    "<WALLET_ADDRESS>",
    {
      "filters": {
        "blockTime": { "gte": 1735718400, "lt": 1738396800 }
      }
    }
  ]
}

Nach Gegenpartei suchen

Kombiniere die Parameter with und direction, um Transfers zwischen zwei bestimmten Wallets in beide Richtungen abzufragen.

Code
{
  "params": [
    "<WALLET_ADDRESS>",
    {
      "with": "<COUNTERPARTY_WALLET>",
      "direction": "in"
    }
  ]
}

SOL-Modus

Natives SOL und WSOL erscheinen auf Solana unterschiedlich, bedeuten für Nutzer aber meist dasselbe. Deshalb bietet die Methode getTransfersByAddress den Parameter solMode.

merged (Standard)

WSOL wird wie natives SOL behandelt.

Zeilen für Wraps und Unwraps werden ausgeschlossen. Eine Abfrage nach dem nativen SOL-Mint gibt sowohl native SOL- als auch WSOL-Transfers zurück.

separate

In diesem Modus bleibt WSOL als eigenständiger Mint erhalten. Außerdem werden Lebenszykluszeilen für Wraps und Unwraps einbezogen, damit alles vollständig nachvollziehbar bleibt.

Für die meisten Produktanwendungen eignet sich merged. Für Abstimmungen, Buchhaltung und Analysen auf Protokollebene eignet sich häufig separate.

Seitennummerierung und Sortierung

Standardmäßige cursorbasierte Seitennummerierung über paginationToken mit bis zu 100 Datensätzen pro Seite. sortOrder akzeptiert asc und desc.

Code
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "getTransfersByAddress",
  "params": [
    "<WALLET_ADDRESS>",
    { "limit": 50, "paginationToken": "315069220:308:2:1" }
  ]
}

Wann du getTransfersByAddress verwenden solltest

getTransfersByAddress und getTransactionsForAddress sind ähnlich, erfüllen aber unterschiedliche Zwecke. 

AnforderungMethode
Geparste Token- und SOL-Transfers mit FilterngetTransfersByAddress
Vollständige Transaktionsdaten oder Aktivitäten ohne TransfersgetTransactionsForAddress
Dekodierte Anweisungen für jede Signatur oder AdresseParsed Events API
Nur SignaturengetTransactionsForAddress mit transactionDetails: 'signatures'
Echtzeit-Streaming von TransfersLaserStream

Erste Schritte

Die Methode getTransfersByAddress ist ab heute in allen kostenpflichtigen Tarifen ab dem Developer-Tarif verfügbar. Sie kostet 10 Credits pro Anfrage und ist Teil deiner standardmäßigen RPC-Ratenbegrenzungsgruppe.

Verwende sie mit deiner bestehenden Helius-RPC-URL:

Code
const response = await fetch("https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: "1",
    method: "getTransfersByAddress",
    params: ["<WALLET_ADDRESS>"]
  })
});

const data = await response.json();
console.log(data.result.data);

In der API-Referenz findest du alle Details zu Parametern und Antworten.

Helius abonnieren

Bleib bei der Solana-Entwicklung auf dem Laufenden und erhalte Updates, wenn wir neue Beiträge veröffentlichen