Repository: Cardinal-Cryptography/zkOS-monorepo
Pull request #166: Relayer: new args + lib reorg
Author: login: pmikolajczyk41
Created: 2025-03-16T10:45:09Z | Merged: 2025-03-17T16:44:10Z

1. Added three new args to the configuration (not used yet):
   - `service_fee_percent`
   - `max_pocket_money`
   - `quote_validity`
2. Changed other configuration types from primitives to target (e.g. from `u64` to `Duration`) to avoid confusion and stupid mistakes.
3. Extracted some parts of `lib.rs` to submodules for clarity and better organisation 


Diff:
diff --git a/crates/shielder-relayer/README.md b/crates/shielder-relayer/README.md
index 5f13cf77..9648279b 100644
--- a/crates/shielder-relayer/README.md
+++ b/crates/shielder-relayer/README.md
@@ -32,30 +32,33 @@ make run
 The relayer service can be configured via CLI arguments or environment variables. Some options can do fallback to
 defaults not provided.
 
-| Option                            | Description                                                                                                                                                                             | Env variable                    | Default value               |
-|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------|-----------------------------|
-| `--logging-format`                | Logging format configuration.                                                                                                                                                           | `LOGGING_FORMAT`                | `Text`                      |
-|                                   |                                                                                                                                                                                         |                                 |                             |
-| `--host`                          | Host where the server should be run.                                                                                                                                                    | `RELAYER_HOST`                  | `0.0.0.0`                   |
-| `--port`                          | Port where the server should be run.                                                                                                                                                    | `RELAYER_PORT`                  | `4141`                      |
-| `--metrics-port`                  | Port where the server metrics should be exposed.                                                                                                                                        | `RELAYER_METRICS_PORT`          | `9615`                      |
-|                                   |                                                                                                                                                                                         |                                 |                             |
-| `--node-rpc-url`                  | URL of the Ethereum RPC node.                                                                                                                                                           | `NODE_RPC_URL`                  |                             |
-| `--shielder-contract-address`     | Address of the Shielder contract.                                                                                                                                                       | `SHIELDER_CONTRACT_ADDRESS`     |                             |
-| `--total-fee`                     | The total fee, which is used as an argument for `withdraw_native` call. It should be a fixed value, close to a sum of 'withdraw_native' on-chain gas cost and the intended relayer fee. | `TOTAL_FEE`                     | `"100_000_000_000_000_000"` |
-| `--relay-gas`                     | The estimated amount of gas 'withdraw_native' on-chain call burns.                                                                                                                      | `RELAY_GAS`                     | `2000000`.                  |
-| `--native-token`                  | Token native to chain where the relayer operates.                                                                                                                                       | `NATIVE_TOKEN`                  |                             |
-|                                   |                                                                                                                                                                                         |                                 |                             |
-| `--balance-monitor-interval-secs` | Interval (in seconds) for monitoring signers' balances.                                                                                                                                 | `BALANCE_MONITOR_INTERVAL_SECS` | `900`                       |
-| `--nonce-policy`                  | Nonce management policy.                                                                                                                                                                | `NONCE_POLICY`                  | `Caching`                   |
-| `--dry-running`                   | Dry running policy.                                                                                                                                                                     | `DRY_RUNNING`                   | `Always`                    |
-| `--relay-count-for-recharge`      | Relay count for recharge.                                                                                                                                                               | `RELAY_COUNT_FOR_RECHARGE`      | `20`                        |
-| `--token-config`                  | Token pricing configuration for tokens that are qualified as a fee token.                                                                                                               | `TOKEN_CONFIG`                  | empty                       |
-| `--price-feed-refresh-interval`   | Price feed refresh interval in seconds.                                                                                                                                                 | `PRICE_FEED_REFRESH_INTERVAL`   | `60`                        |
-| `--price-feed-validity`           | Price feed validity in seconds.                                                                                                                                                         | `PRICE_FEED_VALIDITY`           | `600`                       |
-|                                   |                                                                                                                                                                                         |                                 |                             |
-| `--fee-destination-key`           | Signing key of the address where the fees should go.                                                                                                                                    | `FEE_DESTINATION_KEY`           |                             |
-| `--signing-keys`                  | Signing keys of the relayer.                                                                                                                                                            | `RELAYER_SIGNING_KEYS`          |                             |
+| Option                            | Description                                                                                                                                                                             | Env variable                  | Default value             |
+|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------|---------------------------|
+| `--node-rpc-url`                  | URL of the Ethereum RPC node.                                                                                                                                                           | `NODE_RPC_URL`                |                           |
+| `--shielder-contract-address`     | Address of the Shielder contract.                                                                                                                                                       | `SHIELDER_CONTRACT_ADDRESS`   |                           |
+| `--native-token`                  | Token native to chain where the relayer operates.                                                                                                                                       | `NATIVE_TOKEN`                |                           |
+| `--fee-destination-key`           | Signing key of the address where the fees should go.                                                                                                                                    | `FEE_DESTINATION_KEY`         |                           |
+| `--signing-keys`                  | Signing keys of the relayer.                                                                                                                                                            | `RELAYER_SIGNING_KEYS`        |                           |
+|                                   |                                                                                                                                                                                         |                               |                           |
+| `--logging-format`                | Logging format configuration.                                                                                                                                                           | `LOGGING_FORMAT`              | `Text`                    |
+|                                   |                                                                                                                                                                                         |                               |                           |
+| `--host`                          | Host where the server should be run.                                                                                                                                                    | `RELAYER_HOST`                | `0.0.0.0`                 |
+| `--port`                          | Port where the server should be run.                                                                                                                                                    | `RELAYER_PORT`                | `4141`                    |
+| `--metrics-port`                  | Port where the server metrics should be exposed.                                                                                                                                        | `RELAYER_METRICS_PORT`        | `9615`                    |
+|                                   |                                                                                                                                                                                         |                               |                           |
+| `--total-fee`                     | The total fee, which is used as an argument for `withdraw_native` call. It should be a fixed value, close to a sum of 'withdraw_native' on-chain gas cost and the intended relayer fee. | `TOTAL_FEE`                   | `100_000_000_000_000_000` |
+| `--relay-gas`                     | The estimated amount of gas 'withdraw_native' on-chain call burns.                                                                                                                      | `RELAY_GAS`                   | `2000000`.                |
+|                                   |                                                                                                                                                                                         |                               |                           |
+| `--balance-monitor-interval-secs` | Interval (in seconds) for monitoring signers' balances.                                                                                                                                 | `BALANCE_MONITOR_INTERVAL`    | 900 seconds               |
+| `--nonce-policy`                  | Nonce management policy.                                                                                                                                                                | `NONCE_POLICY`                | `Caching`                 |
+| `--dry-running`                   | Dry running policy.                                                                                                                                                                     | `DRY_RUNNING`                 | `Always`                  |
+| `--relay-count-for-recharge`      | Relay count for recharge.                                                                                                                                                               | `RELAY_COUNT_FOR_RECHARGE`    | `20`                      |
+| `--token-config`                  | Token pricing configuration for tokens that are qualified as a fee token.                                                                                                               | `TOKEN_CONFIG`                | empty                     |
+| `--price-feed-refresh-interval`   | Price feed refresh interval in seconds.                                                                                                                                                 | `PRICE_FEED_REFRESH_INTERVAL` | 60 seconds                |
+| `--price-feed-validity`           | Price feed validity in seconds.                                                                                                                                                         | `PRICE_FEED_VALIDITY`         | 600 seconds               |
+| `--service-fee-percent`           | Commission fee percentage (added to the actual relay cost).                                                                                                                             | `SERVICE_FEE_PERCENT`         | 15%                       |
+| `--quote-validity`                | How long the quote provided by the service is valid. In seconds.                                                                                                                        | `QUOTE_VALIDITY`              | 15 seconds                |
+| `--max-pocket-money`              | Maximum pocket money relayer can provide.                                                                                                                                               | `MAX_POCKET_MONEY`            | `100_000_000_000_000_000` |
 
 # API
 
diff --git a/crates/shielder-relayer/src/config/cli.rs b/crates/shielder-relayer/src/config/cli.rs
index a28b49c1..121566a4 100644
--- a/crates/shielder-relayer/src/config/cli.rs
+++ b/crates/shielder-relayer/src/config/cli.rs
@@ -1,3 +1,6 @@
+use std::time::Duration;
+
+use alloy_primitives::U256;
 use clap::Parser;
 use shielder_relayer::*;
 
@@ -53,11 +56,12 @@ pub struct CLIConfig {
         long,
         help = "Interval (in seconds) for monitoring signers' balances.",
         long_help = format!("Interval (in seconds) for monitoring signers' balances. If not \
-            provided, the value from the environment variable `{BALANCE_MONITOR_INTERVAL_SECS_ENV}` \
+            provided, the value from the environment variable `{BALANCE_MONITOR_INTERVAL_ENV}` \
             will be used. If that is not set, the default value is \
-            `{DEFAULT_BALANCE_MONITOR_INTERVAL_SECS}`.")
+            `{}`.", DEFAULT_BALANCE_MONITOR_INTERVAL.as_secs()),
+        value_parser = parsing::parse_seconds
     )]
-    pub balance_monitor_interval_secs: Option<u64>,
+    pub balance_monitor_interval: Option<Duration>,
 
     #[clap(
         long,
@@ -128,9 +132,10 @@ pub struct CLIConfig {
         long_help = format!("The total fee, which is used as an argument for `withdraw_native` call. \
             It should be a fixed value, close to a sum of 'withdraw_native' on-chain gas cost and the intended relayer fee. \
             If not provided, the value from the environment variable `{TOTAL_FEE_ENV}` will be used. \
-            If that is not set, the default value is `{DEFAULT_TOTAL_FEE:?}`.")
+            If that is not set, the default value is `{DEFAULT_TOTAL_FEE:?}`."),
+        value_parser = parsing::parse_u256
     )]
-    pub total_fee: Option<String>,
+    pub total_fee: Option<U256>,
 
     #[clap(
         long,
@@ -162,25 +167,70 @@ pub struct CLIConfig {
         help = "Price feed refresh interval in seconds.",
         long_help = format!("Price feed refresh interval in seconds. If not provided, the value from the \
             environment variable `{PRICE_FEED_REFRESH_INTERVAL_ENV}` will be used. If that is not set,\
-            the default value is `{DEFAULT_PRICE_FEED_REFRESH_INTERVAL_SECS:?}`.")
+            the default value is `{DEFAULT_PRICE_FEED_REFRESH_INTERVAL:?}`."),
+        value_parser = parsing::parse_seconds
     )]
-    pub price_feed_refresh_interval: Option<u64>,
+    pub price_feed_refresh_interval: Option<Duration>,
 
     #[clap(
         long,
         help = "Price feed validity in seconds.",
         long_help = format!("Price feed validity in seconds. If not provided, the value from the \
             environment variable `{PRICE_FEED_VALIDITY_ENV}` will be used. If that is not set,\
-            the default value is `{DEFAULT_PRICE_FEED_VALIDITY_SECS:?}`.")
+            the default value is `{DEFAULT_PRICE_FEED_VALIDITY:?}`."),
+        value_parser = parsing::parse_seconds
     )]
-    pub price_feed_validity: Option<u64>,
+    pub price_feed_validity: Option<Duration>,
 
     #[clap(
         long,
         help = "Token native to chain where the relayer operates.",
-        long_help = format!("Token native to chain where the relayer operates. If not provided, the value\
+        long_help = format!("Token native to chain where the relayer operates. If not provided, the value \
             from the environment variable `{NATIVE_TOKEN_ENV}` will be used. Example values: 'eth', \
             'azero', 'btc'.")
     )]
     pub native_token: Option<Coin>,
+
+    #[clap(
+        long,
+        help = "Commission fee percentage (added to the actual relay cost).",
+        long_help = format!("Commission fee percentage (added to the actual relay cost). If not \
+        provided, the value from the environment variable `{SERVICE_FEE_PERCENT_ENV}` will be used.\
+        If that is not set, the default value is `{DEFAULT_SERVICE_FEE_PERCENT}`.")
+    )]
+    pub service_fee_percent: Option<u32>,
+
+    #[clap(
+        long,
+        help = "How long the quote provided by the service is valid. In seconds.",
+        long_help = format!("How long the quote provided by the service is valid. In seconds. If not \
+            provided, the value from the environment variable `{QUOTE_VALIDITY_ENV}` will be used.\
+            If that is not set, the default value is `{}`.", DEFAULT_QUOTE_VALIDITY.as_secs()),
+        value_parser = parsing::parse_seconds
+    )]
+    pub quote_validity: Option<Duration>,
+
+    #[clap(
+        long,
+        help = "Maximum pocket money relayer can provide.",
+        long_help = format!("Maximum pocket money relayer can provide. If not provided, the value \
+            from the environment variable `{MAX_POCKET_MONEY_ENV}` will be used. If that is not set, \
+            the default value is `{DEFAULT_MAX_POCKET_MONEY}`."),
+        value_parser = parsing::parse_u256
+    )]
+    pub max_pocket_money: Option<U256>,
+}
+
+pub(super) mod parsing {
+    use std::{str::FromStr, time::Duration};
+
+    use alloy_primitives::U256;
+
+    pub fn parse_seconds(string: &str) -> anyhow::Result<Duration> {
+        Ok(Duration::from_secs(string.parse::<u64>()?))
+    }
+
+    pub fn parse_u256(string: &str) -> anyhow::Result<U256> {
+        Ok(U256::from_str(string)?)
+    }
 }
diff --git a/crates/shielder-relayer/src/config/defaults.rs b/crates/shielder-relayer/src/config/defaults.rs
index ad6f2cd3..e63f60e5 100644
--- a/crates/shielder-relayer/src/config/defaults.rs
+++ b/crates/shielder-relayer/src/config/defaults.rs
@@ -1,16 +1,20 @@
+use std::time::Duration;
+
 use crate::config::{enums::DryRunning, LoggingFormat, NoncePolicy};
 
 pub const DEFAULT_LOGGING_FORMAT: LoggingFormat = LoggingFormat::Text;
 pub const DEFAULT_HOST: &str = "0.0.0.0";
 pub const DEFAULT_PORT: u16 = 4141;
 pub const DEFAULT_METRICS_PORT: u16 = 9615;
-pub const DEFAULT_BALANCE_MONITOR_INTERVAL_SECS: u64 = 60 * 15;
+pub const DEFAULT_BALANCE_MONITOR_INTERVAL: Duration = Duration::from_secs(15);
 pub const DEFAULT_NONCE_POLICY: NoncePolicy = NoncePolicy::Caching;
 pub const DEFAULT_DRY_RUNNING: DryRunning = DryRunning::Always;
 pub const DEFAULT_RELAY_COUNT_FOR_RECHARGE: u32 = 20;
 pub const DEFAULT_TOTAL_FEE: &str = "100_000_000_000_000_000"; // 0.1 TZERO
 pub const DEFAULT_RELAY_GAS: u64 = 2_000_000; // an estimated amount of gas for a 'withdraw_native' call
 
-const ONE_MINUTE_IN_SECONDS: u64 = 60;
-pub const DEFAULT_PRICE_FEED_VALIDITY_SECS: u64 = 10 * ONE_MINUTE_IN_SECONDS;
-pub const DEFAULT_PRICE_FEED_REFRESH_INTERVAL_SECS: u64 = ONE_MINUTE_IN_SECONDS;
+pub const DEFAULT_PRICE_FEED_VALIDITY: Duration = Duration::from_secs(600);
+pub const DEFAULT_PRICE_FEED_REFRESH_INTERVAL: Duration = Duration::from_secs(60);
+pub const DEFAULT_SERVICE_FEE_PERCENT: u32 = 15;
+pub const DEFAULT_QUOTE_VALIDITY: Duration = Duration::from_secs(15);
+pub const DEFAULT_MAX_POCKET_MONEY: &str = "100_000_000_000_000_000"; // 0.1 TZERO
diff --git a/crates/shielder-relayer/src/config/mod.rs b/crates/shielder-relayer/src/config/mod.rs
index 821b31ab..4256ba88 100644
--- a/crates/shielder-relayer/src/config/mod.rs
+++ b/crates/shielder-relayer/src/config/mod.rs
@@ -1,8 +1,10 @@
 use std::{
     fmt::{Debug, Formatter},
     str::FromStr,
+    time::Duration,
 };
 
+use anyhow::anyhow;
 use clap::Parser;
 use cli::CLIConfig;
 use defaults::*;
@@ -12,6 +14,8 @@ use serde::{Deserialize, Serialize};
 use shielder_contract::alloy_primitives::{Address, U256};
 use shielder_relayer::*;
 
+use crate::config::cli::parsing::{parse_seconds, parse_u256};
+
 mod cli;
 mod defaults;
 mod enums;
@@ -68,13 +72,16 @@ impl TokenConfig {
 
 #[derive(Clone, Eq, PartialEq, Debug)]
 pub struct OperationalConfig {
-    pub balance_monitor_interval_secs: u64,
+    pub balance_monitor_interval: Duration,
     pub nonce_policy: NoncePolicy,
     pub dry_running: DryRunning,
     pub relay_count_for_recharge: u32,
     pub token_config: Vec<TokenConfig>,
-    pub price_feed_validity: u64,
-    pub price_feed_refresh_interval: u64,
+    pub price_feed_validity: Duration,
+    pub price_feed_refresh_interval: Duration,
+    pub service_fee_percent: u32,
+    pub quote_validity: Duration,
+    pub max_pocket_money: U256,
 }
 
 #[derive(Clone, Eq, PartialEq)]
@@ -127,7 +134,7 @@ fn resolve_config_from_cli_config(
         host,
         port,
         metrics_port,
-        balance_monitor_interval_secs,
+        balance_monitor_interval,
         node_rpc_url,
         shielder_contract_address,
         fee_destination_key,
@@ -141,6 +148,9 @@ fn resolve_config_from_cli_config(
         price_feed_validity,
         price_feed_refresh_interval,
         native_token,
+        service_fee_percent,
+        quote_validity,
+        max_pocket_money,
     }: CLIConfig,
 ) -> ServerConfig {
     let to_address = |s: &str| Address::from_str(s).expect("Invalid address");
@@ -175,12 +185,11 @@ fn resolve_config_from_cli_config(
             SHIELDER_CONTRACT_ADDRESS_ENV,
             None,
         )),
-        total_fee: U256::from_str(&resolve_value(
+        total_fee: resolve_value(
             total_fee,
             TOTAL_FEE_ENV,
-            Some(DEFAULT_TOTAL_FEE.to_string()),
-        ))
-        .expect("Invalid relay fee"),
+            Some(parse_u256(DEFAULT_TOTAL_FEE).unwrap()),
+        ),
         relay_gas: resolve_value(relay_gas, RELAY_GAS_ENV, Some(DEFAULT_RELAY_GAS)),
         native_token: resolve_value(native_token, NATIVE_TOKEN_ENV, None),
     };
@@ -191,10 +200,11 @@ fn resolve_config_from_cli_config(
     let token_config = serde_json::from_str(&token_config).expect("Invalid token pricing");
 
     let operational_config = OperationalConfig {
-        balance_monitor_interval_secs: resolve_value(
-            balance_monitor_interval_secs,
-            BALANCE_MONITOR_INTERVAL_SECS_ENV,
-            Some(DEFAULT_BALANCE_MONITOR_INTERVAL_SECS),
+        balance_monitor_interval: resolve_value_map(
+            balance_monitor_interval,
+            BALANCE_MONITOR_INTERVAL_ENV,
+            parse_seconds,
+            Some(DEFAULT_BALANCE_MONITOR_INTERVAL),
         ),
         nonce_policy: resolve_value(nonce_policy, NONCE_POLICY_ENV, Some(DEFAULT_NONCE_POLICY)),
         dry_running: resolve_value(dry_running, DRY_RUNNING_ENV, Some(DEFAULT_DRY_RUNNING)),
@@ -204,15 +214,34 @@ fn resolve_config_from_cli_config(
             Some(DEFAULT_RELAY_COUNT_FOR_RECHARGE),
         ),
         token_config,
-        price_feed_validity: resolve_value(
+        price_feed_validity: resolve_value_map(
             price_feed_validity,
             PRICE_FEED_VALIDITY_ENV,
-            Some(DEFAULT_PRICE_FEED_VALIDITY_SECS),
+            parse_seconds,
+            Some(DEFAULT_PRICE_FEED_VALIDITY),
         ),
-        price_feed_refresh_interval: resolve_value(
+        price_feed_refresh_interval: resolve_value_map(
             price_feed_refresh_interval,
             PRICE_FEED_REFRESH_INTERVAL_ENV,
-            Some(DEFAULT_PRICE_FEED_REFRESH_INTERVAL_SECS),
+            parse_seconds,
+            Some(DEFAULT_PRICE_FEED_REFRESH_INTERVAL),
+        ),
+        service_fee_percent: resolve_value(
+            service_fee_percent,
+            SERVICE_FEE_PERCENT_ENV,
+            Some(DEFAULT_SERVICE_FEE_PERCENT),
+        ),
+        quote_validity: resolve_value_map(
+            quote_validity,
+            QUOTE_VALIDITY_ENV,
+            parse_seconds,
+            Some(DEFAULT_QUOTE_VALIDITY),
+        ),
+        max_pocket_money: resolve_value_map(
+            max_pocket_money,
+            MAX_POCKET_MONEY_ENV,
+            parse_u256,
+            Some(parse_u256(DEFAULT_MAX_POCKET_MONEY).unwrap()),
         ),
     };
 
@@ -229,11 +258,25 @@ fn resolve_config_from_cli_config(
     }
 }
 
-fn resolve_value<T: FromStr>(value: Option<T>, env_var: &str, default: Option<T>) -> T {
+fn resolve_value<T: FromStr<Err: Debug>>(value: Option<T>, env_var: &str, default: Option<T>) -> T {
+    resolve_value_map(
+        value,
+        env_var,
+        |s| T::from_str(s).map_err(|e| anyhow!("{e:?}")),
+        default,
+    )
+}
+
+fn resolve_value_map<T, Map: Fn(&str) -> anyhow::Result<T>>(
+    value: Option<T>,
+    env_var: &str,
+    map: Map,
+    default: Option<T>,
+) -> T {
     value.unwrap_or_else(|| {
         std::env::var(env_var)
             .ok()
-            .and_then(|v| T::from_str(&v).ok())
+            .and_then(|v| map(&v).ok())
             .or(default)
             .expect("Missing required configuration")
     })
diff --git a/crates/shielder-relayer/src/config/tests.rs b/crates/shielder-relayer/src/config/tests.rs
index baacfc3c..e6391866 100644
--- a/crates/shielder-relayer/src/config/tests.rs
+++ b/crates/shielder-relayer/src/config/tests.rs
@@ -17,7 +17,7 @@ fn config_resolution() {
     let host = DEFAULT_HOST.to_string();
     let port = 1234;
     let metrics_port = 5678;
-    let balance_monitor_interval_secs = 60;
+    let balance_monitor_interval = Duration::from_secs(60);
     let node_rpc_url = "http://localhost:8545".to_string();
     let shielder_contract_address = address!("0000000000000000000000000000000000000000");
     let fee_destination_key = "key0".to_string();
@@ -26,7 +26,7 @@ fn config_resolution() {
     let nonce_policy = DEFAULT_NONCE_POLICY;
     let dry_running = DryRunning::Always;
     let relay_count_for_recharge = DEFAULT_RELAY_COUNT_FOR_RECHARGE;
-    let total_fee = DEFAULT_TOTAL_FEE.to_string();
+    let total_fee = U256::from_str(&DEFAULT_TOTAL_FEE).unwrap();
     let relay_gas: u64 = DEFAULT_RELAY_GAS + 1;
     let native_token = Coin::Btc;
     let token_config = vec![
@@ -43,8 +43,11 @@ fn config_resolution() {
             pricing: Pricing::Feed,
         },
     ];
-    let price_feed_refresh_interval = DEFAULT_PRICE_FEED_REFRESH_INTERVAL_SECS;
-    let price_feed_validity = 15;
+    let price_feed_refresh_interval = DEFAULT_PRICE_FEED_REFRESH_INTERVAL;
+    let price_feed_validity = Duration::from_secs(15);
+    let service_fee_percent = DEFAULT_SERVICE_FEE_PERCENT;
+    let quote_validity = Duration::from_secs(11);
+    let max_pocket_money = U256::from(12);
 
     let expected_config = ServerConfig {
         logging_format, // from CLI
@@ -54,20 +57,23 @@ fn config_resolution() {
             metrics_port, // from CLI
         },
         chain: ChainConfig {
-            node_rpc_url: node_rpc_url.clone(),             // from CLI
-            shielder_contract_address,                      // from CLI
-            total_fee: U256::from_str(&total_fee).unwrap(), // from CLI
-            relay_gas,                                      // from env
-            native_token,                                   // from env
+            node_rpc_url: node_rpc_url.clone(), // from CLI
+            shielder_contract_address,          // from CLI
+            total_fee,                          // from CLI
+            relay_gas,                          // from env
+            native_token,                       // from env
         },
         operations: OperationalConfig {
-            balance_monitor_interval_secs, // from env
-            nonce_policy,                  // default
-            dry_running,                   // from CLI
-            relay_count_for_recharge,      // default
-            token_config,                  // from env
-            price_feed_refresh_interval,   // default
-            price_feed_validity,           // from CLI
+            balance_monitor_interval,    // from env
+            nonce_policy,                // default
+            dry_running,                 // from CLI
+            relay_count_for_recharge,    // default
+            token_config,                // from env
+            price_feed_refresh_interval, // default
+            price_feed_validity,         // from CLI
+            service_fee_percent,         // default
+            quote_validity,              // from env
+            max_pocket_money,            // from CLI
         },
         keys: KeyConfig {
             fee_destination_key: fee_destination_key.clone(), // from env
@@ -81,7 +87,7 @@ fn config_resolution() {
         host: None,
         port: None,
         metrics_port: Some(metrics_port),
-        balance_monitor_interval_secs: None,
+        balance_monitor_interval: None,
         node_rpc_url: Some(node_rpc_url),
         shielder_contract_address: Some(shielder_contract_address.to_string()),
         fee_destination_key: None,
@@ -95,14 +101,17 @@ fn config_resolution() {
         price_feed_refresh_interval: None,
         price_feed_validity: Some(price_feed_validity),
         native_token: None,
+        service_fee_percent: None,
+        quote_validity: None,
+        max_pocket_money: Some(max_pocket_money),
     };
 
     // ---- Environment variables. -----------------------------------------------------------
     unsafe {
         std::env::set_var(RELAYER_PORT_ENV, port.to_string());
         std::env::set_var(
-            BALANCE_MONITOR_INTERVAL_SECS_ENV,
-            balance_monitor_interval_secs.to_string(),
+            BALANCE_MONITOR_INTERVAL_ENV,
+            balance_monitor_interval.as_secs().to_string(),
         );
         std::env::set_var(FEE_DESTINATION_KEY_ENV, fee_destination_key);
         std::env::set_var(RELAYER_SIGNING_KEYS_ENV, format!("{key1},{key2}"));
@@ -123,6 +132,7 @@ fn config_resolution() {
             ]",
         );
         std::env::set_var(NATIVE_TOKEN_ENV, format!("{native_token:?}"));
+        std::env::set_var(QUOTE_VALIDITY_ENV, "11");
     }
 
     // ---- Test. ------------------------------------------------------------------------------
diff --git a/crates/shielder-relayer/src/currency.rs b/crates/shielder-relayer/src/currency.rs
new file mode 100644
index 00000000..94bad53d
--- /dev/null
+++ b/crates/shielder-relayer/src/currency.rs
@@ -0,0 +1,51 @@
+use std::str::FromStr;
+
+use alloy_primitives::Address;
+use clap::ValueEnum;
+use serde::{Deserialize, Serialize};
+use strum_macros::EnumIter;
+
+/// A list of all supported coins across all chains. Every relayer instance will work with some
+/// subset of these coins.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, EnumIter, Serialize, Deserialize, ValueEnum)]
+pub enum Coin {
+    Eth,
+    Azero,
+    Btc,
+    Usdt,
+    Usdc,
+}
+
+impl Coin {
+    pub fn decimals(&self) -> u32 {
+        match self {
+            Coin::Azero => 18,
+            Coin::Eth => 18,
+            Coin::Btc => 8,
+            Coin::Usdt => 6,
+            Coin::Usdc => 6,
+        }
+    }
+}
+
+impl FromStr for Coin {
+    type Err = ();
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s.to_lowercase().as_str() {
+            "azero" => Ok(Coin::Azero),
+            "eth" => Ok(Coin::Eth),
+            "btc" => Ok(Coin::Btc),
+            "usdt" => Ok(Coin::Usdt),
+            "usdc" => Ok(Coin::Usdc),
+            _ => Err(()),
+        }
+    }
+}
+
+#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
+pub enum TokenKind {
+    #[default]
+    Native,
+    ERC20(Address),
+}
diff --git a/crates/shielder-relayer/src/environment_variables.rs b/crates/shielder-relayer/src/environment_variables.rs
new file mode 100644
index 00000000..cec10684
--- /dev/null
+++ b/crates/shielder-relayer/src/environment_variables.rs
@@ -0,0 +1,21 @@
+pub const LOGGING_FORMAT_ENV: &str = "LOGGING_FORMAT";
+pub const RELAYER_HOST_ENV: &str = "RELAYER_HOST";
+pub const RELAYER_PORT_ENV: &str = "RELAYER_PORT";
+pub const RELAYER_METRICS_PORT_ENV: &str = "RELAYER_METRICS_PORT";
+pub const BALANCE_MONITOR_INTERVAL_ENV: &str = "BALANCE_MONITOR_INTERVAL";
+pub const FEE_DESTINATION_KEY_ENV: &str = "FEE_DESTINATION_KEY";
+pub const RELAYER_SIGNING_KEYS_ENV: &str = "RELAYER_SIGNING_KEYS";
+pub const NODE_RPC_URL_ENV: &str = "NODE_RPC_URL";
+pub const SHIELDER_CONTRACT_ADDRESS_ENV: &str = "SHIELDER_CONTRACT_ADDRESS";
+pub const NONCE_POLICY_ENV: &str = "NONCE_POLICY";
+pub const DRY_RUNNING_ENV: &str = "DRY_RUNNING";
+pub const RELAY_COUNT_FOR_RECHARGE_ENV: &str = "RELAY_COUNT_FOR_RECHARGE";
+pub const TOTAL_FEE_ENV: &str = "TOTAL_FEE";
+pub const RELAY_GAS_ENV: &str = "RELAY_GAS";
+pub const PRICE_FEED_VALIDITY_ENV: &str = "PRICE_FEED_VALIDITY";
+pub const PRICE_FEED_REFRESH_INTERVAL_ENV: &str = "PRICE_FEED_REFRESH_INTERVAL";
+pub const TOKEN_CONFIG_ENV: &str = "TOKEN_CONFIG";
+pub const NATIVE_TOKEN_ENV: &str = "NATIVE_TOKEN";
+pub const SERVICE_FEE_PERCENT_ENV: &str = "SERVICE_FEE_PERCENT";
+pub const QUOTE_VALIDITY_ENV: &str = "QUOTE_VALIDITY";
+pub const MAX_POCKET_MONEY_ENV: &str = "MAX_POCKET_MONEY";
diff --git a/crates/shielder-relayer/src/lib.rs b/crates/shielder-relayer/src/lib.rs
index 9736fe3b..6bcc2590 100644
--- a/crates/shielder-relayer/src/lib.rs
+++ b/crates/shielder-relayer/src/lib.rs
@@ -1,34 +1,16 @@
-use std::str::FromStr;
-
 use axum::{
     http::StatusCode,
     response::{IntoResponse, Response},
     Json,
 };
-use clap::ValueEnum;
 use rust_decimal::Decimal;
 use serde::{Deserialize, Serialize};
 use shielder_contract::alloy_primitives::{Address, Bytes, FixedBytes, TxHash, U256};
-use strum_macros::EnumIter;
 
-pub const LOGGING_FORMAT_ENV: &str = "LOGGING_FORMAT";
-pub const RELAYER_HOST_ENV: &str = "RELAYER_HOST";
-pub const RELAYER_PORT_ENV: &str = "RELAYER_PORT";
-pub const RELAYER_METRICS_PORT_ENV: &str = "RELAYER_METRICS_PORT";
-pub const BALANCE_MONITOR_INTERVAL_SECS_ENV: &str = "BALANCE_MONITOR_INTERVAL_SECS";
-pub const FEE_DESTINATION_KEY_ENV: &str = "FEE_DESTINATION_KEY";
-pub const RELAYER_SIGNING_KEYS_ENV: &str = "RELAYER_SIGNING_KEYS";
-pub const NODE_RPC_URL_ENV: &str = "NODE_RPC_URL";
-pub const SHIELDER_CONTRACT_ADDRESS_ENV: &str = "SHIELDER_CONTRACT_ADDRESS";
-pub const NONCE_POLICY_ENV: &str = "NONCE_POLICY";
-pub const DRY_RUNNING_ENV: &str = "DRY_RUNNING";
-pub const RELAY_COUNT_FOR_RECHARGE_ENV: &str = "RELAY_COUNT_FOR_RECHARGE";
-pub const TOTAL_FEE_ENV: &str = "TOTAL_FEE";
-pub const RELAY_GAS_ENV: &str = "RELAY_GAS";
-pub const PRICE_FEED_VALIDITY_ENV: &str = "PRICE_FEED_VALIDITY";
-pub const PRICE_FEED_REFRESH_INTERVAL_ENV: &str = "PRICE_FEED_REFRESH_INTERVAL";
-pub const TOKEN_CONFIG_ENV: &str = "TOKEN_CONFIG";
-pub const NATIVE_TOKEN_ENV: &str = "NATIVE_TOKEN";
+mod environment_variables;
+pub use environment_variables::*;
+mod currency;
+pub use currency::*;
 
 #[derive(Clone, Debug, Deserialize, Serialize)]
 #[serde(transparent)]
@@ -115,56 +97,11 @@ pub struct RelayQuery {
     pub mac_commitment: U256,
 }
 
-#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
-pub enum TokenKind {
-    #[default]
-    Native,
-    ERC20(Address),
-}
-
 pub fn server_error(msg: &str) -> Response {
     let code = StatusCode::INTERNAL_SERVER_ERROR;
     (code, SimpleServiceResponse::from(msg)).into_response()
 }
 
-/// A list of all supported coins across all chains. Every relayer instance will work with some
-/// subset of these coins.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, EnumIter, Serialize, Deserialize, ValueEnum)]
-pub enum Coin {
-    Eth,
-    Azero,
-    Btc,
-    Usdt,
-    Usdc,
-}
-
-impl Coin {
-    pub fn decimals(&self) -> u32 {
-        match self {
-            Coin::Azero => 18,
-            Coin::Eth => 18,
-            Coin::Btc => 8,
-            Coin::Usdt => 6,
-            Coin::Usdc => 6,
-        }
-    }
-}
-
-impl FromStr for Coin {
-    type Err = ();
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        match s.to_lowercase().as_str() {
-            "azero" => Ok(Coin::Azero),
-            "eth" => Ok(Coin::Eth),
-            "btc" => Ok(Coin::Btc),
-            "usdt" => Ok(Coin::Usdt),
-            "usdc" => Ok(Coin::Usdc),
-            _ => Err(()),
-        }
-    }
-}
-
 pub const RELATIVE_PRICE_DIGITS: u32 = 20;
 
 pub fn scale_u256(a: U256, b: Decimal) -> Result<U256, &'static str> {
diff --git a/crates/shielder-relayer/src/main.rs b/crates/shielder-relayer/src/main.rs
index 7531a894..0d6a3f81 100644
--- a/crates/shielder-relayer/src/main.rs
+++ b/crates/shielder-relayer/src/main.rs
@@ -1,4 +1,4 @@
-use std::{env, io, str::FromStr, sync::Arc, time::Duration};
+use std::{env, io, str::FromStr, sync::Arc};
 
 use alloy_provider::Provider;
 use alloy_signer_local::PrivateKeySigner;
@@ -69,14 +69,14 @@ async fn main() -> Result<()> {
 
     let signers = get_signer_info(&server_config.keys)?;
     let prices = Prices::new(
-        Duration::from_secs(server_config.operations.price_feed_validity),
-        Duration::from_secs(server_config.operations.price_feed_refresh_interval),
+        server_config.operations.price_feed_validity,
+        server_config.operations.price_feed_refresh_interval,
     );
 
     tokio::try_join!(
         balance_monitor(
             &server_config.chain.node_rpc_url,
-            server_config.operations.balance_monitor_interval_secs,
+            server_config.operations.balance_monitor_interval,
             signers.balances.clone(),
         ),
         start_metrics_server(&server_config, signers.balances.clone()),
diff --git a/crates/shielder-relayer/src/monitor/balance_monitor.rs b/crates/shielder-relayer/src/monitor/balance_monitor.rs
index 553a138f..3ecfb9de 100644
--- a/crates/shielder-relayer/src/monitor/balance_monitor.rs
+++ b/crates/shielder-relayer/src/monitor/balance_monitor.rs
@@ -12,11 +12,11 @@ use crate::monitor::Balances;
 /// Periodically check the balance of the relayer's signer addresses.
 pub async fn balance_monitor(
     node_rpc_url: &str,
-    interval_secs: u64,
+    interval_duration: Duration,
     balances: Balances,
 ) -> Result<()> {
     let provider = create_simple_provider(node_rpc_url).await?;
-    let mut interval = interval(Duration::from_secs(interval_secs));
+    let mut interval = interval(interval_duration);
 
     loop {
         interval.tick().await;


Reviews:
user: login: kroist
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T14:34:15Z
user: login: pmikolajczyk41
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T16:03:32Z
user: login: pmikolajczyk41
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T16:03:35Z
user: login: pmikolajczyk41
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T16:03:37Z

Review comments:
diff_hunk: @@ -32,30 +32,33 @@ make run
 The relayer service can be configured via CLI arguments or environment variables. Some options can do fallback to
 defaults not provided.
 
-| Option                            | Description                                                                                                                                                                             | Env variable                    | Default value               |
-|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------|-----------------------------|
-| `--logging-format`                | Logging format configuration.                                                                                                                                                           | `LOGGING_FORMAT`                | `Text`                      |
-|                                   |                                                                                                                                                                                         |                                 |                             |
-| `--host`                          | Host where the server should be run.                                                                                                                                                    | `RELAYER_HOST`                  | `0.0.0.0`                   |
-| `--port`                          | Port where the server should be run.                                                                                                                                                    | `RELAYER_PORT`                  | `4141`                      |
-| `--metrics-port`                  | Port where the server metrics should be exposed.                                                                                                                                        | `RELAYER_METRICS_PORT`          | `9615`                      |
-|                                   |                                                                                                                                                                                         |                                 |                             |
-| `--node-rpc-url`                  | URL of the Ethereum RPC node.                                                                                                                                                           | `NODE_RPC_URL`                  |                             |
-| `--shielder-contract-address`     | Address of the Shielder contract.                                                                                                                                                       | `SHIELDER_CONTRACT_ADDRESS`     |                             |
-| `--total-fee`                     | The total fee, which is used as an argument for `withdraw_native` call. It should be a fixed value, close to a sum of 'withdraw_native' on-chain gas cost and the intended relayer fee. | `TOTAL_FEE`                     | `"100_000_000_000_000_000"` |
-| `--relay-gas`                     | The estimated amount of gas 'withdraw_native' on-chain call burns.                                                                                                                      | `RELAY_GAS`                     | `2000000`.                  |
-| `--native-token`                  | Token native to chain where the relayer operates.                                                                                                                                       | `NATIVE_TOKEN`                  |                             |
-|                                   |                                                                                                                                                                                         |                                 |                             |
-| `--balance-monitor-interval-secs` | Interval (in seconds) for monitoring signers' balances.                                                                                                                                 | `BALANCE_MONITOR_INTERVAL_SECS` | `900`                       |
-| `--nonce-policy`                  | Nonce management policy.                                                                                                                                                                | `NONCE_POLICY`                  | `Caching`                   |
-| `--dry-running`                   | Dry running policy.                                                                                                                                                                     | `DRY_RUNNING`                   | `Always`                    |
-| `--relay-count-for-recharge`      | Relay count for recharge.                                                                                                                                                               | `RELAY_COUNT_FOR_RECHARGE`      | `20`                        |
-| `--token-config`                  | Token pricing configuration for tokens that are qualified as a fee token.                                                                                                               | `TOKEN_CONFIG`                  | empty                       |
-| `--price-feed-refresh-interval`   | Price feed refresh interval in seconds.                                                                                                                                                 | `PRICE_FEED_REFRESH_INTERVAL`   | `60`                        |
-| `--price-feed-validity`           | Price feed validity in seconds.                                                                                                                                                         | `PRICE_FEED_VALIDITY`           | `600`                       |
-|                                   |                                                                                                                                                                                         |                                 |                             |
-| `--fee-destination-key`           | Signing key of the address where the fees should go.                                                                                                                                    | `FEE_DESTINATION_KEY`           |                             |
-| `--signing-keys`                  | Signing keys of the relayer.                                                                                                                                                            | `RELAYER_SIGNING_KEYS`          |                             |
+| Option                            | Description                                                                                                                                                                             | Env variable                  | Default value             |
+|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------|---------------------------|
+| `--logging-format`                | Logging format configuration.                                                                                                                                                           | `LOGGING_FORMAT`              | `Text`                    |
+|                                   |                                                                                                                                                                                         |                               |                           |
+| `--host`                          | Host where the server should be run.                                                                                                                                                    | `RELAYER_HOST`                | `0.0.0.0`                 |
+| `--port`                          | Port where the server should be run.                                                                                                                                                    | `RELAYER_PORT`                | `4141`                    |
+| `--metrics-port`                  | Port where the server metrics should be exposed.                                                                                                                                        | `RELAYER_METRICS_PORT`        | `9615`                    |
+|                                   |                                                                                                                                                                                         |                               |                           |
+| `--node-rpc-url`                  | URL of the Ethereum RPC node.                                                                                                                                                           | `NODE_RPC_URL`                |                           |
+| `--shielder-contract-address`     | Address of the Shielder contract.                                                                                                                                                       | `SHIELDER_CONTRACT_ADDRESS`   |                           |
+| `--total-fee`                     | The total fee, which is used as an argument for `withdraw_native` call. It should be a fixed value, close to a sum of 'withdraw_native' on-chain gas cost and the intended relayer fee. | `TOTAL_FEE`                   | `100_000_000_000_000_000` |
+| `--relay-gas`                     | The estimated amount of gas 'withdraw_native' on-chain call burns.                                                                                                                      | `RELAY_GAS`                   | `2000000`.                |
+| `--native-token`                  | Token native to chain where the relayer operates.                                                                                                                                       | `NATIVE_TOKEN`                |                           |
+|                                   |                                                                                                                                                                                         |                               |                           |
+| `--balance-monitor-interval-secs` | Interval (in seconds) for monitoring signers' balances.                                                                                                                                 | `BALANCE_MONITOR_INTERVAL`    | 900 seconds               |
+| `--nonce-policy`                  | Nonce management policy.                                                                                                                                                                | `NONCE_POLICY`                | `Caching`                 |
+| `--dry-running`                   | Dry running policy.                                                                                                                                                                     | `DRY_RUNNING`                 | `Always`                  |
+| `--relay-count-for-recharge`      | Relay count for recharge.                                                                                                                                                               | `RELAY_COUNT_FOR_RECHARGE`    | `20`                      |
+| `--token-config`                  | Token pricing configuration for tokens that are qualified as a fee token.                                                                                                               | `TOKEN_CONFIG`                | empty                     |
+| `--price-feed-refresh-interval`   | Price feed refresh interval in seconds.                                                                                                                                                 | `PRICE_FEED_REFRESH_INTERVAL` | 60 seconds                |
+| `--price-feed-validity`           | Price feed validity in seconds.                                                                                                                                                         | `PRICE_FEED_VALIDITY`         | 600 seconds               |
+| `--service-fee-percent`           | Commission fee percentage (added to the actual relay cost).                                                                                                                             | `SERVICE_FEE_PERCENT`         | 15%                       |
+| `--quote-validity`                | How long the quote provided by the service is valid. In seconds.                                                                                                                        | `QUOTE_VALIDITY`              | 15 seconds                |
+| `--max-pocket-money`              | Maximum pocket money relayer can provide.                                                                                                                                               | `MAX_POCKET_MONEY`            | `100_000_000_000_000_000` |
+|                                   |                                                                                                                                                                                         |                               |                           |
+| `--fee-destination-key`           | Signing key of the address where the fees should go.                                                                                                                                    | `FEE_DESTINATION_KEY`         |                           |
+| `--signing-keys`                  | Signing keys of the relayer.                                                                                                                                                            | `RELAYER_SIGNING_KEYS`        |                           |
path: crates/shielder-relayer/README.md
user: login: kroist
body: I would move the variables without default values to the top, cause they are the most important ones
created_at: 2025-03-17T14:28:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,16 +1,22 @@
+use std::time::Duration;
+
 use crate::config::{enums::DryRunning, LoggingFormat, NoncePolicy};
 
 pub const DEFAULT_LOGGING_FORMAT: LoggingFormat = LoggingFormat::Text;
 pub const DEFAULT_HOST: &str = "0.0.0.0";
 pub const DEFAULT_PORT: u16 = 4141;
 pub const DEFAULT_METRICS_PORT: u16 = 9615;
-pub const DEFAULT_BALANCE_MONITOR_INTERVAL_SECS: u64 = 60 * 15;
+pub const DEFAULT_BALANCE_MONITOR_INTERVAL: Duration = Duration::from_secs(15);
 pub const DEFAULT_NONCE_POLICY: NoncePolicy = NoncePolicy::Caching;
 pub const DEFAULT_DRY_RUNNING: DryRunning = DryRunning::Always;
 pub const DEFAULT_RELAY_COUNT_FOR_RECHARGE: u32 = 20;
 pub const DEFAULT_TOTAL_FEE: &str = "100_000_000_000_000_000"; // 0.1 TZERO
 pub const DEFAULT_RELAY_GAS: u64 = 2_000_000; // an estimated amount of gas for a 'withdraw_native' call
 
 const ONE_MINUTE_IN_SECONDS: u64 = 60;
-pub const DEFAULT_PRICE_FEED_VALIDITY_SECS: u64 = 10 * ONE_MINUTE_IN_SECONDS;
-pub const DEFAULT_PRICE_FEED_REFRESH_INTERVAL_SECS: u64 = ONE_MINUTE_IN_SECONDS;
+pub const DEFAULT_PRICE_FEED_VALIDITY: Duration = Duration::from_secs(10 * ONE_MINUTE_IN_SECONDS);
+pub const DEFAULT_PRICE_FEED_REFRESH_INTERVAL: Duration =
+    Duration::from_secs(ONE_MINUTE_IN_SECONDS);
path: crates/shielder-relayer/src/config/defaults.rs
user: login: kroist
body: `ONE_MINUTE_IN_SECONDS` is too explicit, it can be just literal `Duration::from_secs(60)`
created_at: 2025-03-17T14:31:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,51 @@
+use std::str::FromStr;
+
+use alloy_primitives::Address;
+use clap::ValueEnum;
+use serde::{Deserialize, Serialize};
+use strum_macros::EnumIter;
+
+/// A list of all supported coins across all chains. Every relayer instance will work with some
+/// subset of these coins.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, EnumIter, Serialize, Deserialize, ValueEnum)]
+pub enum Coin {
+    Eth,
+    Azero,
+    Btc,
+    Usdt,
+    Usdc,
+}
+
+impl Coin {
+    pub fn decimals(&self) -> u32 {
+        match self {
+            Coin::Azero => 18,
+            Coin::Eth => 18,
+            Coin::Btc => 8,
+            Coin::Usdt => 6,
+            Coin::Usdc => 6,
path: crates/shielder-relayer/src/currency.rs
user: login: kroist
body: EVM chains have 18 decimals in native token by default, but for ERC-20 it's not true :) the token contract is the source of truth
created_at: 2025-03-17T14:33:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,16 +1,22 @@
+use std::time::Duration;
+
 use crate::config::{enums::DryRunning, LoggingFormat, NoncePolicy};
 
 pub const DEFAULT_LOGGING_FORMAT: LoggingFormat = LoggingFormat::Text;
 pub const DEFAULT_HOST: &str = "0.0.0.0";
 pub const DEFAULT_PORT: u16 = 4141;
 pub const DEFAULT_METRICS_PORT: u16 = 9615;
-pub const DEFAULT_BALANCE_MONITOR_INTERVAL_SECS: u64 = 60 * 15;
+pub const DEFAULT_BALANCE_MONITOR_INTERVAL: Duration = Duration::from_secs(15);
 pub const DEFAULT_NONCE_POLICY: NoncePolicy = NoncePolicy::Caching;
 pub const DEFAULT_DRY_RUNNING: DryRunning = DryRunning::Always;
 pub const DEFAULT_RELAY_COUNT_FOR_RECHARGE: u32 = 20;
 pub const DEFAULT_TOTAL_FEE: &str = "100_000_000_000_000_000"; // 0.1 TZERO
 pub const DEFAULT_RELAY_GAS: u64 = 2_000_000; // an estimated amount of gas for a 'withdraw_native' call
 
 const ONE_MINUTE_IN_SECONDS: u64 = 60;
-pub const DEFAULT_PRICE_FEED_VALIDITY_SECS: u64 = 10 * ONE_MINUTE_IN_SECONDS;
-pub const DEFAULT_PRICE_FEED_REFRESH_INTERVAL_SECS: u64 = ONE_MINUTE_IN_SECONDS;
+pub const DEFAULT_PRICE_FEED_VALIDITY: Duration = Duration::from_secs(10 * ONE_MINUTE_IN_SECONDS);
+pub const DEFAULT_PRICE_FEED_REFRESH_INTERVAL: Duration =
+    Duration::from_secs(ONE_MINUTE_IN_SECONDS);
path: crates/shielder-relayer/src/config/defaults.rs
user: login: pmikolajczyk41
body: removed, because `6 * Duration::from_secs(60)` is not const
created_at: 2025-03-17T16:03:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -32,30 +32,33 @@ make run
 The relayer service can be configured via CLI arguments or environment variables. Some options can do fallback to
 defaults not provided.
 
-| Option                            | Description                                                                                                                                                                             | Env variable                    | Default value               |
-|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------|-----------------------------|
-| `--logging-format`                | Logging format configuration.                                                                                                                                                           | `LOGGING_FORMAT`                | `Text`                      |
-|                                   |                                                                                                                                                                                         |                                 |                             |
-| `--host`                          | Host where the server should be run.                                                                                                                                                    | `RELAYER_HOST`                  | `0.0.0.0`                   |
-| `--port`                          | Port where the server should be run.                                                                                                                                                    | `RELAYER_PORT`                  | `4141`                      |
-| `--metrics-port`                  | Port where the server metrics should be exposed.                                                                                                                                        | `RELAYER_METRICS_PORT`          | `9615`                      |
-|                                   |                                                                                                                                                                                         |                                 |                             |
-| `--node-rpc-url`                  | URL of the Ethereum RPC node.                                                                                                                                                           | `NODE_RPC_URL`                  |                             |
-| `--shielder-contract-address`     | Address of the Shielder contract.                                                                                                                                                       | `SHIELDER_CONTRACT_ADDRESS`     |                             |
-| `--total-fee`                     | The total fee, which is used as an argument for `withdraw_native` call. It should be a fixed value, close to a sum of 'withdraw_native' on-chain gas cost and the intended relayer fee. | `TOTAL_FEE`                     | `"100_000_000_000_000_000"` |
-| `--relay-gas`                     | The estimated amount of gas 'withdraw_native' on-chain call burns.                                                                                                                      | `RELAY_GAS`                     | `2000000`.                  |
-| `--native-token`                  | Token native to chain where the relayer operates.                                                                                                                                       | `NATIVE_TOKEN`                  |                             |
-|                                   |                                                                                                                                                                                         |                                 |                             |
-| `--balance-monitor-interval-secs` | Interval (in seconds) for monitoring signers' balances.                                                                                                                                 | `BALANCE_MONITOR_INTERVAL_SECS` | `900`                       |
-| `--nonce-policy`                  | Nonce management policy.                                                                                                                                                                | `NONCE_POLICY`                  | `Caching`                   |
-| `--dry-running`                   | Dry running policy.                                                                                                                                                                     | `DRY_RUNNING`                   | `Always`                    |
-| `--relay-count-for-recharge`      | Relay count for recharge.                                                                                                                                                               | `RELAY_COUNT_FOR_RECHARGE`      | `20`                        |
-| `--token-config`                  | Token pricing configuration for tokens that are qualified as a fee token.                                                                                                               | `TOKEN_CONFIG`                  | empty                       |
-| `--price-feed-refresh-interval`   | Price feed refresh interval in seconds.                                                                                                                                                 | `PRICE_FEED_REFRESH_INTERVAL`   | `60`                        |
-| `--price-feed-validity`           | Price feed validity in seconds.                                                                                                                                                         | `PRICE_FEED_VALIDITY`           | `600`                       |
-|                                   |                                                                                                                                                                                         |                                 |                             |
-| `--fee-destination-key`           | Signing key of the address where the fees should go.                                                                                                                                    | `FEE_DESTINATION_KEY`           |                             |
-| `--signing-keys`                  | Signing keys of the relayer.                                                                                                                                                            | `RELAYER_SIGNING_KEYS`          |                             |
+| Option                            | Description                                                                                                                                                                             | Env variable                  | Default value             |
+|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------|---------------------------|
+| `--logging-format`                | Logging format configuration.                                                                                                                                                           | `LOGGING_FORMAT`              | `Text`                    |
+|                                   |                                                                                                                                                                                         |                               |                           |
+| `--host`                          | Host where the server should be run.                                                                                                                                                    | `RELAYER_HOST`                | `0.0.0.0`                 |
+| `--port`                          | Port where the server should be run.                                                                                                                                                    | `RELAYER_PORT`                | `4141`                    |
+| `--metrics-port`                  | Port where the server metrics should be exposed.                                                                                                                                        | `RELAYER_METRICS_PORT`        | `9615`                    |
+|                                   |                                                                                                                                                                                         |                               |                           |
+| `--node-rpc-url`                  | URL of the Ethereum RPC node.                                                                                                                                                           | `NODE_RPC_URL`                |                           |
+| `--shielder-contract-address`     | Address of the Shielder contract.                                                                                                                                                       | `SHIELDER_CONTRACT_ADDRESS`   |                           |
+| `--total-fee`                     | The total fee, which is used as an argument for `withdraw_native` call. It should be a fixed value, close to a sum of 'withdraw_native' on-chain gas cost and the intended relayer fee. | `TOTAL_FEE`                   | `100_000_000_000_000_000` |
+| `--relay-gas`                     | The estimated amount of gas 'withdraw_native' on-chain call burns.                                                                                                                      | `RELAY_GAS`                   | `2000000`.                |
+| `--native-token`                  | Token native to chain where the relayer operates.                                                                                                                                       | `NATIVE_TOKEN`                |                           |
+|                                   |                                                                                                                                                                                         |                               |                           |
+| `--balance-monitor-interval-secs` | Interval (in seconds) for monitoring signers' balances.                                                                                                                                 | `BALANCE_MONITOR_INTERVAL`    | 900 seconds               |
+| `--nonce-policy`                  | Nonce management policy.                                                                                                                                                                | `NONCE_POLICY`                | `Caching`                 |
+| `--dry-running`                   | Dry running policy.                                                                                                                                                                     | `DRY_RUNNING`                 | `Always`                  |
+| `--relay-count-for-recharge`      | Relay count for recharge.                                                                                                                                                               | `RELAY_COUNT_FOR_RECHARGE`    | `20`                      |
+| `--token-config`                  | Token pricing configuration for tokens that are qualified as a fee token.                                                                                                               | `TOKEN_CONFIG`                | empty                     |
+| `--price-feed-refresh-interval`   | Price feed refresh interval in seconds.                                                                                                                                                 | `PRICE_FEED_REFRESH_INTERVAL` | 60 seconds                |
+| `--price-feed-validity`           | Price feed validity in seconds.                                                                                                                                                         | `PRICE_FEED_VALIDITY`         | 600 seconds               |
+| `--service-fee-percent`           | Commission fee percentage (added to the actual relay cost).                                                                                                                             | `SERVICE_FEE_PERCENT`         | 15%                       |
+| `--quote-validity`                | How long the quote provided by the service is valid. In seconds.                                                                                                                        | `QUOTE_VALIDITY`              | 15 seconds                |
+| `--max-pocket-money`              | Maximum pocket money relayer can provide.                                                                                                                                               | `MAX_POCKET_MONEY`            | `100_000_000_000_000_000` |
+|                                   |                                                                                                                                                                                         |                               |                           |
+| `--fee-destination-key`           | Signing key of the address where the fees should go.                                                                                                                                    | `FEE_DESTINATION_KEY`         |                           |
+| `--signing-keys`                  | Signing keys of the relayer.                                                                                                                                                            | `RELAYER_SIGNING_KEYS`        |                           |
path: crates/shielder-relayer/README.md
user: login: pmikolajczyk41
body: moved
created_at: 2025-03-17T16:03:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,51 @@
+use std::str::FromStr;
+
+use alloy_primitives::Address;
+use clap::ValueEnum;
+use serde::{Deserialize, Serialize};
+use strum_macros::EnumIter;
+
+/// A list of all supported coins across all chains. Every relayer instance will work with some
+/// subset of these coins.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, EnumIter, Serialize, Deserialize, ValueEnum)]
+pub enum Coin {
+    Eth,
+    Azero,
+    Btc,
+    Usdt,
+    Usdc,
+}
+
+impl Coin {
+    pub fn decimals(&self) -> u32 {
+        match self {
+            Coin::Azero => 18,
+            Coin::Eth => 18,
+            Coin::Btc => 8,
+            Coin::Usdt => 6,
+            Coin::Usdc => 6,
path: crates/shielder-relayer/src/currency.rs
user: login: pmikolajczyk41
body: tbd
created_at: 2025-03-17T16:03:37Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-03-16T10:53:52Z
body: <table><tr><th>Transaction Name</th><th>Main</th><th>Current</th><th>Difference (%)</th></tr><tr><td>Deposit (size)</td><td>20255</td><td>20255</td><td>0.00000%</td></tr><tr><td>DepositERC20 (gas)</td><td>1761289</td><td>1761241</td><td>-0.00273%</td></tr><tr><td>DepositNative (gas)</td><td>1743247</td><td>1743175</td><td>-0.00413%</td></tr><tr><td>NewAccount (size)</td><td>22867</td><td>22867</td><td>0.00000%</td></tr><tr><td>NewAccountERC20 (gas)</td><td>1794597</td><td>1794549</td><td>-0.00267%</td></tr><tr><td>NewAccountNative (gas)</td><td>1998725</td><td>1998593</td><td>-0.00660%</td></tr><tr><td>Withdraw (size)</td><td>21574</td><td>21574</td><td>0.00000%</td></tr><tr><td>WithdrawERC20 (gas)</td><td>1851951</td><td>1851999</td><td>+0.00259%</td></tr><tr><td>WithdrawNative (gas)</td><td>1861192</td><td>1861204</td><td>+0.00064%</td></tr></table>
<!-- thollander/actions-comment-pull-request "hashFiles('report.html')" -->
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-03-16T10:54:43Z
body: # 📊 Coverage Report

## 📈 Total Coverage Summary

| Type | Covered | Total | Coverage |
|------|---------|--------|----------|
| 📝 Lines | 1458 | 2066 | 🟠 70.57% |
| 📄 Statements | 1458 | 2066 | 🟠 70.57% |
| ⚡ Functions | 107 | 114 | 🟡 93.85% |
| 🔀 Branches | 262 | 272 | 🟡 96.32% |

### Coverage Legend

- ✅ 100% Coverage
- 🟡 80-99% Coverage
- 🟠 50-79% Coverage
- ❌ 0-49% Coverage

## 📁 File Coverage

<details>
<summary>📋 Detailed Coverage Report</summary>

| File | Lines | Statements | Functions | Branches |
|------|-------|------------|-----------|----------|
| 🟡 [zkOS-monorepo/ts/shielder-sdk/src/actions/deposit.ts](zkOS-monorepo/ts/shielder-sdk/src/actions/deposit.ts) | 88.37% | 88.37% | 100% | 85% |
| 🟡 [zkOS-monorepo/ts/shielder-sdk/src/actions/newAccount.ts](zkOS-monorepo/ts/shielder-sdk/src/actions/newAccount.ts) | 84.37% | 84.37% | 100% | 78.94% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/actions/types.ts](zkOS-monorepo/ts/shielder-sdk/src/actions/types.ts) | 100% | 100% | 100% | 100% |
| 🟡 [zkOS-monorepo/ts/shielder-sdk/src/actions/utils.ts](zkOS-monorepo/ts/shielder-sdk/src/actions/utils.ts) | 97.36% | 97.36% | 100% | 90.9% |
| 🟠 [zkOS-monorepo/ts/shielder-sdk/src/actions/withdraw.ts](zkOS-monorepo/ts/shielder-sdk/src/actions/withdraw.ts) | 76.62% | 76.62% | 87.5% | 100% |
| ❌ [zkOS-monorepo/ts/shielder-sdk/src/chain/contract.ts](zkOS-monorepo/ts/shielder-sdk/src/chain/contract.ts) | 1.92% | 1.92% | 0% | 0% |
| ❌ [zkOS-monorepo/ts/shielder-sdk/src/chain/relayer.ts](zkOS-monorepo/ts/shielder-sdk/src/chain/relayer.ts) | 14.04% | 14.04% | 0% | 0% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/client/actions.ts](zkOS-monorepo/ts/shielder-sdk/src/client/actions.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/client/client.ts](zkOS-monorepo/ts/shielder-sdk/src/client/client.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/client/factories.ts](zkOS-monorepo/ts/shielder-sdk/src/client/factories.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/client/types.ts](zkOS-monorepo/ts/shielder-sdk/src/client/types.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/constants.ts](zkOS-monorepo/ts/shielder-sdk/src/constants.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/errors.ts](zkOS-monorepo/ts/shielder-sdk/src/errors.ts) | 100% | 100% | 100% | 100% |
| ❌ [zkOS-monorepo/ts/shielder-sdk/src/index.ts](zkOS-monorepo/ts/shielder-sdk/src/index.ts) | 0% | 0% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/state/accountFactory.ts](zkOS-monorepo/ts/shielder-sdk/src/state/accountFactory.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/state/accountRegistry.ts](zkOS-monorepo/ts/shielder-sdk/src/state/accountRegistry.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/state/accountStateSerde.ts](zkOS-monorepo/ts/shielder-sdk/src/state/accountStateSerde.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/state/idManager.ts](zkOS-monorepo/ts/shielder-sdk/src/state/idManager.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/state/localStateTransition.ts](zkOS-monorepo/ts/shielder-sdk/src/state/localStateTransition.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/state/sync/chainStateTransition.ts](zkOS-monorepo/ts/shielder-sdk/src/state/sync/chainStateTransition.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/state/sync/historyFetcher.ts](zkOS-monorepo/ts/shielder-sdk/src/state/sync/historyFetcher.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/state/sync/synchronizer.ts](zkOS-monorepo/ts/shielder-sdk/src/state/sync/synchronizer.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/state/sync/tokenAccountFinder.ts](zkOS-monorepo/ts/shielder-sdk/src/state/sync/tokenAccountFinder.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/state/types.ts](zkOS-monorepo/ts/shielder-sdk/src/state/types.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/storage/storageManager.ts](zkOS-monorepo/ts/shielder-sdk/src/storage/storageManager.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/storage/storageSchema.ts](zkOS-monorepo/ts/shielder-sdk/src/storage/storageSchema.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/types.ts](zkOS-monorepo/ts/shielder-sdk/src/types.ts) | 100% | 100% | 100% | 100% |
| ✅ [zkOS-monorepo/ts/shielder-sdk/src/utils.ts](zkOS-monorepo/ts/shielder-sdk/src/utils.ts) | 100% | 100% | 100% | 100% |

</details>

<!-- Sticky Pull Request Comment -->
author_association: NONE