Skip to content
System One

jev-trader

Makes one AI trade decision every Monad block on the Kuru MON-USDC market using Jev. The public deployment runs in dry-run mode with a mock model.

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 msread p50 18 ms, whole loop p50 100 msgithub.com
Decision window
~300 ms/blockanswers buy or sell every ~300 msgithub.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. */

View in src/model.ts

Open on GitHub

More like this

Use cases this is tagged with