Skip to content

Commit d27986c

Browse files
authored
Merge pull request #10 from Lay3rLabs/deployment
Full service flow
2 parents ac5829b + 4585ac6 commit d27986c

File tree

20 files changed

+542
-153
lines changed

20 files changed

+542
-153
lines changed

Cargo.lock

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

Taskfile.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# This is mostly just a convenience to start common tasks from the root directory
22
version: "3"
33

4-
# silent: true
4+
silent: true
55

66
dotenv: [".env"]
77

builds/deployments/aggregator-submitter-cid.json

Lines changed: 0 additions & 8 deletions
This file was deleted.

builds/deployments/operator-email-reader-cid.json

Lines changed: 0 additions & 8 deletions
This file was deleted.

builds/deployments/service-handler-code-id.json

Lines changed: 0 additions & 5 deletions
This file was deleted.

docs/GettingStarted.md

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,62 @@
1010
8. Download the latest WIT definitions: `task components:fetch-wit`
1111
9. Copy `.example.env` to `.env` and replace the values
1212

13-
## Summary
13+
## TL;DR
14+
15+
1. Build all contracts, components, and schema
1416

15-
Start all backend services
1617
```bash
18+
task build-all
19+
```
20+
21+
2. Start all backend services
22+
23+
```bash
24+
task backend:start-all
25+
1726
# Alternatively, if you need more than one operator
27+
#
1828
# task backend:start-all OPERATORS=3
19-
task backend:start-all
2029
```
2130

22-
_... do stuff ..._
31+
3. Tap the faucet for all the mnemonics
32+
33+
```bash
34+
task deploy:tap-faucet-all
35+
```
36+
37+
4. Deploy everything
38+
39+
```bash
40+
task deploy:all
41+
42+
# Alternatively, skip uploading contracts, middleware, and/or components
43+
# this assumes they were already uploaded before and the output files exist
44+
#
45+
# task deploy:all SKIP_UPLOAD_CONTRACTS=true SKIP_UPLOAD_COMPONENTS=true SKIP_UPLOAD_MIDDLEWARE=true
46+
```
47+
48+
5. Send an email to the operator email address
49+
50+
See [LocalEmail](./LocalEmail.md) for using the local email server for testing, otherwise, use a real email server
51+
52+
6. Check the on-chain results
53+
54+
```bash
55+
task contracts:query-service-handler-emails
56+
```
57+
58+
7. When done, stop all backend services
2359

24-
Stop all backend services
2560
```bash
2661
task backend:stop-all
2762
```
2863

29-
But "do stuff" assumes you've build and tested all the contracts and components
30-
and sometimes you only want to start/stop parts of the backend
64+
Each of these steps can be done individually and with more granularity as needed.
65+
66+
Let's step through each of these:
67+
3168

32-
So, with that in mind...
3369

3470
## Building
3571

packages/components/aggregator/submitter/src/lib.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,21 @@ struct Component;
1717
impl Guest for Component {
1818
fn process_packet(_packet: Packet) -> Result<Vec<AggregatorAction>, String> {
1919
let chain = host::config_var("CHAIN").ok_or("CHAIN config var is required")?;
20-
let payments_addr = host::config_var("PAYMENTS_CONTRACT_ADDRESS")
21-
.ok_or("PAYMENTS_CONTRACT_ADDRESS config var is required")?;
20+
let service_handler_addr = host::config_var("SERVICE_HANDLER_CONTRACT_ADDRESS")
21+
.ok_or("SERVICE_HANDLER_CONTRACT_ADDRESS config var is required")?;
2222

2323
host::get_cosmos_chain_config(&chain)
2424
.ok_or(format!("failed to get chain config for {}", chain))?;
2525

26-
let payments_addr = CosmosAddr::new_str(&payments_addr, None).map_err(|e| e.to_string())?;
26+
let service_handler_addr =
27+
CosmosAddr::new_str(&service_handler_addr, None).map_err(|e| e.to_string())?;
2728

2829
Ok(vec![AggregatorAction::Submit(SubmitAction::Cosmos(
2930
CosmosSubmitAction {
3031
chain: chain.to_string(),
3132
address: CosmosAddress {
32-
bech32_addr: payments_addr.to_string(),
33-
prefix_len: payments_addr.prefix().len() as u32,
33+
bech32_addr: service_handler_addr.to_string(),
34+
prefix_len: service_handler_addr.prefix().len() as u32,
3435
},
3536
gas_price: None,
3637
},

packages/components/operator/email-reader/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ rust-version = "1.90.0"
1111
crate-type = ["cdylib"]
1212

1313
[dependencies]
14+
# Local
15+
app-contract-api = { workspace = true }
1416

1517
# Error handling
1618
anyhow = { workspace = true }
@@ -41,6 +43,9 @@ imap = { workspace = true, default-features = false }
4143
mailparse = { workspace = true }
4244
cfdkim = { workspace = true}
4345

46+
# Hashing
47+
sha2 = { workspace = true }
48+
4449
# Security
4550
zeroize = { workspace = true }
4651

packages/components/operator/email-reader/src/email/parser.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ pub struct EmailMessage {
1010
// 1) "Original sender" best-effort (From / Resent-From / Sender / envelope)
1111
pub original_sender: String,
1212
// 2) All DKIM-Signature header values (there can be multiple)
13-
dkim_signatures: Vec<String>,
13+
pub dkim_signatures: Vec<String>,
1414
// 3) Subject (decoded)
15-
subject: Option<String>,
15+
pub subject: Option<String>,
1616
// 4) Body (best-effort: prefer text/plain part; fall back to full text)
1717
pub body_text: Option<String>,
1818
// 5) Raw email bytes (can be parsed on demand)

packages/components/operator/email-reader/src/lib.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod email;
55
mod error;
66

77
use anyhow::bail;
8+
use app_contract_api::service_handler::msg::{CustomExecuteMsg, Email};
89
use cfdkim::verify_email_with_resolver;
910

1011
use crate::{email::verify::verify_email, wavs::operator::input::TriggerData};
@@ -38,6 +39,37 @@ impl Guest for Component {
3839

3940
async fn inner(trigger_action: TriggerAction) -> anyhow::Result<Vec<WasmResponse>> {
4041
match trigger_action.data {
42+
TriggerData::Cron(_) => {
43+
// TODO - read a batch instead of just one email
44+
let email = match email::read_next_email().await? {
45+
Some(email) => email,
46+
None => {
47+
return Ok(Vec::new());
48+
}
49+
};
50+
51+
verify_email(&email).await?;
52+
53+
// For right now, treat each email as its own event
54+
let event_id_salt = {
55+
use sha2::{Digest, Sha256};
56+
57+
let mut hasher = Sha256::new();
58+
hasher.update(&email.raw_bytes);
59+
hasher.finalize().to_vec()
60+
};
61+
62+
return Ok(vec![WasmResponse {
63+
payload: CustomExecuteMsg::Email(Email {
64+
from: email.original_sender,
65+
subject: email.subject.unwrap_or_default(),
66+
})
67+
.encode()
68+
.map_err(|e| anyhow::anyhow!("{e:?}"))?,
69+
ordering: None,
70+
event_id_salt: Some(event_id_salt),
71+
}]);
72+
}
4173
TriggerData::Raw(data) => {
4274
let data = std::str::from_utf8(&data)?;
4375
match data {

0 commit comments

Comments
 (0)