Skip to content

Commit bf19b60

Browse files
authored
Merge pull request #53 from oscar24357/fix/package-name
Fix/package name
2 parents 17050bf + 9d81e13 commit bf19b60

3 files changed

Lines changed: 113 additions & 7 deletions

File tree

‎app/app/streams/page.tsx‎

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
'use client'
22

33
import { useState } from 'react'
4-
import { Search } from 'lucide-react'
4+
import { Search, Download } from 'lucide-react'
55
import { RequireWallet } from '@/components/layout/require-wallet'
6+
import { Button } from '@/components/ui/button'
7+
import { streamsToCSV, downloadCSV } from '@/lib/export'
68
import { StreamCard } from '@/components/streams/stream-card'
79
import { EmptyStreams } from '@/components/streams/empty-state'
810
import { StreamStatusBadge } from '@/components/streams/stream-status-badge'
@@ -41,11 +43,26 @@ function StreamsPage() {
4143

4244
return (
4345
<div className="space-y-6">
44-
<div>
45-
<h1 className="text-2xl font-semibold tracking-tight">Streams</h1>
46-
<p className="mt-1 text-sm text-muted-foreground">
47-
All streams you've sent or received.
48-
</p>
46+
<div className="flex items-center justify-between">
47+
<div>
48+
<h1 className="text-2xl font-semibold tracking-tight">Streams</h1>
49+
<p className="mt-1 text-sm text-muted-foreground">
50+
All streams you've sent or received.
51+
</p>
52+
</div>
53+
<Button
54+
variant="outline"
55+
size="sm"
56+
className="gap-1.5"
57+
disabled={all.length === 0}
58+
onClick={() => {
59+
const csv = streamsToCSV(all, now)
60+
downloadCSV(csv, `flowstar-streams-${new Date().toISOString().slice(0, 10)}.csv`)
61+
}}
62+
>
63+
<Download className="size-4" />
64+
Download CSV
65+
</Button>
4966
</div>
5067

5168
{/* Filters */}

‎lib/export.ts‎

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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+
}

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "my-project",
2+
"name": "flowstar",
33
"version": "0.1.0",
44
"private": true,
55
"scripts": {

0 commit comments

Comments
 (0)