> ## 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.

# Lịch sử giao dịch

> Truy xuất lịch sử giao dịch dễ đọc cho mọi địa chỉ Solana, hỗ trợ lọc, phạm vi thời gian và slot cũng như phân trang.

<Warning>
  Enhanced Transactions API là sản phẩm cũ đang ở chế độ bảo trì. API này vẫn hoạt động và các trang này vẫn khả dụng, nhưng không còn nhận thêm loại trình phân tích cú pháp hoặc tính năng mới. Sản phẩm kế nhiệm là [Parsed Events](/docs/vi/parsed-events), giải mã các chỉ thị thông qua danh mục IDL và có trong mọi gói với mức phí 10 credit cho mỗi yêu cầu. [Hướng dẫn di chuyển](/docs/vi/parsed-events/guides/migrate-from-enhanced-transactions) trình bày từng bước chuyển đổi. Bạn cũng có thể sử dụng [`getTransactionsForAddress`](/docs/vi/rpc/gettransactionsforaddress) cho lịch sử giao dịch và backfill, cũng như [Wallet API](/docs/vi/wallet-api/overview) cho dữ liệu ví dễ đọc.
</Warning>

## Tổng quan

Điểm cuối Lịch sử giao dịch trả về lịch sử giao dịch dễ đọc cho mọi địa chỉ Solana. Thay vì xử lý dữ liệu chỉ thị thô và danh sách tài khoản, bạn nhận được thông tin có cấu trúc về:

* Điều đã xảy ra trong giao dịch (chuyển khoản, hoán đổi, hoạt động NFT).
* Các tài khoản có liên quan.
* Lượng SOL hoặc số token đã được chuyển.
* Siêu dữ liệu liên quan (địa chỉ mint token, tên token, ký hiệu token và nhiều thông tin khác).

Gửi yêu cầu `GET` đến `/v0/addresses/{address}/transactions`. Về cơ chế nội bộ, điểm cuối này được cung cấp bởi phương thức RPC [`getTransactionsForAddress`](/docs/vi/rpc/gettransactionsforaddress).

## Khi nào nên sử dụng

* Bạn đang hiển thị lịch sử giao dịch của một địa chỉ cho người dùng (ví, trình theo dõi danh mục đầu tư, trình khám phá).
* Bạn muốn có lịch sử đã được phân tích cú pháp trước và dễ đọc mà không cần tự viết bộ giải mã.
* Bạn cần lọc lịch sử theo loại giao dịch, phạm vi thời gian hoặc phạm vi slot.
* Bạn cần toàn bộ lịch sử token của ví, bao gồm các tài khoản token liên kết (ATA) — xem bên dưới.

Đối với các dự án mới, [`getTransactionsForAddress`](/docs/vi/rpc/gettransactionsforaddress) là giải pháp hiện đại, thuần Helius, hỗ trợ lọc phía máy chủ và tra cứu tài khoản token.

## Bắt đầu nhanh

<Steps>
  <Step title="Get your API key">
    Đăng ký tại [dashboard.helius.dev](https://dashboard.helius.dev) và sao chép khóa API của bạn.
  </Step>

  <Step title="GET the address transactions endpoint">
    Truy xuất lịch sử giao dịch cho bất kỳ địa chỉ Solana nào.

    <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="Filter and paginate">
    Thu hẹp kết quả bằng `type` cùng các bộ lọc thời gian và slot bên dưới, sau đó phân trang qua các địa chỉ có khối lượng lớn bằng con trỏ chữ ký.
  </Step>
</Steps>

## Hỗ trợ mạng

| Mạng    | Được hỗ trợ | Thời gian lưu giữ |
| ------- | ----------- | ----------------- |
| Mainnet | Có          | Không giới hạn    |
| Devnet  | Có          | 2 tuần            |
| Testnet | Không       | Không áp dụng     |

## Tham số yêu cầu

| Tham số            | Mô tả                                                                 | Mặc định    | Ví dụ                            |
| ------------------ | --------------------------------------------------------------------- | ----------- | -------------------------------- |
| `limit`            | Số giao dịch cần trả về (1-100)                                       | 10          | `&limit=25`                      |
| `before-signature` | Truy xuất các giao dịch trước chữ ký này (dùng với `sort-order=desc`) | -           | `&before-signature=sig123...`    |
| `after-signature`  | Truy xuất các giao dịch sau chữ ký này (dùng với `sort-order=asc`)    | -           | `&after-signature=sig456...`     |
| `type`             | Lọc theo loại giao dịch                                               | -           | `&type=NFT_SALE`                 |
| `sort-order`       | Thứ tự sắp xếp kết quả                                                | `desc`      | `&sort-order=asc`                |
| `token-accounts`   | Lọc giao dịch cho các tài khoản token liên quan                       | `none`      | `&token-accounts=balanceChanged` |
| `commitment`       | Mức cam kết                                                           | `finalized` | `&commitment=confirmed`          |

### Lọc theo thời gian

| Tham số    | Mô tả                                               | Ví dụ                  |
| ---------- | --------------------------------------------------- | ---------------------- |
| `gt-time`  | Các giao dịch sau dấu thời gian Unix này            | `&gt-time=1656442333`  |
| `gte-time` | Các giao dịch tại hoặc sau dấu thời gian Unix này   | `&gte-time=1656442333` |
| `lt-time`  | Các giao dịch trước dấu thời gian Unix này          | `&lt-time=1656442333`  |
| `lte-time` | Các giao dịch tại hoặc trước dấu thời gian Unix này | `&lte-time=1656442333` |

### Lọc theo slot

| Tham số    | Mô tả                                 | Ví dụ                 |
| ---------- | ------------------------------------- | --------------------- |
| `gt-slot`  | Các giao dịch sau slot này            | `&gt-slot=148277128`  |
| `gte-slot` | Các giao dịch tại hoặc sau slot này   | `&gte-slot=148277128` |
| `lt-slot`  | Các giao dịch trước slot này          | `&lt-slot=148277128`  |
| `lte-slot` | Các giao dịch tại hoặc trước slot này | `&lte-slot=148277128` |

Lưu ý về lọc:

* Tham số thời gian sử dụng dấu thời gian Unix (số giây kể từ epoch); tham số slot sử dụng số slot Solana.
* Không thể kết hợp bộ lọc theo thời gian và theo slot trong cùng một yêu cầu.
* Sử dụng `sort-order=asc` để sắp xếp tăng dần (cũ nhất trước) hoặc `sort-order=desc` để sắp xếp giảm dần (mới nhất trước).
* Sử dụng bộ lọc thời gian hoặc slot để thu hẹp phạm vi tìm kiếm khi biết khoảng thời gian gần đúng, đồng thời kết hợp với `limit` để kiểm soát kích thước trang.

## Tài khoản token liên kết

Trên Solana, ví không trực tiếp nắm giữ token. Thay vào đó, ví sở hữu các tài khoản token và các tài khoản token đó nắm giữ token. Khi ai đó gửi USDC cho bạn, USDC sẽ được chuyển vào tài khoản token USDC thay vì địa chỉ ví chính.

Điểm cuối này khác biệt ở khả năng truy vấn **toàn bộ lịch sử token** của ví, bao gồm các tài khoản token liên kết (ATA). Các phương thức RPC gốc như `getSignaturesForAddress` không bao gồm ATA.

Bộ lọc `token-accounts` kiểm soát hành vi này:

* **`none`** (mặc định) — chỉ trả về các giao dịch tham chiếu trực tiếp đến địa chỉ ví. Sử dụng tùy chọn này khi bạn chỉ quan tâm đến các tương tác trực tiếp với ví.
* **`balanceChanged`** (khuyên dùng) — trả về các giao dịch tham chiếu đến địa chỉ ví hoặc thay đổi số dư của tài khoản token do ví sở hữu. Tùy chọn này loại bỏ thư rác và các thao tác không liên quan như thu phí hoặc ủy quyền, qua đó cung cấp góc nhìn rõ ràng về hoạt động ví có ý nghĩa.
* **`all`** — trả về tất cả giao dịch tham chiếu đến địa chỉ ví hoặc bất kỳ tài khoản token nào do ví sở hữu.

<Warning>
  Bộ lọc `token-accounts` phụ thuộc vào trường `owner` trong siêu dữ liệu số dư token. Trường này không khả dụng trước slot 111.491.819 (khoảng tháng 12 năm 2022). Các giao dịch liên quan đến tài khoản token hoạt động trước slot này có thể không xuất hiện trong kết quả `balanceChanged` và `all`. Xem [hướng dẫn getTransactionsForAddress](/docs/vi/rpc/gettransactionsforaddress#hạn-chế-và-trường-hợp-biên) để biết giải pháp thay thế kèm ví dụ mã đầy đủ.
</Warning>

## Bộ lọc

### Lọc theo loại giao dịch

Chỉ lấy các loại giao dịch cụ thể, chẳng hạn như bán NFT, chuyển token hoặc hoán đổi:

<Tabs>
  <Tab title="NFT Sales">
    ```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="Token Transfers">
    ```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="Swaps">
    ```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>

Để xem danh sách đầy đủ các loại giao dịch được hỗ trợ, hãy xem [tài liệu tham chiếu Transaction History API](/docs/vi/api-reference/enhanced-transactions/gettransactionsbyaddress).

### Lọc loại trong thời gian chạy

<Note>
  Việc lọc loại diễn ra trong thời gian chạy: API tìm kiếm tuần tự qua các giao dịch cho đến khi tìm thấy ít nhất 50 mục phù hợp. Nếu không tìm thấy kết quả phù hợp nào trong cửa sổ tìm kiếm, API trả về lỗi kèm chữ ký để tiếp tục tìm kiếm từ đó. Đây là hành vi dự kiến, không phải lỗi hoạt động.
</Note>

Khi không tìm thấy giao dịch phù hợp nào trong cửa sổ tìm kiếm hiện tại, API trả về phản hồi lỗi như sau:

```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."
}
```

Để tiếp tục, hãy dùng chữ ký trong thông báo lỗi với tham số thích hợp (`before-signature` cho thứ tự giảm dần, `after-signature` cho thứ tự tăng dần) trong yêu cầu tiếp theo.

<Accordion title="Continuation loop for type filters (full example)">
  ```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');
  ```

  Các điểm chính:

  * Khi sử dụng bộ lọc loại, API tìm kiếm tối đa 50 giao dịch mỗi lần.
  * Nếu không tìm thấy kết quả phù hợp, hãy dùng chữ ký trong thông báo lỗi để tiếp tục tìm kiếm.
  * Sử dụng `before-signature` khi tìm kiếm theo thứ tự giảm dần (mặc định, mới nhất trước).
  * Sử dụng `after-signature` khi tìm kiếm theo thứ tự tăng dần (cũ nhất trước) — bắt buộc đối với tìm kiếm theo trình tự thời gian.
  * Triển khai giới hạn số lần thử lại tối đa để tránh vòng lặp vô hạn.
</Accordion>

## Ví dụ

Các tình huống sau đề cập đến phạm vi thời gian và slot, thứ tự sắp xếp, ATA và bộ lọc kết hợp.

<Accordion title="Filter by time range">
  Lấy các giao dịch trong một khoảng thời gian cụ thể:

  <Tabs>
    <Tab title="Last 24 Hours">
      ```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="Specific Date Range">
      ```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="Filter by slot range">
  Lấy các giao dịch trong một phạm vi slot cụ thể:

  ```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="Change sort order">
  Lấy các giao dịch theo thứ tự tăng dần (cũ nhất trước):

  ```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="Include transfers for related token accounts">
  Truy vấn toàn bộ lịch sử của ví, bao gồm các địa chỉ token liên kết (ATA):

  ```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="Combine multiple filters">
  Kết hợp lọc theo loại với phạm vi thời gian và thứ tự sắp xếp tùy chỉnh:

  ```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>

## Phân trang

Đối với các địa chỉ có khối lượng lớn, hãy phân trang qua kết quả bằng cách dùng chữ ký cuối cùng trong mỗi lô làm con trỏ:

```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;
};
```

Để phân trang trong một phạm vi thời gian, hãy giữ nguyên các bộ lọc thời gian trong mọi yêu cầu và chuyển con trỏ `before-signature` về phía trước trong mỗi vòng lặp:

```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;
};
```

## Các bước tiếp theo

<CardGroup cols={2}>
  <Card title="getTransactionsForAddress" icon="clock-rotate-left" href="/docs/vi/rpc/gettransactionsforaddress">
    Giải pháp thay thế hiện đại, thuần Helius cho lịch sử giao dịch và backfill.
  </Card>

  <Card title="Wallet API" icon="wallet" href="/docs/vi/wallet-api/overview">
    Các điểm cuối REST cho dữ liệu ví dễ đọc: số dư, lịch sử và giao dịch chuyển.
  </Card>

  <Card title="Parse Transactions" icon="code" href="/docs/vi/enhanced-transactions/parse-transactions">
    Phân tích cú pháp một hoặc nhiều chữ ký giao dịch thành dữ liệu dễ đọc.
  </Card>

  <Card title="Getting Data overview" icon="database" href="/docs/vi/getting-data">
    So sánh mọi tùy chọn Helius để truy vấn dữ liệu Solana.
  </Card>
</CardGroup>
