NOUVEAU : Helius acquiert Light Protocol
getTransfersByAddress
Blog/Actualités

getTransfersByAddress : historique analysé des transferts Solana en 1 appel

Produit chez HeliusKiryl Miranovich sur XKiryl Miranovich sur LinkedIn
5 min de lecture

getTransfersByAddress est une nouvelle méthode RPC Solana exclusive à Helius qui renvoie des enregistrements analysés et lisibles des transferts de tokens et de SOL pour une adresse de portefeuille, avec des filtres natifs par mint, date, montant, slot, direction et contrepartie.

C’est le complément idéal de getTransactionsForAddress (gTFA). Alors que gTFA renvoie les données complètes des transactions, getTransfersByAddress renvoie des objets de transfert concis : qui a envoyé quoi, à qui, quand et pour quel montant.

Pourquoi avons-nous besoin d’une méthode RPC dédiée aux transferts ?

La plupart des produits de portefeuille, de paiement et de gestion de portefeuille n’ont pas besoin de toutes les données d’une transaction. Ils ont besoin des transferts.

Alors, que font-ils ? Chaque équipe écrit sa propre version du même parseur de transferts et, malheureusement, la plupart gèrent mal les cas limites.

Jusqu’à présent, pour créer un historique propre des transferts Solana, les développeurs devaient :

  1. Récupérer les signatures avec getSignaturesForAddress
  2. Récupérer chaque signature avec getTransaction
  3. Analyser les soldes avant/après, les soldes de tokens et les instructions internes
  4. Reconstituer les transferts, gérer les différences de sémantique des frais entre SPL Token et Token-2022, et démêler le bruit généré par l’encapsulation et la désencapsulation de WSOL
  5. Répéter l’opération sur plusieurs pages, gérer les nouvelles tentatives et stocker les résultats

Même si la méthode getTransactionsForAddress regroupe les étapes 1 et 2 en un seul appel, les étapes 3 à 5 restent à la charge du développeur.

Désormais, getTransfersByAddress effectue ce travail pour vous et renvoie le résultat sous forme de liste structurée.

Réponse de getTransfersByAddress

Chaque objet de transfert comprend la signature, le slot, l’heure du bloc, le type de transfert, l’expéditeur, le destinataire, le mint, le montant (brut et affichable), les décimales, le statut de confirmation et les indices précis des instructions, afin que vous puissiez relier chaque transfert à sa transaction source.

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
}

Le champ de type indique précisément ce qui s’est produit — transfer, transferFee, mint, burn, wrap, unwrap, changeAccountOwner ou withdrawWithheldFee — vous n’avez donc pas à déduire le comportement à partir des données brutes du programme.

Pourquoi l’analyse des transferts Solana est-elle difficile ?

Un transfert au sein d’une transaction Solana n’est pas un concept unique.

C’est une catégorie qui masque une demi-douzaine de cas limites, et la moindre erreur dans leur traitement corrompt vos données.

SOL ou WSOL

Pour un utilisateur, le SOL natif et le Wrapped SOL semblent être le même actif, mais ils se trouvent dans différentes parties d’une transaction.

Le SOL natif est transféré au moyen des soldes de lamports avant/après sur les comptes système. Le WSOL est transféré au moyen des soldes de tokens sur les comptes de tokens.

Un utilisateur effectuant un swap sur Jupiter peut encapsuler du SOL en WSOL, échanger le WSOL contre de l’USDC, puis ne jamais le désencapsuler, laissant ainsi un compte de tokens WSOL.

Du point de vue de l’utilisateur, il a dépensé du SOL. Du point de vue du réseau, il y a eu trois transferts et une encapsulation.

Pire encore, l’encapsulation elle-même n’est pas un transfert vers un autre propriétaire : le même portefeuille déplace des lamports vers son propre compte de tokens. La comptabiliser comme un transfert revient à compter deux fois l’activité de l’utilisateur.

Frais de transfert Token-2022

Token-2022 a introduit TransferCheckedWithFee, où le débit de l’expéditeur ne correspond pas au crédit du destinataire.

La différence est retenue comme frais sur le compte de tokens du destinataire et peut être versée ultérieurement à une autorité de frais via withdrawWithheldFee.

Un parseur naïf ne voit qu’un transfert et se trompe sur le montant. Un parseur rigoureux détecte l’extension de frais, décompose l’instruction en un transfert et une accumulation de frais retenus, puis suit séparément le compte de frais.

Émissions et destructions

Les tokens émis sur un compte n’ont pas d’expéditeur. Les tokens détruits n’ont pas de destinataire. Dans les variations de soldes avant/après, les deux ressemblent à des « transferts », mais les confondre avec des transferts entre portefeuilles fausse l’analyse des contreparties : vous verriez des portefeuilles « recevoir » des fonds de l’adresse zéro et « envoyer » des fonds dans le néant.

getTransfersByAddress les représente sous les types mint et burn, avec fromUserAccount ou toUserAccount défini sur null. Vous pouvez ainsi les inclure ou les exclure selon ce que vous développez.

Avantages de getTransfersByAddress

La méthode getTransfersByAddress accepte des filtres qui nécessitaient auparavant de récupérer et d’analyser côté client l’intégralité de l’historique des transactions. 

Rechercher par mint

Renvoyez uniquement les transferts d’un token spécifique.

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

Rechercher par montant

Filtrez par montant brut à l’aide des comparaisons gt, gte, lt et lte. Utile pour repérer les baleines, ignorer les poussières (c’est-à-dire les comptes contenant des quantités insignifiantes de tokens) ou signaler une activité inhabituelle.

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

Rechercher par date

L’heure du bloc peut être définie sous forme de plage d’horodatages Unix. Les plages de slots fonctionnent de la même manière pour les requêtes nécessitant une précision au niveau du slot.

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

Rechercher par contrepartie

Combinez les paramètres with et direction pour rechercher les transferts entre deux portefeuilles spécifiques, dans un sens comme dans l’autre.

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

Mode SOL

Le SOL natif et le WSOL apparaissent différemment sur Solana, mais représentent généralement la même chose pour un utilisateur. La méthode getTransfersByAddress propose donc un paramètre solMode.

merged (par défaut)

Le WSOL est traité comme du SOL natif.

Les lignes d’encapsulation et de désencapsulation sont exclues, et une requête portant sur le mint du SOL natif renvoie à la fois les transferts de SOL natif et de WSOL.

separate

Dans ce mode, le WSOL est conservé comme un mint distinct, et les lignes du cycle de vie d’encapsulation et de désencapsulation sont incluses pour assurer une auditabilité complète.

Dans la plupart des cas d’usage produit, merged sera généralement le meilleur choix. Pour le rapprochement, la comptabilité et l’analyse au niveau du protocole, separate est souvent préférable.

Pagination et ordre

Pagination standard par curseur via paginationToken, jusqu’à 100 enregistrements par page. sortOrder accepte asc et desc.

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

Quand utiliser getTransfersByAddress

getTransfersByAddress et getTransactionsForAddress sont similaires, mais répondent à des besoins distincts. 

BesoinMéthode
Transferts analysés de tokens et de SOL, avec filtresgetTransfersByAddress
Données complètes des transactions ou activité hors transfertgetTransactionsForAddress
Instructions décodées pour n’importe quelle signature ou adresseAPI Parsed Events
Uniquement les signaturesgetTransactionsForAddress avec transactionDetails: 'signatures'
Streaming des transferts en temps réelLaserStream

Commencer

La méthode getTransfersByAddress est disponible dès aujourd’hui avec tous les forfaits payants, à partir du forfait Developer. Elle coûte 10 crédits par requête et fait partie de votre groupe de limites de débit RPC standard.

Utilisez-la avec votre URL RPC Helius existante :

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);

Consultez la référence de l’API pour connaître tous les détails sur les paramètres et les réponses.

Abonnez-vous à Helius

Suivez les dernières actualités du développement sur Solana et recevez une notification à chaque publication