跳至主要內容

取得 Solana 錢包所持有的一切代幣帳戶

更新於
2025年11月26日

閱讀時間 8 分鐘

概覽

各位讀者大家好!為了迎接「Solana Summer」以及當前的白名單熱潮,我們認為透過`getParsedProgramAccounts` 方法深入分析您和您的使用者所擁有的所有代幣帳戶,將會有所幫助。此工具便於查詢 Solana 上的各種程式,包括 Solana SPL 代幣帳戶函式庫。 

想看影片教學嗎?跟著諾亞一起學習,只需 13 分鐘,就能掌握如何取得 Solana 錢包中所有代幣。
訂閱我們的 YouTube 頻道,觀看更多影片!

本指南將引導您建立一個簡單的腳本,用以查詢 Solana 主網,並回傳該錢包所擁有的所有代幣帳戶及其帳戶餘額。 

如果您比較喜歡看影片,這裡有一段影片:

您需要準備的物品

程式:Solana 上的智慧合約。在此範例中,我們將使用SPL 代幣程式SPL Token Program),該程式定義了 Solana 上可互換代幣(fungible)與不可互換代幣(non-fungible)的典型應用情境。
程式篩選器:許多鏈上程式查詢會擷取大量資料集,因此縮小搜尋範圍至關重要。我們將使用GetProgramAccountsFilter類型來協助縮小搜尋範圍。 

設定您的執行環境

請在終端機中執行以下指令,建立一個新的專案目錄及名為index.ts 的檔案:

mkdir sol-get-accounts
cd sol-get-accounts
echo > index.ts

初始化您的專案: 

毛線 初始化 --是

npm 初始化 --yes

安裝 Solana Web3 依賴項:

紗線 新增 @solana/web3.js@1 @solana/spl-token

npm 安裝 @solana/web3.js@1 @solana/spl-token

在程式碼編輯器中開啟index.ts檔案,並新增以下依賴項:

import { Connection, GetProgramAccountsFilter } from "@solana/web3.js";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";

**建立與 Solana 主網的連線
**

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


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

請務必在 Solana 主網下啟動您的節點,並複製 HTTP 連結:

取得 Solana 主網端點

const rpcEndpoint = 'https://example.solana-mainnet.quiknode.pro/000000/';
const solanaConnection = new Connection(rpcEndpoint);

將您要查詢的錢包定義為字串:

const walletToQuery = '您的_公鑰'; //範例:vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg

太好了!我們已經準備好要建立我們的代幣查詢了。

建立您的代幣帳戶查詢

建立一個新的非同步函式getTokenAccounts,並要求傳入walletsolanaConnection 兩個參數:

async function getTokenAccounts(wallet: string, solanaConnection: Connection) {
}

建立篩選條件

首先,讓我們定義篩選條件。我們將使用的篩選條件如下: 

  • dataSize是一個用於搜尋特定大小的帳戶的篩選條件。對於代幣帳戶而言,此數值為已知數值 165。
  • memcmp(即「記憶體比對」)篩選器用於將搜尋範圍縮小至帳戶內部。具體而言,我們將使用offset來確定在帳戶的 165 位元組中應從何處開始搜尋(這是該程式另一個已知值:持有者的公開金鑰從第 32 位元組開始),並使用bytes來設定搜尋對象:在此情況下,即為使用者的錢包地址。 
  • 有關 SPL 代幣帳戶資料的來源資訊,請參閱此處

getTokenAccounts 函式內部,定義一個名為filters的變數

    const filters:GetProgramAccountsFilter[] = [
{
dataSize: 165, //size of account (bytes)
},
{
memcmp: {
offset: 32, //location of our query in the account (bytes)
bytes: wallet, //our search criteria, a base58 encoded string
}
}
];

這樣一來,我們的查詢範圍應能縮小至僅搜尋由我們的錢包持有的代幣帳戶。 

取得程式帳戶

現在呼叫getParsedProgramAccounts方法,並傳入SPL 代幣計畫 ID以及我們的篩選條件。 

    const accounts = await solanaConnection.getParsedProgramAccounts(
TOKEN_PROGRAM_ID, //SPL Token Program, new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
{filters: filters}
);

前一個呼叫會傳回一個包含所有符合條件的代幣帳戶的陣列,其結構如下: 

{
pubkey: PublicKey, //Token Account Public Key
account: AccountInfo //Object including information about our token account
}[]

您可以記錄accounts.length,以查看使用者擁有多少個代幣帳戶: 

console.log(`Found ${accounts.length} token account(s) for wallet ${wallet}.`);

解析結果

建立一個簡單的forEach迴圈,用來遍歷結果並將結果記錄出來。在您的getTokenAccounts函式中加入以下內容:

    accounts.forEach((account, i) => {
//Parse the account data
const parsedAccountInfo:any = account.account.data;
const mintAddress:string = parsedAccountInfo["parsed"]["info"]["mint"];
const tokenBalance: number = parsedAccountInfo["parsed"]["info"]["tokenAmount"]["uiAmount"];
//Log results
console.log(`Token Account No. ${i + 1}: ${account.pubkey.toString()}`);
console.log(`--Token Mint: ${mintAddress}`);
console.log(`--Token Balance: ${tokenBalance}`);
});

執行您的程式碼

最後,呼叫getTokenAccounts(walletToQuery, solanaConnection)。您的最終腳本應如下所示:

import { Connection, GetProgramAccountsFilter } from "@solana/web3.js";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";

const rpcEndpoint = 'https://example.solana-mainnet.quiknode.pro/000000/';
const solanaConnection = new Connection(rpcEndpoint);

const walletToQuery = 'YOUR_PUBLIC_KEY'; //example: vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg

async function getTokenAccounts(wallet: string, solanaConnection: Connection) {
const filters:GetProgramAccountsFilter[] = [
{
dataSize: 165, //size of account (bytes)
},
{
memcmp: {
offset: 32, //location of our query in the account (bytes)
bytes: wallet, //our search criteria, a base58 encoded string
},
}];
const accounts = await solanaConnection.getParsedProgramAccounts(
TOKEN_PROGRAM_ID, //new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
{filters: filters}
);
console.log(`Found ${accounts.length} token account(s) for wallet ${wallet}.`);
accounts.forEach((account, i) => {
//Parse the account data
const parsedAccountInfo:any = account.account.data;
const mintAddress:string = parsedAccountInfo["parsed"]["info"]["mint"];
const tokenBalance: number = parsedAccountInfo["parsed"]["info"]["tokenAmount"]["uiAmount"];
//Log results
console.log(`Token Account No. ${i + 1}: ${account.pubkey.toString()}`);
console.log(`--Token Mint: ${mintAddress}`);
console.log(`--Token Balance: ${tokenBalance}`);
});
}
getTokenAccounts(walletToQuery,solanaConnection);

執行 `ts-node index.ts`,您應該會在終端機中看到類似以下的日誌: 

輸出範例:終端機中的 Token Log 

額外功能:新增更多篩選條件

玩得開心嗎?想試試更多篩選條件嗎?舉例來說,假設你想查看某個錢包是否包含特定鑄造廠發行的代幣。你可以將該篩選條件加入上方的 forEach 迴圈中,但為了縮短搜尋時間,不妨考慮將其加入原始查詢中的 filters 變數中。以下是操作方法。 

請在應用程式頂端的定義中,新增一個用於搜尋的 Mint 位址,例如: 

    const MINT_TO_SEARCH = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'; //USDC 鑄幣地址

現在回到我們的getTokenAccounts函式中,在filters 中新增一個篩選條件,用以搜尋位元組位置 0 處的MINT_TO_SEARCH(此程式中鑄幣公鑰的已知位置): 

    const filters:GetProgramAccountsFilter[] = [
{
dataSize: 165, //size of account (bytes)
},
{
memcmp: {
offset: 32, //location of our query in the account (bytes)
bytes: wallet, //our search criteria, a base58 encoded string
},
},
//Add this search parameter
{
memcmp: {
offset: 0, //number of bytes
bytes: MINT_TO_SEARCH, //base58 encoded string
},
}];

重新執行您的程式碼,您應該會發現結果現在僅限於您搜尋的薄荷: 

輸出範例:單一薄荷搜尋結果 

結論

這樣就完成了!現在你應該已經了解如何查詢錢包中的所有代幣帳戶,並打下紮實的基礎,未來便能進一步查詢其他 Solana 程式。 

覺得這篇文章有幫助嗎?點此查看我們其他關於 Solana 的教學文章。訂閱我們的電子報,獲取更多關於 Solana 的文章和指南。如有任何意見回饋,歡迎透過Twitter聯絡我們。您隨時都可以在我們的Discord社群伺服器上與我們聊天,那裡聚集了您見過最酷的開發者們 :)

我們 ❤️ 您的回饋!

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

分享這份指南