Solana Geyser gRPC - Filtri

Solana Stream SDK
Il Solana Stream SDK è fornito come software open-source. Per maggiori dettagli, visita il repository GitHub qui sotto.

Panoramica dei filtri gRPC

Solana Geyser gRPC utilizza i filtri per recuperare in modo efficiente solo i dati che ti interessano, come account, programmi, transazioni, slot e blocchi specifici.
Di seguito forniamo esempi TypeScript che utilizzano il Solana Stream SDK, spiegando chiaramente il ruolo specifico di ciascun filtro. La struttura e il significato dei filtri sono identici utilizzando Rust.

Ruoli ed esempi di ciascun filtro

Sottoscrivere un account

Sottoscrivi gli aggiornamenti in tempo reale di un account specifico. L'esempio seguente sottoscrive l'account OpenBook SOL-USDC al livello di 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" è un'etichetta definita dal client.
  • Più filtri per account, programmi, blocchi e slot possono essere combinati in una singola richiesta JSON.

Sottoscrivere un account con account_data_slice

Questo esempio mostra come recuperare solo una porzione specifica dei dati di un account. Invece di recuperare l'intero dato (165 byte) di un token account USDC, recupera 40 byte a partire dall'offset 32. Questo intervallo include informazioni come il proprietario e il saldo in lamport.
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 }],
}

Sottoscrivere un programma

Questo esempio mostra come sottoscrivere gli aggiornamenti degli account associati a un programma specifico.
Qui sotto sottoscriviamo gli aggiornamenti degli account posseduti dal programma Solend al livello di 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" è un'etichetta personalizzata che può essere impostata liberamente dal client.
  • Per sottoscrivere più programmi, consulta la sezione successiva intitolata "Sottoscrivere più programmi".

Sottoscrivere più programmi

Questo esempio mostra come sottoscrivere contemporaneamente gli aggiornamenti degli account associati a più programmi.
L'esempio seguente sottoscrive gli aggiornamenti degli account posseduti sia dal programma Solend che dal programma 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,
}
Se preferisci assegnare etichette individuali a ciascun programma, utilizza l'approccio seguente:
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,
}

Sottoscrivere tutte le transazioni finalized, non-vote e non fallite

Questo esempio mostra come sottoscrivere tutte le transazioni al livello di commitment Finalized, escludendo le transazioni di voto e quelle fallite.
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 esclude le transazioni di voto.
  • failed: false esclude le transazioni fallite.
  • Se i campi sono lasciati vuoti, vengono recuperate tutte le transazioni.
  • Quando sono specificati più campi, operano con una condizione AND.

Sottoscrivere le transazioni non-vote che menzionano un account

Questo esempio mostra come sottoscrivere le transazioni che coinvolgono un account specifico, escludendo le transazioni di voto.
L'esempio seguente sottoscrive le transazioni non-vote che menzionano account associati al programma 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,
}

Sottoscrivere le transazioni escludendo account

Questo esempio mostra come sottoscrivere le transazioni escludendo quelle che coinvolgono account specifici.
L'esempio seguente recupera le transazioni escludendo tutti gli account posseduti dai programmi Serum e 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,
}

Sottoscrivere le transazioni che menzionano account ed escludono determinati account

Questo esempio mostra come sottoscrivere le transazioni che coinvolgono determinati account, escludendo esplicitamente altri account specificati.
L'esempio seguente sottoscrive le transazioni che menzionano l'account di Serum ma esclude un account specificato:
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,
}

Sottoscrivere una firma di transazione

Questo esempio mostra come sottoscrivere gli aggiornamenti in tempo reale di una firma di transazione specifica, finché non raggiunge lo stato Confirmed o Finalized.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

Sottoscrivere gli slot

Questo esempio mostra come sottoscrivere le notifiche degli slot in arrivo. Non sono richiesti dettagli aggiuntivi oltre all'assegnazione di un nome di tag personalizzato:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

Sottoscrivere i blocchi

Sottoscrivi gli aggiornamenti in tempo reale di tutti i blocchi generati. Per impostazione predefinita, vengono recuperate tutte le transazioni all'interno di un blocco:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

Per escludere le transazioni e recuperare solo le informazioni aggiornate sugli account:

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,
}

Per recuperare solo le transazioni/gli account che coinvolgono account specifici:

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

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

Sottoscrivere i metadati dei blocchi

Sottoscrivi solo le notifiche dei metadati dei blocchi quando i blocchi vengono elaborati. I dati dettagliati delle transazioni non sono inclusi.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

Gestione dei livelli di commitment

Lo stream Solana Geyser gRPC utilizza per impostazione predefinita il livello di commitment Processed.
Puoi specificare livelli di commitment più alti come Confirmed o Finalized. In questi casi, Geyser bufferizza i dati e invia le notifiche una volta raggiunto il livello di commitment specificato.
Per le massime prestazioni, si consiglia di gestire i livelli di commitment lato client.
Ecco come specificare i livelli di commitment:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

enum CommitmentLevel {
  PROCESSED = 0,
  CONFIRMED = 1,
  FINALIZED = 2,
}
  • PROCESSED: dati immediati dopo l'elaborazione. Recupero rapido, ma non ancora confermati.
  • CONFIRMED: dati confermati dal cluster, con maggiore certezza.
  • FINALIZED: dati completamente finalizzati, senza rischio di riorganizzazione.

Vantaggi del lavoro a Processed

Il vantaggio principale del livello di commitment Processed è il recupero immediato delle transazioni, che consente un'elaborazione rapida lato client. I client possono successivamente rilevare le transizioni a Confirmed o Finalized, offrendo una risposta tempestiva.

Come gestire Confirmed e Finalized

Quando si utilizzano i livelli Confirmed o Finalized, gli eventi (transazioni o aggiornamenti degli account) dovrebbero essere bufferizzati per slot.
Bufferizza gli eventi slot per slot, sottoscrivi le notifiche degli slot e rilascia gli eventi dal buffer una volta che uno slot specifico raggiunge il commitment desiderato (Confirmed o Finalized).
Gli eventi vengono inizialmente ricevuti prima che uno slot raggiunga Confirmed o Finalized.

La particolarità di Finalized

A causa delle specifiche di Solana Geyser, non tutti gli slot ricevono notifiche finalized esplicite. Pertanto, quando ricevi una notifica finalized per uno slot, devi trattare tutti gli slot antenati come finalizzati, anche se non sono state ricevute notifiche esplicite.
In particolare, alla ricezione di una notifica finalized, tratta retroattivamente tutti gli slot antenati come finalizzati.