Select Git revision
wallets.rs 7.54 KiB
// Copyright (C) 2020 Éloïs SANCHEZ.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::*;
use async_graphql::connection::*;
use duniter_gva_dbs_reader::{
wallets::{WalletSingleSigWithIdtyOpt, WalletWithIdtyOpt},
PagedData,
};
#[derive(Default)]
pub(crate) struct WalletsQuery;
#[async_graphql::Object]
impl WalletsQuery {
/// Universal dividends issued by a public key
#[allow(clippy::clippy::too_many_arguments)]
async fn wallets(
&self,
ctx: &async_graphql::Context<'_>,
#[graphql(desc = "minimal balance")] min_balance: Option<i64>,
#[graphql(desc = "pagination", default)] pagination: Pagination,
#[graphql(desc = "Wallet type filter", default)] wallet_type_filter: WalletTypeFilter,
) -> async_graphql::Result<Connection<String, Wallet, AggregateSum, EmptyFields>> {
let QueryContext { is_whitelisted } = ctx.data::<QueryContext>()?;
let data = ctx.data::<GvaSchemaData>()?;
let dbs_reader = data.dbs_reader();
let current_base =
if let Some(current_ud) = data.cm_accessor.get_current_meta(|cm| cm.current_ud).await {
current_ud.base()
} else {
0
};
let min_balance_opt = min_balance.map(|amount| SourceAmount::new(amount, current_base));
let PagedData {
data,
has_next_page,
has_previous_page,
}: PagedData<Vec<Wallet>> = match wallet_type_filter {
WalletTypeFilter::OnlyComplex => {
let pagination = Pagination::convert_to_page_info(pagination, *is_whitelisted)?;
data.dbs_pool
.execute(move |_| dbs_reader.wallets(true, min_balance_opt, pagination))
.await??
.map(|data| {
data.into_iter()
.map(|script_with_sa| Wallet {
script: script_with_sa.0.to_string(),
balance: AmountWithBase::from(script_with_sa.1),
idty: None,
})
.collect()
})
}
WalletTypeFilter::OnlySimple => {
let pagination = Pagination::convert_to_page_info(pagination, *is_whitelisted)?;
if ctx
.look_ahead()
.field("edges")
.field("node")
.field("idty")
.exists()
{
data.dbs_pool
.execute(move |shared_dbs| {
dbs_reader.wallets_single_sig_with_idty_opt(
&shared_dbs.bc_db_ro,
min_balance_opt,
pagination,
)
})
.await??
.map(|data| {
data.into_iter()
.map(|WalletSingleSigWithIdtyOpt(pk_with_sa, idty_opt)| Wallet {
script: pk_with_sa.0.to_string(),
balance: AmountWithBase::from(pk_with_sa.1),
idty: idty_opt.map(|idty_db| Identity {
is_member: idty_db.is_member,
username: idty_db.username,
}),
})
.collect()
})
} else {
data.dbs_pool
.execute(move |_| {
dbs_reader.wallets_single_sig(min_balance_opt, pagination)
})
.await??
.map(|data| {
data.into_iter()
.map(|pk_with_sa| Wallet {
script: pk_with_sa.0.to_string(),
balance: AmountWithBase::from(pk_with_sa.1),
idty: None,
})
.collect()
})
}
}
WalletTypeFilter::All => {
let pagination = Pagination::convert_to_page_info(pagination, *is_whitelisted)?;
if ctx
.look_ahead()
.field("edges")
.field("node")
.field("idty")
.exists()
{
data.dbs_pool
.execute(move |shared_dbs| {
dbs_reader.wallets_with_idty_opt(
&shared_dbs.bc_db_ro,
min_balance_opt,
pagination,
)
})
.await??
.map(|data| {
data.into_iter()
.map(|WalletWithIdtyOpt(script_with_sa, idty_opt)| Wallet {
script: script_with_sa.0.to_string(),
balance: AmountWithBase::from(script_with_sa.1),
idty: idty_opt.map(|idty_db| Identity {
is_member: idty_db.is_member,
username: idty_db.username,
}),
})
.collect()
})
} else {
data.dbs_pool
.execute(move |_| dbs_reader.wallets(false, min_balance_opt, pagination))
.await??
.map(|data| {
data.into_iter()
.map(|script_with_sa| Wallet {
script: script_with_sa.0.to_string(),
balance: AmountWithBase::from(script_with_sa.1),
idty: None,
})
.collect()
})
}
}
};
let sum = if ctx.look_ahead().field("aggregate").field("sum").exists() {
data.iter().map(|wallet| wallet.balance).sum()
} else {
AmountWithBase::default()
};
let mut conn = Connection::with_additional_fields(
has_previous_page,
has_next_page,
AggregateSum {
aggregate: Sum { sum },
},
);
conn.append(
data.into_iter()
.map(|wallet| Edge::new(wallet.script.clone(), wallet)),
);
Ok(conn)
}
}