Skip to content

Add MEV-Share client module (closes #34)#63

Merged
koko1123 merged 1 commit into
mainfrom
feat/mev-share
Jun 10, 2026
Merged

Add MEV-Share client module (closes #34)#63
koko1123 merged 1 commit into
mainfrom
feat/mev-share

Conversation

@koko1123

@koko1123 koko1123 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

What

mev_share.MevShareClient — the MEV-Share searcher/user surface from #34, mirroring mev-share-client-ts:

  • sendTransactioneth_sendPrivateTransaction (delegates to the Relay support from Add eth_sendPrivateTransaction support (closes #40) #62)
  • Event stream: on(callback) drives sse_transport over the hint stream; parseEventData is a pure function producing PendingEvent (transaction/bundle) with hash, logs, calldata, selector, to, value
  • simulateBundlemev_simBundle with SimBundleOpts (parentBlock, blockNumber, coinbase, timestamp, gasLimit, baseFee, timeout) and parsed SimBundleResult (profit, mevGasPrice, refundableValue, gasUsed, logs)
  • getEventHistoryGET /api/v1/history with block/timestamp/limit/offset filters
  • initMainnet convenience (relay.flashbots.net + mev-share.flashbots.net); free helpers for all heap-owning results

Tests

19 unit tests (event fixtures incl. malformed, exact-JSON params assertions, result parsers, history queries) plus a refAllDeclsRecursive test that forces semantic analysis of the network paths — no more lazily-hidden API breakage (the failure mode behind #55/#60). Wire shapes verified against the Flashbots docs; three unverifiable details are marked TODO in code.

Docs

New guide docs/content/docs/mev-share.mdx (first flashbots/MEV docs page) with a backrun-loop sketch; registered in nav; docs build passes (20/20 pages).

Verification

zig build/test/fmt --check on 0.16.0 and build test on 0.17.0-dev: pass. CodeRabbit reviewed: its one finding on this diff claimed Writer.buffered() doesn't exist in 0.16 — it does (lib/std/Io/Writer.zig:155), and the new refAllDecls test proves the path compiles.

Closes #34

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added MEV-Share client supporting private transaction sending with hint preferences, bundle simulation with results interpretation, SSE event streaming with automatic reconnection, and historical event querying.
  • Documentation

    • Added comprehensive MEV-Share documentation covering client initialization, transaction and bundle operations, event consumption, and helper functions.

mev_share.MevShareClient wraps flashbots.Relay with the MEV-Share
searcher surface, mirroring mev-share-client-ts:

- sendTransaction: delegates to Relay.sendPrivateTransaction
- Event stream: PendingEvent (transaction/bundle) parsed from the SSE
  hint stream via sse_transport; blocking on(callback) loop
- simulateBundle (mev_simBundle) with SimBundleOpts/SimBundleResult
- getEventHistory (GET /api/v1/history) with query params

flashbots.Relay.authenticatedRequest and buildMevSendBundleParams are
now pub for reuse. 19 unit tests cover event parsing, params builders
(exact-JSON), result parsers, and history queries; a refAllDecls test
forces semantic analysis of the untested network paths so lazily
compiled API breakage cannot hide (lesson from the 0.16 migration).

Unverified wire details are marked TODO in code: simBundle timeout
encoding, sim-result error field name, nested bundleLogs (only txLogs
parsed).

New docs page docs/content/docs/mev-share.mdx with a backrun-loop
sketch; docs build passes (20/20 pages).
@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
eth-zig Ready Ready Preview, Comment Jun 10, 2026 2:33pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a complete MEV-Share client for Zig that mirrors the TypeScript reference implementation. The module enables private transaction backrunning and bundle simulation on Ethereum via MEV-Share's SSE event stream and JSON-RPC APIs. Supporting changes expose relay authentication and bundle parameter helpers from flashbots.zig to avoid duplication.

Changes

MEV-Share Client Implementation & Documentation

Layer / File(s) Summary
Relay Helper API Exposure
src/flashbots.zig
Relay.authenticatedRequest and buildMevSendBundleParams are made public and documented for reuse by MEV-Share client logic for signed requests and bundle parameter construction.
MEV-Share Type System & Memory Management
src/mev_share.zig
Endpoint URL constants, error set, and pending transaction/bundle/event types are defined; freeing functions recursively release allocated hint data, logs, and dynamic arrays.
SSE Event Payload Parsing
src/mev_share.zig
parseEventData decodes SSE data: lines into PendingEvent, classifying entries as transactions or bundles and parsing optional calldata, selector, address, and value fields.
Bundle Simulation Types & Parameter Construction
src/mev_share.zig
SimBundleOpts and SimBundleResult types model mev_simBundle requests and responses; buildSimBundleParams splices bundle JSON and conditionally appends hex-encoded simulation options.
Bundle Simulation & History Response Parsing
src/mev_share.zig
parseSimBundleResult validates JSON-RPC structure and maps result/error fields with nested log parsing; parseEventHistoryResponse parses history array entries; JSON helpers decode hex and u256 fields.
MevShareClient & Public Methods
src/mev_share.zig
Client struct initializes relay auth and HTTP client; sendTransaction submits signed tx; simulateBundle builds params and parses results; blocking on consumes SSE stream with callback invocation and per-event cleanup; getEventHistory queries and parses historical hints.
Unit Test Coverage
src/mev_share.zig
Tests verify event parsing, simulation parameter encoding, response parsing (success/error/RPC error/null), history query construction, history response parsing, client endpoint initialization, and all public declarations compile.
Documentation, Changelog & Module Export
CHANGELOG.md, docs/content/docs/meta.json, docs/content/docs/mev-share.mdx, src/root.zig
Changelog documents MEV-Share functionality; docs navigation includes new page; comprehensive guide covers initialization, transaction submission, SSE semantics, bundle simulation, history queries, and memory management; module is exported from root and included in test compilation.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant MevShareClient
  participant Relay
  participant MevShare_SSE
  participant MevShare_API

  User->>MevShareClient: initMainnet(auth_key)
  MevShareClient->>MevShareClient: init relay + http client

  User->>MevShareClient: sendTransaction(opts)
  MevShareClient->>Relay: authenticatedRequest(eth_sendPrivateTransaction)
  Relay->>MevShare_API: POST /eth/sendPrivateTransaction
  MevShare_API-->>Relay: tx hash
  Relay-->>MevShareClient: hash
  MevShareClient-->>User: [32]u8

  User->>MevShareClient: on(callback)
  MevShareClient->>MevShare_SSE: subscribe event stream
  MevShare_SSE-->>MevShareClient: data: {...hash, txs, logs...}
  MevShareClient->>MevShareClient: parseEventData
  MevShareClient->>User: callback(PendingEvent)
  User->>MevShareClient: process event, return
  MevShareClient->>MevShareClient: freePendingEvent

  User->>MevShareClient: simulateBundle(opts, sim_opts)
  MevShareClient->>MevShareClient: buildSimBundleParams
  MevShareClient->>Relay: authenticatedRequest(mev_simBundle)
  Relay->>MevShare_API: POST /mev/simBundle
  MevShare_API-->>Relay: {success, mev_gas_price, profit...}
  Relay-->>MevShareClient: result json
  MevShareClient->>MevShareClient: parseSimBundleResult
  MevShareClient-->>User: SimBundleResult

  User->>MevShareClient: getEventHistory(params)
  MevShareClient->>MevShareClient: buildHistoryQuery
  MevShareClient->>MevShare_API: GET /api/v1/history?...
  MevShare_API-->>MevShareClient: [{block, timestamp, hint}, ...]
  MevShareClient->>MevShareClient: parseEventHistoryResponse
  MevShareClient-->>User: []EventHistoryEntry
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • #34: This PR directly implements the MEV-Share client module and all API surface (MevShareClient, SSE on, sendTransaction, simulateBundle, getEventHistory) required by the issue specification, including event types and memory management helpers.

Possibly related PRs

  • StrobeLabs/eth.zig#62: The main PR's sendTransaction capability is wired to the MEV-Share private transaction JSON-RPC support (eth_sendPrivateTransaction types/methods) added to flashbots.Relay in that PR.
  • StrobeLabs/eth.zig#48: The main PR's MEV-Share SSE event streaming implementation (SSE parsing, line-by-line event handling, reconnect behavior) directly builds on the retrieved PR's sse_transport module APIs.
  • StrobeLabs/eth.zig#32: The main PR's mev_share.zig reuses helpers from flashbots.zig (Relay.authenticatedRequest and buildMevSendBundleParams) that were made public in that PR to support MEV-Share client logic.

Poem

🐰 A share of MEV, now swift and bright,
No TypeScript bounds—pure Zig takes flight!
Backrun bundles, history in stream,
Flashbots' fastest, a searcher's dream.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add MEV-Share client module (closes #34)' clearly and specifically summarizes the main change: addition of a new MEV-Share client module that resolves the linked issue.
Linked Issues check ✅ Passed The PR fully implements all coding requirements from issue #34: MevShareClient with sendTransaction, on (event stream subscription), simulateBundle, getEventHistory methods; PendingEvent/PendingTransaction/PendingBundle types; authentication reuse; endpoint constants; heap management helpers; comprehensive tests.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #34: new mev_share.zig module, documentation, changelog entry, test infrastructure, and public API exposures in flashbots.zig and root.zig to support MEV-Share functionality. No unrelated changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/mev-share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/mev_share.zig (1)

28-33: ⚡ Quick win

Add the missing Sepolia default alongside the mainnet helpers.

Line 31 already exports sepolia_stream_url, but callers still have to hardcode the Sepolia relay URL because only mainnet_relay_url and initMainnet() exist. That leaves the “network defaults for mainnet and Sepolia” objective only half exposed and leaks a literal into the docs example.

Suggested API addition
 pub const mainnet_stream_url = "https://mev-share.flashbots.net";
 /// MEV-Share SSE event stream + history API (Sepolia).
 pub const sepolia_stream_url = "https://mev-share-sepolia.flashbots.net";
 /// Flashbots relay JSON-RPC endpoint (mainnet).
 pub const mainnet_relay_url = "https://relay.flashbots.net";
+/// Flashbots relay JSON-RPC endpoint (Sepolia).
+pub const sepolia_relay_url = "https://relay-sepolia.flashbots.net";
@@
     /// Convenience constructor for Ethereum mainnet.
     pub fn initMainnet(allocator: std.mem.Allocator, auth_key: [32]u8) MevShareClient {
         return init(allocator, mainnet_relay_url, mainnet_stream_url, auth_key);
     }
+
+    /// Convenience constructor for Ethereum Sepolia.
+    pub fn initSepolia(allocator: std.mem.Allocator, auth_key: [32]u8) MevShareClient {
+        return init(allocator, sepolia_relay_url, sepolia_stream_url, auth_key);
+    }

Also applies to: 369-372

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mev_share.zig` around lines 28 - 33, Add a Sepolia relay constant and a
Sepolia initializer to mirror the existing mainnet helpers: define
sepolia_relay_url (matching the relay endpoint used for Sepolia) alongside
mainnet_relay_url and add an initSepolia() function (parallel to initMainnet())
that wires sepolia_stream_url and sepolia_relay_url into the same setup flow;
then update the network-defaults usage sites (the code around the other
defaults, e.g., the block referenced at 369-372) to use initSepolia() or
sepolia_relay_url instead of a hardcoded Sepolia URL so callers no longer need
to embed literals.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/mev_share.zig`:
- Around line 259-262: The SimBundle wire-shape must serialize
SimBundleOpts.timeout as an unquoted JSON number under simOptions and must parse
failure text from result.error when success==false; update the code that builds
the outbound JSON to put the timeout value (the field timeout: ?u64 in the
SimBundleOpts/struct) inside the simOptions object and emit it as a numeric JSON
value (not a quoted string), and update the response handling logic that
consumes the simulation result to check result.success and, when false, read
result.error (a string) and propagate that text as the failure message; locate
and change the JSON construction/serialization code that references timeout and
the response-parsing code that inspects result.success/result.error to implement
these behaviors.

---

Nitpick comments:
In `@src/mev_share.zig`:
- Around line 28-33: Add a Sepolia relay constant and a Sepolia initializer to
mirror the existing mainnet helpers: define sepolia_relay_url (matching the
relay endpoint used for Sepolia) alongside mainnet_relay_url and add an
initSepolia() function (parallel to initMainnet()) that wires sepolia_stream_url
and sepolia_relay_url into the same setup flow; then update the network-defaults
usage sites (the code around the other defaults, e.g., the block referenced at
369-372) to use initSepolia() or sepolia_relay_url instead of a hardcoded
Sepolia URL so callers no longer need to embed literals.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b23e5e54-c974-46bc-8368-85092e31b8b2

📥 Commits

Reviewing files that changed from the base of the PR and between d272b7b and d6325b6.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • docs/content/docs/meta.json
  • docs/content/docs/mev-share.mdx
  • src/flashbots.zig
  • src/mev_share.zig
  • src/root.zig

Comment thread src/mev_share.zig
Comment on lines +259 to +262
/// Simulation timeout in seconds. Default: 5.
/// TODO: the docs do not specify the wire encoding; sent as a plain
/// JSON number (seconds), matching the documented default ("5").
timeout: ?u64 = null,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Flashbots mev_simBundle timeout encoding response error field name mev-share-client-ts official docs

💡 Result:

The "mev_simBundle" RPC method includes a "timeout" field within its "simOptions" object, which specifies the duration for the simulation in seconds, with a default value of 5 seconds [1][2][3]. In the context of the Flashbots mev-share-client-ts library, simulation is performed using the "simulateBundle" function [4][5]. If you are encountering an encoding error or timeout issue related to a field name, it is likely due to an inconsistency between the expected JSON-RPC schema and the parameters being passed. Based on the official Flashbots specifications for "mev_simBundle", the "simOptions" object is structured as follows [1][3]: { parentBlock?: number | string, blockNumber?: number, coinbase?: string, timestamp?: number, gasLimit?: number, baseFee?: bigint, timeout?: number // Default is 5 seconds } Troubleshooting steps: 1. Verify Field Names: Ensure you are nesting "timeout" inside the "simOptions" object rather than passing it at the top level of the "mev_simBundle" parameters [1][3]. 2. Check Data Types: The "timeout" field expects a number (in seconds) [1][2][3]. If your client is attempting to encode this as a string or another incompatible type, it will trigger an encoding error. 3. Review Library Version: Ensure your "mev-share-client-ts" library is up to date, as the "simOptions" interface is explicitly defined in the library to handle these fields correctly [5][6]. If you are seeing an error specifically mentioning "field name" during encoding, it often indicates that the library's TypeScript interfaces are not matching the structure expected by the MEV-Share Node [1][3]. Always cross-reference your request object against the schema provided in the official Flashbots documentation [1][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/mev_share.zig"

echo "== Lines around 250-290 =="
nl -ba "$FILE" | sed -n '240,290p'

echo
echo "== Lines around 540-590 =="
nl -ba "$FILE" | sed -n '540,590p'

echo
echo "== Lines around 620-670 =="
nl -ba "$FILE" | sed -n '620,670p'

echo
echo "== Search for mev_simBundle / simulateBundle / error parsing =="
rg -n "mev_simBundle|simulateBundle|simOptions|timeout|\"error\"|error\b|fail|failure" "$FILE"

Repository: StrobeLabs/eth.zig

Length of output: 150


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/mev_share.zig"

echo "== Lines around 250-290 =="
awk 'NR>=240 && NR<=290 {printf "%6d  %s\n", NR, $0}' "$FILE"

echo
echo "== Lines around 540-590 =="
awk 'NR>=540 && NR<=590 {printf "%6d  %s\n", NR, $0}' "$FILE"

echo
echo "== Lines around 620-670 =="
awk 'NR>=620 && NR<=670 {printf "%6d  %s\n", NR, $0}' "$FILE"

echo
echo "== Search for mev_simBundle / simulateBundle / simOptions / timeout / \"error\" parsing =="
rg -n "mev_simBundle|simulateBundle|simOptions|timeout|\"error\"|error\b|failure\b|fail\b" "$FILE" || true

Repository: StrobeLabs/eth.zig

Length of output: 13489


🌐 Web query:

Flashbots mev_simBundle response result { success error } field name

💡 Result:

The Flashbots mev_simBundle RPC method returns a JSON object containing a success boolean field, which indicates whether the simulation of the bundle was successful [1][2]. If the simulation fails, the response may include an error string field explaining the failure [2]. According to the official Flashbots MEV-Share client implementations, the simulation response object typically includes the following fields [2]: - success: (boolean) Whether the simulation succeeded [1][2]. - error: (string, optional) An error message if the simulation failed [2]. - stateBlock: (string) The block number used for the simulation, represented as a hex-encoded string [1][2]. - mevGasPrice: (string) The effective MEV gas price [1][2]. - profit: (string) The expected profit in wei [1][2]. - refundableValue: (string) The value that would be refunded [1][2]. - gasUsed: (string) The total gas used by the bundle [1][2]. - logs: (array, optional) Transaction logs resulting from the simulation [1][2]. These fields are commonly accessed by client libraries to verify bundle execution and economic viability before submission [1][3][4].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/mev_share.zig"

echo "== Lines around build params for mev_simBundle (500-560) =="
awk 'NR>=480 && NR<=590 {printf "%6d  %s\n", NR, $0}' "$FILE"

echo
echo "== Lines around simulateBundle() usage (360-460) =="
awk 'NR>=350 && NR<=480 {printf "%6d  %s\n", NR, $0}' "$FILE"

echo
echo "== Tests around timeout + parseSimBundleResult error (880-1030) =="
awk 'NR>=880 && NR<=1035 {printf "%6d  %s\n", NR, $0}' "$FILE"

Repository: StrobeLabs/eth.zig

Length of output: 18501


mev_simBundle: timeout and failure error wire fields align with spec/ts

  • SimBundleOpts.timeout is nested under simOptions and serialized as an unquoted JSON number of seconds (unit tests assert "timeout":10), matching the Flashbots mev_simBundle simOptions.timeout definition.
  • Failure text parsing from result.error (string) when success=false matches mev-share-client-ts’s response shape and is covered by the unit test using {"success":false,"error":"execution reverted"}.

Remaining wire-shape TODOs to review are outside these two fields (e.g., unparsed nested bundleLogs).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mev_share.zig` around lines 259 - 262, The SimBundle wire-shape must
serialize SimBundleOpts.timeout as an unquoted JSON number under simOptions and
must parse failure text from result.error when success==false; update the code
that builds the outbound JSON to put the timeout value (the field timeout: ?u64
in the SimBundleOpts/struct) inside the simOptions object and emit it as a
numeric JSON value (not a quoted string), and update the response handling logic
that consumes the simulation result to check result.success and, when false,
read result.error (a string) and propagate that text as the failure message;
locate and change the JSON construction/serialization code that references
timeout and the response-parsing code that inspects result.success/result.error
to implement these behaviors.

@koko1123 koko1123 merged commit e28b44b into main Jun 10, 2026
14 checks passed
@koko1123 koko1123 deleted the feat/mev-share branch June 10, 2026 14:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MEV-Share client module (mev_share.zig)

1 participant