Skip to content

Commit 8024e66

Browse files
feat(BA-2964): Premium price UI with fixes (#2767)
* Reuse launch auction logic to function for premium price auctions * Rename hook to match new method * Replace auction table with prod premium auction data * increase granularity of ui plot * Rename and refactor hook * Fix deps * Handle loading for price fetch, falsy but valid 0n returns
1 parent f017afc commit 8024e66

File tree

8 files changed

+535
-1075
lines changed

8 files changed

+535
-1075
lines changed

apps/web/src/components/Basenames/PremiumExplainerModal/index.tsx

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
import Modal from 'apps/web/src/components/Modal';
22
import data from 'apps/web/src/data/usernamePriceDecayTable.json';
3-
import { useBasenamesLaunchTime } from 'apps/web/src/hooks/useBasenamesLaunchTime';
3+
import { useBasenamesNameExpiresWithGracePeriod } from 'apps/web/src/hooks/useBasenamesNameExpiresWithGracePeriod';
4+
import { useErrors } from 'apps/web/contexts/Errors';
5+
import { useEffect } from 'react';
46
import { CartesianGrid, Line, LineChart, ResponsiveContainer, Tooltip } from 'recharts';
57
import { formatEther } from 'viem';
68

79
type CustomTooltipProps = {
810
active?: boolean;
911
baseSingleYearEthCost?: bigint;
10-
launchTimeSeconds?: bigint;
12+
auctionStartTimeSeconds?: bigint;
1113
payload: [
1214
{
1315
dataKey: 'premium';
1416
name: 'premium';
15-
payload: { hours: number; premium: number };
17+
payload: { days: number; premium: number };
1618
value: number;
1719
},
1820
];
@@ -22,13 +24,19 @@ function CustomTooltip({
2224
active,
2325
payload,
2426
baseSingleYearEthCost,
25-
launchTimeSeconds,
27+
auctionStartTimeSeconds,
2628
}: CustomTooltipProps) {
27-
if (active && payload?.length && launchTimeSeconds && baseSingleYearEthCost) {
29+
if (
30+
active &&
31+
payload?.length &&
32+
auctionStartTimeSeconds !== undefined &&
33+
auctionStartTimeSeconds !== null &&
34+
baseSingleYearEthCost
35+
) {
2836
const premium = payload[0].value;
29-
const hours = payload[0].payload.hours;
30-
const seconds = hours * 60 * 60;
31-
const tooltipSeconds = seconds + Number(launchTimeSeconds);
37+
const days = payload[0].payload.days;
38+
const seconds = days * 24 * 60 * 60; // Convert days to seconds
39+
const tooltipSeconds = seconds + Number(auctionStartTimeSeconds);
3240
const timeOfPremium = new Date(tooltipSeconds * 1000).toLocaleString(undefined, {
3341
year: 'numeric',
3442
month: '2-digit',
@@ -65,17 +73,31 @@ type PremiumExplainerModalProps = {
6573
toggleModal: () => void;
6674
premiumEthAmount: bigint | undefined;
6775
baseSingleYearEthCost: bigint;
76+
name: string;
6877
};
6978
const chartMarginValues = { top: 2, right: 2, left: 2, bottom: 2 };
7079
export function PremiumExplainerModal({
7180
isOpen,
7281
toggleModal,
7382
premiumEthAmount,
7483
baseSingleYearEthCost,
84+
name,
7585
}: PremiumExplainerModalProps) {
76-
const { data: launchTimeSeconds } = useBasenamesLaunchTime();
86+
const { logError } = useErrors();
87+
const {
88+
data: auctionStartTimeSeconds,
89+
isLoading,
90+
isError,
91+
error,
92+
} = useBasenamesNameExpiresWithGracePeriod(name);
7793

78-
if (!premiumEthAmount || !baseSingleYearEthCost) return null;
94+
useEffect(() => {
95+
if (isError && error) {
96+
logError(error, `Error fetching name expiration with grace period for: ${name}`);
97+
}
98+
}, [isError, error, logError, name]);
99+
100+
if (!premiumEthAmount || !baseSingleYearEthCost || isLoading) return null;
79101
const formattedOneYearCost = Number(formatEther(baseSingleYearEthCost)).toLocaleString(
80102
undefined,
81103
{
@@ -94,8 +116,8 @@ export function PremiumExplainerModal({
94116
<div className="flex max-w-[491px] flex-1 flex-col gap-3">
95117
<h1 className="w-full text-2xl font-bold">This name has a temporary premium</h1>
96118
<p className="mb-3 text-illoblack">
97-
To ensure fair distribution of Basenames, all names have a temporary premium starting at
98-
100 ETH that then decays exponentially to 0 over 36 hours.
119+
To ensure fair distribution of recently expired Basenames, all names have a price premium
120+
which starts at 100 ETH that then decays exponentially to 0 over 21 days.
99121
</p>
100122
<div className="grid grid-cols-2 grid-rows-4">
101123
<div className="col-span-2 mb-2 text-sm font-medium uppercase text-gray-60">
@@ -147,7 +169,7 @@ export function PremiumExplainerModal({
147169
// @ts-expect-error type wants an unnecessary prop
148170
<CustomTooltip
149171
baseSingleYearEthCost={baseSingleYearEthCost}
150-
launchTimeSeconds={launchTimeSeconds}
172+
auctionStartTimeSeconds={auctionStartTimeSeconds}
151173
/>
152174
}
153175
/>

apps/web/src/components/Basenames/RegistrationForm/index.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,15 @@ export default function RegistrationForm() {
138138
const usdPrice = hasResolvedUSDPrice ? formatUsdPrice(price, ethUsdPrice) : '--.--';
139139
const nameIsFree = !hasRegisteredWithDiscount && price === 0n;
140140

141-
const { seconds, timestamp: premiumEndTimestamp } = usePremiumEndDurationRemaining();
141+
const {
142+
seconds,
143+
timestamp: premiumEndTimestamp,
144+
isLoading: isPremiumDataLoading,
145+
} = usePremiumEndDurationRemaining(selectedName);
142146

143-
const isPremiumActive = Boolean(premiumPrice && premiumPrice !== 0n && seconds !== 0n);
147+
const isPremiumActive = Boolean(
148+
!isPremiumDataLoading && premiumPrice && premiumPrice !== 0n && seconds !== 0n,
149+
);
144150
const mainRegistrationElementClasses = classNames(
145151
'z-10 flex flex-col items-start justify-between gap-6 bg-[#F7F7F7] p-8 text-gray-60 shadow-xl md:flex-row md:items-center relative z-20',
146152
{
@@ -331,6 +337,7 @@ export default function RegistrationForm() {
331337
baseSingleYearEthCost={singleYearBasePrice}
332338
isOpen={premiumExplainerModalOpen}
333339
toggleModal={togglePremiumExplainerModal}
340+
name={selectedName}
334341
/>
335342
)}
336343
</>

0 commit comments

Comments
 (0)