Files
trading_bot_v4/app/api/withdrawals/settings/route.ts
mindesbunister ca7b49f745 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
2025-11-19 18:07:07 +01:00

116 lines
3.9 KiB
TypeScript

/**
* Withdrawal Settings API
*
* GET: Retrieve current withdrawal settings
* POST: Update withdrawal settings
*/
import { NextRequest, NextResponse } from 'next/server'
import fs from 'fs'
import path from 'path'
const ENV_PATH = path.join(process.cwd(), '.env')
// Default withdrawal settings
const DEFAULT_SETTINGS = {
ENABLE_AUTO_WITHDRAWALS: false,
WITHDRAWAL_INTERVAL_HOURS: 168, // Weekly
WITHDRAWAL_PROFIT_PERCENT: 10, // 10% of profits
MIN_WITHDRAWAL_AMOUNT: 50, // Minimum $50
MIN_ACCOUNT_BALANCE: 500, // Never drop below $500
WITHDRAWAL_DESTINATION: process.env.WALLET_PUBLIC_KEY || '',
LAST_WITHDRAWAL_TIME: null,
TOTAL_WITHDRAWN: 0,
}
export async function GET() {
try {
// Read from .env file
const envContent = fs.readFileSync(ENV_PATH, 'utf-8')
const settings = { ...DEFAULT_SETTINGS }
// Parse each setting
const boolMatch = envContent.match(/ENABLE_AUTO_WITHDRAWALS=(true|false)/)
if (boolMatch) settings.ENABLE_AUTO_WITHDRAWALS = boolMatch[1] === 'true'
const intervalMatch = envContent.match(/WITHDRAWAL_INTERVAL_HOURS=(\d+\.?\d*)/)
if (intervalMatch) settings.WITHDRAWAL_INTERVAL_HOURS = parseFloat(intervalMatch[1])
const percentMatch = envContent.match(/WITHDRAWAL_PROFIT_PERCENT=(\d+\.?\d*)/)
if (percentMatch) settings.WITHDRAWAL_PROFIT_PERCENT = parseFloat(percentMatch[1])
const minAmountMatch = envContent.match(/MIN_WITHDRAWAL_AMOUNT=(\d+\.?\d*)/)
if (minAmountMatch) settings.MIN_WITHDRAWAL_AMOUNT = parseFloat(minAmountMatch[1])
const minBalanceMatch = envContent.match(/MIN_ACCOUNT_BALANCE=(\d+\.?\d*)/)
if (minBalanceMatch) settings.MIN_ACCOUNT_BALANCE = parseFloat(minBalanceMatch[1])
const lastWithdrawalMatch = envContent.match(/LAST_WITHDRAWAL_TIME=(.*)/)
if (lastWithdrawalMatch && lastWithdrawalMatch[1] !== '') {
settings.LAST_WITHDRAWAL_TIME = lastWithdrawalMatch[1]
}
const totalWithdrawnMatch = envContent.match(/TOTAL_WITHDRAWN=(\d+\.?\d*)/)
if (totalWithdrawnMatch) settings.TOTAL_WITHDRAWN = parseFloat(totalWithdrawnMatch[1])
// Get wallet address
const walletMatch = envContent.match(/WALLET_PUBLIC_KEY=(.*)/)
if (walletMatch) settings.WITHDRAWAL_DESTINATION = walletMatch[1]
return NextResponse.json({
success: true,
settings,
})
} catch (error: any) {
console.error('Failed to load withdrawal settings:', error)
return NextResponse.json({
success: false,
error: error.message,
settings: DEFAULT_SETTINGS,
})
}
}
export async function POST(request: NextRequest) {
try {
const newSettings = await request.json()
// Read current .env
let envContent = fs.readFileSync(ENV_PATH, 'utf-8')
// Update or add each setting
const updates: Record<string, string> = {
ENABLE_AUTO_WITHDRAWALS: String(newSettings.ENABLE_AUTO_WITHDRAWALS),
WITHDRAWAL_INTERVAL_HOURS: String(newSettings.WITHDRAWAL_INTERVAL_HOURS),
WITHDRAWAL_PROFIT_PERCENT: String(newSettings.WITHDRAWAL_PROFIT_PERCENT),
MIN_WITHDRAWAL_AMOUNT: String(newSettings.MIN_WITHDRAWAL_AMOUNT),
MIN_ACCOUNT_BALANCE: String(newSettings.MIN_ACCOUNT_BALANCE),
LAST_WITHDRAWAL_TIME: newSettings.LAST_WITHDRAWAL_TIME || '',
TOTAL_WITHDRAWN: String(newSettings.TOTAL_WITHDRAWN || 0),
}
for (const [key, value] of Object.entries(updates)) {
const regex = new RegExp(`^${key}=.*$`, 'm')
if (regex.test(envContent)) {
envContent = envContent.replace(regex, `${key}=${value}`)
} else {
envContent += `\n${key}=${value}`
}
}
// Write back to .env
fs.writeFileSync(ENV_PATH, envContent)
return NextResponse.json({
success: true,
message: 'Withdrawal settings saved successfully',
})
} catch (error: any) {
console.error('Failed to save withdrawal settings:', error)
return NextResponse.json({
success: false,
error: error.message,
}, { status: 500 })
}
}