Solana Geyser gRPC - Filter

Solana Stream SDK
Solana Stream SDK disediakan sebagai perangkat lunak open-source. Untuk detail lebih lanjut, silakan kunjungi repositori GitHub di bawah ini.

Ikhtisar Filter gRPC

Solana Geyser gRPC menggunakan filter untuk mengambil secara efisien hanya data yang Anda minati, seperti akun, program, transaksi, slot, dan blok tertentu.
Di bawah ini, kami memberikan contoh TypeScript yang menggunakan Solana Stream SDK dan menjelaskan dengan jelas peran setiap filter. Struktur dan makna filter tetap sama saat menggunakan Rust.

Aturan filter Shared saat ini

Pada paket Shared saat ini, setiap map blocks yang tidak kosong hanya tersedia untuk Dedicated, termasuk request yang dipersempit dengan accountInclude atau dengan mengecualikan transaksi. Gunakan subscription transaksi atau blocksMeta jika itu memenuhi kebutuhan Anda; keduanya bukan pengganti blok penuh. Stream Geyser gRPC Dedicated diperlukan untuk blok penuh.
Setiap entri filter akun harus memuat account, owner, atau cuckoo filter yang didukung. Kondisi memcmp atau dataSize saja tidak memilih bentuk akun yang didukung. Persempit request ke salah satu selector tersebut, atau gunakan Geyser gRPC Dedicated jika Anda memerlukan stream akun penuh.

Peran dan Contoh Setiap Filter

Subscribe ke akun

Subscribe ke update real-time untuk akun tertentu. Contoh berikut melakukan subscribe ke akun OpenBook SOL-USDC pada tingkat 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" adalah label yang ditentukan oleh klien.
  • Beberapa filter untuk akun, program, blok, dan slot dapat digabungkan dalam satu request JSON.

Subscribe ke akun dengan account_data_slice

Contoh ini menunjukkan cara mengambil hanya sebagian data akun. Alih-alih mengambil seluruh data (165 byte) dari token account USDC, contoh ini mengambil 40 byte mulai dari offset 32. Rentang ini mencakup informasi seperti pemilik dan saldo 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 }],
}

Subscribe ke program

Contoh ini menunjukkan cara melakukan subscribe ke update akun yang terkait dengan program tertentu.
Di bawah ini, kami melakukan subscribe ke update untuk akun yang dimiliki program Solend pada tingkat 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" adalah label kustom yang dapat ditentukan bebas oleh klien.
  • Untuk subscribe ke beberapa program, lihat bagian berikutnya yang berjudul "Subscribe ke beberapa program".

Subscribe ke beberapa program

Contoh ini menunjukkan cara melakukan subscribe ke update akun yang terkait dengan beberapa program sekaligus.
Contoh di bawah ini melakukan subscribe ke update untuk akun yang dimiliki oleh program Solend dan 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,
}
Jika Anda lebih suka memberikan label tersendiri untuk setiap program, gunakan cara berikut:
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,
}

Subscribe ke semua transaksi finalized yang non-vote dan tidak gagal

Contoh ini menunjukkan cara melakukan subscribe ke semua transaksi pada tingkat commitment Finalized, tanpa transaksi vote dan transaksi yang gagal.
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 mengecualikan transaksi vote.
  • failed: false mengecualikan transaksi yang gagal.
  • Jika field dibiarkan kosong, semua transaksi akan diambil.
  • Jika beberapa field ditentukan, field tersebut berlaku dengan kondisi AND.

Subscribe ke transaksi non-vote yang menyebut sebuah akun

Contoh ini menunjukkan cara melakukan subscribe ke transaksi yang melibatkan akun tertentu, tetapi tanpa transaksi vote.
Contoh di bawah ini melakukan subscribe ke transaksi non-vote yang menyebut akun-akun yang terkait dengan program 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,
}

Subscribe ke transaksi dengan mengecualikan akun

Contoh ini menunjukkan cara melakukan subscribe ke transaksi, kecuali transaksi yang melibatkan akun tertentu.
Contoh di bawah ini mengambil transaksi tanpa akun apa pun yang dimiliki oleh program Serum dan 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,
}

Subscribe ke transaksi yang menyebut akun tertentu & mengecualikan akun lain

Contoh ini menunjukkan cara melakukan subscribe ke transaksi yang melibatkan akun tertentu, sambil secara eksplisit mengecualikan akun lain yang ditentukan.
Contoh di bawah ini melakukan subscribe ke transaksi yang menyebut akun Serum, tetapi mengecualikan akun yang ditentukan:
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,
}

Subscribe ke signature transaksi

Contoh ini menunjukkan cara melakukan subscribe ke update real-time untuk signature transaksi tertentu, hingga mencapai status Confirmed atau Finalized.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

Subscribe ke slot

Contoh ini menunjukkan cara melakukan subscribe ke notifikasi slot yang masuk. Tidak ada detail tambahan yang diperlukan selain menetapkan nama tag kustom:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

Subscribe ke blok (hanya Dedicated pada paket Shared saat ini)

Subscribe ke update real-time dari semua blok yang dihasilkan. Secara default, semua transaksi di dalam blok akan diambil:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

Untuk mengecualikan transaksi dan hanya mengambil informasi akun yang diperbarui (hanya Dedicated pada paket Shared saat ini):

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

Untuk hanya mengambil transaksi/akun yang melibatkan akun tertentu (hanya Dedicated pada paket Shared saat ini):

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

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

Subscribe ke metadata blok

Subscribe hanya ke notifikasi metadata blok saat blok diproses. Data transaksi yang terperinci tidak disertakan.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

Mengelola tingkat commitment

Stream Solana Geyser gRPC secara default menggunakan tingkat commitment Processed.
Anda dapat menentukan tingkat commitment yang lebih tinggi seperti Confirmed atau Finalized. Dalam hal ini, Geyser menahan data di buffer dan mengirim notifikasi setelah tingkat commitment yang ditentukan tercapai.
Untuk performa maksimum, sebaiknya pengelolaan tingkat commitment ditangani di sisi klien.
Berikut cara menentukan tingkat commitment:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

enum CommitmentLevel {
  PROCESSED = 0,
  CONFIRMED = 1,
  FINALIZED = 2,
}
  • PROCESSED: Data langsung setelah diproses. Pengambilan cepat, tetapi belum dikonfirmasi.
  • CONFIRMED: Data yang sudah dikonfirmasi oleh cluster, sehingga kepastiannya lebih tinggi.
  • FINALIZED: Data yang sudah final sepenuhnya tanpa risiko reorganisasi.

Keuntungan bekerja pada Processed

Keuntungan utama tingkat commitment Processed adalah transaksi dapat diterima seketika, sehingga pemrosesan di sisi klien bisa cepat. Klien kemudian dapat mendeteksi transisi ke Confirmed atau Finalized, sehingga respons tetap cepat.

Cara mengelola Confirmed dan Finalized

Saat menggunakan tingkat Confirmed atau Finalized, event (transaksi atau update akun) sebaiknya ditampung di buffer per slot.
Tampung event di buffer slot demi slot, subscribe ke notifikasi slot, dan keluarkan event dari buffer setelah slot tertentu mencapai commitment yang diinginkan (Confirmed atau Finalized).
Pada awalnya, event akan diterima sebelum slot mencapai Confirmed atau Finalized.

Hal khusus tentang Finalized

Karena spesifikasi Solana Geyser, tidak semua slot menerima notifikasi finalized secara eksplisit. Oleh karena itu, saat Anda menerima notifikasi finalized untuk sebuah slot, Anda harus memperlakukan semua slot leluhurnya sebagai finalized, meskipun tidak ada notifikasi yang diterima secara eksplisit.
Secara khusus, setelah menerima notifikasi finalized, perlakukan semua slot leluhur secara retroaktif sebagai finalized.