getTransactionsForAddress 将交易签名查找和完整交易检索合并为一次高效调用。无需分别请求 getSignaturesForAddress 然后对每个签名调用 getTransaction,您可以在单次请求中获得所有内容。
此方法支持:
- 双向排序(最旧优先或最新优先)
- 基于时间和 slot 的过滤
- 交易状态过滤(成功/失败)
- 代币账户过滤
- 基于游标的分页
为什么使用此方法
N+1 问题
使用标准 Solana RPC 方法获取交易历史需要多次调用:
- 调用
getSignaturesForAddress 获取交易签名列表
- 对每个签名调用
getTransaction 获取完整交易数据
对于有 100 笔交易的钱包,这意味着 101 次 API 调用。对于 1,000 笔交易,则是 1,001 次调用。这会造成延迟、复杂性和更高的成本。
getTransactionsForAddress 通过单次调用返回完整交易数据解决了这个问题——每次请求最多 100 笔完整交易或 1,000 个签名。
附加功能
除了效率之外,此方法还提供标准 RPC 中不可用的功能:
- 双向排序:以最旧优先(
asc)查询,从第一笔交易开始追溯地址
- 基于时间的过滤:检索特定日期范围内的交易
- 基于 slot 的过滤:查询特定区块范围的交易
- 状态过滤:仅获取成功或仅获取失败的交易
- 代币账户包含:捕获关联代币账户的交易
代币账户支持
标准 getSignaturesForAddress 仅返回直接引用查询地址的交易。这会遗漏一个重要类别:代币转账。
当代币被发送到钱包时,交易引用的是钱包的关联代币账户(ATA),而非钱包地址本身。这意味着标准方法给您的是不完整的画面。
带有 tokenAccounts: "all" 的 getTransactionsForAddress 自动包含该地址拥有的所有代币账户的交易,为您提供完整的交易历史。
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getTransactionsForAddress",
"params": [
"WALLET_ADDRESS",
{
"filters": {
"tokenAccounts": "all"
}
}
]
}'
如果您只想获取直接引用该地址的交易,请设置 tokenAccounts: "none"。
要查询的 Solana 地址(base-58 编码的公钥)
查询的确认级别:
"finalized" - 仅查询最终确认的区块(默认)
"confirmed" - 查询已确认的区块
注意:此方法不支持 "processed"。 返回的详细级别:
"signatures" - 仅返回签名(最多 1000 个结果)
"full" - 返回完整交易数据(最多 100 个结果)
默认:"full" 返回的最大结果数。
transactionDetails: "full" 时:最大 100
transactionDetails: "signatures" 时:最大 1000
默认:100 排序方向:
"desc" - 最新交易优先(默认)
"asc" - 最旧交易优先
按代币账户关联过滤:
"all" - 包含所有代币账户的交易
"none" - 排除代币账户交易
默认:"all" 按交易状态过滤:
"success" - 仅成功的交易
"failed" - 仅失败的交易
响应格式取决于 transactionDetails 参数。
transactionDetails: "full" 时
完整交易对象数组,每个包含:
交易在区块中的位置。此字段为 getTransactionsForAddress 独有,标准 RPC 方法中不可用。
transactionDetails: "signatures" 时
代码示例
基本请求
获取地址的最新交易:
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getTransactionsForAddress",
"params": [
"ADDRESS_HERE"
]
}'
仅获取签名
检索最多 1000 个签名,不含完整交易数据:
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getTransactionsForAddress",
"params": [
"ADDRESS_HERE",
{
"transactionDetails": "signatures",
"limit": 1000
}
]
}'
最旧优先并按时间过滤
获取特定时间范围内的交易,按最旧优先排序:
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getTransactionsForAddress",
"params": [
"ADDRESS_HERE",
{
"sortOrder": "asc",
"filters": {
"afterTime": 1704067200,
"beforeTime": 1706745600
}
}
]
}'
仅成功交易
仅过滤返回成功的交易:
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getTransactionsForAddress",
"params": [
"ADDRESS_HERE",
{
"filters": {
"status": "success"
}
}
]
}'
分页请求
使用基于游标的分页获取更多结果:
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getTransactionsForAddress",
"params": [
"ADDRESS_HERE",
{
"limit": 100,
"before": "LAST_SIGNATURE_FROM_PREVIOUS_RESPONSE"
}
]
}'
TypeScript 示例
import { Connection } from '@solana/web3.js';
const connection = new Connection('https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY');
interface GetTransactionsOptions {
transactionDetails?: 'full' | 'signatures';
limit?: number;
sortOrder?: 'asc' | 'desc';
before?: string;
after?: string;
filters?: {
tokenAccounts?: 'all' | 'none';
beforeTime?: number;
afterTime?: number;
beforeSlot?: number;
afterSlot?: number;
status?: 'success' | 'failed';
};
}
async function getTransactionsForAddress(
address: string,
options: GetTransactionsOptions = {}
) {
const response = await fetch('https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'getTransactionsForAddress',
params: [address, options],
}),
});
const data = await response.json();
return data.result;
}
// Get recent transactions
const recent = await getTransactionsForAddress('ADDRESS_HERE');
// Get oldest transactions first with time filter
const historical = await getTransactionsForAddress('ADDRESS_HERE', {
sortOrder: 'asc',
filters: {
afterTime: Math.floor(Date.now() / 1000) - 86400 * 30, // Last 30 days
},
});
// Paginate through all transactions
async function getAllTransactions(address: string) {
const allTransactions = [];
let before: string | undefined;
while (true) {
const batch = await getTransactionsForAddress(address, {
limit: 100,
before,
});
if (!batch || batch.length === 0) break;
allTransactions.push(...batch);
before = batch[batch.length - 1].signature;
}
return allTransactions;
}
使用场景
代币发行分析
查找代币铸造的最早交易,以识别首批铸造者和早期持有者。使用 sortOrder: "asc" 从最早开始:
const earlyActivity = await getTransactionsForAddress(tokenMintAddress, {
sortOrder: 'asc',
limit: 100,
filters: {
tokenAccounts: 'all',
},
});
钱包资金来源历史
通过查询完整交易历史追溯钱包资金来源:
const fundingHistory = await getTransactionsForAddress(walletAddress, {
sortOrder: 'asc',
filters: {
tokenAccounts: 'all',
},
transactionDetails: 'full',
});
// First transactions often reveal funding sources
const firstTransactions = fundingHistory.slice(0, 10);
失败交易分析
通过过滤仅显示失败交易来调试交易失败:
const failedTxs = await getTransactionsForAddress(walletAddress, {
filters: {
status: 'failed',
},
transactionDetails: 'full',
});
// Analyze error logs to understand failure reasons
failedTxs.forEach(tx => {
console.log(tx.signature, tx.meta?.err, tx.meta?.logMessages);
});
构建钱包交易动态
为钱包界面创建分页交易历史:
async function getWalletFeed(wallet: string, cursor?: string) {
return getTransactionsForAddress(wallet, {
limit: 20,
before: cursor,
transactionDetails: 'full',
filters: {
tokenAccounts: 'all',
},
});
}
交易模式分析
过滤特定时间窗口内的成功交易:
const trades = await getTransactionsForAddress(traderWallet, {
filters: {
status: 'success',
afterTime: startOfMonth,
beforeTime: endOfMonth,
},
transactionDetails: 'full',
});
合规审计
为监管合规构建完整的交易历史:
async function auditAddress(address: string) {
const allTxs = await getAllTransactions(address);
return {
totalTransactions: allTxs.length,
successful: allTxs.filter(tx => !tx.err).length,
failed: allTxs.filter(tx => tx.err).length,
firstTransaction: allTxs[allTxs.length - 1],
lastTransaction: allTxs[0],
};
}
对于交易量大的地址,您需要对结果进行分页。该方法支持使用 before 和 after 参数的基于游标的分页。
获取较新的交易(默认)
使用 sortOrder: "desc"(默认),交易按最新优先返回。使用 before 获取更旧的交易:
// First request
const page1 = await getTransactionsForAddress(address, { limit: 100 });
// Get next page using last signature as cursor
const lastSignature = page1[page1.length - 1].signature;
const page2 = await getTransactionsForAddress(address, {
limit: 100,
before: lastSignature,
});
优先获取较旧的交易
使用 sortOrder: "asc",交易按最旧优先返回。使用 after 获取更新的交易:
// Get oldest transactions first
const page1 = await getTransactionsForAddress(address, {
sortOrder: 'asc',
limit: 100,
});
// Continue forward in time
const lastSignature = page1[page1.length - 1].signature;
const page2 = await getTransactionsForAddress(address, {
sortOrder: 'asc',
limit: 100,
after: lastSignature,
});
完整分页示例
获取地址的所有交易:
async function getAllTransactions(address: string) {
const allTransactions = [];
let cursor: string | undefined;
while (true) {
const batch = await getTransactionsForAddress(address, {
limit: 100,
before: cursor,
transactionDetails: 'full',
});
if (!batch || batch.length === 0) break;
allTransactions.push(...batch);
cursor = batch[batch.length - 1].signature;
// Optional: Add delay to respect rate limits
await new Promise(resolve => setTimeout(resolve, 100));
}
return allTransactions;
}
最佳实践
-
使用
signatures 模式进行计数:当您只需要计数或列出交易时,使用 transactionDetails: "signatures" 以获得更好的性能和更高的限制。
-
尽早过滤:应用时间、slot 或状态过滤器以减少返回的数据量并改善响应时间。
-
实施分页:对于交易量大的地址,始终使用
before 游标进行分页。
-
缓存结果:交易数据一旦确认就不可变。缓存历史结果以避免冗余请求。
-
处理速率限制:在进行多次连续请求时实施指数退避。
常见错误
| 代码 | 消息 | 解决方案 |
|---|
| -32600 | Invalid request | 检查 JSON-RPC 格式和必需字段 |
| -32602 | Invalid params | 验证地址格式和选项值 |
| -32005 | Request limit exceeded | 减少限制或实施速率限制 |
与标准方法的对比
| 功能 | getSignaturesForAddress + getTransaction | getTransactionsForAddress |
|---|
| API 调用次数 | 多次(1 + N) | 单次 |
| 排序 | 仅最新优先 | 双向 |
| 时间过滤 | 不支持 | 支持 |
| 状态过滤 | 不支持 | 支持 |
| 最大签名数 | 每次调用 1000 | 每次调用 1000 |
| 最大完整交易数 | 受调用次数限制 | 每次调用 100 |