地址轉帳監聽 · 介面詳情
交易查詢模組
交易查詢模組提供對鏈上交易資料的多維度查詢能力,支援按地址查詢歷史列表、批量查詢交易詳情,以及跨鏈聚合查詢。
介面列表
| 方法 | 路徑 | 說明 |
|---|---|---|
| POST | /tx/api/v1/transfers/search | 按地址查詢交易列表(游標分頁) |
| POST | /tx/api/v1/transfers/multi-chain | 多鏈多地址聚合查詢 |
| POST | /tx/api/v1/transactions/batch-get | 按交易雜湊批量查詢詳情 |
| GET | /tx/api/v1/transactions/{tx_hash} | 查詢單筆交易詳情 V2 |
地址交易查詢
介面路徑:POST /tx/api/v1/transfers/search
用途
按單個地址查詢其在指定鏈上的歷史交易列表,支援按交易類型、代幣過濾,使用游標方式分頁。
請求體欄位說明
| 欄位 | 類型 | 必填 | 預設值 | 說明 |
|---|---|---|---|---|
address | string | 是 | - | 待查詢的錢包地址 |
chain_type | string | 否 | - | 鏈類型,不填則跨鏈查詢 |
chain_id | integer | 否 | - | 鏈 ID |
tx_type | string | 否 | "" | 交易類型過濾,空字串表示不過濾 |
token | string | 否 | - | 代幣合約地址,用於過濾特定代幣的轉帳 |
limit | integer | 否 | 20 | 每次返回的最大記錄數,範圍 1~100 |
id | integer | 否 | - | 游標 ID,用於分頁續查 |
範例
# 基本查詢
curl -X POST "$BASE_URL/tx/api/v1/transfers/search" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{
"chain_type": "ethereum",
"chain_id": 1,
"address": "0x1234567890abcdef1234567890abcdef12345678",
"limit": 20
}'
# 按代幣過濾(查詢 USDT 轉帳)
curl -X POST "$BASE_URL/tx/api/v1/transfers/search" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{
"chain_type": "ethereum",
"chain_id": 1,
"address": "0x1234...",
"token": "0xdAC17F958D2ee523a2206206994597C13D831ec7"
}'
回應
{
"code": 1,
"msg": "success",
"data": [
{
"chain_type": "ethereum",
"chain_id": 1,
"height": 21000000,
"tx_time": 1745000000,
"tx_hash": "0xabc123...",
"sender": "0x1234...",
"receiver": "0x5678...",
"amount": "1000000000000000000",
"symbol": "ETH",
"decimals": 18,
"tx_status": "success",
"transfer_type": "native",
"token_transfers": [],
"from_details": [],
"to_details": [],
"internal_transactions": []
}
]
}
注意:此介面成功時
code為1,訊息欄位為msg,與其他介面略有不同。
多地址聚合查詢
介面路徑:POST /tx/api/v1/transfers/multi-chain
用途
同時查詢多條鏈、多個地址的交易記錄,結果聚合後統一返回。
請求體欄位說明
| 欄位 | 類型 | 必填 | 預設值 | 說明 |
|---|---|---|---|---|
addresses | array | 是 | - | 多鏈地址分組列表,至少一項,最多 10 組 |
addresses[].chain_type | string | 是 | - | 鏈類型 |
addresses[].chain_id | integer | 是 | - | 鏈 ID |
addresses[].address | string[] | 是 | - | 該鏈下的地址陣列,每組最多 20 個地址 |
limit | integer | 否 | 20 | 返回的最大記錄數,範圍 1~100 |
id | integer | 否 | - | 游標 ID,用於分頁續查 |
範例
curl -X POST "$BASE_URL/tx/api/v1/transfers/multi-chain" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{
"addresses": [
{"chain_type": "ethereum", "chain_id": 1, "address": ["0xabc...001", "0xabc...002"]},
{"chain_type": "bsc", "chain_id": 56, "address": ["0xdef...003"]},
{"chain_type": "solana", "chain_id": 1, "address": ["SolanaAddress..."]}
],
"limit": 20
}'
回應
與 /tx/api/v1/transfers/search 格式相同,data 為聚合後的交易記錄陣列。
交易詳情批量查詢
介面路徑:POST /tx/api/v1/transactions/batch-get
用途
根據交易雜湊批量查詢交易詳情。
請求體欄位說明
| 欄位 | 類型 | 必填 | 說明 |
|---|---|---|---|
chain_type | string | 是 | 鏈類型 |
chain_id | integer | 是 | 鏈 ID |
tx_hash | string 或 string[] | 是 | 單個交易雜湊或雜湊陣列 |
範例
# 查詢單筆交易
curl -X POST "$BASE_URL/tx/api/v1/transactions/batch-get" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{"chain_type": "ethereum", "chain_id": 1, "tx_hash": "0xabc123..."}'
# 批量查詢多筆交易
curl -X POST "$BASE_URL/tx/api/v1/transactions/batch-get" \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-d '{"chain_type": "ethereum", "chain_id": 1, "tx_hash": ["0xabc123...", "0xdef456..."]}'
單筆交易詳情查詢
介面路徑:GET /tx/api/v1/transactions/{tx_hash}
用途
查詢單筆交易的完整詳情(V2 版本)。與 /tx/api/v1/transactions/batch-get 的主要區別:
- 採用 GET 請求,參數透過 Query String 傳遞
- 支援
no_cache參數強制回源:當資料庫中無記錄時,可按鏈即時拉取並寫入快取 - 回源成功後會自動將資料寫入資料庫快取
- 返回的資料結構採用混合欄位命名(歷史相容格式,部分欄位為 camelCase)
請求參數
| 參數名 | 位置 | 類型 | 必填 | 說明 |
|---|---|---|---|---|
chain_type | query | string | 是 | 鏈類型 |
chain_id | query | integer | 是 | 鏈 ID |
tx_hash | path | string | 是 | 交易雜湊,支援帶或不帶 0x 前綴 |
no_cache | query | string | 否 | 傳 true 或 1 時跳過本地快取直接回源 |
範例
# 正常查詢
curl "$BASE_URL/tx/api/v1/transactions/0xabc123...?chain_type=ethereum&chain_id=1"
# 強制回源查詢
curl "$BASE_URL/tx/api/v1/transactions/0xabc123...?chain_type=ethereum&chain_id=1&no_cache=true"
回應(找到交易)
{
"code": 0,
"msg": "success",
"data": {
"chain_type": "ethereum",
"chain_id": 1,
"height": 21000000,
"txTime": 1745000000000,
"txhash": "0xabc123...",
"sender": "0x1234...",
"fee_payer": "0x1234...",
"receiver": "0x5678...",
"transfer_type": "native",
"gasLimit": "21000",
"gasUsed": "21000",
"gasPrice": "20000000000",
"max_fee_per_gas": "30000000000",
"max_priority_fee_per_gas": "1000000000",
"txFee": "420000000000000",
"nonce": "42",
"symbol": "ETH",
"decimals": 18,
"amount": "1000000000000000000",
"txStatus": "success",
"methodId": "",
"methodCall": "",
"l1OriginHash": "",
"fromDetails": [],
"toDetails": [],
"internalTransactionDetails": [],
"tokenTransferDetails": [],
"listenAddress": null,
"is_reorg_resend": false
}
}
回應(交易不存在)
{
"code": 0,
"msg": "success",
"data": null
}
交易資料結構詳解
TransactionDetail(列表查詢返回格式)
/tx/api/v1/transfers/search、/tx/api/v1/transfers/multi-chain、/tx/api/v1/transactions/batch-get 介面返回的交易格式。
主體欄位:
| 欄位 | 類型 | 說明 |
|---|---|---|
chain_type | string | 歸一化後的鏈類型,小寫 |
chain_id | integer | 鏈 ID |
height | integer | null | 區塊高度 |
tx_time | integer | null | 交易時間,秒級 Unix 時間戳 |
tx_hash | string | 交易雜湊 |
tx_version | integer | null | 交易版本號(Solana 等使用) |
sender | string | null | 傳送方地址 |
fee_payer | string | null | 手續費支付方地址(Solana 場景) |
receiver | string | null | 接收方地址 |
transfer_type | string | null | 交易類型,如 native(原生轉帳)、token(代幣轉帳) |
amount | string | null | 交易金額,字串格式避免精度遺失 |
symbol | string | null | 主幣或代幣符號,如 ETH、BNB |
decimals | integer | null | 精度位數,如 18 |
tx_status | string | null | 交易狀態:success、failed、pending |
tx_fee | string | null | 交易手續費 |
gas_limit | string | null | Gas 上限(EVM) |
gas_used | string | null | 實際消耗 Gas(EVM) |
gas_price | string | null | Gas 單價(EVM) |
max_fee_per_gas | string | null | EIP-1559 最大 Gas 單價 |
max_priority_fee_per_gas | string | null | EIP-1559 優先費單價 |
nonce | string | null | 帳戶 Nonce(EVM) |
method_id | string | null | 合約呼叫方法選擇器(EVM) |
method_call | string | null | 合約方法名或呼叫摘要 |
l1_origin_hash | string | null | 二層鏈對應的 L1 原始交易雜湊 |
token_transfers | array | 代幣轉帳明細列表 |
from_details | array | 輸入地址明細(UTXO 模型) |
to_details | array | 輸出地址明細(UTXO 模型) |
internal_transactions | array | 內部交易或 Solana 指令明細 |
token_transfers(代幣轉帳明細):
| 欄位 | 類型 | 說明 |
|---|---|---|
from_address | string | null | 代幣轉出地址 |
to_address | string | null | 代幣轉入地址 |
token_contract_address | string | null | 代幣合約地址 |
symbol | string | null | 代幣符號 |
amount | string | null | 轉帳數量 |
decimals | integer | null | 代幣精度 |
is_from_contract | boolean | 轉出方是否為合約地址 |
is_to_contract | boolean | 轉入方是否為合約地址 |
from_token_address | string | null | 來源 token 帳戶地址(Solana) |
to_token_address | string | null | 目標 token 帳戶地址(Solana) |
mint | string | null | Solana Mint 地址 |
program_id | string | null | Solana Program ID |
from_details(輸入地址明細,UTXO 模型):
| 欄位 | 類型 | 說明 |
|---|---|---|
address | string | null | 輸入地址 |
amount | string | null | 輸入金額 |
is_contract | boolean | 是否為合約地址 |
vin_index | string | null | UTXO 輸入索引 |
pre_vout_index | string | null | 前序交易輸出索引 |
ref_tx_hash | string | null | 前序引用交易雜湊 |
to_details(輸出地址明細,UTXO 模型):
| 欄位 | 類型 | 說明 |
|---|---|---|
address | string | null | 輸出地址 |
amount | string | null | 輸出金額 |
is_contract | boolean | 是否為合約地址 |
vout_index | string | null | UTXO 輸出索引 |
internal_transactions(內部交易 / Solana 指令):
| 欄位 | 類型 | 說明 |
|---|---|---|
from_address | string | null | 內部呼叫傳送方 |
to_address | string | null | 內部呼叫接收方 |
amount | string | null | 內部呼叫金額 |
tx_status | string | null | 內部呼叫狀態 |
program_id | string | null | Solana Program ID |
instr_index | integer | null | Solana 指令索引 |
depth | integer | null | Solana 呼叫深度 |
instruction | string | null | Solana 指令名稱 |
description | string | null | 指令說明 |
V2 介面欄位命名差異
/tx/api/v1/transactions/{tx_hash} 介面返回的格式採用混合命名風格(歷史相容),與列表查詢格式有所不同:
| V2 格式欄位 | 對應列表格式欄位 | 主要差異 |
|---|---|---|
txhash | tx_hash | 欄位名不同 |
txTime | tx_time | camelCase,且為毫秒級時間戳 |
txStatus | tx_status | camelCase |
txFee | tx_fee | camelCase |
gasLimit | gas_limit | camelCase |
gasUsed | gas_used | camelCase |
gasPrice | gas_price | camelCase |
methodId | method_id | camelCase |
methodCall | method_call | camelCase |
l1OriginHash | l1_origin_hash | camelCase |
fromDetails | from_details | camelCase |
toDetails | to_details | camelCase |
internalTransactionDetails | internal_transactions | 欄位名不同 |
tokenTransferDetails | token_transfers | 欄位名不同 |
分頁說明
交易列表查詢使用游標(Cursor)分頁而非傳統的頁碼分頁:
- 首次請求時不傳
id參數,取得最新的 N 筆記錄 - 如果返回記錄數量等於
limit,說明可能還有更多資料 - 取返回陣列中最後一筆記錄的資料庫內部
id傳給下一次請求的id參數 - 繼續請求,直到返回記錄數量少於
limit為止
注意:游標分頁不支援跳頁,只能順序向前翻頁。
金額處理建議
所有金額欄位均以字串形式返回,以避免大數精度問題。展示時需結合 decimals 欄位進行換算:
function formatAmount(amount, decimals) {
if (!amount || decimals === null) return '0';
const bigAmount = BigInt(amount);
const divisor = BigInt(10 ** decimals);
const intPart = bigAmount / divisor;
const fracPart = bigAmount % divisor;
return `${intPart}.${fracPart.toString().padStart(decimals, '0')}`;
}
// 示例:1000000000000000000 (decimals=18) → "1.000000000000000000"
console.log(formatAmount('1000000000000000000', 18));
DEX Pool 最近交易介面
DEX Pool 模組用於維護需要監聽的 Pool 地址,並提供最近交易查詢。相關訂閱和推送仍使用地址管理介面或 WebSocket subscribe。
當鏈上交易處理成功後,系統會用交易參與地址匹配已啟用的 Pool 地址。命中後將完整 TransactionResult 寫入該 Pool 對應的 Durable Object FIFO 佇列,佇列容量預設最多保留最近 100 筆。
查詢 Pool 最近交易
介面路徑:GET /tx/api/v1/dex-pools/{poolAddress}/trades
用途
公開查詢指定 Pool 的最近交易記錄,不需要額外管理員鑑權。
Query 參數
| 欄位 | 類型 | 必填 | 預設值 | 說明 |
|---|---|---|---|---|
chainType | string | 是 | 無 | 鏈類型;相容 chain_type。 |
chainId | number | 是 | 無 | 鏈 ID;相容 chain_id。 |
limit | number | 否 | 100 | 返回最近交易筆數,範圍 1 到 100。 |
範例
curl "$BASE_URL/tx/api/v1/dex-pools/0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8/trades?chainType=evm&chainId=1&limit=50"
成功回應
{
"code": 0,
"message": "ok",
"data": {
"items": [
{
"chainType": "evm",
"chainId": 1,
"height": 19600000,
"txTime": 1710000000,
"txHash": "0x...",
"sender": "0xsender...",
"feePayer": "0xsender...",
"receiver": "0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8",
"transferType": "Token",
"gasLimit": "21000",
"gasUsed": "21000",
"gasPrice": "1000000000",
"maxFeePerGas": "",
"maxPriorityFeePerGas": "",
"txFee": "21000000000000",
"nonce": "1",
"symbol": "ETH",
"decimals": 18,
"amount": "0",
"txStatus": "success",
"methodId": "0xa9059cbb",
"methodCall": "0x...",
"fromDetails": [],
"toDetails": [],
"internalTransactionDetails": [],
"tokenTransferDetails": [
{
"from": "0xsender...",
"to": "0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8",
"isFromContract": false,
"isToContract": false,
"tokenContractAddress": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"symbol": "USDC",
"amount": "1000000",
"decimals": 6
}
]
}
]
}
}
返回交易欄位
data.items 為 TransactionResult[],欄位命名和 HTTP webhook 推送 body 中的陣列元素一致,不使用 WebSocket 推送裡的 chain_type、txhash、transfer_type 等欄位名。可選欄位值為 undefined 時 JSON 中會省略,值為 null 時會保留為 null。
主要欄位包括:chainType、chainId、height、txTime、txHash、sender、feePayer、receiver、transferType、gasLimit、gasUsed、gasPrice、maxFeePerGas、maxPriorityFeePerGas、txFee、nonce、symbol、decimals、amount、txStatus、methodId、methodCall、fromDetails、toDetails、internalTransactionDetails、tokenTransferDetails。
地址管理模組
地址管理模組用於維護每個業務應用的監聽地址名單。只有新增到名單中的地址,其鏈上交易才會被推送到對應應用的 WebSocket 訂閱者或 Webhook 回呼。
介面列表
| 方法 | 路徑 | 說明 |
|---|---|---|
| PATCH | /tx/api/v1/addresses | Patch 模式:同時增刪地址 |
| POST | /tx/api/v1/addresses | 批量新增地址 |
| POST | /tx/api/v1/addresses/batch-delete | 批量移除地址 |
| POST | /tx/api/v1/addresses/contains | 查詢地址是否存在於名單 |
公共鑑權說明
所有地址受保護介面都透過 X-API-Key 識別呼叫方。服務會基於該 Key 完成介面鑑權、業務歸屬識別和計費統計。
| 方式 | 說明 | 範例 |
|---|---|---|
| 請求頭 | 公共 API Key | X-API-Key: your-api-key |
注意:公網接入只需傳入
X-API-Key,不需要額外的應用標識請求頭或查詢參數。
新增監聽地址介面
介面路徑:POST /tx/api/v1/addresses
用途
向指定應用的監聽地址名單中批量新增地址。支援同時為多條鏈新增地址。
鏈特殊處理行為
- 其他非 EVM 鏈:會嘗試將地址同步到平台內部監聽元件;同步失敗不會阻斷本地入庫。
請求體欄位說明
| 欄位 | 類型 | 必填 | 說明 |
|---|---|---|---|
wallets | array | 是 | 按鏈分組的地址列表,至少一項 |
wallets[].chain_type | string | 是 | 鏈類型,如 ethereum、solana、tron |
wallets[].address | string[] | 是 | 該鏈下的地址陣列,至少一個地址 |
範例
# 新增以太坊地址
curl -X POST "$BASE_URL/tx/api/v1/addresses" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"wallets": [
{
"chain_type": "ethereum",
"address": ["0x1234...", "0xabcd..."]
}
]
}'
# 同時新增多鏈地址
curl -X POST "$BASE_URL/tx/api/v1/addresses" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"wallets": [
{"chain_type": "ethereum", "address": ["0x1234..."]},
{"chain_type": "tron", "address": ["TJDENsfBJs4RFETt1X1uyT9pBxdnAbFnbm"]},
{"chain_type": "solana", "address": ["SolanaAddress..."]}
]
}'
回應
{
"code": 0,
"message": "ok",
"data": "success"
}
移除監聽地址
介面路徑:POST /tx/api/v1/addresses/batch-delete
用途
從指定應用的監聽地址名單中批量移除地址。移除後,該地址的新交易將不再推送給該應用。
請求體欄位說明
與 /tx/api/v1/addresses 相同:wallets[].chain_type + wallets[].address。
範例
curl -X POST "$BASE_URL/tx/api/v1/addresses/batch-delete" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"wallets": [
{"chain_type": "ethereum", "address": ["0x1234..."]}
]
}'
回應
{
"code": 0,
"message": "ok",
"data": "success"
}
地址名單 Patch 更新
介面路徑:PATCH /tx/api/v1/addresses
用途
以 Patch 模式同時對某條鏈執行地址的增刪操作,在一次請求中完成地址名單的部分更新。
請求體欄位說明
| 欄位 | 類型 | 必填 | 預設值 | 說明 |
|---|---|---|---|---|
chain_type | string | 是 | - | 鏈類型,此介面一次只操作一條鏈 |
adds | string[] | 否 | [] | 要加入名單的地址列表 |
removes | string[] | 否 | [] | 要移出名單的地址列表 |
範例
curl -X PATCH "$BASE_URL/tx/api/v1/addresses" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"chain_type": "ethereum",
"adds": ["0xNewAddress001...", "0xNewAddress002..."],
"removes": ["0xOldAddress001..."]
}'
回應
{
"code": 0,
"message": "ok",
"data": "success"
}
地址存在性查詢
介面路徑:POST /tx/api/v1/addresses/contains
用途
查詢某個地址是否已在指定鏈的地址名單中。
說明:目前版本此介面只驗證地址在全域地址表中是否存在,不按 API Key 隔離過濾。
請求體欄位說明
| 欄位 | 類型 | 必填 | 說明 |
|---|---|---|---|
chain_type | string | 是 | 鏈類型 |
address | string | 是 | 待查詢的地址 |
範例
curl -X POST "$BASE_URL/tx/api/v1/addresses/contains" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{"chain_type": "ethereum", "address": "0x1234..."}'
回應
{
"code": 0,
"message": "ok",
"data": {
"is_exist": true
}
}
地址管理最佳實務
地址格式規範:
- EVM 鏈:使用
0x開頭的 Hex 格式地址,建議使用 EIP-55 checksum 格式 - Solana:使用 Base58 格式地址
- Tron:使用 Base58Check 格式(以
T開頭) - Bitcoin:使用標準 Bitcoin 地址格式(P2PKH、P2SH、Bech32 等)
地址名單與 WebSocket 訂閱的關係:
- 透過
/tx/api/v1/addresses新增的地址會被持久化到資料庫,應用重啟後仍然有效 - WebSocket 連線建立後,服務會自動監聽該應用名單中的所有地址
- 也可以在 WebSocket 連線建立後,透過
subscribe命令動態追加監聽,但這種方式僅對目前連線有效,斷線後不會自動恢復
建議使用 HTTP 介面管理地址名單,WebSocket 的 subscribe/unsubscribe 命令僅用於臨時的細粒度控制。
Webhook 回呼推送
Webhook 模組用於把監聽地址命中的鏈上交易主動推送到接入方提供的 HTTP 回呼地址。它適合服務端到服務端整合:接入方無需保持 WebSocket 長連線,只需提供一個可公網存取的 HTTPS 介面並配置到目前應用。
推送配置介面
| 方法 | 路徑 | 說明 |
|---|---|---|
| GET | /tx/api/v1/app/config | 查詢目前應用的推送配置 |
| POST | /tx/api/v1/app/config | 建立或替換目前應用的推送配置 |
| PUT | /tx/api/v1/app/config | 局部更新目前應用的推送配置 |
| DELETE | /tx/api/v1/app/config | 刪除目前應用的推送配置 |
| GET | /tx/api/v1/app/webhook/retry/status | 查詢 Webhook 持久化重試狀態 |
| POST | /tx/api/v1/app/webhook/retry | 手動觸發一次 Webhook 立即重試 |
所有配置介面均透過 X-API-Key 識別目前應用:
curl "$BASE_URL/tx/api/v1/app/config" \
-H "X-API-Key: your-api-key"
配置欄位
| 欄位 | 類型 | 必填 | 說明 |
|---|---|---|---|
enable_ws | boolean | 否 | 是否啟用 WebSocket 推送 |
enable_webhook | boolean | 否 | 是否啟用 Webhook 推送 |
webhook_url | string | null | 否 | 接入方回呼地址,必須是合法 URL;傳 null 表示清空 |
webhook_secret | string | null | 否 | 共享金鑰。服務端推送時會原樣放入請求頭 Sign |
ws_ack_resend_interval_seconds | integer | 否 | WebSocket ACK 重發間隔,單位秒 |
is_active | boolean | 否 | 是否啟用目前應用配置,僅 PUT 支援 |
注意:
GET /tx/api/v1/app/config不會返回webhook_secret。如果需要輪換金鑰,請透過POST或PUT重新設定。
開啟 Webhook
curl -X PUT "$BASE_URL/tx/api/v1/app/config" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"enable_webhook": true,
"webhook_url": "https://example.com/tx-history/webhook",
"webhook_secret": "replace-with-shared-secret"
}'
成功回應:
{
"code": 0,
"message": "ok",
"data": "success"
}
查詢配置回應範例:
{
"code": 0,
"message": "ok",
"data": {
"app_id": "current-business-identity",
"enable_ws": true,
"enable_webhook": true,
"webhook_url": "https://example.com/tx-history/webhook",
"ws_ack_resend_interval_seconds": 60,
"webhook_delivery_status": "active",
"webhook_retrying_since": null,
"webhook_last_failed_transaction_id": null,
"webhook_last_failure_reason": null,
"is_active": true,
"created_at": "2026-05-21T06:00:00.000Z",
"updated_at": "2026-05-21T06:10:00.000Z"
}
}
Webhook 投遞狀態欄位
| 欄位 | 類型 | 說明 |
|---|---|---|
webhook_delivery_status | string | Webhook 投遞狀態:active 正常推送,retrying 正在持久化重試,disabled 已因連續失敗自動關閉 |
webhook_retrying_since | integer | null | 進入重試狀態的秒級 Unix 時間戳 |
webhook_last_failed_transaction_id | integer | null | 超過 36 小時仍失敗時記錄的內部交易 ID |
webhook_last_failure_reason | string | null | 最近一次或最終失敗原因 |
關閉或清空 Webhook
curl -X PUT "$BASE_URL/tx/api/v1/app/config" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"enable_webhook": false,
"webhook_url": null
}'
回呼請求格式
當監聽地址命中新交易,且目前應用滿足 enable_webhook=true、webhook_url 已配置、is_active=true 時,服務端會向 webhook_url 傳送請求。
POST https://example.com/tx-history/webhook
Content-Type: application/json
Sign: replace-with-shared-secret
| 項 | 說明 |
|---|---|
| 請求方法 | 固定為 POST |
Content-Type | 固定為 application/json |
Sign | 配置的 webhook_secret;未配置時為空字串 |
| 請求體 | TransactionResult[],即交易物件陣列 |
| 回應要求 | 建議在業務接收成功後返回任意 2xx 狀態碼;回應體不做格式要求 |
說明:目前版本的
Sign是共享金鑰透傳,不是 HMAC 摘要簽名。接入方應使用常量時間比較驗證該值,並只接受 HTTPS 回呼。
Webhook 持久化重試
當 Webhook 首次推送失敗時,服務會將本批交易寫入持久化重試佇列,並把目前應用標記為 webhook_delivery_status=retrying。處於重試狀態時,後續命中的交易不會繼續直接請求訂閱方服務,而是全部進入佇列。
重試由獨立排程器執行,間隔從 1s 開始漸進增長,最長到 36h。每次重試會從資料庫讀取待推送交易詳情,並按最多 100 筆交易組成一個 TransactionResult[] 批量 POST 到 webhook_url。只要訂閱方返回任意 2xx 狀態碼,本批即視為投遞成功。
如果某批訊息從首次失敗起超過 36h 仍無法成功投遞,服務會自動將 enable_webhook 更新為 false,並在應用配置中記錄失敗交易 ID 與最後失敗原因。訂閱方修復服務後,需要重新開啟 Webhook。
查詢重試狀態
介面路徑:GET /tx/api/v1/app/webhook/retry/status
curl "$BASE_URL/tx/api/v1/app/webhook/retry/status" \
-H "X-API-Key: your-api-key"
回應範例:
{
"code": 0,
"message": "ok",
"data": {
"app_id": "current-business-identity",
"enable_webhook": true,
"webhook_delivery_status": "retrying",
"webhook_retrying_since": 1779680000,
"webhook_last_failed_transaction_id": null,
"webhook_last_failure_reason": "Webhook HTTP 503: service unavailable",
"pending": 42,
"next_retry_at": 1779680060
}
}
手動觸發重試
介面路徑:POST /tx/api/v1/app/webhook/retry
訂閱方服務恢復後,可手動觸發一次立即重試,加快積壓訊息投遞:
curl -X POST "$BASE_URL/tx/api/v1/app/webhook/retry" \
-H "X-API-Key: your-api-key"
回應範例:
{
"code": 0,
"message": "ok",
"data": {
"code": 0,
"message": "ok",
"data": {
"attempted": 42,
"delivered": 42,
"failed": 0,
"finalFailed": false,
"nextRetryAt": null,
"pending": 0
}
}
}
回呼 Body 範例
Webhook 請求體沒有外層 code、message 或 data 包裝,直接是交易陣列。同一次回呼可能包含一筆或多筆交易。
[
{
"chainType": "evm",
"chainId": 1,
"height": 21000000,
"txTime": 1745000000000,
"txHash": "0xabc123...",
"sender": "0x1234...",
"feePayer": "0x1234...",
"receiver": "0x5678...",
"transferType": "NativeCoin",
"gasLimit": "21000",
"gasUsed": "21000",
"gasPrice": "20000000000",
"maxFeePerGas": "30000000000",
"maxPriorityFeePerGas": "1000000000",
"txFee": "420000000000000",
"nonce": "42",
"symbol": "ETH",
"decimals": 18,
"amount": "1000000000000000000",
"txStatus": "success",
"methodId": "",
"methodCall": "",
"fromDetails": [],
"toDetails": [],
"internalTransactionDetails": [],
"tokenTransferDetails": []
}
]
ERC-20 / Token 轉帳範例:
[
{
"chainType": "evm",
"chainId": 1,
"height": 21000001,
"txTime": 1745000005000,
"txHash": "0xdef456...",
"sender": "0x1234...",
"feePayer": "0x1234...",
"receiver": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"transferType": "Token",
"gasLimit": "65000",
"gasUsed": "52000",
"gasPrice": "20000000000",
"maxFeePerGas": "30000000000",
"maxPriorityFeePerGas": "1000000000",
"txFee": "1040000000000000",
"nonce": "43",
"symbol": "ETH",
"decimals": 18,
"amount": "0",
"txStatus": "success",
"methodId": "0xa9059cbb",
"methodCall": "transfer(address,uint256)",
"fromDetails": [],
"toDetails": [],
"internalTransactionDetails": [],
"tokenTransferDetails": [
{
"from": "0x1234...",
"to": "0x5678...",
"isFromContract": false,
"isToContract": false,
"tokenContractAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"symbol": "USDT",
"amount": "1000000000",
"decimals": 6
}
]
}
]
Webhook 交易欄位
Webhook body 中的陣列元素為 TransactionResult,欄位採用 camelCase 命名,和 DEX Pool 最近交易介面 的 data.items 元素一致,不使用 WebSocket 推送中的 chain_type、txhash、transfer_type 等欄位名。
| 欄位 | 類型 | 說明 |
|---|---|---|
chainType | string | 鏈類型。內部規範值通常為 evm、svm、tvm、utxo 等 |
chainId | integer | 鏈 ID |
height | integer | 區塊高度 |
txTime | integer | 交易時間戳;通常為毫秒級 Unix 時間戳 |
txHash | string | 交易雜湊 |
sender | string | 傳送方地址 |
feePayer | string | 手續費支付方地址,部分鏈可能省略 |
receiver | string | 接收方地址或合約地址 |
transferType | string | 交易類型,如 NativeCoin、Token、合約呼叫等 |
gasLimit | string | Gas 上限 |
gasUsed | string | 實際消耗 Gas |
gasPrice | string | Gas 單價 |
maxFeePerGas | string | EIP-1559 最大 Gas 單價 |
maxPriorityFeePerGas | string | EIP-1559 優先費單價 |
txFee | string | 交易手續費 |
nonce | string | 帳戶 Nonce |
symbol | string | 主幣符號 |
decimals | integer | 主幣精度 |
amount | string | 主交易金額,字串格式避免精度遺失 |
txStatus | string | 交易狀態,如 success、failed、pending |
bizStatus | string | null | 業務處理狀態,可能不存在 |
bizStatusReason | string | null | 業務狀態說明,可能不存在 |
methodId | string | 合約方法選擇器 |
methodCall | string | 合約方法名或呼叫摘要 |
txVersion | integer | 交易版本號,部分鏈可能存在 |
l1OriginHash | string | 二層鏈對應的 L1 原始交易雜湊,部分鏈可能存在 |
fromDetails | array | UTXO 輸入地址明細 |
toDetails | array | UTXO 輸出地址明細 |
internalTransactionDetails | array | 內部交易或 Solana 指令明細 |
tokenTransferDetails | array | 代幣轉帳明細 |
tokenTransferDetails
| 欄位 | 類型 | 說明 |
|---|---|---|
from | string | 代幣轉出地址 |
to | string | 代幣轉入地址 |
isFromContract | boolean | 轉出方是否為合約地址 |
isToContract | boolean | 轉入方是否為合約地址 |
tokenContractAddress | string | 代幣合約地址 |
symbol | string | 代幣符號 |
amount | string | 轉帳數量,字串格式 |
decimals | integer | 代幣精度 |
fromTokenAddress | string | 來源 token 帳戶地址,Solana 場景可能存在 |
toTokenAddress | string | 目標 token 帳戶地址,Solana 場景可能存在 |
mint | string | Solana Mint 地址,可能存在 |
programId | string | Solana Program ID,可能存在 |
fromDetails / toDetails
| 欄位 | 類型 | 說明 |
|---|---|---|
address | string | 輸入或輸出地址 |
amount | string | 金額,字串格式 |
isContract | boolean | 是否為合約地址 |
vinIndex | string | UTXO 輸入索引,fromDetails 中可能存在 |
preVoutIndex | string | 前序交易輸出索引,fromDetails 中可能存在 |
txHash | string | 前序引用交易雜湊,fromDetails 中可能存在 |
voutIndex | string | UTXO 輸出索引,toDetails 中可能存在 |
internalTransactionDetails
| 欄位 | 類型 | 說明 |
|---|---|---|
from | string | 內部呼叫傳送方 |
to | string | 內部呼叫接收方 |
amount | string | 內部呼叫金額 |
txStatus | string | 內部呼叫狀態 |
mint | string | Solana Mint 地址,可能存在 |
owner | string | Solana Owner 地址,可能存在 |
programId | string | Solana Program ID,可能存在 |
isFromContract | boolean | 傳送方是否為合約地址 |
isToContract | boolean | 接收方是否為合約地址 |
instrIndex | integer | Solana 外層指令索引 |
depth | integer | Solana 呼叫深度 |
instruction | string | Solana 指令名 |
description | string | 指令說明 |
接入方處理建議
- 鑑權:驗證請求頭
Sign是否等於配置的webhook_secret,未通過時返回401或403。 - 冪等:以
chainType + chainId + txHash作為主冪等鍵;如果一筆交易內有多條代幣明細,可結合tokenContractAddress + from + to + amount做業務明細去重。 - 快速回應:建議先持久化原始 body 或寫入佇列,再非同步執行業務處理,避免回呼介面耗時過長。
- 金額處理:所有金額欄位均為字串,應結合對應
decimals換算展示金額,避免使用 JavaScriptnumber直接承載大整數。 - 異常重試:服務端提供 Webhook 持久化重試,單批最多 100 筆交易,最長重試視窗 36 小時;接入方仍應以
chainType + chainId + txHash做冪等處理,並保留歷史查詢補償能力。
WebSocket 即時推送
WebSocket 模組提供鏈上交易的即時推送能力。客戶端建立 WebSocket 連線後,服務會在監聽地址產生鏈上交易時立即推送訊息。
連線端點:
GET /tx/api/v1/transaction/ws
建立連線
請求說明
WebSocket 握手需要以下請求頭:
| 請求頭 | 類型 | 必填 | 說明 |
|---|---|---|---|
Upgrade | string | 是 | 固定值 websocket |
X-API-Key | string | 是 | 公共 API Key,用於鑑權和計費識別 |
X-ResendDuration | string | 否 | 歷史訊息重發時間視窗(秒),預設 180 |
注意:缺少
X-API-Key時,連線請求會返回400或鑑權失敗。
連線範例
# 使用 wscat
wscat -c "wss://api.gelabs.org/tx/api/v1/transaction/ws" \
-H "X-API-Key: your-api-key"
連線成功訊息
連線建立後,服務端立即推送:
{
"id": "msg-uuid-001",
"time": 1745000000000,
"type": "connected",
"code": 0,
"data": {
"clientId": "client-abc123",
"appId": "current-business-identity"
},
"msg": "success"
}
| 欄位 | 說明 |
|---|---|
data.clientId | 目前連線在服務端的唯一標識,斷線重連後會變化 |
data.appId | 目前連線綁定的呼叫方身分 |
連線失敗
| HTTP 狀態碼 | 原因 | 處理建議 |
|---|---|---|
400 | 未提供 API Key | 確認已正確傳入 X-API-Key |
426 | Upgrade: websocket 頭缺失 | 確認使用 WebSocket 協定連線 |
訊息格式
所有 WebSocket 訊息均使用 JSON 格式,遵循以下統一結構:
{
"id": "消息唯一 ID",
"time": 1745000000000,
"type": "消息类型",
"code": 0,
"data": {},
"msg": "success"
}
| 欄位 | 類型 | 說明 |
|---|---|---|
id | string | 訊息唯一 ID,由傳送方生成 |
time | integer | 訊息時間戳,毫秒級 Unix 時間戳 |
type | string | 訊息類型,決定訊息的業務含義 |
code | integer | 業務狀態碼,0 表示成功,非 0 表示錯誤 |
data | object | null | 訊息業務資料 |
msg | string | 文字訊息,成功時通常為 success |
客戶端命令
客戶端可以向服務端傳送以下命令。每條命令都需要提供唯一的 id 欄位,服務端的回執會使用相同的 id 值。
ping(心跳)
傳送心跳以保持連線活躍。
傳送:
{
"id": "ping-001",
"type": "ping",
"data": {}
}
服務端回執:
{
"id": "ping-001",
"time": 1745000000000,
"type": "pong",
"code": 0,
"data": null,
"msg": "success"
}
subscribe(訂閱地址)
訂閱指定地址在指定鏈上的即時交易推送。
說明:透過此命令訂閱的地址僅對目前連線有效,連線斷開後不會保存。如需持久化地址訂閱,請使用地址受保護介面提前將地址加入名單。
傳送:
{
"id": "cmd-001",
"type": "subscribe",
"data": {
"address": "0x1234567890abcdef1234567890abcdef12345678",
"chain_type": "ethereum"
}
}
命令參數:
| 欄位 | 類型 | 必填 | 說明 |
|---|---|---|---|
data.address | string | 是 | 待訂閱的地址 |
data.chain_type | string | 是 | 鏈類型,服務端會轉為小寫 |
成功回執:
{
"id": "cmd-001",
"type": "subscribe",
"code": 0,
"data": {"API Key": "current-business-identity", "address": "0x1234...", "chain_type": "ethereum"},
"msg": "success"
}
錯誤回執:
{
"id": "cmd-001",
"type": "subscribe",
"code": 400,
"data": null,
"msg": "address and chain_type required"
}
unsubscribe(取消訂閱)
取消對指定地址的即時交易訂閱。
傳送(取消特定鏈):
{
"id": "cmd-002",
"type": "unsubscribe",
"data": {
"address": "0x1234...",
"chain_type": "ethereum"
}
}
傳送(取消所有鏈,省略 chain_type):
{
"id": "cmd-002",
"type": "unsubscribe",
"data": {
"address": "0x1234..."
}
}
命令參數:
| 欄位 | 類型 | 必填 | 說明 |
|---|---|---|---|
data.address | string | 是 | 待取消訂閱的地址 |
data.chain_type | string | 否 | 鏈類型,不填則取消該地址所有鏈的訂閱 |
成功回執:
{
"id": "cmd-002",
"type": "unsubscribe",
"code": 0,
"data": {"address": "0x1234...", "chainType": "ethereum"},
"msg": "success"
}
取消所有鏈時,chainType 為 null。
getTxHash(查詢交易詳情)
透過 WebSocket 連線查詢單筆交易的完整詳情。
傳送:
{
"id": "cmd-003",
"type": "getTxHash",
"data": {
"chain_type": "ethereum",
"chain_id": 1,
"txHash": "0xabc123..."
}
}
命令參數:
| 欄位 | 類型 | 必填 | 說明 |
|---|---|---|---|
data.chain_type | string | 是 | 鏈類型 |
data.chain_id | integer | 是 | 鏈 ID |
data.txHash | string | 否 | 交易雜湊 |
data.messageId | string | 否 | 即時推送訊息的唯一 ID,優先使用此欄位 |
建議:優先使用
messageId(即推送訊息的id欄位值)查詢,服務端可更精確地定位記錄。
錯誤回執(交易不存在):
{
"id": "cmd-003",
"type": "getTxHash",
"code": 404,
"data": null,
"msg": "transaction not found"
}
transactionACK(確認已處理交易)
客戶端收到 transaction 訊息並成功處理後,應傳送 ACK 確認。服務端收到 ACK 後會停止對該筆交易的重發邏輯。
重要:如果客戶端長時間未傳送 ACK,服務端可能在客戶端重連後重新推送未確認的交易,以確保訊息不遺失。
傳送:
{
"id": "ack-001",
"type": "transactionACK",
"data": {
"chain_type": "ethereum",
"chain_id": 1,
"txHash": "0xabc123..."
}
}
成功回執:
{
"id": "ack-001",
"type": "transactionACK",
"code": 0,
"data": {"txHash": "0xabc123..."},
"msg": "success"
}
服務端推送訊息
transaction(即時交易推送)
當監聽地址產生鏈上交易時,服務端主動推送:
{
"id": "msg-tx-uuid-001",
"time": 1745000000000,
"type": "transaction",
"code": 0,
"data": {
"chain_type": "ethereum",
"chain_id": 1,
"height": 21000000,
"txTime": 1745000000000,
"txhash": "0xabc123...",
"sender": "0x1234...",
"fee_payer": "0x1234...",
"receiver": "0x5678...",
"transfer_type": "native",
"gasLimit": "21000",
"gasUsed": "21000",
"gasPrice": "20000000000",
"max_fee_per_gas": "30000000000",
"max_priority_fee_per_gas": "1000000000",
"txFee": "420000000000000",
"nonce": "42",
"symbol": "ETH",
"decimals": 18,
"amount": "1000000000000000000",
"txStatus": "success",
"methodId": "",
"methodCall": "",
"fromDetails": [],
"toDetails": [],
"internalTransactionDetails": null,
"tokenTransferDetails": null,
"listenAddress": ["0x1234..."],
"is_reorg_resend": false
},
"msg": "success"
}
交易訊息關鍵欄位說明:
| 欄位 | 類型 | 說明 |
|---|---|---|
data.listenAddress | string[] | 命中監聽規則的地址列表,一筆交易可能命中多個地址 |
data.is_reorg_resend | boolean | 是否為鏈重組後的重發訊息,true 時需檢查本地記錄 |
data.tokenTransferDetails | array | null | 代幣轉帳明細列表,ERC-20 轉帳時包含具體轉帳資訊 |
data.txTime | integer | 交易時間戳,毫秒級 |
is_reorg_resend 說明:
當值為 true 時,表示此交易因**鏈重組(Reorg)**被重新推送。建議檢查本地是否已存在該 txhash 的記錄,並根據需要更新區塊高度等資訊。
ERC-20 代幣轉帳訊息範例:
{
"id": "msg-tx-002",
"type": "transaction",
"code": 0,
"data": {
"chain_type": "ethereum",
"txhash": "0xdef456...",
"transfer_type": "token",
"tokenTransferDetails": [
{
"from": "0x1234...",
"to": "0x5678...",
"isFromContract": false,
"isToContract": false,
"tokenContractAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"symbol": "USDT",
"amount": "1000000000",
"decimals": 6,
"fromTokenAddress": "",
"toTokenAddress": "",
"mint": "",
"programId": ""
}
],
"listenAddress": ["0x1234..."],
"is_reorg_resend": false
},
"msg": "success"
}
HTTP 輔助介面
WebSocket 連線狀態查詢
介面路徑:GET /tx/api/v1/transaction/ws/status
查詢指定應用的 WebSocket 連線狀態。
curl "$BASE_URL/tx/api/v1/transaction/ws/status" \
-H "X-API-Key: your-api-key"
呼叫方身分由 X-API-Key 識別;公網接入不需要額外傳入應用標識查詢參數。
回應:
{
"code": 0,
"message": "ok",
"data": {
"appId": "current-business-identity",
"connectedClients": 2,
"clients": ["client-abc123", "client-def456"],
"details": [
{
"clientId": "client-abc123",
"connectedAt": 1745000000000,
"uptime": 3600,
"pendingTxCount": 0
}
]
}
}
| 欄位 | 類型 | 說明 |
|---|---|---|
connectedClients | integer | 目前在線客戶端數量 |
details[].uptime | integer | 已存活秒數 |
details[].pendingTxCount | integer | 尚未收到 ACK 的待確認交易數量 |
WebSocket 訊息重放
介面路徑:POST /tx/api/v1/transaction/ws/replay
手動重放一筆漏發的交易訊息。服務端會:
- 將訊息冪等寫入資料庫
- 推送給目前在線的 WebSocket 訂閱者
- 並行觸發 Webhook 回呼
請求體為一筆完整的 WsTransactionMessage 格式訊息(與服務端推送的 transaction 訊息格式相同)。
回應:
{
"code": 0,
"message": "ok",
"data": {
"processed": true,
"txhash": "0xabc123..."
}
}
錯誤處理
WebSocket 命令的錯誤以相同的 JSON 格式透過 WebSocket 訊息返回,code 欄位為非 0:
{
"id": "原始命令的 id",
"type": "命令类型",
"code": 400,
"data": null,
"msg": "錯誤描述"
}
常見錯誤彙總:
| 命令 | code | msg |
|---|---|---|
subscribe | 400 | address and chain_type required |
unsubscribe | 400 | address required |
getTxHash | 400 | chain_type, chain_id, txHash required |
getTxHash | 404 | transaction not found |
transactionACK | 400 | chain_type and messageId/txHash required |
最佳實務
心跳保活
建議每 30 秒傳送一次 ping 命令:
setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ id: `ping-${Date.now()}`, type: 'ping', data: {} }));
}
}, 30000);
斷線重連
function connect() {
const ws = new WebSocket(WS_URL, { headers: { 'X-API-Key': API_KEY } });
ws.on('close', () => {
console.log('连接断开,5 秒后重连...');
setTimeout(connect, 5000);
});
return ws;
}
ACK 策略
- 及時 ACK:收到
transaction訊息並完成業務處理後,立即傳送transactionACK - 避免漏 ACK:如果業務處理耗時較長,可先 ACK 再非同步處理
- ACK 去重:業務層應以
txhash + chain_type + chain_id為唯一鍵做冪等處理
地址訂閱策略
| 方式 | 持久性 | 適用場景 |
|---|---|---|
HTTP 地址管理(/tx/api/v1/addresses) | 持久,重啟後有效 | 常規業務地址的長期監聽 |
WebSocket subscribe 命令 | 臨時,僅目前連線有效 | 臨時偵錯或動態細粒度控制 |
並發連線
同一個 API Key 對應的業務身分支援多個客戶端同時連線,服務端會向所有在線連線廣播交易訊息。適用於多實例水平擴展或主備切換場景(需業務層做冪等處理)。