> ## 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 지갑 거래 기록 가져오기

> 각 거래에 대한 잔액 변화를 포함하여 Solana 지갑의 전체 거래 기록을 가져오세요. 포트폴리오 추적기, 회계 도구 및 분석 플랫폼에 적합합니다.

<Note>
  Wallet API는 베타 버전입니다. 엔드포인트 및 응답 형식이 변경될 수 있습니다.
</Note>

## 개요

Transaction History 엔드포인트는 Enhanced Transactions API를 사용하여 Solana 지갑의 전체 거래 기록을 검색합니다. 이는 최신 거래부터 역순으로 각 거래의 잔액 변화를 포함한 사람이 읽을 수 있는 파싱된 거래를 반환합니다.

엔드포인트는 요청당 최대 100개의 거래를 반환하므로 페이지 매김은 수동입니다. 다음 페이지를 가져오려면 `before` 매개변수를 `pagination.nextCursor`와 함께 사용하고, 더 많은 결과가 있는지 알아보려면 `pagination.hasMore`를 읽으세요. 각 요청은 단일 API 호출이며 100 크레딧이 소모됩니다.

`tokenAccounts` 매개변수는 지갑이 소유한 토큰 계정과 관련된 거래가 포함될지 여부를 제어합니다:

* `balanceChanged` (권장): 스팸을 필터링하여 토큰 계정 잔액을 변경한 거래 포함.
* `none`: 직접적인 지갑 상호작용만 포함.
* `all`: 스팸을 포함한 모든 토큰 계정 거래.

<Warning>
  `tokenAccounts` 필터는 토큰 잔액 메타데이터의 `owner` 필드에 의존하는데, 이는 슬롯 111,491,819 (\~2022년 12월) 이전에는 사용 가능하지 않았습니다. 이러한 슬롯 이전에 활성화된 토큰 계정과 관련된 거래는 누락될 수 있습니다. 해결 방법은 [getTransactionsForAddress 튜토리얼](/docs/ko/rpc/gettransactionsforaddress#제한-사항-및-예외-사항)을 참조하세요.
</Warning>

## 사용 시기

Transaction History API를 사용해야 할 경우:

* **거래 피드 표시**: 사용자에게 전체 거래 기록을 보여줍니다.
* **손익 계산**: 모든 거래의 수익 및 손실을 추적합니다.
* **세금 및 회계**: 세금 신고를 위한 전체 거래 보고서를 생성합니다.
* **포트폴리오 분석**: 거래 패턴 및 활동을 분석합니다.
* **감사 추적**: 지갑 활동의 완전한 기록을 유지합니다.
* **잔액 재구성**: 과거 데이터를 통해 현재 잔액을 재구성합니다.

## 빠른 시작

### 기본 기록 조회

잔액 변화를 포함한 가장 최근 거래 가져오기:

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

      // Display recent transactions
      data.data.forEach(tx => {
        const date = new Date(tx.timestamp * 1000).toLocaleString();
        const status = tx.error ? 'Failed' : 'Success';

        console.log(`\n${status} - ${date}`);
        console.log(`Signature: ${tx.signature.slice(0, 20)}...`);
        console.log(`Fee: ${tx.fee} SOL`);

        // Show balance changes
        tx.balanceChanges.forEach(change => {
          const sign = change.amount > 0 ? '+' : '';
          console.log(`  ${sign}${change.amount} ${change.mint === 'SOL' ? 'SOL' : change.mint.slice(0, 8)}...`);
        });
      });

      return data;
    };

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

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

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

        # Display recent transactions
        for tx in data['data']:
            date = datetime.fromtimestamp(tx['timestamp']).strftime('%Y-%m-%d %H:%M:%S')
            status = 'Failed' if tx.get('error') else 'Success'

            print(f"\n{status} - {date}")
            print(f"Signature: {tx['signature'][:20]}...")
            print(f"Fee: {tx['fee']} SOL")

            # Show balance changes
            for change in tx['balanceChanges']:
                sign = '+' if change['amount'] > 0 else ''
                mint_display = 'SOL' if change['mint'] == 'SOL' else change['mint'][:8] + '...'
                print(f"  {sign}{change['amount']} {mint_display}")

        return data

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

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

### 전체 기록에 대한 페이지 매김

`before` 매개변수와 함께 페이지 매김을 사용하여 모든 거래를 가져오세요:

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"system"}
    const getAllTransactionHistory = async (address) => {
      let allTransactions = [];
      let before = null;

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

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

        allTransactions = allTransactions.concat(data.data);
        before = data.pagination.hasMore ? data.pagination.nextCursor : null;

        console.log(`Fetched ${allTransactions.length} transactions so far...`);

      } while (before);

      console.log(`\nTotal transactions: ${allTransactions.length}`);
      return allTransactions;
    };

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

  <Tab title="Python">
    ```python theme={"system"}
    def get_all_transaction_history(address: str):
        all_transactions = []
        before = None

        while True:
            url = f"https://api.helius.xyz/v1/wallet/{address}/history"
            params = {"api-key": "YOUR_API_KEY"}

            if before:
                params["before"] = before

            response = requests.get(url, params=params, headers={"X-Api-Key": "YOUR_API_KEY"})
            response.raise_for_status()

            data = response.json()
            all_transactions.extend(data['data'])

            print(f"Fetched {len(all_transactions)} transactions so far...")

            if not data['pagination']['hasMore']:
                break

            before = data['pagination']['nextCursor']

        print(f"\nTotal transactions: {len(all_transactions)}")
        return all_transactions

    get_all_transaction_history("86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY")
    ```
  </Tab>
</Tabs>

## 쿼리 매개변수

| 매개변수            | 유형  | 기본값            | 설명                                                       |
| --------------- | --- | -------------- | -------------------------------------------------------- |
| `limit`         | 정수  | 100            | 요청당 최대 거래 수량 (1-100)                                     |
| `before`        | 문자열 | -              | 이 서명 이전의 거래를 가져옵니다 (이전 응답의 `pagination.nextCursor` 사용)   |
| `after`         | 문자열 | -              | 이 서명 이후의 거래를 가져옵니다 (오름차순 페이지 매김용)                        |
| `type`          | 문자열 | -              | 거래 유형별 필터링 (예: SWAP, TRANSFER, NFT\_SALE, TOKEN\_MINT)   |
| `tokenAccounts` | 문자열 | balanceChanged | 토큰 계정 관련 거래 필터링: `none`, `balanceChanged` (권장), 또는 `all` |

### 사용 가능한 거래 유형

`type` 매개변수는 다음 거래 유형별 필터링을 지원합니다:

`SWAP`, `TRANSFER`, `NFT_SALE`, `NFT_BID`, `NFT_LISTING`, `NFT_MINT`, `NFT_CANCEL_LISTING`, `TOKEN_MINT`, `BURN`, `COMPRESSED_NFT_MINT`, `COMPRESSED_NFT_TRANSFER`, `COMPRESSED_NFT_BURN`, `CREATE_STORE`, `WHITELIST_CREATOR`, `ADD_TO_WHITELIST`, `REMOVE_FROM_WHITELIST`, `AUCTION_MANAGER_CLAIM_BID`, `EMPTY_PAYMENT_ACCOUNT`, `UPDATE_PRIMARY_SALE_METADATA`, `ADD_TOKEN_TO_VAULT`, `ACTIVATE_VAULT`, `INIT_VAULT`, `INIT_BANK`, `INIT_STAKE`, `MERGE_STAKE`, `SPLIT_STAKE`, `CREATE_AUCTION_MANAGER`, `START_AUCTION`, `CREATE_AUCTION_MANAGER_V2`, `UPDATE_EXTERNAL_PRICE_ACCOUNT`, `EXECUTE_TRANSACTION`

### 필터 예제

<Tabs>
  <Tab title="유형별 필터">
    ```javascript theme={"system"}
    // Get only SWAP transactions
    const url = `https://api.helius.xyz/v1/wallet/${address}/history?api-key=YOUR_API_KEY&type=SWAP`;
    ```
  </Tab>

  <Tab title="토큰 계정 필터">
    ```javascript theme={"system"}
    // Exclude spam by only including transactions that changed token balances
    const url = `https://api.helius.xyz/v1/wallet/${address}/history?api-key=YOUR_API_KEY&tokenAccounts=balanceChanged`;

    // Only show direct wallet interactions
    const url = `https://api.helius.xyz/v1/wallet/${address}/history?api-key=YOUR_API_KEY&tokenAccounts=none`;
    ```
  </Tab>

  <Tab title="결합 필터">
    ```javascript theme={"system"}
    // Get only NFT sales that changed balances
    const url = `https://api.helius.xyz/v1/wallet/${address}/history?api-key=YOUR_API_KEY&type=NFT_SALE&tokenAccounts=balanceChanged`;
    ```
  </Tab>
</Tabs>

## 응답 형식

```json theme={"system"}
{
  "data": [
    {
      "signature": "5wHu1qwD7Jsj3xqWjdSEJmYr3Q5f5RjXqjqQJ7jqEj7jqEj7jqEj7jqEj7jqEj7jqE",
      "timestamp": 1704067200,
      "slot": 250000000,
      "fee": 0.000005,
      "feePayer": "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
      "error": null,
      "balanceChanges": [
        {
          "mint": "So11111111111111111111111111111111111111111",
          "amount": -0.05,
          "decimals": 9
        },
        {
          "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
          "amount": 50.0,
          "decimals": 6
        }
      ]
    }
  ],
  "pagination": {
    "hasMore": true,
    "nextCursor": "5wHu1qwD7Jsj3xqWjdSEJmYr3Q5f5RjXqjqQJ7jqEj7jqEj7jqEj7jqEj7jqEj7jqE"
  }
}
```

### 필드 노트

* **`timestamp`**: Unix 초. 아직 완전히 처리되지 않은 매우 최근의 거래에는 `null`가 있을 수 있습니다.
* **`error`**: 성공적인 거래에는 `null`; 실패한 경우 오류 값이 있습니다. 실패한 거래도 수수료가 부과됩니다.
* **`balanceChanges`**: 거래에서 지갑 보유량이 변경된 방식 — 양수 `amount`는 받은 토큰, 음수 `amount`는 전송되거나 사용된 토큰입니다.
* **`mint`** (`balanceChanges` 내): 토큰 민트 주소 또는 네이티브 SOL의 경우 `"SOL"`.
* **`amount`** (`balanceChanges` 내): **사람이 읽을 수 있는** 형식으로 이미 `decimals`로 나누어져 있습니다 — `-0.05`는 −0.05 SOL를 의미하지 −0.05 lamports를 의미하지 않습니다. 이 엔드포인트는 원래 `amountRaw` 필드를 포함하지 않습니다.

#### 잔액 변경 예제

```javascript theme={"system"}
// Swap: Sold 0.05 SOL, received 5 USDC
{
  "balanceChanges": [
    { "mint": "SOL", "amount": -0.05, "decimals": 9 },
    { "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "amount": 5.0, "decimals": 6 }
  ]
}

// Simple transfer: Sent 10 USDC
{
  "balanceChanges": [
    { "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "amount": -10.0, "decimals": 6 }
  ]
}
```

## 사용 사례

### 총 거래량 계산

모든 전송을 합산하여 거래량을 계산하세요:

```javascript theme={"system"}
const calculateTradingVolume = async (address, tokenMint) => {
  const transactions = await getAllTransactionHistory(address);

  let totalVolume = 0;

  transactions.forEach(tx => {
    tx.balanceChanges.forEach(change => {
      if (change.mint === tokenMint) {
        totalVolume += Math.abs(change.amount);
      }
    });
  });

  console.log(`Total ${tokenMint} volume: ${totalVolume}`);
  return totalVolume;
};

// Example: Calculate total USDC volume
calculateTradingVolume(
  "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
  "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" // USDC
);
```

### 세금 보고서 생성

세금 신고를 위한 거래 보고서를 만드세요:

```javascript theme={"system"}
const generateTaxReport = async (address, year) => {
  const transactions = await getAllTransactionHistory(address);

  const startDate = new Date(`${year}-01-01`).getTime() / 1000;
  // Set to end of December 31st (23:59:59.999) to include all transactions from that day
  const endDate = new Date(`${year}-12-31T23:59:59.999Z`).getTime() / 1000;

  const taxableTransactions = transactions
    .filter(tx => tx.timestamp >= startDate && tx.timestamp <= endDate)
    .map(tx => ({
      date: new Date(tx.timestamp * 1000).toISOString(),
      signature: tx.signature,
      fee: tx.fee,
      balanceChanges: tx.balanceChanges,
      explorerUrl: `https://orbmarkets.io/tx/${tx.signature}`
    }));

  console.log(`Found ${taxableTransactions.length} transactions in ${year}`);

  // Export as JSON
  const report = {
    address,
    year,
    transactionCount: taxableTransactions.length,
    transactions: taxableTransactions
  };

  console.log(JSON.stringify(report, null, 2));
  return report;
};

generateTaxReport("86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY", 2024);
```

### 실패한 거래 추적

실패한 거래를 찾아 오류를 이해하세요:

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

  const failed = data.data.filter(tx => tx.error !== null);

  console.log(`Found ${failed.length} failed transactions`);

  failed.forEach(tx => {
    const date = new Date(tx.timestamp * 1000).toLocaleString();
    console.log(`\n${date}`);
    console.log(`Signature: ${tx.signature}`);
    console.log(`Error: ${tx.error}`);
    console.log(`Fee Paid: ${tx.fee} SOL`);
  });

  return failed;
};
```

### 과거 잔액 재구성

특정 시점의 잔액을 계산하세요:

```javascript theme={"system"}
const getHistoricalBalance = async (address, targetTimestamp) => {
  const transactions = await getAllTransactionHistory(address);

  // Filter to transactions before target date
  const relevantTxs = transactions.filter(tx => tx.timestamp <= targetTimestamp);

  // Sum all balance changes
  const balances = {};

  relevantTxs.forEach(tx => {
    tx.balanceChanges.forEach(change => {
      if (!balances[change.mint]) {
        balances[change.mint] = 0;
      }
      balances[change.mint] += change.amount;
    });
  });

  console.log(`Historical balances as of ${new Date(targetTimestamp * 1000).toLocaleString()}:`);
  Object.entries(balances).forEach(([mint, balance]) => {
    console.log(`${mint}: ${balance}`);
  });

  return balances;
};

// Example: Get balances on Jan 1, 2024
getHistoricalBalance(
  "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
  new Date("2024-01-01").getTime() / 1000
);
```

단일 토큰의 특정 시점에서의 정확한 잔액은 [Historical Balance](/docs/ko/wallet-api/balance-at) 엔드포인트를 사용하여 체인에서 직접 읽어옵니다. 클라이언트 측의 변동 합계를 사용하지 않습니다.

### 거래 수수료 분석

지불한 총 수수료를 계산하세요:

```javascript theme={"system"}
const analyzeFees = async (address) => {
  const transactions = await getAllTransactionHistory(address);

  const totalFees = transactions.reduce((sum, tx) => sum + tx.fee, 0);
  const avgFee = totalFees / transactions.length;

  const successfulTxs = transactions.filter(tx => !tx.error);
  const failedTxs = transactions.filter(tx => tx.error);

  const wastedFees = failedTxs.reduce((sum, tx) => sum + tx.fee, 0);

  console.log(`Total Transactions: ${transactions.length}`);
  console.log(`Successful: ${successfulTxs.length}`);
  console.log(`Failed: ${failedTxs.length}`);
  console.log(`Total Fees Paid: ${totalFees.toFixed(6)} SOL`);
  console.log(`Average Fee: ${avgFee.toFixed(6)} SOL`);
  console.log(`Wasted on Failed Txs: ${wastedFees.toFixed(6)} SOL`);

  return {
    totalFees,
    avgFee,
    wastedFees,
    successRate: (successfulTxs.length / transactions.length) * 100
  };
};
```

## 모범 사례

* **전체 기록을 위한 페이지 매김 사용.** 일부 지갑에는 수십만 건의 거래가 있으므로 모든 거래를 가져올 때 항상 페이지 매김을 사용하세요.
* **역사 데이터 캐시.** 과거 거래는 변경되지 않습니다. 로컬에 캐시하고 새 거래만 가져오세요.
* **실패한 거래 처리.** `error` 필드를 확인하여 성공 여부를 구분하세요. 실패한 거래도 수수료가 부과됩니다.
* **날짜 필터링을 위한 타임스탬프 사용.** 타임스탬프는 Unix 초로 제공됩니다. 표시 및 필터링을 위해 로컬 날짜로 변환하세요.

## 일반적인 오류

| 오류 코드 | 설명                  | 해결 방법                            |
| ----- | ------------------- | -------------------------------- |
| 400   | 유효하지 않은 지갑 주소 형식    | 주소가 유효한 base58 Solana 주소인지 확인하세요 |
| 401   | API 키 누락 또는 유효하지 않음 | 요청에 API 키가 포함되었는지 확인하세요          |
| 429   | 속도 제한 초과            | 요청 빈도를 줄이거나 플랜을 업그레이드하세요         |

## 다음 단계

<CardGroup cols={3}>
  <Card title="토큰 전송" icon="arrow-right-arrow-left" href="/docs/ko/wallet-api/transfers">
    발신자/수신자 정보를 포함한 전송 전용 보기 — 전체 기록보다 간단합니다.
  </Card>

  <Card title="Wallet API 개요" icon="wallet" href="/docs/ko/wallet-api/overview">
    모든 Wallet API 엔드포인트 및 공유 관례.
  </Card>

  <Card title="API 참조" icon="code" href="/docs/ko/api-reference/wallet-api/history">
    거래 기록에 대한 요청 및 응답 스키마.
  </Card>
</CardGroup>
