feat: add Bonk trading examples and fix function naming
- Add comprehensive Bonk trading examples in README - Fix function naming consistency (width -> with) - Enhance BonkParams with from_trade and from_dev_trade methods - Add amount calculation utilities and tests
This commit is contained in:
@@ -1,6 +1,59 @@
|
||||
use crate::constants;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
|
||||
pub fn get_amount_in_net(
|
||||
amount_in: u64,
|
||||
protocol_fee_rate: u128,
|
||||
platform_fee_rate: u128,
|
||||
share_fee_rate: u128,
|
||||
) -> u64 {
|
||||
let amount_in_u128 = amount_in as u128;
|
||||
let protocol_fee = (amount_in_u128 * protocol_fee_rate / 10000) as u128;
|
||||
let platform_fee = (amount_in_u128 * platform_fee_rate / 10000) as u128;
|
||||
let share_fee = (amount_in_u128 * share_fee_rate / 10000) as u128;
|
||||
amount_in_u128
|
||||
.checked_sub(protocol_fee)
|
||||
.unwrap()
|
||||
.checked_sub(platform_fee)
|
||||
.unwrap()
|
||||
.checked_sub(share_fee)
|
||||
.unwrap() as u64
|
||||
}
|
||||
|
||||
pub fn get_amount_in(
|
||||
amount_out: u64,
|
||||
protocol_fee_rate: u128,
|
||||
platform_fee_rate: u128,
|
||||
share_fee_rate: u128,
|
||||
virtual_base: u128,
|
||||
virtual_quote: u128,
|
||||
real_base: u128,
|
||||
real_quote: u128,
|
||||
slippage_basis_points: u128,
|
||||
) -> u64 {
|
||||
let amount_out_u128 = amount_out as u128;
|
||||
|
||||
// 考虑滑点,实际需要的输出金额更高
|
||||
let amount_out_with_slippage = amount_out_u128 * 10000 / (10000 - slippage_basis_points);
|
||||
|
||||
let input_reserve = virtual_quote.checked_add(real_quote).unwrap();
|
||||
let output_reserve = virtual_base.checked_sub(real_base).unwrap();
|
||||
|
||||
// 根据 AMM 公式反推: amount_in_net = (amount_out * input_reserve) / (output_reserve - amount_out)
|
||||
let numerator = amount_out_with_slippage.checked_mul(input_reserve).unwrap();
|
||||
let denominator = output_reserve
|
||||
.checked_sub(amount_out_with_slippage)
|
||||
.unwrap();
|
||||
let amount_in_net = numerator.checked_div(denominator).unwrap();
|
||||
|
||||
// 计算总费用率
|
||||
let total_fee_rate = protocol_fee_rate + platform_fee_rate + share_fee_rate;
|
||||
|
||||
let amount_in = amount_in_net * 10000 / (10000 - total_fee_rate);
|
||||
|
||||
amount_in as u64
|
||||
}
|
||||
|
||||
pub fn get_amount_out(
|
||||
amount_in: u64,
|
||||
protocol_fee_rate: u128,
|
||||
@@ -80,3 +133,57 @@ pub fn get_token_price(
|
||||
|
||||
price
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::constants::bonk::accounts::{PLATFORM_FEE_RATE, PROTOCOL_FEE_RATE, SHARE_FEE_RATE};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_amount_in_out_consistency() {
|
||||
// 测试参数
|
||||
let protocol_fee_rate = PROTOCOL_FEE_RATE;
|
||||
let platform_fee_rate = PLATFORM_FEE_RATE;
|
||||
let share_fee_rate = SHARE_FEE_RATE;
|
||||
let virtual_base = 1073025605596382;
|
||||
let virtual_quote = 30000852951;
|
||||
let real_base = 0;
|
||||
let real_quote = 0;
|
||||
let slippage_basis_points = 0;
|
||||
|
||||
let original_amount_in = 2000000000;
|
||||
|
||||
let geet_amount_out_result = get_amount_out(
|
||||
original_amount_in,
|
||||
protocol_fee_rate,
|
||||
platform_fee_rate,
|
||||
share_fee_rate,
|
||||
virtual_base,
|
||||
virtual_quote,
|
||||
real_base,
|
||||
real_quote,
|
||||
slippage_basis_points,
|
||||
);
|
||||
|
||||
let amount_out = 25959582643397;
|
||||
let get_amount_in_result = get_amount_in(
|
||||
amount_out,
|
||||
protocol_fee_rate,
|
||||
platform_fee_rate,
|
||||
share_fee_rate,
|
||||
virtual_base,
|
||||
virtual_quote,
|
||||
real_base,
|
||||
real_quote,
|
||||
slippage_basis_points,
|
||||
);
|
||||
|
||||
println!("Original amount_in: {}", original_amount_in);
|
||||
println!("Amount_out: {}", geet_amount_out_result);
|
||||
println!("Calculated amount_in: {}", get_amount_in_result);
|
||||
|
||||
assert!(geet_amount_out_result == 66275810509273);
|
||||
assert!(get_amount_in_result == 753217040);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,11 @@ use std::sync::Arc;
|
||||
use super::traits::ProtocolParams;
|
||||
use crate::common::bonding_curve::BondingCurveAccount;
|
||||
use crate::common::{PriorityFee, SolanaRpcClient};
|
||||
use crate::constants::bonk::accounts::{PLATFORM_FEE_RATE, PROTOCOL_FEE_RATE, SHARE_FEE_RATE};
|
||||
use crate::streaming::event_parser::common::EventType;
|
||||
use crate::streaming::event_parser::protocols::bonk::BonkTradeEvent;
|
||||
use crate::swqos::SwqosClient;
|
||||
use crate::trading::bonk::common::{get_amount_in, get_amount_in_net, get_amount_out};
|
||||
|
||||
/// 通用买入参数
|
||||
#[derive(Clone)]
|
||||
@@ -141,6 +145,64 @@ impl BonkParams {
|
||||
auto_handle_wsol: true,
|
||||
}
|
||||
}
|
||||
pub fn from_trade(trade_info: BonkTradeEvent) -> Self {
|
||||
Self {
|
||||
virtual_base: Some(trade_info.virtual_base as u128),
|
||||
virtual_quote: Some(trade_info.virtual_quote as u128),
|
||||
real_base: Some(trade_info.real_base_after as u128),
|
||||
real_quote: Some(trade_info.real_quote_after as u128),
|
||||
auto_handle_wsol: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_dev_trade(trade_info: BonkTradeEvent) -> Self {
|
||||
const DEFAULT_VIRTUAL_BASE: u128 = 1073025605596382;
|
||||
const DEFAULT_VIRTUAL_QUOTE: u128 = 30000852951;
|
||||
let amount_in = if trade_info.metadata.event_type == EventType::BonkBuyExactIn {
|
||||
trade_info.amount_in
|
||||
} else {
|
||||
get_amount_in(
|
||||
trade_info.amount_out,
|
||||
PROTOCOL_FEE_RATE,
|
||||
PLATFORM_FEE_RATE,
|
||||
SHARE_FEE_RATE,
|
||||
DEFAULT_VIRTUAL_BASE,
|
||||
DEFAULT_VIRTUAL_QUOTE,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
};
|
||||
let real_quote = get_amount_in_net(
|
||||
amount_in,
|
||||
PROTOCOL_FEE_RATE,
|
||||
PLATFORM_FEE_RATE,
|
||||
SHARE_FEE_RATE,
|
||||
) as u128;
|
||||
let amount_out = if trade_info.metadata.event_type == EventType::BonkBuyExactIn {
|
||||
get_amount_out(
|
||||
trade_info.amount_in,
|
||||
PROTOCOL_FEE_RATE,
|
||||
PLATFORM_FEE_RATE,
|
||||
SHARE_FEE_RATE,
|
||||
DEFAULT_VIRTUAL_BASE,
|
||||
DEFAULT_VIRTUAL_QUOTE,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
) as u128
|
||||
} else {
|
||||
trade_info.amount_out as u128
|
||||
};
|
||||
let real_base = amount_out;
|
||||
Self {
|
||||
virtual_base: Some(DEFAULT_VIRTUAL_BASE),
|
||||
virtual_quote: Some(DEFAULT_VIRTUAL_QUOTE),
|
||||
real_base: Some(real_base),
|
||||
real_quote: Some(real_quote),
|
||||
auto_handle_wsol: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ProtocolParams for BonkParams {
|
||||
|
||||
Reference in New Issue
Block a user