refactor: simplify GasFeeStrategy from singleton to static methods
- Replace OnceLock singleton pattern with LazyLock static storage - Convert instance methods to static methods for better performance - Remove enabled/disabled strategy type management complexity - Update parallel execution to use new static API
This commit is contained in:
+65
-167
@@ -1,7 +1,7 @@
|
|||||||
use crate::swqos::{SwqosType, TradeType};
|
use crate::swqos::{SwqosType, TradeType};
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, OnceLock};
|
use std::sync::{Arc, LazyLock};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum GasFeeStrategyType {
|
pub enum GasFeeStrategyType {
|
||||||
@@ -23,30 +23,15 @@ pub struct GasFeeStrategyValue {
|
|||||||
pub tip: f64,
|
pub tip: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
// 静态存储策略数据
|
||||||
pub struct GasFeeStrategy {
|
static STRATEGIES: LazyLock<
|
||||||
strategies: ArcSwap<HashMap<(SwqosType, TradeType, GasFeeStrategyType), GasFeeStrategyValue>>,
|
ArcSwap<HashMap<(SwqosType, TradeType, GasFeeStrategyType), GasFeeStrategyValue>>,
|
||||||
enabled_types: ArcSwap<HashMap<TradeType, Vec<GasFeeStrategyType>>>,
|
> = LazyLock::new(|| ArcSwap::from_pointee(HashMap::new()));
|
||||||
swqos_disabled_types: ArcSwap<HashMap<(SwqosType, TradeType), Vec<GasFeeStrategyType>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
static INSTANCE: OnceLock<Arc<GasFeeStrategy>> = OnceLock::new();
|
pub struct GasFeeStrategy;
|
||||||
|
|
||||||
impl GasFeeStrategy {
|
impl GasFeeStrategy {
|
||||||
pub fn instance() -> Arc<GasFeeStrategy> {
|
|
||||||
INSTANCE.get_or_init(|| Arc::new(GasFeeStrategy::new())).clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
strategies: ArcSwap::new(Arc::new(HashMap::new())),
|
|
||||||
enabled_types: ArcSwap::new(Arc::new(HashMap::new())),
|
|
||||||
swqos_disabled_types: ArcSwap::new(Arc::new(HashMap::new())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_high_low_fee_strategies(
|
pub fn add_high_low_fee_strategies(
|
||||||
&self,
|
|
||||||
swqos_types: &[SwqosType],
|
swqos_types: &[SwqosType],
|
||||||
trade_type: TradeType,
|
trade_type: TradeType,
|
||||||
cu_limit: u32,
|
cu_limit: u32,
|
||||||
@@ -54,8 +39,11 @@ impl GasFeeStrategy {
|
|||||||
high_cu_price: u64,
|
high_cu_price: u64,
|
||||||
low_tip: f64,
|
low_tip: f64,
|
||||||
high_tip: f64,
|
high_tip: f64,
|
||||||
) -> &Self {
|
) {
|
||||||
self.strategies.rcu(|current_map| {
|
for swqos_type in swqos_types {
|
||||||
|
GasFeeStrategy::remove_strategy(*swqos_type, trade_type);
|
||||||
|
}
|
||||||
|
STRATEGIES.rcu(|current_map| {
|
||||||
let mut new_map = (**current_map).clone();
|
let mut new_map = (**current_map).clone();
|
||||||
for swqos_type in swqos_types {
|
for swqos_type in swqos_types {
|
||||||
if swqos_type.eq(&SwqosType::Default) {
|
if swqos_type.eq(&SwqosType::Default) {
|
||||||
@@ -72,11 +60,9 @@ impl GasFeeStrategy {
|
|||||||
}
|
}
|
||||||
Arc::new(new_map)
|
Arc::new(new_map)
|
||||||
});
|
});
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_high_low_fee_strategy(
|
pub fn add_high_low_fee_strategy(
|
||||||
&self,
|
|
||||||
swqos_type: SwqosType,
|
swqos_type: SwqosType,
|
||||||
trade_type: TradeType,
|
trade_type: TradeType,
|
||||||
cu_limit: u32,
|
cu_limit: u32,
|
||||||
@@ -84,11 +70,12 @@ impl GasFeeStrategy {
|
|||||||
high_cu_price: u64,
|
high_cu_price: u64,
|
||||||
low_tip: f64,
|
low_tip: f64,
|
||||||
high_tip: f64,
|
high_tip: f64,
|
||||||
) -> &Self {
|
) {
|
||||||
if swqos_type.eq(&SwqosType::Default) {
|
if swqos_type.eq(&SwqosType::Default) {
|
||||||
return self;
|
return;
|
||||||
}
|
}
|
||||||
self.strategies.rcu(|current_map| {
|
GasFeeStrategy::remove_strategy(swqos_type, trade_type);
|
||||||
|
STRATEGIES.rcu(|current_map| {
|
||||||
let mut new_map = (**current_map).clone();
|
let mut new_map = (**current_map).clone();
|
||||||
new_map.insert(
|
new_map.insert(
|
||||||
(swqos_type, trade_type, GasFeeStrategyType::LowTipHighCuPrice),
|
(swqos_type, trade_type, GasFeeStrategyType::LowTipHighCuPrice),
|
||||||
@@ -100,18 +87,19 @@ impl GasFeeStrategy {
|
|||||||
);
|
);
|
||||||
Arc::new(new_map)
|
Arc::new(new_map)
|
||||||
});
|
});
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_default_fee_strategies(
|
pub fn add_default_fee_strategies(
|
||||||
&self,
|
|
||||||
swqos_types: &[SwqosType],
|
swqos_types: &[SwqosType],
|
||||||
trade_type: TradeType,
|
trade_type: TradeType,
|
||||||
cu_price: u64,
|
cu_price: u64,
|
||||||
tip: f64,
|
tip: f64,
|
||||||
cu_limit: u32,
|
cu_limit: u32,
|
||||||
) -> &Self {
|
) {
|
||||||
self.strategies.rcu(|current_map| {
|
for swqos_type in swqos_types {
|
||||||
|
GasFeeStrategy::remove_strategy(*swqos_type, trade_type);
|
||||||
|
}
|
||||||
|
STRATEGIES.rcu(|current_map| {
|
||||||
let mut new_map = (**current_map).clone();
|
let mut new_map = (**current_map).clone();
|
||||||
for swqos_type in swqos_types {
|
for swqos_type in swqos_types {
|
||||||
new_map.insert(
|
new_map.insert(
|
||||||
@@ -121,18 +109,17 @@ impl GasFeeStrategy {
|
|||||||
}
|
}
|
||||||
Arc::new(new_map)
|
Arc::new(new_map)
|
||||||
});
|
});
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_default_fee_strategy(
|
pub fn add_default_fee_strategy(
|
||||||
&self,
|
|
||||||
swqos_type: SwqosType,
|
swqos_type: SwqosType,
|
||||||
trade_type: TradeType,
|
trade_type: TradeType,
|
||||||
cu_price: u64,
|
cu_price: u64,
|
||||||
tip: f64,
|
tip: f64,
|
||||||
cu_limit: u32,
|
cu_limit: u32,
|
||||||
) -> &Self {
|
) {
|
||||||
self.strategies.rcu(|current_map| {
|
GasFeeStrategy::remove_strategy(swqos_type, trade_type);
|
||||||
|
STRATEGIES.rcu(|current_map| {
|
||||||
let mut new_map = (**current_map).clone();
|
let mut new_map = (**current_map).clone();
|
||||||
new_map.insert(
|
new_map.insert(
|
||||||
(swqos_type, trade_type, GasFeeStrategyType::Default),
|
(swqos_type, trade_type, GasFeeStrategyType::Default),
|
||||||
@@ -140,47 +127,22 @@ impl GasFeeStrategy {
|
|||||||
);
|
);
|
||||||
Arc::new(new_map)
|
Arc::new(new_map)
|
||||||
});
|
});
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_default_fee_strategy(
|
pub fn remove_strategy(swqos_type: SwqosType, trade_type: TradeType) {
|
||||||
&self,
|
STRATEGIES.rcu(|current_map| {
|
||||||
swqos_type: SwqosType,
|
|
||||||
trade_type: TradeType,
|
|
||||||
) -> &Self {
|
|
||||||
self.strategies.rcu(|current_map| {
|
|
||||||
let mut new_map = (**current_map).clone();
|
let mut new_map = (**current_map).clone();
|
||||||
new_map.remove(&(swqos_type, trade_type, GasFeeStrategyType::Default));
|
new_map.remove(&(swqos_type, trade_type, GasFeeStrategyType::Default));
|
||||||
Arc::new(new_map)
|
|
||||||
});
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove_high_low_fee_strategy(
|
|
||||||
&self,
|
|
||||||
swqos_type: SwqosType,
|
|
||||||
trade_type: TradeType,
|
|
||||||
) -> &Self {
|
|
||||||
self.strategies.rcu(|current_map| {
|
|
||||||
let mut new_map = (**current_map).clone();
|
|
||||||
new_map.remove(&(swqos_type, trade_type, GasFeeStrategyType::LowTipHighCuPrice));
|
new_map.remove(&(swqos_type, trade_type, GasFeeStrategyType::LowTipHighCuPrice));
|
||||||
new_map.remove(&(swqos_type, trade_type, GasFeeStrategyType::HighTipLowCuPrice));
|
new_map.remove(&(swqos_type, trade_type, GasFeeStrategyType::HighTipLowCuPrice));
|
||||||
Arc::new(new_map)
|
Arc::new(new_map)
|
||||||
});
|
});
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_all_strategies(
|
|
||||||
&self,
|
|
||||||
) -> HashMap<(SwqosType, TradeType, GasFeeStrategyType), GasFeeStrategyValue> {
|
|
||||||
(**self.strategies.load()).clone()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_strategies(
|
pub fn get_strategies(
|
||||||
&self,
|
|
||||||
trade_type: TradeType,
|
trade_type: TradeType,
|
||||||
) -> Vec<(SwqosType, GasFeeStrategyType, GasFeeStrategyValue)> {
|
) -> Vec<(SwqosType, GasFeeStrategyType, GasFeeStrategyValue)> {
|
||||||
let strategies = self.strategies.load();
|
let strategies = STRATEGIES.load();
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
let mut swqos_types = std::collections::HashSet::new();
|
let mut swqos_types = std::collections::HashSet::new();
|
||||||
for (swqos_type, t_type, _) in strategies.keys() {
|
for (swqos_type, t_type, _) in strategies.keys() {
|
||||||
@@ -200,81 +162,8 @@ impl GasFeeStrategy {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_available_strategies(
|
pub fn clear() {
|
||||||
&self,
|
STRATEGIES.store(Arc::new(HashMap::new()));
|
||||||
trade_type: TradeType,
|
|
||||||
) -> Vec<(SwqosType, GasFeeStrategyType, GasFeeStrategyValue)> {
|
|
||||||
let strategies = self.strategies.load();
|
|
||||||
let enabled_types = self.get_enabled_strategy_types(trade_type);
|
|
||||||
let mut result = Vec::new();
|
|
||||||
let mut swqos_types = std::collections::HashSet::new();
|
|
||||||
for (swqos_type, t_type, _) in strategies.keys() {
|
|
||||||
if *t_type == trade_type {
|
|
||||||
swqos_types.insert(*swqos_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for swqos_type in swqos_types {
|
|
||||||
let disabled_types = self.get_swqos_disabled_strategy_types(swqos_type, trade_type);
|
|
||||||
for strategy_type in &enabled_types {
|
|
||||||
if disabled_types.contains(strategy_type) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if let Some(strategy_value) =
|
|
||||||
strategies.get(&(swqos_type, trade_type, *strategy_type))
|
|
||||||
{
|
|
||||||
result.push((swqos_type, *strategy_type, *strategy_value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_enabled_strategy_types(
|
|
||||||
&self,
|
|
||||||
trade_type: TradeType,
|
|
||||||
types: &[GasFeeStrategyType],
|
|
||||||
) -> &Self {
|
|
||||||
self.enabled_types.rcu(|current_map| {
|
|
||||||
let mut new_map = (**current_map).clone();
|
|
||||||
new_map.insert(trade_type, types.to_vec());
|
|
||||||
Arc::new(new_map)
|
|
||||||
});
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_enabled_strategy_types(&self, trade_type: TradeType) -> Vec<GasFeeStrategyType> {
|
|
||||||
let strategies = self.enabled_types.load();
|
|
||||||
(**strategies).get(&trade_type).cloned().unwrap_or_default()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_swqos_disabled_strategy_types(
|
|
||||||
&self,
|
|
||||||
swqos_type: SwqosType,
|
|
||||||
trade_type: TradeType,
|
|
||||||
types: &[GasFeeStrategyType],
|
|
||||||
) -> &Self {
|
|
||||||
self.swqos_disabled_types.rcu(|current_map| {
|
|
||||||
let mut new_map = (**current_map).clone();
|
|
||||||
new_map.insert((swqos_type, trade_type), types.to_vec());
|
|
||||||
Arc::new(new_map)
|
|
||||||
});
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_swqos_disabled_strategy_types(
|
|
||||||
&self,
|
|
||||||
swqos_type: SwqosType,
|
|
||||||
trade_type: TradeType,
|
|
||||||
) -> Vec<GasFeeStrategyType> {
|
|
||||||
let disabled_strategies = self.swqos_disabled_types.load();
|
|
||||||
(**disabled_strategies).get(&(swqos_type, trade_type)).cloned().unwrap_or_default()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear(&self) -> &Self {
|
|
||||||
self.strategies.store(Arc::new(HashMap::new()));
|
|
||||||
self.enabled_types.store(Arc::new(HashMap::new()));
|
|
||||||
self.swqos_disabled_types.store(Arc::new(HashMap::new()));
|
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,33 +173,42 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn demo() {
|
fn demo() {
|
||||||
GasFeeStrategy::instance()
|
// 给SwqosType::Default 在 Buy 时添加默认策略
|
||||||
// 给SwqosType::Default在 Buy 时添加默认策略
|
GasFeeStrategy::add_default_fee_strategy(
|
||||||
.add_default_fee_strategy(SwqosType::Default, TradeType::Buy, 100, 0.0001, 10)
|
SwqosType::Default,
|
||||||
// 给SwqosType::Jito在 Buy 时添加高低价策略
|
TradeType::Buy,
|
||||||
.add_high_low_fee_strategy(SwqosType::Jito, TradeType::Buy, 10, 100, 10000, 0.001, 0.1)
|
100,
|
||||||
// 给SwqosType::Jito在 Buy 时添加默认策略
|
0.0001,
|
||||||
.add_default_fee_strategy(SwqosType::Jito, TradeType::Buy, 100, 0.0001, 10)
|
10,
|
||||||
// 设置在 Buy 时启用策略 - 启用两个高低价策略、默认策略
|
);
|
||||||
.set_enabled_strategy_types(
|
// 给SwqosType::Jito 在 Buy 时添加高低价策略
|
||||||
TradeType::Buy,
|
GasFeeStrategy::add_high_low_fee_strategy(
|
||||||
&[
|
SwqosType::Jito,
|
||||||
GasFeeStrategyType::HighTipLowCuPrice,
|
TradeType::Buy,
|
||||||
GasFeeStrategyType::LowTipHighCuPrice,
|
10,
|
||||||
GasFeeStrategyType::Default,
|
100,
|
||||||
],
|
10000,
|
||||||
)
|
0.001,
|
||||||
// 设置SwqosType::Jito在 Buy 时禁用策略 - 禁用 (默认策略)
|
0.1,
|
||||||
.set_swqos_disabled_strategy_types(
|
);
|
||||||
SwqosType::Jito,
|
// 获取所有 Buy 策略
|
||||||
TradeType::Buy,
|
let all_strategies = GasFeeStrategy::get_strategies(TradeType::Buy);
|
||||||
&[GasFeeStrategyType::Default],
|
for strategy in all_strategies {
|
||||||
);
|
println!("strategy: {:?}", strategy);
|
||||||
// 获取在 Buy 时可用的策略
|
}
|
||||||
let strategies = GasFeeStrategy::instance().get_available_strategies(TradeType::Buy);
|
println!("--------------------------------");
|
||||||
println!("strategies: {:?}", strategies);
|
// 给SwqosType::Jito 在 Buy 时添加默认策略(会删除 jito 的高低价策略)
|
||||||
// 获取所有 Buy 策略(包括禁用的)
|
GasFeeStrategy::add_default_fee_strategy(SwqosType::Jito, TradeType::Buy, 100, 0.0001, 10);
|
||||||
let all_strategies = GasFeeStrategy::instance().get_strategies(TradeType::Buy);
|
// 获取所有 Buy 策略
|
||||||
println!("all_strategies: {:?}", all_strategies);
|
let all_strategies = GasFeeStrategy::get_strategies(TradeType::Buy);
|
||||||
|
for strategy in all_strategies {
|
||||||
|
println!("strategy: {:?}", strategy);
|
||||||
|
}
|
||||||
|
// 删除SwqosType::Jito 在 Buy 时的策略
|
||||||
|
GasFeeStrategy::remove_strategy(SwqosType::Jito, TradeType::Buy);
|
||||||
|
// 清空策略
|
||||||
|
GasFeeStrategy::clear();
|
||||||
|
println!("--------------------------------");
|
||||||
|
println!("strategy {:?}", GasFeeStrategy::get_strategies(TradeType::Buy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,7 @@ use tokio::task::JoinHandle;
|
|||||||
use crate::{
|
use crate::{
|
||||||
common::GasFeeStrategy,
|
common::GasFeeStrategy,
|
||||||
swqos::{SwqosClient, SwqosType, TradeType},
|
swqos::{SwqosClient, SwqosType, TradeType},
|
||||||
trading::{
|
trading::{common::build_transaction, BuyParams, MiddlewareManager, SellParams},
|
||||||
common::build_transaction, BuyParams, SellParams, MiddlewareManager,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async fn buy_parallel_execute(
|
pub async fn buy_parallel_execute(
|
||||||
@@ -95,8 +93,11 @@ async fn parallel_execute(
|
|||||||
with_tip || matches!(swqos_client.get_swqos_type(), SwqosType::Default)
|
with_tip || matches!(swqos_client.get_swqos_type(), SwqosType::Default)
|
||||||
})
|
})
|
||||||
.flat_map(|(i, swqos_client)| {
|
.flat_map(|(i, swqos_client)| {
|
||||||
let gas_fee_strategy_configs = GasFeeStrategy::instance()
|
let gas_fee_strategy_configs = GasFeeStrategy::get_strategies(if is_buy {
|
||||||
.get_available_strategies(if is_buy { TradeType::Buy } else { TradeType::Sell });
|
TradeType::Buy
|
||||||
|
} else {
|
||||||
|
TradeType::Sell
|
||||||
|
});
|
||||||
gas_fee_strategy_configs
|
gas_fee_strategy_configs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|config| config.0.eq(&swqos_client.get_swqos_type()))
|
.filter(|config| config.0.eq(&swqos_client.get_swqos_type()))
|
||||||
|
|||||||
Reference in New Issue
Block a user