测试版 :钱包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 字段 :代币的小数位数
示例余额变化
// 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 超出速率限制 减少请求频率或升级您的计划
需要帮助?