
jev-trader 如何捕获真实成交trades.ts 用 eth_getLogs 追踪 Maker 成交事件全解析【免费下载链接】jev-traderOne AI trade decision every Monad block. Jev on Kuru MON-USDC.项目地址: https://gitcode.com/gh_mirrors/je/jev-traderjev-trader 是部署在 Monad 链上的 AI 交易机器人AI 模型 Jev 每个 300ms 区块给出买/卖决策并以 post-only 限价单挂在 Kuru MON-USDC 订单簿上。它的订单是挂单等成交Maker成交来自别人打进来自己的交易回执里根本看不到。本文完整解析 trades.ts 如何用eth_getLogs轮询链上Trade事件捕获每一笔真实的 Maker 成交。为什么自己的回执里看不到成交传统思路是发单 → 等eth_getTransactionReceipt→ 判断成没成交。这只适用于 Taker主动吃单。而 jev-trader 的每一笔单都是 post-only 挂单成交发生在别人的 Taker 交易里别人的 Taker 买单打穿我们的卖单 → 成交记录在对方的交易中产生回执与我们无关。所以 jev-trader 换了个思路不盯自己的交易而是盯整条链的成交流。Kuru 订单簿合约每次撮合都会发出一个Trade事件只要轮询这些日志既能看到市场全部成交也能从中挑出打到我身上的那些。TradeFeed一个类抓住全部成交核心实现在 TradeFeed 类里它由 trader.ts 的attachTradeFeed挂上市场地址、RPC 地址、我们的钱包地址maker三个参数注入。整个捕获流程分三步。第一步用 topic0 锁定 Trade 事件事件签名和预计算的 keccak256 哈希直接写在模块顶部src/trades.ts#L20-L22Trade(uint40 orderId, address makerAddress, bool isBuy, uint256 price, uint96 updatedSize, address takerAddress, address txOrigin, uint96 filledSize)注意makerAddress、takerAddress等字段全部未做索引所以不能靠 topic 过滤我的成交只能把事件整体拉回来在内存里按地址比对。第二步分块轮询 eth_getLogs绕开公共节点限制rpc.monad.xyz公共节点拒绝跨度超过 100 个区块的eth_getLogs请求于是 poll() 做了三层防御src/trades.ts#L44-L49常量值作用FIRST_LOOKBACK300首次启动回看约 90 秒的成交热身窗口MAX_RANGE100每次eth_getLogs最多跨 100 块超出就切块MAX_CATCHUP1000断线恢复时单次最多补 1000 块防止一次性回放太多细节很讲究按块推进lastBlock切块循环里每拉完一块就更新游标中途失败也只损失当前块下次轮询从断点续传inFlight守卫上一次轮询还没跑完就直接丢弃新请求绝不并发也绝不抛异常——轮询永远不能拖垮 300ms 主循环removed: true的日志被回滚的区块直接跳过。第三步手动解码避开1e18 价格陷阱decode() 不用 SDK 而是手写解析 8 个 wordword(2)是isBuyword(3)是价格word(7)是成交量。这里藏着项目注释里反复强调的坑src/trades.ts#L9-L12Trade.price无论市场价格精度是多少链上都是 1e18 定点数。MON-USDC 市场的pricePrecision是 1e8若误用会把价格缩小一亿倍而filledSize才按sizePrecision1e10缩放。常量 TRADE_PRICE_DEC 固定为 18正是为了防这个错。 一箭双雕makerAddress 同时喂两个系统解码时做了一次地址比对src/trades.ts#L123makerAddress等于我们的钱包地址吗等于→ 这是一笔我们的真实成交连同orderId、updatedSize剩余未成交量一起塞进fills队列。方向还要翻转Taker 买单isBuy: true打的是我们的卖单所以记录为side: sell不等于→ 只是市场行情进入 500 条环形缓冲RING。同一份日志于是派生出两种价值给 AI 看summary() 聚合出窗口内的成交笔数、买卖量差CVD、VWAP、最新价和方向经 buildState 送入模型成为决策的动量特征给自己记账drainFills()src/trades.ts#L158-L160取出我们的成交交给 harvest() 更新持仓、已实现盈亏并通过 SSE 推给前端面板。从日志到面板fill 事件的完整链路整条数据流串起来是这样的eth_getLogs → decode() → fills 队列 → drainFills() → harvest() → liveFills() 核对订单簿 → applyFill() 记账 → onFill() → SSE fill 事件 → 前端成交带其中 liveFills() 还会用updatedSize同步订单簿状态部分成交就更新剩余数量全部成交updatedSize 0就摘掉这笔订单。注意轮询是挂在热路径之外的——trader.ts#L102 里poll(block).then(() this.harvest())不阻塞本块的读簿→决策→发单保证 300ms 预算不被日志拉取吃掉。 没有私钥也能验证dry run 模拟成交没配PRIVATE_KEY时进入 dry run订单不真正上链但成交判定逻辑完全一样——模拟单从下一区块开始挂在簿上一旦真实成交流里出现打穿其价格的打印simFills()就按打印数量成交事件里标simulated: true。真实成交与模拟成交走的是同一套判定规则这让策略在零资金下就能被完整验证。快速上手本地验证 trades.tscp .env.example .env bun install bun run scripts/trades-smoke.tstrades-smoke.ts 会真实回看约 1000 个区块的Trade日志打印 CVD/VWAP 汇总和最近 5 笔成交是检验eth_getLogs分块逻辑最快的冒烟脚本。配置项集中在 src/config.ts其中READ_RPC_URL专供日志轮询与读簿与发单通道RPC_URL分离。更多背景见 README.md 的 Endpoints 一节。小结jev-trader 捕获真实成交的关键不是盯自己的回执而是换视角轮询全链Trade日志topic0 过滤 100 块分片 断点续传一次解码两用途行情喂 AImakerAddress命中即真实成交精度纪律价格恒按 1e18 还原数量按sizePrecision还原不占热路径日志轮询与 300ms 决策循环解耦成交晚一两块到达也不影响下一单。这套模式对任何想做链上 Maker 策略的项目都通用只要合约在撮合时发带 maker 地址的事件eth_getLogs就是捕获真实成交最可靠、也最便宜的路径。【免费下载链接】jev-traderOne AI trade decision every Monad block. Jev on Kuru MON-USDC.项目地址: https://gitcode.com/gh_mirrors/je/jev-trader创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考