// injbook prints a live Injective order book and what a taker order of a // given size would cost against it. // // go run ./cmd/injbook -market INJ/USDT -side buy -qty 250 package main import ( "context" "flag" "fmt" "os" "strings" "time" "github.com/edwardtay/injective-booklab/book" "github.com/edwardtay/injective-booklab/client" "github.com/edwardtay/injective-booklab/dec" ) func main() { ticker := flag.String("market", "INJ/USDT", "market ticker, e.g. INJ/USDT or BTC/USDC PERP") sideS := flag.String("side", "buy", "buy or sell") qtyS := flag.String("qty", "100", "base quantity") depth := flag.Int("depth", 10, "levels to print per side") flag.Parse() side, err := book.ParseSide(*sideS) must(err) qty, err := dec.Parse(*qtyS) must(err) ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) defer cancel() c := client.New() ms, err := c.Markets(ctx) must(err) var m *client.MarketInfo for i := range ms { if strings.EqualFold(ms[i].Ticker, *ticker) { m = &ms[i] break } } if m == nil { must(fmt.Errorf("market %q not found among %d active markets", *ticker, len(ms))) } snap, err := c.Orderbook(ctx, m.Kind, m.ID, 100) must(err) b := snap.Book mid, _ := b.Mid() spread, _ := b.SpreadBps() fmt.Printf("%s (%s) seq %d via %s in %dms\nmid %s spread %s bps\n\n", m.Ticker, m.Kind, b.Seq, snap.Endpoint, snap.Ms, mid.Round(6), spread.Round(2)) for i := min(*depth, len(b.Asks)) - 1; i >= 0; i-- { fmt.Printf(" ask %18s %s\n", b.Asks[i].Price, b.Asks[i].Qty) } fmt.Println(" ----") for i := 0; i < min(*depth, len(b.Bids)); i++ { fmt.Printf(" bid %18s %s\n", b.Bids[i].Price, b.Bids[i].Qty) } r := book.SimulateTaker(b, side, qty, dec.Zero(), m.TakerFee) fmt.Printf("\n%s %s: filled %s over %d levels, VWAP %s, worst %s, slippage %s bps, fee %s, unfilled %s\n", side, qty, r.Filled, r.LevelsUsed, r.VWAP.Round(6), r.WorstPrice, r.SlippageBps.Round(2), r.Fee.Round(6), r.Unfilled) } func must(err error) { if err != nil { fmt.Fprintln(os.Stderr, "injbook:", err) os.Exit(1) } }