Skip to content

Commit 1c2d59e

Browse files
authored
Merge pull request #476 from AmbireTech/adview-manager-serve-ad
Initial AdView manager for `serve`-ing and testing generated code for ads
2 parents 4fce1c7 + 22be1e7 commit 1c2d59e

File tree

10 files changed

+776
-80
lines changed

10 files changed

+776
-80
lines changed

Cargo.lock

Lines changed: 473 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ members = [
44
"primitives",
55
"adapter",
66
"adview-manager",
7+
# Server for testing adview manager generated code
8+
"adview-manager/serve",
79
"validator_worker",
810
"sentry",
911
"test_harness",

adapter/src/ethereum.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ mod error;
3232
pub mod ewt;
3333

3434
#[cfg(any(test, feature = "test-util"))]
35+
#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))]
3536
pub mod test_util;
3637

3738
pub static OUTPACE_ABI: Lazy<&'static [u8]> =

adview-manager/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ serde_json = "^1.0"
1616
reqwest = { version = "0.11", features = ["json"] }
1717
url = { version = "^2.1", features = ["serde"] }
1818
# Logging
19-
slog = { version = "^2.5.2", features = ["max_level_trace"] }
19+
log = "0.4"
2020
# Async
2121
async-std = "^1.8"
2222
# Other

adview-manager/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# AdView Manager
2+
3+
Gives you the ability to generate the code for showing ads on a publisher website.
4+
5+
### Testing
6+
7+
There is a local server that you can run for testing purposes
8+
This server gives you access to routes for showing ads and in terms to view,
9+
the generated by this crate HTML/JavaScript code which is used on
10+
a publisher websites.
11+
12+
Running the local server:
13+
14+
`RUST_LOG=debug cargo run -p serve`
15+
16+
This will start a server at `127.0.0.1:3030`
17+
18+
You can use `RUST_LOG` environment variable to set the logging level
19+
for the server.
20+
21+
Routes:
22+
23+
- `GET /ad` - visualizes a single ad

adview-manager/serve/Cargo.toml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[package]
2+
authors = ["Ambire <[email protected]>", "Lachezar Lechev <[email protected]>"]
3+
edition = "2021"
4+
name = "serve"
5+
version = "0.1.0"
6+
license = "AGPL-3.0"
7+
publish = false
8+
9+
[features]
10+
11+
[dependencies]
12+
# Domain
13+
adex_primitives = { path = "../../primitives", package = "primitives", features = ["test-util"] }
14+
adview-manager = { path = "../" }
15+
chrono = "0.4"
16+
17+
# Async runtime
18+
tokio = { version = "1", features = ["macros", "time", "rt-multi-thread"] }
19+
20+
# Web Server
21+
warp = { version = "0.3" }
22+
23+
# Template engine
24+
tera = { version = "1" }
25+
26+
# Mocking Market calls
27+
wiremock = { version = "0.5" }
28+
29+
# (De)Serialization
30+
serde = { version = "^1.0", features = ["derive"] }
31+
32+
# Logging
33+
log = "0.4"
34+
env_logger = { version = "0.9" }

adview-manager/serve/src/main.rs

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
use adex_primitives::{
2+
supermarket::units_for_slot,
3+
targeting::{input::Global, Input},
4+
test_util::{DUMMY_CAMPAIGN, DUMMY_IPFS},
5+
ToHex,
6+
};
7+
use adview_manager::{get_unit_html_with_events, Manager, Options, Size};
8+
use chrono::Utc;
9+
use log::{debug, info};
10+
use warp::Filter;
11+
use wiremock::{
12+
matchers::{method, path, query_param},
13+
Mock, MockServer, ResponseTemplate,
14+
};
15+
16+
17+
use tera::{Tera, Context};
18+
19+
#[tokio::main]
20+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
21+
env_logger::init();
22+
23+
let serve_dir = match std::env::current_dir().unwrap() {
24+
serve_path if serve_path.ends_with("serve") => serve_path,
25+
adview_manager_path if adview_manager_path.ends_with("adview-manager") => adview_manager_path.join("serve"),
26+
// running from the Validator stack workspace
27+
workspace_path => workspace_path.join("adview-manager/serve")
28+
};
29+
30+
let templates_glob = format!("{}/templates/**/*.html", serve_dir.display());
31+
32+
info!("Tera templates glob path: {templates_glob}");
33+
// Use globbing
34+
let tera = Tera::new(&templates_glob)?;
35+
36+
// `GET /ad`
37+
let get_ad = warp::get().and(warp::path("ad")).then(move || {
38+
let tera = tera.clone();
39+
40+
async move {
41+
// let logger = logger.clone();
42+
// For mocking the `get_market_demand_resp` call
43+
let mock_server = MockServer::start().await;
44+
45+
let market_url = mock_server.uri().parse().unwrap();
46+
let whitelisted_tokens = vec!["0x6B175474E89094C44Da98b954EedeAC495271d0F"
47+
.parse()
48+
.expect("Valid token Address")];
49+
let disabled_video = false;
50+
let publisher_addr = "0x0000000000000000626f62627973686d75726461"
51+
.parse()
52+
.unwrap();
53+
54+
let options = Options {
55+
market_url,
56+
market_slot: DUMMY_IPFS[0],
57+
publisher_addr,
58+
// All passed tokens must be of the same price and decimals, so that the amounts can be accurately compared
59+
whitelisted_tokens,
60+
size: Some(Size::new(300, 100)),
61+
// TODO: Check this value
62+
navigator_language: Some("bg".into()),
63+
/// Defaulted
64+
disabled_video,
65+
disabled_sticky: false,
66+
};
67+
68+
let manager = Manager::new(options.clone(), Default::default())
69+
.expect("Failed to create Adview Manager");
70+
let pub_prefix = publisher_addr.to_hex();
71+
72+
let units_for_slot_resp = units_for_slot::response::Response {
73+
targeting_input_base: Input {
74+
ad_view: None,
75+
global: Global {
76+
ad_slot_id: options.market_slot.to_string(),
77+
ad_slot_type: "".into(),
78+
publisher_id: publisher_addr,
79+
country: Some("Bulgaria".into()),
80+
event_type: "IMPRESSION".into(),
81+
seconds_since_epoch: Utc::now(),
82+
user_agent_os: None,
83+
user_agent_browser_family: None,
84+
},
85+
campaign: None,
86+
balances: None,
87+
ad_unit_id: None,
88+
ad_slot: None,
89+
},
90+
accepted_referrers: vec![],
91+
fallback_unit: None,
92+
campaigns: vec![],
93+
};
94+
95+
// Mock the `get_market_demand_resp` call
96+
let mock_call = Mock::given(method("GET"))
97+
// &depositAsset={}&depositAsset={}
98+
.and(path(format!("units-for-slot/{}", options.market_slot)))
99+
// pubPrefix=HEX&depositAsset=0xASSET1&depositAsset=0xASSET2
100+
.and(query_param("pubPrefix", pub_prefix))
101+
.and(query_param(
102+
"depositAsset",
103+
"0x6B175474E89094C44Da98b954EedeAC495271d0F",
104+
))
105+
// .and(query_param("depositAsset[]", "0x6B175474E89094C44Da98b954EedeAC495271d03"))
106+
.respond_with(ResponseTemplate::new(200).set_body_json(units_for_slot_resp))
107+
.expect(1)
108+
.named("get_market_demand_resp");
109+
110+
// Mounting the mock on the mock server - it's now effective!
111+
mock_call.mount(&mock_server).await;
112+
113+
let demand_resp = manager
114+
.get_market_demand_resp()
115+
.await
116+
.expect("Should return Mocked response");
117+
118+
debug!("Mocked response: {demand_resp:?}");
119+
120+
let supermarket_ad_unit =
121+
adex_primitives::supermarket::units_for_slot::response::AdUnit {
122+
/// Same as `ipfs`
123+
id: DUMMY_IPFS[1],
124+
media_url: "ipfs://QmcUVX7fvoLMM93uN2bD3wGTH8MXSxeL8hojYfL2Lhp7mR".to_string(),
125+
media_mime: "image/jpeg".to_string(),
126+
target_url: "https://www.adex.network/?stremio-test-banner-1".to_string(),
127+
};
128+
129+
let code = get_unit_html_with_events(
130+
&options,
131+
&supermarket_ad_unit,
132+
"localhost",
133+
DUMMY_CAMPAIGN.id,
134+
&DUMMY_CAMPAIGN.validators,
135+
false,
136+
);
137+
138+
let html = {
139+
let mut context = Context::new();
140+
context.insert("ad_code", &code);
141+
142+
tera.render("ad.html", &context).expect("Should render")
143+
};
144+
145+
warp::reply::html(html)
146+
}
147+
});
148+
149+
warp::serve(get_ad).run(([127, 0, 0, 1], 3030)).await;
150+
151+
Ok(())
152+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
8+
<title>Serve an Ad</title>
9+
</head>
10+
11+
<body>
12+
{{ ad_code | safe }}
13+
</body>
14+
15+
</html>

0 commit comments

Comments
 (0)