Helius 独有功能 - getTransactionsForAddress 仅通过 Helius RPC 节点提供,并不属于标准 Solana RPC。此端点需要开发者计划或更高版本,并且每次请求费用为 100 点数。返回 100 个完整交易或 1,000 个签名。
getTransactionsForAddress 提供强大的交易历史查询功能,具有高级过滤、灵活排序和高效分页。
主要功能
灵活排序
按时间顺序排序(最早优先)或倒序(最新优先)
常见用例
此方法在多个场景中特别有用。代币发行分析有助于跟踪新项目的首次铸币交易和早期代币持有者。钱包资金历史允许您识别特定地址的资金来源和交易模式。交易分析让您可以按成功/失败状态进行过滤,专注于已完成的交易并排除失败的尝试。
该 API 还支持 审计与合规 工作流,通过状态过滤为特定时间段生成交易报告。分析仪表板可以利用历史重播功能构建全面的交易分析。最后,投资组合跟踪应用程序可以访问完整的成功交易历史,用于 DeFi 投资组合管理。
关联代币账户
在 Solana 上,您的钱包实际上并不直接持有代币。相反,您的钱包拥有代币账户,这些代币账户持有您的代币。
当有人向您发送 USDC 时,它会进入您的 USDC 代币账户,而不是您的主钱包地址。
此方法独特之处在于它允许您查询完整的代币历史。您可以查询钱包的完整历史,包括关联代币地址 (ATA)。
本地 RPC 方法如 getSignaturesForAddress 不包括 ATA。
tokenAccounts 过滤器让您可以控制此行为:
none(默认):仅返回直接引用钱包地址的交易。当您只关心直接的钱包交互时使用。
balanceChanged(推荐):返回引用钱包地址或修改钱包拥有的代币账户余额的交易。这将过滤掉垃圾邮件和不相关的操作,如费用收取或委托,提供关于钱包活动的清晰视图。
all:返回引用钱包地址或任何钱包拥有的代币账户的所有交易。
网络支持
| 网络 | 支持 | 保留期 |
|---|
| Mainnet | 是 | 无限 |
| Devnet | 是 | 2周 |
| Testnet | 否 | 不适用 |
快速开始
使用高级功能查询
获取在两个日期之间钱包的所有成功交易,按时间顺序排序:// Get successful transactions between Jan 1-31, 2025 in chronological order
const response = await fetch('https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'getTransactionsForAddress',
params: [
'YOUR_ADDRESS_HERE',
{
transactionDetails: 'full',
sortOrder: 'asc',
limit: 100,
filters: {
blockTime: {
gte: 1735689600, // Jan 1, 2025
lte: 1738368000 // Jan 31, 2025
},
status: 'succeeded', // Only successful transactions
tokenAccounts: 'balanceChanged' // Include associated token accounts
}
}
]
})
});
const data = await response.json();
console.log('Successful transactions in January:', data.result.data);
了解参数
此示例展示了关键功能:
- transactionDetails: 设置为
'full' 以在一次调用中获取完整的交易数据
- sortOrder: 使用
'asc' 以时间顺序排列(最旧的优先)或 'desc' 以最新的优先
- filters.blockTime: 使用
gte (大于或等于)和 lte (小于或等于)设置时间范围
- filters.status: 仅过滤到
'succeeded' 或 'failed' 交易
- filters.tokenAccounts: 包括关联的代币账户的转账、铸造和销毁
请求参数
要查询交易历史的账户的 Base-58 编码的公钥
要返回的交易详细级别:
signatures: 基本签名信息(更快)
full: 完整的交易数据(消除对 getTransaction 调用的需求,限制 ≤ 100)
结果的排序顺序:
desc: 最新的优先(默认)
asc: 最旧的优先(时间顺序,很适合历史分析)
返回的最大交易数:
- 当
transactionDetails: "signatures" 时最多 1000
- 当
transactionDetails: "full" 时最多100
从前一个响应中获取分页令牌(格式:"slot:position")
承诺等级:finalized 或 confirmed。不支持 processed 承诺。
使用比较运算符按槽位号过滤:gte, gt, lte, lt示例:{ "slot": { "gte": 1000, "lte": 2000 } }
使用比较运算符按 Unix 时间戳过滤:gte, gt, lte, lt, eq示例:{ "blockTime": { "gte": 1640995200, "lte": 1641081600 } }
使用比较运算符按交易签名过滤:gte, gt, lte, lt示例:{ "signature": { "lt": "SIGNATURE_STRING" } }
按交易成功/失败状态过滤:
succeeded: 仅成功的交易
failed: 仅失败的交易
any: 成功和失败的交易(默认)
示例:{ "status": "succeeded" }
为相关代币账户过滤交易:
none: 仅返回引用提供地址的交易(默认)
balanceChanged: 返回引用提供地址或修改由提供地址拥有的代币账户余额的交易(推荐)
all: 返回引用提供地址或任何由提供地址拥有的代币账户的交易
示例:{ "tokenAccounts": "balanceChanged" }
用于交易数据的编码格式(仅适用于 transactionDetails: "full")。与 getTransaction API 相同。选项:json, jsonParsed, base64, base58
maxSupportedTransactionVersion
设置返回的最高交易版本。如果省略,则只返回旧版交易。设置为0以包含所有版本的交易。
过滤器
使用过滤器时,可以对slot, blockTime, 或 signature使用比较运算符,还可以使用特殊的status 和 tokenAccounts 过滤器。
比较运算符
这些运算符的工作方式类似于数据库查询,为您的数据范围提供精确控制。
| 运算符 | 全称 | 描述 | 示例 |
|---|
gte | 大于或等于 | 包括大于或等于指定值的值 | slot: { gte: 100 } |
gt | 大于 | 包括大于指定值的值 | blockTime: { gt: 1641081600 } |
lte | 小于或等于 | 包括小于或等于指定值的值 | slot: { lte: 2000 } |
lt | 小于 | 包括小于指定值的值 | blockTime: { lt: 1641168000 } |
eq | 等于 | 包括与指定值完全相等的值(仅blockTime) | blockTime: { eq: 1641081600 } |
枚举过滤器
| 过滤器 | 描述 | 值 |
|---|
status | 按成功/失败过滤交易 | succeeded, failed, 或 any |
tokenAccounts | 过滤相关代币账户的交易 | none, balanceChanged, 或 all |
组合过滤器示例:
// Time range with successful transactions only
"filters": {
"blockTime": {
"gte": 1640995200,
"lte": 1641081600
},
"status": "succeeded"
}
// Slot range
"filters": {
"slot": {
"gte": 1000,
"lte": 2000
}
}
// Only failed transactions
"filters": {
"status": "failed"
}
响应格式
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"data": [
{
"signature": "5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv",
"slot": 1054,
"transactionIndex": 42,
"err": null,
"memo": null,
"blockTime": 1641038400,
"confirmationStatus": "finalized"
}
],
"paginationToken": "1055:5"
}
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"data": [
{
"slot": 1054,
"transactionIndex": 42,
"blockTime": 1641038400,
"transaction": {
"signatures": ["5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv"],
"message": {
"accountKeys": ["...", "..."],
"instructions": ["..."]
}
},
"meta": {
"fee": 5000,
"preBalances": [1000000, 2000000],
"postBalances": [999995000, 2000000]
}
}
],
"paginationToken": "1055:5"
}
}
响应字段
| 字段 | 类型 | 描述 |
|---|
signature | 字符串 | 交易签名(base-58 编码)。仅在签名模式中。 |
slot | 数字 | 包含此交易的块的插槽。 |
transactionIndex | 数字 | 块中交易的从零开始的索引。对于交易排序和块重构很有用。 |
blockTime | 数字 | 空 | 估计的生成时间,以 Unix 时间戳表示(自纪元以来的秒数)。 |
err | 对象 | 空 | 如果交易失败则显示错误,成功则为空。仅在签名模式中。 |
memo | 字符串 | 空 | 与交易相关的备忘录。仅在签名模式中。 |
confirmationStatus | 字符串 | 交易的集群确认状态。仅在签名模式中。 |
transaction | 对象 | 全部交易数据。仅在完整模式中。 |
meta | 对象 | 交易状态元数据。仅在完整模式中。 |
paginationToken | 字符串 | 空 | 用于获取下一页的数据,或者为空如果没有更多结果。 |
transactionIndex 字段是 getTransactionsForAddress 独有的。其他类似的端点如 getSignaturesForAddress、getTransaction 和 getTransactions 不包含此字段。
实用示例
基于时间的分析
生成月度交易报告:
// Get all successful transactions for January 2025
const startTime = Math.floor(new Date('2025-01-01').getTime() / 1000);
const endTime = Math.floor(new Date('2025-02-01').getTime() / 1000);
{
"jsonrpc": "2.0",
"id": 1,
"method": "getTransactionsForAddress",
"params": [
"WALLET_OR_PROGRAM_ADDRESS",
{
"transactionDetails": "signatures",
"filters": {
"blockTime": {
"gte": startTime,
"lt": endTime
},
"status": "succeeded"
},
"limit": 1000
}
]
}
分析流程:
// Calculate daily transaction volume
const dailyStats = {};
response.result.data.forEach(tx => {
const date = new Date(tx.blockTime * 1000).toISOString().split('T')[0];
dailyStats[date] = (dailyStats[date] || 0) + 1;
});
console.log('Daily Transaction Counts:', dailyStats);
代币铸造创建
找到特定代币的铸造创建交易:
{
"jsonrpc": "2.0",
"id": "find-first-mints",
"method": "getTransactionsForAddress",
"params": [
MINT_ADDRESS, // Token mint address
{
"encoding": "jsonParsed",
"maxSupportedTransactionVersion": 0,
"sortOrder": "asc", // Chronological order from the beginning
"limit": 10,
"transactionDetails": "full"
}
]
}
对于流动性池创建,查询池地址:
{
"jsonrpc": "2.0",
"id": 1,
"method": "getTransactionsForAddress",
"params": [
"POOL_ADDRESS_HERE", // Raydium/Meteora pool address
{
"transactionDetails": "full",
"sortOrder": "asc", // First transaction is usually pool creation
"limit": 1
}
]
}
用例:找到代币铸造或流动性池创建的确切时刻,包括创建者地址和初始参数。
资金交易
找出谁为特定地址提供资金:
{
"jsonrpc": "2.0",
"id": 1,
"method": "getTransactionsForAddress",
"params": [
"TARGET_WALLET_ADDRESS",
{
"transactionDetails": "full",
"sortOrder": "asc", // Oldest first
"limit": 10
}
]
}
然后分析交易数据以找到 SOL 转账:
response.result.data.forEach(tx => {
// Look for SOL transfers in preBalances/postBalances
const balanceChanges = tx.meta.preBalances.map((pre, index) =>
tx.meta.postBalances[index] - pre
);
// Positive balance change = incoming SOL
balanceChanges.forEach((change, index) => {
if (change > 0) {
console.log(`Received ${change} lamports from ${tx.transaction.message.accountKeys[index]}`);
}
});
});
最初的几笔交易通常会揭示资金来源,并帮助识别相关地址或资金模式。
当交易数量超过限制时,使用响应中的 paginationToken 获取下一页。该令牌是一个简单的字符串,格式为 "slot:position",用于告知 API 从哪里继续。
如何分页
使用每个响应中的分页令牌获取下一页:
// First request
let paginationToken = null;
let allTransactions = [];
const getNextPage = async (paginationToken = null) => {
const params = [
'ADDRESS',
{
transactionDetails: 'signatures',
limit: 100,
...(paginationToken && { paginationToken })
}
];
const response = await fetch(rpcUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'getTransactionsForAddress',
params
})
});
const data = await response.json();
return data.result;
};
// Paginate through all results
do {
const result = await getNextPage(paginationToken);
allTransactions.push(...result.data);
paginationToken = result.paginationToken;
console.log(`Fetched ${result.data.length} transactions, total: ${allTransactions.length}`);
} while (paginationToken);
多个地址
您无法在单个请求中查询多个地址。要获取多个地址的交易,请在相同时间或槽窗口中查询每个地址,然后合并和排序:
const addresses = ['Address1...', 'Address2...', 'Address3...'];
// Query all addresses in parallel with slot filter
const results = await Promise.all(
addresses.map(address =>
fetch(rpcUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'getTransactionsForAddress',
params: [address, {
sortOrder: 'desc',
filters: { slot: { gt: 250000000 } }
}]
})
}).then(r => r.json())
)
);
// Merge and sort by slot
const allTransactions = results
.flatMap(r => r.result.data)
.sort((a, b) => b.slot - a.slot);
对于较大的历史扫描,请通过时间或槽窗口进行迭代(例如,一次处理1000个槽),并重复此模式。
每个地址查询计为单独的API请求(每个地址100个积分)。
在需要稍后恢复大型查询时存储分页键。监控分页深度以进行性能规划,并在需要按时间顺序重放历史事件的情况下使用升序。
最佳实践
为了获得最佳性能,当不需要完整的交易数据时,使用 transactionDetails: "signatures"。实现合理的页面大小以获得更好的响应时间,并考虑按时间范围或特定槽进行筛选以实现更有针对性的查询。
从广泛的筛选器开始,然后逐步缩小范围以找到所需数据。使用基于时间的筛选器进行分析和报告工作流。您可以结合多个筛选器进行精确查询,以定位特定的交易类型或时间段。
当您需要稍后恢复大型查询时,存储分页键。监视分页深度以进行性能规划,并在需要按时间顺序重放历史事件的情况下使用升序。
错误处理
通过指数退避策略优雅地处理速率限制。在发出请求之前始终验证地址,并在适当时缓存结果以减少API使用并提高应用程序性能。
这与getSignaturesForAddress有何不同?
如果您熟悉标准的 getSignaturesForAddress 方法,以下是主要区别:
一次调用获取完整交易
使用 getSignaturesForAddress,您需要两个步骤:
// Step 1: Get signatures
const signatures = await connection.getSignaturesForAddress(address, { limit: 100 });
// Step 2: Get transaction details (100 additional calls!)
const transactions = await Promise.all(
signatures.map(sig => connection.getTransaction(sig.signature))
);
使用 getTransactionsForAddress,只需一次调用:
const response = await fetch(heliusRpcUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'getTransactionsForAddress',
params: [
address,
{
transactionDetails: 'full',
limit: 100
}
]
})
});
一次性获取令牌历史
使用getSignaturesForAddress,您需要首先调用getTokenAccountsByOwner,然后查询每个代币账户:
// OLD WAY (with getSignaturesForAddress)
// Step 1: Get all token accounts owned by this wallet
const tokenAccounts = await connection.getTokenAccountsByOwner(
new PublicKey(walletAddress),
{ programId: TOKEN_PROGRAM_ID }
);
// Step 2: Fetch signatures for the wallet itself
const walletSignatures = await connection.getSignaturesForAddress(
new PublicKey(walletAddress),
{ limit: 1000 }
);
// Step 3: Fetch signatures for EVERY token account (this is the painful part)
const tokenAccountSignatures = await Promise.all(
tokenAccounts.value.map(async (account) => {
return connection.getSignaturesForAddress(
account.pubkey,
{ limit: 1000 }
);
})
);
// Step 4: Merge all results together
const allSignatures = [
...walletSignatures,
...tokenAccountSignatures.flat()
];
// Step 5: Deduplicate (many transactions touch multiple accounts)
const seen = new Set();
const uniqueSignatures = allSignatures.filter((sig) => {
if (seen.has(sig.signature)) {
return false;
}
seen.add(sig.signature);
return true;
});
// Step 6: Sort chronologically
const sortedSignatures = uniqueSignatures.sort(
(a, b) => a.slot - b.slot
);
return sortedSignatures;
使用getTransactionsForAddress,您只需要设置filters.tokenAccounts:
// NEW WAY (with getTransactionsForAddress)
const response = await fetch("https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: "helius-example",
method: "getTransactionsForAddress",
params: [
walletAddress,
{
filters: {
tokenAccounts: "all"
}
sortOrder: "asc",
limit: 100
}
]
})
});
const { result } = await response.json();
return result;
额外功能
按时间排序
使用sortOrder: 'asc'从最旧到最新排序交易
基于时间的过滤
使用blockTime过滤器按照时间范围进行过滤
状态过滤
使用status过滤器只获取成功或失败的交易
更简单的分页
使用paginationToken而不是复杂的before/until签名
支持与社区