Skip to content

Commit 7a54cbb

Browse files
committed
finished with the route
1 parent 22470df commit 7a54cbb

File tree

4 files changed

+84
-65
lines changed

4 files changed

+84
-65
lines changed

primitives/src/sentry.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,11 @@ pub struct SpenderResponse {
203203
pub spender_leaf: Option<SpenderLeaf>,
204204
}
205205

206+
#[derive(Serialize, Deserialize, Debug)]
207+
pub struct AllSpendersResponse {
208+
pub spenders: Option<HashMap<Address, SpenderResponse>>,
209+
}
210+
206211
// TODO: Maybe there is a better place for this struct
207212
#[derive(Serialize, Deserialize, Debug)]
208213
pub struct SpenderLeaf {

sentry/src/db/accounting.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use std::convert::TryFrom;
22

33
use chrono::{DateTime, Utc};
44
use primitives::{
5-
balances_map::UnifiedMap,
65
channel_v5::Channel,
76
sentry::accounting::{Accounting, Balances, CheckedState},
87
Address, ChannelId, UnifiedNum,
@@ -65,19 +64,6 @@ async fn insert_accounting(
6564
Accounting::try_from(&row).map_err(Error::Balances)
6665
}
6766

68-
async fn get_spenders_for_channel(pool: DbPool, channel_id: &ChannelId) {
69-
let client = pool.get().await?;
70-
71-
let statement = client
72-
.prepare("SELECT spenders FROM accounting WHERE channel_id = $1")
73-
.await?;
74-
75-
let rows = client.query(&statement, &[channel_id]).await?;
76-
let spenders: UnifiedMap = serde_json::from_value(rows)?;
77-
78-
Ok(spenders)
79-
}
80-
8167
#[cfg(test)]
8268
mod test {
8369
use primitives::util::tests::prep_db::{ADDRESSES, DUMMY_CAMPAIGN};

sentry/src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ use routes::analytics::{advanced_analytics, advertiser_analytics, analytics, pub
2525
use routes::campaign::{create_campaign, update_campaign};
2626
use routes::cfg::config;
2727
use routes::channel::{
28-
channel_list, channel_validate, create_channel, create_validator_messages, last_approved, get_spender_limits, get_all_spender_limits
28+
channel_list, channel_validate, create_channel, create_validator_messages,
29+
get_all_spender_limits, get_spender_limits, last_approved,
2930
};
3031
use slog::Logger;
3132
use std::collections::HashMap;
@@ -398,10 +399,11 @@ async fn channels_router<A: Adapter + 'static>(
398399
req = ChannelLoad.call(req, app).await?;
399400

400401
get_spender_limits(req, app).await
401-
} else if let(Some(caps), &Method::GET) = (CHANNEL_ALL_SPENDER_LIMITS.captures(&path), method) {
402+
} else if let (Some(caps), &Method::GET) = (CHANNEL_ALL_SPENDER_LIMITS.captures(&path), method)
403+
{
402404
req = AuthRequired.call(req, app).await?;
403405

404-
let param = let param = RouteParams(vec![caps
406+
let param = RouteParams(vec![caps
405407
.get(1)
406408
.map_or("".to_string(), |m| m.as_str().to_string())]);
407409
req.extensions_mut().insert(param);

sentry/src/routes/channel.rs

Lines changed: 74 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ use primitives::{
1212
adapter::Adapter,
1313
sentry::{
1414
channel_list::{ChannelListQuery, LastApprovedQuery},
15-
LastApproved, LastApprovedResponse, SuccessResponse, SpenderLeaf, SpenderResponse
15+
LastApproved, LastApprovedResponse, MessageResponse, SuccessResponse, SpenderLeaf, SpenderResponse, AllSpendersResponse
1616
},
1717
spender::{Spendable, Deposit},
18-
validator::MessageTypes,
18+
validator::{MessageTypes, NewState},
1919
channel_v5::Channel as ChannelV5,
20-
Address, Channel, ChannelId, UnifiedNum
20+
Address, BigNum, Channel, ChannelId, UnifiedNum
2121
};
2222
use slog::error;
2323
use std::{
@@ -273,25 +273,7 @@ pub async fn get_spender_limits<A: Adapter + 'static>(
273273
let channel_id = ChannelId::from_hex(route_params.index(0))?;
274274
let spender = Address::from_str(&route_params.index(1))?;
275275

276-
let default_response = Response::builder()
277-
.header("Content-type", "application/json")
278-
.body(
279-
serde_json::to_string(&SpenderResponse {
280-
total_deposited: None,
281-
spender_leaf: None,
282-
})?
283-
.into(),
284-
)
285-
.expect("should build response");
286-
287-
let approve_state = match latest_approve_state_v5(&app.pool, &channel).await? {
288-
Some(approve_state) => approve_state,
289-
None => return Ok(default_response),
290-
};
291-
292-
let state_root = approve_state.msg.state_root.clone();
293-
294-
let new_state = latest_new_state_v5(&app.pool, &channel, &state_root).await?.ok_or(ResponseError::BadRequest("non-existing NewState".to_string()))?;
276+
let new_state = get_corresponding_new_state(&app.pool, &channel).await.ok_or_else(|| ResponseError::NotFound)?;
295277

296278
let latest_spendable = fetch_spendable(app.pool.clone(), &spender, &channel_id)
297279
.await?;
@@ -306,54 +288,98 @@ pub async fn get_spender_limits<A: Adapter + 'static>(
306288
// Calculate total_spent
307289
let spender_balance = new_state.msg.balances.get(&spender).ok_or_else(|| ResponseError::BadRequest("No balance for this spender".to_string()))?;
308290

309-
let spender_balance = UnifiedNum::from_u64(spender_balance.to_u64().expect("Consider replacing this in a way that uses UnifiedMap"));
310-
let total_spent = total_deposited.checked_sub(&spender_balance).ok_or_else(|| ResponseError::BadRequest("Total spent is too large".to_string()))?;
311-
312-
let spender_leaf = SpenderLeaf {
313-
total_spent,
314-
// merkle_proof: [u8; 32], // TODO
315-
};
291+
// TODO: Maybe throw error if None?
292+
let spender_leaf = get_spender_leaf_for_spender(spender_balance, &total_deposited);
316293

317294
// Return
318295
let res = SpenderResponse {
319296
total_deposited: Some(total_deposited),
320-
spender_leaf: Some(spender_leaf),
297+
spender_leaf,
321298
};
322299
Ok(success_response(serde_json::to_string(&res)?))
323300
}
301+
324302
pub async fn get_all_spender_limits<A: Adapter + 'static>(
325303
req: Request<Body>,
326304
app: &Application<A>,
327305
) -> Result<Response<Body>, ResponseError> {
328-
let route_params = req
329-
.extensions()
330-
.get::<RouteParams>()
331-
.expect("request should have route params");
332-
333306
let channel = req
334307
.extensions()
335308
.get::<ChannelV5>()
336309
.expect("Request should have Channel")
337310
.to_owned();
338311

339-
// Get all spenders for this channel
312+
let new_state = get_corresponding_new_state(&app.pool, &channel).await.ok_or_else(|| ResponseError::NotFound)?;
313+
314+
let mut all_spender_limits: HashMap<Address, SpenderResponse> = HashMap::new();
315+
316+
// Using for loop to avoid async closures
317+
for (spender, balance) in new_state.msg.balances.iter() {
318+
let latest_spendable = fetch_spendable(app.pool.clone(), &spender, &channel.id()).await.expect("todo: fix");
319+
320+
let latest_spendable = match latest_spendable {
321+
Some(spendable) => spendable,
322+
None => create_spendable_document(&app.adapter, app.pool.clone(), &channel, &spender).await.expect("todo"),
323+
};
324+
325+
let total_deposited = latest_spendable.deposit.total.checked_add(&latest_spendable.deposit.still_on_create2).ok_or_else(|| ResponseError::BadRequest("Total Deposited is too large".to_string())).expect("todo");
326+
327+
// TODO: Maybe throw error if None?
328+
let spender_leaf = get_spender_leaf_for_spender(balance, &total_deposited);
329+
330+
let spender_response = SpenderResponse {
331+
total_deposited: Some(total_deposited),
332+
spender_leaf,
333+
};
340334

341-
// Calculate spender limits for every spender
335+
all_spender_limits.insert(spender.clone(), spender_response);
336+
}
342337

343338
// Format and return output
344339

345-
let default_response = Response::builder()
346-
.header("Content-type", "application/json")
347-
.body(
348-
serde_json::to_string(&LastApprovedResponse {
349-
last_approved: None,
350-
heartbeats: None,
351-
})?
352-
.into(),
353-
)
354-
.expect("should build response");
340+
let res = AllSpendersResponse {
341+
spenders: Some(all_spender_limits),
342+
};
343+
344+
Ok(success_response(serde_json::to_string(&res)?))
345+
}
346+
347+
async fn get_corresponding_new_state(pool: &DbPool, channel: &ChannelV5) -> Option<MessageResponse<NewState>> {
348+
// Get all spenders for this channel
349+
let approve_state = match latest_approve_state_v5(&pool, &channel).await {
350+
Ok(Some(approve_state)) => approve_state,
351+
_ => return None,
352+
};
353+
354+
let state_root = approve_state.msg.state_root.clone();
355+
356+
let new_state = match latest_new_state_v5(&pool, &channel, &state_root).await {
357+
Ok(Some(new_state)) => Some(new_state),
358+
_ => None,
359+
};
360+
361+
new_state
362+
}
363+
364+
// TODO pass UnifiedNum instead
365+
fn get_spender_leaf_for_spender(spender_balance: &BigNum, total_deposited: &UnifiedNum) -> Option<SpenderLeaf> {
366+
let spender_balance = match spender_balance.to_u64() {
367+
Some(balance) => UnifiedNum::from_u64(balance),
368+
None => return None,
369+
};
370+
371+
let total_spent = match total_deposited.checked_sub(&spender_balance) {
372+
Some(spent) => spent,
373+
None => return None,
374+
};
375+
376+
// Return
377+
let leaf = SpenderLeaf {
378+
total_spent,
379+
// merkle_proof: [u8; 32], // TODO
380+
};
355381

356-
Ok(success_response(serde_json::to_string(&default_response)?))
382+
Some(leaf)
357383
}
358384

359385
#[cfg(test)]

0 commit comments

Comments
 (0)