Solana Geyser gRPC - 過濾器

Solana Stream SDK
Solana Stream SDK 作為開源軟體提供。更多詳情請訪問以下 GitHub 倉庫。

gRPC 過濾器概述

Solana Geyser gRPC 使用過濾器高效獲取您感興趣的資料,如特定賬戶、程式、交易、slot 和區塊。
以下是使用 Solana Stream SDK 的 TypeScript 示例,清楚地說明了每個過濾器的具體作用。使用 Rust 時,過濾器的結構和含義完全相同。

各過濾器的作用和示例

訂閱賬戶

訂閱特定賬戶的實時更新。以下示例以 Confirmed 確認級別訂閱 SOL-USDC OpenBook 賬戶:
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" 是客戶端自定義的標籤。
  • 賬戶、程式、區塊和 slot 的多個過濾器可以在單個 JSON 請求中組合使用。

使用 account_data_slice 訂閱賬戶

此示例演示僅檢索賬戶資料的特定部分。不獲取 USDC 代幣賬戶的全部資料(165 位元組),而是從偏移量 32 開始檢索 40 位元組。此範圍包含所有者和 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 }],
}

訂閱程式

此示例演示訂閱與特定程式關聯的賬戶更新。
以下以 Processed 確認級別訂閱 Solend 程式擁有的賬戶更新。
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" 是客戶端可以自由設定的自定義標籤。
  • 要訂閱多個程式,請參閱下一節"訂閱多個程式"。

訂閱多個程式

此示例演示如何同時訂閱與多個程式關聯的賬戶更新。
以下示例訂閱 Solend 和 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,
}
如果您希望為每個程式分配單獨的標籤,請使用以下方式:
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,
}

訂閱所有已最終確認的非投票且未失敗的交易

此示例演示以 Finalized 確認級別訂閱所有交易,排除投票交易和失敗交易。
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 排除投票交易。
  • failed: false 排除失敗交易。
  • 如果欄位留空,將檢索所有交易。
  • 指定多個欄位時,它們以 AND 條件執行。

訂閱涉及特定賬戶的非投票交易

此示例演示訂閱涉及特定賬戶但排除投票交易的交易。
以下示例訂閱涉及 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,
}

訂閱排除特定賬戶的交易

此示例演示訂閱排除涉及特定賬戶的交易。
以下示例檢索排除 Serum 和 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,
}

訂閱涉及特定賬戶並排除某些賬戶的交易

此示例演示訂閱涉及某些賬戶的交易,同時明確排除其他指定賬戶。
以下示例訂閱涉及 Serum 賬戶的交易,但排除指定賬戶:
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,
}

訂閱交易簽名

此示例演示訂閱特定交易簽名的實時更新,直到它達到 ConfirmedFinalized 狀態。
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

訂閱 slot

此示例演示訂閱傳入 slot 的通知。除了分配自定義標籤名稱外,無需其他詳細資訊:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

訂閱區塊

訂閱所有生成區塊的實時更新。預設情況下,將檢索區塊內的所有交易:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

排除交易,僅檢索更新的賬戶資訊:

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

僅檢索涉及特定賬戶的交易/賬戶:

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

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

訂閱區塊後設資料

僅訂閱區塊處理時的區塊後設資料通知。不包含詳細的交易資料。
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

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

管理確認級別

Solana Geyser gRPC 流預設使用 Processed 確認級別。
您可以指定更高的確認級別,如 ConfirmedFinalized。在這些情況下,Geyser 會緩衝資料並在達到指定的確認級別後傳送通知。
為獲得最佳效能,建議在客戶端管理確認級別。
以下是指定確認級別的方法:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk'

enum CommitmentLevel {
  PROCESSED = 0,
  CONFIRMED = 1,
  FINALIZED = 2,
}
  • PROCESSED:處理後的即時資料。檢索速度快,但尚未確認。
  • CONFIRMED:經叢集確認的資料,提供更高的確定性。
  • FINALIZED:完全最終確認的資料,沒有重組風險。

使用 Processed 的優勢

Processed 確認級別的主要優勢是即時交易檢索,能夠快速進行客戶端處理。客戶端隨後可以檢測到向 ConfirmedFinalized 的轉換,提供快速響應能力。

如何管理 ConfirmedFinalized

使用 ConfirmedFinalized 級別時,應按 slot 緩衝事件(交易或賬戶更新)。
按 slot 緩衝事件,訂閱 slot 通知,並在特定 slot 達到所需確認級別(ConfirmedFinalized)後從緩衝區釋放事件。
事件最初會在 slot 達到 ConfirmedFinalized 之前接收。

Finalized 的特殊之處

由於 Solana Geyser 規範,並非所有 slot 都會收到明確的最終確認通知。因此,當您收到某個 slot 的最終確認通知時,必須將所有祖先 slot 也視為已最終確認,即使沒有收到明確的通知。
具體來說,收到最終確認通知後,追溯地將所有祖先 slot 視為已最終確認。