신규: Parsed Events Scan API를 사용해 보세요
Parsed Events Scan API 소개
블로그/업데이트

Parsed Events Scan API 소개

Developer Experience EngineerX의 0xIchigoLinkedIn의 0xIchigoGitHub의 0xIchigo
Software EngineerX의 Jacopo FrancavillaLinkedIn의 Jacopo Francavilla
읽는 데 11분

새로운 Helius Parsed Events Scan 엔드포인트는 모든 Solana 주소의 기록에서 필요한 트랜잭션을 찾아, 이미 파싱된 결과만 반환합니다. 자체 기록 파이프라인을 구축하지 않아도 프로그램, 명령어, 네이티브 SOL, 토큰 민트 또는 이들의 조합으로 필터링할 수 있습니다.

스캔 비용은 매우 저렴합니다. 요청당 10크레딧에 검색한 트랜잭션 1,000개당 1크레딧이 추가됩니다. 아래에서 공유하는 테스트에서는 스캔 엔드포인트가 최신 크리에이터 수수료 청구 10건을 찾기 위해 Pump.fun 트랜잭션 3,402개를 182ms 만에 검색했으며, 비용은 14크레딧이었습니다. 예를 들어 같은 트랜잭션을 getTransactionsForAddress로 가져오면 파싱 전부터 350크레딧, 즉 25배의 비용이 듭니다.

간단히 살펴보겠습니다.

Scan 엔드포인트가 나오기 전에는 주소 기록에서 특정 활동을 찾으려면 직접 파이프라인을 구축해야 했습니다.

  • 서명 페이지 가져오기
  • 각 트랜잭션 요청하기
  • 자체 파서로 디코딩하기
  • 필터 적용하기
  • 일치 항목을 충분히 찾을 때까지 반복하기

활동이 많은 주소에서는 일치 항목 하나를 찾기 전에 수천 개의 트랜잭션을 처리해야 합니다.

새로운 Helius Parsed Events Scan API 엔드포인트는 이 워크플로를 서버로 옮깁니다.

  1. 주소와 원하는 이벤트 조건을 전송합니다.
  2. API가 주소를 스캔하고 일치하는 트랜잭션을 파싱합니다.
  3. 일치하는 결과만 받습니다. 파싱된 트랜잭션, 서명 또는 개수를 받을 수 있습니다.

다음 기준으로 트랜잭션을 일치시킬 수 있습니다.

  • 프로그램(모든 명령어)
  • 프로그램과 명령어 이름
  • 프로그램과 원시 명령어 판별자
  • 한 요청에 여러 프로그램(최대 20개)
  • 토큰 민트 주소
  • 프로그램과 토큰 민트

Scan API는 슬롯, 시간, 서명 범위뿐 아니라 상태, 커미트먼트, 정렬 순서, 토큰 계정 필터도 지원합니다.

따라서 다음과 같이 범위를 좁힌 기록 쿼리에 유용합니다.

  • 프로그램의 모든 매수 또는 매도 명령어 찾기
  • Jupiter, DFlow, Pump.fun 같은 여러 온체인 거래 플랫폼에 걸친 지갑의 전체 거래 기록 찾기
  • 특정 기간에 지갑이 지정된 프로그램과 상호작용한 횟수 찾기
  • 명령어 판별자로 IDL이 없는 프로그램 검색하기
  • 디코딩된 프로그램 오류와 함께 프로그램 호출 실패 모니터링하기
  • 수수료 또는 매개변수 변경을 위해 프로그램의 관리 또는 구성 명령어 모니터링하기

Solana 프로그램 명령어로 스캔하기

다음 요청은 Pump.fun 프로그램 기록을 스캔하고 buy 또는 sell 명령어가 포함된 파싱된 트랜잭션을 반환합니다.

코드
curl --request POST \
  --url "https://mainnet.helius-rpc.com/v1/parsed-events/scan?api-key=$HELIUS_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "address": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
    "match": {
      "programs": [
        {
          "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
          "instructions": ["buy", "sell"]
        }
      ]
    },
    "limit": 100
  }'

이 요청을 사용해 Parsed Events Scan 데모 도구는 레코드 261개를 스캔하고 일치 항목 100개를 찾았습니다. 최신 이벤트 100개를 182ms 만에 반환했으며, 총비용은 11크레딧에 불과했습니다.

명령어 이름에는 알려진 모든 프로그램 IDL 버전의 표기 또는 snake_case 형식을 사용할 수 있습니다. Parsed Events Scan API는 최상위 명령어와 Cross-program Invocation(CPI)을 통해 호출된 내부 명령어를 모두 확인합니다.

프로그램에는 같은 작업의 여러 버전이 있는 경우가 많습니다. 예를 들어 Pump.fun의 IDL에는 buy, buy_exact_sol_in, buy_v2, buy_exact_quote_in_v2, sell, sell_v2 명령어가 있습니다. Scan API에서는 일치시킬 모든 명령어 이름을 나열할 수 있습니다.

Pump.fun 활동의 상당 부분은 매수와 매도이므로 일치 항목을 빠르게 찾을 수 있습니다. 필요한 활동이 드물수록 Scan으로 더 많은 비용을 절감할 수 있습니다. 예를 들어 크리에이터 수수료는 프로그램 트랜잭션에서 차지하는 비중이 매우 작습니다.

코드
curl --request POST \
  --url "https://mainnet.helius-rpc.com/v1/parsed-events/scan?api-key=$HELIUS_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "address": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
    "match": {
      "programs": [
        {
          "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
          "instructions": ["collect_creator_fee"]
        }
      ]
    },
    "limit": 10
  }'

Parsed Events Scan 데모 도구로 최신 청구 10건을 찾으면, 이 요청이 트랜잭션 3,402개를 182ms 만에 스캔하고 14크레딧을 사용한 것을 확인할 수 있습니다.

이에 상응하는 getTransactionsForAddress 호출에는 350크레딧이 필요합니다. 스캔 엔드포인트보다 25배 더 많은 비용입니다.

Solana 프로그램에 명명된 명령어가 포함된 IDL이 없다면 어떻게 하나요?

IDL이 없는 Solana 프로그램에 Parsed Events Scan API를 사용하려면 명령어 데이터 접두사로 일치시킬 수 있습니다.

각 판별자는 16진수로 인코딩된 바이트를 1개에서 8개까지 포함할 수 있습니다. 단일 프로그램에 이름과 판별자를 함께 사용할 수 있으며, 둘 중 하나만 일치해도 해당 명령어가 일치합니다. 예시는 다음과 같습니다.

코드
{
  "match": {
    "programs": [
      {
        "programId": "<PROGRAM_ADDRESS>",
        "discriminators": ["0x66063d1201daebea"]
      }
    ]
  }
}

여러 Solana 프로그램을 한 번에 스캔하기

단일 Parsed Events Scan API 요청에 최대 20개의 프로그램을 나열할 수 있으며, 트랜잭션이 그중 하나라도 호출하면 일치합니다.

예를 들어 다음 요청은 한 번의 스캔으로 지갑의 거래를 검색해 Jupiter, DFlow, Pump.fun에서 일치 항목을 찾습니다.

코드
{
  "address": "<WALLET_ADDRESS>",
  "match": {
    "programs": [
      {
        "programId": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
        "instructions": ["route", "shared_accounts_route", "route_v2", "shared_accounts_route_v2"]
      },
      { "programId": "DF1ow4tspfHX9JwWJsAb9epbkA8hmpSEAtxXy1V27QBH" },
      {
        "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
        "instructions": ["buy", "buy_exact_sol_in", "buy_v2", "sell", "sell_v2"]
      }
    ]
  }
}

토큰 민트로 스캔하기

Scan API는 각 트랜잭션의 실행 전후 토큰 잔액에서 민트 주소를 확인해 지정된 토큰 민트와 관련된 트랜잭션도 찾을 수 있습니다. 기본적으로 스캔한 주소에 속한 잔액만 집계합니다.

토큰을 기준으로 지갑을 스캔할 때는 tokenAccounts를 balanceChanged로 설정하세요. 들어오는 토큰 전송이 지갑 자체가 아닌 지갑의 토큰 계정에만 영향을 주는 경우가 많습니다. 따라서 기본적으로 해당 트랜잭션은 지갑 기록에서 제외됩니다.

예를 들어 다음 요청은 2026년 9월 Ansem의 wSOL 활동을 찾습니다.

코드
curl --request POST \
  --url "https://mainnet.helius-rpc.com/v1/parsed-events/scan?api-key=$HELIUS_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "address": "<ANSEM_WALLET_ADDRESS>",
    "match": {
      "mints": [{ "mint": "So11111111111111111111111111111111111111112" }]
    },
    "tokenAccounts": "balanceChanged",
    "time": {
      "gte": 1788220800,
      "lte": 1790812800
    }
  }'

Scan API는 총 7,555개의 트랜잭션을 스캔한 후 일치하는 트랜잭션 53개를 찾았습니다.

프로그램과 민트 조합하기

개발자는 programs와 mints를 모두 설정해 결과 범위를 좁힐 수 있습니다. 함께 사용하면 트랜잭션이 두 조건을 모두 충족해야 일치합니다. 하지만 프로그램 활동을 단일 토큰으로 좁힐 때는 필터보다 스캔하는 주소가 더 중요합니다.

예를 들어 특정 토큰의 모든 Pump.fun 거래를 찾으려면 Pump.fun 프로그램 대신 토큰의 민트 주소를 스캔하세요. 각 매수 또는 매도에는 민트가 계정으로 나열되므로 기본 설정으로 일치합니다.

코드
{
  "address": "<MINT_ADDRESS>",
  "match": {
    "programs": [
      {
        "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
        "instructions": ["buy", "buy_exact_sol_in", "buy_v2", "sell", "sell_v2"]
      }
    ]
  }
}

민트 기록에는 해당 토큰의 활동만 있지만 프로그램 기록에는 모든 토큰의 거래가 포함됩니다. 따라서 프로그램을 스캔하면 관련 없는 트랜잭션에 예산을 낭비하게 됩니다.

일치 범위 선택하기

기본적으로 프로그램의 명령어와 민트의 토큰 잔액은 스캔한 주소와 관련된 경우에만 집계됩니다. 주소가 토큰 계정을 소유하거나 해당 주소가 잔액의 민트인 경우 토큰 잔액이 주소와 관련된 것으로 간주됩니다. 다음 경우에는 명령어가 주소와 관련된 것으로 간주됩니다.

  • 명령어의 계정 중 하나가 해당 주소인 경우
  • 명령어의 계정 중 하나가 해당 주소가 소유한 토큰 계정인 경우
  • 해당 주소가 민트이고, 명령어의 계정 중 하나가 해당 민트의 토큰 계정인 경우
  • 해당 주소가 호출되는 프로그램인 경우

프로그램이나 민트에서 "scope": "transaction"를 설정하면 트랜잭션 내 어느 위치에 있든 집계할 수 있습니다. 주소가 수수료만 지불하거나, 멀티시그 트랜잭션을 실행하거나, 일치시키려는 명령어의 계정이 아닐 때 사용하세요.

예를 들어 다음 요청은 USDC도 이동시킨 토큰 트랜잭션을 찾습니다. 기본 범위에서는 USDC 잔액이 민트 주소에 속해야 하므로 아무것도 일치하지 않습니다.

코드
{
  "address": "<MINT_ADDRESS>",
  "match": {
    "mints": [
      { "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "scope": "transaction" }
    ]
  },
  "returnShape": "signatures"
}

프로그램에도 같은 일치 범위를 적용할 수 있습니다. 다음 요청은 릴레이어가 수수료를 지불한 Jupiter 스왑을 찾습니다.

릴레이어는 수수료 지불자로서 트랜잭션에 서명하기만 하므로 경로 명령어의 계정에 포함되지 않습니다. 따라서 기본 범위에서는 이러한 트랜잭션이 하나도 일치하지 않습니다.

코드
{
  "address": "<RELAYER_ADDRESS>",
  "match": {
    "programs": [
      {
        "programId": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
        "instructions": ["route", "shared_accounts_route", "route_v2", "shared_accounts_route_v2"],
        "scope": "transaction"
      }
    ]
  },
  "returnShape": "signatures"
}

제안을 실행하는 멀티시그 멤버에도 같은 논리가 적용됩니다. 멀티시그가 실행하는 명령어는 멤버의 계정이 아니라 볼트의 계정에 작용합니다. 따라서 멤버의 기록에서 해당 명령어를 스캔하려면 transaction 범위가 필요합니다.

네이티브 SOL 추적하기

네이티브 SOL에는 토큰 잔액이 없으므로 스캔은 lamport를 기준으로 일치시킵니다.

래핑된 SOL과 다른 네이티브 SOL 민트(So11111111111111111111111111111111111111111)를 전달하세요. 스캔한 주소의 SOL 잔액이 변경되면 트랜잭션이 일치하며, 주소가 지불한 수수료는 제외됩니다.

코드
{
  "address": "<WALLET_ADDRESS>",
  "match": {
    "mints": [{ "mint": "So11111111111111111111111111111111111111111" }]
  },
  "time": { "gte": 1788220800, "lt": 1790812800 }
}

이를 통해 Pump.fun 매도처럼 프로그램이 전송 명령어 없이 지급한 SOL을 포착할 수 있습니다. Jito 팁이나 계정에서 지불 또는 환불된 임대료 같은 부수적인 이동도 포착합니다.

파싱된 트랜잭션, 서명 또는 개수 가져오기

returnShape는 응답에 포함할 일치 결과를 설정합니다.

returnShape응답용도
transactions (기본값)data에 파싱된 일치 항목을 최대 limit개 포함디코딩된 명령어, 전송 및 요약 읽기
signatures모든 일치 항목의 signature, slot, transactionIndex, blockTime목록이 먼저 필요한 백필 및 인덱서
countdata 없음. scan.matchedTransactions가 개수활동 확인, 자격 검증, 분석 등

예를 들어 다음 요청은 트랜잭션을 반환하지 않고 2026년 9월 한 트레이더의 Pump.fun 매수 횟수를 계산합니다.

코드
{
  "address": "<WALLET_ADDRESS>",
  "match": {
    "programs": [
      {
        "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
        "instructions": ["buy", "buy_exact_sol_in", "buy_v2"]
      }
    ]
  },
  "returnShape": "count",
  "time": { "gte": 1788220800, "lt": 1790812800 }
}

개수를 계산할 때 signatures와 count는 limit를 무시하고 요청이 스캔하는 범위의 모든 일치 항목을 포함합니다. 긴 기록의 개수를 계산하려면 페이지를 계속 조회하면서 scan.matchedTransactions를 합산하세요.

세 가지 응답 형식의 비용은 모두 같습니다.

각 요청에서 스캔할 기록 범위 제어하기

한 번의 스캔은 요청당 최대 10,000개의 트랜잭션을 검사하고 최대 100개의 일치 항목을 반환할 수 있습니다.

budget.maxScannedTransactions 필드는 이 한도를 제어하며 기본값은 10,000입니다. limit 필드는 엔드포인트가 반환하는 일치 항목 수를 제어합니다. 1에서 100 사이의 값을 사용할 수 있으며 기본값은 100입니다.

일치 항목이 드물 수 있으므로 두 제어 값은 서로 독립적입니다. 즉, 요청이 수천 개의 트랜잭션을 스캔해도 일치 항목은 몇 개만 반환할 수 있습니다.

기본적으로 스캔 요청에는 성공한 트랜잭션만 포함됩니다.

실패한 트랜잭션을 포함하려면 status를 failed 또는 any로 설정하세요. 프로그램의 IDL에 오류가 정의되어 있으면 실패한 트랜잭션에 디코딩된 프로그램 오류가 포함됩니다.

스캔 요약

모든 응답에는 scan 요약이 포함됩니다.

코드
{
  "data": [],
  "paginationToken": "460903064:422",
  "scan": {
    "stoppedOn": "budget",
    "scannedTransactions": 2000,
    "matchedTransactions": 0,
    "scannedThrough": {
      "slot": 460903064,
      "blockTime": 1792856105
    },
    "creditsCharged": 12
  }
}

요약에서 다음 정보를 확인할 수 있습니다.

  • 스캔이 중단된 이유
  • 스캔한 트랜잭션 수
  • 일치한 트랜잭션 수
  • 스캔한 마지막 슬롯과 블록 시간
  • 요청에 사용된 크레딧 수

스캔 페이지네이션 작동 방식

스캔이 중단되면 scan.stoppedOn 필드에 이유가 표시됩니다.

  • windowEnd: 스캔이 기록 또는 범위의 끝에 도달함
  • limit: 응답에 요청한 수의 일치 항목이 포함됨
  • budget: 요청이 트랜잭션 스캔 예산에 도달함
  • deadline: 요청이 시간 제한에 도달함

응답에 paginationToken가 포함되면 다음 요청에 해당 토큰을 보내세요. 현재 data 배열이 비어 있어도 계속 진행해야 합니다. 빈 결과는 이후에 일치 항목이 없다는 의미가 아니라, 일치 항목을 찾기 전에 요청 예산을 모두 사용했다는 의미일 수 있습니다.

예를 들어 다음 루프는 지난 1시간 동안의 Pump.fun 거래를 수집합니다.

time 범위와 요청 한도가 전체 기록을 탐색하지 않도록 제한한다는 점에 유의하세요.

코드
const PUMP_PROGRAM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";
const ONE_HOUR_AGO = Math.floor(Date.now() / 1000) - 3600;
const MAX_REQUESTS = 50;

let paginationToken;
let requests = 0;

async function scanHistory() {
  const response = await fetch(
    `https://mainnet.helius-rpc.com/v1/parsed-events/scan?api-key=${process.env.HELIUS_API_KEY}`,
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        address: PUMP_PROGRAM,
        match: {
          programs: [{ programId: PUMP_PROGRAM, instructions: ["buy", "sell"] }],
        },
        time: { gte: ONE_HOUR_AGO },
        limit: 100,
        ...(paginationToken && { paginationToken }),
      }),
    }
  );

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  }

  return response.json();
}

do {
  const page = await scanHistory();
  requests++;

  for (const transaction of page.data) {
    console.log(transaction.signature);
  }

  paginationToken = page.paginationToken;
} while (paginationToken && requests < MAX_REQUESTS);

클라이언트 측 파이프라인 없이 파싱된 결과 받기

data의 각 항목은 Parsed Events Parse Transactions 엔드포인트와 동일한 TransactionResult 형식을 사용합니다. 가능한 경우 결과에 디코딩된 명령어, 전송, 계정 변경, 이벤트, 트랜잭션 요약 및 프로토콜별 파싱 데이터가 포함될 수 있습니다. 애플리케이션에 원본 Solana 트랜잭션 페이로드도 필요하면 rawTransaction를 "json", "jsonParsed" 또는 "base64"로 설정하세요.

가장 큰 차이는 기록 워크플로가 실행되는 위치입니다.

애플리케이션은 검색을 한 번 정의하기만 하면 됩니다. Parsed Events Scan API가 기록 페이지네이션, 일치 여부 확인, 파싱을 처리한 후 관련 트랜잭션을 반환합니다.

최신 Helius SDK 사용하기

Helius의 TypeScript 및 Rust SDK는 모두 Parsed Events API와 새로운 스캔 엔드포인트를 지원합니다.

TypeScript SDK는 스캔을 helius.parsedEvents.scan()로 제공합니다. 응답 유형은 전달된 returnShape를 따릅니다.

코드
const { scan } = await helius.parsedEvents.scan({
  address: "<WALLET_ADDRESS>",
  match: {
    programs: [{ programId: "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", instructions: ["buy", "sell"] }],
  },
  returnShape: "count",
});

console.log(scan.matchedTransactions, scan.stoppedOn);

Rust SDK의 helius.parsed_events()에서도 scan, scan_signatures, scan_count를 사용할 수 있으며, 모두 동일한 ScanRequest를 받습니다.

Parsed Events Scan API 요금

각 Parsed Events Scan API 요청 비용은 10크레딧에 스캔한 기록 페이지당 1크레딧이 추가됩니다. 기록 페이지 하나에는 최대 1,000개의 트랜잭션이 포함됩니다.

예를 들어 기본값인 트랜잭션 10,000개 예산을 사용하는 요청은 최대 20크레딧이 듭니다. 정확한 비용은 응답의 scan.creditsCharged에 표시됩니다.

비교하면 스캔 비용은 getTransactionsForAddress로 같은 기록을 페이지 단위로 가져오는 비용의 10분의 1입니다. getTransactionsForAddress는 페이지당 최대 1,000개의 트랜잭션에 100크레딧이 듭니다.

사용량 제어하기

사용량을 제어하려면 가능한 한 범위가 좁은 주소를 사용하고, 가능할 때 슬롯 또는 시간 범위를 추가하세요. 관련 없는 트랜잭션이 적을수록 각 요청에서 더 유용한 일치 항목을 찾을 수 있습니다.

Enhanced Transactions API를 Parsed Events API로 교체하기

Enhanced Transactions API는 유지보수 모드로 계속 사용할 수 있지만 새로운 파서 유형이나 기능은 추가되지 않습니다. 후속 API인 Parsed Events는 Helius의 IDL 카탈로그를 사용해 수천 개의 Solana 프로그램에서 명령어를 디코딩합니다. 아직 이전하지 않았다면 Parsed Events API로 마이그레이션하세요.

어떤 차이가 있나요?

Enhanced Transactions API는 활동을 스왑, 전송, NFT 판매 같은 고정된 트랜잭션 유형으로 분류합니다. 반면 Parsed Events Scan API는 프로그램 명령어, 원시 판별자, 토큰 민트 또는 이러한 조건의 조합을 사용해 더 정밀하게 검색할 수 있습니다. Helius는 주소 기록을 스캔하면서 이러한 필터를 적용하고 일치하는 트랜잭션만 파싱합니다.

Parsed Events API를 사용하면 개발자가 클라이언트 측 스캐너를 유지하지 않고도 더 많은 프로그램을 지원하고 기록 쿼리를 세밀하게 제어할 수 있습니다.

시작하기

필요한 온체인 활동은 알고 있지만 클라이언트 측 기록 스캐너를 직접 구축하고 유지하고 싶지 않다면 Parsed Events Scan API를 사용하세요. 전체 요청 스키마, 응답 필드, 한도, 오류 및 더 많은 예시는 Scan Transaction History API 레퍼런스에서 확인할 수 있습니다.

Scan API의 기능을 더 살펴보려면 Helius 대시보드의 새로운 Scan 도구를 확인하세요. 프로그램, 민트 및 다양한 필터를 기준으로 주소를 스캔해 보세요.

Helius 구독하기

최신 Solana 개발 소식을 확인하고 새 게시물 알림을 받아보세요

확대 이미지