アカウントモデルのコンテキスト
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フィルタに加えて、アカウントサブスクリプションは結果をさらに絞り込むための追加のフィルタリングオプションをサポートしています:
特定アカウントフィルタリング
公開鍵で正確なアカウントを監視します:組み合わせたフィルタリング戦略
力は複数のフィルタータイプを組み合わせることから来ます。以下はメンタルモデルです:- 幅広くカバーする - 「このプログラムによって管理されているすべてのアカウントをください」
- 構造でフィルタリングする - 「しかし、この特定のタイプのアカウントのみ」
- 特定のデータを対象にする - 「そして、この特定の情報を含むもののみ」
- 既知のアカウントを監視する - 「または、私が気にしているこれらの正確なアカウントのみを監視します」
大局的な理解
アカウントサブスクリプションは、データベースの変更をライブで見ることと考えてください。Solanaの状態は本質的に巨大なキー値ストアで、各アカウントはエントリーです。プログラムが実行されると、これらのアカウントが変更されます。サブスクリプションによって、特定のエントリーのリアルタイムでの変更を見ることができます。 フィルタリングシステムはデータベースインデックスのように機能します。「すべての変更」を見るのではなく、「これらの基準に合致するアカウントへの変更」を見るのです。これにより、関連性のないデータでシステムを圧迫することなく、迅速に反応するアプリケーションを構築できるようになります。他のプログラムへのこのパターンの適用
学んだアプローチは、任意のSolanaプログラムに対して機能します。以下が一般的なパターンです:- アカウント構造を調査する - プログラムのソースコードまたはドキュメントを確認
- オーナーフィルタリングから始める - アカウントを管理するプログラムをターゲットに
- 構造的フィルタを適用する - アカウントのサイズ、データパターン、またはその他の特徴を使用して特定のアカウントタイプに絞り込む
- ターゲットフィルタを追加する - アプリケーションにとって重要な特定のアカウント、状態、またはデータ値に集中する