Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add all_swaps_uuids_by_filter RPC #785. #800

Merged
merged 1 commit into from
Jan 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions etomic_build/client/all_swaps_uuids_by_filter
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data '
{
"userpass":"'$userpass'",
"method":"all_swaps_uuids_by_filter",
"my_coin":"MORTY"
}
'
46 changes: 25 additions & 21 deletions mm2src/database/my_swaps.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// This module contains code to work with my_swaps table in MM2 SQLite DB
use crate::mm2::lp_swap::{my_swaps_dir, MyRecentSwapsReq, SavedSwap};
use crate::mm2::lp_swap::{my_swaps_dir, MySwapsFilter, PagingOptions, SavedSwap};
use common::{log::{debug, error},
mm_ctx::MmArc,
read_dir,
Expand Down Expand Up @@ -146,36 +146,37 @@ fn offset_by_uuid(
Ok(offset.try_into().expect("row index should be always above zero"))
}

/// Adds where clauses determined by MyRecentSwapsReq
fn apply_my_recent_swaps_filter(builder: &mut SqlBuilder, params: &mut Vec<(&str, String)>, req: &MyRecentSwapsReq) {
if let Some(my_coin) = &req.my_coin {
/// Adds where clauses determined by MySwapsFilter
fn apply_my_swaps_filter(builder: &mut SqlBuilder, params: &mut Vec<(&str, String)>, filter: &MySwapsFilter) {
if let Some(my_coin) = &filter.my_coin {
builder.and_where("my_coin = :my_coin");
params.push((":my_coin", my_coin.clone()));
}

if let Some(other_coin) = &req.other_coin {
if let Some(other_coin) = &filter.other_coin {
builder.and_where("other_coin = :other_coin");
params.push((":other_coin", other_coin.clone()));
}

if let Some(from_timestamp) = &req.from_timestamp {
if let Some(from_timestamp) = &filter.from_timestamp {
builder.and_where("started_at >= :from_timestamp");
params.push((":from_timestamp", from_timestamp.to_string()));
}

if let Some(to_timestamp) = &req.to_timestamp {
if let Some(to_timestamp) = &filter.to_timestamp {
builder.and_where("started_at < :to_timestamp");
params.push((":to_timestamp", to_timestamp.to_string()));
}
}

pub fn select_uuids_for_recent_swaps_req(
pub fn select_uuids_by_my_swaps_filter(
conn: &Connection,
req: &MyRecentSwapsReq,
filter: &MySwapsFilter,
paging_options: Option<&PagingOptions>,
) -> SqlResult<RecentSwapsSelectSqlResult, SelectRecentSwapsUuidsErr> {
let mut query_builder = SqlBuilder::select_from(MY_SWAPS_TABLE);
let mut params = vec![];
apply_my_recent_swaps_filter(&mut query_builder, &mut params, req);
apply_my_swaps_filter(&mut query_builder, &mut params, filter);

// count total records matching the filter
let mut count_builder = query_builder.clone();
Expand All @@ -191,20 +192,23 @@ pub fn select_uuids_for_recent_swaps_req(
return Ok(RecentSwapsSelectSqlResult::default());
}

// calculate offset, page_number is ignored if from_uuid is set
let skipped = match req.from_uuid {
Some(uuid) => offset_by_uuid(conn, &query_builder, &params, &uuid)?,
None => match req.page_number {
Some(page) => (page.get() - 1) * req.limit,
None => 0,
},
};

// query the uuids finally
query_builder.field("uuid");
query_builder.order_desc("started_at");
query_builder.limit(req.limit);
query_builder.offset(skipped);

let skipped = match paging_options {
Some(paging) => {
// calculate offset, page_number is ignored if from_uuid is set
let offset = match paging.from_uuid {
Some(uuid) => offset_by_uuid(conn, &query_builder, &params, &uuid)?,
None => (paging.page_number.get() - 1) * paging.limit,
};
query_builder.limit(paging.limit);
query_builder.offset(offset);
offset
},
None => 0,
};

let uuids_query = query_builder.sql().expect("SQL query builder should never fail here");
debug!("Trying to execute SQL query {} with params {:?}", uuids_query, params);
Expand Down
75 changes: 53 additions & 22 deletions mm2src/lp_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
//
#![cfg_attr(not(feature = "native"), allow(dead_code))]

use crate::mm2::{database::my_swaps::{insert_new_swap, select_uuids_for_recent_swaps_req},
use crate::mm2::{database::my_swaps::{insert_new_swap, select_uuids_by_my_swaps_filter},
lp_network::broadcast_p2p_msg};
use async_std::sync as async_std_sync;
use bigdecimal::BigDecimal;
Expand Down Expand Up @@ -770,25 +770,64 @@ pub fn save_stats_swap_status(ctx: &MmArc, data: Json) {
unwrap!(save_stats_swap(ctx, &swap));
}

fn ten() -> usize { 10 }
const fn ten() -> usize { 10 }

fn one() -> NonZeroUsize { NonZeroUsize::new(1).unwrap() }

#[derive(Debug, Deserialize)]
pub struct MyRecentSwapsReq {
#[serde(default = "ten")]
pub limit: usize,
pub from_uuid: Option<Uuid>,
pub page_number: Option<NonZeroUsize>,
pub struct MySwapsFilter {
pub my_coin: Option<String>,
pub other_coin: Option<String>,
pub from_timestamp: Option<u64>,
pub to_timestamp: Option<u64>,
}

/// Returns the data of recent swaps of `my` node. Returns no more than `limit` records (default: 10).
/// Skips the first `skip` records (default: 0).
/// Returns *all* uuids of swaps, which match the selected filter.
pub fn all_swaps_uuids_by_filter(ctx: MmArc, req: Json) -> HyRes {
let filter: MySwapsFilter = try_h!(json::from_value(req));
let db_result = try_h!(select_uuids_by_my_swaps_filter(ctx.sqlite_connection(), &filter, None));

rpc_response(
200,
json!({
"result": {
"uuids": db_result.uuids,
"my_coin": filter.my_coin,
"other_coin": filter.other_coin,
"from_timestamp": filter.from_timestamp,
"to_timestamp": filter.to_timestamp,
"found_records": db_result.uuids.len(),
},
})
.to_string(),
)
}

#[derive(Debug, Deserialize)]
pub struct PagingOptions {
#[serde(default = "ten")]
pub limit: usize,
#[serde(default = "one")]
pub page_number: NonZeroUsize,
pub from_uuid: Option<Uuid>,
}

#[derive(Debug, Deserialize)]
pub struct MyRecentSwapsReq {
#[serde(flatten)]
paging_options: PagingOptions,
#[serde(flatten)]
filter: MySwapsFilter,
}

/// Returns the data of recent swaps of `my` node.
pub fn my_recent_swaps(ctx: MmArc, req: Json) -> HyRes {
let req: MyRecentSwapsReq = try_h!(json::from_value(req));
let db_result = try_h!(select_uuids_for_recent_swaps_req(ctx.sqlite_connection(), &req));
let db_result = try_h!(select_uuids_by_my_swaps_filter(
ctx.sqlite_connection(),
&req.filter,
Some(&req.paging_options),
));

// iterate over uuids trying to parse the corresponding files content and add to result vector
let swaps: Vec<Json> = db_result
Expand All @@ -806,25 +845,17 @@ pub fn my_recent_swaps(ctx: MmArc, req: Json) -> HyRes {
})
.collect();

let page_number = match req.page_number {
Some(number) => Json::from(number.get()),
None => match req.from_uuid {
Some(_) => Json::Null,
None => Json::from(1),
},
};

rpc_response(
200,
json!({
"result": {
"swaps": swaps,
"from_uuid": req.from_uuid,
"from_uuid": req.paging_options.from_uuid,
"skipped": db_result.skipped,
"limit": req.limit,
"limit": req.paging_options.limit,
"total": db_result.total_count,
"page_number": page_number,
"total_pages": calc_total_pages(db_result.total_count, req.limit),
"page_number": req.paging_options.page_number,
"total_pages": calc_total_pages(db_result.total_count, req.paging_options.limit),
"found_records": db_result.uuids.len(),
},
})
Expand Down
7 changes: 4 additions & 3 deletions mm2src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ use std::net::SocketAddr;

use crate::mm2::lp_ordermatch::{buy, cancel_all_orders, cancel_order, my_orders, order_status, orderbook, sell,
set_price};
use crate::mm2::lp_swap::{active_swaps_rpc, coins_needed_for_kick_start, import_swaps, list_banned_pubkeys,
max_taker_vol, my_recent_swaps, my_swap_status, recover_funds_of_swap, stats_swap_status,
unban_pubkeys};
use crate::mm2::lp_swap::{active_swaps_rpc, all_swaps_uuids_by_filter, coins_needed_for_kick_start, import_swaps,
list_banned_pubkeys, max_taker_vol, my_recent_swaps, my_swap_status, recover_funds_of_swap,
stats_swap_status, unban_pubkeys};

#[path = "rpc/lp_commands.rs"] pub mod lp_commands;
use self::lp_commands::*;
Expand Down Expand Up @@ -119,6 +119,7 @@ pub fn dispatcher(req: Json, ctx: MmArc) -> DispatcherRes {
// Sorted alphanumerically (on the first latter) for readability.
// "autoprice" => lp_autoprice (ctx, req),
"active_swaps" => hyres(active_swaps_rpc(ctx, req)),
"all_swaps_uuids_by_filter" => all_swaps_uuids_by_filter(ctx, req),
"buy" => hyres(buy(ctx, req)),
"cancel_all_orders" => hyres(cancel_all_orders(ctx, req)),
"cancel_order" => hyres(cancel_order(ctx, req)),
Expand Down