Skip to content

Take Orders SDK – Phase 2: Take‑Order Candidates and Quoting #2355

@findolor

Description

@findolor

Summary

Build a take‑order candidate layer that turns discovered orders into a flat list of:

TakeOrderCandidate {
  order: OrderV4,
  input_io_index: u32,
  output_io_index: u32,
  max_output: Float,  // from quote2.outputMax
  ratio: Float,       // from quote2.IORatio (input per 1 output, order POV)
  // optional: order_hash, token addresses, debugging info
}

for a given (networkKey, inputToken, outputToken). This layer:

  • Uses the existing Raindex order discovery (with directional filters from Phase 1).
  • Calls get_order_quotes / RaindexOrder::get_quotes to quote each (inputIOIndex, outputIOIndex) pair.
  • Filters to the desired direction and non‑zero capacity.
  • Exposes the resulting TakeOrderCandidate[] to both Rust and wasm/JS.

No simulation or TakeOrdersConfigV4 building happens in this issue.


Goals

  • Provide a clean, backend‑agnostic abstraction for “things we could include in TakeOrdersConfigV4.orders[]”.
  • Keep quoting and candidate construction:
    • Reusable for future features (exact‑out, custom selection policies).
    • Easy to test with local EVM fixtures and/or synthetic orders.
  • Avoid leaking subgraph/local‑DB details into simulation or js_api layers.

Implementation Plan

1. Define TakeOrderCandidate

  • File (suggested):

    • crates/common/src/raindex_client/order_quotes.rs
      or a new module crates/common/src/raindex_client/take_order_candidates.rs.
  • Struct:

    #[derive(Clone, Debug)]
    pub struct TakeOrderCandidate {
        pub order: OrderV4,
        pub input_io_index: u32,
        pub output_io_index: u32,
        pub max_output: Float, // output token units
        pub ratio: Float,      // input per 1 output, order POV
        // Optional debug fields:
        // pub order_hash: B256,
        // pub input_token: Address,
        // pub output_token: Address,
    }
  • Notes:

    • OrderV4 should come from the decoded subgraph/local‑DB data already available on RaindexOrder.
    • The candidate struct should not depend on subgraph types (SgOrder etc.).

2. Build candidates from RaindexOrder + quotes

  • Public function:

    pub fn build_take_order_candidates_for_pair(
        orders: &[RaindexOrder],
        input_token: Address,
        output_token: Address,
        block_number: Option<u64>,
        gas: Option<u64>,
    ) -> Result<Vec<TakeOrderCandidate>, RaindexError>
  • Implementation outline:

    • For each RaindexOrder in orders:
      • Call RaindexOrder::get_quotes(block_number, gas_string?):
        • This wraps rain_orderbook_quote::get_order_quotes and already returns per‑pair quotes.
      • For each quote response:
        • Extract:
          • pair → IO indices (input_index, output_index).
          • dataOrderQuoteValue { max_output, ratio } (when success == true).
        • Resolve the OrderV4 associated with this RaindexOrder.
        • Check direction:
          • order.validInputs[input_index].token == input_token.
          • order.validOutputs[output_index].token == output_token.
        • Check capacity:
          • max_output > 0.
        • If all conditions pass, push a TakeOrderCandidate for this (order, input_index, output_index).
    • Return the concatenated list of candidates across all orders.
  • Edge cases:

    • If get_quotes fails for an order, decide whether to:
      • Bubble the error up, or
      • Log/wrap it and continue with other orders (consistent with how we treat batch errors elsewhere).

3. Wasm/JS exposure (optional but recommended)

  • Goal:

    • Expose TakeOrderCandidate[] to wasm/JS so tools and UIs can:
      • Inspect available legs and prices.
      • Implement alternative selection strategies client‑side if desired.
  • Tasks:

    • Derive Tsify for TakeOrderCandidate with appropriate TS field types, e.g.:

      #[cfg_attr(target_family = "wasm", derive(Tsify))]
      #[serde(rename_all = "camelCase")]
      pub struct TakeOrderCandidate { ... }
    • Add a wasm‑exported function, e.g. on RaindexClient or a helper:

      #[wasm_export(
          js_name = "getTakeOrderCandidates",
          unchecked_return_type = "TakeOrderCandidate[]"
      )]
      pub async fn get_take_order_candidates(
          &self,
          network_key: String,
          input_token: Address,
          output_token: Address,
          block_number: Option<u64>,
          gas: Option<String>,
      ) -> Result<Vec<TakeOrderCandidate>, RaindexError> { ... }
    • The wasm function should:

      • Use existing YAML/settings to resolve:
        • Chain ID.
        • Orderbook addresses.
      • Use GetOrdersFilters with directional tokens from Phase 1 to fetch RaindexOrder[].
      • Call build_take_order_candidates_for_pair to turn those into candidates.

4. Tests

  • Unit tests (Rust, non‑wasm):

    • Use LocalEvm fixtures (rain_orderbook_test_fixtures::LocalEvm) to:
      • Deploy a simple orderbook + 2 ERC‑20 tokens.
      • Deploy one or more OrderV4 strategies where IO indices are known.
      • Call build_take_order_candidates_for_pair and assert:
        • Candidates exist for the intended (inputToken, outputToken) direction.
        • max_output / ratio in the candidate match on‑chain quote2.
    • Test filtering:
      • Orders with zero max_output are excluded.
      • Orders that reference the tokens but not in the right IO direction are excluded.
  • Wasm/JS smoke test (if wasm API is added):

    • From JS, call getTakeOrderCandidates(...) in a test environment.
    • Assert:
      • Non‑empty result for known fixtures.
      • Shape and types of the returned objects are correct in TS.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions