Skip to content

primitives - Balances & BalancesState #423

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

Merged
merged 5 commits into from
Aug 24, 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
112 changes: 33 additions & 79 deletions primitives/src/sentry/accounting.rs → primitives/src/balances.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,14 @@
use std::{convert::TryFrom, marker::PhantomData};

use crate::{balances_map::UnifiedMap, channel_v5::Channel, Address, UnifiedNum};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Deserializer, Serialize};
use crate::{Address, UnifiedMap, UnifiedNum};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use thiserror::Error;

#[derive(Serialize, Debug, Clone, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct Accounting<S: BalancesState> {
pub channel: Channel,
#[serde(flatten)]
pub balances: Balances<S>,
pub updated: Option<DateTime<Utc>>,
pub created: DateTime<Utc>,
}

#[derive(Serialize, Debug, Clone, PartialEq, Eq, Default)]
#[serde(rename_all = "camelCase")]
pub struct Balances<S> {
pub struct Balances<S: BalancesState> {
pub earners: UnifiedMap,
pub spenders: UnifiedMap,
#[serde(skip_serializing, skip_deserializing)]
state: PhantomData<S>,
}

Expand Down Expand Up @@ -82,6 +70,14 @@ impl<S: BalancesState> Balances<S> {
.entry(earner)
.or_insert_with(UnifiedNum::default);
}

pub fn into_unchecked(self) -> Balances<UncheckedState> {
Balances {
earners: self.earners,
spenders: self.spenders,
state: PhantomData::default(),
}
}
}

#[derive(Debug, Error)]
Expand All @@ -103,15 +99,25 @@ pub enum Error {
},
}

pub trait BalancesState {}
pub trait BalancesState: std::fmt::Debug + Eq + Clone + Serialize + DeserializeOwned {
fn from_unchecked(balances: Balances<UncheckedState>) -> Result<Balances<Self>, Error>;
}

#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
pub struct CheckedState;
impl BalancesState for CheckedState {}
impl BalancesState for CheckedState {
fn from_unchecked(balances: Balances<UncheckedState>) -> Result<Balances<Self>, Error> {
balances.check()
}
}

#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
pub struct UncheckedState;
impl BalancesState for UncheckedState {}
impl BalancesState for UncheckedState {
fn from_unchecked(balances: Balances<Self>) -> Result<Balances<Self>, Error> {
Ok(balances)
}
}

impl TryFrom<Balances<UncheckedState>> for Balances<CheckedState> {
type Error = Error;
Expand All @@ -123,82 +129,30 @@ impl TryFrom<Balances<UncheckedState>> for Balances<CheckedState> {

/// This modules implements the needed non-generic structs that help with Deserialization of the `Balances<S>`
mod de {
use super::*;

#[derive(Deserialize)]
struct DeserializeAccounting {
pub channel: Channel,
#[serde(flatten)]
pub balances: DeserializeBalances,
pub created: DateTime<Utc>,
pub updated: Option<DateTime<Utc>>,
}
use serde::Deserializer;

impl<'de> Deserialize<'de> for Accounting<UncheckedState> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let de_acc = DeserializeAccounting::deserialize(deserializer)?;

Ok(Self {
channel: de_acc.channel,
balances: Balances::<UncheckedState>::try_from(de_acc.balances)
.map_err(serde::de::Error::custom)?,
created: de_acc.created,
updated: de_acc.updated,
})
}
}

impl<'de> Deserialize<'de> for Accounting<CheckedState> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let unchecked_acc = Accounting::<UncheckedState>::deserialize(deserializer)?;

Ok(Self {
channel: unchecked_acc.channel,
balances: unchecked_acc
.balances
.check()
.map_err(serde::de::Error::custom)?,
created: unchecked_acc.created,
updated: unchecked_acc.updated,
})
}
}
use super::*;

#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
struct DeserializeBalances {
pub earners: UnifiedMap,
pub spenders: UnifiedMap,
}

impl<'de> Deserialize<'de> for Balances<CheckedState> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let unchecked_balances = Balances::<UncheckedState>::deserialize(deserializer)?;

unchecked_balances.check().map_err(serde::de::Error::custom)
}
}

impl<'de> Deserialize<'de> for Balances<UncheckedState> {
impl<'de, S: BalancesState> Deserialize<'de> for Balances<S> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let deser_balances = DeserializeBalances::deserialize(deserializer)?;

Ok(Balances {
let unchecked_balances = Balances {
earners: deser_balances.earners,
spenders: deser_balances.spenders,
state: PhantomData::<UncheckedState>::default(),
})
};

S::from_unchecked(unchecked_balances).map_err(serde::de::Error::custom)
}
}

Expand Down
2 changes: 2 additions & 0 deletions primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub use self::{
ad_slot::AdSlot,
ad_unit::AdUnit,
address::Address,
balances::Balances,
balances_map::{BalancesMap, UnifiedMap},
big_num::BigNum,
campaign::{Campaign, CampaignId},
Expand All @@ -22,6 +23,7 @@ mod ad_unit;
pub mod adapter;
pub mod address;
pub mod analytics;
pub mod balances;
pub mod balances_map;
pub mod big_num;
pub mod campaign;
Expand Down
30 changes: 20 additions & 10 deletions primitives/src/sentry.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
use crate::{
balances::BalancesState,
channel_v5::Channel as ChannelV5,
validator::{ApproveState, Heartbeat, MessageTypes, NewState, Type as MessageType},
Address, BigNum, Channel, ChannelId, ValidatorId, IPFS,
Address, Balances, BigNum, Channel, ChannelId, ValidatorId, IPFS,
};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, fmt, hash::Hash};

pub mod accounting;
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct Accounting<S: BalancesState> {
pub channel: ChannelV5,
#[serde(flatten, bound = "S: BalancesState")]
pub balances: Balances<S>,
pub updated: Option<DateTime<Utc>>,
pub created: DateTime<Utc>,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct LastApproved {
pub struct LastApproved<S: BalancesState> {
/// NewState can be None if the channel is brand new
pub new_state: Option<MessageResponse<NewState>>,
#[serde(bound = "S: BalancesState")]
pub new_state: Option<MessageResponse<NewState<S>>>,
/// ApproveState can be None if the channel is brand new
pub approve_state: Option<MessageResponse<ApproveState>>,
}
Expand Down Expand Up @@ -53,7 +64,7 @@ pub mod message {
}

impl<T: Type> TryFrom<MessageTypes> for Message<T> {
type Error = MessageTypeError<T>;
type Error = MessageError<T>;

fn try_from(value: MessageTypes) -> Result<Self, Self::Error> {
<T as TryFrom<MessageTypes>>::try_from(value).map(Self)
Expand Down Expand Up @@ -81,8 +92,7 @@ pub mod message {
"type":"ApproveState",
"stateRoot":"4739522efc1e81499541621759dadb331eaf08829d6a3851b4b654dfaddc9935",
"signature":"0x00128a39b715e87475666c3220fc0400bf34a84d24f77571d2b4e1e88b141d52305438156e526ff4fe96b7a13e707ab2f6f3ca00bd928dabc7f516b56cfe6fd61c",
"isHealthy":true,
"exhausted":false
"isHealthy":true
},
"received":"2021-01-05T14:00:48.549Z"
});
Expand All @@ -96,7 +106,6 @@ pub mod message {
state_root: "4739522efc1e81499541621759dadb331eaf08829d6a3851b4b654dfaddc9935".to_string(),
signature: "0x00128a39b715e87475666c3220fc0400bf34a84d24f77571d2b4e1e88b141d52305438156e526ff4fe96b7a13e707ab2f6f3ca00bd928dabc7f516b56cfe6fd61c".to_string(),
is_healthy: true,
exhausted: false,
}),
};

Expand Down Expand Up @@ -184,8 +193,9 @@ pub struct ChannelListResponse {

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct LastApprovedResponse {
pub last_approved: Option<LastApproved>,
pub struct LastApprovedResponse<S: BalancesState> {
#[serde(bound = "S: BalancesState")]
pub last_approved: Option<LastApproved<S>>,
/// None -> withHeartbeat=true wasn't passed
/// Some(vec![]) (empty vec) or Some(heartbeats) - withHeartbeat=true was passed
#[serde(default, skip_serializing_if = "Option::is_none")]
Expand Down
Loading