Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Earn protocol WIP #19 #557

Merged
merged 3 commits into from
Nov 4, 2024
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
31 changes: 31 additions & 0 deletions apps/earn-protocol/app/earn/user-activity/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { type FC } from 'react'
import { parseQueryStringServerSide } from '@summerfi/app-utils'
import { type ReadonlyURLSearchParams } from 'next/navigation'

import { getUsersActivity } from '@/app/server-handlers/sdk/get-users-activity'
import { getVaultsList } from '@/app/server-handlers/sdk/get-vaults-list'
import { UserActivityView } from '@/features/user-activity/components/UserActivityView/UserActivityView'

export const revalidate = 60

interface UserActivityPageProps {
searchParams: ReadonlyURLSearchParams
}

const UserActivityPage: FC<UserActivityPageProps> = async ({ searchParams }) => {
const [{ vaults }, { usersActivity, totalUsers }] = await Promise.all([
getVaultsList(),
getUsersActivity(),
])

return (
<UserActivityView
vaultsList={vaults}
usersActivity={usersActivity}
totalUsers={totalUsers}
searchParams={parseQueryStringServerSide({ searchParams })}
/>
)
}

export default UserActivityPage
65 changes: 65 additions & 0 deletions apps/earn-protocol/app/server-handlers/sdk/get-users-activity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {
sdkSupportedNetworks,
type SDKUserActivityType,
UserActivityType,
} from '@summerfi/app-types'
import { getChainInfoByChainId } from '@summerfi/sdk-common'

import { backendSDK } from '@/app/server-handlers/sdk/sdk-backend-client'

export interface UserActivity {
timestamp: SDKUserActivityType['deposits'][0]['timestamp']
amount: SDKUserActivityType['deposits'][0]['amount']
balance: SDKUserActivityType['inputTokenBalance']
vault: SDKUserActivityType['vault']
account: SDKUserActivityType['account']['id']
activity: UserActivityType
}

export type UsersActivity = UserActivity[]

export async function getUsersActivity(): Promise<{
usersActivity: UsersActivity
totalUsers: number
callDataTimestamp: number
}> {
const usersActivityByNetwork = await Promise.all(
sdkSupportedNetworks.map((networkId) => {
const chainInfo = getChainInfoByChainId(networkId)

return backendSDK.armada.users.getUsersActivityRaw({
chainInfo,
})
}),
)

// flatten the list
const usersActivityListRaw = usersActivityByNetwork.reduce<
(typeof usersActivityByNetwork)[number]['positions']
>((acc, { positions }) => [...acc, ...positions], [])

const totalUsers = usersActivityListRaw.filter((position) => position.deposits.length > 0).length

const usersActivityList = usersActivityListRaw.flatMap((position) => [
...position.deposits.map((deposit) => ({
...deposit,
balance: position.inputTokenBalance,
vault: position.vault,
account: position.account.id,
activity: UserActivityType.DEPOSIT,
})),
...position.withdrawals.map((deposit) => ({
...deposit,
balance: position.inputTokenBalance,
vault: position.vault,
account: position.account.id,
activity: UserActivityType.WITHDRAW,
})),
])

return {
usersActivity: usersActivityList,
totalUsers,
callDataTimestamp: Date.now(),
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
import { VaultOpenHeaderBlock } from '@/components/layout/VaultOpenView/VaultOpenHeaderBlock'
import { VaultSimulationGraph } from '@/components/layout/VaultOpenView/VaultSimulationGraph'
import { TransactionHashPill } from '@/components/molecules/TransactionHashPill/TransactionHashPill'
import { MockedLineChart } from '@/components/organisms/Charts/MockedLineChart'
import { HistoricalYieldChart } from '@/components/organisms/Charts/HistoricalYieldChart'
import { RebalancingActivity } from '@/components/organisms/RebalancingActivity/RebalancingActivity'
import { UserActivity } from '@/components/organisms/UserActivity/UserActivity'
import { VaultExposure } from '@/components/organisms/VaultExposure/VaultExposure'
Expand Down Expand Up @@ -148,7 +148,7 @@ export const VaultOpenViewComponent = ({
}
defaultExpanded
>
<MockedLineChart />
<HistoricalYieldChart aprHourlyList={vault.aprValues} />
</Expander>
<Expander
title={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,25 +114,27 @@ export const VaultsListView = ({ selectedNetwork, vaultsList }: VaultsListViewPr
onChangeNetwork={handleChangeNetwork}
topContent={
<SimpleGrid columns={3} style={{ justifyItems: 'stretch' }} gap={170}>
{/** TODO: fill data */}
<DataBlock
title="Total Assets"
// TODO: fill data
titleTooltip="Tooltip about assets or something"
size="large"
value={`$${formattedTotalAssets}`}
/>
{/** TODO: fill data */}
<DataBlock
title="Total Assets"
titleTooltip="Tooltip about assets or something"
title="Total Liquidity"
// TODO: fill data
titleTooltip="Tooltip about liquidity or something"
size="large"
// TODO: fill data
value="14.3b"
/>
{/** TODO: fill data */}
<DataBlock
title="Total Assets"
titleTooltip="Tooltip about assets or something"
title="Protocols Supported"
// TODO: fill data
titleTooltip="Tooltip about protocols or something"
size="large"
// TODO: fill data
value="6"
/>
</SimpleGrid>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const ComparisonChart = ({ data, dataNames, colors, compare }: Comparison
</linearGradient>
</defs>

<XAxis dataKey="name" fontSize={12} interval={0} />
<XAxis dataKey="name" fontSize={12} interval={5} tickMargin={10} />
<YAxis strokeWidth={0} width={45} tickFormatter={(label: string) => `${label}%`} />
<Tooltip
formatter={(val) => `${Number(val).toFixed(2)}`}
Expand All @@ -52,7 +52,7 @@ export const ComparisonChart = ({ data, dataNames, colors, compare }: Comparison
}}
/>
{dataNames.map((dataName, dataIndex) =>
dataName === 'Summer USDS Strategy' ? (
dataName === 'Summer Strategy' ? (
<Area
key={dataName}
type="natural"
Expand All @@ -67,8 +67,8 @@ export const ComparisonChart = ({ data, dataNames, colors, compare }: Comparison
/>
) : (
<Line
animationId={dataIndex}
key={dataName}
animationId={dataIndex}
animationDuration={300}
animationBegin={dataIndex * 50}
animationEasing="ease-out"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
'use client'

import { useMemo, useState } from 'react'
import { Card } from '@summerfi/app-earn-ui'
import { type CardVariant } from '@summerfi/app-earn-ui/dist/types/src/components/atoms/Card/Card'
import { type TimeframesType } from '@summerfi/app-types'
import BigNumber from 'bignumber.js'
import dayjs from 'dayjs'

import { ChartHeader } from '@/components/organisms/Charts/ChartHeader'
import { ComparisonChart } from '@/components/organisms/Charts/ComparisonChart'

const dataNames = ['Summer Strategy']

const colors = {
'Summer Strategy-color': '#FF49A4',
}

export const HistoricalYieldChart = ({
aprHourlyList,
cardVariant = 'cardSecondary',
}: {
cardVariant?: CardVariant
aprHourlyList: string[]
}) => {
const [compare, setCompare] = useState(true)
const [timeframe, setTimeframe] = useState<TimeframesType>('90d')
const _unused = setTimeframe

const parsedData = useMemo(() => {
const now = dayjs().startOf('hour')

return [...aprHourlyList].reverse().map((item, itemIndex) => ({
name: now.subtract(itemIndex, 'hour').format('MMM DD, HH:mm'),
'Summer Strategy': new BigNumber(item).toFixed(2),
}))
}, [aprHourlyList])

return (
<Card
variant={cardVariant}
style={{ marginTop: 'var(--spacing-space-medium)', flexDirection: 'column' }}
>
<ChartHeader
compare={compare}
setCompare={setCompare}
timeframe={timeframe}
setTimeframe={(_nextTimeFrame) => null}
/>
<ComparisonChart
timeframe={timeframe}
colors={colors}
data={parsedData}
compare={compare}
dataNames={dataNames}
/>
</Card>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { type FC, type ReactNode, useMemo, useState } from 'react'
import { Table, type TableSortedColumn } from '@summerfi/app-earn-ui'

import { type UsersActivity } from '@/app/server-handlers/sdk/get-users-activity'
import { userActivityColumns } from '@/features/user-activity/table/columns'
import { userActivityMapper } from '@/features/user-activity/table/mapper'

interface UserActivityTableProps {
userActivityList: UsersActivity
customRow?: {
idx: number
content: ReactNode
}
hiddenColumns?: string[]
rowsToDisplay?: number
}

export const UserActivityTable: FC<UserActivityTableProps> = ({
userActivityList,
customRow,
hiddenColumns,
rowsToDisplay,
}) => {
const [sortConfig, setSortConfig] = useState<TableSortedColumn<string>>()

const rows = useMemo(
() => userActivityMapper(userActivityList, sortConfig),
[userActivityList, sortConfig],
)

return (
<Table
rows={rows.slice(0, rowsToDisplay)}
columns={userActivityColumns}
customRow={customRow}
handleSort={(_sortConfig) => setSortConfig(_sortConfig)}
hiddenColumns={hiddenColumns}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.wrapper {
display: flex;
flex-direction: column;
padding: 0 var(--general-space-16);

@media screen and (min-width: 768px) {
padding: unset;
}
}

.filtersWrapper {
display: flex;
justify-content: flex-start;
gap: var(--general-space-16);
flex-wrap: wrap;
margin-bottom: var(--general-space-24);
}
Loading
Loading