From fc9418c9e429672632422d704637a66959d2cb0e Mon Sep 17 00:00:00 2001 From: Jesse Pinho Date: Wed, 29 May 2024 07:40:15 -0700 Subject: [PATCH] Fix small bugs with auction UIs (#1197) * Add 'block' label to block heights * Add AuctionId to ExpandedDetails * Set overflow-hidden on box so that auction ID fits * Show ended auctions as completed, even when their endHeight hasn't been reached * Add changeset * Fix logic * Refactor ProgressBar a bit to indicate if an auction ended unfulfilled * Fix seqnum bug * Reorganize * Reorganize more --- .changeset/big-moose-guess.md | 5 ++ .../components/swap/auction-list/index.tsx | 5 +- packages/getters/src/dutch-auction.ts | 6 +++ packages/ui/components/ui/box.tsx | 2 +- .../{ => expanded-details}/get-price.test.ts | 0 .../{ => expanded-details}/get-price.ts | 0 .../get-step-index.test.ts | 0 .../{ => expanded-details}/get-step-index.ts | 0 .../index.tsx} | 33 ++++++++---- .../get-progress.test.ts | 29 ----------- .../ui/dutch-auction-component/index.tsx | 11 ++-- .../progress-bar/index.tsx | 38 +++++++------- .../progress-bar/indicator.tsx | 8 --- .../indicator/get-progress.test.ts | 51 +++++++++++++++++++ .../indicator}/get-progress.ts | 2 + .../progress-bar/indicator/index.tsx | 43 ++++++++++++++++ 16 files changed, 161 insertions(+), 72 deletions(-) create mode 100644 .changeset/big-moose-guess.md create mode 100644 packages/getters/src/dutch-auction.ts rename packages/ui/components/ui/dutch-auction-component/{ => expanded-details}/get-price.test.ts (100%) rename packages/ui/components/ui/dutch-auction-component/{ => expanded-details}/get-price.ts (100%) rename packages/ui/components/ui/dutch-auction-component/{ => expanded-details}/get-step-index.test.ts (100%) rename packages/ui/components/ui/dutch-auction-component/{ => expanded-details}/get-step-index.ts (100%) rename packages/ui/components/ui/dutch-auction-component/{expanded-details.tsx => expanded-details/index.tsx} (78%) delete mode 100644 packages/ui/components/ui/dutch-auction-component/get-progress.test.ts delete mode 100644 packages/ui/components/ui/dutch-auction-component/progress-bar/indicator.tsx create mode 100644 packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.test.ts rename packages/ui/components/ui/dutch-auction-component/{ => progress-bar/indicator}/get-progress.ts (95%) create mode 100644 packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/index.tsx diff --git a/.changeset/big-moose-guess.md b/.changeset/big-moose-guess.md new file mode 100644 index 0000000000..7a9cec3ed5 --- /dev/null +++ b/.changeset/big-moose-guess.md @@ -0,0 +1,5 @@ +--- +'@penumbra-zone/ui': patch +--- + +Fixed a couple bugs, and displayed the auction ID in its details. diff --git a/apps/minifront/src/components/swap/auction-list/index.tsx b/apps/minifront/src/components/swap/auction-list/index.tsx index b6f69ebf89..9b544c9ca9 100644 --- a/apps/minifront/src/components/swap/auction-list/index.tsx +++ b/apps/minifront/src/components/swap/auction-list/index.tsx @@ -82,7 +82,9 @@ export const AuctionList = () => { filter === 'all' && "You don't currently have any auctions."} - {!filteredAuctionInfos.length && `You don't currently have any ${filter} auctions.`} + {!filteredAuctionInfos.length && + filter !== 'all' && + `You don't currently have any ${filter} auctions.`} {filteredAuctionInfos.map(auctionInfo => ( @@ -93,6 +95,7 @@ export const AuctionList = () => { className='bg-charcoal' > dutchAuction?.description, +); diff --git a/packages/ui/components/ui/box.tsx b/packages/ui/components/ui/box.tsx index 63160fa250..e2461e5606 100644 --- a/packages/ui/components/ui/box.tsx +++ b/packages/ui/components/ui/box.tsx @@ -1,7 +1,7 @@ import { VariantProps, cva } from 'class-variance-authority'; import { PropsWithChildren } from 'react'; -const variants = cva('rounded-lg border bg-background', { +const variants = cva('overflow-hidden rounded-lg border bg-background', { variants: { spacing: { /** Useful for e.g., wrapping around a transparent ``. */ diff --git a/packages/ui/components/ui/dutch-auction-component/get-price.test.ts b/packages/ui/components/ui/dutch-auction-component/expanded-details/get-price.test.ts similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/get-price.test.ts rename to packages/ui/components/ui/dutch-auction-component/expanded-details/get-price.test.ts diff --git a/packages/ui/components/ui/dutch-auction-component/get-price.ts b/packages/ui/components/ui/dutch-auction-component/expanded-details/get-price.ts similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/get-price.ts rename to packages/ui/components/ui/dutch-auction-component/expanded-details/get-price.ts diff --git a/packages/ui/components/ui/dutch-auction-component/get-step-index.test.ts b/packages/ui/components/ui/dutch-auction-component/expanded-details/get-step-index.test.ts similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/get-step-index.test.ts rename to packages/ui/components/ui/dutch-auction-component/expanded-details/get-step-index.test.ts diff --git a/packages/ui/components/ui/dutch-auction-component/get-step-index.ts b/packages/ui/components/ui/dutch-auction-component/expanded-details/get-step-index.ts similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/get-step-index.ts rename to packages/ui/components/ui/dutch-auction-component/expanded-details/get-step-index.ts diff --git a/packages/ui/components/ui/dutch-auction-component/expanded-details.tsx b/packages/ui/components/ui/dutch-auction-component/expanded-details/index.tsx similarity index 78% rename from packages/ui/components/ui/dutch-auction-component/expanded-details.tsx rename to packages/ui/components/ui/dutch-auction-component/expanded-details/index.tsx index 1814fe604e..e9a35f5d7a 100644 --- a/packages/ui/components/ui/dutch-auction-component/expanded-details.tsx +++ b/packages/ui/components/ui/dutch-auction-component/expanded-details/index.tsx @@ -1,18 +1,24 @@ import { Metadata } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb'; -import { DutchAuction } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/auction/v1/auction_pb'; +import { + AuctionId, + DutchAuction, +} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/auction/v1/auction_pb'; import { formatAmount } from '@penumbra-zone/types/amount'; import { ReactNode } from 'react'; -import { Separator } from '../separator'; +import { Separator } from '../../separator'; import { getPrice } from './get-price'; import { getDisplayDenomExponent } from '@penumbra-zone/getters/metadata'; -import { cn } from '../../../lib/utils'; +import { cn } from '../../../../lib/utils'; +import { AuctionIdComponent } from '../../auction-id-component'; export const ExpandedDetails = ({ + auctionId, dutchAuction, inputMetadata, outputMetadata, fullSyncHeight, }: { + auctionId?: AuctionId; dutchAuction: DutchAuction; inputMetadata?: Metadata; outputMetadata?: Metadata; @@ -37,14 +43,14 @@ export const ExpandedDetails = ({ const outputExponent = getDisplayDenomExponent(outputMetadata); return ( -
+
{maxPrice && ( {formatAmount(maxPrice, outputExponent)} {outputMetadata && ( {' '} - {outputMetadata.symbol} / {inputMetadata?.symbol} @{' '} + {outputMetadata.symbol} / {inputMetadata?.symbol} @ block{' '} {description.startHeight.toString()} )} @@ -57,7 +63,7 @@ export const ExpandedDetails = ({ {outputMetadata && ( {' '} - {outputMetadata.symbol} / {inputMetadata?.symbol} @ {fullSyncHeight.toString()} + {outputMetadata.symbol} / {inputMetadata?.symbol} @ block {fullSyncHeight.toString()} )} @@ -69,7 +75,8 @@ export const ExpandedDetails = ({ {outputMetadata && ( {' '} - {outputMetadata.symbol} / {inputMetadata?.symbol} @ {description.endHeight.toString()} + {outputMetadata.symbol} / {inputMetadata?.symbol} @ block{' '} + {description.endHeight.toString()} )} @@ -88,6 +95,12 @@ export const ExpandedDetails = ({ {outputMetadata && {outputMetadata.symbol}} )} + + {auctionId && ( + + + + )}
); }; @@ -102,8 +115,10 @@ const Row = ({ highlight?: boolean; }) => (
- {label} + + {label} + - {children} + {children}
); diff --git a/packages/ui/components/ui/dutch-auction-component/get-progress.test.ts b/packages/ui/components/ui/dutch-auction-component/get-progress.test.ts deleted file mode 100644 index 4404ba588e..0000000000 --- a/packages/ui/components/ui/dutch-auction-component/get-progress.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { getProgress } from './get-progress'; - -describe('getProgress()', () => { - const startHeight = 1_001n; - const endHeight = 2_000n; - - it('returns 0 when `fullSyncHeight` is undefined', () => { - expect(getProgress(startHeight, endHeight, undefined)).toBe(0); - }); - - it('returns a decimal representing the progress between the start and end heights', () => { - const fullSyncHeight = 1_500n; - - expect(getProgress(startHeight, endHeight, fullSyncHeight)).toBe(0.5); - }); - - it('clamps to 0 if the start height has not yet been reached', () => { - const fullSyncHeight = 500n; - - expect(getProgress(startHeight, endHeight, fullSyncHeight)).toBe(0); - }); - - it('clamps to 1 if the end height has been passed', () => { - const fullSyncHeight = 10_000n; - - expect(getProgress(startHeight, endHeight, fullSyncHeight)).toBe(1); - }); -}); diff --git a/packages/ui/components/ui/dutch-auction-component/index.tsx b/packages/ui/components/ui/dutch-auction-component/index.tsx index fdede15b50..2d16cd043f 100644 --- a/packages/ui/components/ui/dutch-auction-component/index.tsx +++ b/packages/ui/components/ui/dutch-auction-component/index.tsx @@ -1,4 +1,7 @@ -import { DutchAuction } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/auction/v1/auction_pb'; +import { + AuctionId, + DutchAuction, +} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/auction/v1/auction_pb'; import { Metadata } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb'; import { Button } from '../button'; import { ChevronRight } from 'lucide-react'; @@ -9,6 +12,7 @@ import { ExpandedDetails } from './expanded-details'; import { AnimatePresence, motion } from 'framer-motion'; interface BaseProps { + auctionId?: AuctionId; dutchAuction: DutchAuction; inputMetadata?: Metadata; outputMetadata?: Metadata; @@ -34,6 +38,7 @@ interface PropsWithoutButton extends BaseProps { type Props = PropsWithButton | PropsWithoutButton; export const DutchAuctionComponent = ({ + auctionId, dutchAuction, inputMetadata, outputMetadata, @@ -62,10 +67,9 @@ export const DutchAuctionComponent = ({ @@ -92,6 +96,7 @@ export const DutchAuctionComponent = ({
{ - const progress = getProgress(auction.startHeight, auction.endHeight, fullSyncHeight); - - const auctionEnded = - (!!seqNum && seqNum > 0n) || (!!fullSyncHeight && fullSyncHeight >= auction.endHeight); - const auctionIsUpcoming = !!fullSyncHeight && fullSyncHeight < auction.startHeight; + const seqNum = dutchAuction.state?.seq; + const description = getDescription(dutchAuction); + const auctionIsUpcoming = + seqNum === 0n && !!fullSyncHeight && fullSyncHeight < description.startHeight; const auctionIsInProgress = + seqNum === 0n && !!fullSyncHeight && - fullSyncHeight >= auction.startHeight && - fullSyncHeight <= auction.endHeight; + fullSyncHeight >= description.startHeight && + fullSyncHeight <= description.endHeight; - const input = getValueView(auction.input?.amount, inputMetadata); - const totalTime = getTotalTime(auction); - const remainingTime = getRemainingTime(auction.endHeight, fullSyncHeight); - const timeTillStart = getTimeTillStart(auction.startHeight, fullSyncHeight); + const input = getValueView(description.input?.amount, inputMetadata); + const totalTime = getTotalTime(description); + const remainingTime = getRemainingTime(description.endHeight, fullSyncHeight); + const timeTillStart = getTimeTillStart(description.startHeight, fullSyncHeight); return (
- {seqNum !== undefined && !auctionIsUpcoming && ( -
- -
+ {!auctionIsUpcoming && ( + )} diff --git a/packages/ui/components/ui/dutch-auction-component/progress-bar/indicator.tsx b/packages/ui/components/ui/dutch-auction-component/progress-bar/indicator.tsx deleted file mode 100644 index 500275ff2d..0000000000 --- a/packages/ui/components/ui/dutch-auction-component/progress-bar/indicator.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { CircleArrowRight, CircleCheck } from 'lucide-react'; - -export const Indicator = ({ icon }: { icon: 'arrow' | 'checkmark' }) => - icon === 'arrow' ? ( - - ) : ( - - ); diff --git a/packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.test.ts b/packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.test.ts new file mode 100644 index 0000000000..7e8cd6c3e3 --- /dev/null +++ b/packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.test.ts @@ -0,0 +1,51 @@ +import { describe, expect, it } from 'vitest'; +import { getProgress } from './get-progress'; + +describe('getProgress()', () => { + const startHeight = 1_001n; + const endHeight = 2_000n; + + it('returns 0 when `fullSyncHeight` is undefined and `seqNum` is undefined', () => { + expect(getProgress(startHeight, endHeight, undefined, undefined)).toBe(0); + }); + + it('returns 0 when `fullSyncHeight` is undefined and `seqNum` is `0n`', () => { + expect(getProgress(startHeight, endHeight, undefined, 0n)).toBe(0); + }); + + it('returns 1 when `fullSyncHeight` is undefined and `seqNum` is `1n`', () => { + expect(getProgress(startHeight, endHeight, undefined, 1n)).toBe(1); + }); + + it('returns a decimal representing the progress between the start and end heights when `seqNum` is undefined', () => { + const fullSyncHeight = 1_500n; + + expect(getProgress(startHeight, endHeight, fullSyncHeight)).toBe(0.5); + }); + + it('returns a decimal representing the progress between the start and end heights when `seqNum` is `0n`', () => { + const fullSyncHeight = 1_500n; + const seqNum = 0n; + + expect(getProgress(startHeight, endHeight, fullSyncHeight, seqNum)).toBe(0.5); + }); + + it('returns 1 if `seqNum` is greater than 0 which means the auction has ended)', () => { + const fullSyncHeight = 1_500n; + const seqNum = 1n; + + expect(getProgress(startHeight, endHeight, fullSyncHeight, seqNum)).toBe(1); + }); + + it('clamps to 0 if the start height has not yet been reached', () => { + const fullSyncHeight = 500n; + + expect(getProgress(startHeight, endHeight, fullSyncHeight)).toBe(0); + }); + + it('clamps to 1 if the end height has been passed', () => { + const fullSyncHeight = 10_000n; + + expect(getProgress(startHeight, endHeight, fullSyncHeight)).toBe(1); + }); +}); diff --git a/packages/ui/components/ui/dutch-auction-component/get-progress.ts b/packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.ts similarity index 95% rename from packages/ui/components/ui/dutch-auction-component/get-progress.ts rename to packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.ts index b2764e7ad8..5d8280a0cb 100644 --- a/packages/ui/components/ui/dutch-auction-component/get-progress.ts +++ b/packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.ts @@ -12,7 +12,9 @@ export const getProgress = ( startHeight: bigint, endHeight: bigint, fullSyncHeight?: bigint, + seqNum?: bigint, ): number => { + if (seqNum) return 1; if (!fullSyncHeight) return 0; const currentDistanceFromStartHeightInclusive = Number(fullSyncHeight) - Number(startHeight) + 1; diff --git a/packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/index.tsx b/packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/index.tsx new file mode 100644 index 0000000000..d12a6942b7 --- /dev/null +++ b/packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/index.tsx @@ -0,0 +1,43 @@ +import { DutchAuction } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/auction/v1/auction_pb'; +import { CircleArrowRight, CircleCheck, CircleX } from 'lucide-react'; +import { getProgress } from './get-progress'; +import { getDescription } from '@penumbra-zone/getters/dutch-auction'; +import { isZero } from '@penumbra-zone/types/amount'; + +export const Indicator = ({ + dutchAuction, + fullSyncHeight, +}: { + dutchAuction: DutchAuction; + fullSyncHeight?: bigint; +}) => { + const description = getDescription(dutchAuction); + const seqNum = dutchAuction.state?.seq; + if (seqNum === undefined) return null; + + const auctionEnded = + (!!seqNum && seqNum > 0n) || (!!fullSyncHeight && fullSyncHeight >= description.endHeight); + const endedUnfulfilled = + auctionEnded && + !!dutchAuction.state?.inputReserves && + !isZero(dutchAuction.state.inputReserves); + + const progress = getProgress( + description.startHeight, + description.endHeight, + fullSyncHeight, + seqNum, + ); + + return ( +
+ {endedUnfulfilled ? ( + + ) : auctionEnded ? ( + + ) : ( + + )} +
+ ); +};