Solana Geyser gRPC - Filtros

Solana Stream SDK
El Solana Stream SDK se proporciona como software de código abierto. Para más detalles, visite el repositorio GitHub a continuación.

Panorama general de los filtros gRPC

Solana Geyser gRPC utiliza filtros para buscar eficientemente los datos que te interesan, como cuentas específicas, programas, transacciones, slots y bloques.
A continuación, proporcionamos ejemplos de TypeScript usando el SDK de Solana Stream, explicando claramente los roles específicos de cada filtro. La estructura y el significado de los filtros son idénticos al usar Rust.

Funciones y ejemplos de cada filtro

Suscribirse a una cuenta

Suscríbete a actualizaciones en tiempo real para una cuenta específica. El siguiente ejemplo se suscribe a la cuenta SOL-USDC OpenBook en el nivel de compromiso confirmado:
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" es una etiqueta definida por el cliente.
  • Múltiples filtros para cuentas, programas, bloques y slots se pueden combinar en una sola solicitud JSON.

Suscribirse a una cuenta con account_data_slice

Este ejemplo demuestra la recuperación de sólo una parte específica de los datos de la cuenta. En lugar de recoger los datos completos (165 bytes) de una cuenta de token USDC, recupera 40 bytes a partir del offset 32. Esta gama incluye información como el propietario y el saldo de 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 }],
}

Suscribirse a un programa

Este ejemplo demuestra que se suscribe a las actualizaciones de la cuenta asociadas con un programa específico.
A continuación, nos suscribemos a las actualizaciones de cuentas de propiedad del programa Solend en el Processed nivel de compromiso.
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" es una etiqueta personalizada que se puede configurar libremente por el cliente.
  • Para suscribirse a múltiples programas, consulte la siguiente sección titulada "Suscríbete a múltiples programas".

Suscríbete a múltiples programas

Este ejemplo demuestra cómo suscribirse a las actualizaciones de la cuenta asociadas con múltiples programas a la vez.
El ejemplo a continuación se suscribe a las actualizaciones de las cuentas de propiedad de los programas Solend y 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 prefiere asignar etiquetas individuales a cada programa, utilice el siguiente enfoque:
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,
}

Suscríbete a todas las transacciones no facturadas y no fallidas

Este ejemplo demuestra que se suscribe a todas las transacciones en el Finalized nivel de compromiso, excluyendo las transacciones de voto y las transacciones fallidas.
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 excluye las transacciones de votación.
  • failed: false excluye las transacciones fallidas.
  • Si los campos quedan vacíos, todas las transacciones se recuperan.
  • Cuando se especifican varios campos, funcionan con una condición AND.

Suscríbete a transacciones no facturadas que mencionan una cuenta

Este ejemplo demuestra que se suscribe a transacciones relacionadas con una cuenta específica pero excluyendo las transacciones de voto.
El ejemplo a continuación se suscribe a transacciones no facturadas que mencionan cuentas asociadas con el programa 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,
}

Suscríbete a transacciones excluidas cuentas

Este ejemplo demuestra que se suscribe a transacciones que excluyen las que incluyen cuentas específicas.
El ejemplo a continuación recupera transacciones, excluyendo cualquier cuenta propiedad de los programas de Serum y 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,
}

Suscribirse a transacciones que mencionan cuentas y excluyen ciertas cuentas

Este ejemplo demuestra que se suscribe a las transacciones que implican ciertas cuentas, al tiempo que excluye explícitamente otras cuentas especificadas.
El ejemplo a continuación se suscribe a las transacciones que mencionan la cuenta de Serum pero excluye una cuenta especificada:
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,
}

Suscribirse a una firma de transacción

Este ejemplo demuestra que se suscribe a actualizaciones en tiempo real para una firma de transacción específica, hasta que llegue a estado 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,
}

Suscribirse a slots

Este ejemplo demuestra que se suscribe a notificaciones de slots entrantes. No se requieren detalles adicionales más allá de asignar un nombre de etiqueta personalizado:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

Suscríbete a bloques

Suscríbete a actualizaciones en tiempo real de todos los bloques generados. Por defecto, todas las transacciones dentro de un bloque serán recuperadas:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

Para excluir las transacciones y sólo recuperar información actualizada de la cuenta:

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

Sólo para recuperar transacciones/accounts involucrando cuentas específicas:

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

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

Suscríbete a los metadatos bloqueados

Suscribirse sólo para bloquear notificaciones de metadatos cuando se procesan bloques. No se incluyen datos de transacción detallados.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

Gestión de los niveles de compromiso

El flujo Solana Geyser gRPC predetermina al Processed nivel de compromiso.
Puede especificar niveles de compromiso más altos como Confirmed o Finalized. En estos casos, Geyser amortiza los datos y envía notificaciones una vez alcanzado el nivel de compromiso especificado.
Para el máximo rendimiento, se recomienda manejar la gestión de nivel de compromiso en el lado cliente.
He aquí cómo especificar los niveles de compromiso:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

enum CommitmentLevel {
  PROCESSED = 0,
  CONFIRMED = 1,
  FINALIZED = 2,
}
  • PROCESSED: Datos inmediatos después del tratamiento. Retrieval rápido, pero aún no confirmado.
  • CONFIRMED: Datos confirmados por el grupo, proporcionando mayor certeza.
  • FINALIZED: Datos completos sin riesgo de reorganización.

Beneficios de trabajar en Processed

La principal ventaja del nivel Processed de compromiso es la recuperación inmediata de transacciones, lo que permite el tratamiento rápido del lado cliente. Los clientes pueden detectar posteriormente transiciones a Confirmed o Finalized, ofreciendo una respuesta rápida.

Cómo gestionar Confirmed y Finalized

Cuando se utiliza niveles Confirmed o Finalized, eventos (transacciones o actualizaciones de cuentas) deben ser amortiguados por slot.
Almacena los eventos en buffer slot por slot, suscribirse a las notificaciones de slot, y liberar eventos del buffer una vez que un slot específico alcanza el compromiso deseado (Confirmed o Finalized).
Los eventos serán recibidos inicialmente antes de que un slot llegue a Confirmed o Finalized.

Lo especial sobre Finalized

Debido a las especificaciones de Solana Geyser, no todas los slots reciben notificaciones explícitas finalizadas. Por lo tanto, cuando reciba una notificación final para un slot, debe tratar todas los slots del antepasado como finalizado, incluso si no se recibieron explícitamente notificaciones.
Específicamente, al recibir una notificación finalizada, trate retroactivamente todas los slots del antepasado como finalizado.