Conversation
1. Add meta field to subgraph queries for order discovery 2. Create oracle module with: - extractOracleUrl() placeholder for meta parsing - fetchSignedContext() for batch oracle requests - Support for batch format (array of contexts) 3. Wire oracle into quoting logic: - Extract oracle URL from order meta before quote2 - Fetch signed context and inject into takeOrder struct - Graceful fallback on oracle failures 4. Ensure signed context flows through to takeOrdersConfig The solver now automatically fetches oracle data for orders that specify an oracle-url, enabling external data integration.
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (5)
WalkthroughAdds an oracle integration module that encodes order batches, POSTs to an oracle endpoint with timeout handling, and validates signed-context responses; quote routines attempt to fetch and inject oracle-signed context before quoting; subgraph queries now request order Changes
Sequence DiagramsequenceDiagram
actor Client
participant QuoteService as Quote Service
participant OracleModule as Oracle Module
participant OracleEndpoint as Oracle Endpoint
Client->>QuoteService: quoteSingleOrderV4(order)
QuoteService->>QuoteService: inspect order.meta for oracle info
alt oracle metadata present
QuoteService->>OracleModule: extractOracleUrl(metaHex)
OracleModule-->>QuoteService: oracle URL or null
alt URL found
QuoteService->>OracleModule: fetchSignedContext(url, [orderRequest])
OracleModule->>OracleModule: encode batch (ABI)
OracleModule->>OracleEndpoint: POST (application/octet-stream) with timeout
OracleEndpoint-->>OracleModule: HTTP 200 + JSON array
OracleModule->>OracleModule: validate parse SignedContextV1[]
OracleModule-->>QuoteService: SignedContextV1[]
QuoteService->>QuoteService: inject signedContext into orderDetails
end
end
QuoteService->>QuoteService: perform quote
QuoteService-->>Client: return quote result
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/oracle/index.ts`:
- Around line 89-93: Validate the oracle JSON before casting to
SignedContextV1[]: after parsing into contexts, iterate over each item and
ensure it has the required keys and types (e.g., that "signer" is a string,
"signature" is a string and/or bytes representation, and "context" is an object
or array as expected) and reject or throw a descriptive error for any malformed
entry; update the code around the contexts variable and the SignedContextV1
validation logic (the parsing block that populates contexts and the code that
later uses contexts for takeOrder) to perform these checks and sanitize/convert
fields as needed before returning or passing into takeOrder.
- Around line 36-41: The OracleOrderRequest currently types order as any;
replace that with the concrete OrderV4 type (e.g., use OrderV4) so the compiler
enforces structural compatibility during ABI encoding. Import or reference the
resolved OrderV4 type where OracleOrderRequest is declared, update the interface
field to order: OrderV4, and run TypeScript/tsc to fix any resulting type
mismatches in functions that construct or pass OracleOrderRequest objects
(adjust those call sites to produce a valid OrderV4).
- Around line 77-83: The fetch call that posts the oracle request (the statement
creating response = await fetch(url, { method: 'POST', headers: {...}, body:
ethers.getBytes(body) })) has no timeout and can hang; wrap the request with an
AbortController (or use AbortSignal.timeout(ms)) and pass its signal to fetch,
enforce a reasonable deadline (e.g., 5–10s), and ensure you abort the controller
on timeout; update the code around the fetch invocation to create controller =
new AbortController(), pass signal: controller.signal into fetch, use
setTimeout(() => controller.abort(), TIMEOUT_MS) (or AbortSignal.timeout) and
handle the abort in the existing error handling so the quoting pipeline fails
fast instead of blocking.
- Around line 12-18: The extractOracleUrl function currently logs a console.warn
on every invocation which will flood logs; change this by removing the per-call
console.warn or replace it with a one-time warning emitted via a module-level
flag (e.g., a let warned = false at module scope) so the message is logged only
once, or eliminate the log altogether and simply return null; update the
extractOracleUrl function to reference the module-level flag (or remove the
call) and ensure no per-invocation console.warn remains.
- Line 1: The code is using ethers v6 APIs but the project depends on ethers
v5.7.0; update the v6-specific calls to their v5 equivalents: replace uses of
ethers.AbiCoder.defaultAbiCoder() with ethers.utils.defaultAbiCoder and replace
ethers.getBytes(...) with ethers.utils.arrayify(...). Locate these calls in
src/oracle/index.ts (references around the symbols AbiCoder.defaultAbiCoder and
getBytes) and update any related variable names/usages so they call
ethers.utils.* accordingly, ensuring types/inputs remain the same.
- Around line 69-75: The code is ABI-encoding OrderV4 tuples using a hardcoded
tuple signature; replace that raw string with the canonical ABI constant from
the common ABI module. Import the Orderbook ABI export (e.g., Orderbook or
Orderbook.V5) and use its Order/OrderV4 type or parsed ABI parameter (via
parseAbiParameters if needed) in the abiCoder.encode call instead of the inline
tuple string so the encode uses the shared OrderV4 definition; update the import
and pass the referenced ABI constant where the current abiCoder.encode([...],
[tuples]) call appears.
In `@src/order/quote.ts`:
- Around line 42-63: Extract the duplicated oracle-fetch block into a private
helper named fetchOracleContext that accepts the orderDetails object, uses
extractOracleUrl(orderMeta) and fetchSignedContext(oracleUrl, [...]) to obtain
signed context, and updates orderDetails.takeOrder.struct.signedContext; then
replace the inline try/catch in quoteSingleOrderV3 and quoteSingleOrderV4 with a
call to await fetchOracleContext(orderDetails) wrapped in the same try/catch
that logs the warning on failure (preserve the same warning text), ensuring you
reference the existing functions fetchSignedContext and extractOracleUrl and the
same orderDetails.takeOrder.struct shape so behavior is unchanged.
- Around line 42-63: The oracle metadata access is wrong because
quoteSingleOrderV3 and quoteSingleOrderV4 receive a Pair (PairV3 | PairV4) that
doesn’t contain the original SgOrder.meta, so the fetch block using
(orderDetails as any).orderDetails?.meta is unreachable; fix by changing the
function(s) signature to accept the original SgOrder (or at least its
meta/oracle URL) alongside the Pair, or alternatively persist the SgOrder.meta
onto the Pair when the Pair is constructed so extractOracleUrl can read it; then
factor the duplicated fetch logic into a shared helper (e.g.,
fetchSignedContextForOrder) that calls extractOracleUrl and fetchSignedContext
and sets takeOrder.struct.signedContext (referencing
orderDetails.takeOrder.struct.signedContext) and use that helper from both
quoteSingleOrderV3 and quoteSingleOrderV4.
- Fix ethers v6 → v5 APIs (defaultAbiCoder, arrayify) - Use ABI.Orderbook.V5.OrderV4 constant instead of hardcoded tuple string - Add 5s timeout on oracle fetch via AbortController - Validate SignedContextV1 shape on each response entry - Extract fetchOracleContext helper to deduplicate quote logic - Remove noisy console.warn from stub extractOracleUrl - Type OracleOrderRequest.order properly instead of any
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/order/quote.ts (1)
14-16:⚠️ Potential issue | 🟠 Major
(orderDetails as any).metawill always beundefined— oracle fetch is dead code.
orderDetailsis typed asPair(PairV3 | PairV4), andas anyis required becausemetais not a member of thePairtype. Consequently,orderMetais alwaysundefined, the guard on Line 16 returns immediately every time, and oracle signed context is never fetched — making the entire oracle integration a no-op.The previous form
(orderDetails as any).orderDetails?.metaexhibited the same issue; the path was shortened but the root cause (the originalSgOrder.metais not surfaced onPair) was not addressed. The fix requires one of:
- Adding a
meta?: stringfield toPairBase(or the variant types) and populating it when constructing thePairfrom anSgOrder, or- Changing
quoteSingleOrderV3/quoteSingleOrderV4(andquoteSingleOrder) to accept the originalSgOrder(or at least its oracle URL) alongside thePair.#!/bin/bash # Verify whether Pair / PairBase / PairV3 / PairV4 expose a `meta` field rg -n "meta" --type=ts src/order/types/ -C 2 # Also check if SgOrder carries meta and whether it's threaded into Pair construction rg -n "meta" --type=ts src/subgraph/types.ts -C 2 rg -n "fromArgs\|new Pair\|PairV3\|PairV4" --type=ts src/order/types/ -A 10 | grep -A 5 "meta"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/order/quote.ts` around lines 14 - 16, fetchOracleContext is dead because (orderDetails as any).meta is always undefined—the Pair type (PairBase / PairV3 / PairV4) doesn’t expose SgOrder.meta—so oracle logic never runs. Fix by either: 1) add an optional meta?: string to PairBase (and relevant PairV3/PairV4) and ensure the Pair factory/constructor that converts an SgOrder copies SgOrder.meta into the Pair, replacing the (orderDetails as any).meta access; or 2) change quoteSingleOrderV3 / quoteSingleOrderV4 (and quoteSingleOrder) to accept the original SgOrder (or at least its oracle URL) alongside the Pair and pass that through to fetchOracleContext, then remove the incorrect cast in fetchOracleContext. Ensure fetchOracleContext reads the strongly typed field (meta or provided oracle URL) so oracle fetching actually executes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/oracle/index.ts`:
- Around line 110-122: The current validation in the SignedContextV1 mapping
(the contexts constant in src/oracle/index.ts) only checks that entry.context is
an array but not that its items are strings; update the validator inside the
json.map where you check (entry as any).context to ensure Array.isArray((entry
as any).context) && ((entry as any).context).every((c: unknown) => typeof c ===
"string") so that non-string elements are rejected and the thrown Error message
still references the index i; keep returning entry as SignedContextV1 after the
stricter check.
---
Duplicate comments:
In `@src/order/quote.ts`:
- Around line 14-16: fetchOracleContext is dead because (orderDetails as
any).meta is always undefined—the Pair type (PairBase / PairV3 / PairV4) doesn’t
expose SgOrder.meta—so oracle logic never runs. Fix by either: 1) add an
optional meta?: string to PairBase (and relevant PairV3/PairV4) and ensure the
Pair factory/constructor that converts an SgOrder copies SgOrder.meta into the
Pair, replacing the (orderDetails as any).meta access; or 2) change
quoteSingleOrderV3 / quoteSingleOrderV4 (and quoteSingleOrder) to accept the
original SgOrder (or at least its oracle URL) alongside the Pair and pass that
through to fetchOracleContext, then remove the incorrect cast in
fetchOracleContext. Ensure fetchOracleContext reads the strongly typed field
(meta or provided oracle URL) so oracle fetching actually executes.
src/oracle/index.ts
Outdated
| // Validate shape of each entry | ||
| const contexts: SignedContextV1[] = json.map((entry: unknown, i: number) => { | ||
| if ( | ||
| typeof entry !== "object" || | ||
| entry === null || | ||
| typeof (entry as any).signer !== "string" || | ||
| !Array.isArray((entry as any).context) || | ||
| typeof (entry as any).signature !== "string" | ||
| ) { | ||
| throw new Error(`Oracle response[${i}] is not a valid SignedContextV1`); | ||
| } | ||
| return entry as SignedContextV1; | ||
| }); |
There was a problem hiding this comment.
context array elements are not validated as strings.
Array.isArray((entry as any).context) only verifies it's an array; it doesn't check that every element is a string. A malformed oracle response with numeric or object entries in context would silently pass validation, violate the string[] contract, and fail unpredictably downstream.
🛡️ Proposed fix
!Array.isArray((entry as any).context) ||
+ !(entry as any).context.every((elem: unknown) => typeof elem === "string") ||
typeof (entry as any).signature !== "string"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/oracle/index.ts` around lines 110 - 122, The current validation in the
SignedContextV1 mapping (the contexts constant in src/oracle/index.ts) only
checks that entry.context is an array but not that its items are strings; update
the validator inside the json.map where you check (entry as any).context to
ensure Array.isArray((entry as any).context) && ((entry as
any).context).every((c: unknown) => typeof c === "string") so that non-string
elements are rejected and the thrown Error message still references the index i;
keep returning entry as SignedContextV1 after the stricter check.
Replace ethers.utils.defaultAbiCoder/arrayify with viem's encodeAbiParameters/hexToBytes. Use proper viem ABI parameter definitions instead of string-based encoding.
- Up to 2 retries with exponential backoff (500ms, 1s) - After 3 consecutive failures, oracle URL enters 5min cooloff - During cooloff, requests to that URL are skipped immediately - Cooloff resets on first successful response - Invalid responses (bad shape, wrong length) also count as failures - All configurable via module constants
No retries, no delays in the loop. Single attempt with 5s timeout — if it fails, record the failure and move on. After 3 consecutive failures the URL enters a 5min cooloff where it's skipped immediately (no network call at all). This way one bad oracle can't block the processing of other orders.
…ager Extract oracle cooloff tracking from module-level singleton into an OracleManager class. Instance lives on OrderManager, threaded through to quote functions. This makes it properly scoped to the solver instance lifecycle and testable. - OracleManager class in src/oracle/manager.ts - fetchSignedContext takes OracleManager as parameter - OrderManager creates and owns the OracleManager instance - OracleManager is optional in quote functions for backward compat
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/oracle/index.ts (1)
150-162:⚠️ Potential issue | 🟡 Minor
contextarray elements are not validated as strings.Line 156 only verifies
Array.isArray((entry as any).context)without checking that every element is astring. A malformed oracle response with non-string entries silently passes validation.🛡️ Proposed fix
!Array.isArray((entry as any).context) || + !(entry as any).context.every((elem: unknown) => typeof elem === "string") || typeof (entry as any).signature !== "string"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/oracle/index.ts` around lines 150 - 162, The validation for SignedContextV1 entries currently only checks Array.isArray((entry as any).context) but doesn't ensure each element is a string; update the json.map validation that creates contexts to assert that (entry as any).context is an array of strings (e.g., use Array.isArray and .every(elem => typeof elem === "string")) and throw the same Error(`Oracle response[${i}] is not a valid SignedContextV1`) if any element is non-string so the SignedContextV1 cast is only applied after the full shape check.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/oracle/index.ts`:
- Around line 32-43: OracleOrderRequest uses bare string for Ethereum-typed
fields which causes type errors when passed to encodeAbiParameters with
oracleBatchAbiParams; update the OracleOrderRequest interface so owner,
interpreter, store, and token are typed as viem Address (e.g. `0x${string}`),
and bytecode, vaultId, nonce (and any bytes/bytes32 fields) are typed as viem
Hex (e.g. `0x${string}`), or alternatively perform explicit casts to
`\`0x${string}\`` for those specific properties at the call site before calling
encodeAbiParameters; apply this change to the nested order fields referenced by
encodeAbiParameters and keep the already-casted counterparty treatment
consistent.
---
Duplicate comments:
In `@src/oracle/index.ts`:
- Around line 150-162: The validation for SignedContextV1 entries currently only
checks Array.isArray((entry as any).context) but doesn't ensure each element is
a string; update the json.map validation that creates contexts to assert that
(entry as any).context is an array of strings (e.g., use Array.isArray and
.every(elem => typeof elem === "string")) and throw the same Error(`Oracle
response[${i}] is not a valid SignedContextV1`) if any element is non-string so
the SignedContextV1 cast is only applied after the full shape check.
Follow codebase conventions: - Oracle health map lives on SharedState.oracleHealth - fetchOracleContext is a standalone fn with this: SharedState, called via .call(state) like processOrder/findBestTrade - Health helpers (isInCooloff, recordOracleSuccess/Failure) are plain exported functions operating on the health map - No new classes, no module-level singletons - quoteSingleOrder receives SharedState to thread through
- fetchSignedContext returns Result<SignedContextV1[], string> - fetchOracleContext returns Result<void, string> - Callers check .isErr() instead of try/catch - Follows codebase convention for error handling
…terface - OracleOrderRequest.order uses Order.V3 | Order.V4 from order/types - OracleOrderRequest.counterparty typed as 0x - Drop custom SignedContextV1 interface — signed context is already typed as any[] on TakeOrderV3/V4, and the response validation ensures the right shape at runtime - fetchSignedContext returns Result<any[], string> matching the existing signedContext field type
Adds support for fetching signed context from oracle servers for orders that specify an oracle-url in their metadata. Changes: adds meta field to subgraph queries, new oracle module for fetching signed contexts (batch format per spec), wires oracle fetch into quoting pipeline. Note: extractOracleUrl is a placeholder pending SDK update.
Summary by CodeRabbit