Skip to content

Issue #382 Channel and Campaign Database & Persistance #400

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 25 commits into from
May 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b386a62
primitives - Config - change creators_whitelist to Address
elpiel Apr 28, 2021
dd2a007
primitives - WIP campaign_validator
elpiel Apr 28, 2021
29e7f7a
rustfmt & primitives - fix prep_db
elpiel Apr 28, 2021
35fe2a2
primtivies - campaign impls of FromSql, ToSql & Row:
elpiel Apr 28, 2021
cd691a6
sentry - db - campaign - insert_campaign
elpiel Apr 29, 2021
1c6e49b
WIP sentry - routes - campaign create
elpiel Apr 29, 2021
5c74e89
Added fetch campaign implementation + postgres integration tests
simzzz May 12, 2021
d0eadc8
removed a field which was retrieved twice
simzzz May 12, 2021
cfffdac
Imported active
simzzz May 12, 2021
05a39e1
removed try_from for from
simzzz May 13, 2021
71abe12
comitting progress
simzzz May 17, 2021
e6468bf
renamed function because of clippy
simzzz May 17, 2021
13c2c25
code clean up
simzzz May 17, 2021
78695f6
fixed failing test
simzzz May 17, 2021
9be0bc5
sentry - db - fix issue with creating test DB pool twice
elpiel May 18, 2021
0495813
requested changes from review
simzzz May 19, 2021
a5719e0
removed dbg
simzzz May 20, 2021
97fa17f
Merge pull request #401 from AdExNetwork/fetch_campaign_and_postgres_…
elpiel May 20, 2021
7a78f09
Merge branch 'aip-61-adex-v5' into issue-382-channel-and-campaign
elpiel May 20, 2021
869a141
sentry - db - campaing- fix warnings
elpiel May 20, 2021
dce8139
primitives - config - add min_validator_fee
elpiel May 20, 2021
33a6924
fix rustfmt & clippy
elpiel May 20, 2021
78dcc7f
primitives - remove ChannelValidator
elpiel May 20, 2021
7ae6e56
adapter - ethereum - fix test_utils
elpiel May 20, 2021
21037aa
primitives - config - clean-up old unused values
elpiel May 20, 2021
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
2 changes: 2 additions & 0 deletions adapter/src/ethereum/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ pub async fn deploy_token_contract(
let token_info = TokenInfo {
min_token_units_for_deposit: BigNum::from(min_token_units),
precision: NonZeroU8::new(18).expect("should create NonZeroU8"),
// 0.000_1
min_validator_fee: BigNum::from(100_000_000_000_000),
};

Ok((token_info, token_contract.address(), token_contract))
Expand Down
22 changes: 15 additions & 7 deletions docs/config/dev.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ validator_tick_timeout = 5000
ip_rate_limit = { type = 'ip', timeframe = 20000 }
sid_rate_limit = { type = 'sid', timeframe = 20000 }

ethereum_core_address = '0x333420fc6a897356e69b62417cd17ff012177d2b'
# TODO: Replace with real contract address
outpace_address = '0x333420fc6a897356e69b62417cd17ff012177d2b'
# TODO: Replace with real contract address
Expand All @@ -29,21 +28,30 @@ ethereum_network = 'http://localhost:8545'
ethereum_adapter_relayer = 'https://goerli-relayer.adex.network'

creators_whitelist = []
minimal_deposit = "0"
minimal_fee = "0"
validators_whitelist = []

[[token_address_whitelist]]
address = '0x73967c6a0904aa032c103b4104747e88c566b1a2' #DAI
# DAI
address = '0x73967c6a0904aa032c103b4104747e88c566b1a2'
# 1 * 10^-10 = 0.0_000_000_001
min_token_units_for_deposit = '100000000'
min_validator_fee = '100000000'
precision = 18

[[token_address_whitelist]]
address = '0x509ee0d083ddf8ac028f2a56731412edd63223b9' #USDT
min_token_units_for_deposit = '100000000'
# USDT
address = '0x509ee0d083ddf8ac028f2a56731412edd63223b9'
# 1.000_000
min_token_units_for_deposit = '1000000'
# 0.001
min_validator_fee = '1000'
precision = 6

[[token_address_whitelist]]
address = '0x44dcfcead37be45206af6079648988b29284b2c6' #USDC
# USDC
address = '0x44dcfcead37be45206af6079648988b29284b2c6'
# 1.000_000
min_token_units_for_deposit = '100000000'
# 0.001
min_validator_fee = '1000'
precision = 6
30 changes: 21 additions & 9 deletions docs/config/prod.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ validator_tick_timeout = 10000

ip_rate_limit = { type = 'ip', timeframe = 1200000 }
sid_rate_limit = { type = 'sid', timeframe = 0 }
ethereum_core_address = '0x333420fc6a897356e69b62417cd17ff012177d2b'

# TODO: Replace with real contract address
outpace_address = '0x333420fc6a897356e69b62417cd17ff012177d2b'
# TODO: Replace with real contract address
Expand All @@ -28,27 +28,39 @@ ethereum_network = 'http://localhost:8545'
ethereum_adapter_relayer = 'https://relayer.adex.network'

creators_whitelist = []
minimal_deposit = "0"
minimal_fee = "0"
validators_whitelist = []


[[token_address_whitelist]]
address = '0x6b175474e89094c44da98b954eedeac495271d0f' #DAI
# DAI
address = '0x6b175474e89094c44da98b954eedeac495271d0f'
# 1 * 10^-10 = 0.0_000_000_001
min_token_units_for_deposit = '100000000'
min_validator_fee = '100000000'
precision = 18

[[token_address_whitelist]]
address = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359' #SAI
# SAI
address = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359'
# 1 * 10^-10 = 0.0_000_000_001
min_token_units_for_deposit = '100000000'
min_validator_fee = '100000000'
precision = 18

[[token_address_whitelist]]
address = '0xdac17f958d2ee523a2206206994597c13d831ec7' #USDT
min_token_units_for_deposit = '100000000'
# USDT
address = '0xdac17f958d2ee523a2206206994597c13d831ec7'
# 1.000_000
min_token_units_for_deposit = '1000000'
# 0.001
min_validator_fee = '1000'
precision = 6

[[token_address_whitelist]]
address = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' #USDC
# USDC
address = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
# 1.000_000
min_token_units_for_deposit = '100000000'
# 0.001
min_validator_fee = '1000'
precision = 6

31 changes: 31 additions & 0 deletions primitives/src/ad_unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,34 @@ pub struct AdUnit {
)]
pub modified: Option<DateTime<Utc>>,
}

#[cfg(feature = "postgres")]
mod postgres {
use super::AdUnit;

use bytes::BytesMut;
use postgres_types::{accepts, to_sql_checked, FromSql, IsNull, Json, ToSql, Type};
use std::error::Error;
impl<'a> FromSql<'a> for AdUnit {
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
let json = <Json<Self> as FromSql>::from_sql(ty, raw)?;

Ok(json.0)
}

accepts!(JSONB);
}

impl ToSql for AdUnit {
fn to_sql(
&self,
ty: &Type,
w: &mut BytesMut,
) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
Json(self).to_sql(ty, w)
}

accepts!(JSONB);
to_sql_checked!();
}
}
3 changes: 1 addition & 2 deletions primitives/src/adapter.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::{
channel::ChannelError, channel_v5::Channel, Address,
BigNum, DomainError, ValidatorId,
channel::ChannelError, channel_v5::Channel, Address, BigNum, DomainError, ValidatorId,
};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
Expand Down
167 changes: 120 additions & 47 deletions primitives/src/campaign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ mod campaign_id {
pub struct CampaignId([u8; 16]);

impl CampaignId {
/// Generates randomly a `CampaignId` using `Uuid::new_v4().to_simple()`
pub fn new() -> Self {
Self::default()
}
Expand Down Expand Up @@ -184,32 +185,26 @@ pub struct Campaign {
}

impl Campaign {
pub fn find_validator(&self, validator: ValidatorId) -> Option<&'_ ValidatorDesc> {
pub fn find_validator(&self, validator: &ValidatorId) -> Option<ValidatorRole<'_>> {
match (self.leader(), self.follower()) {
(Some(leader), _) if leader.id == validator => Some(leader),
(_, Some(follower)) if follower.id == validator => Some(follower),
(Some(leader), _) if &leader.id == validator => Some(ValidatorRole::Leader(leader)),
(_, Some(follower)) if &follower.id == validator => {
Some(ValidatorRole::Follower(follower))
}
_ => None,
}
}

/// Matches the Channel.leader to the Campaign.spec.leader
/// If they match it returns `Some`, otherwise, it returns `None`
pub fn leader(&self) -> Option<&'_ ValidatorDesc> {
if self.channel.leader == self.validators.leader().id {
Some(self.validators.leader())
} else {
None
}
self.validators.find(&self.channel.leader)
}

/// Matches the Channel.follower to the Campaign.spec.follower
/// If they match it returns `Some`, otherwise, it returns `None`
pub fn follower(&self) -> Option<&'_ ValidatorDesc> {
if self.channel.follower == self.validators.follower().id {
Some(self.validators.follower())
} else {
None
}
self.validators.find(&self.channel.follower)
}

/// Returns the pricing of a given event
Expand Down Expand Up @@ -289,10 +284,10 @@ pub mod validators {
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
/// A (leader, follower) tuple
/// Unordered list of the validators representing the leader & follower
pub struct Validators(ValidatorDesc, ValidatorDesc);

#[derive(Debug)]
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ValidatorRole<'a> {
Leader(&'a ValidatorDesc),
Follower(&'a ValidatorDesc),
Expand All @@ -308,33 +303,15 @@ pub mod validators {
}

impl Validators {
pub fn new(leader: ValidatorDesc, follower: ValidatorDesc) -> Self {
Self(leader, follower)
}

pub fn leader(&self) -> &ValidatorDesc {
&self.0
pub fn new(validators: (ValidatorDesc, ValidatorDesc)) -> Self {
Self(validators.0, validators.1)
}

pub fn follower(&self) -> &ValidatorDesc {
&self.1
}

pub fn find(&self, validator_id: &ValidatorId) -> Option<ValidatorRole<'_>> {
if &self.leader().id == validator_id {
Some(ValidatorRole::Leader(&self.leader()))
} else if &self.follower().id == validator_id {
Some(ValidatorRole::Follower(&self.follower()))
} else {
None
}
}

pub fn find_index(&self, validator_id: &ValidatorId) -> Option<u32> {
if &self.leader().id == validator_id {
Some(0)
} else if &self.follower().id == validator_id {
Some(1)
pub fn find(&self, validator_id: &ValidatorId) -> Option<&ValidatorDesc> {
if &self.0.id == validator_id {
Some(&self.0)
} else if &self.1.id == validator_id {
Some(&self.1)
} else {
None
}
Expand All @@ -346,8 +323,8 @@ pub mod validators {
}

impl From<(ValidatorDesc, ValidatorDesc)> for Validators {
fn from((leader, follower): (ValidatorDesc, ValidatorDesc)) -> Self {
Self(leader, follower)
fn from(validators: (ValidatorDesc, ValidatorDesc)) -> Self {
Self(validators.0, validators.1)
}
}

Expand Down Expand Up @@ -383,19 +360,115 @@ pub mod validators {
0 => {
self.index += 1;

Some(self.validators.leader())
Some(&self.validators.0)
}
1 => {
self.index += 1;

Some(self.validators.follower())
Some(&self.validators.1)
}
_ => None,
}
}
}
}

// TODO: Postgres Campaign
// TODO: Postgres CampaignSpec
// TODO: Postgres Validators
#[cfg(feature = "postgres")]
mod postgres {
use super::{Active, Campaign, CampaignId, PricingBounds, Validators};
use bytes::BytesMut;
use postgres_types::{accepts, to_sql_checked, FromSql, IsNull, Json, ToSql, Type};
use std::error::Error;
use tokio_postgres::Row;

impl From<&Row> for Campaign {
fn from(row: &Row) -> Self {
Self {
id: row.get("id"),
channel: row.get("channel"),
creator: row.get("creator"),
budget: row.get("budget"),
validators: row.get("validators"),
title: row.get("title"),
pricing_bounds: row.get("pricing_bounds"),
event_submission: row.get("event_submission"),
ad_units: row.get::<_, Json<_>>("ad_units").0,
targeting_rules: row.get("targeting_rules"),
created: row.get("created"),
active: Active {
from: row.get("active_from"),
to: row.get("active_to"),
},
}
}
}

impl<'a> FromSql<'a> for CampaignId {
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
let str_slice = <&str as FromSql>::from_sql(ty, raw)?;

Ok(str_slice.parse()?)
}

accepts!(TEXT, VARCHAR);
}

impl ToSql for CampaignId {
fn to_sql(
&self,
ty: &Type,
w: &mut BytesMut,
) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
self.to_string().to_sql(ty, w)
}

accepts!(TEXT, VARCHAR);
to_sql_checked!();
}

impl<'a> FromSql<'a> for Validators {
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
let json = <Json<Self> as FromSql>::from_sql(ty, raw)?;

Ok(json.0)
}

accepts!(JSONB);
}

impl ToSql for Validators {
fn to_sql(
&self,
ty: &Type,
w: &mut BytesMut,
) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
Json(self).to_sql(ty, w)
}

accepts!(JSONB);
to_sql_checked!();
}

impl<'a> FromSql<'a> for PricingBounds {
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
let json = <Json<Self> as FromSql>::from_sql(ty, raw)?;

Ok(json.0)
}

accepts!(JSONB);
}

impl ToSql for PricingBounds {
fn to_sql(
&self,
ty: &Type,
w: &mut BytesMut,
) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
Json(self).to_sql(ty, w)
}

accepts!(JSONB);
to_sql_checked!();
}
}
Loading