Skip to content

Quote signed-context oracles server-side, expose parsedMeta#97

Open
alastairong1 wants to merge 2 commits intoalastair/comprehensive-health-endpointfrom
alastair/parsed-meta-signed-oracle
Open

Quote signed-context oracles server-side, expose parsedMeta#97
alastairong1 wants to merge 2 commits intoalastair/comprehensive-health-endpointfrom
alastair/parsed-meta-signed-oracle

Conversation

@alastairong1
Copy link
Copy Markdown
Contributor

Summary

Two changes that together let signed-context oracle orders (SPYM and
similar) return real ioRatio values from the /v1/orders/* list
endpoints instead of the "-" sentinel:

  1. Fix the body shape fetch_oracle_context sends. The existing
    implementation POSTed abi.encode(empty bytes) to the maker's oracle
    URL — every request 400'd with Invalid ABI-encoded body. The fix
    matches the oracle server's own smoke-test format: it ABI-encodes the
    tuple (OrderV4, U256 inputIOIndex, U256 outputIOIndex, address counterparty) (using 0/0/address(0) for the indices and
    counterparty). The orderbook then runs the order's full Rainlang —
    including × baseline-multiplier — so the returned ioRatio is the
    exact ratio the order would fill at right now, not an approximation.
  2. Expose parsed_meta: Vec<ParsedMeta> on OrderSummary. Since
    the server handles oracle plumbing internally, consumers don't need
    this to quote. It's exposed for clients that want to surface extra
    detail (tagging oracle-driven orders in the UI, reading
    DotrainSourceV1 for strategy configuration, etc.).

Why it was broken

For Pyth-oracle orders (NVDA, MSTR, etc.) the order's Rainlang reads
Pyth's on-chain contract directly — quote() works without any signed
context, ioRatio was always populated.

For signed-context oracle orders (SPYM, where the maker runs their own
off-chain signer), the order's Rainlang reads the price out of
signed-context<col row>() opcodes. quote() without a signed context
reverts (Oracle data stale, signed-context out of bounds), so the
API has to POST to the maker's URL first to get the signed payload, then
hand that into quote() as the 4th arg. The plumbing was wired up but
the request body was wrong.

Verification

Deployed to api.preview.st0x.io (rest-api-17-link). Server logs show:

INFO fetched oracle signed context
     oracle_url=https://st0x-oracle-server.fly.dev/context/v1
     count=1
     order_hash=0xc4009a82b1591da80723e3b6a4420c4e9548496ce3378fd9c6785991a0a91bcc

— SPYM signed-context orders now successfully fetch their signed payload.
ioRatio populates when markets are open / oracle data is fresh.
"-" still appears for orders that genuinely can't fill right now:

  • Oracle data stale (markets closed, last Alpaca quote > 30s old)
  • Old orders with deprecated /context URLs (now 404)
  • Orders whose Rainlang reverts for other reasons (vault empty, etc.)

All 208 tests pass.

Notes for review

  • Function signature changed: fetch_oracle_context(oracle_url)
    fetch_oracle_context(order, oracle_url) so we can derive
    OrderV4 from the order to build the request body.
  • Success-path log bumped from debug! to info! so deploys can
    verify the wiring without manually bumping RUST_LOG.
  • The parsed_meta field's utoipa schema is Vec<serde_json::Value>
    because ParsedMeta is defined in rain_orderbook_common and we
    don't want to ToSchema-ify a foreign type. Serialization shape is
    unchanged — matches the SDK's TypeScript ParsedMeta enum.

Targeting alastair/comprehensive-health-endpoint because that branch
holds the rest of the in-flight oracle infrastructure (oracle URL
extraction on RaindexOrder, the 4-arg fetch_order_quotes_batch
signature, etc.). Will rebase once the snapshot is split into per-topic
PRs against main.

🤖 Generated with Claude Code

Two changes that together let signed-context oracle orders (e.g. SPYM)
return real `ioRatio` values from `/v1/orders/token/*` and
`/v1/orders/owner/*` instead of the `"-"` sentinel:

1. **`fetch_oracle_context` now sends the right body.** The previous
   implementation POSTed `abi.encode(empty bytes)` (just `0x20` || `0x00`)
   to the maker's oracle URL, which the server (st0x-oracle-server) 400'd
   with `Invalid ABI-encoded body`. As a result every signed-context
   `quote()` call fell through with empty `signedContext` and the order's
   Rainlang reverted with `signed-context out of bounds` — the API then
   reported `ioRatio: "-"`, which the frontend would helpfully synthesise
   from oracle price plus phantom liquidity.

   The fix matches what the oracle server's own smoke test does: it
   ABI-encodes the tuple `(OrderV4, U256 inputIOIndex, U256 outputIOIndex,
   address counterparty)` via `SolValue::abi_encode`, with `(0, 0,
   address(0))` for the IO indices and counterparty. The orderbook
   contract then runs the order's full Rainlang including `× baseline-
   multiplier`, so the returned `io_ratio` is the exact ratio the order
   would fill at right now.

   Stale-oracle reverts (`Oracle data stale`) still surface as `"-"` —
   that's correct, the order legitimately can't fill outside market hours.
   Old orders with deprecated URLs (`/context` instead of `/context/v1`)
    404 and also surface as `"-"` — also correct, they can't fill.

   Function signature changed from `(oracle_url: &str)` to
   `(order: &RaindexOrder, oracle_url: &str)` so we can build the request
   body. Success path now logs at INFO so deploys can verify the wiring
   without bumping `RUST_LOG`.

2. **`OrderSummary` exposes `parsed_meta: Vec<ParsedMeta>`.** Since the
   server now does the oracle plumbing internally, frontends don't need
   this field to *quote* — but exposing it lets clients tag oracle-driven
   orders in the UI, read `DotrainSourceV1` for strategy configuration,
   etc. Mirrors the Rain SDK's `ParsedMeta` enum shape; schema declared
   as `Vec<serde_json::Value>` because `ParsedMeta` lives outside this
   crate.

Verified on api.preview.st0x.io — INFO logs show
`fetched oracle signed context oracle_url=...context/v1 count=1` for
SPYM orders. `ioRatio` populates when markets are open / oracle data is
fresh; `"-"` only appears for orders that genuinely can't fill.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc12d2a7-ffe8-40cc-8d54-8e639b906b29

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch alastair/parsed-meta-signed-oracle

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

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.

1 participant