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