Skip to content

feat: add positive output vault balance order filter#2562

Open
findolor wants to merge 1 commit intomainfrom
t3code/safe-zero-balance-filter
Open

feat: add positive output vault balance order filter#2562
findolor wants to merge 1 commit intomainfrom
t3code/safe-zero-balance-filter

Conversation

@findolor
Copy link
Copy Markdown
Collaborator

@findolor findolor commented Apr 30, 2026

Motivation

Quote-layer zero-balance filtering was tied to the order snapshot returned by the indexer, which can be wrong for historical block quotes. Consumers only need a way to request orders that have usable indexed output vault liquidity before they build quote requests.

Solution

  • Add hasPositiveOutputVaultBalance to order list filters as an optional feature flag.
  • Treat omitted or false as no filter.
  • Treat true as requiring at least one output vault with vaultId != 0 and indexed balance greater than zero.
  • Push the filter into subgraph order fetching with the existing outputs_ nested filter.
  • Apply the same filter in local-db order list and count SQL.
  • Add FLOAT_GT_ZERO for local-db Rain Float balance comparison.
  • Remove the quote-layer output filtering from the PR.

Checks

By submitting this for review, I'm confirming I've done the following:

  • made this PR as small as possible
  • unit-tested any new functionality
  • linked any relevant issues or PRs
  • included screenshots (if this involves a front-end change)

Verified locally:

  • nix develop -c cargo fmt --all
  • nix develop -c cargo test -p rain_orderbook_subgraph_client positive_output_vault_balance
  • nix develop -c cargo test -p rain_orderbook_common positive_output_vault_balance
  • nix develop -c cargo test -p rain_orderbook_subgraph_client
  • nix develop -c cargo test -p rain_orderbook_common
  • nix develop -c ob-rs-test
  • nix develop -c rainix-wasm-test
  • nix develop -c rainix-rs-static

Copy link
Copy Markdown
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

📝 Walkthrough

Walkthrough

The PR introduces a new SQLite scalar function FLOAT_GT_ZERO for vault balance comparisons and integrates an optional filter for orders with positive output vault balances across both local database queries and subgraph order fetching with in-memory filtering.

Changes

Cohort / File(s) Summary
SQLite Function Registration
crates/common/src/local_db/functions/float_gt_zero.rs, crates/common/src/local_db/functions/mod.rs
New scalar function FLOAT_GT_ZERO that compares parsed float values against zero, with unit tests validating behavior for zero, positive, and negative values. Function is registered alongside existing float-related operations.
Query Infrastructure
crates/common/src/local_db/query/fetch_orders/query.sql, crates/common/src/local_db/query/fetch_orders_count/query.sql
SQL templates extended with /*POSITIVE_OUTPUT_VAULT_BALANCE_CLAUSE*/ placeholders in main WHERE/GROUP BY sections and subquery filtering to conditionally filter orders based on output vault balance.
Fetch Orders Logic
crates/common/src/local_db/query/fetch_orders/mod.rs, crates/common/src/local_db/query/fetch_orders_common.rs
New optional has_positive_output_vault_balance argument added to FetchOrdersArgs. Common logic generates dynamic SQL filters using EXISTS/NOT EXISTS subqueries with FLOAT_GT_ZERO comparisons on running vault balances.
Count Query Tests
crates/common/src/local_db/query/fetch_orders_count/mod.rs
Test coverage added for the new filter flag, validating correct SQL generation with AND NOT EXISTS clauses and balance comparison logic.
Client-Side Integration
crates/common/src/raindex_client/orders.rs, crates/common/src/raindex_client/local_db/query/fetch_orders.rs
New has_positive_output_vault_balance filter field exposed in GetOrdersFilters. Client-side implementation decodes vault balances from subgraph, filters orders in-memory when flag is set, applies custom pagination. Field propagated from client filters to local database query builder.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~70 minutes

Poem

🐰 A function hops in, FLOAT_GT_ZERO so bright,
Comparing vault balances left and right,
Orders now filter on output's treasure chest,
Subgraph and database join in this quest,
With EXISTS clauses dancing, the query's blessed! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title 'feat: add positive output vault balance order filter' directly describes the main change across all modified files—adding a new order filter feature based on positive output vault balance.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/safe-zero-balance-filter

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.

@findolor findolor self-assigned this Apr 30, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/quote/src/order_quotes.rs`:
- Around line 161-168: The zero-balance check is using the live snapshot
`order.outputs` instead of the outputs for the requested quote block, which can
drop valid historical pairs; update the call site that invokes
`output_vault_has_zero_orderbook_balance(&order.outputs, output.token,
output_vault_id)` to pass the outputs snapshot for the requested `block_number`
(the historical outputs/order state used to build the quote) instead of
`order.outputs` so the zero-balance decision is based on the quote's block
state; change the argument to the appropriate variable representing outputs at
the quote block (the historical/order-at-block outputs snapshot used elsewhere
in the quote-generation flow) in the same conditional.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 739414e0-4ca1-449e-83d2-63658485c754

📥 Commits

Reviewing files that changed from the base of the PR and between 643f47a and 07f0af9.

📒 Files selected for processing (2)
  • crates/quote/ARCHITECTURE.md
  • crates/quote/src/order_quotes.rs

Comment thread crates/quote/src/order_quotes.rs Outdated
@findolor findolor closed this Apr 30, 2026
@findolor findolor reopened this Apr 30, 2026
@findolor findolor force-pushed the t3code/safe-zero-balance-filter branch from 07f0af9 to 56699f4 Compare April 30, 2026 09:41
@findolor findolor changed the title fix: filter zero-balance quote outputs feat: add positive output vault balance order filter Apr 30, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/common/src/raindex_client/orders.rs (1)

1366-1376: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

fetch_orders_for_pair never turns the new balance filter on.

This helper still builds GetOrdersFilters with has_positive_output_vault_balance: None. If it is part of quote candidate discovery, both the local-db and SG paths will bypass the new filtering entirely.

#!/bin/bash
set -euo pipefail

# Find every caller of fetch_orders_for_pair.
rg -n -C3 '\bfetch_orders_for_pair\s*\(' --type=rust

# Check whether those callers are in quote/candidate-building flows.
rg -n -C3 'fetch_orders_for_pair|get_quotes|order_quotes|build_candidate_from_quote' crates/common/src/raindex_client
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/common/src/raindex_client/orders.rs` around lines 1366 - 1376, The
GetOrdersFilters constructed in fetch_orders_for_pair currently leaves
has_positive_output_vault_balance as None, so the new balance-based filtering is
never applied; change the construction in fetch_orders_for_pair (the
GetOrdersFilters creation) to set has_positive_output_vault_balance: Some(true)
when this helper is used for quote candidate discovery, or alternatively add a
boolean parameter to fetch_orders_for_pair (e.g.,
require_positive_output_vault_balance) and propagate it to set
has_positive_output_vault_balance accordingly; update all callers of
fetch_orders_for_pair involved in quote/candidate-building flows (those found by
searching for
fetch_orders_for_pair/get_quotes/order_quotes/build_candidate_from_quote) to
pass the flag so the local-db and SG paths actually enable the filter.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/common/src/local_db/query/fetch_orders_common.rs`:
- Around line 49-66: The current POSITIVE_OUTPUT_VAULT_BALANCE_CLAUSE
(POSITIVE_OUTPUT_VAULT_BALANCE_EXISTS_BODY) only checks at order scope and still
exempts vault_id 0; change it to enforce pair-level semantics and drop the
special-case vault 0 exclusion. Update the EXISTS subquery so it correlates to
the specific pair (match io_balance and vb_balance to the pair identifiers used
in the outer query — e.g., token / pair id columns used by aliases l and la or
whatever pair key is present) instead of only matching the order, and remove the
"AND io_balance.vault_id != {zero_vault_id}" predicate; ensure
vb_balance.balance is tested per that same pair
(FLOAT_GT_ZERO(vb_balance.balance)) so only output vaults for the exact pair are
considered.

In `@crates/common/src/raindex_client/orders.rs`:
- Around line 1435-1468: sg_order_has_positive_output_vault_balance currently
uses any(...) so mixed-balance orders slip through and
sg_vault_has_positive_orderbook_balance short-circuits on vault_id ==
U256::ZERO, preserving the zero-vault exception; change
sg_order_has_positive_output_vault_balance to require all outputs be positive
(use all instead of any) and remove the early return for vault_id == U256::ZERO
inside sg_vault_has_positive_orderbook_balance so the zero vault is treated like
any other vault (only return false on parse failures or when the balance is not
> zero).

---

Outside diff comments:
In `@crates/common/src/raindex_client/orders.rs`:
- Around line 1366-1376: The GetOrdersFilters constructed in
fetch_orders_for_pair currently leaves has_positive_output_vault_balance as
None, so the new balance-based filtering is never applied; change the
construction in fetch_orders_for_pair (the GetOrdersFilters creation) to set
has_positive_output_vault_balance: Some(true) when this helper is used for quote
candidate discovery, or alternatively add a boolean parameter to
fetch_orders_for_pair (e.g., require_positive_output_vault_balance) and
propagate it to set has_positive_output_vault_balance accordingly; update all
callers of fetch_orders_for_pair involved in quote/candidate-building flows
(those found by searching for
fetch_orders_for_pair/get_quotes/order_quotes/build_candidate_from_quote) to
pass the flag so the local-db and SG paths actually enable the filter.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1664e9a1-35aa-4a29-bbd6-49c02007f9c7

📥 Commits

Reviewing files that changed from the base of the PR and between 07f0af9 and 56699f4.

📒 Files selected for processing (9)
  • crates/common/src/local_db/functions/float_gt_zero.rs
  • crates/common/src/local_db/functions/mod.rs
  • crates/common/src/local_db/query/fetch_orders/mod.rs
  • crates/common/src/local_db/query/fetch_orders/query.sql
  • crates/common/src/local_db/query/fetch_orders_common.rs
  • crates/common/src/local_db/query/fetch_orders_count/mod.rs
  • crates/common/src/local_db/query/fetch_orders_count/query.sql
  • crates/common/src/raindex_client/local_db/query/fetch_orders.rs
  • crates/common/src/raindex_client/orders.rs
✅ Files skipped from review due to trivial changes (1)
  • crates/common/src/local_db/query/fetch_orders_count/mod.rs

Comment on lines +49 to +66
pub(crate) const POSITIVE_OUTPUT_VAULT_BALANCE_CLAUSE: &str =
"/*POSITIVE_OUTPUT_VAULT_BALANCE_CLAUSE*/";
const POSITIVE_OUTPUT_VAULT_BALANCE_EXISTS_BODY: &str = "EXISTS (
SELECT 1 FROM order_ios io_balance
JOIN running_vault_balances vb_balance
ON vb_balance.chain_id = io_balance.chain_id
AND vb_balance.orderbook_address = io_balance.orderbook_address
AND vb_balance.owner = l.order_owner
AND vb_balance.token = io_balance.token
AND vb_balance.vault_id = io_balance.vault_id
WHERE io_balance.chain_id = l.chain_id
AND io_balance.orderbook_address = l.orderbook_address
AND io_balance.transaction_hash = la.transaction_hash
AND io_balance.log_index = la.log_index
AND lower(io_balance.io_type) = 'output'
AND io_balance.vault_id != {zero_vault_id}
AND FLOAT_GT_ZERO(vb_balance.balance)
)";
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Apr 30, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

This clause still works at order scope and still exempts vault id 0.

EXISTS (...) only proves that an order has some positive output vault, so mixed orders still keep their zero-balance output pairs. On top of that, io_balance.vault_id != {zero_vault_id} preserves the exact vault-id-0 bypass the PR is trying to remove. This needs pair-level filtering semantics, and the special-case exclusion for vault 0 should go away.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/common/src/local_db/query/fetch_orders_common.rs` around lines 49 -
66, The current POSITIVE_OUTPUT_VAULT_BALANCE_CLAUSE
(POSITIVE_OUTPUT_VAULT_BALANCE_EXISTS_BODY) only checks at order scope and still
exempts vault_id 0; change it to enforce pair-level semantics and drop the
special-case vault 0 exclusion. Update the EXISTS subquery so it correlates to
the specific pair (match io_balance and vb_balance to the pair identifiers used
in the outer query — e.g., token / pair id columns used by aliases l and la or
whatever pair key is present) instead of only matching the order, and remove the
"AND io_balance.vault_id != {zero_vault_id}" predicate; ensure
vb_balance.balance is tested per that same pair
(FLOAT_GT_ZERO(vb_balance.balance)) so only output vaults for the exact pair are
considered.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

False positive for this use case.

outputs_ applies token_in, balance_gt: 0, and vaultId_not: 0 to the same output vault relation. With an output token filter, orders whose
requested output token vault has zero balance are excluded.

Returned data is still order-level, but pair pruning is not needed here.

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.

@findolor, thanks for the clarification — that makes sense. The EXISTS subquery is intentionally order-scoped (does this order have any output vault with a positive balance and non-zero vault id?), and the vault_id != {zero_vault_id} condition deliberately mirrors the vaultId_not: 0 predicate on the subgraph side to keep both paths consistent. Pair-level pruning isn't needed here, so the implementation is correct. I'll mark this as a false positive.


✏️ Learnings added
Learnt from: findolor
Repo: rainlanguage/raindex PR: 2562
File: crates/common/src/local_db/query/fetch_orders_common.rs:49-66
Timestamp: 2026-04-30T10:27:57.541Z
Learning: In `crates/common/src/local_db/query/fetch_orders_common.rs`, the `POSITIVE_OUTPUT_VAULT_BALANCE_EXISTS_BODY` SQL clause is intentionally order-scoped (EXISTS checks whether the order has at least one output vault with a positive balance). The `io_balance.vault_id != {zero_vault_id}` predicate is deliberate, mirroring the subgraph-side `vaultId_not: 0` filter. Pair-level filtering is not required here; order-level semantics are the intended behavior.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2399
File: crates/rest_api/src/routes/take_orders.rs:74-95
Timestamp: 2026-01-16T12:07:15.521Z
Learning: In Rust projects using utoipa, when you use #[schema(...)] attributes (for example #[schema(example = json!(...))]), the json! macro is handled internally by utoipa's proc-macro at compile time. You do not need to import serde_json::json! in the module for these attributes. Do not add a serde_json::json! import solely for these schema attributes; ensure serde_json is present only if used elsewhere."

Comment thread crates/common/src/raindex_client/orders.rs Outdated
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