1use serde::{Deserialize, Serialize};
2use std::collections::BTreeMap;
3
4#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
6pub enum FilterType {
7 Equals,
8 NotEquals,
9 GreaterThan,
10 LessThan,
11 GreaterOrEqualThan,
12 LessOrEqualThan,
13 Like,
14}
15
16#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
18pub enum ConjunctionType {
19 And,
20 Or,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct FilterPredicate {
26 #[serde(rename = "Type")]
27 pub predicate_type: String, #[serde(rename = "FilterType")]
29 pub filter_type: FilterType,
30 #[serde(rename = "Column")]
31 pub column: String,
32 #[serde(rename = "Value")]
33 pub value: serde_json::Value, }
35
36impl FilterPredicate {
37 pub fn new(
38 filter_type: FilterType,
39 column: String,
40 value: impl Into<serde_json::Value>,
41 ) -> Self {
42 Self {
43 predicate_type: "FilterPredicate".to_string(),
44 filter_type,
45 column,
46 value: value.into(),
47 }
48 }
49
50 pub fn equals(column: String, value: impl Into<serde_json::Value>) -> Self {
51 Self::new(FilterType::Equals, column, value)
52 }
53
54 pub fn not_equals(column: String, value: impl Into<serde_json::Value>) -> Self {
55 Self::new(FilterType::NotEquals, column, value)
56 }
57
58 pub fn greater_than(column: String, value: impl Into<serde_json::Value>) -> Self {
59 Self::new(FilterType::GreaterThan, column, value)
60 }
61
62 pub fn less_than(column: String, value: impl Into<serde_json::Value>) -> Self {
63 Self::new(FilterType::LessThan, column, value)
64 }
65
66 pub fn like(column: String, pattern: String) -> Self {
67 Self::new(FilterType::Like, column, pattern)
68 }
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
73pub struct Conjunction {
74 #[serde(rename = "Type")]
75 pub conjunction_type_name: String, #[serde(rename = "ConjunctionType")]
77 pub conjunction_type: ConjunctionType,
78 #[serde(rename = "Predicates")]
79 pub predicates: Vec<Filter>,
80}
81
82impl Conjunction {
83 pub fn new(conjunction_type: ConjunctionType, predicates: Vec<Filter>) -> Self {
84 Self {
85 conjunction_type_name: "Conjunction".to_string(),
86 conjunction_type,
87 predicates,
88 }
89 }
90
91 pub fn and(predicates: Vec<Filter>) -> Self {
92 Self::new(ConjunctionType::And, predicates)
93 }
94
95 pub fn or(predicates: Vec<Filter>) -> Self {
96 Self::new(ConjunctionType::Or, predicates)
97 }
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
102#[serde(untagged)]
103pub enum Filter {
104 Predicate(FilterPredicate),
105 Conjunction(Conjunction),
106}
107
108impl From<FilterPredicate> for Filter {
109 fn from(predicate: FilterPredicate) -> Self {
110 Filter::Predicate(predicate)
111 }
112}
113
114impl From<Conjunction> for Filter {
115 fn from(conjunction: Conjunction) -> Self {
116 Filter::Conjunction(conjunction)
117 }
118}
119
120#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
122pub enum SortOrder {
123 ASC,
124 DESC,
125}
126
127#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
129pub struct OrderBy {
130 #[serde(rename = "Column")]
131 pub column: String,
132 #[serde(rename = "SortOrder")]
133 pub sort_order: SortOrder,
134}
135
136impl OrderBy {
137 pub fn new(column: String, sort_order: SortOrder) -> Self {
138 Self { column, sort_order }
139 }
140
141 pub fn asc(column: String) -> Self {
142 Self::new(column, SortOrder::ASC)
143 }
144
145 pub fn desc(column: String) -> Self {
146 Self::new(column, SortOrder::DESC)
147 }
148}
149
150#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
152pub struct CursorColumn {
153 pub name: String,
154 pub sort_order: SortOrder,
155}
156
157impl CursorColumn {
158 pub fn new(name: String, sort_order: SortOrder) -> Self {
159 Self { name, sort_order }
160 }
161
162 pub fn asc(name: String) -> Self {
163 Self::new(name, SortOrder::ASC)
164 }
165
166 pub fn desc(name: String) -> Self {
167 Self::new(name, SortOrder::DESC)
168 }
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
173pub struct QueryParams {
174 #[serde(rename = "Namespace")]
175 pub namespace: String,
176 #[serde(rename = "Table")]
177 pub table: String,
178 #[serde(rename = "Columns")]
179 pub columns: Vec<String>,
180 #[serde(rename = "Filter")]
181 pub filter: Vec<Filter>,
182 #[serde(rename = "Order")]
183 pub order: Vec<OrderBy>,
184 #[serde(rename = "Limit", skip_serializing_if = "Option::is_none")]
185 pub limit: Option<u32>,
186}
187
188impl QueryParams {
189 pub fn new(namespace: String, table: String, columns: Vec<String>) -> Self {
190 Self {
191 namespace,
192 table,
193 columns,
194 filter: Vec::new(),
195 order: Vec::new(),
196 limit: None,
197 }
198 }
199
200 pub fn with_filter(mut self, filter: Vec<Filter>) -> Self {
201 self.filter = filter;
202 self
203 }
204
205 pub fn with_order(mut self, order: Vec<OrderBy>) -> Self {
206 self.order = order;
207 self
208 }
209
210 pub fn with_limit(mut self, limit: u32) -> Self {
211 self.limit = Some(limit);
212 self
213 }
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct ColumnInfo {
219 #[serde(rename = "Name")]
220 pub name: String,
221 #[serde(rename = "Type")]
222 pub column_type: String,
223}
224
225#[derive(Debug, Clone, Serialize, Deserialize)]
227pub struct TableInfo {
228 #[serde(rename = "Namespace")]
229 pub namespace: String,
230 #[serde(rename = "Table")]
231 pub table: String,
232 #[serde(rename = "Columns")]
233 pub columns: Vec<ColumnInfo>,
234}
235
236#[derive(Debug, Clone, Serialize, Deserialize)]
239pub struct EventRow {
240 pub block_number: u64,
241 pub transaction_index: u32,
242 pub log_index: u32,
243 pub batch_index: Option<u32>,
244 pub timestamp: Option<u64>,
245}
246
247#[derive(Debug, Clone, Serialize, Deserialize, Default)]
250pub struct Cursor {
251 pub block_number: u64,
252 pub transaction_index: u32,
253 pub log_index: u32,
254 pub batch_index: Option<u32>,
255 pub timestamp: Option<u64>,
256 #[serde(default)]
257 pub values: BTreeMap<String, serde_json::Value>,
258}
259
260impl Cursor {
261 pub fn value(&self, column: &str) -> Option<&serde_json::Value> {
262 self.values.get(column)
263 }
264
265 pub fn insert_value(&mut self, column: String, value: serde_json::Value) {
266 self.values.insert(column, value);
267 }
268}
269
270#[derive(Debug, Clone, Serialize, Deserialize)]
272pub struct PagedResult<TRow>
273where
274 TRow: Clone + Serialize,
275{
276 pub limit: u32,
278 pub size: u32,
280 pub first_cursor: Option<Cursor>,
282 pub last_cursor: Option<Cursor>,
284 pub sort_order: SortOrder,
286 pub has_more: bool,
288 pub results: Vec<TRow>,
290}
291
292impl<TRow> PagedResult<TRow>
293where
294 TRow: Clone + Serialize,
295{
296 pub fn new(
297 limit: u32,
298 results: Vec<TRow>,
299 sort_order: SortOrder,
300 has_more: bool,
301 first_cursor: Option<Cursor>,
302 last_cursor: Option<Cursor>,
303 ) -> Self {
304 let size = results.len() as u32;
305 Self {
306 limit,
307 size,
308 first_cursor,
309 last_cursor,
310 sort_order,
311 has_more,
312 results,
313 }
314 }
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct PagedQueryParams {
320 pub namespace: String,
322 pub table: String,
324 pub sort_order: SortOrder,
326 pub columns: Vec<String>,
328 #[serde(skip_serializing_if = "Option::is_none")]
330 pub filter: Option<Vec<Filter>>,
331 #[serde(skip_serializing_if = "Option::is_none")]
333 pub cursor_columns: Option<Vec<CursorColumn>>,
334 #[serde(skip_serializing_if = "Option::is_none")]
336 pub order_columns: Option<Vec<OrderBy>>,
337 pub limit: u32,
339}
340
341impl PagedQueryParams {
342 pub fn new(
343 namespace: String,
344 table: String,
345 sort_order: SortOrder,
346 columns: Vec<String>,
347 limit: u32,
348 ) -> Self {
349 Self {
350 namespace,
351 table,
352 sort_order,
353 columns,
354 filter: None,
355 cursor_columns: None,
356 order_columns: None,
357 limit,
358 }
359 }
360
361 pub fn with_filter(mut self, filter: Vec<Filter>) -> Self {
362 self.filter = Some(filter);
363 self
364 }
365
366 pub fn with_cursor_columns(mut self, cursor_columns: Vec<CursorColumn>) -> Self {
367 self.cursor_columns = Some(cursor_columns);
368 self
369 }
370
371 pub fn with_order_columns(mut self, order_columns: Vec<OrderBy>) -> Self {
372 self.order_columns = Some(order_columns);
373 self
374 }
375
376 pub fn resolved_cursor_columns(&self) -> Vec<CursorColumn> {
377 if let Some(cursor_columns) = &self.cursor_columns {
378 if !cursor_columns.is_empty() {
379 return cursor_columns.clone();
380 }
381 }
382
383 let mut columns = vec![
384 CursorColumn::new("blockNumber".to_string(), self.sort_order.clone()),
385 CursorColumn::new("transactionIndex".to_string(), self.sort_order.clone()),
386 CursorColumn::new("logIndex".to_string(), self.sort_order.clone()),
387 ];
388 if self.table == "TransferBatch" {
389 columns.push(CursorColumn::new(
390 "batchIndex".to_string(),
391 self.sort_order.clone(),
392 ));
393 }
394 columns
395 }
396
397 pub fn resolved_order_columns(&self) -> Vec<OrderBy> {
398 if let Some(order_columns) = &self.order_columns {
399 if !order_columns.is_empty() {
400 return order_columns.clone();
401 }
402 }
403
404 self.resolved_cursor_columns()
405 .into_iter()
406 .map(|column| OrderBy::new(column.name, column.sort_order))
407 .collect()
408 }
409}