> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 交易历史

> 获取任何Solana地址的人类可读交易历史，支持过滤、时间和槽位范围以及分页。

<Warning>
  增强型交易API是处于维护模式的旧版产品。它仍然有效，这些页面可供使用，但不再接收新的解析器类型或功能开发。它的继任者是[解析事件](/docs/zh/parsed-events)，通过IDL目录解码指令，现处于封闭测试阶段。您还可以使用[`getTransactionsForAddress`](/docs/zh/rpc/gettransactionsforaddress)进行交易历史和回填，使用[钱包API](/docs/zh/wallet-api/overview)获取人类可读的钱包数据。
</Warning>

## 概述

交易历史端点返回任何Solana地址的人类可读交易历史。相比处理原始指令数据和账户列表，您将获得结构化的信息：

* 交易中发生了什么（转账、交换、NFT活动）。
* 涉及了哪些账户。
* 转移了多少SOL或多少代币。
* 相关元数据（代币铸造地址、代币名称、代币符号等）。

发送一个`GET`请求到`/v0/addresses/{address}/transactions`。在底层，该端点由[`getTransactionsForAddress`](/docs/zh/rpc/gettransactionsforaddress) RPC方法支持。

## 何时使用

* 您向用户显示一个地址的交易历史（钱包、投资组合跟踪器、探索器）。
* 您希望获得无须编写解码器的人类可读历史。
* 您需要按交易类型、时间范围或槽位范围过滤历史。
* 您需要一个钱包的完整代币历史，包括关联的代币账户（ATAs）——请参见下文。

对于新构建，[`getTransactionsForAddress`](/docs/zh/rpc/gettransactionsforaddress)是现代的、Helius原生的路径，具备服务器端过滤和代币账户查询。

## 快速开始

<Steps>
  <Step title="获取您的API密钥">
    在[dashboard.helius.dev](https://dashboard.helius.dev)注册并复制您的API密钥。
  </Step>

  <Step title="获取地址交易端点">
    检索任何Solana地址的交易历史。

    <Tabs>
      <Tab title="JavaScript">
        ```javascript theme={"system"}
        const fetchWalletTransactions = async () => {
          const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K"; // Replace with target wallet
          const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY`;

          const response = await fetch(url);
          const transactions = await response.json();
          console.log("Wallet transactions:", transactions);
        };

        fetchWalletTransactions();
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={"system"}
        import requests

        def fetch_wallet_transactions():
            wallet_address = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K"  # Replace with target wallet
            url = f"https://mainnet.helius-rpc.com/v0/addresses/{wallet_address}/transactions?api-key=YOUR_API_KEY"

            response = requests.get(url)
            transactions = response.json()
            print("Wallet transactions:", transactions)

        fetch_wallet_transactions()
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="过滤和分页">
    使用下面的`type`、时间和槽位过滤器缩小结果，并通过签名光标翻页以处理高流量地址。
  </Step>
</Steps>

## 网络支持

| 网络  | 支持 | 保留期 |
| --- | -- | --- |
| 主网  | 是  | 无限制 |
| 开发网 | 是  | 2周  |
| 测试网 | 否  | 不适用 |

## 请求参数

| 参数                 | 描述                                 | 默认值         | 示例                               |
| ------------------ | ---------------------------------- | ----------- | -------------------------------- |
| `limit`            | 要返回的交易数量（1-100）                    | 10          | `&limit=25`                      |
| `before-signature` | 获取此签名之前的交易（与`sort-order=desc`一起使用） | -           | `&before-signature=sig123...`    |
| `after-signature`  | 获取此签名之后的交易（与`sort-order=asc`一起使用）  | -           | `&after-signature=sig456...`     |
| `type`             | 按交易类型过滤                            | -           | `&type=NFT_SALE`                 |
| `sort-order`       | 结果的排序顺序                            | `desc`      | `&sort-order=asc`                |
| `token-accounts`   | 过滤与相关代币账户的交易                       | `none`      | `&token-accounts=balanceChanged` |
| `commitment`       | 承诺级别                               | `finalized` | `&commitment=confirmed`          |

### 基于时间的过滤

| 参数         | 描述              | 示例                     |
| ---------- | --------------- | ---------------------- |
| `gt-time`  | 此Unix时间戳之后的交易   | `&gt-time=1656442333`  |
| `gte-time` | 于此Unix时间戳或之后的交易 | `&gte-time=1656442333` |
| `lt-time`  | 此Unix时间戳之前的交易   | `&lt-time=1656442333`  |
| `lte-time` | 于此Unix时间戳或之前的交易 | `&lte-time=1656442333` |

### 基于槽位的过滤

| 参数         | 描述         | 示例                    |
| ---------- | ---------- | --------------------- |
| `gt-slot`  | 此槽位之后的交易   | `&gt-slot=148277128`  |
| `gte-slot` | 于此槽位或之后的交易 | `&gte-slot=148277128` |
| `lt-slot`  | 此槽位之前的交易   | `&lt-slot=148277128`  |
| `lte-slot` | 于此槽位或之前的交易 | `&lte-slot=148277128` |

过滤说明：

* 时间参数使用Unix时间戳（自纪元以来的秒数）；槽位参数使用Solana槽位号。
* 不能在同一请求中合并时间和槽位过滤器。
* 使用`sort-order=asc`进行升序（最旧优先）或`sort-order=desc`进行降序（最新优先）。
* 当您知道大致的时期时，使用时间或槽位过滤器缩小搜索范围，并配合`limit`控制页面大小。

## 关联代币账户

在Solana上，钱包不会直接持有代币，而是钱包拥有代币账户，这些代币账户持有代币。当有人发送USDC给您时，它会进入您的USDC代币账户，而不是您的主钱包地址。

此端点的独特之处在于它能够查询钱包的**完整代币历史**，包括关联的代币账户（ATAs）。本地RPC方法如`getSignaturesForAddress`不包括ATAs。

`token-accounts`过滤器控制此行为：

* **`none`**（默认）— 仅返回直接引用钱包地址的交易。当您只关心直接钱包交互时使用此选项。
* **`balanceChanged`**（推荐）— 返回引用钱包地址或修改由钱包拥有的代币账户余额的交易。此方式会筛除垃圾邮件和与钱包无关的操作（如费用收取或委托），为您提供有意义的清晰视图。
* **`all`** — 返回引用钱包地址或任何由钱包拥有的代币账户的所有交易。

<Warning>
  `token-accounts`过滤器依赖于代币余额元数据中的`owner`字段，该字段在槽位111,491,819（约2022年12月）之前不可用。在此槽位之前活跃的代币账户交易可能会在`balanceChanged`和`all`结果中缺失。请参阅[getTransactionsForAddress教程](/docs/zh/rpc/gettransactionsforaddress#限制和边缘情况)，了解完整代码示例的解决方案。
</Warning>

## 过滤器

### 按交易类型过滤

仅获取特定类型的交易，如NFT销售、代币转移或交换：

<Tabs>
  <Tab title="NFT销售">
    ```javascript theme={"system"}
    const fetchNftSales = async () => {
      const tokenAddress = "GjUG1BATg5V4bdAr1csKys1XK9fmrbntgb1iV7rAkn94"; // NFT mint address
      const url = `https://mainnet.helius-rpc.com/v0/addresses/${tokenAddress}/transactions?api-key=YOUR_API_KEY&type=NFT_SALE`;

      const response = await fetch(url);
      const nftSales = await response.json();
      console.log("NFT sale transactions:", nftSales);
    };
    ```
  </Tab>

  <Tab title="代币转移">
    ```javascript theme={"system"}
    const fetchTokenTransfers = async () => {
      const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K"; // Wallet address
      const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&type=TRANSFER`;

      const response = await fetch(url);
      const transfers = await response.json();
      console.log("Transfer transactions:", transfers);
    };
    ```
  </Tab>

  <Tab title="交换">
    ```javascript theme={"system"}
    const fetchSwapTransactions = async () => {
      const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K"; // Wallet address
      const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&type=SWAP`;

      const response = await fetch(url);
      const swaps = await response.json();
      console.log("Swap transactions:", swaps);
    };
    ```
  </Tab>
</Tabs>

有关支持的交易类型的完整列表，请参阅[交易历史API参考](/docs/zh/api-reference/enhanced-transactions/gettransactionsbyaddress)。

### 运行时类型过滤

<Note>
  类型过滤是在运行时进行的：API按顺序搜索交易直至找到至少50个匹配项。如果在搜索窗口中找不到任何匹配项，它将返回错误并带有签名，以便继续搜索。这是预期的行为，并非故障。
</Note>

当在当前搜索窗口中找不到匹配的交易时，API返回如下错误响应：

```json theme={"system"}
{
  "error": "Failed to find events within the search period. To continue search, query the API again with the `before-signature` parameter set to 2UKbsu95YzxGjUGYRg2znozmmVADVgmnhHqzDxq8Xfb3V5bf2NHUkaXGPrUpQnRFVHVKbawdQXtm4xJt9njMDHvg."
}
```

要继续，请使用错误消息中的签名和适当的参数（`before-signature`用于降序，`after-signature`用于升序）进行下一次请求。

<Accordion title="类型过滤器的连续循环（完整示例）">
  ```javascript theme={"system"}
  const fetchFilteredTransactions = async (sortOrder = 'desc') => {
    const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";
    const transactionType = "NFT_SALE";
    let continuationSignature = null;
    let allFilteredTransactions = [];
    let maxRetries = 10; // Prevent infinite loops
    let retryCount = 0;

    // Determine which parameter to use based on sort order
    const continuationParam = sortOrder === 'asc' ? 'after-signature' : 'before-signature';

    while (retryCount < maxRetries) {
      // Build URL with optional continuation parameter
      let url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&type=${transactionType}&sort-order=${sortOrder}`;

      if (continuationSignature) {
        url += `&${continuationParam}=${continuationSignature}`;
      }

      try {
        const response = await fetch(url);
        const data = await response.json();

        // Check if we received an error about search period
        if (data.error && data.error.includes("Failed to find events within the search period")) {
          // Extract the signature from the error message
          const signatureMatch = data.error.match(/parameter set to ([A-Za-z0-9]+)/);

          if (signatureMatch && signatureMatch[1]) {
            console.log(`No results in this period. Continuing search from: ${signatureMatch[1]}`);
            continuationSignature = signatureMatch[1];
            retryCount++;
            continue; // Continue searching with new signature
          } else {
            console.log("No more transactions to search");
            break;
          }
        }

        // Check if we received transactions
        if (Array.isArray(data) && data.length > 0) {
          console.log(`Found ${data.length} ${transactionType} transactions`);
          allFilteredTransactions = [...allFilteredTransactions, ...data];

          // Set continuation signature for next page
          continuationSignature = data[data.length - 1].signature;
          retryCount = 0; // Reset retry count since we found results
        } else {
          console.log("No more transactions found");
          break;
        }

      } catch (error) {
        console.error("Error fetching transactions:", error);
        break;
      }
    }

    console.log(`Total ${transactionType} transactions found: ${allFilteredTransactions.length}`);
    return allFilteredTransactions;
  };

  // Usage examples:
  // Descending order (newest first) - uses 'before-signature' parameter
  fetchFilteredTransactions('desc');

  // Ascending order (oldest first) - uses 'after-signature' parameter
  fetchFilteredTransactions('asc');
  ```

  关键点：

  * 使用类型过滤器时，API一次搜索最多50个交易。
  * 如果找不到匹配项，使用错误消息中的签名继续搜索。
  * 在降序（默认情况下，最新优先）搜索时使用`before-signature`。
  * 在升序（最旧优先）搜索时使用`after-signature` — 对于按时间顺序的搜索是必需的。
  * 实施最大重试限制，以防止无限循环。
</Accordion>

## 示例

以下场景涵盖时间和槽位范围、排序顺序、ATAs和组合过滤器。

<Accordion title="按时间范围过滤">
  获取特定时间窗口内的交易：

  <Tabs>
    <Tab title="过去24小时">
      ```javascript theme={"system"}
      const fetchRecentTransactions = async () => {
        const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";
        const now = Math.floor(Date.now() / 1000);
        const oneDayAgo = now - (24 * 60 * 60);

        const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&gte-time=${oneDayAgo}&lte-time=${now}`;

        const response = await fetch(url);
        const transactions = await response.json();
        console.log("Transactions from last 24 hours:", transactions);
      };
      ```
    </Tab>

    <Tab title="特定日期范围">
      ```javascript theme={"system"}
      const fetchTransactionsByDateRange = async () => {
        const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";

        // January 1, 2024 to January 31, 2024
        const startTime = Math.floor(new Date('2024-01-01').getTime() / 1000);
        const endTime = Math.floor(new Date('2024-01-31').getTime() / 1000);

        const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&gte-time=${startTime}&lte-time=${endTime}`;

        const response = await fetch(url);
        const transactions = await response.json();
        console.log("Transactions in January 2024:", transactions);
      };
      ```
    </Tab>
  </Tabs>
</Accordion>

<Accordion title="按槽位范围过滤">
  获取特定槽位范围内的交易：

  ```javascript theme={"system"}
  const fetchTransactionsBySlotRange = async () => {
    const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";
    const startSlot = 148000000;
    const endSlot = 148100000;

    const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&gte-slot=${startSlot}&lte-slot=${endSlot}`;

    const response = await fetch(url);
    const transactions = await response.json();
    console.log(`Transactions between slots ${startSlot} and ${endSlot}:`, transactions);
  };
  ```
</Accordion>

<Accordion title="更改排序顺序">
  获取升序（最旧优先）的交易：

  ```javascript theme={"system"}
  const fetchOldestTransactions = async () => {
    const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";
    const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&sort-order=asc&limit=10`;

    const response = await fetch(url);
    const transactions = await response.json();
    console.log("10 oldest transactions:", transactions);
  };
  ```
</Accordion>

<Accordion title="包括相关代币账户的转移">
  查询钱包的完整历史，包括关联代币地址（ATAs）：

  ```javascript theme={"system"}
  const fetchTransactionsWithATA = async () => {
    const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";

    const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&token-accounts=balanceChanged&sort-order=desc&limit=50`;

    const response = await fetch(url);
    const transactions = await response.json();
    console.log("Most recent transactions (including ATA transfers)", transactions);
  };
  ```
</Accordion>

<Accordion title="组合多种过滤器">
  将类型过滤与时间范围和自定义排序顺序组合：

  ```javascript theme={"system"}
  const fetchFilteredTransactionsAdvanced = async () => {
    const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";

    // Get NFT sales from the last 7 days, oldest first
    const now = Math.floor(Date.now() / 1000);
    const sevenDaysAgo = now - (7 * 24 * 60 * 60);

    const url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&type=NFT_SALE&gte-time=${sevenDaysAgo}&sort-order=asc&limit=50`;

    const response = await fetch(url);
    const transactions = await response.json();
    console.log("NFT sales from last 7 days (oldest first):", transactions);
  };
  ```
</Accordion>

## 分页

对于高流量地址，使用每批次的最后一个签名作为光标翻页查看结果：

```javascript theme={"system"}
const fetchAllTransactions = async () => {
  const walletAddress = "2k5AXX4guW9XwRQ1AKCpAuUqgWDpQpwFfpVFh3hnm2Ha"; // Replace with target wallet
  const baseUrl = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY`;
  let url = baseUrl;
  let lastSignature = null;
  let allTransactions = [];

  while (true) {
    if (lastSignature) {
      url = baseUrl + `&before-signature=${lastSignature}`;
    }

    const response = await fetch(url);

    // Check response status
    if (!response.ok) {
      console.error(`API error: ${response.status}`);
      break;
    }

    const transactions = await response.json();

    if (transactions && transactions.length > 0) {
      console.log(`Fetched batch of ${transactions.length} transactions`);
      allTransactions = [...allTransactions, ...transactions];
      lastSignature = transactions[transactions.length - 1].signature;
    } else {
      console.log(`Finished! Total transactions: ${allTransactions.length}`);
      break;
    }
  }

  return allTransactions;
};
```

要在一个时间范围内分页，请在每个请求上保留时间过滤器，并在每次循环中推进`before-signature`光标：

```javascript theme={"system"}
const fetchAllTransactionsInTimeRange = async () => {
  const walletAddress = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K";
  const startTime = Math.floor(new Date('2024-01-01').getTime() / 1000);
  const endTime = Math.floor(new Date('2024-01-31').getTime() / 1000);

  let beforeSignature = null;
  let allTransactions = [];

  while (true) {
    let url = `https://mainnet.helius-rpc.com/v0/addresses/${walletAddress}/transactions?api-key=YOUR_API_KEY&gte-time=${startTime}&lte-time=${endTime}&limit=100`;

    if (beforeSignature) {
      url += `&before-signature=${beforeSignature}`;
    }

    const response = await fetch(url);
    const transactions = await response.json();

    if (!Array.isArray(transactions) || transactions.length === 0) {
      break;
    }

    allTransactions = [...allTransactions, ...transactions];
    beforeSignature = transactions[transactions.length - 1].signature;

    console.log(`Fetched ${transactions.length} transactions, total: ${allTransactions.length}`);
  }

  console.log(`Total transactions in time range: ${allTransactions.length}`);
  return allTransactions;
};
```

## 后续步骤

<CardGroup cols={2}>
  <Card title="getTransactionsForAddress" icon="clock-rotate-left" href="/docs/zh/rpc/gettransactionsforaddress">
    现代的、Helius原生的交易历史和回填替代品。
  </Card>

  <Card title="钱包API" icon="wallet" href="/docs/zh/wallet-api/overview">
    人类可读的钱包数据的REST端点：余额、历史和转移。
  </Card>

  <Card title="解析交易" icon="code" href="/docs/zh/enhanced-transactions/parse-transactions">
    将一个或多个交易签名解析成人类可读数据。
  </Card>

  <Card title="获取数据概述" icon="database" href="/docs/zh/getting-data">
    比较每个Helius选项以查询Solana数据。
  </Card>
</CardGroup>
