Skip to content

Commit 5949b79

Browse files
committed
fix(cli): backfill active-filtered markets and dedupe status helper
- Keep markets list filling up to --limit when --active is set by paginating additional API pages\n- Preserve independent active/closed semantics while avoiding undersized result pages\n- Move shared Option<bool> filter matcher into commands/mod.rs and reuse in events/markets\n- Add/retain tests and run full suite
1 parent ae33669 commit 5949b79

File tree

3 files changed

+70
-17
lines changed

3 files changed

+70
-17
lines changed

src/commands/events.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use polymarket_client_sdk::gamma::{
88
},
99
};
1010

11-
use super::is_numeric_id;
11+
use super::{flag_matches, is_numeric_id};
1212
use crate::output::events::{print_event_detail, print_events_table};
1313
use crate::output::tags::print_tags_table;
1414
use crate::output::{OutputFormat, print_json};
@@ -78,10 +78,6 @@ fn apply_status_filters(
7878
.collect()
7979
}
8080

81-
fn flag_matches(value: Option<bool>, filter: Option<bool>) -> bool {
82-
filter.is_none_or(|expected| value == Some(expected))
83-
}
84-
8581
pub async fn execute(client: &gamma::Client, args: EventsArgs, output: OutputFormat) -> Result<()> {
8682
match args.command {
8783
EventsCommand::List {

src/commands/markets.rs

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use polymarket_client_sdk::gamma::{
1111
},
1212
};
1313

14-
use super::is_numeric_id;
14+
use super::{flag_matches, is_numeric_id};
1515
use crate::output::markets::{print_market_detail, print_markets_table};
1616
use crate::output::tags::print_tags_table;
1717
use crate::output::{OutputFormat, print_json};
@@ -87,8 +87,55 @@ fn apply_status_filters(
8787
.collect()
8888
}
8989

90-
fn flag_matches(value: Option<bool>, filter: Option<bool>) -> bool {
91-
filter.is_none_or(|expected| value == Some(expected))
90+
async fn list_markets(
91+
client: &gamma::Client,
92+
limit: i32,
93+
offset: Option<i32>,
94+
order: Option<String>,
95+
ascending: bool,
96+
active: Option<bool>,
97+
closed: Option<bool>,
98+
) -> Result<Vec<Market>> {
99+
let page_size = limit.max(1);
100+
let mut next_offset = offset.unwrap_or(0);
101+
let mut collected: Vec<Market> = Vec::new();
102+
103+
loop {
104+
let request = MarketsRequest::builder()
105+
.limit(page_size)
106+
.maybe_closed(closed)
107+
.maybe_offset(Some(next_offset))
108+
.maybe_order(order.clone())
109+
.maybe_ascending(if ascending { Some(true) } else { None })
110+
.build();
111+
112+
let page = client.markets(&request).await?;
113+
if page.is_empty() {
114+
break;
115+
}
116+
117+
let raw_count = page.len();
118+
collected.extend(apply_status_filters(page, active, closed));
119+
120+
if collected.len() >= page_size as usize {
121+
collected.truncate(page_size as usize);
122+
break;
123+
}
124+
125+
// Without an active filter, the API-side limit should be authoritative.
126+
if active.is_none() {
127+
break;
128+
}
129+
130+
// Reached end of available results from the backend.
131+
if raw_count < page_size as usize {
132+
break;
133+
}
134+
135+
next_offset += raw_count as i32;
136+
}
137+
138+
Ok(collected)
92139
}
93140

94141
pub async fn execute(
@@ -105,15 +152,8 @@ pub async fn execute(
105152
order,
106153
ascending,
107154
} => {
108-
let request = MarketsRequest::builder()
109-
.limit(limit)
110-
.maybe_closed(closed)
111-
.maybe_offset(offset)
112-
.maybe_order(order)
113-
.maybe_ascending(if ascending { Some(true) } else { None })
114-
.build();
115-
116-
let markets = apply_status_filters(client.markets(&request).await?, active, closed);
155+
let markets =
156+
list_markets(client, limit, offset, order, ascending, active, closed).await?;
117157

118158
match output {
119159
OutputFormat::Table => print_markets_table(&markets),

src/commands/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ pub fn parse_condition_id(s: &str) -> anyhow::Result<B256> {
3030
.map_err(|_| anyhow::anyhow!("Invalid condition ID: must be a 0x-prefixed 32-byte hex"))
3131
}
3232

33+
pub fn flag_matches(value: Option<bool>, filter: Option<bool>) -> bool {
34+
filter.is_none_or(|expected| value == Some(expected))
35+
}
36+
3337
#[cfg(test)]
3438
mod tests {
3539
use super::*;
@@ -87,4 +91,17 @@ mod tests {
8791
let err = parse_condition_id("garbage").unwrap_err().to_string();
8892
assert!(err.contains("32-byte"), "got: {err}");
8993
}
94+
95+
#[test]
96+
fn flag_matches_true_cases() {
97+
assert!(flag_matches(Some(true), Some(true)));
98+
assert!(flag_matches(Some(false), Some(false)));
99+
assert!(flag_matches(Some(true), None));
100+
}
101+
102+
#[test]
103+
fn flag_matches_false_cases() {
104+
assert!(!flag_matches(Some(true), Some(false)));
105+
assert!(!flag_matches(None, Some(true)));
106+
}
90107
}

0 commit comments

Comments
 (0)