見出し画像

ある時点のトークン量を知る方法

特定の条件で発生するエラーを調査するために、とある時点のトークン量を知る必要がありました。

やってみるとこれが意外に面倒だったのでメモしておきます。
ポイントは Dune を使って特定日時より後に生成された最初のブロックのブロック番号を取得するということです。

もっといい方法があれば教えて頂けるとありがたいです😄

調査対象

Orca の ORCA/USDC プールを調べます。

ターゲットの日時は 2022/08/08 05:23:24 とします。この時点で、このプールの保管用トークンアカウント(Vault) に、どれだけのトークンが入っていたのかを調べます。

上記から適当なトランザクションを選んで、調査に使うアカウントのアドレスを確認します。シンプルにスワップが成功しているものが読み解きやすいです。

このログで Orca Token Swap V2 の処理を見て、アドレスを拾います。

  • プール識別用の poolID
    2p7nYbtPBgtmY69NsE8DAW6szpRJn7tQvDnqvoEWQvjY

  • vault ($ORCAトークン用)
    9vYWHBPz817wJdQpE8u3h8UoY3sZ16ZXdCcvLB7jY4Dj

  • vault ($USDCトークン用)
    6UczejMUv1tzdvUzKpULKHxrK9sqLm8edR1v9jinVWm9

Pool Source / Pool Destination のそれぞれが $ORCA, $USDC 用のどちらかなのはスワップの方向性を見ることでわかりますし、実際にそのアカウントをクリックしてみれば Solscan からもわかります。

手軽な方法として、トークン量を確認する画面でトークンも確認できます。
「Token Balance Change」タブにはトランザクション前後のトークン量の変化がアカウントごとに示されています。

先程の Pool Source / Pool Destination がどちらのものなのか、ここから確認できます。また、「Balance After」がトランザクション後のトークン量です。

調査方法

調査方法

先程適当なトランザクションを選び、「Token Balance Change」からトランザクション後のトークン量を確認しました。

調査方法はこれと同様ですが、適当なトランザクションを選ぶのではなく、ターゲットの日時である 2022/08/08 05:23:24 以前で、なるべく新しいものを選びます。

ターゲット日時の周辺で次のトランザクションがあったら、2 を選びます。

  1. 2022/08/08 05:22:59

  2. 2022/08/08 05:23:22

  3. 2022/08/08 05:24:01

使うツール

使うツールは以下の通りです。

  • Solscan

  • Solscan API

  • Dune

調査

1. Solscan API

Solscan API のドキュメント兼お試し画面を開きます。

/account/transactions を開き、「Try it out」で入力できるようにします。

account に poolID のアカウントのアドレスを入れます。
これにより、poolID を含むトランザクションを探すことができます。

問題は beforeHash です。
beforeHash で指定したトランザクションより前に処理されたトランザクションを探してくれるので、ターゲット日時直後のトランザクションを1つは手に入れなければなりません。

2. Dune

beforeHash を手に入れるために Dune を使います。
Dune をつかって、ターゲット日時の直後に生成されているブロックを探します。そのブロックがわかれば、その中に含まれるトランザクションを適当に1つ選べばよいです。

新規クエリとして、下記を入力します。

SELECT
  min(slot)
FROM
  `solana`.`blocks`
WHERE
  time > '2022-08-08 05:23:24'::timestamp
;

クエリエンジンとして「7. Dune Engine V2 (Beta)」を選び、「Run」で実行します。

結果としてブロックのID (145062910) が得られれば成功です。
シンプルな処理なので、実行されれば短時間(1分以内)で返ってきます。

3. Solscan

Solscan にブロックのID「145062910」を入力し、ブロックの情報を表示します。ブロック生成日時が「2022/08/08 05:23:25」なのでターゲット日時の1秒後です。

このブロックから適当なトランザクションを選びます。先頭の1つを選びハッシュ値を取得します。

4XYbtXWUiFYV7HoMeJzWeGaahdPt8FkUsZc5YuzSDARZ1MDZSSpSATeV4qp9Vy8rAVrKKdYv4eTLqvoXrQCUdiyi

4. Solscan API

先ほど入力していなかった beforeHash に取得したトランザクションのハッシュ値を入れて、「Execute」で実行します。

Response body にトランザクションの一覧が表示されるのを待ちます。
タイムアウトしたときは「 [ ] 」と表示されるので、再度「Execute」から実行します。

得られたトランザクションの一覧の先頭からハッシュ値を取得します。

5vbMRGPzyvyKtbivcRT9ELtuRkTJFzcUDoPbFYaoxEPVWD6x7ssY4MRGyXv32gTmVdwn4AaK7AWaoF5NXWij7t2r

5. Solscan

再び Solscan で、得られたトランザクションの詳細を確認します。

トランザクションの実行日時は「2022/08/08 05:21:34」でターゲット日時より前のものです。

そして、「Token Balance Change」を確認すると、$ORCA トークンと $USDC トークンのトークン量が確認できます。

  • $ORCA: 1,732,766.917527

  • $USDC: 1,715,895.375293

補足

Dune を使う理由

最初、Dune を使わずに、@solana/web3.js のみでターゲット日時直後のブロックを探そうとしました。

下記のメソッドを使えば、スロット番号(ブロック番号でもある)からブロックの生成日時が確認できます。

そのため、バイナリサーチなどを使えば見つけられると考えましたが罠がありました。

ブロックが生成されなかったスロットについては、getBlockTime はエラーを返してきます。その場合、手がかりなしになってしまい検索が進められません。1, 2 ブロック生成されなかっただけであれば、前後を探してみればよさそうです。障害で長時間ブロックが作られなかった場合はより厄介です。

このあたりを考えるのを避け、このぐらいのクエリなら Dune もすぐ返してくれるのでは・・・という期待で Dune を使い、期待通りでした。

この記事が気に入ったらサポートをしてみませんか?