Skip to content

Commit d38288f

Browse files
extend one omni-executor to have multiple SendGrid key/email/sendname (#3560)
* add support for multiple client to get email code * clippy * fix cargo test * fmt * fix env name in ci * fix test * remove unnecessary comments and scope * fmt * add default for ci testing --------- Co-authored-by: Kai <7630809+Kailai-Wang@users.noreply.github.com>
1 parent 7a2d499 commit d38288f

File tree

17 files changed

+327
-114
lines changed

17 files changed

+327
-114
lines changed

tee-worker/omni-executor/.env.example

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
1-
# Sendgrid
2-
OE_SENDGRID_API_KEY=
3-
OE_SENDGRID_FROM_EMAIL=
4-
OE_SENDGRID_FROM_NAME=
1+
# Multi-Client Mailer Configuration
2+
# Console mailer for testing/development
3+
OE_MAILER_TYPE_CONSOLE=console
4+
OE_MAILER_FROM_EMAIL_CONSOLE=test@example.com
5+
OE_MAILER_FROM_NAME_CONSOLE='Console Mailer'
6+
7+
# Heima client configuration
8+
OE_MAILER_TYPE_HEIMA=sendgrid
9+
OE_MAILER_API_HOST_HEIMA=
10+
OE_MAILER_API_KEY_HEIMA=
11+
OE_MAILER_FROM_EMAIL_HEIMA=
12+
OE_MAILER_FROM_NAME_HEIMA='Heima Network'
13+
14+
# Wildmeta client configuration
15+
OE_MAILER_TYPE_WILDMETA=sendgrid
16+
OE_MAILER_API_HOST_WILDMETA=
17+
OE_MAILER_API_KEY_WILDMETA=
18+
OE_MAILER_FROM_EMAIL_WILDMETA=
19+
OE_MAILER_FROM_NAME_WILDMETA='Wildmeta'
520

621
# Pumpx
722
OE_PUMPX_API_BASE_URL=
@@ -21,6 +36,30 @@ OE_ETHEREUM_URL=
2136
OE_BSC_URL=
2237
OE_BSC_TESTNET_URL=
2338

39+
# Google OAuth
40+
OE_GOOGLE_CLIENT_ID=
41+
OE_GOOGLE_CLIENT_SECRET=
42+
43+
# Arbitrum
44+
OE_ARBITRUM_URL=
45+
OE_ARBITRUM_TESTNET_URL=
46+
47+
# HyperEVM
48+
OE_HYPEREVM_URL=
49+
OE_HYPEREVM_TESTNET_URL=
50+
51+
# Alchemy
52+
OE_ALCHEMY_KEY=
53+
54+
# Omni Account Factory
55+
OE_OMNI_FACTORY_ADDRESS=
56+
57+
# Entry Point
58+
OE_ENTRY_POINT_ADDRESS=
59+
60+
# Wildmeta API
61+
OE_WILDMETA_API_URL=
62+
2463
# Solana
2564
OE_SOLANA_URL=
2665

tee-worker/omni-executor/.env.test

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
11
RUST_LOG=debug,jsonrpsee-client=info
2-
OE_SENDGRID_API_HOST=http://127.0.0.1:3456/sendgrid/v3/mail/send
3-
OE_SENDGRID_API_KEY=sendgrid_api_key
4-
OE_SENDGRID_FROM_EMAIL=no-reply@heima.network
5-
OE_SENDGRID_FROM_NAME='Heima Dev Verify'
2+
3+
# Multi-client mailer test configuration
4+
OE_MAILER_TYPE_CONSOLE=console
5+
OE_MAILER_FROM_EMAIL_CONSOLE=test@example.com
6+
OE_MAILER_FROM_NAME_CONSOLE='Console Test Mailer'
7+
8+
OE_MAILER_TYPE_HEIMA=sendgrid
9+
OE_MAILER_API_HOST_HEIMA=http://127.0.0.1:3456/sendgrid/v3/mail/send
10+
OE_MAILER_API_KEY_HEIMA=sendgrid_api_key
11+
OE_MAILER_FROM_EMAIL_HEIMA=no-reply@heima.network
12+
OE_MAILER_FROM_NAME_HEIMA='Heima Dev Verify'
613
OE_PUMPX_API_BASE_URL=http://127.0.0.1:3456/pumpx
714
OE_BINANCE_API_KEY=binance_api_key
815
OE_BINANCE_API_SECRET=binance_api_secret
916
OE_BINANCE_API_BASE_URL=http://127.0.0.1:3456/binance
1017
OE_SOLANA_URL=http://127.0.0.1:3456/solana
1118
OE_BSC_URL=http://127.0.0.1:3456/evm/bsc
12-
OE_ETHERUM_URL=http://127.0.0.1:3456/evm/eth
19+
OE_ETHEREUM_URL=http://127.0.0.1:3456/evm/eth
20+
OE_GOOGLE_CLIENT_ID=test_google_client_id
21+
OE_GOOGLE_CLIENT_SECRET=test_google_client_secret
22+
OE_PARENTCHAIN_URL=ws://localhost:9944
23+
OE_ARBITRUM_URL=http://127.0.0.1:3456/evm/arbitrum
24+
OE_HYPEREVM_URL=http://127.0.0.1:3456/evm/hyperevm
25+
OE_ALCHEMY_KEY=test_alchemy_key
26+
OE_OMNI_FACTORY_ADDRESS=0x0000000000000000000000000000000000000000
27+
OE_ENTRY_POINT_ADDRESS=0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789
28+
OE_WILDMETA_API_URL=http://127.0.0.1:3456/wildmeta

tee-worker/omni-executor/LOCAL_DEV.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ Key environment variables (set in `.env` file):
164164
```bash
165165
# Mock server configuration
166166
OE_PUMPX_API_BASE_URL=http://omni-executor:3456/pumpx
167-
OE_MAILER_TYPE=console
167+
OE_MAILER_TYPE_CONSOLE=console
168168

169169
# Network endpoints
170170
OE_PARENTCHAIN_URL=ws://heima-node:9944
@@ -237,7 +237,7 @@ For even faster development, you can run the omni-executor directly without Dock
237237
export OE_PARENTCHAIN_URL=ws://localhost:9944
238238
export OE_ETHEREUM_URL=http://localhost:8545
239239
export OE_PUMPX_API_BASE_URL=http://localhost:3456/pumpx
240-
export OE_MAILER_TYPE=console
240+
export OE_MAILER_TYPE_CONSOLE=console
241241
export RUST_LOG=debug
242242
```
243243

tee-worker/omni-executor/config-loader/src/config.rs

Lines changed: 111 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
use std::collections::HashMap;
1818
use std::str::FromStr;
19-
use tracing::info;
19+
use tracing::{info, warn};
2020

2121
#[derive(Debug, Clone, PartialEq)]
2222
pub enum MailerType {
@@ -37,7 +37,6 @@ impl FromStr for MailerType {
3737
}
3838

3939
const DEFAULT_MAILER_TYPE: &str = "sendgrid";
40-
const DEFAULT_MAILER_API_HOST: &str = ""; // Optional
4140
const DEFAULT_MAILER_API_KEY: &str = "";
4241
const DEFAULT_MAILER_FROM_EMAIL: &str = "no-reply@example.com";
4342
const DEFAULT_MAILER_FROM_NAME: &str = "Heima Verify";
@@ -63,12 +62,29 @@ const DEFAULT_ENTRY_POINT_ADDRESS: &str = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026
6362
const DEFAULT_WILDMETA_API_URL: &str = "https://test-dex-api.heima.network";
6463

6564
#[derive(Debug, Clone)]
66-
pub struct ConfigLoader {
65+
pub struct MailerConfig {
6766
pub mailer_type: MailerType,
6867
pub mailer_api_host: Option<String>,
6968
pub mailer_api_key: String,
7069
pub mailer_from_email: String,
7170
pub mailer_from_name: String,
71+
}
72+
73+
impl Default for MailerConfig {
74+
fn default() -> Self {
75+
Self {
76+
mailer_type: MailerType::from_str(DEFAULT_MAILER_TYPE).unwrap_or(MailerType::Sendgrid),
77+
mailer_api_host: None,
78+
mailer_api_key: DEFAULT_MAILER_API_KEY.to_string(),
79+
mailer_from_email: DEFAULT_MAILER_FROM_EMAIL.to_string(),
80+
mailer_from_name: DEFAULT_MAILER_FROM_NAME.to_string(),
81+
}
82+
}
83+
}
84+
85+
#[derive(Debug, Clone)]
86+
pub struct ConfigLoader {
87+
pub mailer_configs: HashMap<String, MailerConfig>,
7288
pub google_client_id: String,
7389
pub google_client_secret: String,
7490
pub parentchain_url: String,
@@ -115,51 +131,6 @@ impl ConfigLoader {
115131
info!("Executing: {}", std::env::args().collect::<Vec<_>>().join(" "));
116132

117133
let vars: HashMap<&str, EnvVar> = HashMap::from([
118-
(
119-
"mailer_type",
120-
EnvVar {
121-
env_key: "OE_MAILER_TYPE",
122-
default: DEFAULT_MAILER_TYPE,
123-
sensitive: false,
124-
optional: false,
125-
},
126-
),
127-
(
128-
"mailer_api_host",
129-
EnvVar {
130-
env_key: "OE_SENDGRID_API_HOST",
131-
default: DEFAULT_MAILER_API_HOST,
132-
sensitive: false,
133-
optional: true,
134-
},
135-
),
136-
(
137-
"mailer_api_key",
138-
EnvVar {
139-
env_key: "OE_SENDGRID_API_KEY",
140-
default: DEFAULT_MAILER_API_KEY,
141-
sensitive: true,
142-
optional: false,
143-
},
144-
),
145-
(
146-
"mailer_from_email",
147-
EnvVar {
148-
env_key: "OE_SENDGRID_FROM_EMAIL",
149-
default: DEFAULT_MAILER_FROM_EMAIL,
150-
sensitive: false,
151-
optional: false,
152-
},
153-
),
154-
(
155-
"mailer_from_name",
156-
EnvVar {
157-
env_key: "OE_SENDGRID_FROM_NAME",
158-
default: DEFAULT_MAILER_FROM_NAME,
159-
sensitive: false,
160-
optional: false,
161-
},
162-
),
163134
(
164135
"google_client_id",
165136
EnvVar {
@@ -354,12 +325,10 @@ impl ConfigLoader {
354325
let get = |key: &str| get_env_value(&vars[key]).unwrap_or_default();
355326
let get_opt = |key: &str| get_env_value(&vars[key]);
356327

328+
let mailer_configs = Self::load_mailer_configs();
329+
357330
ConfigLoader {
358-
mailer_type: MailerType::from_str(&get("mailer_type")).unwrap_or(MailerType::Sendgrid),
359-
mailer_api_host: get_opt("mailer_api_host"),
360-
mailer_api_key: get("mailer_api_key"),
361-
mailer_from_email: get("mailer_from_email"),
362-
mailer_from_name: get("mailer_from_name"),
331+
mailer_configs,
363332
google_client_id: get("google_client_id"),
364333
google_client_secret: get("google_client_secret"),
365334
parentchain_url: get("parentchain_url"),
@@ -382,4 +351,93 @@ impl ConfigLoader {
382351
wildmeta_api_url: get("wildmeta_api_url"),
383352
}
384353
}
354+
355+
/// Load mailer configurations for multiple clients from environment variables
356+
/// Format: OE_MAILER_TYPE_{CLIENT}, OE_MAILER_API_HOST_{CLIENT}, etc.
357+
/// CLIENT can be HEIMA, WILDMETA, CONSOLE, etc.
358+
fn load_mailer_configs() -> HashMap<String, MailerConfig> {
359+
let mut configs = HashMap::new();
360+
361+
// Get all environment variables
362+
let env_vars: HashMap<String, String> = std::env::vars().collect();
363+
364+
// Find all unique client suffixes
365+
let mut clients = std::collections::HashSet::new();
366+
for key in env_vars.keys() {
367+
if key.starts_with("OE_MAILER_TYPE_") {
368+
// Extract client name from OE_MAILER_TYPE_{CLIENT}
369+
if let Some(client) = key.strip_prefix("OE_MAILER_TYPE_") {
370+
info!("Found mailer type configuration for client: {}", client);
371+
clients.insert(client.to_lowercase());
372+
}
373+
}
374+
}
375+
376+
info!("Total discovered clients: {:?}", clients);
377+
378+
// If no clients are configured via environment variables, provide default console fallback
379+
if clients.is_empty() {
380+
warn!("No mailer configurations found in environment variables. Adding default console mailer.");
381+
let default_config = MailerConfig {
382+
mailer_type: MailerType::Console,
383+
mailer_api_host: None,
384+
mailer_api_key: String::new(),
385+
mailer_from_email: "test@example.com".to_string(),
386+
mailer_from_name: "Default Console Mailer".to_string(),
387+
};
388+
configs.insert("console".to_string(), default_config);
389+
return configs;
390+
}
391+
392+
// Load configuration for each client
393+
for client in clients {
394+
let client_upper = client.to_uppercase();
395+
let mut config = MailerConfig::default();
396+
397+
// Load client-specific values, falling back to defaults
398+
if let Ok(mailer_type) = std::env::var(format!("OE_MAILER_TYPE_{}", client_upper)) {
399+
config.mailer_type =
400+
MailerType::from_str(&mailer_type).unwrap_or(config.mailer_type);
401+
}
402+
403+
if let Ok(api_host) = std::env::var(format!("OE_MAILER_API_HOST_{}", client_upper)) {
404+
config.mailer_api_host = if api_host.is_empty() { None } else { Some(api_host) };
405+
}
406+
407+
if let Ok(api_key) = std::env::var(format!("OE_MAILER_API_KEY_{}", client_upper)) {
408+
config.mailer_api_key = api_key;
409+
}
410+
411+
if let Ok(from_email) = std::env::var(format!("OE_MAILER_FROM_EMAIL_{}", client_upper))
412+
{
413+
config.mailer_from_email = from_email;
414+
}
415+
416+
if let Ok(from_name) = std::env::var(format!("OE_MAILER_FROM_NAME_{}", client_upper)) {
417+
config.mailer_from_name = from_name;
418+
}
419+
420+
info!(
421+
"Loaded mailer config for client '{}': type={:?}, from_email={}",
422+
client, config.mailer_type, config.mailer_from_email
423+
);
424+
425+
configs.insert(client.clone(), config);
426+
}
427+
428+
configs
429+
}
430+
431+
/// Get mailer configuration for a specific client
432+
pub fn get_mailer_config(&self, client_id: &str) -> Option<MailerConfig> {
433+
let client_key = client_id.to_lowercase();
434+
self.mailer_configs.get(&client_key).cloned()
435+
}
436+
437+
/// Get all available client configurations
438+
pub fn list_available_clients(&self) -> Vec<String> {
439+
let mut clients: Vec<String> = self.mailer_configs.keys().cloned().collect();
440+
clients.sort();
441+
clients
442+
}
385443
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
mod config;
2-
pub use config::{ConfigLoader, MailerType};
2+
3+
pub use config::{ConfigLoader, MailerConfig, MailerType};

tee-worker/omni-executor/docker/docker-compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ services:
2121
- OE_PUMPX_WORKER_URL=ws://omni-executor:2100
2222
- OE_PUMPX_API_BASE_URL=http://omni-executor:3456/pumpx/
2323
- OE_PUMPX_SIGNER_URL=http://omni-executor:3456/jsonrpc
24-
- OE_MAILER_TYPE=console
24+
- OE_MAILER_TYPE_CONSOLE=console
2525
# These should be set in the .env file or overridden as needed:
2626
# - OE_BSC_URL=
2727
# - OE_BSC_TESTNET_URL=
@@ -59,7 +59,7 @@ services:
5959
- "8545:8545"
6060
networks:
6161
- litentry-test-network
62-
62+
6363
aa-contracts-deploy:
6464
build:
6565
context: ..

tee-worker/omni-executor/executor-worker/src/main.rs

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use alloy::signers::local::PrivateKeySigner;
2424
use binance_api::BinanceApiClient;
2525
use clap::Parser;
2626
use cli::{Cli, Commands, RunArgs};
27-
use config_loader::{ConfigLoader, MailerType};
27+
use config_loader::ConfigLoader;
2828
use cross_chain_intent_executor::{Chain, CrossChainIntentExecutor, RpcEndpointRegistry};
2929
use ethereum_intent_executor::EthereumIntentExecutor;
3030
use ethereum_rpc::client::EthereumRpcClient;
@@ -40,7 +40,6 @@ use executor_crypto::rsa::{traits::PublicKeyParts, Rsa3072PubKey};
4040
use executor_crypto::{ecdsa, ed25519, PairTrait};
4141
use executor_primitives::AccountId;
4242
use executor_storage::{init_storage, StorageDB};
43-
use heima_identity_verification::web2::email::{mailer::MailerTrait, ConsoleMailer, Mailer};
4443
use intent_asset_lock::precise::PreciseAssetsLock;
4544
use intent_asset_lock::AccountAssetLocks;
4645
use metrics_exporter_prometheus::PrometheusBuilder;
@@ -542,23 +541,6 @@ async fn main() -> Result<(), ()> {
542541
let wildmeta_timestamp_storage =
543542
Arc::new(executor_storage::WildmetaTimestampStorage::new(storage_db.clone()));
544543

545-
// Create mailer instance based on config_loader only
546-
let mailer: Box<dyn MailerTrait + Send + Sync> = match config_loader.mailer_type {
547-
MailerType::Console => {
548-
info!("Using Console Mailer - verification codes will be printed to logs");
549-
Box::new(ConsoleMailer::new())
550-
},
551-
MailerType::Sendgrid => {
552-
info!("Using SendGrid Mailer - verification codes will be sent via email");
553-
Box::new(Mailer::new(
554-
config_loader.mailer_api_host.clone(),
555-
config_loader.mailer_api_key.clone(),
556-
config_loader.mailer_from_email.clone(),
557-
config_loader.mailer_from_name.clone(),
558-
))
559-
},
560-
};
561-
562544
start_rpc_server(
563545
worker_url.port().expect("Missing worker port"),
564546
shielding_key,
@@ -570,7 +552,6 @@ async fn main() -> Result<(), ()> {
570552
pumpx_signer_client,
571553
wildmeta_api,
572554
wildmeta_timestamp_storage,
573-
mailer,
574555
)
575556
.await
576557
.map_err(|e| {

0 commit comments

Comments
 (0)