新着: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 クレジットかかります。以下で紹介するテストでは、Scan エンドポイントが 3,402 件の Pump.fun トランザクションを検索し、直近 10 件のクリエイター手数料請求を 182 ms で取得しました。使用したのは 14 クレジットです。たとえば、同じトランザクションを getTransactionsForAddress で取得すると、解析前の時点で 350 クレジット、つまり 25 倍のコストがかかります。

概要を簡単にご紹介します。

Scan エンドポイントが登場する以前は、アドレス履歴から特定の種類のアクティビティを見つけるために、次のパイプラインを自分で構築する必要がありました。

  • 署名のページを取得する
  • 各トランザクションをリクエストする
  • 独自のパーサーでデコードする
  • フィルターを適用する
  • 十分な一致が得られるまで繰り返す

利用頻度の高いアドレスでは、一致を見つけるまでに数千件ものトランザクションを処理しなければなりません。

新しい Helius Parsed Events Scan API エンドポイントは、この処理をサーバー側へ移します。

  1. 対象のアドレスとイベント条件を送信する
  2. API がアドレスをスキャンし、一致するトランザクションを解析する
  3. 一致した結果だけを受け取る(解析済みトランザクション、署名、または件数)

トランザクションは次の条件で照合できます。

  • プログラム(任意の命令)
  • プログラムと命令名
  • プログラムと生の命令ディスクリミネーター
  • 1 回のリクエストに複数のプログラム(最大 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 件のイベントを 182 ms で返し、合計コストはわずか 11 クレジットでした。

命令名には、既知のプログラム IDL の任意のバージョンにある表記、または snake_case 形式を使用できます。Parsed Events Scan API は、最上位の命令と、クロスプログラム呼び出し(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 件のトランザクションを 182 ms でスキャンし、14 クレジットを使用したことがわかります。

同等の getTransactionsForAddress 呼び出しには 350 クレジットがかかり、Scan エンドポイントの 25 倍のコストになります。

Solana プログラムに命令名を含む IDL がない場合はどうなりますか?

IDL のない Solana プログラムで Parsed Events Scan API を使用する場合は、代わりに命令データのプレフィックスで照合できます。

各ディスクリミネーターには、16 進数でエンコードされた 1~8 バイトを含められます。1 つのプログラムに対して名前とディスクリミネーターを組み合わせることができ、命令はいずれかに一致すれば対象になります。例:

コード
{
  "match": {
    "programs": [
      {
        "programId": "<PROGRAM_ADDRESS>",
        "discriminators": ["0x66063d1201daebea"]
      }
    ]
  }
}

複数の Solana プログラムを一度にスキャンする

1 回の Parsed Events Scan API リクエストに最大 20 件のプログラムを指定でき、そのいずれかを呼び出すトランザクションが一致します。

たとえば、次のリクエストは 1 回のスキャンで、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 の両方を設定して、結果を絞り込めます。組み合わせた場合、トランザクションが一致するには両方の条件を満たす必要があります。ただし、プログラムのアクティビティを 1 つのトークンに絞る場合は、フィルターよりもスキャン対象アドレスの選択が重要です。

たとえば、特定のトークンに関するすべての Pump.fun 取引を検索するには、Pump.fun プログラムではなく、そのトークンのミントアドレスをスキャンします。各購入または売却ではミントがアカウントとして列挙されるため、デフォルトで一致します。

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

ミントの履歴にはそのトークンのアクティビティだけが含まれます。一方、プログラムの履歴にはすべてのトークンの取引が含まれるため、プログラムをスキャンすると無関係なトランザクションに予算を浪費します。

一致範囲を選択する

デフォルトでは、プログラムの命令とミントのトークン残高は、スキャン対象アドレスに関係する場合だけ対象になります。アドレスがトークンアカウントを所有している場合、またはアドレスが残高のミントである場合、そのトークン残高はアドレスに関係すると見なされます。命令がアドレスに関係すると見なされる条件は次のとおりです。

  • 命令のアカウントの 1 つがそのアドレスである
  • 命令のアカウントの 1 つが、そのアドレスの所有するトークンアカウントである
  • アドレスがミントであり、命令のアカウントの 1 つがそのミントのトークンアカウントである
  • アドレスが呼び出されるプログラムである

トランザクション内のどこにあっても対象にするには、プログラムまたはミントで "scope": "transaction" を設定します。アドレスが手数料を支払うだけの場合、マルチシグ tx を実行する場合、または照合する命令のアカウントではない場合に使用します。

たとえば、次のリクエストは 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"
}

同じロジックは、提案を実行するマルチシグメンバーにも当てはまります。マルチシグが実行する命令は、メンバーのアカウントではなく Vault のアカウントを操作します。そのため、メンバーの履歴をスキャンするには transaction 範囲が必要です。

ネイティブ SOL を追跡する

ネイティブ SOL にはトークン残高がないため、スキャンでは lamport に基づいて照合します。

ラップド SOL とは異なるネイティブ SOL ミント(So11111111111111111111111111111111111111111)を渡します。スキャン対象アドレスの SOL 残高が、支払った手数料分を除いて変化した場合にトランザクションが一致します。

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

これにより、Pump.fun での売却など、プログラムが転送命令なしで支払う SOL を検出できます。また、Jito チップや、アカウントに支払われた、またはアカウントから返金された rent など、付随的な移動も検出します。

解析済みトランザクション、署名、または件数を取得する

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 を合計します。

3 つの形式はすべて同じ料金です。

各リクエストでスキャンする履歴の量を制御する

1 回のスキャンで最大 10,000 件のトランザクションを確認し、最大 100 件の一致を返せます。

budget.maxScannedTransactions フィールドはこの上限を制御し、デフォルトは 10,000 です。limit フィールドはエンドポイントが返す一致件数を制御します。1~100 の値を指定でき、デフォルトは 100 です。

一致がまばらな場合もあるため、この 2 つは個別に制御できます。つまり、1 回のリクエストで数千件の tx をスキャンしても、一致が数件しか返らない場合があります。

デフォルトでは、スキャンリクエストには成功したトランザクションだけが含まれます。

失敗したトランザクションを含めるには、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 を使用する

TypeScript と Rust の両方の SDK が、Parsed Events API と新しい Scan エンドポイントに対応しています。

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 履歴ページには最大 1,000 件のトランザクションが含まれます。

たとえば、デフォルトの 10,000 トランザクションの予算を使用するリクエストは、最大 20 クレジットです。正確な料金は、レスポンスの scan.creditsCharged で確認できます。

比較すると、スキャンのコストは、同じ履歴を getTransactionsForAddress でページングする場合の 10 分の 1 です。後者は 1 ページ(最大 1,000 トランザクション)あたり 100 クレジットかかります。

使用量を制御する

使用量を抑えるには、実用上可能な限り対象を絞ったアドレスを使用し、可能であればスロットまたは時刻の範囲を追加します。無関係なトランザクションが少ないほど、各リクエスト内で有用な一致を多く取得できます。

Enhanced Transactions API を Parsed Events API に置き換える

Enhanced Transactions 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開発の最新情報や新しい記事の公開通知を受け取れます

拡大画像