Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const discordBotService = require('./services/discordBotService');
const cacheService = require('./services/cacheService');
const tvlService = require('./services/tvlService');
const vaultExportService = require('./services/vaultExportService');
const notificationService = require('./services/notificationService');


app.get('/', (req, res) => {
res.json({ message: 'Vesting Vault API is running!' });
Expand Down
53 changes: 53 additions & 0 deletions backend/src/services/calendarService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
const { sequelize } = require('../database/connection');
const { QueryTypes } = require('sequelize');

class CalendarService {
async getUpcomingUnlocks(userAddress, days = 30) {
const today = new Date();
const endDate = new Date();
endDate.setDate(today.getDate() + days);

// Fetch all vaults where user is a beneficiary
const vaults = await sequelize.query(
`SELECT v.id, v.token_address, v.total_amount, v.created_at,
b.total_allocated, b.total_withdrawn
FROM vaults v
JOIN beneficiaries b ON b.vault_id = v.id
WHERE b.address = :userAddress`,
{
replacements: { userAddress },
type: QueryTypes.SELECT,
}
);

if (!vaults.length) return [];

const unlocks = [];

for (const vault of vaults) {
const remaining = parseFloat(vault.total_allocated) - parseFloat(vault.total_withdrawn);
if (remaining <= 0) continue;

// Simple linear daily unlock projection over 30 days
const dailyUnlock = remaining / days;

for (let i = 1; i <= days; i++) {
const unlockDate = new Date(today);
unlockDate.setDate(today.getDate() + i);

unlocks.push({
date: unlockDate.toISOString().split('T')[0],
token: vault.token_address,
amount_unlocking: parseFloat(dailyUnlock.toFixed(6)),
});
}
}

// Sort by date
unlocks.sort((a, b) => new Date(a.date) - new Date(b.date));

return unlocks;
}
}

module.exports = new CalendarService();