Solana Geyser gRPC - Filtres

Solana Stream SDK
Le Solana Stream SDK est fourni sous forme de logiciel open source. Pour plus de détails, veuillez consulter le dépôt GitHub ci-dessous.

Aperçu des filtres gRPC

Solana Geyser gRPC utilise des filtres pour récupérer efficacement uniquement les données qui vous intéressent, comme des comptes, des programmes, des transactions, des slots et des blocs spécifiques.
Ci-dessous, nous fournissons des exemples TypeScript utilisant le Solana Stream SDK, qui expliquent clairement le rôle précis de chaque filtre. La structure et la signification des filtres sont identiques lorsque vous utilisez Rust.

Règles de filtre actuelles du plan Shared

Sur le plan Shared actuel, toute map blocks non vide est réservée à Geyser gRPC Dedicated, y compris une requête restreinte avec accountInclude ou par l'exclusion des transactions. Utilisez un abonnement aux transactions ou blocksMeta lorsque cela suffit à votre besoin ; aucun des deux n'équivaut à un bloc complet. Un stream Geyser gRPC Dedicated est nécessaire pour obtenir des blocs complets.
Chaque entrée de filtre de compte doit comporter account, owner ou un filtre cuckoo pris en charge. Une condition memcmp ou dataSize seule ne sélectionne pas une forme de compte prise en charge. Limitez la requête à l'un de ces sélecteurs, ou utilisez Geyser gRPC Dedicated lorsqu'un stream de comptes complet est nécessaire.

Rôles et exemples de chaque filtre

S'abonner à un compte

Abonnez-vous aux mises à jour en temps réel d'un compte spécifique. L'exemple suivant s'abonne au compte OpenBook SOL-USDC au niveau de commitment Confirmed :
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: { slots: {} },
  accounts: {
    'wsol/usdc': {
      account: ['8BnEgHoWFysVcuFFX7QztDmzuH8r5ZFvyP3sYwn1XTh6'],
    },
  },
  transactions: {},
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.CONFIRMED,
}
  • "wsol/usdc" est une étiquette définie par le client.
  • Plusieurs filtres pour les comptes, les programmes, les blocs et les slots peuvent être combinés dans une seule requête JSON.

S'abonner à un compte avec account_data_slice

Cet exemple montre comment récupérer uniquement une partie spécifique des données d'un compte. Au lieu de récupérer l'intégralité des données (165 octets) d'un compte de token USDC, il récupère 40 octets à partir de l'offset 32. Cette plage comprend des informations telles que le propriétaire et le solde en lamports.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: {},
  accounts: {
    usdc: {
      owner: ['TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'],
      filters: [
        {
          tokenAccountState: true,
        },
        {
          memcmp: {
            offset: 0,
            data: {
              base58: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
            },
          },
        },
      ],
    },
  },
  transactions: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
  commitment: CommitmentLevel.CONFIRMED,
  accountsDataSlice: [{ offset: 32, length: 40 }],
}

S'abonner à un programme

Cet exemple montre comment s'abonner aux mises à jour de comptes associées à un programme spécifique.
Ci-dessous, nous nous abonnons aux mises à jour des comptes détenus par le programme Solend, au niveau de commitment Processed.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: {
    slots: {},
  },
  accounts: {
    solend: {
      owner: ['So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo'],
    },
  },
  transactions: {},
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED,
}
  • "solend" est une étiquette personnalisée que le client peut définir librement.
  • Pour vous abonner à plusieurs programmes, veuillez consulter la section suivante intitulée « S'abonner à plusieurs programmes ».

S'abonner à plusieurs programmes

Cet exemple montre comment s'abonner en une seule fois aux mises à jour de comptes associées à plusieurs programmes.
L'exemple ci-dessous s'abonne aux mises à jour des comptes détenus par les programmes Solend et Serum.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: {
    slots: {},
  },
  accounts: {
    programs: {
      owner: [
        'So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo',
        '9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin',
      ],
    },
  },
  transactions: {},
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED,
}
Si vous préférez attribuer une étiquette distincte à chaque programme, utilisez l'approche suivante :
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: {
    slots: {},
  },
  accounts: {
    solend: {
      owner: ['So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo'],
    },
    serum: {
      owner: ['9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'],
    },
  },
  transactions: {},
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED,
}

S'abonner à toutes les transactions finalisées, hors transactions de vote et transactions échouées

Cet exemple montre comment s'abonner à toutes les transactions au niveau de commitment Finalized, en excluant les transactions de vote et les transactions échouées.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: {
    slots: {},
  },
  accounts: {},
  transactions: {
    alltxs: {
      vote: false,
      failed: false,
    },
  },
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.FINALIZED,
}
  • vote: false exclut les transactions de vote.
  • failed: false exclut les transactions échouées.
  • Si les champs sont laissés vides, toutes les transactions sont récupérées.
  • Lorsque plusieurs champs sont spécifiés, ils sont combinés avec une condition AND.

S'abonner aux transactions hors vote qui mentionnent un compte

Cet exemple montre comment s'abonner aux transactions impliquant un compte spécifique, en excluant les transactions de vote.
L'exemple ci-dessous s'abonne aux transactions hors vote qui mentionnent des comptes associés au programme Serum.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: {
    slots: {},
  },
  accounts: {},
  transactions: {
    serum: {
      vote: false,
      accountInclude: ['9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'],
    },
  },
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED,
}

S'abonner aux transactions en excluant des comptes

Cet exemple montre comment s'abonner aux transactions en excluant celles qui impliquent des comptes spécifiques.
L'exemple ci-dessous récupère les transactions en excluant tout compte détenu par les programmes Serum et Tokenkeg.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: {
    slots: {},
  },
  accounts: {},
  transactions: {
    serum: {
      accountExclude: [
        '9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin',
        'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
      ],
    },
  },
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED,
}

S'abonner aux transactions qui mentionnent des comptes, en excluant certains comptes

Cet exemple montre comment s'abonner aux transactions impliquant certains comptes, tout en excluant explicitement d'autres comptes spécifiés.
L'exemple ci-dessous s'abonne aux transactions qui mentionnent le compte de Serum, mais exclut un compte spécifié :
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: {
    slots: {},
  },
  accounts: {},
  transactions: {
    serum: {
      accountInclude: ['9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'],
      accountExclude: ['9wFFyRfZBsuAha4YcuxcXLKwMxJR43S7fPfQLusDBzvT'],
    },
  },
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED,
}

S'abonner à une signature de transaction

Cet exemple montre comment s'abonner aux mises à jour en temps réel d'une signature de transaction spécifique, jusqu'à ce qu'elle atteigne l'état Confirmed ou Finalized.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: {},
  accounts: {},
  transactions: {
    sign: {
      signature:
        '5rp2hL9b6kexex11Mugfs3vfU9GhieKruj4CkFFSnu52WLxiGn4VcLLwsB62XURhMmT1j4CZiXT6FFtYbXsLq2Zs',
    },
  },
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED,
}

S'abonner aux slots

Cet exemple montre comment s'abonner aux notifications des slots entrants. Aucun détail supplémentaire n'est requis, à part l'attribution d'un nom d'étiquette personnalisé :
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: {
    incoming_slots: {},
  },
  accounts: {},
  transactions: {},
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED,
}

S'abonner aux blocs (réservé à Geyser gRPC Dedicated sur le plan Shared actuel)

Abonnez-vous aux mises à jour en temps réel de tous les blocs générés. Par défaut, toutes les transactions d'un bloc seront récupérées :
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: {},
  accounts: {},
  transactions: {},
  blocks: {
    blocks: {},
  },
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED,
}

Pour exclure les transactions et récupérer uniquement les informations de compte mises à jour (réservé à Geyser gRPC Dedicated sur le plan Shared actuel) :

typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: {},
  accounts: {},
  transactions: {},
  blocks: {
    blocks: {
      includeTransactions: false,
      includeAccounts: true,
    },
  },
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED,
}

Pour récupérer uniquement les transactions/comptes impliquant des comptes spécifiques (réservé à Geyser gRPC Dedicated sur le plan Shared actuel) :

typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: {},
  accounts: {},
  transactions: {},
  blocks: {
    blocks: {
      accountInclude: ['So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo'],
    },
  },
  blocksMeta: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED,
}

S'abonner aux métadonnées de bloc

Abonnez-vous uniquement aux notifications de métadonnées de bloc lorsque des blocs sont traités. Les données détaillées des transactions ne sont pas incluses.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

const request = {
  slots: {},
  accounts: {},
  transactions: {},
  blocks: {},
  blocksMeta: {
    blockmetadata: {},
  },
  accountsDataSlice: [],
  commitment: CommitmentLevel.PROCESSED,
}

Gérer les niveaux de commitment

Le flux Solana Geyser gRPC utilise par défaut le niveau de commitment Processed.
Vous pouvez spécifier des niveaux de commitment plus élevés, comme Confirmed ou Finalized. Dans ces cas, Geyser met les données en mémoire tampon et envoie les notifications une fois le niveau de commitment spécifié atteint.
Pour des performances maximales, il est recommandé de gérer le niveau de commitment côté client.
Voici comment spécifier les niveaux de commitment :
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

enum CommitmentLevel {
  PROCESSED = 0,
  CONFIRMED = 1,
  FINALIZED = 2,
}
  • PROCESSED : Données disponibles immédiatement après le traitement. Récupération rapide, mais données pas encore confirmées.
  • CONFIRMED : Données confirmées par le cluster, offrant une certitude accrue.
  • FINALIZED : Données entièrement finalisées, sans risque de réorganisation.

Avantages de travailler au niveau Processed

Le principal avantage du niveau de commitment Processed est la récupération immédiate des transactions, ce qui permet un traitement rapide côté client. Les clients peuvent ensuite détecter les transitions vers Confirmed ou Finalized, ce qui offre une grande réactivité.

Comment gérer Confirmed et Finalized

Lorsque vous utilisez les niveaux Confirmed ou Finalized, les événements (transactions ou mises à jour de compte) devraient être mis en mémoire tampon par slot.
Mettez les événements en mémoire tampon slot par slot, abonnez-vous aux notifications de slots, puis libérez les événements de la mémoire tampon une fois qu'un slot donné atteint le niveau de commitment souhaité (Confirmed ou Finalized).
Les événements seront d'abord reçus avant qu'un slot n'atteigne Confirmed ou Finalized.

La particularité de Finalized

En raison des spécifications de Solana Geyser, tous les slots ne reçoivent pas de notification explicite de finalisation. Par conséquent, lorsque vous recevez une notification de finalisation pour un slot, vous devez traiter tous les slots ancêtres comme finalisés, même si aucune notification n'a été reçue explicitement.
Plus précisément, à la réception d'une notification de finalisation, traitez rétroactivement tous les slots ancêtres comme finalisés.