跳至主要內容

如何建立 Solana WebSocket 訂閱

更新於
2026年6月1日

閱讀時間 10 分鐘

用於監控 Solana 即時資料的工具

監控 Solana 上的即時變更有幾種方法。如果您不確定哪種方法最適合您的使用情境,請參閱我們的部落格文章,其中對各種選項進行了比較。如果您已準備好使用 Solana Web3js(1.x 版)透過 WebSockets 開始開發,請繼續閱讀(如果您偏好 2.x 版,請參閱我們的指南,點此查看)!

概覽

建立事件監聽器是向您的應用程式或使用者發出通知,告知您正在監控的某項內容已發生變更的有效方法。Solana 內建了數個實用的事件監聽器(亦稱為訂閱),讓監聽 Solana 區塊鏈上的變更變得輕而易舉。不確定該如何運用嗎? 以下提供幾個可能派上用場的實例:一個監測與鏈上程式(例如銷售機器人)互動的 Discord 機器人、一個檢查使用者交易是否出錯的 dApp,或是當使用者錢包餘額變動時發送的手機通知。

想看影片教學嗎?跟著 Sahil 一起學習,只需 4 分鐘就能掌握如何建立 Solana 區塊鏈的 WebSocket 訂閱。
訂閱我們的 YouTube 頻道,觀看更多影片!

您將負責的工作內容

在本指南中,您將學習如何運用數種 Solana 事件監聽器方法以及 Quicknode 的 WebSocket 端點 (WSS://),來監聽鏈上變更。具體而言,您將建立一個簡單的 TypeScript 應用程式,用以追蹤某個帳戶(或錢包)的變更。接著,您將學習如何使用 Solana 的取消訂閱方法,從應用程式中移除監聽器。 我們還將介紹 Solana 其他一些監聽器方法的基礎知識。

您需要準備的物品

  • 已安裝Node.js(版本 16.15 或更高)
  • 已安裝 npm 或 yarn(我們將使用 yarn 來初始化專案並安裝必要的套件。若您偏好使用 npm,亦可改用 npm)
  • 已具備 TypeScript 經驗,並已安裝ts-node
  • Solana Web3

設定您的執行環境

請在終端機中使用以下指令建立一個新的專案目錄:

mkdir solana-subscriptions
cd solana-subscriptions

建立一個名為app.ts 的檔案:

echo > app.ts

請使用「yes」參數初始化您的專案,以便為新套件採用預設值: 

毛線 初始化 --是
#或
npm 初始化 --yes

安裝 Solana Web3 依賴項:

紗線 新增 @solana/web3.js@1
#或
npm 安裝 @solana/web3.js@1

在您偏好的程式碼編輯器中開啟app.ts檔案,並在第 1 行從 Solana Web3 函式庫導入ConnectionPublicKey 以及LAMPORTS_PER_SOL: 

import { Connection, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js";

好啦!我們都準備好了。 

設定您的 Quicknode 端點

若要在 Solana 上進行開發,您需要一個 API 端點來連線至該網路。您可以使用公開節點,或自行部署並管理基礎架構;不過,若您希望將回應時間縮短 8 倍,不妨將繁重的工作交給我們處理。


了解為何超過 50% 的 Solana 專案選擇 Quicknode,並點此註冊帳號。

我們將使用一個 Solana Devnet 節點。請複製 HTTP ProviderWSS Provider 的連結:

新的 Solana 端點

請在app.js的第 3 行和第 4 行建立兩個新變數,用來儲存這些 URL: 

const WSS_ENDPOINT = 'wss://example.solana-devnet.quiknode.pro/000/'; // 請替換為您的 URL
const HTTP_ENDPOINT = 'https://example.solana-devnet.quiknode.pro/000/'; // 請替換為您的網址

建立與 Solana 的連線

在第 5 行,建立一個新的 Solana連線: 

const solanaConnection = new Connection(HTTP_ENDPOINT,{wsEndpoint:WSS_ENDPOINT});

如果您過去曾建立過連線至 Solana 的 Connection 實例,可能會注意到我們的參數有些不同之處,特別是新增了 {wsEndpoint:WSS\_ENDPOINT}. 讓我們深入探討一下。 

Connection類別的建構函式允許我們傳入一個可選的commitmentOrConfig。我們可以在其中包含幾個值得關注的選項,例如 ConnectionConfig中包含幾個值得關注的選項,但今天我們將聚焦於可選參數wsEndpoint。此選項可讓您提供全節點 JSON RPC PubSub WebSocket 端點的 URL。在我們的案例中,這正是我們先前定義的 WSS 端點:WSS_ENDPOINT

如果未傳入wsEndpoint 參數會發生什麼情況?其實,Solana 已透過makeWebsocketUrl函式來處理此情況,該函式會將您的端點 URL 中的https替換為wss,或將http替換為ws來源)。由於所有 Quicknode HTTP 端點都有對應的 WSS 端點,且使用相同的驗證憑證,因此除非您希望為 WebSocket 查詢使用獨立的端點,否則省略此參數並無問題。

讓我們來建立一些訂閱吧!

建立帳號 訂閱

要在 Solana 上追蹤一個錢包,我們需要呼叫solanaConnection 上的onAccountChange方法。我們將傳入ACCOUNT_TO_WATCH(即要追蹤的錢包公鑰)以及一個回呼函式。我們已建立一個簡單的日誌,用以通知我們已偵測到事件,並記錄新的帳戶餘額。請將這段程式碼片段新增至您的程式碼中,位置在第 7 行solanaConnection宣告之後: 

(async()=>{
const ACCOUNT_TO_WATCH = new PublicKey('vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg'); // Replace with your own Wallet Address
const subscriptionId = await solanaConnection.onAccountChange(
ACCOUNT_TO_WATCH,
(updatedAccountInfo) =>
console.log(`---Event Notification for ${ACCOUNT_TO_WATCH.toString()}--- \nNew Account Balance:`, updatedAccountInfo.lamports / LAMPORTS_PER_SOL, ' SOL'),
"confirmed"
);
console.log('Starting web socket, subscription ID: ', subscriptionId);
})()

建立一個簡單的測試

這段程式碼目前可以直接執行,但我們將再新增一項功能,以協助我們測試其是否運作正常。我們將透過新增一個sleep函式(用以增加時間延遲)以及一個airdrop請求來達成此目的。請在第 6 行的非同步程式碼區塊之前,加入以下內容: 

const sleep = (ms:number) => {
return new Promise(resolve => setTimeout(resolve, ms));
}

接著,在您的非同步程式碼區塊中,於「Starting web socket」這條日誌之後,加入這個 airdrop 呼叫:

    等待 睡眠(10000); //等待 10 秒進行 Socket 測試
await solanaConnection.requestAirdrop(待監控帳戶, LAMPORTS_PER_SOL);

您的程式碼將在套接字建立後,實際等待 10 秒,才會向錢包發出空投請求(注意:此功能僅在開發網和測試網有效)。 

我們的程式碼現在如下所示: 

import { Connection, PublicKey, LAMPORTS_PER_SOL, } from "@solana/web3.js";

const WSS_ENDPOINT = 'wss://example.solana-devnet.quiknode.pro/000/'; // replace with your URL
const HTTP_ENDPOINT = 'https://example.solana-devnet.quiknode.pro/000/'; // replace with your URL
const solanaConnection = new Connection(HTTP_ENDPOINT, { wsEndpoint: WSS_ENDPOINT });
const sleep = (ms:number) => {
return new Promise(resolve => setTimeout(resolve, ms));
}

(async () => {
const ACCOUNT_TO_WATCH = new PublicKey('vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg');
const subscriptionId = await solanaConnection.onAccountChange(
ACCOUNT_TO_WATCH,
(updatedAccountInfo) =>
console.log(`---Event Notification for ${ACCOUNT_TO_WATCH.toString()}--- \nNew Account Balance:`, updatedAccountInfo.lamports / LAMPORTS_PER_SOL, ' SOL'),
"confirmed"
);
console.log('Starting web socket, subscription ID: ', subscriptionId);
await sleep(10000); //Wait 10 seconds for Socket Testing
await solanaConnection.requestAirdrop(ACCOUNT_TO_WATCH, LAMPORTS_PER_SOL);
})()

開始使用您的 Socket 吧!

現在就來試試看吧。在終端機中輸入 `ts-node app.ts` 即可啟動您的 WebSocket!大約 10 秒後,您應該會看到類似以下的終端機回呼日誌:

solana-subscriptions % ts-node app.ts
Starting web socket, subscription ID: 0
---Event Notification for vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg---
New Account Balance: 88790.51694709 SOL

太棒了!您應該會注意到,即使在事件通知發出後,您的應用程式仍然保持開啟狀態。這是因為我們的訂閱機制仍在監聽帳戶的變更。我們需要一種方法來取消訂閱該監聽器。按下 Ctrl^C 來停止該程序。

取消訂閱「帳戶變更監聽器」

Solana 提供了一個內建方法removeAccountChangeListener,可供我們用來取消訂閱「帳號變更」監聽器。此方法僅接受一個有效的subscriptionId(數字)作為參數。請在您的async區塊中,於空投指令之後再加入一個sleep 指令,以留出時間讓交易完成處理,然後呼叫removeAccountChangeListener

    await sleep(10000); //Wait 10 for Socket Testing
await solanaConnection.removeAccountChangeListener(subscriptionId);
console.log(`Websocket ID: ${subscriptionId} closed.`);

現在請再次執行您的程式碼,您應該會看到相同的序列,隨後 WebSocket 便會關閉: 

solana-subscriptions % ts-node app.ts
Starting web socket, subscription ID: 0
---Event Notification for vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg---
New Account Balance: 88791.51694709 SOL
Websocket ID: 0 closed.

做得很好!如您所見,若您希望在某個事件發生後(例如:時間經過、達到特定閾值、通知次數達到一定數量等)停用監聽器,這項功能便會派上用場。 

我們已將此腳本的最終程式碼發佈至我們的 Github 儲存庫,供您參考。

其他 Solana WebSocket 訂閱服務

Solana 還有其他幾個類似的 WebSocket 訂閱/取消訂閱方法,同樣相當實用。我們將在本節中簡要介紹這些方法。

  • onProgramAccountChange:註冊一個回呼函式,每當指定程式所擁有的帳戶發生變更時,該回呼函式即會被呼叫。傳入程式的 PublicKey 以及一個可選的帳戶篩選條件陣列。此功能特別適用於追蹤使用者 Token 帳戶的變更。若要取消訂閱,請使用removeProgramAccountChangeListener
  • onLogs:註冊一個回呼函式,每當產生日誌時即會被呼叫——可透過傳入有效的PublicKey,以類似onAccountChange的方式使用。該回呼函式將傳回最近的交易 ID。若要取消訂閱,請使用removeOnLogsListener
  • onSlotChange:註冊一個在插槽變更時被呼叫的回呼函式。此方法僅接收一個回呼函式作為參數。請使用removeSlotChangeListener 取消訂閱。
  • onSignature:透過傳入有效的交易簽名,註冊一個在簽名更新時被呼叫的回呼函式。該回呼函式將回傳交易是否發生錯誤。請使用removeSignatureListener 取消訂閱。onRootChange:註冊一個在根節點變更時被呼叫的回呼函式。此方法僅接收一個回呼函式作為參數。請使用removeRootChangeListener 取消訂閱。

*注意:所有取消訂閱的方法都需要一個 subscriptionId (數字)參數。您可以在我們的文件(網址:quicknode.com/docs/solana)中查閱這些方法的更多資訊歡迎透過對app.js進行微調,親自嘗試這些其他訂閱方式。

計費與優化

WebSocket 方法的計費抵免額是根據收到的回應數量計算,而非訂閱數量。例如,如果您開啟一個 accountChange 訂閱並收到 100 則回覆,您的帳戶將被扣款 5,000 點數(每則回覆可獲得 50 學分 X 100 則回覆)。

為了優化您的訂閱服務,並確保您不會因不必要的訂閱或不相關的回覆而被收費,您應考慮以下事項:

  • 當您不再有興趣接收資料時,請使用取消訂閱的方法來移除監聽器,並且
  • 針對適用方法使用篩選器,以僅接收相關資料。

取消訂閱的方法

以下方法可用於從訂閱中移除監聽器:

在 logsSubscribe 中使用篩選器

訂閱日誌 此方法可讓您篩選交易日誌,從而大幅減少收到的回應數量。以下是一個範例:

// To subscribe to all logs (expensive and not recommended):
const subscriptionId = await connection.onLogs(
'all',
(logs) => {
console.log('New log:', logs);
}
);

// To subscribe only to logs mentioning a specific address:
const EXAMPLE_PUBLIC_KEY = new PublicKey('YOUR_ADDRESS_HERE');
const specificAddressSubscriptionId = await connection.onLogs(
EXAMPLE_PUBLIC_KEY,
(logs) => {
console.log('Log mentioning specific address:', logs);
}
);

在 programSubscribe 中使用篩選器

節目訂閱 此方法功能強大,但可能會產生大量回應。請使用篩選器來縮小您接收的資料範圍:

const filters = [
{
memcmp: {
offset: 0, // Specify the offset in the account data
bytes: 'base58_encoded_bytes_here' // Specify the bytes to compare
}
},
{
dataSize: 128 // If your account data is fixed, you can filter by data size - update this value to match your account's data size
}
];

const subscriptionId = await connection.onProgramAccountChange(
new PublicKey('Your_Program_ID_Here'),
(accountInfo) => {
console.log('Account changed:', accountInfo);
},
'confirmed',
filters
);

在此範例中,我們同時使用 memcmp 以及 dataSize 篩選器。該 memcmp filter 會比對帳戶資料中特定偏移位置處的一系列位元組,而 dataSize 根據帳戶的資料量進行篩選。此組合能大幅減少您收到的回應數量,僅聚焦於符合您特定條件的帳戶。有關使用方式的更多資訊,請參閱 GetProgramAccountsFilter, 請參閱 Solana RPC 文件.

最佳優化實務

  1. 請設定具體的篩選條件:篩選條件越具體,您收到的無關回覆就越少。

  2. 請根據您的使用情境選擇適當的承諾等級:較高的承諾等級(例如「finalized」)可能會導致更新次數較少,但更新結果更為確定。

  3. 定期檢視並取消未使用的訂閱服務:審核您的有效訂閱,並取消任何不再需要的訂閱。

  4. 監控您的使用狀況:請追蹤您收到的回覆數量,並在必要時調整篩選條件或訂閱策略(Quicknode 儀表板)。

透過實施這些優化策略,您可以確保僅接收所需資料,從而將不必要的計費額度消耗降至最低,同時維持 Solana 應用程式的效能。

替代方案

Quicknode 提供多種從 Solana 獲取即時資料的解決方案。請參考以下選項,找出最適合您使用情境的工具:

  • WebSockets:如本指南所述,WebSockets 可提供與 Solana 節點的直接連線以進行即時更新——這對於簡單的應用程式和快速開發而言是理想選擇。若您想搭配 Solana Kit 使用 SolanaWebSockets,請參閱我們的指南:《使用 WebSockets 與 Solana Kit 監控 Solana 帳戶》,了解如何透過 Solana Kit 在 Solana 中設定 WebSocket 訂閱。
  • Solana gRPC(相容於 Yellowstone 的 Geyser gRPC):Solana gRPC 提供了一個強大的 gRPC 介面,用於串流 Solana 資料,並內建篩選功能及歷史資料支援。
  • Streams:一款用於處理並將 Solana 資料路由至多個目的地的託管解決方案,具備內建篩選功能及歷史資料支援。

如需更多資訊,請參閱我們的部落格文章

結論

做得很好!現在你應該已經掌握了在 Solana 上使用 WebSocket 訂閱的方法。你目前是如何運用 Solana WebSocket 的呢?我們很想看看你的創作成果!歡迎在DiscordTwitter 上與我們分享你的應用程式。

若想進一步了解,請點此查看我們其他關於 Solana 的教學文章;如果您覺得 WebSocket 訂閱功能很有趣,不妨訂閱我們的電子報

我們 ❤️ 您的回饋!

如果您有任何意見回饋或對新主題的建議,請告訴我們。我們非常樂意聽取您的意見。

分享這份指南