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

# Cách lấy tất cả giao dịch chuyển tiền của ví Solana

> Theo dõi tất cả giao dịch chuyển token đến và đi đối với bất kỳ ví Solana nào. Xem thông tin người gửi/người nhận, số lượng và dấu thời gian để có lịch sử chuyển tiền đầy đủ.

<Note>
  Wallet API đang ở giai đoạn Beta. Các điểm cuối và định dạng phản hồi có thể thay đổi.
</Note>

## Tổng quan

Điểm cuối Token Transfers truy xuất toàn bộ hoạt động chuyển token của một ví Solana, bao gồm thông tin chi tiết về người gửi và người nhận. Không giống như [lịch sử giao dịch](/docs/vi/wallet-api/history) đầy đủ, điểm cuối này tập trung riêng vào các giao dịch chuyển tiền, nên rất phù hợp để theo dõi thanh toán và giám sát hoạt động chuyển tiền.

Điểm cuối trả về tối đa 100 giao dịch chuyển tiền cho mỗi yêu cầu (mặc định là 50). Sử dụng tham số `cursor` với `pagination.nextCursor` để lấy trang tiếp theo và đọc `pagination.hasMore` để biết khi nào còn kết quả khác.

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

Sử dụng Token Transfers API khi cần:

* **Theo dõi thanh toán**: giám sát các khoản thanh toán đến cho bộ xử lý thanh toán.
* **Xây dựng nguồn cấp dữ liệu chuyển tiền**: hiển thị nguồn cấp hoạt động "đã gửi/đã nhận" đơn giản.
* **Giám sát các token cụ thể**: theo dõi giao dịch chuyển một token cụ thể (ví dụ: thanh toán bằng USDC).
* **Xác định đối tác giao dịch**: xem ai đã gửi hoặc nhận token.
* **Tạo biên lai**: tạo biên lai thanh toán có thông tin chi tiết về người gửi/người nhận.
* **Phát hiện hoạt động đáng ngờ**: giám sát các mẫu chuyển tiền bất thường.

## Bắt đầu nhanh

### Truy vấn chuyển tiền cơ bản

Lấy các giao dịch chuyển đến và đi gần đây:

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"system"}
    const getWalletTransfers = async (address) => {
      const url = `https://api.helius.xyz/v1/wallet/${address}/transfers?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} transfers`);

      // Display recent transfers
      data.data.forEach(transfer => {
        const date = new Date(transfer.timestamp * 1000).toLocaleString();
        const direction = transfer.direction === 'in' ? 'Received' : 'Sent';
        const counterparty = transfer.counterparty.slice(0, 8) + '...';

        console.log(`\n${direction} - ${date}`);
        console.log(`Amount: ${transfer.amount} ${transfer.symbol || transfer.mint.slice(0, 8) + '...'}`);
        console.log(`${transfer.direction === 'in' ? 'From' : 'To'}: ${counterparty}`);
        console.log(`Signature: ${transfer.signature.slice(0, 20)}...`);
      });

      return data;
    };

    getWalletTransfers("86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY");
    ```
  </Tab>

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

    def get_wallet_transfers(address: str):
        url = f"https://api.helius.xyz/v1/wallet/{address}/transfers"
        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'])} transfers")

        # Display recent transfers
        for transfer in data['data']:
            date = datetime.fromtimestamp(transfer['timestamp']).strftime('%Y-%m-%d %H:%M:%S')
            direction = 'Received' if transfer['direction'] == 'in' else 'Sent'
            counterparty = transfer['counterparty'][:8] + '...'
            symbol = transfer.get('symbol') or transfer['mint'][:8] + '...'

            print(f"\n{direction} - {date}")
            print(f"Amount: {transfer['amount']} {symbol}")
            print(f"{'From' if transfer['direction'] == 'in' else 'To'}: {counterparty}")
            print(f"Signature: {transfer['signature'][:20]}...")

        return data

    get_wallet_transfers("86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY")
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"system"}
    curl "https://api.helius.xyz/v1/wallet/86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY/transfers?api-key=YOUR_API_KEY"
    ```
  </Tab>
</Tabs>

### Lọc theo hướng

Lọc kết quả ở phía máy khách để chỉ lấy các giao dịch chuyển đến hoặc đi:

<Tabs>
  <Tab title="Incoming Only">
    ```javascript theme={"system"}
    const getIncomingTransfers = async (address) => {
      const data = await getWalletTransfers(address);

      const incoming = data.data.filter(t => t.direction === 'in');

      console.log(`Received ${incoming.length} incoming transfers`);

      incoming.forEach(transfer => {
        console.log(`Received ${transfer.amount} ${transfer.symbol} from ${transfer.counterparty.slice(0, 8)}...`);
      });

      return incoming;
    };
    ```
  </Tab>

  <Tab title="Outgoing Only">
    ```javascript theme={"system"}
    const getOutgoingTransfers = async (address) => {
      const data = await getWalletTransfers(address);

      const outgoing = data.data.filter(t => t.direction === 'out');

      console.log(`Made ${outgoing.length} outgoing transfers`);

      outgoing.forEach(transfer => {
        console.log(`Sent ${transfer.amount} ${transfer.symbol} to ${transfer.counterparty.slice(0, 8)}...`);
      });

      return outgoing;
    };
    ```
  </Tab>
</Tabs>

## Tham số truy vấn

| Tham số  | Kiểu      | Mặc định | Mô tả                                                    |
| -------- | --------- | -------- | -------------------------------------------------------- |
| `limit`  | số nguyên | 50       | Số lượng giao dịch chuyển tiền tối đa cần trả về (1-100) |
| `cursor` | chuỗi     | -        | Con trỏ phân trang từ phản hồi trước                     |

## Định dạng phản hồi

```json theme={"system"}
{
  "data": [
    {
      "signature": "5wHu1qwD7Jsj3xqWjdSEJmYr3Q5f5RjXqjqQJ7jqEj7jqEj7jqEj7jqEj7jqEj7jqE",
      "timestamp": 1704067200,
      "direction": "in",
      "counterparty": "HXsKP7wrBWaQ8T2Vtjry3Nj3oUgwYcqq9vrHDM12G664",
      "mint": "So11111111111111111111111111111111111111111",
      "symbol": "SOL",
      "amount": 1.5,
      "amountRaw": "1500000000",
      "decimals": 9
    },
    {
      "signature": "4aHu2qwD8Jtj4xqWjdSEJmYr3Q5f5RjXqjqQJ7jqEj7jqEj7jqEj7jqEj7jqEj7jqE",
      "timestamp": 1704067100,
      "direction": "out",
      "counterparty": "2ojv9BAiHUrvsm9gxDe7fJSzbNZSJcxZvf8dqmWGHG8S",
      "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "symbol": "USDC",
      "amount": 100.0,
      "amountRaw": "100000000",
      "decimals": 6
    }
  ],
  "pagination": {
    "hasMore": true,
    "nextCursor": "5wHu1qwD7Jsj3xqWjdSEJmYr3Q5f5RjXqjqQJ7jqEj7jqEj7jqEj7jqEj7jqEj7jqE"
  }
}
```

### Ghi chú về trường

* **`direction`**: tương ứng với ví đang được truy vấn. `in` là token **đã nhận** (thanh toán đến); `out` là token **đã gửi** (thanh toán đi).
* **`counterparty`**: đối với giao dịch chuyển `in`, đây là người gửi; đối với giao dịch chuyển `out`, đây là người nhận.
* **`amount`**: số lượng chuyển tiền ở định dạng dễ đọc, đã được chia cho `decimals`. Sử dụng giá trị này để hiển thị (ví dụ: `1.5` SOL, `100.0` USDC).
* **`amountRaw`**: cùng một số lượng dưới dạng chuỗi số nguyên thô, trước khi điều chỉnh phần thập phân (ví dụ: `"1500000000"` cho 1,5 SOL). Giá trị này được tuần tự hóa dưới dạng chuỗi để tránh mất độ chính xác của số dấu phẩy động. Sử dụng giá trị này cho các lệnh trên chuỗi hoặc phép tính chính xác: `amount = parseInt(amountRaw) / 10**decimals`.
* **`mint`**: địa chỉ mint của token (`So11111111111111111111111111111111111111111` cho SOL gốc).
* **`symbol`**: ký hiệu token. Không phải token nào cũng có ký hiệu; hãy dùng địa chỉ mint khi `symbol` là `null`.

## Trường hợp sử dụng

### Theo dõi lịch sử thanh toán cho người bán

Giám sát các khoản thanh toán USDC đến:

```javascript theme={"system"}
const trackMerchantPayments = async (merchantWallet) => {
  const data = await getWalletTransfers(merchantWallet);

  // Filter for incoming USDC transfers
  const usdcPayments = data.data.filter(t =>
    t.direction === 'in' &&
    t.mint === 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' // USDC
  );

  console.log(`Received ${usdcPayments.length} USDC payments`);

  const totalReceived = usdcPayments.reduce((sum, t) => sum + t.amount, 0);
  console.log(`Total USDC Received: $${totalReceived.toFixed(2)}`);

  // Display each payment
  usdcPayments.forEach(payment => {
    const date = new Date(payment.timestamp * 1000).toLocaleString();
    console.log(`${date}: $${payment.amount} from ${payment.counterparty}`);
  });

  return {
    count: usdcPayments.length,
    total: totalReceived,
    payments: usdcPayments
  };
};
```

### Tạo biên lai thanh toán

Tạo biên lai chi tiết cho một giao dịch chuyển tiền cụ thể:

```javascript theme={"system"}
const generatePaymentReceipt = async (address, signature) => {
  const data = await getWalletTransfers(address);

  const transfer = data.data.find(t => t.signature === signature);

  if (!transfer) {
    console.log('Transfer not found');
    return null;
  }

  const receipt = {
    receiptId: transfer.signature.slice(0, 16),
    date: new Date(transfer.timestamp * 1000).toISOString(),
    type: transfer.direction === 'in' ? 'Payment Received' : 'Payment Sent',
    amount: `${transfer.amount} ${transfer.symbol || 'tokens'}`,
    from: transfer.direction === 'in' ? transfer.counterparty : address,
    to: transfer.direction === 'out' ? transfer.counterparty : address,
    transactionUrl: `https://orbmarkets.io/tx/${transfer.signature}`
  };

  console.log('--- PAYMENT RECEIPT ---');
  Object.entries(receipt).forEach(([key, value]) => {
    console.log(`${key}: ${value}`);
  });

  return receipt;
};
```

### Giám sát các mẫu chuyển tiền đáng ngờ

Phát hiện hoạt động chuyển tiền bất thường:

```javascript theme={"system"}
const detectSuspiciousActivity = async (address) => {
  const data = await getWalletTransfers(address);

  const recentTransfers = data.data.filter(t => {
    const hourAgo = Date.now() / 1000 - 3600;
    return t.timestamp > hourAgo;
  });

  // Check for high frequency
  if (recentTransfers.length > 100) {
    console.log(`Warning: ${recentTransfers.length} transfers in the last hour`);
  }

  // Check for large amounts
  const largeTransfers = recentTransfers.filter(t => {
    // Assuming USDC/stablecoins
    return t.amount > 10000 && t.decimals === 6;
  });

  if (largeTransfers.length > 0) {
    console.log(`Warning: ${largeTransfers.length} large transfers (>$10k) in the last hour`);
  }

  // Check for transfers to same address
  const counterparties = recentTransfers.map(t => t.counterparty);
  const duplicates = counterparties.filter((item, index) => counterparties.indexOf(item) !== index);

  if (duplicates.length > 5) {
    console.log(`Warning: Multiple transfers to the same address`);
  }

  return {
    recentCount: recentTransfers.length,
    largeTransfers: largeTransfers.length,
    suspiciousPatterns: duplicates.length > 5
  };
};
```

### Xây dựng nguồn cấp hoạt động chuyển tiền

Tạo nguồn cấp hoạt động thân thiện với người dùng:

```javascript theme={"system"}
const buildTransferFeed = async (address) => {
  const data = await getWalletTransfers(address);

  const feed = data.data.map(transfer => {
    const date = new Date(transfer.timestamp * 1000);
    const timeAgo = getTimeAgo(date);

    return {
      id: transfer.signature,
      direction: transfer.direction,
      title: transfer.direction === 'in' ? 'Received' : 'Sent',
      subtitle: `${transfer.amount} ${transfer.symbol || 'tokens'}`,
      description: transfer.direction === 'in'
        ? `from ${transfer.counterparty.slice(0, 8)}...`
        : `to ${transfer.counterparty.slice(0, 8)}...`,
      timeAgo,
      explorerUrl: `https://orbmarkets.io/tx/${transfer.signature}`
    };
  });

  return feed;
};

function getTimeAgo(date) {
  const seconds = Math.floor((new Date() - date) / 1000);

  if (seconds < 60) return 'Just now';
  if (seconds < 3600) return `${Math.floor(seconds / 60)}m ago`;
  if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ago`;
  return `${Math.floor(seconds / 86400)}d ago`;
}
```

### Đối soát thanh toán

Đối chiếu các giao dịch chuyển tiền với các khoản thanh toán dự kiến:

```javascript theme={"system"}
const reconcilePayments = async (address, expectedPayments) => {
  const data = await getWalletTransfers(address);

  const recentTransfers = data.data.filter(t =>
    t.direction === 'in' &&
    t.mint === 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' // USDC
  );

  const reconciliation = expectedPayments.map(expected => {
    const match = recentTransfers.find(t =>
      Math.abs(t.amount - expected.amount) < 0.01 &&
      t.counterparty === expected.from
    );

    return {
      orderId: expected.orderId,
      expectedAmount: expected.amount,
      status: match ? 'Received' : 'Pending',
      receivedAmount: match?.amount,
      signature: match?.signature,
      timestamp: match?.timestamp
    };
  });

  console.log('Payment Reconciliation:');
  reconciliation.forEach(r => {
    console.log(`Order ${r.orderId}: ${r.status}`);
  });

  return reconciliation;
};

// Example usage
const expected = [
  { orderId: 'ORDER-001', amount: 100.00, from: 'ABC...' },
  { orderId: 'ORDER-002', amount: 250.50, from: 'XYZ...' }
];

reconcilePayments("86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY", expected);
```

## Phân trang

Đối với ví có nhiều giao dịch chuyển tiền, hãy duyệt qua các trang kết quả bằng tham số `cursor` và `pagination.hasMore`:

```javascript theme={"system"}
const getAllTransfers = async (address) => {
  let allTransfers = [];
  let cursor = null;

  do {
    const url = cursor
      ? `https://api.helius.xyz/v1/wallet/${address}/transfers?api-key=YOUR_API_KEY&cursor=${cursor}`
      : `https://api.helius.xyz/v1/wallet/${address}/transfers?api-key=YOUR_API_KEY`;

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

    allTransfers = allTransfers.concat(data.data);
    cursor = data.pagination.hasMore ? data.pagination.nextCursor : null;

    console.log(`Fetched ${allTransfers.length} transfers so far...`);

  } while (cursor);

  console.log(`\nTotal transfers: ${allTransfers.length}`);
  return allTransfers;
};
```

## Phương pháp hay nhất

* **Lọc phía máy khách đối với các token cụ thể.** API trả về tất cả giao dịch chuyển token. Lọc theo địa chỉ `mint` để theo dõi các token cụ thể như USDC hoặc SOL.
* **Kết hợp với Identity API.** Sử dụng điểm cuối [Identity](/docs/vi/wallet-api/identity) để hiển thị tên dễ đọc cho các đối tác giao dịch đã biết (sàn giao dịch, giao thức và các đối tượng khác).
* **Lưu vào bộ nhớ đệm các giao dịch chuyển tiền gần đây.** Dữ liệu chuyển tiền không thay đổi. Lưu kết quả vào bộ nhớ đệm và chỉ lấy các giao dịch chuyển tiền mới kể từ truy vấn gần nhất.
* **Phân trang để có lịch sử đầy đủ.** Triển khai phân trang để xử lý hiệu quả các ví có hàng nghìn giao dịch chuyển tiền.
* **Xử lý trường hợp thiếu ký hiệu.** Không phải token nào cũng có trường `symbol`. Hãy dùng địa chỉ mint khi `symbol` là `null`.

## Giao dịch chuyển tiền so với lịch sử giao dịch

| Tính năng              | Giao dịch chuyển tiền          | Lịch sử giao dịch               |
| ---------------------- | ------------------------------ | ------------------------------- |
| **Trọng tâm**          | Chỉ các giao dịch chuyển token | Tất cả loại giao dịch           |
| **Dữ liệu**            | Thông tin người gửi/người nhận | Thay đổi số dư của tất cả token |
| **Trường hợp sử dụng** | Theo dõi thanh toán            | Nhật ký hoạt động đầy đủ        |
| **Hiệu suất**          | Nhanh hơn, đơn giản hơn        | Toàn diện hơn                   |

Sử dụng [Transfers](/docs/vi/wallet-api/transfers) khi chỉ cần quan tâm đến các khoản thanh toán. Sử dụng [Transaction History](/docs/vi/wallet-api/history) khi cần dữ liệu đầy đủ về thay đổi số dư.

## Lỗi thường gặp

| Mã lỗi | Mô tả                             | Giải pháp                                            |
| ------ | --------------------------------- | ---------------------------------------------------- |
| 400    | Định dạng địa chỉ ví không hợp lệ | Xác minh địa chỉ là một địa chỉ Solana base58 hợp lệ |
| 401    | Thiếu hoặc sai khóa API           | Kiểm tra khóa API đã được đưa vào yêu cầu            |
| 429    | Vượt quá giới hạn tốc độ          | Giảm tần suất yêu cầu hoặc nâng cấp gói dịch vụ      |

## Bước tiếp theo

<CardGroup cols={3}>
  <Card title="Wallet History" icon="clock-rotate-left" href="/docs/vi/wallet-api/history">
    Lịch sử giao dịch đầy đủ cùng các thay đổi số dư theo từng giao dịch.
  </Card>

  <Card title="Wallet API Overview" icon="wallet" href="/docs/vi/wallet-api/overview">
    Tất cả điểm cuối Wallet API và các quy ước dùng chung.
  </Card>

  <Card title="API Reference" icon="code" href="/docs/vi/api-reference/wallet-api/transfers">
    Lược đồ yêu cầu và phản hồi cho các giao dịch chuyển token.
  </Card>
</CardGroup>
