dbc / app.py
0xaryan's picture
init
19fc8d0
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()