Revert "Reapply "feat: implement auto-pump mechanism to prevent pool drainage""
This reverts commit f240b96847.
This commit is contained in:
parent
be7cdbf0f8
commit
a80a1a4e5c
8 changed files with 29 additions and 1727 deletions
|
|
@ -1,4 +0,0 @@
|
||||||
ALTER TABLE "coin" ADD COLUMN "pump_fee_rate" numeric(10, 8) DEFAULT '0.00500000' NOT NULL;--> statement-breakpoint
|
|
||||||
ALTER TABLE "coin" ADD COLUMN "burn_rate" numeric(10, 8) DEFAULT '0.00100000' NOT NULL;--> statement-breakpoint
|
|
||||||
ALTER TABLE "transaction" ADD COLUMN "pump_fee_applied" numeric(30, 8) DEFAULT '0.00000000';--> statement-breakpoint
|
|
||||||
ALTER TABLE "transaction" ADD COLUMN "tokens_burned" numeric(30, 8) DEFAULT '0.00000000';
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -22,13 +22,6 @@
|
||||||
"when": 1748700252762,
|
"when": 1748700252762,
|
||||||
"tag": "0002_lush_guardian",
|
"tag": "0002_lush_guardian",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
|
||||||
{
|
|
||||||
"idx": 3,
|
|
||||||
"version": "7",
|
|
||||||
"when": 1748710560443,
|
|
||||||
"tag": "0003_adorable_leper_queen",
|
|
||||||
"breakpoints": true
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -34,7 +34,6 @@
|
||||||
: userHolding
|
: userHolding
|
||||||
);
|
);
|
||||||
let estimatedResult = $derived(calculateEstimate(numericAmount, type, currentPrice));
|
let estimatedResult = $derived(calculateEstimate(numericAmount, type, currentPrice));
|
||||||
let estimatedAutoPump = $derived(calculateAutoPumpEffects(numericAmount, type, coin));
|
|
||||||
let hasValidAmount = $derived(numericAmount > 0);
|
let hasValidAmount = $derived(numericAmount > 0);
|
||||||
let userBalance = $derived($PORTFOLIO_DATA ? $PORTFOLIO_DATA.baseCurrencyBalance : 0);
|
let userBalance = $derived($PORTFOLIO_DATA ? $PORTFOLIO_DATA.baseCurrencyBalance : 0);
|
||||||
let hasEnoughFunds = $derived(
|
let hasEnoughFunds = $derived(
|
||||||
|
|
@ -65,25 +64,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateAutoPumpEffects(amount: number, tradeType: 'BUY' | 'SELL', coinData: any) {
|
|
||||||
if (!amount) return { fee: 0, burn: 0 };
|
|
||||||
|
|
||||||
const pumpFeeRate = Number(coinData.pumpFeeRate || 0.005);
|
|
||||||
const burnRate = Number(coinData.burnRate || 0.001);
|
|
||||||
|
|
||||||
if (tradeType === 'BUY') {
|
|
||||||
const fee = amount * pumpFeeRate;
|
|
||||||
const estimatedTokens = calculateEstimate(amount, tradeType, currentPrice).result;
|
|
||||||
const burn = estimatedTokens * burnRate;
|
|
||||||
return { fee, burn };
|
|
||||||
} else {
|
|
||||||
const estimatedValue = calculateEstimate(amount, tradeType, currentPrice).result;
|
|
||||||
const fee = estimatedValue * pumpFeeRate;
|
|
||||||
const burn = amount * burnRate;
|
|
||||||
return { fee, burn };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleClose() {
|
function handleClose() {
|
||||||
open = false;
|
open = false;
|
||||||
amount = '';
|
amount = '';
|
||||||
|
|
@ -203,20 +183,6 @@
|
||||||
: `~$${estimatedResult.result.toFixed(6)}`}
|
: `~$${estimatedResult.result.toFixed(6)}`}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{#if estimatedAutoPump.fee > 0 || estimatedAutoPump.burn > 0}
|
|
||||||
<div class="border-muted mt-2 border-t pt-2">
|
|
||||||
<div class="text-muted-foreground text-xs">
|
|
||||||
<div class="mb-1 flex items-center justify-between">
|
|
||||||
<span>🔥 Auto-pump fee (0.5%):</span>
|
|
||||||
<span>+${estimatedAutoPump.fee.toFixed(6)} to pool</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<span>🔥 Token burn (0.1%):</span>
|
|
||||||
<span>-{estimatedAutoPump.burn.toFixed(6)} {coin.symbol}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<p class="text-muted-foreground mt-1 text-xs">
|
<p class="text-muted-foreground mt-1 text-xs">
|
||||||
AMM estimation - includes slippage from pool impact
|
AMM estimation - includes slippage from pool impact
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -83,8 +83,6 @@ export const coin = pgTable("coin", {
|
||||||
change24h: decimal("change_24h", { precision: 30, scale: 4 }).default("0.0000"), // Percentage
|
change24h: decimal("change_24h", { precision: 30, scale: 4 }).default("0.0000"), // Percentage
|
||||||
poolCoinAmount: decimal("pool_coin_amount", { precision: 30, scale: 8 }).notNull().default("0.00000000"),
|
poolCoinAmount: decimal("pool_coin_amount", { precision: 30, scale: 8 }).notNull().default("0.00000000"),
|
||||||
poolBaseCurrencyAmount: decimal("pool_base_currency_amount", { precision: 30, scale: 8, }).notNull().default("0.00000000"),
|
poolBaseCurrencyAmount: decimal("pool_base_currency_amount", { precision: 30, scale: 8, }).notNull().default("0.00000000"),
|
||||||
pumpFeeRate: decimal("pump_fee_rate", { precision: 10, scale: 8 }).notNull().default("0.00500000"), // 0.5%
|
|
||||||
burnRate: decimal("burn_rate", { precision: 10, scale: 8 }).notNull().default("0.00100000"), // 0.1%
|
|
||||||
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
||||||
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
||||||
isListed: boolean("is_listed").default(true).notNull(),
|
isListed: boolean("is_listed").default(true).notNull(),
|
||||||
|
|
@ -111,8 +109,6 @@ export const transaction = pgTable("transaction", {
|
||||||
quantity: decimal("quantity", { precision: 30, scale: 8 }).notNull(),
|
quantity: decimal("quantity", { precision: 30, scale: 8 }).notNull(),
|
||||||
pricePerCoin: decimal("price_per_coin", { precision: 20, scale: 8 }).notNull(),
|
pricePerCoin: decimal("price_per_coin", { precision: 20, scale: 8 }).notNull(),
|
||||||
totalBaseCurrencyAmount: decimal("total_base_currency_amount", { precision: 30, scale: 8 }).notNull(),
|
totalBaseCurrencyAmount: decimal("total_base_currency_amount", { precision: 30, scale: 8 }).notNull(),
|
||||||
pumpFeeApplied: decimal("pump_fee_applied", { precision: 30, scale: 8 }).default("0.00000000"),
|
|
||||||
tokensBurned: decimal("tokens_burned", { precision: 30, scale: 8 }).default("0.00000000"),
|
|
||||||
timestamp: timestamp("timestamp", { withTimezone: true }).notNull().defaultNow(),
|
timestamp: timestamp("timestamp", { withTimezone: true }).notNull().defaultNow(),
|
||||||
recipientUserId: integer('recipient_user_id').references(() => user.id, { onDelete: 'set null' }),
|
recipientUserId: integer('recipient_user_id').references(() => user.id, { onDelete: 'set null' }),
|
||||||
senderUserId: integer('sender_user_id').references(() => user.id, { onDelete: 'set null' }),
|
senderUserId: integer('sender_user_id').references(() => user.id, { onDelete: 'set null' }),
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,6 @@ export interface CoinData {
|
||||||
change24h: number;
|
change24h: number;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
creatorName: string | null;
|
creatorName: string | null;
|
||||||
pumpFeeRate?: number;
|
|
||||||
burnRate?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MarketFilters {
|
export interface MarketFilters {
|
||||||
|
|
|
||||||
|
|
@ -130,8 +130,6 @@ export async function GET({ params, url }) {
|
||||||
isListed: coin.isListed,
|
isListed: coin.isListed,
|
||||||
createdAt: coin.createdAt,
|
createdAt: coin.createdAt,
|
||||||
creatorId: coin.creatorId,
|
creatorId: coin.creatorId,
|
||||||
pumpFeeRate: coin.pumpFeeRate,
|
|
||||||
burnRate: coin.burnRate,
|
|
||||||
creatorName: user.name,
|
creatorName: user.name,
|
||||||
creatorUsername: user.username,
|
creatorUsername: user.username,
|
||||||
creatorBio: user.bio,
|
creatorBio: user.bio,
|
||||||
|
|
@ -186,9 +184,7 @@ export async function GET({ params, url }) {
|
||||||
poolCoinAmount: Number(coinData.poolCoinAmount),
|
poolCoinAmount: Number(coinData.poolCoinAmount),
|
||||||
poolBaseCurrencyAmount: Number(coinData.poolBaseCurrencyAmount),
|
poolBaseCurrencyAmount: Number(coinData.poolBaseCurrencyAmount),
|
||||||
circulatingSupply: Number(coinData.circulatingSupply),
|
circulatingSupply: Number(coinData.circulatingSupply),
|
||||||
initialSupply: Number(coinData.initialSupply),
|
initialSupply: Number(coinData.initialSupply)
|
||||||
pumpFeeRate: Number(coinData.pumpFeeRate),
|
|
||||||
burnRate: Number(coinData.burnRate)
|
|
||||||
},
|
},
|
||||||
candlestickData,
|
candlestickData,
|
||||||
volumeData,
|
volumeData,
|
||||||
|
|
|
||||||
|
|
@ -42,34 +42,6 @@ async function calculate24hMetrics(coinId: number, currentPrice: number) {
|
||||||
return { change24h: Number(change24h.toFixed(4)), volume24h: Number(volume24h.toFixed(4)) };
|
return { change24h: Number(change24h.toFixed(4)), volume24h: Number(volume24h.toFixed(4)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateAutoPumpEffects(
|
|
||||||
coinData: any,
|
|
||||||
transactionValue: number,
|
|
||||||
tokensTraded: number
|
|
||||||
) {
|
|
||||||
const pumpFeeRate = Number(coinData.pumpFeeRate);
|
|
||||||
const burnRate = Number(coinData.burnRate);
|
|
||||||
|
|
||||||
const pumpFee = transactionValue * pumpFeeRate;
|
|
||||||
const tokensBurned = tokensTraded * burnRate;
|
|
||||||
|
|
||||||
// Ensure we don't burn more tokens than available in pool
|
|
||||||
const maxBurnableTokens = Number(coinData.poolCoinAmount) * 0.99; // Keep 1% minimum
|
|
||||||
const actualTokensBurned = Math.min(tokensBurned, maxBurnableTokens);
|
|
||||||
|
|
||||||
const newPoolBase = Number(coinData.poolBaseCurrencyAmount) + pumpFee;
|
|
||||||
const newPoolCoin = Number(coinData.poolCoinAmount) - actualTokensBurned;
|
|
||||||
const newCirculatingSupply = Number(coinData.circulatingSupply) - actualTokensBurned;
|
|
||||||
|
|
||||||
return {
|
|
||||||
pumpFee,
|
|
||||||
tokensBurned: actualTokensBurned,
|
|
||||||
newPoolBase,
|
|
||||||
newPoolCoin,
|
|
||||||
newCirculatingSupply
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function POST({ params, request }) {
|
export async function POST({ params, request }) {
|
||||||
const session = await auth.api.getSession({
|
const session = await auth.api.getSession({
|
||||||
headers: request.headers
|
headers: request.headers
|
||||||
|
|
@ -155,13 +127,6 @@ export async function POST({ params, request }) {
|
||||||
throw error(400, 'Trade amount too small - would result in zero tokens');
|
throw error(400, 'Trade amount too small - would result in zero tokens');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply auto-pump effects
|
|
||||||
const autoPumpEffects = calculateAutoPumpEffects(coinData, amount, coinsBought);
|
|
||||||
|
|
||||||
const finalPoolBase = autoPumpEffects.newPoolBase;
|
|
||||||
const finalPoolCoin = autoPumpEffects.newPoolCoin;
|
|
||||||
const finalPrice = finalPoolBase / finalPoolCoin;
|
|
||||||
|
|
||||||
await tx.update(user)
|
await tx.update(user)
|
||||||
.set({
|
.set({
|
||||||
baseCurrencyBalance: (userBalance - totalCost).toString(),
|
baseCurrencyBalance: (userBalance - totalCost).toString(),
|
||||||
|
|
@ -203,25 +168,22 @@ export async function POST({ params, request }) {
|
||||||
type: 'BUY',
|
type: 'BUY',
|
||||||
quantity: coinsBought.toString(),
|
quantity: coinsBought.toString(),
|
||||||
pricePerCoin: (totalCost / coinsBought).toString(),
|
pricePerCoin: (totalCost / coinsBought).toString(),
|
||||||
totalBaseCurrencyAmount: totalCost.toString(),
|
totalBaseCurrencyAmount: totalCost.toString()
|
||||||
pumpFeeApplied: autoPumpEffects.pumpFee.toString(),
|
|
||||||
tokensBurned: autoPumpEffects.tokensBurned.toString()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await tx.insert(priceHistory).values({
|
await tx.insert(priceHistory).values({
|
||||||
coinId: coinData.id,
|
coinId: coinData.id,
|
||||||
price: finalPrice.toString()
|
price: newPrice.toString()
|
||||||
});
|
});
|
||||||
|
|
||||||
const metrics = await calculate24hMetrics(coinData.id, finalPrice);
|
const metrics = await calculate24hMetrics(coinData.id, newPrice);
|
||||||
|
|
||||||
await tx.update(coin)
|
await tx.update(coin)
|
||||||
.set({
|
.set({
|
||||||
currentPrice: finalPrice.toString(),
|
currentPrice: newPrice.toString(),
|
||||||
marketCap: (autoPumpEffects.newCirculatingSupply * finalPrice).toString(),
|
marketCap: (Number(coinData.circulatingSupply) * newPrice).toString(),
|
||||||
poolCoinAmount: finalPoolCoin.toString(),
|
poolCoinAmount: newPoolCoin.toString(),
|
||||||
poolBaseCurrencyAmount: finalPoolBase.toString(),
|
poolBaseCurrencyAmount: newPoolBaseCurrency.toString(),
|
||||||
circulatingSupply: autoPumpEffects.newCirculatingSupply.toString(),
|
|
||||||
change24h: metrics.change24h.toString(),
|
change24h: metrics.change24h.toString(),
|
||||||
volume24h: metrics.volume24h.toString(),
|
volume24h: metrics.volume24h.toString(),
|
||||||
updatedAt: new Date()
|
updatedAt: new Date()
|
||||||
|
|
@ -229,12 +191,12 @@ export async function POST({ params, request }) {
|
||||||
.where(eq(coin.id, coinData.id));
|
.where(eq(coin.id, coinData.id));
|
||||||
|
|
||||||
const priceUpdateData = {
|
const priceUpdateData = {
|
||||||
currentPrice: finalPrice,
|
currentPrice: newPrice,
|
||||||
marketCap: autoPumpEffects.newCirculatingSupply * finalPrice,
|
marketCap: Number(coinData.circulatingSupply) * newPrice,
|
||||||
change24h: metrics.change24h,
|
change24h: metrics.change24h,
|
||||||
volume24h: metrics.volume24h,
|
volume24h: metrics.volume24h,
|
||||||
poolCoinAmount: finalPoolCoin,
|
poolCoinAmount: newPoolCoin,
|
||||||
poolBaseCurrencyAmount: finalPoolBase
|
poolBaseCurrencyAmount: newPoolBaseCurrency
|
||||||
};
|
};
|
||||||
|
|
||||||
const tradeData = {
|
const tradeData = {
|
||||||
|
|
@ -270,13 +232,9 @@ export async function POST({ params, request }) {
|
||||||
type: 'BUY',
|
type: 'BUY',
|
||||||
coinsBought,
|
coinsBought,
|
||||||
totalCost,
|
totalCost,
|
||||||
newPrice: finalPrice,
|
newPrice,
|
||||||
priceImpact: ((finalPrice - currentPrice) / currentPrice) * 100,
|
priceImpact,
|
||||||
newBalance: userBalance - totalCost,
|
newBalance: userBalance - totalCost
|
||||||
autoPumpEffects: {
|
|
||||||
feeApplied: autoPumpEffects.pumpFee,
|
|
||||||
tokensBurned: autoPumpEffects.tokensBurned,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -317,13 +275,6 @@ export async function POST({ params, request }) {
|
||||||
throw error(400, 'Trade amount results in zero base currency received');
|
throw error(400, 'Trade amount results in zero base currency received');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply auto-pump effects
|
|
||||||
const autoPumpEffects = calculateAutoPumpEffects(coinData, totalCost, amount);
|
|
||||||
|
|
||||||
const finalPoolBase = autoPumpEffects.newPoolBase;
|
|
||||||
const finalPoolCoin = autoPumpEffects.newPoolCoin;
|
|
||||||
const finalPrice = finalPoolBase / finalPoolCoin;
|
|
||||||
|
|
||||||
await tx.update(user)
|
await tx.update(user)
|
||||||
.set({
|
.set({
|
||||||
baseCurrencyBalance: (userBalance + totalCost).toString(),
|
baseCurrencyBalance: (userBalance + totalCost).toString(),
|
||||||
|
|
@ -356,25 +307,22 @@ export async function POST({ params, request }) {
|
||||||
type: 'SELL',
|
type: 'SELL',
|
||||||
quantity: amount.toString(),
|
quantity: amount.toString(),
|
||||||
pricePerCoin: (totalCost / amount).toString(),
|
pricePerCoin: (totalCost / amount).toString(),
|
||||||
totalBaseCurrencyAmount: totalCost.toString(),
|
totalBaseCurrencyAmount: totalCost.toString()
|
||||||
pumpFeeApplied: autoPumpEffects.pumpFee.toString(),
|
|
||||||
tokensBurned: autoPumpEffects.tokensBurned.toString()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await tx.insert(priceHistory).values({
|
await tx.insert(priceHistory).values({
|
||||||
coinId: coinData.id,
|
coinId: coinData.id,
|
||||||
price: finalPrice.toString()
|
price: newPrice.toString()
|
||||||
});
|
});
|
||||||
|
|
||||||
const metrics = await calculate24hMetrics(coinData.id, finalPrice);
|
const metrics = await calculate24hMetrics(coinData.id, newPrice);
|
||||||
|
|
||||||
await tx.update(coin)
|
await tx.update(coin)
|
||||||
.set({
|
.set({
|
||||||
currentPrice: finalPrice.toString(),
|
currentPrice: newPrice.toString(),
|
||||||
marketCap: (autoPumpEffects.newCirculatingSupply * finalPrice).toString(),
|
marketCap: (Number(coinData.circulatingSupply) * newPrice).toString(),
|
||||||
poolCoinAmount: finalPoolCoin.toString(),
|
poolCoinAmount: newPoolCoin.toString(),
|
||||||
poolBaseCurrencyAmount: finalPoolBase.toString(),
|
poolBaseCurrencyAmount: newPoolBaseCurrency.toString(),
|
||||||
circulatingSupply: autoPumpEffects.newCirculatingSupply.toString(),
|
|
||||||
change24h: metrics.change24h.toString(),
|
change24h: metrics.change24h.toString(),
|
||||||
volume24h: metrics.volume24h.toString(),
|
volume24h: metrics.volume24h.toString(),
|
||||||
updatedAt: new Date()
|
updatedAt: new Date()
|
||||||
|
|
@ -382,12 +330,12 @@ export async function POST({ params, request }) {
|
||||||
.where(eq(coin.id, coinData.id));
|
.where(eq(coin.id, coinData.id));
|
||||||
|
|
||||||
const priceUpdateData = {
|
const priceUpdateData = {
|
||||||
currentPrice: finalPrice,
|
currentPrice: newPrice,
|
||||||
marketCap: autoPumpEffects.newCirculatingSupply * finalPrice,
|
marketCap: Number(coinData.circulatingSupply) * newPrice,
|
||||||
change24h: metrics.change24h,
|
change24h: metrics.change24h,
|
||||||
volume24h: metrics.volume24h,
|
volume24h: metrics.volume24h,
|
||||||
poolCoinAmount: finalPoolCoin,
|
poolCoinAmount: newPoolCoin,
|
||||||
poolBaseCurrencyAmount: finalPoolBase
|
poolBaseCurrencyAmount: newPoolBaseCurrency
|
||||||
};
|
};
|
||||||
|
|
||||||
const tradeData = {
|
const tradeData = {
|
||||||
|
|
@ -423,13 +371,9 @@ export async function POST({ params, request }) {
|
||||||
type: 'SELL',
|
type: 'SELL',
|
||||||
coinsSold: amount,
|
coinsSold: amount,
|
||||||
totalReceived: totalCost,
|
totalReceived: totalCost,
|
||||||
newPrice: finalPrice,
|
newPrice,
|
||||||
priceImpact: ((finalPrice - currentPrice) / currentPrice) * 100,
|
priceImpact,
|
||||||
newBalance: userBalance + totalCost,
|
newBalance: userBalance + totalCost
|
||||||
autoPumpEffects: {
|
|
||||||
feeApplied: autoPumpEffects.pumpFee,
|
|
||||||
tokensBurned: autoPumpEffects.tokensBurned
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Reference in a new issue