跳至內容
0%

推出 Solana 歷史代幣餘額查詢功能

作者:Alchemy

最後更新:2026年7月21日1 分鐘閱讀
getTokenAccountsByOwnerAtSlot — 歷史 Solana 代幣餘額

問一個 Solana 錢包今天持有什麼,任何節點一次呼叫就能回答。問它去年春天持有什麼,或是被盜前那一刻持有什麼,簡單的做法就行不通了。節點提供的是當前餘額,並不會保留誰在何時持有什麼的完整紀錄。所以「這個錢包當時持有什麼」這個問題,老實說,答案一直是:自己重建。

今天我們要改變這一點。getTokenAccountsByOwnerAtSlot 能在一次呼叫中,回傳一個錢包在過去任何時間點所持有的一切,包含精確餘額。

重建歷史紀錄的問題

標準的 getTokenAccountsByOwner 只回答一個問題:這個錢包現在持有什麼。這能滿足大多數即時應用流程的需求,但留下了一整類問題無法回答。

要自己重建過去的餘額,你得重演這個帳戶的整個生命歷程。用 getSignaturesForAddress 拉出錢包完整的簽章歷史,用 getTransaction 取得每一筆交易,再逐個 slot 重新推導餘額,直到你要的目標時間點。對於一個活躍的錢包,這意味著數千次呼叫、大量解析工作,以及算錯的高風險。歸檔節點(archival node)能幫你讀取舊狀態,但它們仍然無法直接回答「列出這個持有者在 slot X 時的代幣帳戶」這類問題。

運作方式

這個方法保留了你已經熟悉的 getTokenAccountsByOwner 語法,並加入了一項:slot。slot 是 Solana 的時鐘,大致相當於一個區塊,傳入 slot 代表「告訴我這個錢包在歷史上那個精確時間點的狀態」。

呼叫這個方法時,你會拿到錢包的代幣帳戶(token accounts),也就是持有錢包所擁有的每一種代幣的個別紀錄。在 Solana 上,錢包本身並不直接持有餘額,所以列出這些帳戶才是讀取持有狀況的方式。每個帳戶都會附帶其餘額與 lamports,也就是每個帳戶為了存在於鏈上必須攜帶的少量 SOL(一枚代幣的小數分割,1 SOL 等於 10 億 lamports)。這個方法涵蓋 Solana 的兩種代幣標準:SPL Token,這是最原始的標準,幾乎所有知名代幣(如 USDC)都基於它;以及 Token-2022,較新的版本,附加了轉帳手續費、機密餘額等功能。這兩種標準對應不同的 program ID,所以單一 programId 過濾條件只會回傳該 program 底下的帳戶。

在呼叫背後,是一個持續建置的歷史索引:一份針對每個代幣帳戶的版本化紀錄,記錄誰在哪些 slot 之間持有多少數量,並隨著新區塊產生持續更新。你可以用兩種方式限定查詢範圍:按 mint,讀取某個代幣在過去某個 slot 的餘額;或按 program,列出該 program 在該 slot 下所擁有的每個代幣帳戶。若要取得橫跨兩種標準的完整投資組合,分別用 SPL Token 的 program ID 呼叫一次、用 Token-2022 的 program ID 呼叫一次,再合併結果。下方範例僅限定在 SPL Token。

javascript
Copied
const res = await fetch("https://solana-mainnet.g.alchemy.com/v2/{ALCHEMY_API_KEY}", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "getTokenAccountsByOwnerAtSlot", params: [ "89zoESAF7JqYQz5uhf5eYwg3QsKXQy5QFs4WZQ4hMPnb", { programId: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" }, { encoding: "jsonParsed", slot: 80000000 } ] }) }); console.log(await res.json());

分頁結果會保持一致,因為 pageKey 固定了你所指定的 slot。就算鏈的最新進度在你分頁的過程中持續前進,你的結果仍然描述的是同一個時間點,每頁最多可回傳 10,000 個帳戶。

為什麼這很重要

特定時間點的持有狀況成為第一級查詢對象。原本你得自己建置並維護的索引管線,現在收斂成一次 RPC 呼叫,讓你的團隊能專注在產品本身,而不是底層管線工程。

這讓一些原本很麻煩的工作變得可行:

  • 任何歷史時間點的投資組合與損益(PnL)快照
  • 綁定特定 slot 或日期的成本基礎與稅務申報
  • 爭議處理、鑑識與事件調查,例如證明某個錢包在被盜前一個區塊持有什麼
  • 需要準確歷史狀態、卻不想重演交易紀錄的分析與索引管線

我們在測試期間,將結果與鏈上真實資料進行了比對驗證。抽樣的歷史查詢結果與鏈上餘額及 lamports 完全吻合,包含像是 slot 80,000,000 時的 KIN 餘額這類深層歷史資料。

開始使用

這個方法已在標準的 Solana mainnet 端點上開放使用,所以如果你已經透過 Alchemy 發送 Solana RPC 請求,可以直接用現有的 API key 呼叫它。指向 https://solana-mainnet.g.alchemy.com/v2/{ALCHEMY_API_KEY},加上 slot,就能讀回持有狀況。

請參閱 Solana API quickstart 來設定 key 並發送你的第一個請求。

常見問答

getTokenAccountsByOwnerAtSlot 做什麼?

它會回傳一個 Solana 錢包在你指定的過去 slot 時的代幣帳戶,包含餘額與 lamports。它與 getTokenAccountsByOwner 的結構相同,只是多了一個 slot 參數。

什麼是 SPL Token 與 Token-2022?

它們是 Solana 的兩種代幣標準。SPL Token 是最原始的標準,幾乎涵蓋網路上所有知名代幣。Token-2022 是較新的版本,新增了轉帳手續費、機密餘額等可選功能。這個方法兩者都涵蓋。

這和 getTokenAccountsByOwner 有什麼不同?

getTokenAccountsByOwner 只回傳當前的持有狀況。getTokenAccountsByOwnerAtSlot 則能回答同一個問題在任何過去 slot 的狀態,它讀取的是歷史索引,而不是即時節點狀態。

我需要歸檔節點或自訂索引器嗎?

不需要。這個方法讀取的是預先建好的歷史索引,所以你不需要自己運行歸檔基礎設施,也不必重演交易歷史。

我可以查詢錢包的完整投資組合,而不只是單一代幣嗎?

可以,但如果錢包同時持有兩種標準的代幣,就無法只用一次 programId 呼叫完成。按 mint 限定範圍可查詢單一代幣,按 programId 限定範圍則可列出該 program 在某個 slot 下的所有帳戶。SPL Token 與 Token-2022 使用不同的 program ID,所以要取得完整投資組合,需分別查詢兩者並合併結果。

隨著鏈持續前進,分頁如何保持準確?

pageKey 固定了你查詢的 slot,所以即使有新區塊到達,跨頁的結果仍保持一致,每頁最多可回傳 10,000 個帳戶。

Alchemy 電子報

搶先掌握最新發布消息

訂閱我們的電子報

取得 Alchemy 最新產品更新與資源

A
O
D
+
超過 80,000 名訂閱者

輸入您的電子郵件地址,即表示您同意接收我們的行銷通訊與產品更新。您了解 Alchemy 會依照我們的隱私權聲明處理所收到的資訊。您可以隨時取消訂閱。