kabu_anvil/test_config/
mod.rs

1use std::collections::HashMap;
2
3use alloy_primitives::{Address, TxHash};
4use eyre::Result;
5use serde::Deserialize;
6use tokio::fs;
7
8use kabu::types::entities::PoolClass;
9
10#[derive(Deserialize, Debug)]
11pub struct TestConfig {
12    pub modules: Modules,
13    pub settings: Settings,
14    pub pools: HashMap<String, PoolConfig>,
15    pub txs: HashMap<String, TransactionConfig>,
16    pub tokens: HashMap<String, TokenConfig>,
17    pub assertions: AssertionsConfig,
18}
19
20fn default_true() -> bool {
21    true
22}
23fn default_false() -> bool {
24    false
25}
26
27#[allow(dead_code)]
28#[derive(Default, Deserialize, Debug, Clone)]
29pub struct AssertionsConfig {
30    pub swaps_encoded: Option<usize>,
31    pub swaps_ok: Option<usize>,
32    pub best_profit_eth: Option<f64>,
33}
34
35#[allow(dead_code)]
36#[derive(Deserialize, Debug)]
37pub struct Modules {
38    #[serde(default = "default_true")]
39    pub price: bool,
40    #[serde(default = "default_true")]
41    pub signer: bool,
42    #[serde(default = "default_true")]
43    pub encoder: bool,
44    #[serde(default = "default_true")]
45    pub arb_path_merger: bool,
46    #[serde(default = "default_true")]
47    pub same_path_merger: bool,
48    #[serde(default = "default_true")]
49    pub diff_path_merger: bool,
50    #[serde(default)]
51    pub arb_block: bool,
52    #[serde(default = "default_true")]
53    pub arb_mempool: bool,
54    #[serde(default = "default_false")]
55    pub flashbots: bool,
56}
57
58#[allow(dead_code)]
59#[derive(Deserialize, Debug)]
60pub struct Settings {
61    pub block: u64,
62    pub coinbase: Option<Address>,
63    pub multicaller: Option<Address>,
64}
65
66#[derive(Deserialize, Debug)]
67pub struct PoolConfig {
68    pub address: Address,
69    pub class: PoolClass,
70}
71
72#[derive(Deserialize, Debug)]
73pub struct TransactionConfig {
74    pub hash: TxHash,
75    pub send: String,
76}
77
78#[derive(Deserialize, Debug)]
79pub struct TokenConfig {
80    pub address: Address,
81    pub symbol: Option<String>,
82    pub name: Option<String>,
83    pub decimals: Option<u8>,
84    pub basic: Option<bool>,
85    pub middle: Option<bool>,
86    pub price: Option<f64>,
87}
88
89impl TestConfig {
90    pub async fn from_file(filename: String) -> Result<TestConfig> {
91        let toml_content = fs::read_to_string(filename.as_str()).await?;
92        let config: TestConfig = toml::from_str(&toml_content)?;
93        Ok(config)
94    }
95}
96
97#[cfg(test)]
98mod test {
99    use crate::test_config::TestConfig;
100
101    #[test]
102    fn test_deserialization() {
103        let cfg = r#"
104[settings]
105block = 19101579
106coinbase = "0x1dd35b4da6534230ff53048f7477f17f7f4e7a70"
107multicaller = "0x3dd35b4da6534230ff53048f7477f17f7f4e7a70"
108skip_default = false
109
110[modules]
111
112[pools]
113a = { address = "0x2dd35b4da6534230ff53048f7477f17f7f4e7a70", class = "uniswap2" }
114
115[txs]
116tx_1 = { hash = "0xf9fb98fe76dc5f4e836cdc3d80cd7902150a8609c617064f1447c3980fd6776b", send = "mempool" }
117tx_2 = { hash = "0x1ec982c2d4eb5475192b26f7208b797328eab88f8e5be053f797f74bcb87a20c", send = "mempool" }
118
119[tokens]
120weth = { address = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", symbol = "WETH", decimals = 18, basic = true, middle = false }
121
122[assertions]
123swaps_encoded = 14
124swaps_ok = 11
125best_profit_eth = 181.37
126        "#;
127        let config: TestConfig = toml::from_str(cfg).unwrap();
128        assert_eq!(config.settings.block, 19101579);
129        assert_eq!(config.assertions.swaps_encoded.unwrap_or_default(), 14);
130        assert_eq!(config.assertions.swaps_ok.unwrap_or_default(), 11);
131        assert_eq!(config.assertions.best_profit_eth.unwrap_or_default(), 181.37);
132    }
133}