Skip to content

Commit

Permalink
Fix small bugs with auction UIs (#1197)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
jessepinho authored May 29, 2024
1 parent 67d9bcf commit fc9418c
Show file tree
Hide file tree
Showing 16 changed files with 161 additions and 72 deletions.
5 changes: 5 additions & 0 deletions .changeset/big-moose-guess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@penumbra-zone/ui': patch
---

Fixed a couple bugs, and displayed the auction ID in its details.
5 changes: 4 additions & 1 deletion apps/minifront/src/components/swap/auction-list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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.`}

<LayoutGroup>
{filteredAuctionInfos.map(auctionInfo => (
Expand All @@ -93,6 +95,7 @@ export const AuctionList = () => {
className='bg-charcoal'
>
<DutchAuctionComponent
auctionId={auctionInfo.id}
dutchAuction={auctionInfo.auction}
inputMetadata={getMetadata(
metadataByAssetId,
Expand Down
6 changes: 6 additions & 0 deletions packages/getters/src/dutch-auction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { DutchAuction } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/auction/v1/auction_pb';
import { createGetter } from './utils/create-getter';

export const getDescription = createGetter(
(dutchAuction?: DutchAuction) => dutchAuction?.description,
);
2 changes: 1 addition & 1 deletion packages/ui/components/ui/box.tsx
Original file line number Diff line number Diff line change
@@ -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 `<Input />`. */
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -37,14 +43,14 @@ export const ExpandedDetails = ({
const outputExponent = getDisplayDenomExponent(outputMetadata);

return (
<div className='flex w-full flex-col'>
<div className='flex w-full flex-col overflow-hidden'>
{maxPrice && (
<Row label='Maximum'>
{formatAmount(maxPrice, outputExponent)}
{outputMetadata && (
<span className='font-mono text-xs'>
{' '}
{outputMetadata.symbol} / {inputMetadata?.symbol} @{' '}
{outputMetadata.symbol} / {inputMetadata?.symbol} @ block{' '}
{description.startHeight.toString()}
</span>
)}
Expand All @@ -57,7 +63,7 @@ export const ExpandedDetails = ({
{outputMetadata && (
<span className='font-mono text-xs'>
{' '}
{outputMetadata.symbol} / {inputMetadata?.symbol} @ {fullSyncHeight.toString()}
{outputMetadata.symbol} / {inputMetadata?.symbol} @ block {fullSyncHeight.toString()}
</span>
)}
</Row>
Expand All @@ -69,7 +75,8 @@ export const ExpandedDetails = ({
{outputMetadata && (
<span className='font-mono text-xs'>
{' '}
{outputMetadata.symbol} / {inputMetadata?.symbol} @ {description.endHeight.toString()}
{outputMetadata.symbol} / {inputMetadata?.symbol} @ block{' '}
{description.endHeight.toString()}
</span>
)}
</Row>
Expand All @@ -88,6 +95,12 @@ export const ExpandedDetails = ({
{outputMetadata && <span className='font-mono text-xs'> {outputMetadata.symbol}</span>}
</Row>
)}

{auctionId && (
<Row label='Auction ID'>
<AuctionIdComponent auctionId={auctionId} />
</Row>
)}
</div>
);
};
Expand All @@ -102,8 +115,10 @@ const Row = ({
highlight?: boolean;
}) => (
<div className='flex items-center justify-between'>
<span className={cn('font-mono', !highlight && 'text-muted-foreground')}>{label}</span>
<span className={cn('font-mono text-nowrap', !highlight && 'text-muted-foreground')}>
{label}
</span>
<Separator />
<span className={!highlight ? 'text-muted-foreground' : undefined}>{children}</span>
<span className={cn('overflow-hidden', !highlight && 'text-muted-foreground')}>{children}</span>
</div>
);

This file was deleted.

11 changes: 8 additions & 3 deletions packages/ui/components/ui/dutch-auction-component/index.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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;
Expand All @@ -34,6 +38,7 @@ interface PropsWithoutButton extends BaseProps {
type Props = PropsWithButton | PropsWithoutButton;

export const DutchAuctionComponent = ({
auctionId,
dutchAuction,
inputMetadata,
outputMetadata,
Expand Down Expand Up @@ -62,10 +67,9 @@ export const DutchAuctionComponent = ({

<ProgressBar
fullSyncHeight={fullSyncHeight}
auction={description}
dutchAuction={dutchAuction}
inputMetadata={inputMetadata}
outputMetadata={outputMetadata}
seqNum={dutchAuction.state?.seq}
/>
</button>

Expand All @@ -92,6 +96,7 @@ export const DutchAuctionComponent = ({
<div className='w-4 shrink-0' />

<ExpandedDetails
auctionId={auctionId}
dutchAuction={dutchAuction}
inputMetadata={inputMetadata}
outputMetadata={outputMetadata}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Metadata } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';
import { ValueViewComponent } from '../../tx/view/value';
import { DutchAuctionDescription } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/auction/v1/auction_pb';
import { DutchAuction } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/auction/v1/auction_pb';
import { Separator } from '../../separator';
import { getProgress } from '../get-progress';
import { Indicator } from './indicator';
import { ClockIcon, HourglassIcon } from 'lucide-react';
import {
Expand All @@ -12,44 +11,41 @@ import {
getTotalTime,
getValueView,
} from './helpers';
import { getDescription } from '@penumbra-zone/getters/dutch-auction';

export const ProgressBar = ({
auction,
dutchAuction,
inputMetadata,
outputMetadata,
fullSyncHeight,
seqNum,
}: {
auction: DutchAuctionDescription;
dutchAuction: DutchAuction;
inputMetadata?: Metadata;
outputMetadata?: Metadata;
fullSyncHeight?: bigint;
seqNum?: bigint;
}) => {
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 (
<div className='relative flex grow items-center justify-between gap-2 overflow-hidden'>
<ValueViewComponent view={input} size='sm' />

<div className='relative flex min-h-4 shrink grow items-center overflow-hidden'>
{seqNum !== undefined && !auctionIsUpcoming && (
<div className='absolute' style={{ left: `max(${progress * 100}% - 16px, 0px)` }}>
<Indicator icon={auctionEnded ? 'checkmark' : 'arrow'} />
</div>
{!auctionIsUpcoming && (
<Indicator dutchAuction={dutchAuction} fullSyncHeight={fullSyncHeight} />
)}

<Separator />
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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 (
<div className='absolute' style={{ left: `max(${progress * 100}% - 16px, 0px)` }}>
{endedUnfulfilled ? (
<CircleX size={16} className='text-red' />
) : auctionEnded ? (
<CircleCheck size={16} className='text-green' />
) : (
<CircleArrowRight size={16} />
)}
</div>
);
};

0 comments on commit fc9418c

Please sign in to comment.