import gradio as gr import numpy as np import matplotlib.pyplot as plt from decimal import Decimal def simulate_full_bonding_curve_with_fees( initial_market_cap_sol, migration_market_cap_sol, total_token_supply, token_decimals, quote_decimals, migration_fee_percent, creator_migration_fee_percent, partner_lp_percentage, creator_lp_percentage, partner_locked_lp_percentage, creator_locked_lp_percentage, trading_fee_bps, total_trading_volume_sol ): total_trading_volume_sol = float(total_trading_volume_sol) percentage_supply = Decimal(100) migration_quote_amount = Decimal(initial_market_cap_sol) * percentage_supply / Decimal(100) migration_quote_threshold = migration_quote_amount * Decimal(100) / (Decimal(100) - Decimal(migration_fee_percent)) circulating_supply = Decimal(total_token_supply) * percentage_supply / Decimal(100) start_price = Decimal(initial_market_cap_sol) / circulating_supply end_price = Decimal(migration_market_cap_sol) / circulating_supply # Calculate k for the price formula P(x) = k / (C - x)^2 # S(x) = integral P(x)dx from 0 to x = k/(C-x) - k/C # initial_market_cap_sol is the SOL value for 0 tokens sold (conceptually) # For the purpose of plotting the amount of SOL raised against tokens sold: # Let C = float(circulating_supply) # The price at a given number of tokens sold 's' is P(s) = k / (C - s)^2 # The SOL raised to sell 's' tokens is Integral(P(x)dx) from 0 to s which is k/(C-s) - k/C # We use migration_quote_amount as the SOL raised when 0 tokens are sold for the *start* of the curve for simplicity in k calc. # This interpretation aligns k with the initial SOL amount rather than price directly. C_float = float(circulating_supply) if C_float == 0: # Avoid division by zero if circulating supply is zero x = np.array([0]) prices = np.array([0]) x_end_plot = 0 else: # k is derived from the initial state: initial_market_cap_sol is the SOL value for 0 tokens sold (conceptually) # P(x) = k / (C-x)^2. SOL_raised(x) = k/(C-x) - k/C. # if initial_market_cap_sol is S(0), then k = initial_market_cap_sol * C_float. This is wrong, initial_market_cap_sol is not S(0). # initial_market_cap_sol is effectively the amount of SOL in the pool at the start for pricing calculations. # Let's use the definition that migration_quote_amount (SOL before fees) is the target SOL to be in the curve before it migrates. # The curve starts with some implicit SOL amount that gives start_price. # Price(x) = k / (C-x)^2. So, Price(0) = k / C^2 = start_price. # k = start_price * C^2 k = float(start_price) * (C_float**2) if k == 0 or (float(migration_quote_threshold) + k / C_float) == 0: # Handle division by zero or k=0 x_end_plot = C_float # Sell all tokens if k is 0 or threshold makes denominator 0 else: # Calculate x_end_plot: number of tokens sold to reach migration_quote_threshold SOL # SOL_raised(x_end_plot) = migration_quote_threshold # migration_quote_threshold = k/(C_float - x_end_plot) - k/C_float # k/(C_float - x_end_plot) = migration_quote_threshold + k/C_float # C_float - x_end_plot = k / (migration_quote_threshold + k/C_float) x_end_plot = C_float - (k / (float(migration_quote_threshold) + k / C_float)) # Ensure x_end_plot is not negative or greater than C_float x_end_plot = max(0, min(x_end_plot, C_float * 0.9999)) # Plot up to 99.99% to avoid infinity if x_end_plot <= 1e-9: # If effectively no tokens are sold to reach threshold (e.g. threshold is 0) x_end_plot = C_float * 0.01 # Plot a small portion to show something if x_end_plot <= 1e-9: # If C_float is also tiny x_end_plot = 1 # Default to 1 token if supply is extremely small num_points = 100 if x_end_plot == 0: x = np.array([0]) # Handle case with single point prices = np.array([float(start_price)]) else: x = np.linspace(0.0, x_end_plot, num_points) prices = k / (C_float - x + 1e-9)**2 # Add small epsilon to avoid division by zero if x reaches C_float prices = [float(p) for p in prices] total_fee = float(migration_quote_threshold) * float(migration_fee_percent) / 100 creator_migration_fee = total_fee * (creator_migration_fee_percent / 100) partner_migration_fee = total_fee - creator_migration_fee total_lp_tokens = float(migration_quote_threshold) creator_lp_tokens = total_lp_tokens * (creator_lp_percentage / 100) partner_lp_tokens = total_lp_tokens * (partner_lp_percentage / 100) creator_locked_lp = creator_lp_tokens * (creator_locked_lp_percentage / 100) partner_locked_lp = partner_lp_tokens * (partner_locked_lp_percentage / 100) trading_fee_rate = trading_fee_bps / 10000 total_trading_fee = total_trading_volume_sol * trading_fee_rate creator_trading_fee = total_trading_fee * (creator_lp_percentage / 100) partner_trading_fee = total_trading_fee * (partner_lp_percentage / 100) fig, ax = plt.subplots() ax.plot(x, prices) ax.set_xlabel("Tokens Sold") ax.set_ylabel("Price (in SOL)") ax.set_title("Bonding Curve Simulation (in SOL)") note = """ Bonding Curve Unit: SOL Parameter Explanations: - Initial Market Cap: Total valuation (in SOL) at curve start. - Migration Market Cap: Valuation (in SOL) when curve ends and migrates to AMM. - Migration Quote Amount: Amount of SOL raised before fees. - Migration Threshold: Total SOL needed to trigger migration (includes fees). - LP Tokens: Represents user's share in the post-migration AMM liquidity pool. Approximated here as equal to the migration threshold in SOL. - Trading Fee BPS: The fee rate applied to all swaps post-migration. BPS = Basis Points (e.g., 100 BPS = 1%). - Creator/Partner Trading Fee: Earnings from swap volume based on LP share. - All SOL values are approximated assuming quote token = SOL. """ return ( fig, f"Initial Price: {start_price:.8f} SOL", f"Migration Price: {end_price:.8f} SOL", f"Migration Quote Amount: {migration_quote_amount:.2f} SOL", f"Migration Threshold (after fee): {migration_quote_threshold:.2f} SOL", f"Bonding Curve Unit: SOL", f"Creator Migration Fee: {creator_migration_fee:.2f} SOL", f"Partner Migration Fee: {partner_migration_fee:.2f} SOL", f"Total LP Tokens: {total_lp_tokens:.2f}", f"Creator LP: {creator_lp_tokens:.2f} (Locked: {creator_locked_lp:.2f})", f"Partner LP: {partner_lp_tokens:.2f} (Locked: {partner_locked_lp:.2f})", f"Creator Trading Fee: {creator_trading_fee:.2f} SOL", f"Partner Trading Fee: {partner_trading_fee:.2f} SOL", note.strip() ) gr.Interface( fn=simulate_full_bonding_curve_with_fees, inputs=[ gr.Textbox(label="Initial Market Cap (SOL)", value="1000"), gr.Textbox(label="Migration Market Cap (SOL)", value="10000"), gr.Textbox(label="Total Token Supply", value="1000000"), gr.Textbox(label="Token Decimals", value="6"), gr.Textbox(label="Quote Token Decimals", value="9"), gr.Slider(label="Migration Fee Percent (%)", minimum=0, maximum=50, step=0.5, value=10), gr.Slider(label="Creator Fee Share of Migration Fee (%)", minimum=0, maximum=100, step=1, value=50), gr.Slider(label="Partner LP %", minimum=0, maximum=100, step=1, value=50), gr.Slider(label="Creator LP %", minimum=0, maximum=100, step=1, value=50), gr.Slider(label="Partner Locked LP %", minimum=0, maximum=100, step=1, value=100), gr.Slider(label="Creator Locked LP %", minimum=0, maximum=100, step=1, value=100), gr.Slider(label="Post-Migration Trading Fee (bps)", minimum=0, maximum=1000, step=5, value=30), gr.Textbox(label="Total Trading Volume (SOL)", value="1000"), ], outputs=[ gr.Plot(label="Bonding Curve"), gr.Textbox(label="Initial Price", lines=1, interactive=False), gr.Textbox(label="Migration Price", lines=1, interactive=False), gr.Textbox(label="Migration Quote Amount", lines=1, interactive=False), gr.Textbox(label="Migration Threshold", lines=1, interactive=False), gr.Textbox(label="Bonding Curve Unit", lines=1, interactive=False), gr.Textbox(label="Creator Migration Fee", lines=1, interactive=False), gr.Textbox(label="Partner Migration Fee", lines=1, interactive=False), gr.Textbox(label="Total LP Tokens", lines=1, interactive=False), gr.Textbox(label="Creator LP", lines=1, interactive=False), gr.Textbox(label="Partner LP", lines=1, interactive=False), gr.Textbox(label="Creator Trading Fee", lines=1, interactive=False), gr.Textbox(label="Partner Trading Fee", lines=1, interactive=False), gr.Textbox(label="Explanation", lines=12, interactive=False), ], title="Dynamic Bonding Curve Simulator (with Full Fee + LP Breakdown)" ).launch()