閱讀時間 8 分鐘
概覽
您是否曾需要擷取與某個錢包相關的所有交易?想查看與某台糖果機相關的所有鑄造交易?或者想查看某個 NFT 的交易紀錄?Solana 的getSignaturesForAddress方法是一個多功能工具,能讓您輕鬆取得交易紀錄。
想看影片教學嗎?跟著諾亞一起學習,只需 15 分鐘,就能掌握如何使用 Solana web3.js 取得 Solana 交易日誌。
您將負責的工作內容
在這份指南中,您將深入探索 Solana 交易的精彩世界!您將建立一個簡單的腳本,用以查詢某個地址(錢包、程式 ID、代幣鑄造等),並找出所有與該地址相關的交易紀錄。
您需要準備的物品
- Node.js(版本 16.15 或更高)
- 已安裝Yarn
- Solana Web3
- 具備 Solana 基本交易的實作經驗。若想溫習相關知識,請閱讀我們的初學者指南《如何在 Solana 上發送交易》
- 具備 JavaScript 知識
我們開始吧!
設定您的執行環境
請在終端機中執行以下指令,建立一個新的專案目錄及名為log.js 的檔案:
mkdir get_sol_tx
cd get_sol_tx
echo > log.js
安裝 Solana web3 依賴項:
yarn init -y
yarn add @solana/web3.js@1
或
npm init -y
npm install --save @solana/web3.js@1
在您選擇的程式碼編輯器中開啟log.js 檔案,並在第 1 行引入@solana/web3.js,並將其儲存為常數 **solanaWeb3:
**
const solanaWeb3 = require('@solana/web3.js');
請指定您要搜尋的地址:
const searchAddress = '此處請填寫您的地址'; //範例 'vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg'
注意:此處可為 Solana 上的任何有效地址(例如:錢包地址、鑄造地址、程式地址)。若您尚未擁有此類地址,可將「vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg」作為範例。
好啦,我們準備好要開動了!
建立與您的 Quicknode RPC 的連線
若要在 Solana 上進行開發,您需要一個 API 端點來連線至該網路。您可以使用公開節點,或自行部署並管理基礎架構;不過,若您希望將回應時間縮短 8 倍,不妨將繁重的工作交給我們處理。
了解為何超過 50% 的 Solana 專案選擇 Quicknode,並點此免費註冊。
我們將在 Solana Devnet 上啟動我們的節點,但您也可以根據自身需求啟動相應的節點。請複製 HTTP Provider 的連結:

返回log.js檔案,建立一個常數「endpoint」,並將您的 Quicknode URL 賦值給它。在下一行中,將此常數作為Connection函式的參數傳入,並將結果儲存到另一個名為solanaConnection 的常數中:
const 端點 = 'https://example.solana-devnet.quiknode.pro/000000/';
const solanaConnection = new solanaWeb3.Connection(端點);
太好了!您已經準備好要建立搜尋功能了。
建立交易查詢
getSignaturesForAddress方法將在此承擔大部分繁重的工作。其運作方式如下:
它將接受兩個參數:
- 要搜尋的地址(必填):您要查詢的公鑰
- 選項 (可選):一個包含 3 個可選項目的物件:
- 之前:從特定交易簽名之前的時間點開始向後搜尋
- 之後:從特定交易簽名開始,朝時間前方向搜尋
- limit:要回傳的交易筆數上限(請注意,最大值和預設值皆為 1,000)
它將返回一個 Promise,該 Promise 代表一個包含ConfirmedSignatureInfo 陣列的物件,而 ConfirmedSignatureInfo 是一種包含關鍵交易資訊的類型物件:
- 簽名(交易 ID),
- slot 和 blockTime(用以查看交易何時被處理),
- err(若有錯誤),以及
- 備註(如有與該交易相關的備註)
定義一個新的非同步函式 `getTransactions`,該函式接受兩個參數:`address` 和`numTx`。
在我們的函式內部,呼叫solanaConnection的新實例上的getSignaturesForAddress方法,並將輸出儲存至變數transactionList 中:
const getTransactions = async(address, numTx) => {
const pubKey = new solanaWeb3.PublicKey(address);
let transactionList = await solanaConnection.getSignaturesForAddress(pubKey, {limit:numTx});
}
這應該會回傳一個包含所有符合搜尋條件的交易紀錄的陣列。讓我們以易於閱讀的方式記錄結果。
在getTransactions 函式內部,建立一個forEach迴圈,用來記錄每筆交易相關的資訊:
const getTransactions = async(address, numTx) => {
const pubKey = new solanaWeb3.PublicKey(address);
let transactionList = await solanaConnection.getSignaturesForAddress(pubKey, {limit:numTx});
transactionList.forEach((transaction, i) => {
const date = new Date(transaction.blockTime*1000);
console.log(`Transaction No: ${i+1}`);
console.log(`Signature: ${transaction.signature}`);
console.log(`Time: ${date}`);
console.log(`Status: ${transaction.confirmationStatus}`);
console.log(("-").repeat(20));
})
}
執行您的程式碼!
如果一切設定正確,您應該就能呼叫您的函式並看到一些結果!請將以下內容新增至log.js 檔案的末尾:
getTransactions(searchAddress,3);
現在請在終端機中輸入:
node log.js
您應該會看到類似以下的內容:

哇!還挺簡單的,對吧?不妨試著測試幾個不同的錢包、一個 NFT 鑄造地址,以及一個 Candy Machine ID。你可以發現,這種方法應該會產生類似的結果,這使得它在許多不同的應用場景中都非常實用。
恭喜!您已成功完成交易……您可以在這裡停下來,但如果您想了解還能用這個交易簽名做些什麼,請繼續閱讀!👇
解析交易
現在我們已經掌握了一些關於交易歷史的有用基本資訊,但每筆交易究竟做了什麼呢?我們可以使用 Solana 的getParsedTransaction方法,藉此取得大量額外的詳細資訊。
getParsedTransaction方法會接受一個已確認或已最終確認的交易簽名,並返回一個ParsedTransactionWithMeta物件:
export type ParsedTransactionWithMeta = {
/** The slot during which the transaction was processed */
slot: number;
/** The details of the transaction */
transaction: ParsedTransaction;
/** Metadata produced from the transaction */
meta: ParsedTransactionMeta | null;
/** The unix timestamp of when the transaction was processed */
blockTime?: number | null;
/** The version of the transaction message */
version?: TransactionVersion;
};
這裡蘊含了大量資訊,雖然我們不會在這個入門指南中詳細探討,但我們仍想舉個例子,說明您該如何與這些物件進行互動。
在您的getTransactions函式中,讓我們宣告兩個新變數:signatureList和transactionDetails。我們將透過對transactionList 進行映射來產生一個簽名清單,並透過將這些簽名傳入getParsedTransactions 來產生每筆交易的詳細資訊:
const getTransactions = async(address, numTx) => {
const pubKey = new solanaWeb3.PublicKey(address);
let transactionList = await solanaConnection.getSignaturesForAddress(pubKey, {limit:numTx});
//Add this code
let signatureList = transactionList.map(transaction=>transaction.signature);
let transactionDetails = await solanaConnection.getParsedTransactions(signatureList, {maxSupportedTransactionVersion:0});
//--END of new code
transactionList.forEach((transaction, i) => {
const date = new Date(transaction.blockTime*1000);
console.log(`Transaction No: ${i+1}`);
console.log(`Signature: ${transaction.signature}`);
console.log(`Time: ${date}`);
console.log(`Status: ${transaction.confirmationStatus}`);
console.log(("-").repeat(20));
})
}
當我們的承諾回傳結果時,`transactionDetails` 會返回一個由 `ParsedTransactionWithMeta` 物件組成的陣列。讓我們試著從中找出一些有用的資訊。
假設我們想找出在某筆交易中,我們曾與之互動的所有程式或智慧合約。在原始的forEach迴圈內,於date變數宣告之後,讓我們建立一個新變數transactionInstructions:
const transactionInstructions = 交易詳情[i].交易.訊息.指令;
這將利用我們的索引i,來查找與迴圈中正在查詢的同一筆交易相關的詳細交易資訊。由於每筆交易可能包含多條指令或多個程式迭代,因此我們需要另一個迴圈來取得該交易中的每個程式互動。在迴圈內部,於記錄confirmationStatus之後,請加入以下內容:
transactionInstructions.forEach((instruction, n)=>{
console.log(`---Instructions ${n+1}: ${instruction.programId.toString()}`);
})
我們在此的處理方式是:針對每筆交易,檢視每條交易指令,並記錄程式名稱(若有)及程式 ID。
最終的函式應如下所示:
const getTransactions = async(address, numTx) => {
const pubKey = new solanaWeb3.PublicKey(address);
let transactionList = await solanaConnection.getSignaturesForAddress(pubKey, {limit:numTx});
let signatureList = transactionList.map(transaction=>transaction.signature);
let transactionDetails = await solanaConnection.getParsedTransactions(signatureList, {maxSupportedTransactionVersion:0});
transactionList.forEach((transaction, i) => {
const date = new Date(transaction.blockTime*1000);
const transactionInstructions = transactionDetails[i].transaction.message.instructions;
console.log(`Transaction No: ${i+1}`);
console.log(`Signature: ${transaction.signature}`);
console.log(`Time: ${date}`);
console.log(`Status: ${transaction.confirmationStatus}`);
transactionInstructions.forEach((instruction, n)=>{
console.log(`---Instructions ${n+1}: ${instruction.programId.toString()}`);
})
console.log(("-").repeat(20));
})
}
現在,請再次執行您的腳本。在終端機中輸入:
node log.js
您應該會看到類似以下的內容:

做得真棒!我們的交易結果現在已包含我們曾互動過的各項計畫的詳細資訊!
如果您願意,可以在此處搜尋您的地址,將結果與 Solana 區塊鏈瀏覽器進行比對(請務必透過頁面右上角的選項切換至相同網路進行搜尋)。
總結
太棒了!現在你已經深入了解了 Solana 交易這個令人興奮的世界!
我們將在未來的指南中進一步探討這些內容;但如果您迫不及待想繼續探索,不妨嘗試對 `transactionDetails` 陣列進行實驗,執行一些類似的查詢,但這次改為檢視:
- transactionDetails[i].meta
- transactionDetails[i].transaction.message.accountKeys
若要將這些概念付諸實踐,請點此查看我們其他關於 Solana 的教學指南。
訂閱我們的電子報,獲取更多關於 Solana 的文章和指南。如有任何意見回饋,歡迎透過Twitter聯絡我們。您隨時都可以在我們的Discord社群伺服器上與我們聊天,那裡聚集了您這輩子見過最酷的開發者們 :)
我們 ❤️ 您的回饋!
如果您有任何意見回饋或對新主題的建議,請告訴我們。我們非常樂意聽取您的意見。
