Skip to content

Commit

Permalink
Implement pagination for QueryMsg::List
Browse files Browse the repository at this point in the history
  • Loading branch information
maurolacy committed Aug 29, 2020
1 parent 6168761 commit 963bf0c
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 10 deletions.
18 changes: 17 additions & 1 deletion contracts/cw20-atomic-swap/schema/query_msg.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,23 @@
],
"properties": {
"list": {
"type": "object"
"type": "object",
"properties": {
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"string",
"null"
]
}
}
}
}
},
Expand Down
30 changes: 26 additions & 4 deletions contracts/cw20-atomic-swap/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ pub fn query<S: Storage, A: Api, Q: Querier>(
msg: QueryMsg,
) -> StdResult<Binary> {
match msg {
QueryMsg::List {} => to_binary(&query_list(deps)?),
QueryMsg::List { start_after, limit } => to_binary(&query_list(deps, start_after, limit)?),
QueryMsg::Details { id } => to_binary(&query_details(deps, id)?),
}
}
Expand All @@ -200,9 +200,28 @@ fn query_details<S: Storage, A: Api, Q: Querier>(
Ok(details)
}

fn query_list<S: Storage, A: Api, Q: Querier>(deps: &Extern<S, A, Q>) -> StdResult<ListResponse> {
// Settings for pagination
const MAX_LIMIT: u32 = 30;
const DEFAULT_LIMIT: u32 = 10;

fn query_list<S: Storage, A: Api, Q: Querier>(
deps: &Extern<S, A, Q>,
start_after: Option<String>,
limit: Option<u32>,
) -> StdResult<ListResponse> {
let start = calc_range_start(start_after);
let limit = limit.unwrap_or(DEFAULT_LIMIT).min(MAX_LIMIT) as usize;
Ok(ListResponse {
swaps: all_swap_ids(&deps.storage)?,
swaps: all_swap_ids(&deps.storage, start, limit)?,
})
}

// This will set the first key after the provided key, by appending a 1 byte
fn calc_range_start(start_after: Option<String>) -> Option<Vec<u8>> {
start_after.map(|id| {
let mut v = Vec::from(id);
v.push(1);
v
})
}

Expand Down Expand Up @@ -565,7 +584,10 @@ mod tests {
handle(&mut deps, env.clone(), HandleMsg::Create(create2.clone())).unwrap();

// Get the list of ids
let query_msg = QueryMsg::List {};
let query_msg = QueryMsg::List {
start_after: None,
limit: None,
};
let ids: ListResponse = from_binary(&query(&mut deps, query_msg).unwrap()).unwrap();
assert_eq!(2, ids.swaps.len());
assert_eq!(vec!["swap0001", "swap0002"], ids.swaps);
Expand Down
5 changes: 4 additions & 1 deletion contracts/cw20-atomic-swap/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ pub fn is_valid_name(name: &str) -> bool {
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
/// Show all open swaps. Return type is ListResponse.
List {},
List {
start_after: Option<String>,
limit: Option<u32>,
},
/// Returns the details of the named swap, error if not created.
/// Return type: DetailsResponse.
Details { id: String },
Expand Down
13 changes: 9 additions & 4 deletions contracts/cw20-atomic-swap/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,14 @@ pub fn atomic_swaps_read<S: ReadonlyStorage>(storage: &S) -> ReadonlyBucket<S, A
}

/// This returns the list of ids for all active swaps
pub fn all_swap_ids<S: ReadonlyStorage>(storage: &S) -> StdResult<Vec<String>> {
pub fn all_swap_ids<S: ReadonlyStorage>(
storage: &S,
start: Option<Vec<u8>>,
limit: usize,
) -> StdResult<Vec<String>> {
prefixed_read(PREFIX_SWAP, storage)
.range(None, None, Order::Ascending)
.range(start.as_deref(), None, Order::Ascending)
.take(limit)
.map(|(k, _)| String::from_utf8(k).map_err(|_| StdError::invalid_utf8("Parsing swap id")))
.collect()
}
Expand All @@ -55,7 +60,7 @@ mod tests {
#[test]
fn test_no_swap_ids() {
let storage = MockStorage::new();
let ids = all_swap_ids(&storage).unwrap();
let ids = all_swap_ids(&storage, None, 10).unwrap();
assert_eq!(0, ids.len());
}

Expand All @@ -81,7 +86,7 @@ mod tests {
.save("zen".as_bytes(), &dummy_swap())
.unwrap();

let ids = all_swap_ids(&storage).unwrap();
let ids = all_swap_ids(&storage, None, 10).unwrap();
assert_eq!(3, ids.len());
assert_eq!(
vec!["assign".to_string(), "lazy".to_string(), "zen".to_string()],
Expand Down

0 comments on commit 963bf0c

Please sign in to comment.