File size: 9,203 Bytes
19fc8d0 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
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()
|