测试版 :钱包API目前处于测试阶段。API和响应格式可能会更改。
交易历史端点使用增强交易API检索Solana钱包的完整交易历史。返回人类可读的解析交易以及每笔交易的余额变化。分页是手动的 - API每次请求最多返回100笔交易。
按时间逆序返回交易(最新的在前)。
关联的代币账户(ATAs): tokenAccounts 参数控制是否包含涉及钱包拥有的代币账户的交易:
balanceChanged(推荐):包含更改代币账户余额的交易,过滤垃圾信息
none:仅直接钱包交互
all:所有代币账户交易,包括垃圾信息
旧交易的限制 :tokenAccounts 过滤器依赖于代币余额元数据中的 owner 字段,该字段在插槽111,491,819(约2022年12月)之前不可用。在此插槽之前活跃的代币账户交易可能会丢失。请参阅getTransactionsForAddress教程 以获取解决方法。
分页: 使用 before 参数与 pagination.nextCursor 一起获取下一页。响应包括 pagination.hasMore 以指示是否有更多结果。每次请求进行一次API调用,费用为100个积分。
何时使用此功能
当您需要时使用交易历史API:
显示交易记录 :向用户展示他们的完整交易历史
计算盈亏 :跟踪所有交易的收益和损失
税务与会计 :生成完整的交易报告用于报税
投资组合分析 :分析交易模式和活动
审计追踪 :维护钱包活动的完整记录
余额重建 :从历史数据中重建当前余额
快速开始
基本历史查询
获取最新的余额变动交易:
const getTransactionHistory = async ( address ) => {
const url = `https://api.helius.xyz/v1/wallet/ ${ address } /history?api-key=YOUR_API_KEY` ;
const response = await fetch ( url );
if ( ! response . ok ) {
throw new Error ( `HTTP error! status: ${ response . status } ` );
}
const data = await response . json ();
console . log ( `Found ${ data . data . length } transactions` );
// Display recent transactions
data . data . forEach ( tx => {
const date = new Date ( tx . timestamp * 1000 ). toLocaleString ();
const status = tx . error ? 'Failed' : 'Success' ;
console . log ( ` \n ${ status } - ${ date } ` );
console . log ( `Signature: ${ tx . signature . slice ( 0 , 20 ) } ...` );
console . log ( `Fee: ${ tx . fee } SOL` );
// Show balance changes
tx . balanceChanges . forEach ( change => {
const sign = change . amount > 0 ? '+' : '' ;
console . log ( ` ${ sign }${ change . amount } ${ change . mint === 'SOL' ? 'SOL' : change . mint . slice ( 0 , 8 ) } ...` );
});
});
return data ;
};
getTransactionHistory ( "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY" );
import requests
from datetime import datetime
def get_transaction_history ( address : str ):
url = f "https://api.helius.xyz/v1/wallet/ { address } /history"
headers = { "X-Api-Key" : "YOUR_API_KEY" }
response = requests.get(url, headers = headers)
response.raise_for_status()
data = response.json()
print ( f "Found { len (data[ 'data' ]) } transactions" )
# Display recent transactions
for tx in data[ 'data' ]:
date = datetime.fromtimestamp(tx[ 'timestamp' ]).strftime( '%Y-%m- %d %H:%M:%S' )
status = 'Failed' if tx.get( 'error' ) else 'Success'
print ( f " \n { status } - { date } " )
print ( f "Signature: { tx[ 'signature' ][: 20 ] } ..." )
print ( f "Fee: { tx[ 'fee' ] } SOL" )
# Show balance changes
for change in tx[ 'balanceChanges' ]:
sign = '+' if change[ 'amount' ] > 0 else ''
mint_display = 'SOL' if change[ 'mint' ] == 'SOL' else change[ 'mint' ][: 8 ] + '...'
print ( f " { sign }{ change[ 'amount' ] } { mint_display } " )
return data
get_transaction_history( "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY" )
curl "https://api.helius.xyz/v1/wallet/86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY/history?api-key=YOUR_API_KEY"
完整历史的分页
使用分页和参数 before 获取所有交易:
const getAllTransactionHistory = async ( address ) => {
let allTransactions = [];
let before = null ;
do {
const url = before
? `https://api.helius.xyz/v1/wallet/ ${ address } /history?api-key=YOUR_API_KEY&before= ${ before } `
: `https://api.helius.xyz/v1/wallet/ ${ address } /history?api-key=YOUR_API_KEY` ;
const response = await fetch ( url );
const data = await response . json ();
allTransactions = allTransactions . concat ( data . data );
before = data . pagination . hasMore ? data . pagination . nextCursor : null ;
console . log ( `Fetched ${ allTransactions . length } transactions so far...` );
} while ( before );
console . log ( ` \n Total transactions: ${ allTransactions . length } ` );
return allTransactions ;
};
getAllTransactionHistory ( "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY" );
def get_all_transaction_history ( address : str ):
all_transactions = []
before = None
while True :
url = f "https://api.helius.xyz/v1/wallet/ { address } /history"
params = { "api-key" : "YOUR_API_KEY" }
if before:
params[ "before" ] = before
response = requests.get(url, params = params, headers = { "X-Api-Key" : "YOUR_API_KEY" })
response.raise_for_status()
data = response.json()
all_transactions.extend(data[ 'data' ])
print ( f "Fetched { len (all_transactions) } transactions so far..." )
if not data[ 'pagination' ][ 'hasMore' ]:
break
before = data[ 'pagination' ][ 'nextCursor' ]
print ( f " \n Total transactions: { len (all_transactions) } " )
return all_transactions
get_all_transaction_history( "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY" )
查询参数
参数 类型 默认值 描述 limitinteger 100 每次请求的最大交易数(1-100) beforestring - 获取此签名之前的交易(使用上次响应中的 pagination.nextCursor) afterstring - 获取此签名之后的交易(用于升序分页) typestring - 按交易类型过滤(例如,SWAP, TRANSFER, NFT_SALE, TOKEN_MINT) tokenAccountsstring balanceChanged 过滤涉及代币账户的交易:none, balanceChanged(推荐)或 all
可用交易类型
参数 type 支持按以下交易类型过滤:
SWAP, TRANSFER, NFT_SALE, NFT_BID, NFT_LISTING, NFT_MINT, NFT_CANCEL_LISTING, TOKEN_MINT, BURN, COMPRESSED_NFT_MINT, COMPRESSED_NFT_TRANSFER, COMPRESSED_NFT_BURN, CREATE_STORE, WHITELIST_CREATOR, ADD_TO_WHITELIST, REMOVE_FROM_WHITELIST, AUCTION_MANAGER_CLAIM_BID, EMPTY_PAYMENT_ACCOUNT, UPDATE_PRIMARY_SALE_METADATA, ADD_TOKEN_TO_VAULT, ACTIVATE_VAULT, INIT_VAULT, INIT_BANK, INIT_STAKE, MERGE_STAKE, SPLIT_STAKE, CREATE_AUCTION_MANAGER, START_AUCTION, CREATE_AUCTION_MANAGER_V2, UPDATE_EXTERNAL_PRICE_ACCOUNT, EXECUTE_TRANSACTION
过滤器示例
// Get only SWAP transactions
const url = `https://api.helius.xyz/v1/wallet/ ${ address } /history?api-key=YOUR_API_KEY&type=SWAP` ;
// Exclude spam by only including transactions that changed token balances
const url = `https://api.helius.xyz/v1/wallet/ ${ address } /history?api-key=YOUR_API_KEY&tokenAccounts=balanceChanged` ;
// Only show direct wallet interactions
const url = `https://api.helius.xyz/v1/wallet/ ${ address } /history?api-key=YOUR_API_KEY&tokenAccounts=none` ;
// Get only NFT sales that changed balances
const url = `https://api.helius.xyz/v1/wallet/ ${ address } /history?api-key=YOUR_API_KEY&type=NFT_SALE&tokenAccounts=balanceChanged` ;
响应格式
{
"data" : [
{
"signature" : "5wHu1qwD7Jsj3xqWjdSEJmYr3Q5f5RjXqjqQJ7jqEj7jqEj7jqEj7jqEj7jqEj7jqE" ,
"timestamp" : 1704067200 ,
"slot" : 250000000 ,
"fee" : 0.000005 ,
"feePayer" : "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY" ,
"error" : null ,
"balanceChanges" : [
{
"mint" : "So11111111111111111111111111111111111111112" ,
"amount" : -0.05 ,
"decimals" : 9
},
{
"mint" : "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" ,
"amount" : 50.0 ,
"decimals" : 6
}
]
}
],
"pagination" : {
"hasMore" : true ,
"nextCursor" : "5wHu1qwD7Jsj3xqWjdSEJmYr3Q5f5RjXqjqQJ7jqEj7jqEj7jqEj7jqEj7jqEj7jqE"
}
}
对于尚未完全处理的最新交易,timestamp 字段可能是 null。
计算总交易量
汇总所有转账以获取交易量:
const calculateTradingVolume = async ( address , tokenMint ) => {
const transactions = await getAllTransactionHistory ( address );
let totalVolume = 0 ;
transactions . forEach ( tx => {
tx . balanceChanges . forEach ( change => {
if ( change . mint === tokenMint ) {
totalVolume += Math . abs ( change . amount );
}
});
});
console . log ( `Total ${ tokenMint } volume: ${ totalVolume } ` );
return totalVolume ;
};
// Example: Calculate total USDC volume
calculateTradingVolume (
"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY" ,
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" // USDC
);
生成税务报告
创建税务申报的交易报告:
const generateTaxReport = async ( address , year ) => {
const transactions = await getAllTransactionHistory ( address );
const startDate = new Date ( ` ${ year } -01-01` ). getTime () / 1000 ;
// Set to end of December 31st (23:59:59.999) to include all transactions from that day
const endDate = new Date ( ` ${ year } -12-31T23:59:59.999Z` ). getTime () / 1000 ;
const taxableTransactions = transactions
. filter ( tx => tx . timestamp >= startDate && tx . timestamp <= endDate )
. map ( tx => ({
date: new Date ( tx . timestamp * 1000 ). toISOString (),
signature: tx . signature ,
fee: tx . fee ,
balanceChanges: tx . balanceChanges ,
explorerUrl: `https://orbmarkets.io/tx/ ${ tx . signature } `
}));
console . log ( `Found ${ taxableTransactions . length } transactions in ${ year } ` );
// Export as JSON
const report = {
address ,
year ,
transactionCount: taxableTransactions . length ,
transactions: taxableTransactions
};
console . log ( JSON . stringify ( report , null , 2 ));
return report ;
};
generateTaxReport ( "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY" , 2024 );
跟踪失败的交易
查找所有失败的交易以了解错误:
const getFailedTransactions = async ( address ) => {
const data = await getTransactionHistory ( address );
const failed = data . data . filter ( tx => tx . error !== null );
console . log ( `Found ${ failed . length } failed transactions` );
failed . forEach ( tx => {
const date = new Date ( tx . timestamp * 1000 ). toLocaleString ();
console . log ( ` \n ${ date } ` );
console . log ( `Signature: ${ tx . signature } ` );
console . log ( `Error: ${ tx . error } ` );
console . log ( `Fee Paid: ${ tx . fee } SOL` );
});
return failed ;
};
重建历史余额
计算特定时间点的余额:
const getHistoricalBalance = async ( address , targetTimestamp ) => {
const transactions = await getAllTransactionHistory ( address );
// Filter to transactions before target date
const relevantTxs = transactions . filter ( tx => tx . timestamp <= targetTimestamp );
// Sum all balance changes
const balances = {};
relevantTxs . forEach ( tx => {
tx . balanceChanges . forEach ( change => {
if ( ! balances [ change . mint ]) {
balances [ change . mint ] = 0 ;
}
balances [ change . mint ] += change . amount ;
});
});
console . log ( `Historical balances as of ${ new Date ( targetTimestamp * 1000 ). toLocaleString () } :` );
Object . entries ( balances ). forEach (([ mint , balance ]) => {
console . log ( ` ${ mint } : ${ balance } ` );
});
return balances ;
};
// Example: Get balances on Jan 1, 2024
getHistoricalBalance (
"86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY" ,
new Date ( "2024-01-01" ). getTime () / 1000
);
分析交易费用
计算支付的总费用:
const analyzeFees = async ( address ) => {
const transactions = await getAllTransactionHistory ( address );
const totalFees = transactions . reduce (( sum , tx ) => sum + tx . fee , 0 );
const avgFee = totalFees / transactions . length ;
const successfulTxs = transactions . filter ( tx => ! tx . error );
const failedTxs = transactions . filter ( tx => tx . error );
const wastedFees = failedTxs . reduce (( sum , tx ) => sum + tx . fee , 0 );
console . log ( `Total Transactions: ${ transactions . length } ` );
console . log ( `Successful: ${ successfulTxs . length } ` );
console . log ( `Failed: ${ failedTxs . length } ` );
console . log ( `Total Fees Paid: ${ totalFees . toFixed ( 6 ) } SOL` );
console . log ( `Average Fee: ${ avgFee . toFixed ( 6 ) } SOL` );
console . log ( `Wasted on Failed Txs: ${ wastedFees . toFixed ( 6 ) } SOL` );
return {
totalFees ,
avgFee ,
wastedFees ,
successRate: ( successfulTxs . length / transactions . length ) * 100
};
};
理解余额变化
每笔交易包括一个数组 balanceChanges,显示钱包持有量的变化:
正数金额 (+):收到的代币
负数金额 (-):发送或消费的代币
mint 字段 :代币铸币地址(或本地 SOL 使用 "SOL")
decimals 字段 :代币的小数位数
所有 amount 值在 balanceChanges 中是可读的 —— 已经被 decimals 分割。例如,-0.05 意味着 −0.05 SOL,而不是 −0.05 lamports。此端点不包括原始 amountRaw 字段。
示例余额变动
// Swap: Sold 0.05 SOL, received 5 USDC
{
"balanceChanges" : [
{ "mint" : "SOL" , "amount" : - 0.05 , "decimals" : 9 },
{ "mint" : "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" , "amount" : 5.0 , "decimals" : 6 }
]
}
// Simple transfer: Sent 10 USDC
{
"balanceChanges" : [
{ "mint" : "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" , "amount" : - 10.0 , "decimals" : 6 }
]
}
最佳实践
在获取完整的交易历史时,始终实施分页。一些钱包有数十万笔交易。
历史交易从未改变。在本地缓存它们,仅获取新交易。
检查 error 字段区分成功和失败的交易。失败的交易仍然会产生费用。
时间戳为 Unix 秒。转换为本地日期以便显示和筛选。
常见错误
错误代码 描述 解决方案 400 无效的钱包地址格式 验证地址是否为有效的 base58 Solana 地址 401 缺少或无效的 API 密钥 确保在请求中包含 API 密钥 429 超出速率限制 减少请求频率或升级您的计划
需要帮助?
API 参考 查看详细的 API 规范和请求/响应架构