見出し画像

Blocknative Mempool APIの使い方


はじめに

この記事は 仮想通貨botter Advent Calendar 2022 6日目の記事です。

はじめまして、5000兆円欲しい5000e12です。
2021年12月から給付金、richmanbtcさんのMLbotなど参考に参戦しました。
多くのbotterのようにテクニカル・MLを用いたトレードやDEXでのアビトラなどはあまりせずに、NFTをセールで買って二次流通で売るみたいなことを主にしていました。
QASHさんのツイートでいうところの2番の劣化版で、コミュニティで情報を集め、手動でやっていても儲かるものを自動化するというパターンが多かったように思います。

今回はそのようなちょっとした技術力があれば勝つことができる人にとって役立つツールの一つである、BlocknativeのMempool APIの使い方を書いていきます。

Mempool APIが使えれば条件さえ整えばこんなことができます。

  • NFTのセールで買って二次流通で売って差額で儲ける

  • 初期の売り圧がないトークンを運営の流動性追加後すぐに買える

Blocknative Mempool APIの使い方

API発行

まずblocknativeのアカウントを発行します。発行したアカウントでログイン後、右上の名前のところをクリックし「Account」をクリックします。
My API KeysのところにAPI Keyがあるのでそれを利用します。アカウント発行後にDefault keyが一つあるのでそれを使ってもいいですし、Add new API keyで新規発行しても問題ないです。

サンプルコード

さっそくですが、特定メソッドが呼ばれるまで待機するコードの全体像です。これをコピペするだけでも動作します。
依存ライブラリはwebsocketsのみです。

import asyncio
from datetime import datetime
import json

from websockets.client import connect

API_KEY = "<発行したAPI Key>"

def generate_base_params():
    return {
        "timeStamp": datetime.now().isoformat(), "dappId": API_KEY,
        "version":"4.3.0",
        "blockchain": {"system":"ethereum", "network": "goerli"},
    }


async def main():
    async with connect('wss://api.blocknative.com/v0') as ws:
        res = await ws.recv()
        print(json.loads(res)['status'])

        await ws.send(json.dumps(generate_base_params() | {'categoryCode': 'initialize', 'eventCode': 'checkDappId'}))
        res = await ws.recv()
        print(json.loads(res)['status'])

        await ws.send(json.dumps(generate_base_params() | {'categoryCode': 'configs', 'eventCode': 'put', 'config': {
            'abi': [{'inputs':[{'internalType':'bool','name':'flag','type':'bool'}],'name':'runWithBool','outputs':[],'stateMutability':'nonpayable','type':'function'}],
            'filters': [{'contractCall.methodName': 'runWithBool', 'contractCall.params.flag': True}],
            'scope': '0xADf258F11DCb632121380F06f15cC3B144B10f59',
            'watchAddress': True,
        }}))
        res = await ws.recv()
        print(json.loads(res)['status'])

        res = await ws.recv()
        print(res)



asyncio.run(main())

細かくコードを分割して説明していきます。

def generate_base_params():
    return {
        "timeStamp": datetime.now().isoformat(), "dappId": API_KEY,
        "version":"4.3.0",
        "blockchain": {"system":"ethereum", "network": "goerli"},
    }

websocket経由でリクエストを送る時、共通して付与するパラメータを生成する関数です。詳細は下記ドキュメントのパラメータ一覧を見てください。
https://docs.blocknative.com/websocket#required-parameters

async def main():
    async with connect('wss://api.blocknative.com/v0') as ws:
        res = await ws.recv()
        print(json.loads(res)['status'])

メインの処理部分について説明していきます。
blocknativeのwebsocketエントリポイントに接続すると、接続出来たかどうかのレスポンスが返ってきます。
以降、レスポンスに含まれているstatusキーにokかerrorが入っているので、リクエストが間違っていないかどうかを判断することができます。

        await ws.send(json.dumps(generate_base_params() | {'categoryCode': 'initialize', 'eventCode': 'checkDappId'}))
        res = await ws.recv()
        print(json.loads(res)['status'])

dappIdに指定したAPI Keyが正常であるかのチェックを行っています。
このリクエストがないと、後続の設定が行えません。

        await ws.send(json.dumps(generate_base_params() | {'categoryCode': 'configs', 'eventCode': 'put', 'config': {
            'abi': [{'inputs':[{'internalType':'bool','name':'flag','type':'bool'}],'name':'runWithBool','outputs':[],'stateMutability':'nonpayable','type':'function'}],
            'filters': [{'contractCall.methodName': 'runWithBool', 'contractCall.params.flag': True}],
            'scope': '0xADf258F11DCb632121380F06f15cC3B144B10f59',
            'watchAddress': True,
        }}))
        res = await ws.recv()
        print(json.loads(res)['status'])

このリクエストでどのようなコントラクトにどのような条件でトランザクションが発行された場合、通知するかの設定をします。
今回の例だと、「0xADf258F11DCb632121380F06f15cC3B144B10f59 のコントラクトに対して、runWithBool関数を引数がtrueで呼ばれた場合」という条件を設定しています。
今回サンプルコードに利用したコントラクトは以下になるので、そのまま実行してみたり引数を代えてみたり実験してみてください。

https://goerli.etherscan.io/address/0xADf258F11DCb632121380F06f15cC3B144B10f59

        res = await ws.recv()
        print(res)

この最後のレスポンス待ちのコードは、上記で設定した条件に当てはまるトランザクションがmempoolに入ってきた時にレスポンスが返ってきます。
このコードの後にNFTをmintする処理やトークンを買ったりする処理をいれることで、早くトランザクションを投げるようなコードが出来上がります。

トランザクションを投げる場合の考慮すべき点

これで簡単にあるコントラクトのあるメソッドが呼び出されたら、〇〇をする!ということができるようになりました。
例えば後続処理でトランザクションを投げる場合、以下のように考えなければいけない点があります。

  • どのノードに投げる?

    • 適当なノードに投げるとトリガーとなったトランザクションより2ブロックぐらいずれたりする。

  • ガス代はどうする?

    • いっぱい盛ると最悪トリガーとなるトランザクションを追い抜いてしまう

    • 少なくすると競合の人たちに抜かされてしまう

自分もまだまだ経験不足で試行錯誤している段階なので、ここらへんの考察した記事をどなたか書いてくれることを望んでおきます。

さてどこで使おうか

mempool APIの使い方はわかった!さぁどこで使おうか・・・
自分でイチから調べたり、たくさんあるコミュニティの中から自分に合ったもので情報を集めるなど、色んな戦い方があると思います。
自分の場合は、イチから情報を精査する能力がないので、Kudasaiで共有される情報を元に行動しています。

https://twitter.com/kudasai_japan

最後に

だらだらと書いてきましたが、この市況の中でこのコード使う機会は頻繁に発生しないと思います。しかし、局所的に発生するかもしれない儲かるチャンスに向けて、このMempool APIを含めた様々なツールについて活用できる状態になっていることが重要だと思っています。
厳しい市況ですが、技術・ツールについて知見を深めて、次なるバブルで大きく勝っていきましょう✊

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