feat: Add automated profit withdrawal system

- UI page: /withdrawals with stats dashboard and config form
- Settings API: GET/POST for .env configuration
- Stats API: Real-time profit and withdrawal calculations
- Execute API: Safe withdrawal with Drift SDK integration
- Drift service: withdrawFromDrift() with USDC spot market (index 0)
- Safety checks: Min withdrawal amount, min account balance, profit-only
- Telegram notifications: Withdrawal alerts with Solscan links
- Dashboard navigation: Added Withdrawals card (3-card grid)

User goal: 10% of profits automatically withdrawn on schedule
Current: Manual trigger ready, scheduled automation pending
Files: 5 new (withdrawals page, 3 APIs, Drift service), 2 modified
This commit is contained in:
mindesbunister
2025-11-19 18:07:07 +01:00
parent c42bf94c1f
commit ca7b49f745
7 changed files with 962 additions and 1 deletions

View File

@@ -17,6 +17,16 @@ interface TelegramNotificationOptions {
maxGain?: number
}
interface TelegramWithdrawalOptions {
type: 'withdrawal'
amount: number
signature: string
availableProfit: number
totalWithdrawn: number
}
type TelegramOptions = TelegramNotificationOptions | TelegramWithdrawalOptions
/**
* Send Telegram notification for position closure
*/
@@ -107,3 +117,59 @@ function formatHoldTime(seconds: number): string {
return `${secs}s`
}
}
/**
* Send Telegram notification (supports both position closures and withdrawals)
*/
export async function sendTelegramNotification(options: TelegramOptions): Promise<void> {
if ('type' in options && options.type === 'withdrawal') {
return sendWithdrawalNotification(options)
}
return sendPositionClosedNotification(options as TelegramNotificationOptions)
}
/**
* Send withdrawal notification
*/
async function sendWithdrawalNotification(options: TelegramWithdrawalOptions): Promise<void> {
try {
const token = process.env.TELEGRAM_BOT_TOKEN
const chatId = process.env.TELEGRAM_CHAT_ID
if (!token || !chatId) {
console.log('⚠️ Telegram credentials not configured, skipping notification')
return
}
const message = `💸 PROFIT WITHDRAWAL
💰 Amount: $${options.amount.toFixed(2)} USDC
📊 Available Profit: $${options.availableProfit.toFixed(2)}
📈 Total Withdrawn: $${options.totalWithdrawn.toFixed(2)}
🔗 Transaction: <a href="https://solscan.io/tx/${options.signature}">${options.signature.substring(0, 8)}...</a>
✅ Funds sent to your wallet`
const url = `https://api.telegram.org/bot${token}/sendMessage`
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chat_id: chatId,
text: message,
parse_mode: 'HTML'
})
})
if (!response.ok) {
const errorData = await response.json()
console.error('❌ Telegram notification failed:', errorData)
} else {
console.log('✅ Telegram withdrawal notification sent')
}
} catch (error) {
console.error('❌ Error sending Telegram notification:', error)
}
}