erc20_payment_lib/
config.rs

1use serde::{Deserialize, Serialize};
2use std::collections::btree_map::BTreeMap as Map;
3
4use rust_decimal::Decimal;
5use std::path::Path;
6
7use crate::err_custom_create;
8use crate::error::*;
9use erc20_payment_lib_common::err_create;
10use tokio::fs;
11use web3::types::Address;
12
13#[derive(Debug, Clone)]
14pub struct AdditionalOptions {
15    ///Set to keep running when finished processing transactions
16    pub keep_running: bool,
17    ///Set to skip running service loop (do not send and process transactions)
18    pub skip_service_loop: bool,
19    ///Do not send or process transactions, only generate stubs
20    pub generate_tx_only: bool,
21    ///Skip multi contract check when generating txs
22    pub skip_multi_contract_check: bool,
23    pub contract_use_direct_method: bool,
24    pub contract_use_unpacked_method: bool,
25    pub use_transfer_for_single_payment: bool,
26}
27
28impl Default for AdditionalOptions {
29    fn default() -> Self {
30        AdditionalOptions {
31            keep_running: true,
32            generate_tx_only: false,
33            skip_multi_contract_check: false,
34            contract_use_direct_method: false,
35            contract_use_unpacked_method: false,
36            use_transfer_for_single_payment: true,
37            skip_service_loop: false,
38        }
39    }
40}
41
42impl AdditionalOptions {
43    pub fn keep_running(&mut self, keep_running: bool) -> &mut Self {
44        self.keep_running = keep_running;
45        self
46    }
47}
48
49#[derive(Deserialize, Serialize, Debug, Clone)]
50#[serde(rename_all = "kebab-case")]
51pub struct Engine {
52    pub process_interval: u64,
53    pub process_interval_after_error: u64,
54    pub process_interval_after_no_gas_or_token_start: u64,
55    pub process_interval_after_no_gas_or_token_max: u64,
56    pub process_interval_after_no_gas_or_token_increase: f64,
57    pub process_interval_after_send: u64,
58    pub report_alive_interval: u64,
59    pub gather_interval: u64,
60    pub mark_as_unrecoverable_after_seconds: Option<u64>,
61    pub gather_at_start: bool,
62    pub automatic_recover: bool,
63    pub ignore_deadlines: bool,
64}
65
66#[derive(Deserialize, Serialize, Debug, Clone)]
67pub struct Config {
68    pub chain: Map<String, Chain>,
69    pub engine: Engine,
70}
71
72#[derive(Deserialize, Serialize, Debug, Clone)]
73#[serde(rename_all = "kebab-case")]
74pub struct MultiContractSettings {
75    pub address: Address,
76    pub max_at_once: usize,
77}
78
79#[derive(Deserialize, Serialize, Debug, Clone)]
80#[serde(rename_all = "kebab-case")]
81pub struct WrapperContractSettings {
82    pub address: Address,
83}
84
85#[derive(Deserialize, Serialize, Debug, Clone)]
86#[serde(rename_all = "kebab-case")]
87pub struct MintContractSettings {
88    pub address: Address,
89    pub max_glm_allowed: Decimal,
90}
91
92#[derive(Deserialize, Serialize, Debug, Clone)]
93#[serde(rename_all = "kebab-case")]
94pub struct LockContractSettings {
95    pub address: Address,
96}
97
98#[derive(Deserialize, Serialize, Debug, Clone)]
99#[serde(rename_all = "kebab-case")]
100pub struct DistributorContractSettings {
101    pub address: Address,
102}
103
104#[derive(Deserialize, Serialize, Debug, Clone)]
105#[serde(rename_all = "kebab-case")]
106pub struct EasContractSettings {
107    pub address: Address,
108}
109
110#[derive(Deserialize, Serialize, Debug, Clone)]
111#[serde(rename_all = "kebab-case")]
112pub struct EasSchemaRegistrySettings {
113    pub address: Address,
114}
115
116#[derive(Deserialize, Serialize, Debug, Clone)]
117#[serde(rename_all = "kebab-case")]
118pub struct FaucetClientSettings {
119    pub max_eth_allowed: Decimal,
120    pub faucet_srv: String,
121    pub faucet_host: String,
122    pub faucet_srv_port: u16,
123    pub faucet_lookup_domain: String,
124}
125
126#[derive(Deserialize, Serialize, Debug, Clone)]
127#[serde(rename_all = "kebab-case")]
128pub struct RpcSettings {
129    pub names: Option<String>,
130    pub endpoints: Option<String>,
131    pub dns_source: Option<String>,
132    pub json_source: Option<String>,
133    pub skip_validation: Option<bool>,
134    pub backup_level: Option<i64>,
135    pub verify_interval_secs: Option<u64>,
136    pub min_interval_ms: Option<u64>,
137    pub max_timeout_ms: Option<u64>,
138    pub allowed_head_behind_secs: Option<i64>,
139    pub max_consecutive_errors: Option<u64>,
140}
141
142#[derive(Deserialize, Serialize, Debug, Clone)]
143#[serde(rename_all = "kebab-case")]
144pub struct Chain {
145    pub chain_name: String,
146    pub chain_id: i64,
147    pub rpc_endpoints: Vec<RpcSettings>,
148    pub currency_symbol: String,
149    pub priority_fee: Decimal,
150    pub max_fee_per_gas: Decimal,
151    pub token: Token,
152    pub multi_contract: Option<MultiContractSettings>,
153    pub wrapper_contract: Option<WrapperContractSettings>,
154    pub mint_contract: Option<MintContractSettings>,
155    pub lock_contract: Option<LockContractSettings>,
156    pub distributor_contract: Option<DistributorContractSettings>,
157    pub attestation_contract: Option<EasContractSettings>,
158    pub schema_registry_contract: Option<EasSchemaRegistrySettings>,
159    pub faucet_client: Option<FaucetClientSettings>,
160    pub transaction_timeout: u64,
161    pub confirmation_blocks: u64,
162    pub faucet_eth_amount: Option<Decimal>,
163    pub faucet_glm_amount: Option<Decimal>,
164    pub block_explorer_url: Option<String>,
165    pub replacement_timeout: Option<f64>,
166    pub external_source_check_interval: Option<u64>,
167}
168
169#[derive(Deserialize, Serialize, Debug, Clone)]
170pub struct Token {
171    pub symbol: String,
172    pub address: Address,
173    pub faucet: Option<Address>,
174}
175
176impl Config {
177    pub fn default_config_str() -> &'static str {
178        //include config.toml
179        let config = include_str!("../config-payments.toml");
180        config
181    }
182
183    pub fn default_config() -> Self {
184        //include config.toml
185        Self::load_from_str(Self::default_config_str()).unwrap()
186    }
187
188    pub fn load_from_str(str: &str) -> Result<Self, PaymentError> {
189        match toml::from_str(str) {
190            Ok(config) => Ok(config),
191            Err(e) => Err(err_custom_create!("Failed to parse toml {}: {}", str, e)),
192        }
193    }
194
195    pub async fn load<P: AsRef<Path>>(path: P) -> Result<Self, PaymentError> {
196        match toml::from_str(&String::from_utf8_lossy(&fs::read(&path).await.map_err(
197            |e| match e.kind() {
198                std::io::ErrorKind::NotFound => {
199                    err_create!(e)
200                }
201                _ => {
202                    err_custom_create!(
203                        "Failed to read config file {}. Error {}",
204                        path.as_ref().display(),
205                        e
206                    )
207                }
208            },
209        )?)) {
210            Ok(config) => Ok(config),
211            Err(e) => Err(err_custom_create!(
212                "Failed to parse toml {}: {}",
213                path.as_ref().display(),
214                e
215            )),
216        }
217    }
218
219    pub async fn change_rpc_endpoints(
220        &mut self,
221        chain: &str,
222        rpc_endpoints: Vec<RpcSettings>,
223    ) -> Result<(), PaymentError> {
224        self.chain
225            .get_mut(chain)
226            .ok_or(err_custom_create!("Chain {} not found", chain))?
227            .rpc_endpoints = rpc_endpoints;
228        Ok(())
229    }
230
231    pub async fn change_max_fee(
232        &mut self,
233        chain: &str,
234        max_fee_per_gas: Decimal,
235    ) -> Result<(), PaymentError> {
236        self.chain
237            .get_mut(chain)
238            .ok_or(err_custom_create!("Chain {} not found", chain))?
239            .max_fee_per_gas = max_fee_per_gas;
240        Ok(())
241    }
242}