feat: implement auto-pump mechanism to prevent pool drainage

This commit is contained in:
Face 2025-05-31 20:04:25 +03:00
parent d9f2836fb9
commit b8de80d8a9
8 changed files with 1727 additions and 29 deletions

View file

@ -130,6 +130,8 @@ export async function GET({ params, url }) {
isListed: coin.isListed,
createdAt: coin.createdAt,
creatorId: coin.creatorId,
pumpFeeRate: coin.pumpFeeRate,
burnRate: coin.burnRate,
creatorName: user.name,
creatorUsername: user.username,
creatorBio: user.bio,
@ -184,7 +186,9 @@ export async function GET({ params, url }) {
poolCoinAmount: Number(coinData.poolCoinAmount),
poolBaseCurrencyAmount: Number(coinData.poolBaseCurrencyAmount),
circulatingSupply: Number(coinData.circulatingSupply),
initialSupply: Number(coinData.initialSupply)
initialSupply: Number(coinData.initialSupply),
pumpFeeRate: Number(coinData.pumpFeeRate),
burnRate: Number(coinData.burnRate)
},
candlestickData,
volumeData,

View file

@ -42,6 +42,34 @@ async function calculate24hMetrics(coinId: number, currentPrice: number) {
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 }) {
const session = await auth.api.getSession({
headers: request.headers
@ -127,6 +155,13 @@ export async function POST({ params, request }) {
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)
.set({
baseCurrencyBalance: (userBalance - totalCost).toString(),
@ -168,22 +203,25 @@ export async function POST({ params, request }) {
type: 'BUY',
quantity: 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({
coinId: coinData.id,
price: newPrice.toString()
price: finalPrice.toString()
});
const metrics = await calculate24hMetrics(coinData.id, newPrice);
const metrics = await calculate24hMetrics(coinData.id, finalPrice);
await tx.update(coin)
.set({
currentPrice: newPrice.toString(),
marketCap: (Number(coinData.circulatingSupply) * newPrice).toString(),
poolCoinAmount: newPoolCoin.toString(),
poolBaseCurrencyAmount: newPoolBaseCurrency.toString(),
currentPrice: finalPrice.toString(),
marketCap: (autoPumpEffects.newCirculatingSupply * finalPrice).toString(),
poolCoinAmount: finalPoolCoin.toString(),
poolBaseCurrencyAmount: finalPoolBase.toString(),
circulatingSupply: autoPumpEffects.newCirculatingSupply.toString(),
change24h: metrics.change24h.toString(),
volume24h: metrics.volume24h.toString(),
updatedAt: new Date()
@ -191,12 +229,12 @@ export async function POST({ params, request }) {
.where(eq(coin.id, coinData.id));
const priceUpdateData = {
currentPrice: newPrice,
marketCap: Number(coinData.circulatingSupply) * newPrice,
currentPrice: finalPrice,
marketCap: autoPumpEffects.newCirculatingSupply * finalPrice,
change24h: metrics.change24h,
volume24h: metrics.volume24h,
poolCoinAmount: newPoolCoin,
poolBaseCurrencyAmount: newPoolBaseCurrency
poolCoinAmount: finalPoolCoin,
poolBaseCurrencyAmount: finalPoolBase
};
const tradeData = {
@ -232,9 +270,13 @@ export async function POST({ params, request }) {
type: 'BUY',
coinsBought,
totalCost,
newPrice,
priceImpact,
newBalance: userBalance - totalCost
newPrice: finalPrice,
priceImpact: ((finalPrice - currentPrice) / currentPrice) * 100,
newBalance: userBalance - totalCost,
autoPumpEffects: {
feeApplied: autoPumpEffects.pumpFee,
tokensBurned: autoPumpEffects.tokensBurned,
}
});
} else {
@ -275,6 +317,13 @@ export async function POST({ params, request }) {
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)
.set({
baseCurrencyBalance: (userBalance + totalCost).toString(),
@ -307,22 +356,25 @@ export async function POST({ params, request }) {
type: 'SELL',
quantity: 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({
coinId: coinData.id,
price: newPrice.toString()
price: finalPrice.toString()
});
const metrics = await calculate24hMetrics(coinData.id, newPrice);
const metrics = await calculate24hMetrics(coinData.id, finalPrice);
await tx.update(coin)
.set({
currentPrice: newPrice.toString(),
marketCap: (Number(coinData.circulatingSupply) * newPrice).toString(),
poolCoinAmount: newPoolCoin.toString(),
poolBaseCurrencyAmount: newPoolBaseCurrency.toString(),
currentPrice: finalPrice.toString(),
marketCap: (autoPumpEffects.newCirculatingSupply * finalPrice).toString(),
poolCoinAmount: finalPoolCoin.toString(),
poolBaseCurrencyAmount: finalPoolBase.toString(),
circulatingSupply: autoPumpEffects.newCirculatingSupply.toString(),
change24h: metrics.change24h.toString(),
volume24h: metrics.volume24h.toString(),
updatedAt: new Date()
@ -330,12 +382,12 @@ export async function POST({ params, request }) {
.where(eq(coin.id, coinData.id));
const priceUpdateData = {
currentPrice: newPrice,
marketCap: Number(coinData.circulatingSupply) * newPrice,
currentPrice: finalPrice,
marketCap: autoPumpEffects.newCirculatingSupply * finalPrice,
change24h: metrics.change24h,
volume24h: metrics.volume24h,
poolCoinAmount: newPoolCoin,
poolBaseCurrencyAmount: newPoolBaseCurrency
poolCoinAmount: finalPoolCoin,
poolBaseCurrencyAmount: finalPoolBase
};
const tradeData = {
@ -371,9 +423,13 @@ export async function POST({ params, request }) {
type: 'SELL',
coinsSold: amount,
totalReceived: totalCost,
newPrice,
priceImpact,
newBalance: userBalance + totalCost
newPrice: finalPrice,
priceImpact: ((finalPrice - currentPrice) / currentPrice) * 100,
newBalance: userBalance + totalCost,
autoPumpEffects: {
feeApplied: autoPumpEffects.pumpFee,
tokensBurned: autoPumpEffects.tokensBurned
}
});
}
});