Skip to content

Commit

Permalink
wallet sidebar: add relative time from fill tooltip
Browse files Browse the repository at this point in the history
  • Loading branch information
sehyunc committed Nov 17, 2024
1 parent 2068a2e commit 4e8445c
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 127 deletions.
6 changes: 3 additions & 3 deletions app/components/track-last-visit.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client"

import { useEffect } from "react"
import React from "react"

import { useLocalStorage } from "usehooks-ts"

Expand All @@ -20,9 +20,9 @@ export function useLastVisit() {
export function TrackLastVisit() {
const { setLastVisit } = useLastVisit()

useEffect(() => {
React.useEffect(() => {
const handleBeforeUnload = () => {
// setLastVisit(Date.now())
setLastVisit(Date.now())
}

window.addEventListener("beforeunload", handleBeforeUnload)
Expand Down
1 change: 0 additions & 1 deletion app/components/wallet-sidebar/assets-menu-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export function AssetsMenuItem() {
<SidebarMenuItem>
<CollapsibleTrigger asChild>
<SidebarMenuButton tooltip="Assets">
{/* <PieChart /> */}
Assets
<span className="ml-auto">
{formatCurrency(totalRenegadeBalanceUsd)}
Expand Down
62 changes: 0 additions & 62 deletions app/components/wallet-sidebar/hooks/use-filtered-fills.ts

This file was deleted.

79 changes: 79 additions & 0 deletions app/components/wallet-sidebar/hooks/use-unviewed-fills.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from "react"

import { OrderMetadata, useOrderHistory } from "@renegade-fi/react"

import { useLastVisit } from "@/app/components/track-last-visit"
import {
useViewedFills,
generateFillIdentifier,
} from "@/app/components/wallet-sidebar/hooks/use-viewed-fills"

export function useRecentUnviewedFills() {
const { lastVisit } = useLastVisit()
const lastVisitBigInt = React.useMemo(
() => (lastVisit ? BigInt(lastVisit) : null),
[lastVisit],
)

const { data: orders } = useOrderHistory({
query: {
select: (data) => {
if (!lastVisitBigInt) return []

const filteredOrders: OrderMetadata[] = []

for (const order of data.values()) {
const latestFill = order.fills[order.fills.length - 1]
if (!latestFill || latestFill.price.timestamp <= lastVisitBigInt) {
continue
}

const recentFills = order.fills.filter(
(fill) => fill.price.timestamp > lastVisitBigInt,
)

if (recentFills.length > 0) {
filteredOrders.push({
...order,
fills: recentFills,
})
}
}

return filteredOrders.sort((a, b) => {
const latestFillA = a.fills[a.fills.length - 1].price.timestamp
const latestFillB = b.fills[b.fills.length - 1].price.timestamp
return Number(latestFillB - latestFillA)
})
},
},
})

const { isFillViewed } = useViewedFills()

const filteredOrders = React.useMemo(() => {
if (!orders) return []

return orders
.map((order) => ({
...order,
fills: order.fills.filter(
(fill) =>
!isFillViewed(
generateFillIdentifier(order.id, fill.price.timestamp),
),
),
}))
.filter((order) => order.fills.length > 0)
}, [orders, isFillViewed])

const totalUnviewedFills = React.useMemo(
() => filteredOrders.reduce((acc, order) => acc + order.fills.length, 0),
[filteredOrders],
)

return {
filteredOrders,
totalUnviewedFills,
}
}
20 changes: 0 additions & 20 deletions app/components/wallet-sidebar/hooks/use-viewed-fills.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,36 +18,16 @@ export function useViewedFills() {
)

const markFillAsViewed = (fillId: FillIdentifier) => {
console.debug(`[useViewedFills] Marking fill as viewed:`, {
fillId,
wasAlreadyViewed: viewedFills.includes(fillId),
currentViewedFills: viewedFills,
})

if (!viewedFills.includes(fillId)) {
setViewedFills([...viewedFills, fillId])
console.debug(`[useViewedFills] Updated viewed fills:`, [
...viewedFills,
fillId,
])
}
}

const isFillViewed = (fillId: FillIdentifier) => {
const isViewed = viewedFills.includes(fillId)
console.debug(`[useViewedFills] Checking if fill is viewed:`, {
fillId,
isViewed,
currentViewedFills: viewedFills,
})
return isViewed
}

console.debug(
`[useViewedFills] Hook rendered with viewed fills:`,
viewedFills,
)

return {
viewedFills,
markFillAsViewed,
Expand Down
1 change: 0 additions & 1 deletion app/components/wallet-sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ export function WalletSidebar({
</SidebarHeader>
<SidebarContent className="border-b">
<SidebarGroup>
{/* <SidebarGroupLabel>Renegade</SidebarGroupLabel> */}
<SidebarMenu>
<AssetsMenuItem />
<RecentFillsMenuItem />
Expand Down
69 changes: 38 additions & 31 deletions app/components/wallet-sidebar/recent-fills-menu-item.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import React from "react"

import { Token } from "@renegade-fi/react"
import { useQueryClient } from "@tanstack/react-query"
import { ChevronRight } from "lucide-react"
import { formatUnits } from "viem"

import { useViewedFills } from "@/app/components/wallet-sidebar/hooks/use-viewed-fills"
import { OrderDetailsSheet } from "@/app/trade/[base]/components/order-details/order-details-sheet"

import {
Expand All @@ -20,18 +18,21 @@ import {
SidebarMenuSubButton,
SidebarMenuSubItem,
} from "@/components/ui/sidebar"
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip"

import { amountTimesPrice } from "@/hooks/use-usd-price"
import { formatCurrencyFromString } from "@/lib/format"
import { createPriceQueryKey } from "@/lib/query"
import { formatCurrencyFromString, formatRelativeTimestamp } from "@/lib/format"
import { decimalNormalizePrice } from "@/lib/utils"

import { useFilteredFills } from "./hooks/use-filtered-fills"
import { useRecentUnviewedFills } from "./hooks/use-unviewed-fills"
import { generateFillIdentifier } from "./hooks/use-viewed-fills"

export function RecentFillsMenuItem() {
const { filteredOrders, totalUnviewedFills } = useFilteredFills()
const { markFillAsViewed } = useViewedFills()
const queryClient = useQueryClient()
const { filteredOrders, totalUnviewedFills } = useRecentUnviewedFills()

if (!totalUnviewedFills) {
return null
Expand All @@ -54,40 +55,46 @@ export function RecentFillsMenuItem() {
<SidebarMenuSub>
{filteredOrders.map((order) => (
<React.Fragment key={order.id}>
{order.fills.map((fill, index) => {
{order.fills.map((fill) => {
const isBuy = order.data.side === "Buy"
const token = Token.findByAddress(order.data.base_mint)
const quoteToken = Token.findByAddress(order.data.quote_mint)
const fillId = generateFillIdentifier(
order.id,
fill.price.timestamp,
)

const priceKey = createPriceQueryKey(
"binance",
order.data.base_mint,
)
const price = queryClient.getQueryData<number>(priceKey) ?? 0

const usdValue = amountTimesPrice(fill.amount, price)
const formattedUsdValue = formatCurrencyFromString(
formatUnits(usdValue, token.decimals),
const value = amountTimesPrice(
fill.amount,
decimalNormalizePrice(
fill.price.price,
token.decimals,
quoteToken.decimals,
),
)
const formattedValue = formatUnits(value, token.decimals)
const formattedUsdValue =
formatCurrencyFromString(formattedValue)

return (
<SidebarMenuSubItem key={fillId}>
<OrderDetailsSheet
key={fillId}
order={order}
onOpenChange={(isOpen) => {
if (!isOpen) {
markFillAsViewed(fillId)
}
}}
>
<SidebarMenuSubButton className="cursor-pointer">
{`${isBuy ? "Bought" : "Sold"} ${formattedUsdValue} of ${token?.ticker}`}
</SidebarMenuSubButton>
</OrderDetailsSheet>
<Tooltip>
<OrderDetailsSheet
key={fillId}
order={order}
>
<TooltipTrigger asChild>
<SidebarMenuSubButton className="cursor-default">
{`${isBuy ? "Bought" : "Sold"} ${formattedUsdValue} of ${token?.ticker}`}
</SidebarMenuSubButton>
</TooltipTrigger>
</OrderDetailsSheet>
<TooltipContent>
{formatRelativeTimestamp(
Number(fill.price.timestamp),
)}
</TooltipContent>
</Tooltip>
</SidebarMenuSubItem>
)
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,17 @@ import {

import { useMediaQuery } from "@/hooks/use-media-query"

interface OrderDetailsSheetProps {
order: OrderMetadata
children: React.ReactNode
onOpenChange?: (open: boolean) => void
}

export function OrderDetailsSheet({
children,
order,
onOpenChange,
}: OrderDetailsSheetProps) {
}: {
children: React.ReactNode
order: OrderMetadata
}) {
const isDesktop = useMediaQuery("(min-width: 1024px)")
if (isDesktop) {
return (
<Sheet onOpenChange={onOpenChange}>
<Sheet>
<SheetTrigger asChild>{children}</SheetTrigger>
<SheetContent
hideCloseButton
Expand Down

0 comments on commit 4e8445c

Please sign in to comment.