アカウントモデルのコンテキスト
Solanaのアカウントとその構造に詳しい場合、このセクションはスキップしてください。
- データ: プログラムの状態、トークン残高、その他の情報を格納する実際のバイト
- オーナー: このアカウントを制御し、そのデータを修正できるプログラム
- Lamports: 家賃免除のためのアカウントのSOL残高
- 実行可能: このアカウントがプログラムコードを含むかどうか
基本的なアカウントサブスクリプション
トークンアカウントの変更を購読するシンプルな例から始めましょう。このスクリプトはトークンの残高が変わるたびに通知します:BKMHWYLAX4un3HUbR7a3u9jPmzCiLNa4mSj1RiX11eWFについて更新を受け取りました。
このアカウントに含まれるのは:
- 2,039,280ラマポート(約0.002 SOLの残高 - これはこのトークンアカウントの家賃免除額です)
- オーナープログラム
TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA(これはSPLトークンプログラムです) - トランザクション署名
5C9Hr5nG2j8eQz6inxPmfyjbYdmXddzUDyR1iQgEnjYQ3RNvuP4Zzc8t1enLNy7Rk8KNCtQPEQztENYWxkt9GaVD(このアカウントの変更を引き起こした特定のトランザクションを示します) - スロット352366983(この更新がブロックチェーン上で発生したときのもの)
- データフィールド(base58でエンコードされた165バイトのアカウントデータが含まれます)
データサイズを用いたアカウントフィルタリングの理解
データフィールドは重要です - 実際のトークンアカウントの構造を含んでいるからです。スマートアカウントフィルタリングのためにこの理解を活用しましょう。なぜデータサイズフィルタリングを使うのか
フィルタリングが必要な理由を理解するために、まずトークンアカウントが何であるかを理解しましょう。ウォレットが保有する各トークンについて、オンチェーン上に別個のアカウントがあります。 ウォレットが3つの異なるトークンを持っている場合(USDC、BONK、SOL)、実際には1つのウォレットアカウント(メインのSOLアカウント)と3つのトークンアカウント(各トークンタイプごとに1つ)があります。各トークンアカウントはちょうど165バイトであり、どのトークンを保持しているか(ミントアドレス)、誰が所有しているか(ウォレットアドレス)、およびそのトークンの量(量)が格納されています。 トークンプログラムはSolana上に何百万ものアカウントを持っていますが、それらすべてがユーザーのバランスを保有する「トークンアカウント」ではありません。フィルタリングの有無で何が起こるかを見てみましょう: フィルタリングなし - 大洪水:- トークンアカウント(165バイト)- ユーザーのバランス: 数百万のアカウント
- ミントアカウント(82バイト)- トークン定義: 数十万のアカウント
- マルチシグアカウント(355バイト)- 共有ウォレット制御: 数万のアカウント
- 関連トークンプログラムアカウント(さまざまなサイズ)- 数百万のアカウント
- フィルタリングなし: 数百万のアカウント更新(ミント作成、マルチシグの変更など)
- データサイズフィルタリングあり: トークン残高の変更のみ
なぜ165バイトなのか
これは魔法ではありません - SPLトークンプログラムのアカウント構造から来ています。ソースコードを見ると、Accountの構造体がちょうど165バイトで定義されていることがわかります:
- ミントアカウント(82バイト)
- マルチシグアカウント(355バイト)
- 関連トークンアカウントプログラムアカウント
- 異なるサイズの他のトークン関連アカウント
アカウント構造のデコード
165バイトをフィルタリングした理由を理解したうえで、例のアカウント内の内容をデコードしましょう:- バイト0-31: ミントアドレス(このアカウントが保有するトークン)
- バイト32-63: オーナーアドレス(このトークンアカウントの所有者)
- バイト64-71: トークン量(アカウントに含まれるトークン数)
- バイト72-164: 追加メタデータ(代理人、状態、クローズオーソリティなど)
フィルタの組み合わせ: データサイズ+memcmpでレーザ精度
ミントアドレスがバイト0-31にあることがわかったので、さらに特定の情報に絞り込むことができます。例えば、USDCトークンアカウントのみを監視したい場合、datasizeフィルターをmemcmpフィルターと組み合わせて、特定のミントアドレスをターゲットにできます:
- オーナーフィルター: “トークンプログラムが所有するアカウントを教えて”(数百万のアカウント)
- データサイズフィルター: “だが165バイトの標準トークンアカウントのみ”(数十万)
- Memcmpフィルター: “そしてUSDCを保有するもののみ”(数千)
USDCアカウント更新の読み取り: 誰が、どのくらい、どこで?
これらのフィルタリングされた更新には実際に何が含まれるかを見てみましょう。トークンアカウントが変わったときに重要な質問に答えるUSDC専用モニターを作成します:- 誰がこのトークンアカウントを所有していますか?
- どのくらいの量のUSDCが含まれていますか?
- どこに(どの特定のアカウントが)変わりましたか?
- いつこの変化が起こりましたか?
- どのトランザクションがこの変化を引き起こしましたか?
bs58.encode()関数を使用します。
完全なフィルタリングリファレンス
これまでに使用した基本的なowner、datasize、memcmpフィルタに加えて、アカウントサブスクリプションは結果をさらに絞り込むための追加のフィルタリングオプションをサポートしています:
特定アカウントフィルタリング
公開鍵で正確なアカウントを監視します:組み合わせたフィルタリング戦略
複数のフィルタタイプを組み合わせることによりパワーが発揮されます。こちらはメンタルモデルです:- 広範なネットをキャストする
owner- “このプログラムが管理するすべてのアカウントを教えて” - 構造でフィルタリングする
datasize- “だが特定のタイプのアカウントのみ” - 特定のデータをターゲットにする
memcmp- “そして特定の情報を含むもののみ” - 既知のアカウントを監視する
account- “または私が重要だと思う正確なアカウントを監視するだけ”
大きな図を理解する
アカウントサブスクリプションはデータベースの変更のライブフィードを監視するようなものです。Solanaの状態は基本的に巨大なキー・バリューストアであり、各アカウントがエントリです。プログラムが実行されると、これらのアカウントが変更されます。サブスクリプションにより、特定のエントリがリアルタイムで変更されるのを監視できます。 フィルタリングシステムはデータベースインデックスのように機能します - 単に「すべての変更」を監視するのではなく、「これらの基準に一致するアカウントの変更」を監視しているのです。これにより、システムを無関係なデータで圧倒することなく、関連するオンチェーンイベントにすぐに応答するアプリケーションを構築することが可能になります。このパターンを他のプログラムに適用する
習得したアプローチは、どのSolanaプログラムにも適用できます。こちらが一般的なパターンです:- アカウント構造を調査する - プログラムのソースコードまたはドキュメントを確認
- オーナーフィルタリングから始める - アカウントを管理するプログラムをターゲットに
- 構造的フィルタを適用する - アカウントのサイズ、データパターン、またはその他の特徴を使用して特定のアカウントタイプに絞り込む
- ターゲットフィルタを追加する - アプリケーションにとって重要な特定のアカウント、状態、またはデータ値に集中する