CosmosOsmosisアービトラージ
created at
CosmosアビトラBotの作り方 その1【コード付き】
初めまして。Cosmos上でのアービトラージBotの作成方法について何回かの記事に分けて解説していきたいと思います。
なぜCosmos チェーン?
Dex上でアービトラージをやる上で最もメジャーなのはEthereumやPolygonのようなEVM互換のあるチェーンです。こういったチェーンではWeb3.pyのような便利なツールがあるだけでなく、ネット上にも様々な解説記事が上がっており、開発難易度は非常に低いです。ですが、この開発難易度が低いということは逆に言えば競合が多いということでもあります。
Cosmos上で存在する様々なチェーン
Cosmosは一般的なイメージでのブロックチェーンと違い、どちらかというとプラットフォームのようなイメージに近いものです。Cosmos上でOsmosisチェーンやKAVAチェーンといったブロックチェーンが存在し、それらがIBCという技術によってつながっています。これらのチェーンはEVM界でいうところのブリッジと比べ、セキュリティ面で非常に優れています。このIBCを使ったチェーン間のアービトーラジは手間がかかるものの、そこにはまだ収益機会がまだ残っています。これもCosmosチェーンにターゲットを絞る理由の一つとなります。
対象読者
Defi上の基本的な用語の解説は省略していきます。一応Dex Bot未経験の方にもわかるように書いていく所存です。
また、この界隈にはPythonしか使えない!といったBotterの方々も多いと思います。ですが、CosmosにはWeb3.pyのような初心者向けツールは用意されていません。CosmosチェーンはCosmos SDKと呼ばれるGo言語で書かれた開発キットがあり(EthereumでいうところのGeth)、これを用いて開発することも多いため、今回はGo言語を使っていきます。もちろんPythonでプールの情報を取得したり、トランザクションを送ることもできます。GoじゃなくてPythonやNode.jsでBotを作りたいという方は適宜コードを変えて試してみてください。
序編:Osmosis上でのAtomicアービトラージ
まずはCosmos上でもっとも流動性が高くメジャーなチェーンであるOsmosisチェーン上でAtomicArb(同一トランザクションでのアービトラージ)Botを開発していきます。これがCosmosのDebotの基本形となります。
必要な情報をバリデータから取得する。
まずはバリデータからAPIを通じて必要な価格情報を取得することから始めましょう。自分自身がバリデータになる方法は後編で解説します。
Osmosis上のバリデータのリストはMintscanなどで確認できます。メジャーなバリデータは大体APIを公開しているのでまずはそれを使ってプールの情報を取得していきます。
import ( "encoding/json" "fmt" "io/ioutil" "net/http" ) type PoolAssets struct { Type string `json:"@type"` Id string Pool_params struct { Swap_fee string Exit_fee string } Pool_assets [2]struct { Token struct { Denom string Amount string } Weight string } } type PoolDetails struct { Pools []PoolAssets }
Go言語ではこのように型定義をします。APIから情報を取ってくる場合はまずはCurlなどで情報をあらかじめ取得しておき、それが格納できるように箱を作っていきます。
次にnet/httpというパッケージを使ってAPI情報を取得していきます。
func GetPoolAll() PoolDetails {
var url string
url = "https://api.osl.zone/osmosis/gamm/v1beta1/pools?pagination.limit=880".
// url = "https://api-osmosis-ia.cosmosia.notional.ventures/osmosis/gamm/v1beta1/pools?pagination.limit=880"
resp, err := http.Get(url)
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var poolMap PoolDetails
json.Unmarshal(body, &poolMap)
return poolMap
}
urlには各々のバリデータが公開しているアドレスを使ってください。Botを動かすサーバーの場所によって通信速度も変わってきますので、色々なAPIを試して選択されることをお勧めします。その他は一般的なGo言語でのAPIの取り方となります。
また、Osmosisのプールの中にはアクティブでないプールも多く含まれているため、これらを除くコードもあった方がよいかもしれません。今回はGetActivePools()という関数を作り、とあるバリデータが公開しているAPIを使って監視するプールの数を絞っていきます。また、このAPIの呼び出しは最初の一回のみなので速度面には影響しません。
type PoolCandidates struct {
Symbol string `json:"symbol"`
Denom string `json:"denom"`
Price float64 `json:"price"`
Fees string `json:"fees"`
}
//計算量を抑えるため、流動性の少ないプールを除いたプールを使う。
func GetActivePools() map[int][2]PoolCandidates {
resp, err := http.Get("https://api-osmosis.imperator.co/pools/v2/all?low_liquidity=false")
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var poolMap map[int][2]PoolCandidates
json.Unmarshal(body, &poolMap)
return poolMap
}
このAPIを使用するもう一つの利点はDenomの情報をとることができます。これによって各々のコインの価格の桁数を合わせることができます。
ではmain.goを用意してこれらの関数を呼び出し、価格情報を取得してみましょう。
func main() {
active_pools := GetActivePools()
whole_pools := GetPoolAll()
}
次回からは、Go言語の特徴の一つである構造体を用いてこれらの情報を整形して使えるようにしていきます。また、Atmic Arbにおける典型なアルゴリズムであるベルマンフォード法の解説と実装までできればと考えています。
質問や訂正などあればTwitter(X)のDMまでよろしくお願いいたします。
↓その2です