jarrodwatts/jev-trader on GitHub
- Stars
- 2,224
- Forks
- 425
- Language
- TypeScript
- License
- MIT
- Last push
- 17 Sep 2026
Read from GitHub on . Counts change daily.
Reported by the author
- Loop, mock model
- p50 100 ms
read p50 18 ms, whole loop p50 100 ms
github.com - Decision window
- ~300 ms/block
answers buy or sell every ~300 ms
github.com
jev-trader trades MON-USDC on the Kuru order book on Monad. Every block, about 300 milliseconds, it asks Jev a choice question: will MON be higher or lower than the current mid after a set number of blocks (100 by default, about 30 seconds)? Jev answers buy or sell with a probability for each. The bot posts a post-only limit order one tick inside the best price on that side and cancels whatever it had resting, so fills come from takers and the bot earns the spread instead of paying it. When the model misses a block, the decision is recorded as hold and nothing is posted.
The model sees a compact state: mid price, spread, book imbalance, depth at several distances from mid, the top five levels on each side, recent returns and recent taker trades. The prompt tells it taker flow is the strongest signal.
The hot path makes two RPC calls: one eth_call to read the order book and one eth_sendRawTransaction to place the order. The gas limit is fixed at startup and fees are static, so nothing is estimated per block; receipts and the fee estimate run on later blocks. In a dry run with a mock model standing in for Jev, the author measured a median of 18 milliseconds for the book read and 100 milliseconds for the whole loop, 80 of it the mock’s simulated inference time.
The public deployment runs in dry-run mode with the mock model. Setting MODEL=jev and TYPESAFE_AI_API_KEY switches to Jev; live orders also need a PRIVATE_KEY.
How it uses Jev
No direct call turned up in the code, so this is where it loads the SDK.
import { experimental_evaluate } from "ai";
import { typeSafeAi } from "@ai-sdk/typesafe-ai";
import { config } from "./config";
/** Models answer buy or sell. `hold` only appears on late blocks (no decision was made). */
export type Action = "buy" | "sell" | "hold";
/** What the model sees. Compact, relative, human-readable. */
