|
| 1 | +import type { StreamData } from '@/types/stream' |
| 2 | +import { formatTokenAmount, getStreamStatus } from '@/lib/stream-utils' |
| 3 | + |
| 4 | +const SECONDS_PER_DAY = BigInt(86400) |
| 5 | +const DAYS_PER_MONTH = BigInt(30) |
| 6 | + |
| 7 | +function unixToISO(seconds: bigint): string { |
| 8 | + if (seconds === BigInt(0)) return '' |
| 9 | + return new Date(Number(seconds) * 1000).toISOString() |
| 10 | +} |
| 11 | + |
| 12 | +function escapeCSV(value: string): string { |
| 13 | + if (/[",\n\r]/.test(value)) return `"${value.replace(/"/g, '""')}"` |
| 14 | + return value |
| 15 | +} |
| 16 | + |
| 17 | +function row(values: string[]): string { |
| 18 | + return values.map(escapeCSV).join(',') |
| 19 | +} |
| 20 | + |
| 21 | +const HEADERS = [ |
| 22 | + 'Stream ID', |
| 23 | + 'Status', |
| 24 | + 'Sender', |
| 25 | + 'Recipient', |
| 26 | + 'Token', |
| 27 | + 'Token Address', |
| 28 | + 'Total Amount', |
| 29 | + 'Withdrawn Amount', |
| 30 | + 'Remaining Amount', |
| 31 | + 'Start Date', |
| 32 | + 'End Date', |
| 33 | + 'Cliff Date', |
| 34 | + 'Cliff Amount', |
| 35 | + 'Rate (per day)', |
| 36 | + 'Rate (per month)', |
| 37 | +] |
| 38 | + |
| 39 | +export function streamsToCSV( |
| 40 | + streams: StreamData[], |
| 41 | + nowSeconds: number = Math.floor(Date.now() / 1000), |
| 42 | +): string { |
| 43 | + const lines: string[] = [HEADERS.join(',')] |
| 44 | + |
| 45 | + for (const s of streams) { |
| 46 | + const { decimals, symbol } = s.token |
| 47 | + const status = getStreamStatus(s, nowSeconds) |
| 48 | + const remaining = s.depositedAmount - s.withdrawnAmount |
| 49 | + |
| 50 | + const ratePerDay = formatTokenAmount(s.amountPerSecond * SECONDS_PER_DAY, decimals, 6) |
| 51 | + const ratePerMonth = formatTokenAmount( |
| 52 | + s.amountPerSecond * SECONDS_PER_DAY * DAYS_PER_MONTH, |
| 53 | + decimals, |
| 54 | + 6, |
| 55 | + ) |
| 56 | + |
| 57 | + lines.push( |
| 58 | + row([ |
| 59 | + s.id, |
| 60 | + status, |
| 61 | + s.sender, |
| 62 | + s.recipient, |
| 63 | + symbol, |
| 64 | + s.token.address, |
| 65 | + formatTokenAmount(s.depositedAmount, decimals, 6), |
| 66 | + formatTokenAmount(s.withdrawnAmount, decimals, 6), |
| 67 | + formatTokenAmount(remaining > BigInt(0) ? remaining : BigInt(0), decimals, 6), |
| 68 | + unixToISO(s.startTime), |
| 69 | + unixToISO(s.endTime), |
| 70 | + s.cliffTime > s.startTime ? unixToISO(s.cliffTime) : '', |
| 71 | + s.cliffAmount > BigInt(0) ? formatTokenAmount(s.cliffAmount, decimals, 6) : '', |
| 72 | + ratePerDay, |
| 73 | + ratePerMonth, |
| 74 | + ]), |
| 75 | + ) |
| 76 | + } |
| 77 | + |
| 78 | + return lines.join('\n') |
| 79 | +} |
| 80 | + |
| 81 | +export function downloadCSV(csv: string, filename: string): void { |
| 82 | + const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }) |
| 83 | + const url = URL.createObjectURL(blob) |
| 84 | + const a = document.createElement('a') |
| 85 | + a.href = url |
| 86 | + a.download = filename |
| 87 | + a.click() |
| 88 | + URL.revokeObjectURL(url) |
| 89 | +} |
0 commit comments