update dir
This commit is contained in:
Executable
+211
@@ -0,0 +1,211 @@
|
||||
//! Bonding curve account for the Pump.fun Solana Program
|
||||
//!
|
||||
//! This module contains the definition for the bonding curve account.
|
||||
//!
|
||||
//! # Bonding Curve Account
|
||||
//!
|
||||
//! The bonding curve account is used to manage token pricing and liquidity.
|
||||
//!
|
||||
//! # Fields
|
||||
//!
|
||||
//! - `discriminator`: Unique identifier for the bonding curve
|
||||
//! - `virtual_token_reserves`: Virtual token reserves used for price calculations
|
||||
//! - `virtual_sol_reserves`: Virtual SOL reserves used for price calculations
|
||||
//! - `real_token_reserves`: Actual token reserves available for trading
|
||||
//! - `real_sol_reserves`: Actual SOL reserves available for trading
|
||||
//! - `token_total_supply`: Total supply of tokens
|
||||
//! - `complete`: Whether the bonding curve is complete/finalized
|
||||
//!
|
||||
//! # Methods
|
||||
//!
|
||||
//! - `new`: Creates a new bonding curve instance
|
||||
//! - `get_buy_price`: Calculates the amount of tokens received for a given SOL amount
|
||||
//! - `get_sell_price`: Calculates the amount of SOL received for selling tokens
|
||||
//! - `get_market_cap_sol`: Calculates the current market cap in SOL
|
||||
//! - `get_final_market_cap_sol`: Calculates the final market cap in SOL after all tokens are sold
|
||||
//! - `get_buy_out_price`: Calculates the price to buy out all remaining tokens
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
|
||||
use crate::{constants::pumpfun::global_constants::{INITIAL_REAL_TOKEN_RESERVES, INITIAL_VIRTUAL_SOL_RESERVES, INITIAL_VIRTUAL_TOKEN_RESERVES, TOKEN_TOTAL_SUPPLY}, trading::pumpfun::common::{get_bonding_curve_pda, get_creator_vault_pda}};
|
||||
|
||||
/// Represents the global configuration account for token pricing and fees
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct BondingCurveAccount {
|
||||
/// Unique identifier for the bonding curve
|
||||
pub discriminator: u64,
|
||||
/// Account address
|
||||
pub account: Pubkey,
|
||||
/// Virtual token reserves used for price calculations
|
||||
pub virtual_token_reserves: u64,
|
||||
/// Virtual SOL reserves used for price calculations
|
||||
pub virtual_sol_reserves: u64,
|
||||
/// Actual token reserves available for trading
|
||||
pub real_token_reserves: u64,
|
||||
/// Actual SOL reserves available for trading
|
||||
pub real_sol_reserves: u64,
|
||||
/// Total supply of tokens
|
||||
pub token_total_supply: u64,
|
||||
/// Whether the bonding curve is complete/finalized
|
||||
pub complete: bool,
|
||||
/// Creator of the bonding curve
|
||||
pub creator: Pubkey,
|
||||
}
|
||||
|
||||
impl BondingCurveAccount {
|
||||
/// Creates a new bonding curve instance
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `discriminator` - Unique identifier for the curve
|
||||
/// * `virtual_token_reserves` - Virtual token reserves for price calculations
|
||||
/// * `virtual_sol_reserves` - Virtual SOL reserves for price calculations
|
||||
/// * `real_token_reserves` - Actual token reserves available
|
||||
/// * `real_sol_reserves` - Actual SOL reserves available
|
||||
/// * `token_total_supply` - Total supply of tokens
|
||||
/// * `complete` - Whether the curve is complete
|
||||
pub fn new(mint: &Pubkey, dev_buy_token: u64, dev_cost_sol: u64, creator: Pubkey) -> Self {
|
||||
Self {
|
||||
discriminator: 0,
|
||||
account: get_bonding_curve_pda(mint).unwrap(),
|
||||
virtual_token_reserves: INITIAL_VIRTUAL_TOKEN_RESERVES - dev_buy_token,
|
||||
virtual_sol_reserves: INITIAL_VIRTUAL_SOL_RESERVES + dev_cost_sol,
|
||||
real_token_reserves: INITIAL_REAL_TOKEN_RESERVES - dev_buy_token,
|
||||
real_sol_reserves: dev_cost_sol,
|
||||
token_total_supply: TOKEN_TOTAL_SUPPLY,
|
||||
complete: false,
|
||||
creator: creator,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_creator_vault_pda(&self) -> Pubkey {
|
||||
get_creator_vault_pda(&self.creator).unwrap()
|
||||
}
|
||||
|
||||
/// Calculates the amount of tokens received for a given SOL amount
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `amount` - Amount of SOL to spend
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Ok(u64)` - Amount of tokens that would be received
|
||||
/// * `Err(&str)` - Error message if curve is complete
|
||||
pub fn get_buy_price(&self, amount: u64) -> Result<u64, &'static str> {
|
||||
if self.complete {
|
||||
return Err("Curve is complete");
|
||||
}
|
||||
|
||||
if amount == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
// Calculate the product of virtual reserves using u128 to avoid overflow
|
||||
let n: u128 = (self.virtual_sol_reserves as u128) * (self.virtual_token_reserves as u128);
|
||||
|
||||
// Calculate the new virtual sol reserves after the purchase
|
||||
let i: u128 = (self.virtual_sol_reserves as u128) + (amount as u128);
|
||||
|
||||
// Calculate the new virtual token reserves after the purchase
|
||||
let r: u128 = n / i + 1;
|
||||
|
||||
// Calculate the amount of tokens to be purchased
|
||||
let s: u128 = (self.virtual_token_reserves as u128) - r;
|
||||
|
||||
// Convert back to u64 and return the minimum of calculated tokens and real reserves
|
||||
let s_u64 = s as u64;
|
||||
Ok(if s_u64 < self.real_token_reserves {
|
||||
s_u64
|
||||
} else {
|
||||
self.real_token_reserves
|
||||
})
|
||||
}
|
||||
|
||||
/// Calculates the amount of SOL received for selling tokens
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `amount` - Amount of tokens to sell
|
||||
/// * `fee_basis_points` - Fee in basis points (1/100th of a percent)
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Ok(u64)` - Amount of SOL that would be received after fees
|
||||
/// * `Err(&str)` - Error message if curve is complete
|
||||
pub fn get_sell_price(&self, amount: u64, fee_basis_points: u64) -> Result<u64, &'static str> {
|
||||
if self.complete {
|
||||
return Err("Curve is complete");
|
||||
}
|
||||
|
||||
if amount == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
// Calculate the proportional amount of virtual sol reserves to be received using u128
|
||||
let n: u128 = ((amount as u128) * (self.virtual_sol_reserves as u128))
|
||||
/ ((self.virtual_token_reserves as u128) + (amount as u128));
|
||||
|
||||
// Calculate the fee amount in the same units
|
||||
let a: u128 = (n * (fee_basis_points as u128)) / 10000;
|
||||
|
||||
// Return the net amount after deducting the fee, converting back to u64
|
||||
Ok((n - a) as u64)
|
||||
}
|
||||
|
||||
/// Calculates the current market cap in SOL
|
||||
pub fn get_market_cap_sol(&self) -> u64 {
|
||||
if self.virtual_token_reserves == 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
((self.token_total_supply as u128) * (self.virtual_sol_reserves as u128)
|
||||
/ (self.virtual_token_reserves as u128)) as u64
|
||||
}
|
||||
|
||||
/// Calculates the final market cap in SOL after all tokens are sold
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `fee_basis_points` - Fee in basis points (1/100th of a percent)
|
||||
pub fn get_final_market_cap_sol(&self, fee_basis_points: u64) -> u64 {
|
||||
let total_sell_value: u128 =
|
||||
self.get_buy_out_price(self.real_token_reserves, fee_basis_points) as u128;
|
||||
let total_virtual_value: u128 = (self.virtual_sol_reserves as u128) + total_sell_value;
|
||||
let total_virtual_tokens: u128 =
|
||||
(self.virtual_token_reserves as u128) - (self.real_token_reserves as u128);
|
||||
|
||||
if total_virtual_tokens == 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
((self.token_total_supply as u128) * total_virtual_value / total_virtual_tokens) as u64
|
||||
}
|
||||
|
||||
/// Calculates the price to buy out all remaining tokens
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `amount` - Amount of tokens to buy
|
||||
/// * `fee_basis_points` - Fee in basis points (1/100th of a percent)
|
||||
pub fn get_buy_out_price(&self, amount: u64, fee_basis_points: u64) -> u64 {
|
||||
// Get the effective amount of sol tokens
|
||||
let sol_tokens: u128 = if amount < self.real_sol_reserves {
|
||||
self.real_sol_reserves as u128
|
||||
} else {
|
||||
amount as u128
|
||||
};
|
||||
|
||||
// Calculate total sell value
|
||||
let total_sell_value: u128 = (sol_tokens * (self.virtual_sol_reserves as u128))
|
||||
/ ((self.virtual_token_reserves as u128) - sol_tokens)
|
||||
+ 1;
|
||||
|
||||
// Calculate fee
|
||||
let fee: u128 = (total_sell_value * (fee_basis_points as u128)) / 10000;
|
||||
|
||||
// Return total including fee, converting back to u64
|
||||
(total_sell_value + fee) as u64
|
||||
}
|
||||
|
||||
pub fn get_token_price(&self) -> f64 {
|
||||
let v_sol = self.virtual_sol_reserves as f64 / 100_000_000.0;
|
||||
let v_tokens = self.virtual_token_reserves as f64 / 100_000.0;
|
||||
let token_price = v_sol / v_tokens;
|
||||
token_price
|
||||
}
|
||||
}
|
||||
Executable
+120
@@ -0,0 +1,120 @@
|
||||
//! Global account for the Pump.fun Solana Program
|
||||
//!
|
||||
//! This module contains the definition for the global configuration account.
|
||||
//!
|
||||
//! # Global Account
|
||||
//!
|
||||
//! The global account is used to store the global configuration for the Pump.fun program.
|
||||
//!
|
||||
//! # Fields
|
||||
//!
|
||||
//! - `discriminator`: Unique identifier for the global account
|
||||
//! - `initialized`: Whether the global account has been initialized
|
||||
//! - `authority`: Authority pubkey that can modify settings
|
||||
//! - `fee_recipient`: Account that receives fees
|
||||
//! - `initial_virtual_token_reserves`: Initial virtual token reserves for price calculations
|
||||
//! - `initial_virtual_sol_reserves`: Initial virtual SOL reserves for price calculations
|
||||
//! - `initial_real_token_reserves`: Initial actual token reserves available for trading
|
||||
//! - `token_total_supply`: Total supply of tokens
|
||||
//! - `fee_basis_points`: Fee in basis points (1/100th of a percent)
|
||||
//! - `withdraw_authority`: Authority that can withdraw fees
|
||||
//! - `enable_migrate`: Whether migration is enabled
|
||||
//! - `pool_migration_fee`: Fee for pool migration
|
||||
//! - `creator_fee`: Fee for creators
|
||||
//! - `fee_recipients`: Array of fee recipient accounts
|
||||
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use crate::constants::pumpfun::global_constants::*;
|
||||
|
||||
/// Represents the global configuration account for token pricing and fees
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct GlobalAccount {
|
||||
/// Unique identifier for the global account
|
||||
pub discriminator: u64,
|
||||
/// Pubkey of the global account
|
||||
pub account: Pubkey,
|
||||
/// Whether the global account has been initialized
|
||||
pub initialized: bool,
|
||||
/// Authority that can modify global settings
|
||||
pub authority: Pubkey,
|
||||
/// Account that receives fees
|
||||
pub fee_recipient: Pubkey,
|
||||
/// Initial virtual token reserves for price calculations
|
||||
pub initial_virtual_token_reserves: u64,
|
||||
/// Initial virtual SOL reserves for price calculations
|
||||
pub initial_virtual_sol_reserves: u64,
|
||||
/// Initial actual token reserves available for trading
|
||||
pub initial_real_token_reserves: u64,
|
||||
/// Total supply of tokens
|
||||
pub token_total_supply: u64,
|
||||
/// Fee in basis points (1/100th of a percent)
|
||||
pub fee_basis_points: u64,
|
||||
/// Authority that can withdraw fees
|
||||
pub withdraw_authority: Pubkey,
|
||||
/// Whether migration is enabled
|
||||
pub enable_migrate: bool,
|
||||
/// Fee for pool migration
|
||||
pub pool_migration_fee: u64,
|
||||
/// Fee for creators
|
||||
pub creator_fee: u64,
|
||||
/// Array of fee recipient accounts
|
||||
pub fee_recipients: [Pubkey; 7],
|
||||
}
|
||||
|
||||
impl GlobalAccount {
|
||||
/// Creates a new global account instance
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
discriminator: 0,
|
||||
account: GLOBAL_ACCOUNT,
|
||||
initialized: true,
|
||||
authority: AUTHORITY,
|
||||
fee_recipient: FEE_RECIPIENT,
|
||||
initial_virtual_token_reserves: INITIAL_VIRTUAL_TOKEN_RESERVES,
|
||||
initial_virtual_sol_reserves: INITIAL_VIRTUAL_SOL_RESERVES,
|
||||
initial_real_token_reserves: INITIAL_REAL_TOKEN_RESERVES,
|
||||
token_total_supply: TOKEN_TOTAL_SUPPLY,
|
||||
fee_basis_points: FEE_BASIS_POINTS,
|
||||
withdraw_authority: WITHDRAW_AUTHORITY,
|
||||
enable_migrate: ENABLE_MIGRATE,
|
||||
pool_migration_fee: POOL_MIGRATION_FEE,
|
||||
creator_fee: CREATOR_FEE,
|
||||
fee_recipients: [
|
||||
PUMPFUN_AMM_FEE_1,
|
||||
PUMPFUN_AMM_FEE_2,
|
||||
PUMPFUN_AMM_FEE_3,
|
||||
PUMPFUN_AMM_FEE_4,
|
||||
PUMPFUN_AMM_FEE_5,
|
||||
PUMPFUN_AMM_FEE_6,
|
||||
PUMPFUN_AMM_FEE_7,
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates the initial amount of tokens received for a given SOL amount
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `amount` - Amount of SOL to spend
|
||||
///
|
||||
/// # Returns
|
||||
/// Amount of tokens that would be received
|
||||
pub fn get_initial_buy_price(&self, amount: u64) -> u64 {
|
||||
if amount == 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let n: u128 = (self.initial_virtual_sol_reserves as u128)
|
||||
* (self.initial_virtual_token_reserves as u128);
|
||||
let i: u128 = (self.initial_virtual_sol_reserves as u128) + (amount as u128);
|
||||
let r: u128 = n / i + 1;
|
||||
let s: u128 = (self.initial_virtual_token_reserves as u128) - r;
|
||||
|
||||
if s < (self.initial_real_token_reserves as u128) {
|
||||
s as u64
|
||||
} else {
|
||||
self.initial_real_token_reserves
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,5 +4,7 @@ pub mod tip_cache;
|
||||
pub mod types;
|
||||
pub mod address_lookup_cache;
|
||||
pub mod subscription_handle;
|
||||
pub mod bonding_curve;
|
||||
pub mod global;
|
||||
|
||||
pub use types::*;
|
||||
|
||||
Reference in New Issue
Block a user