概要
Solana ブロックチェーンは、データをシーケンシャルな追記専用台帳に保存します。これはデータの整合性とトランザクションのスループットには優れていますが、大きな代償も伴います。履歴データのクエリが非常に非効率になり、実用に耐えないほど遅くなります。 複雑な処理では、多くの場合、複数のソースからのデータをフィルタリング、集約、または結合する必要があります。このような場合、Solana に直接クエリを実行する方法は、ほとんどの実用的なアプリケーションに適していません。 この問題を解決するため、ほとんどの企業は Solana の履歴データのプライベートインデックスを構築しています。 このガイドでは、ライフサイクル全体を説明します。getTransactionsForAddress やその他のアーカイブ RPC メソッドによる履歴データのバックフィル、データベースの選択、リアルタイムストリーミングによるインデックスの最新状態の維持を取り上げます。
使用する場面
次の場合はインデックスを構築します。- プロダクトで高速なフィルター付きクエリが必要で、直接の RPC 呼び出しでは遅すぎる場合(例:ウォレットのトークンアカウントと残高、取引ペアの完全な履歴)
- オンチェーンデータのフィルタリング、集約、結合、またはオフチェーンデータ(CEX の価格、KYC、ラベル)との組み合わせが必要な場合
- 前処理済みでクエリ可能なデータを必要とする PnL、保有者分析、NFT 販売履歴などを計算する場合
- 多数のユーザーにサービスを提供しており、チェーンに対するリクエストごとのレイテンシーを許容できない場合
Solana データのインデックス化とは何ですか?
インデックス化とは、Solana ブロックチェーンからデータをクエリしてバックエンドデータベース(PostgreSQL、ClickHouse など)に保存するプロセスです。これにより、Solana RPC 呼び出しを使用してブロックチェーンに直接クエリすることなく、顧客のリクエストに迅速に応答できます。 インデクサーは通常、次の 4 つの処理を行います。- 履歴データをバックフィルする: アーカイブ RPC メソッドを使用して、すべての履歴データをクエリします
- 新しいデータをストリーミングする: ネットワークによって確認された新しいブロックを処理します
- データを解析・変換する: 確認済みブロックから関連データ(トランザクション、状態変更など)を抽出します
- データをデータベースに整理する: 新しいデータでインデックスを更新します
多くの企業が Solana インデックスを構築する理由
企業が Solana インデックスを構築するのは、ネイティブ RPC では提供されない用途固有のブロックチェーンデータ(NFT 販売履歴など)へ高速かつリアルタイムにアクセスできることが、ビジネスに不可欠だからです。 また、企業はカスタムインデックスを活用して、オフチェーンデータ(中央集権型取引所の価格、KYC 情報など)とオンチェーンデータを組み合わせています。ウォレットの例
たとえば、Solana ウォレットがユーザーのトークンアカウントと残高を迅速に返す必要がある場合、getTokenAccountsByOwner と getTokenAccountBalance を使用して Solana に直接クエリすると遅すぎるため、プロダクトが使用不能になる可能性があります。その代わり、ウォレットは通常、顧客のアドレス、トークン、アカウント残高について独自のインデックスを維持します。
取引の例
同様に、暗号資産取引会社は、取引アルゴリズムをバックテストするため、特定の取引ペア(例:SOL-USDC)または特定の市場で発生するすべての取引活動を記録したい場合があります。 このデータをブロックチェーンに直接クエリする方法は、実用的な取引分析には遅すぎます。その代わり、クオンツトレーダーは SOL-USDC 市場のインデックスを構築し、LaserStream などのリアルタイムストリーミングプロダクトを使用して最新の取引で更新し続けることができます。フィルタリングの例
ユーザーがフロントエンドアプリケーションで、特定の条件(トークンの種類、送金額、日付、ウォレットアドレスなど)に基づいてトランザクションをフィルタリングしたい場合を考えてみます。 インデクサーがない場合、アプリは数十万のブロックにまたがる数百万件のトランザクションを走査し、それぞれがフィルター条件に一致するかを確認する必要があります。 この処理は、最新プロダクトのユーザー体験には遅すぎます。PnL の例
トレーダーの損益(PnL)を計算するには、次の処理が必要です。- 指定期間内にウォレットに関連付けられたすべてのトランザクションを検索する
- スワップトランザクションを抽出し、買いまたは売りとしてラベル付けする
- 各スワップでユーザーが支払った手数料を特定する
- 各取引時点における各トークンの履歴価格データを取得する
- 各トランザクションの PnL を集約し、トレーダーの合計 PnL を計算する
ステップ 1:履歴データを取得する
Solana インデックスを構築する最初のステップは、必要なすべての履歴データを取得することです。 これには主に 3 つの方法があります。方法 1:getTransactionsForAddress(推奨)
getTransactionsForAddress RPC メソッドを使用すると、ブロックチェーンデータの任意の範囲について、完全なトランザクション詳細を取得できます。強力なフィルタリング機能により、インデックスに不要なデータの取得に時間を浪費しません。また、逆方向検索機能により、トランザクションを時系列順で取得できます。
この方法を使用する手順
- データが必要な期間を決定し、それに応じてフィルターを設定します
- すべてのトランザクション詳細を取得するため、
transactionDetailsをfullに設定します - 必要に応じて、関連トークンアカウントのトランザクションを含めるように
tokenAccountsフィルターを設定します paginationTokenを使用して結果をページネーションします- 各反復で必要なデータを抽出し、データベースに保存します
getTransactionsForAddress を使用する利点
gTFA エンドポイントを使用する主な利点は、速度とシンプルさです。スロットおよび時間ベースのフィルター、トークンアカウントのサポート、逆方向検索、ページネーションにより、複雑なループや再試行ロジックなしで、Solana の履歴にある任意の時点から必要なデータを 1 回の呼び出しで取得できます。getSignaturesForAddress とは異なり、そのアドレスが所有する関連トークンアカウントが関与するトランザクションも含められます。
インデックスがトークンとネイティブ SOL の移動(支払い、台帳、残高照合)に特化している場合、getTransfersByAddress は完全なトランザクションではなく、解析済みで照合に使用できる転送行を返すため、解析ステップを省略できます。
方法 2:getSignaturesForAddress と getTransaction
gTFA がリリースされる前は、getSignaturesForAddress を使用して署名を新しいものから古いものへ再帰的にループし、getTransaction を呼び出して完全なトランザクション詳細を抽出する方法が、履歴データをクエリする標準的なアプローチでした。
この方法を使用する手順
この方法を使用する基本的な手順は次のとおりです。getSignaturesForAddressを呼び出します- この呼び出しで最後に受信したトランザクションの署名を保存します
getSignaturesForAddressの次の呼び出しでは、beforeパラメーターをこの署名に設定します- 必要な限りループで繰り返します
- この方法で取得した各トランザクション署名について、
getTransactionを呼び出して完全なトランザクション詳細を取得します - 関連データをデータベースに挿入します
この方法の欠点
残念ながら、この方法を使用するには次の対応が必要です。- 最新のトランザクションから開始し、過去にさかのぼります
- トランザクションごとに追加の RPC 呼び出しを 1 回実行します
- 並行処理に対応するスレッドセーフなキューを構築します
- データの欠落やレート制限を防ぐため、再試行とバックオフのロジックを構築します
- アドレスが所有する関連トークンアカウントが関与するトランザクションは含まれません
getTransactionsForAddress を使用してください。
方法 3:getBlock を使用する
getBlock メソッドは、対象ブロック内のトランザクションの多くが分析に関連する場合に最も効果的です。たとえば、DFlow の Aggregator、Pump.fun プログラム、Solana の Token プログラムなど、頻繁に使用される Solana プログラムのトランザクションをインデックス化する場合です。
この方法を使用する手順
getBlock で履歴データをクエリする基本的なプロセスは次のとおりです。
- クエリする期間を決定します
- この期間をスロット番号に変換します
- 対応するブロックを順番に取得します(順方向または逆方向)
- 各ブロックについて、インデックスに関連するトランザクションをフィルタリングします
- そこから関連情報をインデックスに保存します
ステップ 2:Solana データをデータベースと同期する
履歴データを取得したら、変換してデータベースに効率的に保存する必要があります。 ストレージは、具体的なユースケースに合わせて選択してください。あらゆる状況に適した単一のソリューションはありません。適切なデータベースは、データセットのサイズ、レイテンシー要件、クエリパターン、チームの専門知識によって異なります。選択肢 1:SQL データベース
ほとんどのユースケースでは、Solana データを PostgreSQL などのリレーショナルデータベースに保存することを推奨します。SQL は柔軟で広く普及しており、習得も容易です。最新のリレーショナルデータベースは 1 億行を超える規模まで拡張でき、ACID 準拠、複雑な結合、強力なセカンダリインデックスといった利点も提供します。 プロトタイピング、ローカル開発、または単一ファイルのデータベースを設定なしで使用したい場合は、SQLite を使用してください。データセットが数ギガバイト未満に収まる場合に最適です。 データレプリケーション、複数クライアントからの同時アクセス、全文検索や JSON 演算子などの高度な機能が必要な本番アプリケーションには、PostgreSQL を使用してください。 本番レベルの Solana インデクサーの多くでは、PostgreSQL を推奨します。実装例:
例として、トークン転送を PostgreSQL データベースに保存する方法を示します。 まず、テーブルを作成します。選択肢 2:カラムナーデータベース
カラムナーデータベースは、分析クエリ、集約、大量の時系列データ向けに最適化されています。数十億件のトランザクションをインデックス化する必要がある場合、ClickHouse や Cassandra などのカラムナーデータベースが最適です。 大規模なデータセットに対してリアルタイム分析クエリが必要な場合は、ClickHouse を使用してください。高速な読み取り、集約、時系列分析向けに最適化されています。 非常に高い書き込みスループット、容易な水平スケーリング、高い耐障害性が必要な場合は、Cassandra を使用してください。大量の Solana データを継続的に取り込む用途に最適です。実装例:
トークン転送を ClickHouse データベースに保存する方法を示します。 この目的では、MergeTree テーブルエンジンを使用するテーブルを作成します。高い取り込みレート向けに設計されているため、インデックス化に最適です。 次のコマンドを使用します。(token_mint, date) を主キーとソートキーの両方に設定します。ClickHouse はソートキーに従ってディスク上のデータを並べます。これは、単一のトークンミントをクエリし、日付範囲でレスポンスを絞り込む場合に最適です。
クエリの例を次に示します。
FixedString(N) データ形式を使用して保存されます。ClickHouse はデータを自動的に圧縮するため、ストレージコストを 10~20 分の 1 に削減し、クエリ性能を向上させます。
クエリ性能を最適化するには、マテリアライズドビューを使用して一般的な集約を事前計算してください。
たとえば、ダッシュボードの取引量関連チャートで使用するために、トークンの日次転送量を事前計算できます。
選択肢 3:データレイク
データレイクは、長期アーカイブや分析クエリのために、大量の未加工および処理済みブロックチェーンデータを保存する用途に最適です。 シンプルな実装では、Parquet データ形式と Amazon Athena を使用します。 Parquet は、効率的なデータ保存と取得のために設計された列指向のデータファイル形式です。 Amazon Athena は、インフラストラクチャをセットアップしたり、別のデータベースにデータを読み込んだりすることなく、標準 SQL を使用して Amazon S3 に保存されたデータを分析できる対話型クエリサービスです。実装例:
トークン転送のアーカイブを作成し、クエリできるようにします。 まず、S3 に保存する必要があります。solana_index という名前のバケットを作成し、次のキー構造を使用してトークン転送データを時間単位でパーティション化します。
インデックス化フレームワークを使用する
Carbon などのフレームワークを使用すると、定型コードの記述を避け、数日ではなく数時間でインデクサーをセットアップできます。主な機能:
- 一般的なプログラム(Token プログラム、DeFi プロトコル、Metaplex)用の構築済みデコーダー
- 設定可能なデータソース(RPC、LaserStream、Enhanced WebSockets)
- バックフィルとリアルタイムストリーミングの両方を標準サポート
- 複数のストレージバックエンドへの出力(Postgres を標準でサポート)
- 完全にカスタマイズ可能:独自のデータソース、デコーダー、データシンクをセットアップできます
ステップ 3:インデックスを最新の状態に保つ
履歴データをバックフィルした後、新しいブロックチェーンアクティビティに合わせてインデックスを最新の状態に保つには、リアルタイムストリーミングソリューションが必要です。これがないと、インデックスの情報が古くなります。方法 1:LaserStream(推奨)
すべての本番環境のインデックス化ユースケースでは、デフォルトの選択肢として LaserStream gRPC を推奨します。信頼性、超低レイテンシー、耐障害性を備えたデータストリーミング専用に設計されています。 LaserStream を使用する利点には、次のようなものがあります。- 24 時間の履歴リプレイ:インデクサーが切断された場合、LaserStream は中断した位置から欠落したすべてのトランザクションを自動的にリプレイします
- 自動再接続:LaserStream SDK(Rust、Go、JS/TS)がネットワーク中断をシームレスに処理します
- ノードフェイルオーバー:LaserStream 接続は複数のノードからのデータを同時に集約し、最大限の稼働時間を確保します
インデックス化で LaserStream を使用する方法
subscribe メソッドを使用して、ブロックチェーンイベントをサブスクライブします。
ベストプラクティスをいくつか示します。
- フィルターを可能な限り絞り込む:帯域幅の消費と必要な処理を最小限に抑えるため、実際にインデックス化する必要があるデータのみをサブスクライブします
confirmedコミットメントレベルを使用する:レイテンシーとファイナリティーのバランスを取れます。processedレベルは信頼性が低すぎる可能性があり、finalizedでは ~13 秒のレイテンシーが追加されます- 失敗したトランザクションを追跡する必要がある場合を除き、
failed: falseを設定します - インデックス化には関係しないため、投票トランザクションを除外します(
vote: false)
方法 2:LaserStream WebSocket を使用する
LaserStream WebSocket は、Helius 固有のtransactionSubscribe 拡張機能を含む LaserStream の WebSocket 版です。LaserStream gRPC と同じバックエンドで動作し、gRPC が不要な場合に費用対効果の高いリアルタイムストリーミングの代替手段となります。
次の場合は LaserStream WebSocket を使用してください。
- アプリケーションが時折発生するデータ欠落を許容できる場合
- リアルタイム更新が重要ではあるものの、ミッションクリティカルではない場合
- 欠落データを検出してバックフィルする既存のインフラストラクチャがある場合
- 予算上の制約が大きく、ストリーミングコストを最小限に抑える必要がある場合
- LaserStream の導入を決定する前に、プロトタイピングまたはテストを行う場合
- 速度:LaserStream WebSocket は LaserStream gRPC と同じバックエンドで動作しますが、WebSocket プロトコルでは JSON フレーミングとメッセージごとのオーバーヘッドが追加されます。同じデータで可能な限り低いレイテンシーを実現するには、LaserStream gRPC を使用してください
- 信頼性:履歴リプレイは保証されません。WebSocket が切断された場合、RPC メソッドを使用して欠落を手動で検出し、バックフィルする必要があります
- 複雑さ:データの完全性を確保するため、追加の監視インフラストラクチャが必要です
インデックス化で WebSocket を使用する方法
すべてのトークン転送を保存するインデックスを更新するには、次のようにtransactionSubscribe をサブスクライブします。
始める
堅牢な Solana インデックスを構築してデータをバックフィルするには、次の 3 つの主要な課題を解決する必要があります。- 履歴データを効率的に取得する
- 迅速に取得できるようデータを変換して保存する
- インデックス化した Solana データをリアルタイムで最新の状態に保つ
getTransactionsForAddress などのアーカイブ呼び出し、LaserStream などの業界をリードするデータストリーミングソリューションにより、Solana インデックスの構築はこれまで以上に簡単で実用的になりました。
補完的な選択肢
独自のインデックスを運用すると完全に制御できますが、常に必要とは限りません。一般的なニーズでは、マネージド Helius API でカスタムインデックスを置き換えたり補完したりできます。- DAS API — アセットデータを自分でインデックス化することなく、NFT、代替可能トークン、圧縮アセット(メタデータ、所有権、残高、所有者・コレクション・作成者別)をクエリできます。
- Wallet API — ウォレット残高、履歴、転送、ID のための高レベル REST エンドポイントです。USD 換算額を含み、よりシンプルなレスポンス形式を提供します。
次のステップ
- API にアクセスするため、無料の Helius アカウントに登録します
- バックフィルについては、getTransactionsForAddress ガイドを参照してください
- リアルタイムストリーミングについては、LaserStream の概要を確認してください
- すべてのアーカイブ方法については、履歴データの概要を参照してください