Merge branch '0xfnzero:main' into main
This commit is contained in:
@@ -317,6 +317,34 @@ impl GasFeeStrategy {
|
|||||||
self.strategies.store(Arc::new(HashMap::new()));
|
self.strategies.store(Arc::new(HashMap::new()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 动态更新买入小费(保持其他参数不变)
|
||||||
|
/// Dynamically update buy tip (keep other parameters unchanged)
|
||||||
|
pub fn update_buy_tip(&self, buy_tip: f64) {
|
||||||
|
self.strategies.rcu(|current_map| {
|
||||||
|
let mut new_map = (**current_map).clone();
|
||||||
|
for ((swqos_type, trade_type, strategy_type), value) in new_map.iter_mut() {
|
||||||
|
if *trade_type == TradeType::Buy {
|
||||||
|
value.tip = buy_tip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Arc::new(new_map)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 动态更新卖出小费(保持其他参数不变)
|
||||||
|
/// Dynamically update sell tip (keep other parameters unchanged)
|
||||||
|
pub fn update_sell_tip(&self, sell_tip: f64) {
|
||||||
|
self.strategies.rcu(|current_map| {
|
||||||
|
let mut new_map = (**current_map).clone();
|
||||||
|
for ((swqos_type, trade_type, strategy_type), value) in new_map.iter_mut() {
|
||||||
|
if *trade_type == TradeType::Sell {
|
||||||
|
value.tip = sell_tip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Arc::new(new_map)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// 打印所有策略。
|
/// 打印所有策略。
|
||||||
/// Print all strategies
|
/// Print all strategies
|
||||||
pub fn print_all_strategies(&self) {
|
pub fn print_all_strategies(&self) {
|
||||||
|
|||||||
@@ -217,3 +217,13 @@ pub const SWQOS_ENDPOINTS_ASTRALANE: [&str; 8] = [
|
|||||||
"http://lim.gateway.astralane.io/iris",
|
"http://lim.gateway.astralane.io/iris",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
pub const SWQOS_MIN_TIP_DEFAULT: f64 = 0.00001; // 其它SWQOS默认最低小费
|
||||||
|
pub const SWQOS_MIN_TIP_JITO: f64 = SWQOS_MIN_TIP_DEFAULT;
|
||||||
|
pub const SWQOS_MIN_TIP_NEXTBLOCK: f64 = SWQOS_MIN_TIP_DEFAULT;
|
||||||
|
pub const SWQOS_MIN_TIP_ZERO_SLOT: f64 = SWQOS_MIN_TIP_DEFAULT;
|
||||||
|
pub const SWQOS_MIN_TIP_TEMPORAL: f64 = SWQOS_MIN_TIP_DEFAULT;
|
||||||
|
pub const SWQOS_MIN_TIP_BLOXROUTE: f64 = SWQOS_MIN_TIP_DEFAULT;
|
||||||
|
pub const SWQOS_MIN_TIP_NODE1: f64 = 0.002; // 如需更高阈值可调整
|
||||||
|
pub const SWQOS_MIN_TIP_FLASHBLOCK: f64 = SWQOS_MIN_TIP_DEFAULT;
|
||||||
|
pub const SWQOS_MIN_TIP_BLOCKRAZOR: f64 = SWQOS_MIN_TIP_DEFAULT;
|
||||||
|
pub const SWQOS_MIN_TIP_ASTRALANE: f64 = SWQOS_MIN_TIP_DEFAULT;
|
||||||
|
|||||||
+19
-3
@@ -688,12 +688,28 @@ impl SolanaTrade {
|
|||||||
/// - 交易执行或确认失败
|
/// - 交易执行或确认失败
|
||||||
/// - 网络或 RPC 错误
|
/// - 网络或 RPC 错误
|
||||||
pub async fn wrap_wsol_to_sol(&self, amount: u64) -> Result<String, anyhow::Error> {
|
pub async fn wrap_wsol_to_sol(&self, amount: u64) -> Result<String, anyhow::Error> {
|
||||||
use crate::trading::common::wsol_manager::wrap_wsol_to_sol as wrap_wsol_to_sol_internal;
|
use crate::trading::common::wsol_manager::{wrap_wsol_to_sol as wrap_wsol_to_sol_internal, wrap_wsol_to_sol_without_create};
|
||||||
|
use crate::common::seed::get_associated_token_address_with_program_id_use_seed;
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
|
|
||||||
let recent_blockhash = self.rpc.get_latest_blockhash().await?;
|
// 检查临时seed账户是否已存在
|
||||||
let instructions = wrap_wsol_to_sol_internal(&self.payer.pubkey(), amount)?;
|
let seed_ata_address = get_associated_token_address_with_program_id_use_seed(
|
||||||
|
&self.payer.pubkey(),
|
||||||
|
&crate::constants::WSOL_TOKEN_ACCOUNT,
|
||||||
|
&crate::constants::TOKEN_PROGRAM,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let account_exists = self.rpc.get_account(&seed_ata_address).await.is_ok();
|
||||||
|
|
||||||
|
let instructions = if account_exists {
|
||||||
|
// 如果账户已存在,使用不创建账户的版本
|
||||||
|
wrap_wsol_to_sol_without_create(&self.payer.pubkey(), amount)?
|
||||||
|
} else {
|
||||||
|
// 如果账户不存在,使用创建账户的版本
|
||||||
|
wrap_wsol_to_sol_internal(&self.payer.pubkey(), amount)?
|
||||||
|
};
|
||||||
|
|
||||||
|
let recent_blockhash = self.rpc.get_latest_blockhash().await?;
|
||||||
let mut transaction = Transaction::new_with_payer(&instructions, Some(&self.payer.pubkey()));
|
let mut transaction = Transaction::new_with_payer(&instructions, Some(&self.payer.pubkey()));
|
||||||
transaction.sign(&[&*self.payer], recent_blockhash);
|
transaction.sign(&[&*self.payer], recent_blockhash);
|
||||||
let signature = self.rpc.send_and_confirm_transaction(&transaction).await?;
|
let signature = self.rpc.send_and_confirm_transaction(&transaction).await?;
|
||||||
|
|||||||
@@ -46,24 +46,10 @@ pub async fn build_transaction(
|
|||||||
|
|
||||||
// Add tip transfer instruction
|
// Add tip transfer instruction
|
||||||
if with_tip && tip_amount > 0.0 {
|
if with_tip && tip_amount > 0.0 {
|
||||||
// 🔧 Node1 最小小费金额限制:0.002 SOL(仅限 Node1)
|
|
||||||
const MIN_TIP_AMOUNT: f64 = 0.002;
|
|
||||||
|
|
||||||
// 检查是否是 Node1 的 tip_account
|
|
||||||
let is_node1 = NODE1_TIP_ACCOUNTS.iter().any(|&account| account == *tip_account);
|
|
||||||
|
|
||||||
let actual_tip_amount = if is_node1 && tip_amount < MIN_TIP_AMOUNT {
|
|
||||||
// Node1 要求最小 0.002 SOL
|
|
||||||
MIN_TIP_AMOUNT
|
|
||||||
} else {
|
|
||||||
// 其他 swqos 使用原始金额
|
|
||||||
tip_amount
|
|
||||||
};
|
|
||||||
|
|
||||||
instructions.push(transfer(
|
instructions.push(transfer(
|
||||||
&payer.pubkey(),
|
&payer.pubkey(),
|
||||||
tip_account,
|
tip_account,
|
||||||
sol_str_to_lamports(actual_tip_amount.to_string().as_str()).unwrap_or(0),
|
sol_str_to_lamports(tip_amount.to_string().as_str()).unwrap_or(0),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,17 +96,22 @@ pub fn wrap_sol_only(payer: &Pubkey, amount_in: u64) -> SmallVec<[Instruction; 2
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 将 WSOL 转换为 SOL,使用 seed 账户
|
/// 将 WSOL 转换为 SOL,使用 seed 账户
|
||||||
/// 1. 使用 super::seed::create_associated_token_account_use_seed 创建 WSOL seed 账号
|
/// 1. 检查 seed 账户是否已存在
|
||||||
/// 2. 使用 get_associated_token_address_with_program_id_use_seed 获取该账号的 ATA 地址
|
/// 2. 如果不存在,使用 super::seed::create_associated_token_account_use_seed 创建 WSOL seed 账号
|
||||||
/// 3. 添加从用户 WSOL ATA 转账到该 seed ATA 账号的指令
|
/// 3. 使用 get_associated_token_address_with_program_id_use_seed 获取该账号的 ATA 地址
|
||||||
/// 4. 添加关闭 WSOL seed 账号的指令
|
/// 4. 添加从用户 WSOL ATA 转账到该 seed ATA 账号的指令
|
||||||
|
/// 5. 添加关闭 WSOL seed 账号的指令
|
||||||
|
///
|
||||||
|
/// 注意:此函数只生成指令,不检查账户是否存在(需要调用方在发送交易前检查)
|
||||||
|
/// 如果临时账户已存在,可以安全地跳过创建步骤,直接转账并关闭
|
||||||
pub fn wrap_wsol_to_sol(
|
pub fn wrap_wsol_to_sol(
|
||||||
payer: &Pubkey,
|
payer: &Pubkey,
|
||||||
amount: u64,
|
amount: u64,
|
||||||
) -> Result<Vec<Instruction>, anyhow::Error> {
|
) -> Result<Vec<Instruction>, anyhow::Error> {
|
||||||
let mut instructions = Vec::new();
|
let mut instructions = Vec::new();
|
||||||
|
|
||||||
// 1. 创建 WSOL seed 账户
|
// 1. 创建 WSOL seed 账户(注意:如果账户已存在会失败)
|
||||||
|
// 调用方应该先检查账户是否存在,如果存在则跳过此步骤
|
||||||
let seed_account_instructions = create_associated_token_account_use_seed(
|
let seed_account_instructions = create_associated_token_account_use_seed(
|
||||||
payer,
|
payer,
|
||||||
payer,
|
payer,
|
||||||
@@ -152,3 +157,49 @@ pub fn wrap_wsol_to_sol(
|
|||||||
|
|
||||||
Ok(instructions)
|
Ok(instructions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 将 WSOL 转换为 SOL(仅转账和关闭,不创建账户)
|
||||||
|
/// 用于当临时seed账户已存在的情况
|
||||||
|
pub fn wrap_wsol_to_sol_without_create(
|
||||||
|
payer: &Pubkey,
|
||||||
|
amount: u64,
|
||||||
|
) -> Result<Vec<Instruction>, anyhow::Error> {
|
||||||
|
let mut instructions = Vec::new();
|
||||||
|
|
||||||
|
// 1. 获取 seed 账户的 ATA 地址
|
||||||
|
let seed_ata_address = get_associated_token_address_with_program_id_use_seed(
|
||||||
|
payer,
|
||||||
|
&crate::constants::WSOL_TOKEN_ACCOUNT,
|
||||||
|
&crate::constants::TOKEN_PROGRAM,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// 2. 获取用户的 WSOL ATA 地址
|
||||||
|
let user_wsol_ata = crate::common::fast_fn::get_associated_token_address_with_program_id_fast(
|
||||||
|
payer,
|
||||||
|
&crate::constants::WSOL_TOKEN_ACCOUNT,
|
||||||
|
&crate::constants::TOKEN_PROGRAM,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3. 添加从用户 WSOL ATA 转账到 seed ATA 的指令
|
||||||
|
let transfer_instruction = crate::common::spl_token::transfer(
|
||||||
|
&crate::constants::TOKEN_PROGRAM,
|
||||||
|
&user_wsol_ata,
|
||||||
|
&seed_ata_address,
|
||||||
|
payer,
|
||||||
|
amount,
|
||||||
|
&[],
|
||||||
|
)?;
|
||||||
|
instructions.push(transfer_instruction);
|
||||||
|
|
||||||
|
// 4. 添加关闭 WSOL seed 账户的指令
|
||||||
|
let close_instruction = close_account(
|
||||||
|
&crate::constants::TOKEN_PROGRAM,
|
||||||
|
&seed_ata_address,
|
||||||
|
payer,
|
||||||
|
payer,
|
||||||
|
&[],
|
||||||
|
)?;
|
||||||
|
instructions.push(close_instruction);
|
||||||
|
|
||||||
|
Ok(instructions)
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,6 +15,18 @@ use crate::{
|
|||||||
common::{GasFeeStrategy, SolanaRpcClient},
|
common::{GasFeeStrategy, SolanaRpcClient},
|
||||||
swqos::{SwqosClient, SwqosType, TradeType},
|
swqos::{SwqosClient, SwqosType, TradeType},
|
||||||
trading::{common::build_transaction, MiddlewareManager},
|
trading::{common::build_transaction, MiddlewareManager},
|
||||||
|
constants::swqos::{
|
||||||
|
SWQOS_MIN_TIP_DEFAULT,
|
||||||
|
SWQOS_MIN_TIP_JITO,
|
||||||
|
SWQOS_MIN_TIP_NEXTBLOCK,
|
||||||
|
SWQOS_MIN_TIP_ZERO_SLOT,
|
||||||
|
SWQOS_MIN_TIP_TEMPORAL,
|
||||||
|
SWQOS_MIN_TIP_BLOXROUTE,
|
||||||
|
SWQOS_MIN_TIP_NODE1,
|
||||||
|
SWQOS_MIN_TIP_FLASHBLOCK,
|
||||||
|
SWQOS_MIN_TIP_BLOCKRAZOR,
|
||||||
|
SWQOS_MIN_TIP_ASTRALANE,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[repr(align(64))]
|
#[repr(align(64))]
|
||||||
@@ -142,6 +154,26 @@ pub async fn execute_parallel(
|
|||||||
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()))
|
||||||
|
.filter(|config| {
|
||||||
|
// 当需要 tip 且不是 Default 时,按 provider 最低小费进行筛选
|
||||||
|
if with_tip && !matches!(config.0, SwqosType::Default) {
|
||||||
|
let min_tip = match config.0 {
|
||||||
|
SwqosType::Jito => SWQOS_MIN_TIP_JITO,
|
||||||
|
SwqosType::NextBlock => SWQOS_MIN_TIP_NEXTBLOCK,
|
||||||
|
SwqosType::ZeroSlot => SWQOS_MIN_TIP_ZERO_SLOT,
|
||||||
|
SwqosType::Temporal => SWQOS_MIN_TIP_TEMPORAL,
|
||||||
|
SwqosType::Bloxroute => SWQOS_MIN_TIP_BLOXROUTE,
|
||||||
|
SwqosType::Node1 => SWQOS_MIN_TIP_NODE1,
|
||||||
|
SwqosType::FlashBlock => SWQOS_MIN_TIP_FLASHBLOCK,
|
||||||
|
SwqosType::BlockRazor => SWQOS_MIN_TIP_BLOCKRAZOR,
|
||||||
|
SwqosType::Astralane => SWQOS_MIN_TIP_ASTRALANE,
|
||||||
|
SwqosType::Default => SWQOS_MIN_TIP_DEFAULT,
|
||||||
|
};
|
||||||
|
config.2.tip >= min_tip
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
})
|
||||||
.map(move |config| (i, swqos_client.clone(), config))
|
.map(move |config| (i, swqos_client.clone(), config))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|||||||
Reference in New Issue
Block a user